Loading client/src/components/History/CurrentHistory/HistoryOperations/SelectionOperations.test.js +44 −3 Original line number Diff line number Diff line Loading @@ -82,20 +82,33 @@ describe("History Selection Operations", () => { expect(wrapper.find(option).exists()).toBe(false); }); it("should display 'unhide' option only on hidden items", async () => { it("should display 'unhide' option on hidden items", async () => { const option = '[data-description="unhide option"]'; expect(wrapper.find(option).exists()).toBe(false); await wrapper.setProps({ filterText: "visible:false" }); expect(wrapper.find(option).exists()).toBe(true); }); it("should display 'delete' option only on non-deleted items", async () => { it("should display 'unhide' option when hidden and visible items are mixed", async () => { const option = '[data-description="unhide option"]'; expect(wrapper.find(option).exists()).toBe(false); await wrapper.setProps({ filterText: "visible:any" }); expect(wrapper.find(option).exists()).toBe(true); }); it("should display 'delete' option on non-deleted items", async () => { const option = '[data-description="delete option"]'; expect(wrapper.find(option).exists()).toBe(true); await wrapper.setProps({ filterText: "deleted:true" }); expect(wrapper.find(option).exists()).toBe(false); }); it("should display 'delete' option when non-deleted and deleted items are mixed", async () => { const option = '[data-description="delete option"]'; await wrapper.setProps({ filterText: "deleted:any" }); expect(wrapper.find(option).exists()).toBe(true); }); it("should display 'permanently delete' option always", async () => { const option = '[data-description="purge option"]'; expect(wrapper.find(option).exists()).toBe(true); Loading @@ -103,7 +116,7 @@ describe("History Selection Operations", () => { expect(wrapper.find(option).exists()).toBe(true); }); it("should display 'undelete' option only on deleted and non-purged items", async () => { it("should display 'undelete' option on deleted and non-purged items", async () => { const option = '[data-description="undelete option"]'; expect(wrapper.find(option).exists()).toBe(false); await wrapper.setProps({ Loading @@ -113,6 +126,15 @@ describe("History Selection Operations", () => { expect(wrapper.find(option).exists()).toBe(true); }); it("should display 'undelete' option when non-purged items (deleted or not) are mixed", async () => { const option = '[data-description="undelete option"]'; await wrapper.setProps({ filterText: "deleted:any", 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({ Loading @@ -134,6 +156,17 @@ describe("History Selection Operations", () => { expect(wrapper.find(option).exists()).toBe(true); }); it("should display 'undelete' option when is query selection mode and filtering by any deleted state", 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:any", contentSelection: getPurgedContentSelection(), isQuerySelection: true, }); expect(wrapper.find(option).exists()).toBe(true); }); it("should display collection building options only on visible and non-deleted items", async () => { const buildListOption = '[data-description="build list"]'; const buildPairOption = '[data-description="build pair"]'; Loading @@ -149,6 +182,14 @@ describe("History Selection Operations", () => { expect(wrapper.find(buildListOption).exists()).toBe(false); expect(wrapper.find(buildPairOption).exists()).toBe(false); expect(wrapper.find(buildListOfPairsOption).exists()).toBe(false); await wrapper.setProps({ filterText: "visible:any" }); expect(wrapper.find(buildListOption).exists()).toBe(false); expect(wrapper.find(buildPairOption).exists()).toBe(false); expect(wrapper.find(buildListOfPairsOption).exists()).toBe(false); await wrapper.setProps({ filterText: "deleted:any" }); expect(wrapper.find(buildListOption).exists()).toBe(false); expect(wrapper.find(buildPairOption).exists()).toBe(false); expect(wrapper.find(buildListOfPairsOption).exists()).toBe(false); }); it("should display list building option when all are selected", async () => { Loading client/src/components/History/CurrentHistory/HistoryOperations/SelectionOperations.vue +9 −2 Original line number Diff line number Diff line Loading @@ -25,7 +25,10 @@ data-description="undelete option"> <span v-localize>Undelete</span> </b-dropdown-item> <b-dropdown-item v-if="!showDeleted" v-b-modal:delete-selected-content data-description="delete option"> <b-dropdown-item v-if="!showStrictDeleted" v-b-modal:delete-selected-content data-description="delete option"> <span v-localize>Delete</span> </b-dropdown-item> <b-dropdown-item v-b-modal:purge-selected-content data-description="purge option"> Loading Loading @@ -193,10 +196,14 @@ export default { computed: { /** @returns {Boolean} */ showHidden() { return HistoryFilters.checkFilter(this.filterText, "visible", false); return !HistoryFilters.checkFilter(this.filterText, "visible", true); }, /** @returns {Boolean} */ showDeleted() { return !HistoryFilters.checkFilter(this.filterText, "deleted", false); }, /** @returns {Boolean} */ showStrictDeleted() { return HistoryFilters.checkFilter(this.filterText, "deleted", true); }, /** @returns {Boolean} */ Loading lib/galaxy/webapps/galaxy/services/history_contents.py +6 −2 Original line number Diff line number Diff line Loading @@ -1417,8 +1417,12 @@ class HistoryItemOperator: def _delete(self, item: HistoryItemModel, trans: ProvidesHistoryContext): if isinstance(item, HistoryDatasetCollectionAssociation): return self.dataset_collection_manager.delete(trans, "history", item.id, recursive=True, purge=False) return self.hda_manager.delete(item, flush=self.flush) self.dataset_collection_manager.delete(trans, "history", item.id, recursive=True, purge=False) else: self.hda_manager.delete(item, flush=self.flush) # In the edge case where all selected items are already deleted we need to force an update # otherwise the history will wait indefinitely for the items to be deleted item.update() def _undelete(self, item: HistoryItemModel): if getattr(item, "purged", False): Loading Loading
client/src/components/History/CurrentHistory/HistoryOperations/SelectionOperations.test.js +44 −3 Original line number Diff line number Diff line Loading @@ -82,20 +82,33 @@ describe("History Selection Operations", () => { expect(wrapper.find(option).exists()).toBe(false); }); it("should display 'unhide' option only on hidden items", async () => { it("should display 'unhide' option on hidden items", async () => { const option = '[data-description="unhide option"]'; expect(wrapper.find(option).exists()).toBe(false); await wrapper.setProps({ filterText: "visible:false" }); expect(wrapper.find(option).exists()).toBe(true); }); it("should display 'delete' option only on non-deleted items", async () => { it("should display 'unhide' option when hidden and visible items are mixed", async () => { const option = '[data-description="unhide option"]'; expect(wrapper.find(option).exists()).toBe(false); await wrapper.setProps({ filterText: "visible:any" }); expect(wrapper.find(option).exists()).toBe(true); }); it("should display 'delete' option on non-deleted items", async () => { const option = '[data-description="delete option"]'; expect(wrapper.find(option).exists()).toBe(true); await wrapper.setProps({ filterText: "deleted:true" }); expect(wrapper.find(option).exists()).toBe(false); }); it("should display 'delete' option when non-deleted and deleted items are mixed", async () => { const option = '[data-description="delete option"]'; await wrapper.setProps({ filterText: "deleted:any" }); expect(wrapper.find(option).exists()).toBe(true); }); it("should display 'permanently delete' option always", async () => { const option = '[data-description="purge option"]'; expect(wrapper.find(option).exists()).toBe(true); Loading @@ -103,7 +116,7 @@ describe("History Selection Operations", () => { expect(wrapper.find(option).exists()).toBe(true); }); it("should display 'undelete' option only on deleted and non-purged items", async () => { it("should display 'undelete' option on deleted and non-purged items", async () => { const option = '[data-description="undelete option"]'; expect(wrapper.find(option).exists()).toBe(false); await wrapper.setProps({ Loading @@ -113,6 +126,15 @@ describe("History Selection Operations", () => { expect(wrapper.find(option).exists()).toBe(true); }); it("should display 'undelete' option when non-purged items (deleted or not) are mixed", async () => { const option = '[data-description="undelete option"]'; await wrapper.setProps({ filterText: "deleted:any", 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({ Loading @@ -134,6 +156,17 @@ describe("History Selection Operations", () => { expect(wrapper.find(option).exists()).toBe(true); }); it("should display 'undelete' option when is query selection mode and filtering by any deleted state", 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:any", contentSelection: getPurgedContentSelection(), isQuerySelection: true, }); expect(wrapper.find(option).exists()).toBe(true); }); it("should display collection building options only on visible and non-deleted items", async () => { const buildListOption = '[data-description="build list"]'; const buildPairOption = '[data-description="build pair"]'; Loading @@ -149,6 +182,14 @@ describe("History Selection Operations", () => { expect(wrapper.find(buildListOption).exists()).toBe(false); expect(wrapper.find(buildPairOption).exists()).toBe(false); expect(wrapper.find(buildListOfPairsOption).exists()).toBe(false); await wrapper.setProps({ filterText: "visible:any" }); expect(wrapper.find(buildListOption).exists()).toBe(false); expect(wrapper.find(buildPairOption).exists()).toBe(false); expect(wrapper.find(buildListOfPairsOption).exists()).toBe(false); await wrapper.setProps({ filterText: "deleted:any" }); expect(wrapper.find(buildListOption).exists()).toBe(false); expect(wrapper.find(buildPairOption).exists()).toBe(false); expect(wrapper.find(buildListOfPairsOption).exists()).toBe(false); }); it("should display list building option when all are selected", async () => { Loading
client/src/components/History/CurrentHistory/HistoryOperations/SelectionOperations.vue +9 −2 Original line number Diff line number Diff line Loading @@ -25,7 +25,10 @@ data-description="undelete option"> <span v-localize>Undelete</span> </b-dropdown-item> <b-dropdown-item v-if="!showDeleted" v-b-modal:delete-selected-content data-description="delete option"> <b-dropdown-item v-if="!showStrictDeleted" v-b-modal:delete-selected-content data-description="delete option"> <span v-localize>Delete</span> </b-dropdown-item> <b-dropdown-item v-b-modal:purge-selected-content data-description="purge option"> Loading Loading @@ -193,10 +196,14 @@ export default { computed: { /** @returns {Boolean} */ showHidden() { return HistoryFilters.checkFilter(this.filterText, "visible", false); return !HistoryFilters.checkFilter(this.filterText, "visible", true); }, /** @returns {Boolean} */ showDeleted() { return !HistoryFilters.checkFilter(this.filterText, "deleted", false); }, /** @returns {Boolean} */ showStrictDeleted() { return HistoryFilters.checkFilter(this.filterText, "deleted", true); }, /** @returns {Boolean} */ Loading
lib/galaxy/webapps/galaxy/services/history_contents.py +6 −2 Original line number Diff line number Diff line Loading @@ -1417,8 +1417,12 @@ class HistoryItemOperator: def _delete(self, item: HistoryItemModel, trans: ProvidesHistoryContext): if isinstance(item, HistoryDatasetCollectionAssociation): return self.dataset_collection_manager.delete(trans, "history", item.id, recursive=True, purge=False) return self.hda_manager.delete(item, flush=self.flush) self.dataset_collection_manager.delete(trans, "history", item.id, recursive=True, purge=False) else: self.hda_manager.delete(item, flush=self.flush) # In the edge case where all selected items are already deleted we need to force an update # otherwise the history will wait indefinitely for the items to be deleted item.update() def _undelete(self, item: HistoryItemModel): if getattr(item, "purged", False): Loading