From cf71db8586cc0894dc20de754c89220539e49643 Mon Sep 17 00:00:00 2001 From: Assunta DeSanto Date: Fri, 14 Oct 2022 13:20:53 -0400 Subject: [PATCH 01/12] using filter is:deleted to display deleted workflows --- lib/galaxy/managers/workflows.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/galaxy/managers/workflows.py b/lib/galaxy/managers/workflows.py index e98d12fc191..795ea44fa84 100644 --- a/lib/galaxy/managers/workflows.py +++ b/lib/galaxy/managers/workflows.py @@ -166,7 +166,6 @@ class WorkflowsManager(sharable.SharableModelManager, deletable.DeletableManager query = query.options(latest_workflow_load) query = query.filter(or_(*filters)) query = query.filter(model.StoredWorkflow.table.c.hidden == (true() if show_hidden else false())) - query = query.filter(model.StoredWorkflow.table.c.deleted == (true() if show_deleted else false())) if payload.search: search_query = payload.search parsed_search = parse_filters_structured(search_query, INDEX_SEARCH_FILTERS) @@ -194,6 +193,9 @@ class WorkflowsManager(sharable.SharableModelManager, deletable.DeletableManager elif key == "is": if q == "published": query = query.filter(model.StoredWorkflow.published == true()) + elif q == "deleted": + query = query.filter(model.StoredWorkflow.deleted == true()) + show_deleted = true elif q == "shared_with_me": if not show_shared: message = "Can only use tag is:shared_with_me if show_shared parameter also true." @@ -213,6 +215,7 @@ class WorkflowsManager(sharable.SharableModelManager, deletable.DeletableManager term, ) ) + query = query.filter(model.StoredWorkflow.table.c.deleted == (true() if show_deleted else false())) if include_total_count: total_matches = query.count() else: From 4ee7bfe9cf100742a2d6f5af1383bb797060f7c5 Mon Sep 17 00:00:00 2001 From: Assunta DeSanto Date: Tue, 18 Oct 2022 13:48:05 -0400 Subject: [PATCH 02/12] creating simple Vue test for restoring deleted WF --- .../src/components/Workflow/WorkflowDropdown.test.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/client/src/components/Workflow/WorkflowDropdown.test.js b/client/src/components/Workflow/WorkflowDropdown.test.js index e853721cd25..b787772a20b 100644 --- a/client/src/components/Workflow/WorkflowDropdown.test.js +++ b/client/src/components/Workflow/WorkflowDropdown.test.js @@ -112,6 +112,7 @@ describe("WorkflowDropdown.vue", () => { confirmRequest = true; global.confirm = jest.fn(() => confirmRequest); axiosMock.onDelete("/api/workflows/workflowid123").reply(202, "deleted..."); + axiosMock.onRestore("/api/workflows/workfrlowid123".reply(204, "restored...")); }); afterEach(() => { @@ -137,5 +138,15 @@ describe("WorkflowDropdown.vue", () => { expect(emitted["onRemove"]).toBeFalsy(); expect(emitted["onSuccess"]).toBeFalsy(); }); + + it("should restore previously deleted workflows", async () => { + await mountAndDelete(); + const emitted = wrapper.emitted(); + expect(emitted["onRemove"][0][0]).toEqual("workflowid123"); + expect(emitted["onSuccess"][0][0]).toEqual("deleted..."); + await wrapper.vm.onRestore(); + expect(emitted["onRestore"][0][0].toEqual("workflowid123")); + expect(emitted)["onRestore"].toEqual("restored..."); + }); }); }); From aa28e864ed2ac5c4e128ed614ab43f6aa6c6d9e3 Mon Sep 17 00:00:00 2001 From: Assunta DeSanto Date: Tue, 18 Oct 2022 13:48:26 -0400 Subject: [PATCH 03/12] passing disabled prop for Tags --- client/src/components/Common/Tags.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/src/components/Common/Tags.vue b/client/src/components/Common/Tags.vue index e6470d138d3..972fe3daee1 100644 --- a/client/src/components/Common/Tags.vue +++ b/client/src/components/Common/Tags.vue @@ -1,5 +1,5 @@ diff --git a/client/src/components/Workflow/WorkflowList.vue b/client/src/components/Workflow/WorkflowList.vue index 93e336382f2..833ca87b5ad 100644 --- a/client/src/components/Workflow/WorkflowList.vue +++ b/client/src/components/Workflow/WorkflowList.vue @@ -33,24 +33,37 @@ @onRemove="onRemove" @onUpdate="onUpdate" @onSuccess="onSuccess" - @onError="onError" /> + @onError="onError" + @onRestore="onRestore" /> From 2a0fecf8b119d09ed58ddeb54060c54cae9f4126 Mon Sep 17 00:00:00 2001 From: Assunta DeSanto Date: Tue, 18 Oct 2022 14:36:25 -0400 Subject: [PATCH 05/12] removing confirmation message for restoration --- .../components/Workflow/WorkflowDropdown.vue | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/client/src/components/Workflow/WorkflowDropdown.vue b/client/src/components/Workflow/WorkflowDropdown.vue index ca3c824b2f5..2f0bc8bdd5a 100644 --- a/client/src/components/Workflow/WorkflowDropdown.vue +++ b/client/src/components/Workflow/WorkflowDropdown.vue @@ -125,7 +125,7 @@ export default { readOnly() { return !!this.workflow.shared; }, - isDeleted(){ + isDeleted() { return this.workflow.deleted; }, sourceUrl() { @@ -216,19 +216,17 @@ export default { onRestore: function () { const id = this.workflow.id; const name = this.workflow.name; - const confirmationMessage = this.l(`Are you sure you want to restore workflow '${name}'?`); - if (window.confirm(confirmationMessage)) { - console.log (name + " is restored!") - // this.services - // .undeleteWorkflow(id) //what is function called on backend? - // .then((message) => { - // this.$emit("onRestore", id); - // this.$emit("onSuccess", message); - // }) - // .catch((error) => { - // this.$emit("onError", error); - // }); - } + + console.log(name + " is restored!"); + // this.services + // .undeleteWorkflow(id) //what is function called on backend? + // .then((message) => { + // this.$emit("onRestore", id); + // this.$emit("onSuccess", message); + // }) + // .catch((error) => { + // this.$emit("onError", error); + // }); }, }, }; From 902c69422157fa211a5959b0087bb2ef3738edde Mon Sep 17 00:00:00 2001 From: Assunta DeSanto Date: Mon, 24 Oct 2022 15:22:10 -0400 Subject: [PATCH 06/12] connecting to undelete endpoint --- .../components/Workflow/WorkflowDropdown.vue | 21 ++++++++----------- client/src/components/Workflow/services.js | 10 +++++++++ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/client/src/components/Workflow/WorkflowDropdown.vue b/client/src/components/Workflow/WorkflowDropdown.vue index 2f0bc8bdd5a..a33fc87838d 100644 --- a/client/src/components/Workflow/WorkflowDropdown.vue +++ b/client/src/components/Workflow/WorkflowDropdown.vue @@ -215,18 +215,15 @@ export default { }, onRestore: function () { const id = this.workflow.id; - const name = this.workflow.name; - - console.log(name + " is restored!"); - // this.services - // .undeleteWorkflow(id) //what is function called on backend? - // .then((message) => { - // this.$emit("onRestore", id); - // this.$emit("onSuccess", message); - // }) - // .catch((error) => { - // this.$emit("onError", error); - // }); + this.services + .undeleteWorkflow(id) + .then((message) => { + this.$emit("onRestore", id); + this.$emit("onSuccess", message); + }) + .catch((error) => { + this.$emit("onError", error); + }); }, }, }; diff --git a/client/src/components/Workflow/services.js b/client/src/components/Workflow/services.js index cf54aa1f76b..93a0833b8e1 100644 --- a/client/src/components/Workflow/services.js +++ b/client/src/components/Workflow/services.js @@ -37,6 +37,16 @@ export class Services { } } + async undeleteWorkflow(id) { + const url = safePath(`/api/workflows/${id}/undelete`); + try { + const response = await axios.post(url); + return response.data; + } catch (e) { + rethrowSimple(e); + } + } + async updateWorkflow(id, data) { const url = safePath(`/api/workflows/${id}`); try { From 82059d27a03532f652de963d5070890cc66b6f73 Mon Sep 17 00:00:00 2001 From: Assunta DeSanto Date: Mon, 24 Oct 2022 15:22:28 -0400 Subject: [PATCH 07/12] fixing test after connecting to endpoint --- client/src/components/Workflow/WorkflowDropdown.test.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/components/Workflow/WorkflowDropdown.test.js b/client/src/components/Workflow/WorkflowDropdown.test.js index b787772a20b..5a440fb133d 100644 --- a/client/src/components/Workflow/WorkflowDropdown.test.js +++ b/client/src/components/Workflow/WorkflowDropdown.test.js @@ -112,7 +112,7 @@ describe("WorkflowDropdown.vue", () => { confirmRequest = true; global.confirm = jest.fn(() => confirmRequest); axiosMock.onDelete("/api/workflows/workflowid123").reply(202, "deleted..."); - axiosMock.onRestore("/api/workflows/workfrlowid123".reply(204, "restored...")); + axiosMock.onPost("/api/workflows/workflowid123/undelete").reply(204, "restored..."); }); afterEach(() => { @@ -145,8 +145,9 @@ describe("WorkflowDropdown.vue", () => { expect(emitted["onRemove"][0][0]).toEqual("workflowid123"); expect(emitted["onSuccess"][0][0]).toEqual("deleted..."); await wrapper.vm.onRestore(); - expect(emitted["onRestore"][0][0].toEqual("workflowid123")); - expect(emitted)["onRestore"].toEqual("restored..."); + await flushPromises(); + expect(emitted["onRestore"][0][0]).toEqual("workflowid123"); + expect(emitted["onSuccess"][1][0]).toEqual("restored..."); }); }); }); From 8c07195b5e8c46b78505db7f0cc0e6cb9cb53db6 Mon Sep 17 00:00:00 2001 From: Martin Cech Date: Mon, 24 Oct 2022 19:25:33 -0700 Subject: [PATCH 08/12] update the search help box with new filtering option --- .../src/components/Workflow/WorkflowList.vue | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/client/src/components/Workflow/WorkflowList.vue b/client/src/components/Workflow/WorkflowList.vue index 833ca87b5ad..ae95cc4d8b5 100644 --- a/client/src/components/Workflow/WorkflowList.vue +++ b/client/src/components/Workflow/WorkflowList.vue @@ -93,25 +93,27 @@ import SharingIndicators from "components/Indices/SharingIndicators"; const helpHtml = `

This textbox box can be used to filter the workflows displayed. -

Text entered here will be searched against workflow names and tags. Additionally, advanced -filtering tags can be used to refine the search more precisely. Tags are of the form +

Text entered here will be searched against workflow names and workflow tags. Additionally, advanced +filtering tags can be used to refine the search more precisely. Filtering tags are of the form <tag_name>:<tag_value> or <tag_name>:'<tag_value>'. For instance to search just for RNAseq in the workflow name, name:rnsseq can be used. Notice by default the search is not case-sensitive. -If the quoted version of tag is used, the search is not case sensitive and only full matches will be +If the quoted version of tag is used, the search is case sensitive and only full matches will be returned. So name:'RNAseq' would show only workflows named exactly RNAseq. -

The available tags are: +

The available filtering tags are:

name
-
This filters only against the workflow name.
+
Shows workflows with given sequence of characters in their names.
tag
-
This filters only against the workflow tag. You may also just click on a tag in your list of workflows to filter on that tag using this directly.
+
Shows workflows with the given workflow tag. You may also just click on a tag in your list of workflows to filter on that tag directly.
is:published
-
This filters the workflows such that only published workflows are shown. You may also just click on the "published" icon of a workflow in your list to filter on this directly.
+
Shows published workflows. You may also just click on the "published" icon of a workflow in your list to filter on this directly.
is:shared
-
This filters the workflows such that only workflows shared from another user directly with you are are shown. You may also just click on the "shared with me" icon of a workflow in your list to filter on this directly.
+
Shows workflows shared by another user directly with you. You may also just click on the "shared with me" icon of a workflow in your list to filter on this directly.
+
is:deleted
+
Shows deleted workflows.
`; From e16a1a969c3b783098c5510ecbb96af1d34de8a0 Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Tue, 25 Oct 2022 15:05:12 -0400 Subject: [PATCH 09/12] Drop confirmation on delete since it's easily revertible now. --- .../components/Workflow/WorkflowDropdown.vue | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/client/src/components/Workflow/WorkflowDropdown.vue b/client/src/components/Workflow/WorkflowDropdown.vue index a33fc87838d..19f5835321d 100644 --- a/client/src/components/Workflow/WorkflowDropdown.vue +++ b/client/src/components/Workflow/WorkflowDropdown.vue @@ -182,19 +182,15 @@ export default { }, onDelete: function () { const id = this.workflow.id; - const name = this.workflow.name; - const confirmationMessage = this.l(`Are you sure you want to delete workflow '${name}'?`); - if (window.confirm(confirmationMessage)) { - this.services - .deleteWorkflow(id) - .then((message) => { - this.$emit("onRemove", id); - this.$emit("onSuccess", message); - }) - .catch((error) => { - this.$emit("onError", error); - }); - } + this.services + .deleteWorkflow(id) + .then((message) => { + this.$emit("onRemove", id); + this.$emit("onSuccess", message); + }) + .catch((error) => { + this.$emit("onError", error); + }); }, onRename: function () { const id = this.workflow.id; From 4afaa5abbe9569c641e542b42559cfa723560dc4 Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Tue, 25 Oct 2022 15:11:24 -0400 Subject: [PATCH 10/12] Remove jest testing of workflow deletion confirmation (since we don't confirm anymore) --- .../Workflow/WorkflowDropdown.test.js | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/client/src/components/Workflow/WorkflowDropdown.test.js b/client/src/components/Workflow/WorkflowDropdown.test.js index 5a440fb133d..e9ba6b88bab 100644 --- a/client/src/components/Workflow/WorkflowDropdown.test.js +++ b/client/src/components/Workflow/WorkflowDropdown.test.js @@ -93,7 +93,6 @@ describe("WorkflowDropdown.vue", () => { describe("workflow clicking workflow deletion", () => { let axiosMock; - let confirmRequest; async function mountAndDelete() { const workflow = { @@ -109,8 +108,6 @@ describe("WorkflowDropdown.vue", () => { beforeEach(async () => { axiosMock = new MockAdapter(axios); - confirmRequest = true; - global.confirm = jest.fn(() => confirmRequest); axiosMock.onDelete("/api/workflows/workflowid123").reply(202, "deleted..."); axiosMock.onPost("/api/workflows/workflowid123/undelete").reply(204, "restored..."); }); @@ -119,26 +116,13 @@ describe("WorkflowDropdown.vue", () => { axiosMock.restore(); }); - it("should confirm with localized deletion message", async () => { - await mountAndDelete(); - expect(global.confirm).toHaveBeenCalledWith(expect.toBeLocalized()); - }); - - it("should fire deletion API request upon confirmation", async () => { + it("should fire deletion API request upon remove action", async () => { await mountAndDelete(); const emitted = wrapper.emitted(); expect(emitted["onRemove"][0][0]).toEqual("workflowid123"); expect(emitted["onSuccess"][0][0]).toEqual("deleted..."); }); - it("should not fire deletion API request if not confirmed", async () => { - confirmRequest = false; - await mountAndDelete(); - const emitted = wrapper.emitted(); - expect(emitted["onRemove"]).toBeFalsy(); - expect(emitted["onSuccess"]).toBeFalsy(); - }); - it("should restore previously deleted workflows", async () => { await mountAndDelete(); const emitted = wrapper.emitted(); From f0383341a8e505718657462e723d31f9871b9eac Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Tue, 25 Oct 2022 15:15:19 -0400 Subject: [PATCH 11/12] Fix html in helpHtml (missing tags mainly) --- .../src/components/Workflow/WorkflowList.vue | 69 ++++++++++++------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/client/src/components/Workflow/WorkflowList.vue b/client/src/components/Workflow/WorkflowList.vue index ae95cc4d8b5..306a33abbb9 100644 --- a/client/src/components/Workflow/WorkflowList.vue +++ b/client/src/components/Workflow/WorkflowList.vue @@ -40,9 +40,9 @@ + @tag-click="onTagClick" />