diff --git a/app/assets/javascripts/ci_variable_list/ci_variable_list.js b/app/assets/javascripts/ci_variable_list/ci_variable_list.js index 065cb4f5616..055e2f83e33 100644 --- a/app/assets/javascripts/ci_variable_list/ci_variable_list.js +++ b/app/assets/javascripts/ci_variable_list/ci_variable_list.js @@ -3,7 +3,6 @@ import SecretValues from '../behaviors/secret_values'; import CreateItemDropdown from '../create_item_dropdown'; import { parseBoolean } from '../lib/utils/common_utils'; import { s__ } from '../locale'; -import setupToggleButtons from '../toggle_buttons'; const ALL_ENVIRONMENTS_STRING = s__('CiVariable|All environments'); @@ -115,8 +114,6 @@ export default class VariableList { initRow(rowEl) { const $row = $(rowEl); - setupToggleButtons($row[0]); - // Reset the resizable textarea $row.find(this.inputMap.secret_value.selector).css('height', ''); diff --git a/app/assets/javascripts/toggle_buttons.js b/app/assets/javascripts/toggle_buttons.js deleted file mode 100644 index 5b85107991a..00000000000 --- a/app/assets/javascripts/toggle_buttons.js +++ /dev/null @@ -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)); - }); -} diff --git a/app/views/ci/variables/_variable_row.html.haml b/app/views/ci/variables/_variable_row.html.haml index 3a7f7a241ac..483c767d029 100644 --- a/app/views/ci/variables/_variable_row.html.haml +++ b/app/views/ci/variables/_variable_row.html.haml @@ -1,23 +1,16 @@ - form_field = local_assigns.fetch(:form_field, nil) - variable = local_assigns.fetch(:variable, nil) -- only_key_value = local_assigns.fetch(:only_key_value, false) - id = variable&.id - variable_type = variable&.variable_type - key = variable&.key - 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]" - destroy_input_name = "#{form_field}[variables_attributes][][_destroy]" - variable_type_input_name = "#{form_field}[variables_attributes][][variable_type]" - key_input_name = "#{form_field}[variables_attributes][][key]" - 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?}" } } .ci-variable-row-body.border-bottom @@ -40,25 +33,5 @@ %p.masking-validation-error.gl-field-error.hide = 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' - - 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') } = sprite_icon('close') diff --git a/app/views/projects/pipeline_schedules/_form.html.haml b/app/views/projects/pipeline_schedules/_form.html.haml index 5208f58ae87..1c828952f6c 100644 --- a/app/views/projects/pipeline_schedules/_form.html.haml +++ b/app/views/projects/pipeline_schedules/_form.html.haml @@ -25,8 +25,8 @@ #{ s_('PipelineSchedules|Variables') } %ul.ci-variable-list - @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', only_key_value: true + = render 'ci/variables/variable_row', form_field: 'schedule', variable: variable + = render 'ci/variables/variable_row', form_field: 'schedule' - 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}" } } - if @schedule.variables.size == 0 diff --git a/app/views/shared/buttons/_project_feature_toggle.html.haml b/app/views/shared/buttons/_project_feature_toggle.html.haml deleted file mode 100644 index 321fbee1b35..00000000000 --- a/app/views/shared/buttons/_project_feature_toggle.html.haml +++ /dev/null @@ -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') diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d6590081dd9..8094e6391c9 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -7393,24 +7393,12 @@ msgstr "" msgid "CiVariable|Create wildcard" msgstr "" -msgid "CiVariable|Masked" -msgstr "" - msgid "CiVariable|New environment" msgstr "" -msgid "CiVariable|Protected" -msgstr "" - msgid "CiVariable|Search environments" msgstr "" -msgid "CiVariable|Toggle masked" -msgstr "" - -msgid "CiVariable|Toggle protected" -msgstr "" - msgid "Classification Label (optional)" msgstr "" @@ -34373,9 +34361,6 @@ msgstr "" msgid "Something went wrong when reordering designs. Please try again" msgstr "" -msgid "Something went wrong when toggling the button" -msgstr "" - msgid "Something went wrong while adding your award. Please try again." msgstr "" diff --git a/spec/features/groups/clusters/user_spec.rb b/spec/features/groups/clusters/user_spec.rb index 1788167c94c..bb3efa208c6 100644 --- a/spec/features/groups/clusters/user_spec.rb +++ b/spec/features/groups/clusters/user_spec.rb @@ -94,16 +94,7 @@ RSpec.describe 'User Cluster', :js do expect(page).to have_button('Save changes') end - 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 + include_examples "user disables a cluster" context 'when user changes cluster parameters' do before do diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb index 0c9db24f1d8..6f3ae15fa62 100644 --- a/spec/features/projects/clusters/gcp_spec.rb +++ b/spec/features/projects/clusters/gcp_spec.rb @@ -118,16 +118,7 @@ RSpec.describe 'Gcp Cluster', :js do expect(page.find(:css, '.cluster-name').value).to eq(cluster.name) end - 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 + include_examples "user disables a cluster" context 'when user changes cluster parameters' do before do diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb index d9887ea4fe0..2b18116e5b9 100644 --- a/spec/features/projects/clusters/user_spec.rb +++ b/spec/features/projects/clusters/user_spec.rb @@ -82,16 +82,7 @@ RSpec.describe 'User Cluster', :js do expect(page).to have_button('Save changes') end - 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 + include_examples "user disables a cluster" context 'when user changes cluster parameters' do before do diff --git a/spec/frontend/toggle_buttons_spec.js b/spec/frontend/toggle_buttons_spec.js deleted file mode 100644 index 435fd35744f..00000000000 --- a/spec/frontend/toggle_buttons_spec.js +++ /dev/null @@ -1,115 +0,0 @@ -import $ from 'jquery'; -import waitForPromises from 'helpers/wait_for_promises'; -import setupToggleButtons from '~/toggle_buttons'; - -function generateMarkup(isChecked = true) { - return ` - - `; -} - -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(); - }); - }); -}); diff --git a/spec/support/shared_examples/features/clusters_shared_examples.rb b/spec/support/shared_examples/features/clusters_shared_examples.rb new file mode 100644 index 00000000000..6ee60f20b2e --- /dev/null +++ b/spec/support/shared_examples/features/clusters_shared_examples.rb @@ -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