Unverified Commit 076f5e4b authored by Dannon's avatar Dannon Committed by GitHub
Browse files

Merge pull request #14115 from davelopez/fix_bulk_operations_visibility

[22.05] Fix bulk operations visibility
parents b9e8b5e8 df00f977
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
<template>
    <b-modal
        v-model="show"
        title="Something went wrong..."
        header-text-variant="danger"
        :title="title"
        :header-text-variant="titleVariant"
        title-tag="h2"
        scrollable
        ok-only
@@ -60,6 +60,12 @@ export default {
            }
            return [];
        },
        title() {
            return this.isPartialSuccess ? "Some items could not be processed" : "Something went wrong...";
        },
        titleVariant() {
            return this.isPartialSuccess ? "warning" : "danger";
        },
        errorMessage() {
            return this.operationError?.errorMessage?.message;
        },
+36 −2
Original line number Diff line number Diff line
@@ -24,6 +24,9 @@ const TASKS_CONFIG = {
    enable_celery_tasks: true,
};

const getPurgedContentSelection = () => new Map([["FAKE_ID", { purged: true }]]);
const getNonPurgedContentSelection = () => new Map([["FAKE_ID", { purged: false }]]);

async function mountSelectionOperationsWrapper(config) {
    const wrapper = shallowMount(
        SelectionOperations,
@@ -93,10 +96,41 @@ describe("History Selection Operations", () => {
                expect(wrapper.find(option).exists()).toBe(false);
            });

            it("should display 'undelete' option only on deleted items", async () => {
            it("should display 'permanently delete' option always", async () => {
                const option = '[data-description="purge option"]';
                expect(wrapper.find(option).exists()).toBe(true);
                await wrapper.setProps({ filterText: "deleted:true" });
                expect(wrapper.find(option).exists()).toBe(true);
            });

            it("should display 'undelete' option only on deleted and non-purged items", async () => {
                const option = '[data-description="undelete option"]';
                expect(wrapper.find(option).exists()).toBe(false);
                await wrapper.setProps({ filterText: "deleted:true" });
                await wrapper.setProps({
                    filterText: "deleted:true",
                    contentSelection: getNonPurgedContentSelection(),
                });
                expect(wrapper.find(option).exists()).toBe(true);
            });

            it("should not display 'undelete' when is manual selection mode and all selected items are purged", async () => {
                const option = '[data-description="undelete option"]';
                await wrapper.setProps({
                    filterText: "deleted:true",
                    contentSelection: getPurgedContentSelection(),
                    isQuerySelection: false,
                });
                expect(wrapper.find(option).exists()).toBe(false);
            });

            it("should display 'undelete' option when is query selection mode and filtering by deleted", async () => {
                const option = '[data-description="undelete option"]';
                // In query selection mode we don't know if some items may not be purged, so we allow to undelete
                await wrapper.setProps({
                    filterText: "deleted:true",
                    contentSelection: getPurgedContentSelection(),
                    isQuerySelection: true,
                });
                expect(wrapper.find(option).exists()).toBe(true);
            });

+14 −3
Original line number Diff line number Diff line
@@ -20,15 +20,15 @@
                    <span v-localize>Hide</span>
                </b-dropdown-item>
                <b-dropdown-item
                    v-if="showDeleted"
                    v-if="canUndeleteSelection"
                    v-b-modal:restore-selected-content
                    data-description="undelete option">
                    <span v-localize>Undelete</span>
                </b-dropdown-item>
                <b-dropdown-item v-else v-b-modal:delete-selected-content data-description="delete option">
                <b-dropdown-item v-if="!showDeleted" v-b-modal:delete-selected-content data-description="delete option">
                    <span v-localize>Delete</span>
                </b-dropdown-item>
                <b-dropdown-item v-if="!showDeleted" v-b-modal:purge-selected-content data-description="purge option">
                <b-dropdown-item v-b-modal:purge-selected-content data-description="purge option">
                    <span v-localize>Delete (permanently)</span>
                </b-dropdown-item>
                <b-dropdown-divider v-if="showBuildOptions" />
@@ -210,6 +210,17 @@ export default {
        noTagsSelected() {
            return this.selectedTags.length === 0;
        },
        canUndeleteSelection() {
            return this.showDeleted && (this.isQuerySelection || !this.areAllSelectedPurged);
        },
        areAllSelectedPurged() {
            for (const item of this.contentSelection.values()) {
                if (Object.prototype.hasOwnProperty.call(item, "purged") && !item["purged"]) {
                    return false;
                }
            }
            return true;
        },
    },
    watch: {
        hasSelection(newVal) {
+5 −1
Original line number Diff line number Diff line
@@ -1602,11 +1602,15 @@ class HistoryItemOperator:

    def _undelete(self, item: HistoryItemModel):
        if getattr(item, "purged", False):
            return
            raise exceptions.ItemDeletionException("This item has been permanently deleted and cannot be recovered.")
        manager = self._get_item_manager(item)
        manager.undelete(item, flush=self.flush)

    def _purge(self, item: HistoryItemModel, trans: ProvidesHistoryContext):
        if getattr(item, "purged", False):
            # TODO: remove this `update` when we can properly track the operation results to notify the history
            item.update()
            return
        if isinstance(item, HistoryDatasetCollectionAssociation):
            return self.dataset_collection_manager.delete(trans, "history", item.id, recursive=True, purge=True)
        self.hda_manager.purge(item, flush=self.flush)
+5 −2
Original line number Diff line number Diff line
@@ -1122,7 +1122,7 @@ class HistoryContentsApiBulkOperationTestCase(ApiTestCase):
            # collections don't have a `purged` attribute but they should be marked deleted on purge
            assert purged_collection["deleted"] is True

            # Un-deleting a purged dataset should not have any effect
            # Un-deleting a purged dataset should not have any effect and raise an error
            payload = {
                "operation": "undelete",
                "items": [
@@ -1134,7 +1134,10 @@ class HistoryContentsApiBulkOperationTestCase(ApiTestCase):
            }
            bulk_operation_result = self._apply_bulk_operation(history_id, payload)
            history_contents = self._get_history_contents(history_id)
            self._assert_bulk_success(bulk_operation_result, 1)
            assert bulk_operation_result["success_count"] == 0
            assert len(bulk_operation_result["errors"]) == 1
            error = bulk_operation_result["errors"][0]
            assert error["item"]["id"] == datasets_ids[0]
            purged_dataset = self._get_dataset_with_id_from_history_contents(history_contents, datasets_ids[0])
            assert purged_dataset["deleted"] is True
            assert purged_dataset["purged"] is True