Add modal for stopping jobs in admin area
This commit is contained in:
		
							parent
							
								
									3b13159d9c
								
							
						
					
					
						commit
						76f16bbf71
					
				|  | @ -157,6 +157,11 @@ import Activities from './activities'; | |||
|         case 'dashboard:todos:index': | ||||
|           import('./pages/dashboard/todos/index').then(callDefault).catch(fail); | ||||
|           break; | ||||
|         case 'admin:jobs:index': | ||||
|           import('./pages/admin/jobs/index') | ||||
|             .then(callDefault) | ||||
|             .catch(fail); | ||||
|           break; | ||||
|         case 'dashboard:projects:index': | ||||
|         case 'dashboard:projects:starred': | ||||
|           import('./pages/dashboard/projects') | ||||
|  |  | |||
|  | @ -0,0 +1,47 @@ | |||
| <script> | ||||
|   import axios from '~/lib/utils/axios_utils'; | ||||
|   import Flash from '~/flash'; | ||||
|   import modal from '~/vue_shared/components/modal.vue'; | ||||
|   import { s__ } from '~/locale'; | ||||
|   import { redirectTo } from '~/lib/utils/url_utility'; | ||||
| 
 | ||||
|   export default { | ||||
|     components: { | ||||
|       modal, | ||||
|     }, | ||||
|     props: { | ||||
|       url: { | ||||
|         type: String, | ||||
|         required: true, | ||||
|       }, | ||||
|     }, | ||||
|     computed: { | ||||
|       text() { | ||||
|         return s__('AdminArea|You’re about to stop all jobs. This will halt all current jobs that are running.'); | ||||
|       }, | ||||
|     }, | ||||
|     methods: { | ||||
|       onSubmit() { | ||||
|         return axios.post(this.url) | ||||
|           .then((response) => { | ||||
|             // follow the rediect to refresh the page | ||||
|             redirectTo(response.request.responseURL); | ||||
|           }) | ||||
|           .catch((error) => { | ||||
|             Flash(s__('AdminArea|Stopping jobs failed')); | ||||
|             throw error; | ||||
|           }); | ||||
|       }, | ||||
|     }, | ||||
|   }; | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <modal | ||||
|     id="stop-jobs-modal" | ||||
|     :title="s__('AdminArea|Stop all jobs?')" | ||||
|     :text="text" | ||||
|     kind="danger" | ||||
|     :primary-button-label="s__('AdminArea|Stop jobs')" | ||||
|     @submit="onSubmit" /> | ||||
| </template> | ||||
|  | @ -0,0 +1,29 @@ | |||
| import Vue from 'vue'; | ||||
| 
 | ||||
| import Translate from '~/vue_shared/translate'; | ||||
| 
 | ||||
| import stopJobsModal from './components/stop_jobs_modal.vue'; | ||||
| 
 | ||||
| Vue.use(Translate); | ||||
| 
 | ||||
| export default () => { | ||||
|   const stopJobsButton = document.getElementById('stop-jobs-button'); | ||||
| 
 | ||||
|   // eslint-disable-next-line no-new
 | ||||
|   new Vue({ | ||||
|     el: '#stop-jobs-modal', | ||||
|     components: { | ||||
|       stopJobsModal, | ||||
|     }, | ||||
|     mounted() { | ||||
|       stopJobsButton.classList.remove('disabled'); | ||||
|     }, | ||||
|     render(createElement) { | ||||
|       return createElement('stop-jobs-modal', { | ||||
|         props: { | ||||
|           url: stopJobsButton.dataset.url, | ||||
|         }, | ||||
|       }); | ||||
|     }, | ||||
|   }); | ||||
| }; | ||||
|  | @ -12,6 +12,7 @@ | |||
|   min-height: $modal-body-height; | ||||
|   position: relative; | ||||
|   padding: #{3 * $grid-size} #{2 * $grid-size}; | ||||
|   text-align: left; | ||||
| 
 | ||||
|   .form-actions { | ||||
|     margin: #{2 * $grid-size} #{-2 * $grid-size} #{-2 * $grid-size}; | ||||
|  |  | |||
|  | @ -20,6 +20,6 @@ class Admin::JobsController < Admin::ApplicationController | |||
|   def cancel_all | ||||
|     Ci::Build.running_or_pending.each(&:cancel) | ||||
| 
 | ||||
|     redirect_to admin_jobs_path | ||||
|     redirect_to admin_jobs_path, status: 303 | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -9,7 +9,12 @@ | |||
| 
 | ||||
|     .nav-controls | ||||
|       - if @all_builds.running_or_pending.any? | ||||
|         = link_to 'Cancel all', cancel_all_admin_jobs_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post | ||||
|         #stop-jobs-modal | ||||
| 
 | ||||
|         %button#stop-jobs-button.btn.btn-danger{ data: { toggle: 'modal', | ||||
|           target: '#stop-jobs-modal', | ||||
|           url: cancel_all_admin_jobs_path } } | ||||
|           = s_('AdminArea|Stop all jobs') | ||||
| 
 | ||||
|   .row-content-block.second-block | ||||
|     #{(@scope || 'all').capitalize} jobs | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ describe 'Admin Builds' do | |||
|           expect(page).to have_selector('.nav-links li.active', text: 'All') | ||||
|           expect(page).to have_selector('.row-content-block', text: 'All jobs') | ||||
|           expect(page.all('.build-link').size).to eq(4) | ||||
|           expect(page).to have_link 'Cancel all' | ||||
|           expect(page).to have_button 'Stop all jobs' | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|  | @ -31,7 +31,7 @@ describe 'Admin Builds' do | |||
| 
 | ||||
|           expect(page).to have_selector('.nav-links li.active', text: 'All') | ||||
|           expect(page).to have_content 'No jobs to show' | ||||
|           expect(page).not_to have_link 'Cancel all' | ||||
|           expect(page).not_to have_button 'Stop all jobs' | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|  | @ -51,7 +51,7 @@ describe 'Admin Builds' do | |||
|           expect(page.find('.build-link')).not_to have_content(build2.id) | ||||
|           expect(page.find('.build-link')).not_to have_content(build3.id) | ||||
|           expect(page.find('.build-link')).not_to have_content(build4.id) | ||||
|           expect(page).to have_link 'Cancel all' | ||||
|           expect(page).to have_button 'Stop all jobs' | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|  | @ -63,7 +63,7 @@ describe 'Admin Builds' do | |||
| 
 | ||||
|           expect(page).to have_selector('.nav-links li.active', text: 'Pending') | ||||
|           expect(page).to have_content 'No jobs to show' | ||||
|           expect(page).not_to have_link 'Cancel all' | ||||
|           expect(page).not_to have_button 'Stop all jobs' | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|  | @ -83,7 +83,7 @@ describe 'Admin Builds' do | |||
|           expect(page.find('.build-link')).not_to have_content(build2.id) | ||||
|           expect(page.find('.build-link')).not_to have_content(build3.id) | ||||
|           expect(page.find('.build-link')).not_to have_content(build4.id) | ||||
|           expect(page).to have_link 'Cancel all' | ||||
|           expect(page).to have_button 'Stop all jobs' | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|  | @ -95,7 +95,7 @@ describe 'Admin Builds' do | |||
| 
 | ||||
|           expect(page).to have_selector('.nav-links li.active', text: 'Running') | ||||
|           expect(page).to have_content 'No jobs to show' | ||||
|           expect(page).not_to have_link 'Cancel all' | ||||
|           expect(page).not_to have_button 'Stop all jobs' | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|  | @ -113,7 +113,7 @@ describe 'Admin Builds' do | |||
|           expect(page.find('.build-link')).not_to have_content(build1.id) | ||||
|           expect(page.find('.build-link')).not_to have_content(build2.id) | ||||
|           expect(page.find('.build-link')).to have_content(build3.id) | ||||
|           expect(page).to have_link 'Cancel all' | ||||
|           expect(page).to have_button 'Stop all jobs' | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|  | @ -125,7 +125,7 @@ describe 'Admin Builds' do | |||
| 
 | ||||
|           expect(page).to have_selector('.nav-links li.active', text: 'Finished') | ||||
|           expect(page).to have_content 'No jobs to show' | ||||
|           expect(page).to have_link 'Cancel all' | ||||
|           expect(page).to have_button 'Stop all jobs' | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|  |  | |||
|  | @ -0,0 +1,63 @@ | |||
| import Vue from 'vue'; | ||||
| 
 | ||||
| import axios from '~/lib/utils/axios_utils'; | ||||
| import stopJobsModal from '~/pages/admin/jobs/index/components/stop_jobs_modal.vue'; | ||||
| import * as urlUtility from '~/lib/utils/url_utility'; | ||||
| 
 | ||||
| import mountComponent from '../../../../../helpers/vue_mount_component_helper'; | ||||
| 
 | ||||
| describe('stop_jobs_modal.vue', () => { | ||||
|   const props = { | ||||
|     url: `${gl.TEST_HOST}/stop_jobs_modal.vue/stopAll`, | ||||
|   }; | ||||
|   let vm; | ||||
| 
 | ||||
|   afterEach(() => { | ||||
|     vm.$destroy(); | ||||
|   }); | ||||
| 
 | ||||
|   beforeEach(() => { | ||||
|     const Component = Vue.extend(stopJobsModal); | ||||
|     vm = mountComponent(Component, props); | ||||
|   }); | ||||
| 
 | ||||
|   describe('onSubmit', () => { | ||||
|     it('stops jobs and redirects to overview page', (done) => { | ||||
|       const responseURL = `${gl.TEST_HOST}/stop_jobs_modal.vue/jobs`; | ||||
|       const redirectSpy = spyOn(urlUtility, 'redirectTo'); | ||||
|       spyOn(axios, 'post').and.callFake((url) => { | ||||
|         expect(url).toBe(props.url); | ||||
|         return Promise.resolve({ | ||||
|           request: { | ||||
|             responseURL, | ||||
|           }, | ||||
|         }); | ||||
|       }); | ||||
| 
 | ||||
|       vm.onSubmit() | ||||
|       .then(() => { | ||||
|         expect(redirectSpy).toHaveBeenCalledWith(responseURL); | ||||
|       }) | ||||
|       .then(done) | ||||
|       .catch(done.fail); | ||||
|     }); | ||||
| 
 | ||||
|     it('displays error if stopping jobs failed', (done) => { | ||||
|       const dummyError = new Error('stopping jobs failed'); | ||||
|       const redirectSpy = spyOn(urlUtility, 'redirectTo'); | ||||
|       spyOn(axios, 'post').and.callFake((url) => { | ||||
|         expect(url).toBe(props.url); | ||||
|         return Promise.reject(dummyError); | ||||
|       }); | ||||
| 
 | ||||
|       vm.onSubmit() | ||||
|         .then(done.fail) | ||||
|         .catch((error) => { | ||||
|           expect(error).toBe(dummyError); | ||||
|           expect(redirectSpy).not.toHaveBeenCalled(); | ||||
|         }) | ||||
|         .then(done) | ||||
|         .catch(done.fail); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
		Loading…
	
		Reference in New Issue