diff options
9 files changed, 167 insertions, 25 deletions
diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue index e035ba462db..b8f0566f48c 100644 --- a/app/assets/javascripts/groups/components/app.vue +++ b/app/assets/javascripts/groups/components/app.vue @@ -152,14 +152,14 @@ export default { showLeaveGroupModal(group, parentGroup) { this.targetGroup = group; this.targetParentGroup = parentGroup; - this.showModal = true; + this.updateModal = true; this.groupLeaveConfirmationMessage = s__(`GroupsTree|Are you sure you want to leave the "${group.fullName}" group?`); }, hideLeaveGroupModal() { - this.showModal = false; + this.updateModal = false; }, leaveGroup() { - this.showModal = false; + this.updateModal = false; this.targetGroup.isBeingRemoved = true; this.service.leaveGroup(this.targetGroup.leavePath) .then(res => res.json()) diff --git a/app/assets/javascripts/pipelines/components/async_button.vue b/app/assets/javascripts/pipelines/components/async_button.vue index 77553ca67cc..a5f22c4ec80 100644 --- a/app/assets/javascripts/pipelines/components/async_button.vue +++ b/app/assets/javascripts/pipelines/components/async_button.vue @@ -31,10 +31,9 @@ type: String, required: true, }, - confirmActionMessage: { - type: String, - required: false, - default: '', + id: { + type: Number, + required: true, }, }, data() { @@ -49,11 +48,10 @@ }, methods: { onClick() { - if (this.confirmActionMessage !== '' && confirm(this.confirmActionMessage)) { - this.makeRequest(); - } else if (this.confirmActionMessage === '') { - this.makeRequest(); - } + eventHub.$emit('actionConfirmationModal', { + id: this.id, + callback: this.makeRequest, + }); }, makeRequest() { this.isLoading = true; diff --git a/app/assets/javascripts/pipelines/components/pipelines_table.vue b/app/assets/javascripts/pipelines/components/pipelines_table.vue index 6681b89e629..62fe479fdf4 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_table.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_table.vue @@ -1,5 +1,7 @@ <script> import pipelinesTableRowComponent from './pipelines_table_row.vue'; + import stopConfirmationModal from './stop_confirmation_modal.vue'; + import retryConfirmationModal from './retry_confirmation_modal.vue'; /** * Pipelines Table Component. @@ -9,6 +11,8 @@ export default { components: { pipelinesTableRowComponent, + stopConfirmationModal, + retryConfirmationModal, }, props: { pipelines: { @@ -70,5 +74,7 @@ :auto-devops-help-path="autoDevopsHelpPath" :view-type="viewType" /> + <stop-confirmation-modal /> + <retry-confirmation-modal /> </div> </template> diff --git a/app/assets/javascripts/pipelines/components/pipelines_table_row.vue b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue index d0e4cf7ff40..0e3a10ed7f4 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_table_row.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue @@ -305,6 +305,9 @@ css-class="js-pipelines-retry-button btn-default btn-retry" title="Retry" icon="repeat" + :id="pipeline.id" + data-toggle="modal" + data-target="#retry-confirmation-modal" /> <async-button-component @@ -313,7 +316,9 @@ css-class="js-pipelines-cancel-button btn-remove" title="Cancel" icon="close" - confirm-action-message="Are you sure you want to cancel this pipeline?" + :id="pipeline.id" + data-toggle="modal" + data-target="#stop-confirmation-modal" /> </div> </div> diff --git a/app/assets/javascripts/pipelines/components/retry_confirmation_modal.vue b/app/assets/javascripts/pipelines/components/retry_confirmation_modal.vue new file mode 100644 index 00000000000..e2ac08d67bc --- /dev/null +++ b/app/assets/javascripts/pipelines/components/retry_confirmation_modal.vue @@ -0,0 +1,65 @@ +<script> + import modal from '~/vue_shared/components/modal.vue'; + import { s__, sprintf } from '~/locale'; + import eventHub from '../event_hub'; + + export default { + components: { + modal, + }, + data() { + return { + id: '', + callback: () => {}, + }; + }, + computed: { + title() { + return sprintf(s__('Pipeline|Retry pipeline #%{id}?'), { + id: `'${this.id}'`, + }, false); + }, + text() { + return sprintf(s__('Pipeline|You’re about to retry pipeline %{id}.'), { + id: `<strong>#${this.id}</strong>`, + }, false); + }, + primaryButtonLabel() { + return s__('Pipeline|Retry pipeline'); + }, + }, + created() { + eventHub.$on('actionConfirmationModal', this.updateModal); + }, + beforeDestroy() { + eventHub.$off('actionConfirmationModal', this.updateModal); + }, + methods: { + updateModal(action) { + this.id = action.id; + this.callback = action.callback; + }, + onSubmit() { + this.callback(); + }, + }, + }; +</script> + +<template> + <modal + id="retry-confirmation-modal" + :title="title" + :text="text" + kind="danger" + :primary-button-label="primaryButtonLabel" + @submit="onSubmit" + > + <template + slot="body" + slot-scope="props" + > + <p v-html="props.text"></p> + </template> + </modal> +</template> diff --git a/app/assets/javascripts/pipelines/components/stop_confirmation_modal.vue b/app/assets/javascripts/pipelines/components/stop_confirmation_modal.vue new file mode 100644 index 00000000000..d737d567787 --- /dev/null +++ b/app/assets/javascripts/pipelines/components/stop_confirmation_modal.vue @@ -0,0 +1,65 @@ +<script> + import modal from '~/vue_shared/components/modal.vue'; + import { s__, sprintf } from '~/locale'; + import eventHub from '../event_hub'; + + export default { + components: { + modal, + }, + data() { + return { + id: '', + callback: () => {}, + }; + }, + computed: { + title() { + return sprintf(s__('Pipeline|Stop pipeline #%{id}?'), { + id: `'${this.id}'`, + }, false); + }, + text() { + return sprintf(s__('Pipeline|You’re about to stop pipeline %{id}.'), { + id: `<strong>#${this.id}</strong>`, + }, false); + }, + primaryButtonLabel() { + return s__('Pipeline|Stop pipeline'); + }, + }, + created() { + eventHub.$on('actionConfirmationModal', this.updateModal); + }, + beforeDestroy() { + eventHub.$off('actionConfirmationModal', this.updateModal); + }, + methods: { + updateModal(action) { + this.id = action.id; + this.callback = action.callback; + }, + onSubmit() { + this.callback(); + }, + }, + }; +</script> + +<template> + <modal + id="stop-confirmation-modal" + :title="title" + :text="text" + kind="danger" + :primary-button-label="primaryButtonLabel" + @submit="onSubmit" + > + <template + slot="body" + slot-scope="props" + > + <p v-html="props.text"></p> + </template> + </modal> +</template> diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index 592c99fc64a..37a06b65481 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -109,7 +109,8 @@ describe 'Pipelines', :js do context 'when canceling' do before do - accept_confirm { find('.js-pipelines-cancel-button').click } + find('.js-pipelines-cancel-button').click + find('.js-primary-button').click wait_for_requests end @@ -140,6 +141,7 @@ describe 'Pipelines', :js do context 'when retrying' do before do find('.js-pipelines-retry-button').click + find('.js-primary-button').click wait_for_requests end @@ -238,7 +240,8 @@ describe 'Pipelines', :js do context 'when canceling' do before do - accept_alert { find('.js-pipelines-cancel-button').click } + find('.js-pipelines-cancel-button').click + find('.js-primary-button').click end it 'indicates that pipeline was canceled' do diff --git a/spec/javascripts/groups/components/app_spec.js b/spec/javascripts/groups/components/app_spec.js index 8338efe915b..3adc29262f3 100644 --- a/spec/javascripts/groups/components/app_spec.js +++ b/spec/javascripts/groups/components/app_spec.js @@ -268,10 +268,10 @@ describe('AppComponent', () => { it('updates props which show modal confirmation dialog', () => { const group = Object.assign({}, mockParentGroupItem); - expect(vm.showModal).toBeFalsy(); + expect(vm.updateModal).toBeFalsy(); expect(vm.groupLeaveConfirmationMessage).toBe(''); vm.showLeaveGroupModal(group, mockParentGroupItem); - expect(vm.showModal).toBeTruthy(); + expect(vm.updateModal).toBeTruthy(); expect(vm.groupLeaveConfirmationMessage).toBe(`Are you sure you want to leave the "${group.fullName}" group?`); }); }); @@ -280,9 +280,9 @@ describe('AppComponent', () => { it('hides modal confirmation which is shown before leaving the group', () => { const group = Object.assign({}, mockParentGroupItem); vm.showLeaveGroupModal(group, mockParentGroupItem); - expect(vm.showModal).toBeTruthy(); + expect(vm.updateModal).toBeTruthy(); vm.hideLeaveGroupModal(); - expect(vm.showModal).toBeFalsy(); + expect(vm.updateModal).toBeFalsy(); }); }); @@ -307,7 +307,7 @@ describe('AppComponent', () => { spyOn($, 'scrollTo'); vm.leaveGroup(); - expect(vm.showModal).toBeFalsy(); + expect(vm.updateModal).toBeFalsy(); expect(vm.targetGroup.isBeingRemoved).toBeTruthy(); expect(vm.service.leaveGroup).toHaveBeenCalledWith(vm.targetGroup.leavePath); setTimeout(() => { @@ -475,7 +475,7 @@ describe('AppComponent', () => { it('renders modal confirmation dialog', () => { vm.groupLeaveConfirmationMessage = 'Are you sure you want to leave the "foo" group?'; - vm.showModal = true; + vm.updateModal = true; const modalDialogEl = vm.$el.querySelector('.modal'); expect(modalDialogEl).not.toBe(null); expect(modalDialogEl.querySelector('.modal-title').innerText.trim()).toBe('Are you sure?'); diff --git a/spec/javascripts/pipelines/async_button_spec.js b/spec/javascripts/pipelines/async_button_spec.js index d010d897642..8ce33d410a7 100644 --- a/spec/javascripts/pipelines/async_button_spec.js +++ b/spec/javascripts/pipelines/async_button_spec.js @@ -15,6 +15,7 @@ describe('Pipelines Async Button', () => { title: 'Foo', icon: 'repeat', cssClass: 'bar', + id: 123, }, }).$mount(); }); @@ -38,9 +39,8 @@ describe('Pipelines Async Button', () => { describe('With confirm dialog', () => { it('should call the service when confimation is positive', () => { - spyOn(window, 'confirm').and.returnValue(true); - eventHub.$on('postAction', (endpoint) => { - expect(endpoint).toEqual('/foo'); + eventHub.$on('actionConfirmationModal', (data) => { + expect(data.id).toEqual(123); }); component = new AsyncButtonComponent({ @@ -49,7 +49,7 @@ describe('Pipelines Async Button', () => { title: 'Foo', icon: 'fa fa-foo', cssClass: 'bar', - confirmActionMessage: 'bar', + id: 123, }, }).$mount(); |