summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/registry
diff options
context:
space:
mode:
authorNick Kipling <nkipling@gitlab.com>2019-07-26 19:42:49 +0100
committerNathan Friend <nathan@gitlab.com>2019-07-30 13:49:49 -0300
commit918e7d43dfe614475ee2dd2b6f4c765726db6ef4 (patch)
treee76709006133602ecd904827346e21021d8a37da /app/assets/javascripts/registry
parenta37d672ff5c4c102a5b507ad744919748cbdcb34 (diff)
downloadgitlab-ce-918e7d43dfe614475ee2dd2b6f4c765726db6ef4.tar.gz
Reworked how deletion works with multi vs single
Single deletion no longer requires a prop Modal description is now generated on demand Added dedicated functions for deleting Updated tests to match new function naming Updated css class name to be more specific
Diffstat (limited to 'app/assets/javascripts/registry')
-rw-r--r--app/assets/javascripts/registry/components/table_registry.vue99
-rw-r--r--app/assets/javascripts/registry/stores/actions.js3
2 files changed, 54 insertions, 48 deletions
diff --git a/app/assets/javascripts/registry/components/table_registry.vue b/app/assets/javascripts/registry/components/table_registry.vue
index 90d6a4ce27f..df665b36c4b 100644
--- a/app/assets/javascripts/registry/components/table_registry.vue
+++ b/app/assets/javascripts/registry/components/table_registry.vue
@@ -41,6 +41,7 @@ export default {
itemsToBeDeleted: [],
modalId: `confirm-image-deletion-modal-${this.repo.id}`,
selectAllChecked: false,
+ modalDescription: '',
};
},
computed: {
@@ -54,67 +55,68 @@ export default {
return n__(
'ContainerRegistry|Remove image',
'ContainerRegistry|Remove images',
- this.singleItemSelected ? 1 : this.itemsToBeDeleted.length,
+ this.itemsToBeDeleted.length === 0 ? 1 : this.itemsToBeDeleted.length,
);
},
- modalDescription() {
- const selectedCount = this.itemsToBeDeleted.length;
-
- if (this.singleItemSelected) {
- // Attempt to pull 'single' property if it's an object in this.itemsToBeDeleted
- // Otherwise, simply use the int value of the selected row
- const { single: itemIndex = this.itemsToBeDeleted[0] } = this.itemsToBeDeleted[0];
+ },
+ methods: {
+ ...mapActions(['fetchList', 'deleteItem', 'multiDeleteItems']),
+ setModalDescription(itemsToDeleteLength, itemIndex) {
+ if (itemsToDeleteLength) {
+ this.modalDescription = sprintf(
+ s__(`ContainerRegistry|You are about to delete <b>%{count}</b> images. This will
+ delete the images and all tags pointing to them.`),
+ { count: itemsToDeleteLength },
+ );
+ } else {
const { tag } = this.repo.list[itemIndex];
- return sprintf(
+ this.modalDescription = sprintf(
s__(`ContainerRegistry|You are about to delete the image <b>%{title}</b>. This will
- delete the image and all tags pointing to this image.`),
+ delete the image and all tags pointing to this image.`),
{ title: `${this.repo.name}:${tag}` },
);
}
-
- return sprintf(
- s__(`ContainerRegistry|You are about to delete <b>%{count}</b> images. This will
- delete the images and all tags pointing to them.`),
- { count: selectedCount },
- );
- },
- singleItemSelected() {
- return this.findSingleRowToDelete || this.itemsToBeDeleted.length === 1;
},
- findSingleRowToDelete() {
- return this.itemsToBeDeleted.find(x => x.single !== undefined);
- },
- },
- methods: {
- ...mapActions(['fetchList', 'deleteItems']),
layers(item) {
return item.layers ? n__('%d layer', '%d layers', item.layers) : '';
},
formatSize(size) {
return numberToHumanSize(size);
},
- addSingleItemToBeDeleted(index) {
- this.itemsToBeDeleted.push({ single: index });
+ removeModalEvents() {
+ this.$refs.deleteModal.$refs.modal.$off('ok');
+ this.$refs.deleteModal.$refs.modal.$off('hide');
},
- removeSingleItemToBeDeleted() {
- const singleIndex = this.itemsToBeDeleted.findIndex(x => x.single !== undefined);
+ deleteSingleItem(index) {
+ this.setModalDescription(0, index);
- if (singleIndex > -1) {
- this.itemsToBeDeleted.splice(singleIndex, 1);
- }
- },
- handleDeleteRegistry() {
- let { itemsToBeDeleted } = this;
+ this.$refs.deleteModal.$refs.modal.$once('ok', () => {
+ this.removeModalEvents();
+ this.handleSingleDelete(this.repo.list[index]);
+ });
- if (this.findSingleRowToDelete) {
- itemsToBeDeleted = [this.findSingleRowToDelete.single];
- }
+ this.$refs.deleteModal.$refs.modal.$once('hide', this.removeModalEvents);
+ },
+ deleteMultipleItems() {
+ this.$refs.deleteModal.$refs.modal.$once('ok', () => {
+ this.removeModalEvents();
+ this.handleMultipleDelete();
+ });
+ this.$refs.deleteModal.$refs.modal.$once('hide', this.removeModalEvents);
+ },
+ handleSingleDelete(itemToDelete) {
+ this.deleteItem(itemToDelete)
+ .then(() => this.fetchList({ repo: this.repo }))
+ .catch(() => this.showError(errorMessagesTypes.DELETE_REGISTRY));
+ },
+ handleMultipleDelete() {
+ const { itemsToBeDeleted } = this;
this.itemsToBeDeleted = [];
if (this.bulkDeletePath) {
- this.deleteItems({
+ this.multiDeleteItems({
path: this.bulkDeletePath,
items: itemsToBeDeleted.map(x => this.repo.list[x].tag),
})
@@ -142,6 +144,7 @@ export default {
selectAll() {
this.itemsToBeDeleted = this.repo.list.map((x, index) => index);
this.selectAllChecked = true;
+ this.setModalDescription(this.itemsToBeDeleted.length);
},
deselectAll() {
this.itemsToBeDeleted = [];
@@ -160,6 +163,12 @@ export default {
this.selectAllChecked = true;
}
}
+
+ if (this.itemsToBeDeleted.length === 1) {
+ this.setModalDescription(0, this.itemsToBeDeleted[0]);
+ } else if (this.itemsToBeDeleted.length > 1) {
+ this.setModalDescription(this.itemsToBeDeleted.length);
+ }
},
},
};
@@ -191,13 +200,14 @@ export default {
variant="danger"
:title="s__('ContainerRegistry|Remove selected images')"
:aria-label="s__('ContainerRegistry|Remove selected images')"
+ @click="deleteMultipleItems()"
><icon name="remove"
/></gl-button>
</th>
</tr>
</thead>
<tbody>
- <tr v-for="(item, index) in repo.list" :key="item.tag" class="image-row">
+ <tr v-for="(item, index) in repo.list" :key="item.tag" class="registry-image-row">
<td class="check">
<gl-form-checkbox
v-if="item.canDelete"
@@ -242,7 +252,7 @@ export default {
:aria-label="s__('ContainerRegistry|Remove image')"
variant="danger"
class="js-delete-registry-row float-right btn-inverted btn-border-color btn-icon"
- @click="addSingleItemToBeDeleted(index)"
+ @click="deleteSingleItem(index)"
>
<icon name="remove" />
</gl-button>
@@ -257,12 +267,7 @@ export default {
:page-info="repo.pagination"
/>
- <gl-modal
- :modal-id="modalId"
- ok-variant="danger"
- @ok="handleDeleteRegistry"
- @cancel="removeSingleItemToBeDeleted"
- >
+ <gl-modal ref="deleteModal" :modal-id="modalId" ok-variant="danger">
<template v-slot:modal-title>{{ modalTitle }}</template>
<template v-slot:modal-ok>{{ s__('ContainerRegistry|Remove image(s) and tags') }}</template>
<p v-html="modalDescription"></p>
diff --git a/app/assets/javascripts/registry/stores/actions.js b/app/assets/javascripts/registry/stores/actions.js
index 4c20c003c5a..a2e0130e79e 100644
--- a/app/assets/javascripts/registry/stores/actions.js
+++ b/app/assets/javascripts/registry/stores/actions.js
@@ -36,7 +36,8 @@ export const fetchList = ({ commit }, { repo, page }) => {
};
export const deleteItem = (_, item) => axios.delete(item.destroyPath);
-export const deleteItems = (_, { path, items }) => axios.delete(path, { params: { ids: items } });
+export const multiDeleteItems = (_, { path, items }) =>
+ axios.delete(path, { params: { ids: items } });
export const setMainEndpoint = ({ commit }, data) => commit(types.SET_MAIN_ENDPOINT, data);
export const toggleLoading = ({ commit }) => commit(types.TOGGLE_MAIN_LOADING);