summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/deploy_freeze
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/deploy_freeze')
-rw-r--r--app/assets/javascripts/deploy_freeze/components/deploy_freeze_table.vue63
-rw-r--r--app/assets/javascripts/deploy_freeze/store/actions.js16
-rw-r--r--app/assets/javascripts/deploy_freeze/store/mutation_types.js4
-rw-r--r--app/assets/javascripts/deploy_freeze/store/mutations.js33
4 files changed, 110 insertions, 6 deletions
diff --git a/app/assets/javascripts/deploy_freeze/components/deploy_freeze_table.vue b/app/assets/javascripts/deploy_freeze/components/deploy_freeze_table.vue
index 8282f1d910a..77767456f76 100644
--- a/app/assets/javascripts/deploy_freeze/components/deploy_freeze_table.vue
+++ b/app/assets/javascripts/deploy_freeze/components/deploy_freeze_table.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTable, GlButton, GlModalDirective, GlSprintf } from '@gitlab/ui';
+import { GlTable, GlButton, GlModal, GlModalDirective, GlSprintf } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import { s__ } from '~/locale';
@@ -21,21 +21,42 @@ export default {
key: 'edit',
label: s__('DeployFreeze|Edit'),
},
+ {
+ key: 'delete',
+ label: s__('DeployFreeze|Delete'),
+ },
],
translations: {
addDeployFreeze: s__('DeployFreeze|Add deploy freeze'),
+ deleteDeployFreezeTitle: s__('DeployFreeze|Delete deploy freeze?'),
+ deleteDeployFreezeMessage: s__(
+ 'DeployFreeze|Deploy freeze from %{start} to %{end} in %{timezone} will be removed. Are you sure?',
+ ),
emptyStateText: s__(
'DeployFreeze|No deploy freezes exist for this project. To add one, select %{strongStart}Add deploy freeze%{strongEnd}',
),
},
+ modal: {
+ id: 'deleteFreezePeriodModal',
+ actionPrimary: {
+ text: s__('DeployFreeze|Delete freeze period'),
+ attributes: { variant: 'danger', 'data-testid': 'modal-confirm' },
+ },
+ },
components: {
GlTable,
GlButton,
+ GlModal,
GlSprintf,
},
directives: {
GlModal: GlModalDirective,
},
+ data() {
+ return {
+ freezePeriodToDelete: null,
+ };
+ },
computed: {
...mapState(['freezePeriods']),
tableIsNotEmpty() {
@@ -46,7 +67,14 @@ export default {
this.fetchFreezePeriods();
},
methods: {
- ...mapActions(['fetchFreezePeriods', 'setFreezePeriod']),
+ ...mapActions(['fetchFreezePeriods', 'setFreezePeriod', 'deleteFreezePeriod']),
+ handleDeleteFreezePeriod(freezePeriod) {
+ this.freezePeriodToDelete = freezePeriod;
+ },
+ confirmDeleteFreezePeriod() {
+ this.deleteFreezePeriod(this.freezePeriodToDelete);
+ this.freezePeriodToDelete = null;
+ },
},
};
</script>
@@ -72,6 +100,18 @@ export default {
@click="setFreezePeriod(item)"
/>
</template>
+ <template #cell(delete)="{ item }">
+ <gl-button
+ v-gl-modal="$options.modal.id"
+ category="secondary"
+ variant="danger"
+ icon="remove"
+ :aria-label="$options.modal.actionPrimary.text"
+ :loading="item.isDeleting"
+ data-testid="delete-deploy-freeze"
+ @click="handleDeleteFreezePeriod(item)"
+ />
+ </template>
<template #empty>
<p data-testid="empty-freeze-periods" class="gl-text-center text-plain">
<gl-sprintf :message="$options.translations.emptyStateText">
@@ -90,5 +130,24 @@ export default {
>
{{ $options.translations.addDeployFreeze }}
</gl-button>
+ <gl-modal
+ :title="$options.translations.deleteDeployFreezeTitle"
+ :modal-id="$options.modal.id"
+ :action-primary="$options.modal.actionPrimary"
+ static
+ @primary="confirmDeleteFreezePeriod"
+ >
+ <template v-if="freezePeriodToDelete">
+ <gl-sprintf :message="$options.translations.deleteDeployFreezeMessage">
+ <template #start>
+ <code>{{ freezePeriodToDelete.freezeStart }}</code>
+ </template>
+ <template #end>
+ <code>{{ freezePeriodToDelete.freezeEnd }}</code>
+ </template>
+ <template #timezone>{{ freezePeriodToDelete.cronTimezone.formattedTimezone }}</template>
+ </gl-sprintf>
+ </template>
+ </gl-modal>
</div>
</template>
diff --git a/app/assets/javascripts/deploy_freeze/store/actions.js b/app/assets/javascripts/deploy_freeze/store/actions.js
index fed80b46eda..1ac6781a0e3 100644
--- a/app/assets/javascripts/deploy_freeze/store/actions.js
+++ b/app/assets/javascripts/deploy_freeze/store/actions.js
@@ -1,5 +1,6 @@
import Api from '~/api';
import createFlash from '~/flash';
+import { logError } from '~/lib/logger';
import { __ } from '~/locale';
import * as types from './mutation_types';
@@ -52,6 +53,21 @@ export const updateFreezePeriod = (store) =>
}),
);
+export const deleteFreezePeriod = ({ state, commit }, { id }) => {
+ commit(types.REQUEST_DELETE_FREEZE_PERIOD, id);
+
+ return Api.deleteFreezePeriod(state.projectId, id)
+ .then(() => commit(types.RECEIVE_DELETE_FREEZE_PERIOD_SUCCESS, id))
+ .catch((e) => {
+ createFlash({
+ message: __('Error: Unable to delete deploy freeze'),
+ });
+ commit(types.RECEIVE_DELETE_FREEZE_PERIOD_ERROR, id);
+
+ logError(`Unable to delete deploy freeze`, e);
+ });
+};
+
export const fetchFreezePeriods = ({ commit, state }) => {
commit(types.REQUEST_FREEZE_PERIODS);
diff --git a/app/assets/javascripts/deploy_freeze/store/mutation_types.js b/app/assets/javascripts/deploy_freeze/store/mutation_types.js
index 8e6fdfd4443..0fec96e2e4c 100644
--- a/app/assets/javascripts/deploy_freeze/store/mutation_types.js
+++ b/app/assets/javascripts/deploy_freeze/store/mutation_types.js
@@ -10,4 +10,8 @@ export const SET_SELECTED_ID = 'SET_SELECTED_ID';
export const SET_FREEZE_START_CRON = 'SET_FREEZE_START_CRON';
export const SET_FREEZE_END_CRON = 'SET_FREEZE_END_CRON';
+export const REQUEST_DELETE_FREEZE_PERIOD = 'REQUEST_DELETE_FREEZE_PERIOD';
+export const RECEIVE_DELETE_FREEZE_PERIOD_SUCCESS = 'RECEIVE_DELETE_FREEZE_PERIOD_SUCCESS';
+export const RECEIVE_DELETE_FREEZE_PERIOD_ERROR = 'RECEIVE_DELETE_FREEZE_PERIOD_ERROR';
+
export const RESET_MODAL = 'RESET_MODAL';
diff --git a/app/assets/javascripts/deploy_freeze/store/mutations.js b/app/assets/javascripts/deploy_freeze/store/mutations.js
index fdd1ea6e32e..151f7f39f5a 100644
--- a/app/assets/javascripts/deploy_freeze/store/mutations.js
+++ b/app/assets/javascripts/deploy_freeze/store/mutations.js
@@ -1,15 +1,28 @@
+import Vue from 'vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { secondsToHours } from '~/lib/utils/datetime_utility';
import * as types from './mutation_types';
-const formatTimezoneName = (freezePeriod, timezoneList) =>
- convertObjectPropsToCamelCase({
+const formatTimezoneName = (freezePeriod, timezoneList) => {
+ const tz = timezoneList.find((timezone) => timezone.identifier === freezePeriod.cron_timezone);
+ return convertObjectPropsToCamelCase({
...freezePeriod,
cron_timezone: {
- formattedTimezone: timezoneList.find((tz) => tz.identifier === freezePeriod.cron_timezone)
- ?.name,
+ formattedTimezone: tz && `[UTC ${secondsToHours(tz.offset)}] ${tz.name}`,
identifier: freezePeriod.cron_timezone,
},
});
+};
+
+const setFreezePeriodIsDeleting = (state, id, isDeleting) => {
+ const freezePeriod = state.freezePeriods.find((f) => f.id === id);
+
+ if (!freezePeriod) {
+ return;
+ }
+
+ Vue.set(freezePeriod, 'isDeleting', isDeleting);
+};
export default {
[types.REQUEST_FREEZE_PERIODS](state) {
@@ -53,6 +66,18 @@ export default {
state.selectedId = id;
},
+ [types.REQUEST_DELETE_FREEZE_PERIOD](state, id) {
+ setFreezePeriodIsDeleting(state, id, true);
+ },
+
+ [types.RECEIVE_DELETE_FREEZE_PERIOD_SUCCESS](state, id) {
+ state.freezePeriods = state.freezePeriods.filter((f) => f.id !== id);
+ },
+
+ [types.RECEIVE_DELETE_FREEZE_PERIOD_ERROR](state, id) {
+ setFreezePeriodIsDeleting(state, id, false);
+ },
+
[types.RESET_MODAL](state) {
state.freezeStartCron = '';
state.freezeEndCron = '';