Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
856f7ae4d1
commit
01979f1e76
11 changed files with 19 additions and 271 deletions
|
@ -3,7 +3,6 @@ import SecretValues from '../behaviors/secret_values';
|
||||||
import CreateItemDropdown from '../create_item_dropdown';
|
import CreateItemDropdown from '../create_item_dropdown';
|
||||||
import { parseBoolean } from '../lib/utils/common_utils';
|
import { parseBoolean } from '../lib/utils/common_utils';
|
||||||
import { s__ } from '../locale';
|
import { s__ } from '../locale';
|
||||||
import setupToggleButtons from '../toggle_buttons';
|
|
||||||
|
|
||||||
const ALL_ENVIRONMENTS_STRING = s__('CiVariable|All environments');
|
const ALL_ENVIRONMENTS_STRING = s__('CiVariable|All environments');
|
||||||
|
|
||||||
|
@ -115,8 +114,6 @@ export default class VariableList {
|
||||||
initRow(rowEl) {
|
initRow(rowEl) {
|
||||||
const $row = $(rowEl);
|
const $row = $(rowEl);
|
||||||
|
|
||||||
setupToggleButtons($row[0]);
|
|
||||||
|
|
||||||
// Reset the resizable textarea
|
// Reset the resizable textarea
|
||||||
$row.find(this.inputMap.secret_value.selector).css('height', '');
|
$row.find(this.inputMap.secret_value.selector).css('height', '');
|
||||||
|
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
import $ from 'jquery';
|
|
||||||
import createFlash from './flash';
|
|
||||||
import { parseBoolean } from './lib/utils/common_utils';
|
|
||||||
import { __ } from './locale';
|
|
||||||
|
|
||||||
/*
|
|
||||||
example HAML:
|
|
||||||
```
|
|
||||||
%button.js-project-feature-toggle.project-feature-toggle{ type: "button",
|
|
||||||
class: "#{'is-checked' if enabled?}",
|
|
||||||
'aria-label': _('Toggle Kubernetes Cluster') }
|
|
||||||
%input{ type: "hidden", class: 'js-project-feature-toggle-input', value: enabled? }
|
|
||||||
```
|
|
||||||
*/
|
|
||||||
|
|
||||||
function updateToggle(toggle, isOn) {
|
|
||||||
toggle.classList.toggle('is-checked', isOn);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onToggleClicked(toggle, input, clickCallback) {
|
|
||||||
const previousIsOn = parseBoolean(input.value);
|
|
||||||
|
|
||||||
// Visually change the toggle and start loading
|
|
||||||
updateToggle(toggle, !previousIsOn);
|
|
||||||
toggle.setAttribute('disabled', true);
|
|
||||||
toggle.classList.toggle('is-loading', true);
|
|
||||||
|
|
||||||
Promise.resolve(clickCallback(!previousIsOn, toggle))
|
|
||||||
.then(() => {
|
|
||||||
// Actually change the input value
|
|
||||||
input.setAttribute('value', !previousIsOn);
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
// Revert the visuals if something goes wrong
|
|
||||||
updateToggle(toggle, previousIsOn);
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
// Remove the loading indicator in any case
|
|
||||||
toggle.removeAttribute('disabled');
|
|
||||||
toggle.classList.toggle('is-loading', false);
|
|
||||||
|
|
||||||
$(input).trigger('trigger-change');
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
createFlash({
|
|
||||||
message: __('Something went wrong when toggling the button'),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function setupToggleButtons(container, clickCallback = () => {}) {
|
|
||||||
const toggles = container.querySelectorAll('.js-project-feature-toggle');
|
|
||||||
|
|
||||||
toggles.forEach((toggle) => {
|
|
||||||
const input = toggle.querySelector('.js-project-feature-toggle-input');
|
|
||||||
const isOn = parseBoolean(input.value);
|
|
||||||
|
|
||||||
// Get the visible toggle in sync with the hidden input
|
|
||||||
updateToggle(toggle, isOn);
|
|
||||||
|
|
||||||
toggle.addEventListener('click', onToggleClicked.bind(null, toggle, input, clickCallback));
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,23 +1,16 @@
|
||||||
- form_field = local_assigns.fetch(:form_field, nil)
|
- form_field = local_assigns.fetch(:form_field, nil)
|
||||||
- variable = local_assigns.fetch(:variable, nil)
|
- variable = local_assigns.fetch(:variable, nil)
|
||||||
- only_key_value = local_assigns.fetch(:only_key_value, false)
|
|
||||||
|
|
||||||
- id = variable&.id
|
- id = variable&.id
|
||||||
- variable_type = variable&.variable_type
|
- variable_type = variable&.variable_type
|
||||||
- key = variable&.key
|
- key = variable&.key
|
||||||
- value = variable&.value
|
- value = variable&.value
|
||||||
- is_protected_default = ci_variable_protected_by_default?
|
|
||||||
- is_protected = ci_variable_protected?(variable, only_key_value)
|
|
||||||
- is_masked_default = false
|
|
||||||
- is_masked = ci_variable_masked?(variable, only_key_value)
|
|
||||||
|
|
||||||
- id_input_name = "#{form_field}[variables_attributes][][id]"
|
- id_input_name = "#{form_field}[variables_attributes][][id]"
|
||||||
- destroy_input_name = "#{form_field}[variables_attributes][][_destroy]"
|
- destroy_input_name = "#{form_field}[variables_attributes][][_destroy]"
|
||||||
- variable_type_input_name = "#{form_field}[variables_attributes][][variable_type]"
|
- variable_type_input_name = "#{form_field}[variables_attributes][][variable_type]"
|
||||||
- key_input_name = "#{form_field}[variables_attributes][][key]"
|
- key_input_name = "#{form_field}[variables_attributes][][key]"
|
||||||
- value_input_name = "#{form_field}[variables_attributes][][secret_value]"
|
- value_input_name = "#{form_field}[variables_attributes][][secret_value]"
|
||||||
- protected_input_name = "#{form_field}[variables_attributes][][protected]"
|
|
||||||
- masked_input_name = "#{form_field}[variables_attributes][][masked]"
|
|
||||||
|
|
||||||
%li.js-row.ci-variable-row{ data: { is_persisted: "#{!id.nil?}" } }
|
%li.js-row.ci-variable-row{ data: { is_persisted: "#{!id.nil?}" } }
|
||||||
.ci-variable-row-body.border-bottom
|
.ci-variable-row-body.border-bottom
|
||||||
|
@ -40,25 +33,5 @@
|
||||||
%p.masking-validation-error.gl-field-error.hide
|
%p.masking-validation-error.gl-field-error.hide
|
||||||
= s_("CiVariables|Cannot use Masked Variable with current value")
|
= s_("CiVariables|Cannot use Masked Variable with current value")
|
||||||
= link_to sprite_icon('question-o'), help_page_path('ci/variables/index', anchor: 'mask-a-cicd-variable'), target: '_blank', rel: 'noopener noreferrer'
|
= link_to sprite_icon('question-o'), help_page_path('ci/variables/index', anchor: 'mask-a-cicd-variable'), target: '_blank', rel: 'noopener noreferrer'
|
||||||
- unless only_key_value
|
|
||||||
.ci-variable-body-item.ci-variable-protected-item.table-section.section-20.mr-0.border-top-0
|
|
||||||
.gl-mr-3
|
|
||||||
= s_("CiVariable|Protected")
|
|
||||||
= render "shared/buttons/project_feature_toggle", is_checked: is_protected, label: s_("CiVariable|Toggle protected") do
|
|
||||||
%input{ type: "hidden",
|
|
||||||
class: 'js-ci-variable-input-protected js-project-feature-toggle-input',
|
|
||||||
name: protected_input_name,
|
|
||||||
value: is_protected,
|
|
||||||
data: { default: is_protected_default.to_s } }
|
|
||||||
.ci-variable-body-item.ci-variable-masked-item.table-section.section-20.mr-0.border-top-0
|
|
||||||
.gl-mr-3
|
|
||||||
= s_("CiVariable|Masked")
|
|
||||||
= render "shared/buttons/project_feature_toggle", is_checked: is_masked, label: s_("CiVariable|Toggle masked"), class_list: "js-project-feature-toggle project-feature-toggle qa-variable-masked" do
|
|
||||||
%input{ type: "hidden",
|
|
||||||
class: 'js-ci-variable-input-masked js-project-feature-toggle-input',
|
|
||||||
name: masked_input_name,
|
|
||||||
value: is_masked,
|
|
||||||
data: { default: is_masked_default.to_s } }
|
|
||||||
= render_if_exists 'ci/variables/environment_scope', form_field: form_field, variable: variable
|
|
||||||
%button.gl-button.btn.btn-default.btn-icon.js-row-remove-button.ci-variable-row-remove-button.table-section{ type: 'button', 'aria-label': s_('CiVariables|Remove variable row') }
|
%button.gl-button.btn.btn-default.btn-icon.js-row-remove-button.ci-variable-row-remove-button.table-section{ type: 'button', 'aria-label': s_('CiVariables|Remove variable row') }
|
||||||
= sprite_icon('close')
|
= sprite_icon('close')
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
#{ s_('PipelineSchedules|Variables') }
|
#{ s_('PipelineSchedules|Variables') }
|
||||||
%ul.ci-variable-list
|
%ul.ci-variable-list
|
||||||
- @schedule.variables.each do |variable|
|
- @schedule.variables.each do |variable|
|
||||||
= render 'ci/variables/variable_row', form_field: 'schedule', variable: variable, only_key_value: true
|
= render 'ci/variables/variable_row', form_field: 'schedule', variable: variable
|
||||||
= render 'ci/variables/variable_row', form_field: 'schedule', only_key_value: true
|
= render 'ci/variables/variable_row', form_field: 'schedule'
|
||||||
- if @schedule.variables.size > 0
|
- if @schedule.variables.size > 0
|
||||||
%button.gl-button.btn.btn-confirm-secondary.gl-mt-3.js-secret-value-reveal-button{ type: 'button', data: { secret_reveal_status: "#{@schedule.variables.size == 0}" } }
|
%button.gl-button.btn.btn-confirm-secondary.gl-mt-3.js-secret-value-reveal-button{ type: 'button', data: { secret_reveal_status: "#{@schedule.variables.size == 0}" } }
|
||||||
- if @schedule.variables.size == 0
|
- if @schedule.variables.size == 0
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
- class_list ||= "js-project-feature-toggle project-feature-toggle"
|
|
||||||
- data ||= nil
|
|
||||||
- disabled ||= false
|
|
||||||
- is_checked ||= false
|
|
||||||
- label ||= nil
|
|
||||||
|
|
||||||
%button{ type: 'button',
|
|
||||||
class: "#{class_list} #{'is-disabled' if disabled} #{'is-checked' if is_checked}",
|
|
||||||
"aria-label": label,
|
|
||||||
disabled: disabled,
|
|
||||||
data: data }
|
|
||||||
- if yield.present?
|
|
||||||
= yield
|
|
||||||
%span.toggle-icon
|
|
||||||
= sprite_icon('status_success_borderless', size: 18, css_class: 'gl-text-blue-500 toggle-status-checked')
|
|
||||||
= sprite_icon('status_failed_borderless', size: 18, css_class: 'gl-text-gray-400 toggle-status-unchecked')
|
|
|
@ -7393,24 +7393,12 @@ msgstr ""
|
||||||
msgid "CiVariable|Create wildcard"
|
msgid "CiVariable|Create wildcard"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "CiVariable|Masked"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "CiVariable|New environment"
|
msgid "CiVariable|New environment"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "CiVariable|Protected"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "CiVariable|Search environments"
|
msgid "CiVariable|Search environments"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "CiVariable|Toggle masked"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "CiVariable|Toggle protected"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Classification Label (optional)"
|
msgid "Classification Label (optional)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -34373,9 +34361,6 @@ msgstr ""
|
||||||
msgid "Something went wrong when reordering designs. Please try again"
|
msgid "Something went wrong when reordering designs. Please try again"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Something went wrong when toggling the button"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Something went wrong while adding your award. Please try again."
|
msgid "Something went wrong while adding your award. Please try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -94,16 +94,7 @@ RSpec.describe 'User Cluster', :js do
|
||||||
expect(page).to have_button('Save changes')
|
expect(page).to have_button('Save changes')
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when user disables the cluster' do
|
include_examples "user disables a cluster"
|
||||||
before do
|
|
||||||
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
|
|
||||||
page.within('.js-cluster-details-form') { click_button 'Save changes' }
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'user sees the successful message' do
|
|
||||||
expect(page).to have_content('Kubernetes cluster was successfully updated.')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when user changes cluster parameters' do
|
context 'when user changes cluster parameters' do
|
||||||
before do
|
before do
|
||||||
|
|
|
@ -118,16 +118,7 @@ RSpec.describe 'Gcp Cluster', :js do
|
||||||
expect(page.find(:css, '.cluster-name').value).to eq(cluster.name)
|
expect(page.find(:css, '.cluster-name').value).to eq(cluster.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when user disables the cluster' do
|
include_examples "user disables a cluster"
|
||||||
before do
|
|
||||||
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
|
|
||||||
page.within('.js-cluster-details-form') { click_button 'Save changes' }
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'user sees the successful message' do
|
|
||||||
expect(page).to have_content('Kubernetes cluster was successfully updated.')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when user changes cluster parameters' do
|
context 'when user changes cluster parameters' do
|
||||||
before do
|
before do
|
||||||
|
|
|
@ -82,16 +82,7 @@ RSpec.describe 'User Cluster', :js do
|
||||||
expect(page).to have_button('Save changes')
|
expect(page).to have_button('Save changes')
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when user disables the cluster' do
|
include_examples "user disables a cluster"
|
||||||
before do
|
|
||||||
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
|
|
||||||
page.within('.js-cluster-details-form') { click_button 'Save changes' }
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'user sees the successful message' do
|
|
||||||
expect(page).to have_content('Kubernetes cluster was successfully updated.')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when user changes cluster parameters' do
|
context 'when user changes cluster parameters' do
|
||||||
before do
|
before do
|
||||||
|
|
|
@ -1,115 +0,0 @@
|
||||||
import $ from 'jquery';
|
|
||||||
import waitForPromises from 'helpers/wait_for_promises';
|
|
||||||
import setupToggleButtons from '~/toggle_buttons';
|
|
||||||
|
|
||||||
function generateMarkup(isChecked = true) {
|
|
||||||
return `
|
|
||||||
<button type="button" class="${isChecked ? 'is-checked' : ''} js-project-feature-toggle">
|
|
||||||
<input type="hidden" class="js-project-feature-toggle-input" value="${isChecked}" />
|
|
||||||
</button>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setupFixture(isChecked, clickCallback) {
|
|
||||||
const wrapper = document.createElement('div');
|
|
||||||
wrapper.innerHTML = generateMarkup(isChecked);
|
|
||||||
|
|
||||||
setupToggleButtons(wrapper, clickCallback);
|
|
||||||
|
|
||||||
return wrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('ToggleButtons', () => {
|
|
||||||
describe('when input value is true', () => {
|
|
||||||
it('should initialize as checked', () => {
|
|
||||||
const wrapper = setupFixture(true);
|
|
||||||
|
|
||||||
expect(
|
|
||||||
wrapper.querySelector('.js-project-feature-toggle').classList.contains('is-checked'),
|
|
||||||
).toEqual(true);
|
|
||||||
|
|
||||||
expect(wrapper.querySelector('.js-project-feature-toggle-input').value).toEqual('true');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should toggle to unchecked when clicked', () => {
|
|
||||||
const wrapper = setupFixture(true);
|
|
||||||
const toggleButton = wrapper.querySelector('.js-project-feature-toggle');
|
|
||||||
|
|
||||||
toggleButton.click();
|
|
||||||
|
|
||||||
return waitForPromises().then(() => {
|
|
||||||
expect(toggleButton.classList.contains('is-checked')).toEqual(false);
|
|
||||||
expect(wrapper.querySelector('.js-project-feature-toggle-input').value).toEqual('false');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when input value is false', () => {
|
|
||||||
it('should initialize as unchecked', () => {
|
|
||||||
const wrapper = setupFixture(false);
|
|
||||||
|
|
||||||
expect(
|
|
||||||
wrapper.querySelector('.js-project-feature-toggle').classList.contains('is-checked'),
|
|
||||||
).toEqual(false);
|
|
||||||
|
|
||||||
expect(wrapper.querySelector('.js-project-feature-toggle-input').value).toEqual('false');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should toggle to checked when clicked', () => {
|
|
||||||
const wrapper = setupFixture(false);
|
|
||||||
const toggleButton = wrapper.querySelector('.js-project-feature-toggle');
|
|
||||||
|
|
||||||
toggleButton.click();
|
|
||||||
|
|
||||||
return waitForPromises().then(() => {
|
|
||||||
expect(toggleButton.classList.contains('is-checked')).toEqual(true);
|
|
||||||
expect(wrapper.querySelector('.js-project-feature-toggle-input').value).toEqual('true');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should emit `trigger-change` event', () => {
|
|
||||||
const changeSpy = jest.fn();
|
|
||||||
const wrapper = setupFixture(false);
|
|
||||||
const toggleButton = wrapper.querySelector('.js-project-feature-toggle');
|
|
||||||
const input = wrapper.querySelector('.js-project-feature-toggle-input');
|
|
||||||
|
|
||||||
$(input).on('trigger-change', changeSpy);
|
|
||||||
|
|
||||||
toggleButton.click();
|
|
||||||
|
|
||||||
return waitForPromises().then(() => {
|
|
||||||
expect(changeSpy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('clickCallback', () => {
|
|
||||||
it('should show loading indicator while waiting', () => {
|
|
||||||
const isChecked = true;
|
|
||||||
const clickCallback = (newValue, toggleButton) => {
|
|
||||||
const input = toggleButton.querySelector('.js-project-feature-toggle-input');
|
|
||||||
|
|
||||||
expect(newValue).toEqual(false);
|
|
||||||
|
|
||||||
// Check for the loading state
|
|
||||||
expect(toggleButton.classList.contains('is-checked')).toEqual(false);
|
|
||||||
expect(toggleButton.classList.contains('is-loading')).toEqual(true);
|
|
||||||
expect(toggleButton.disabled).toEqual(true);
|
|
||||||
expect(input.value).toEqual('true');
|
|
||||||
|
|
||||||
// After the callback finishes, check that the loading state is gone
|
|
||||||
return waitForPromises().then(() => {
|
|
||||||
expect(toggleButton.classList.contains('is-checked')).toEqual(false);
|
|
||||||
expect(toggleButton.classList.contains('is-loading')).toEqual(false);
|
|
||||||
expect(toggleButton.disabled).toEqual(false);
|
|
||||||
expect(input.value).toEqual('false');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const wrapper = setupFixture(isChecked, clickCallback);
|
|
||||||
const toggleButton = wrapper.querySelector('.js-project-feature-toggle');
|
|
||||||
|
|
||||||
toggleButton.click();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.shared_examples "user disables a cluster" do
|
||||||
|
context 'when user disables the cluster' do
|
||||||
|
before do
|
||||||
|
page.find(:css, '.js-cluster-enable-toggle-area .js-project-feature-toggle').click
|
||||||
|
page.within('.js-cluster-details-form') { click_button 'Save changes' }
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'user sees the successful message' do
|
||||||
|
expect(page).to have_content('Kubernetes cluster was successfully updated.')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue