diff --git a/src/components/Process/Row.vue b/src/components/Process/Row.vue index 126a37be755c24bc5bfc5f37f12fd8b01168fbd0..8eb421f9ae1f460ee6eb5ec811f9887a6f8bf399 100644 --- a/src/components/Process/Row.vue +++ b/src/components/Process/Row.vue @@ -57,7 +57,7 @@ <p class="control" v-if="canDelete"> <button class="button has-text-danger" - v-on:click="remove" + v-on:click="deleteModal = hasAdminAccess" :disabled="!hasAdminAccess || null" :title="hasAdminAccess ? 'Delete this process' : 'An admin access is required to delete this process'" > @@ -67,25 +67,47 @@ </div> </td> </tr> + <Modal v-model="deleteModal" title="Delete process"> + <span> + Are you sure you want to delete process <strong>{{ deleteModalText }}</strong>? + </span> + <br /> + <span>This action is irreversible.</span> + <template v-slot:footer="{ close }"> + <button class="button" v-on:click="close">Cancel</button> + <button + class="button is-danger" + :class="{ 'is-loading': deleteLoading }" + v-on:click="remove" + > + Delete + </button> + </template> + </Modal> </template> <script> -import { mapState, mapGetters, mapMutations, mapActions } from 'vuex' +import { mapState, mapGetters, mapActions as mapVuexActions } from 'vuex' +import { mapActions } from 'pinia' import { PROCESS_MODES, PROCESS_FINAL_STATES } from '@/config' import { ago, errorParser, humanTimedelta, secondsToTimedelta } from '@/helpers' -import { corporaMixin } from '@/mixins' +import { corporaMixin, truncateMixin } from '@/mixins' import ItemId from '@/components/ItemId.vue' import StateTag from './StateTag.vue' +import Modal from '@/components/Modal.vue' +import { useNotificationStore } from '@/stores' export default { mixins: [ - corporaMixin + corporaMixin, + truncateMixin ], components: { ItemId, - StateTag + StateTag, + Modal }, emits: ['update'], props: { @@ -94,6 +116,10 @@ export default { required: true } }, + data: () => ({ + deleteModal: false, + deleteLoading: false + }), computed: { ...mapState('process', ['processes']), ...mapGetters('auth', ['isVerified']), @@ -164,17 +190,26 @@ export default { durationText () { if (['unscheduled', 'pending'].includes(this.process.state)) return 'Pending for ' return 'Running for ' + }, + deleteModalText () { + if (this.process.name?.length > 0) return `${this.truncateShort(this.process.name)} (${this.process.id})` + return this.process.id } }, methods: { - ...mapActions('process', ['deleteProcess', 'retryProcess']), - ...mapMutations('notifications', ['notify']), + ...mapVuexActions('process', ['deleteProcess', 'retryProcess']), + ...mapActions(useNotificationStore, ['notify']), async remove () { + if (this.deleteLoading || !this.hasAdminAccess) return + this.deleteLoading = true try { const response = await this.deleteProcess(this.processId) if (response.status === 204) this.$emit('update') + this.deleteModal = false } catch (err) { this.notify({ type: 'error', text: errorParser(err) }) + } finally { + this.deleteLoading = false } }, async retry () {