debian-mirror-gitlab/app/assets/javascripts/artifacts/components/artifacts_bulk_delete.vue
2023-05-27 22:25:52 +05:30

182 lines
4.9 KiB
Vue

<script>
import { GlButton, GlModal, GlSprintf } from '@gitlab/ui';
import { createAlert } from '~/alert';
import { TYPENAME_PROJECT } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import getJobArtifactsQuery from '../graphql/queries/get_job_artifacts.query.graphql';
import bulkDestroyJobArtifactsMutation from '../graphql/mutations/bulk_destroy_job_artifacts.mutation.graphql';
import { removeArtifactFromStore } from '../graphql/cache_update';
import {
I18N_BULK_DELETE_BANNER,
I18N_BULK_DELETE_CLEAR_SELECTION,
I18N_BULK_DELETE_DELETE_SELECTED,
I18N_BULK_DELETE_MODAL_TITLE,
I18N_BULK_DELETE_BODY,
I18N_BULK_DELETE_ACTION,
I18N_BULK_DELETE_PARTIAL_ERROR,
I18N_BULK_DELETE_ERROR,
I18N_MODAL_CANCEL,
BULK_DELETE_MODAL_ID,
} from '../constants';
export default {
name: 'ArtifactsBulkDelete',
components: {
GlButton,
GlModal,
GlSprintf,
},
inject: ['projectId'],
props: {
selectedArtifacts: {
type: Array,
required: true,
},
queryVariables: {
type: Object,
required: true,
},
},
data() {
return {
isModalVisible: false,
isDeleting: false,
};
},
computed: {
checkedCount() {
return this.selectedArtifacts.length || 0;
},
modalActionPrimary() {
return {
text: I18N_BULK_DELETE_ACTION(this.checkedCount),
attributes: {
loading: this.isDeleting,
variant: 'danger',
},
};
},
modalActionCancel() {
return {
text: I18N_MODAL_CANCEL,
attributes: {
loading: this.isDeleting,
},
};
},
},
methods: {
async onConfirmDelete(e) {
// don't close modal until deletion is complete
if (e) {
e.preventDefault();
}
this.isDeleting = true;
try {
await this.$apollo.mutate({
mutation: bulkDestroyJobArtifactsMutation,
variables: {
projectId: convertToGraphQLId(TYPENAME_PROJECT, this.projectId),
ids: this.selectedArtifacts,
},
update: (store, { data }) => {
const { errors, destroyedCount, destroyedIds } = data.bulkDestroyJobArtifacts;
if (errors?.length) {
createAlert({
message: I18N_BULK_DELETE_PARTIAL_ERROR,
captureError: true,
error: new Error(errors.join(' ')),
});
}
if (destroyedIds?.length) {
this.$emit('deleted', destroyedCount);
// Remove deleted artifacts from the cache
destroyedIds.forEach((id) => {
removeArtifactFromStore(store, id, getJobArtifactsQuery, this.queryVariables);
});
store.gc();
this.$emit('clearSelectedArtifacts');
}
},
});
} catch (error) {
this.onError(error);
} finally {
this.isDeleting = false;
this.isModalVisible = false;
}
},
onError(error) {
createAlert({
message: I18N_BULK_DELETE_ERROR,
captureError: true,
error,
});
},
handleClearSelection() {
this.$emit('clearSelectedArtifacts');
},
handleModalShow() {
this.isModalVisible = true;
},
handleModalHide() {
this.isModalVisible = false;
},
},
i18n: {
banner: I18N_BULK_DELETE_BANNER,
clearSelection: I18N_BULK_DELETE_CLEAR_SELECTION,
deleteSelected: I18N_BULK_DELETE_DELETE_SELECTED,
modalTitle: I18N_BULK_DELETE_MODAL_TITLE,
modalBody: I18N_BULK_DELETE_BODY,
},
BULK_DELETE_MODAL_ID,
};
</script>
<template>
<div class="gl-my-4 gl-p-4 gl-border-1 gl-border-solid gl-border-gray-100">
<div class="gl-display-flex gl-align-items-center">
<div>
<gl-sprintf :message="$options.i18n.banner(checkedCount)">
<template #strong="{ content }">
<strong>{{ content }}</strong>
</template>
</gl-sprintf>
</div>
<div class="gl-ml-auto">
<gl-button
variant="default"
data-testid="bulk-delete-clear-button"
@click="handleClearSelection"
>
{{ $options.i18n.clearSelection }}
</gl-button>
<gl-button
variant="danger"
data-testid="bulk-delete-delete-button"
@click="handleModalShow"
>
{{ $options.i18n.deleteSelected }}
</gl-button>
</div>
</div>
<gl-modal
size="sm"
:modal-id="$options.BULK_DELETE_MODAL_ID"
:visible="isModalVisible"
:title="$options.i18n.modalTitle(checkedCount)"
:action-primary="modalActionPrimary"
:action-cancel="modalActionCancel"
@hide="handleModalHide"
@primary="onConfirmDelete"
>
<gl-sprintf
data-testid="bulk-delete-modal-content"
:message="$options.i18n.modalBody(checkedCount)"
/>
</gl-modal>
</div>
</template>