From 54a927af7c1806a1bf91f75f89ed8ae718045067 Mon Sep 17 00:00:00 2001 From: guerler Date: Mon, 19 Apr 2021 12:51:52 -0400 Subject: [PATCH 01/10] Add new element to pages, allow history import --- .../Markdown/Elements/HistoryImport.vue | 17 +++++++++++ client/src/components/Markdown/Markdown.vue | 3 ++ .../components/Markdown/MarkdownDialog.vue | 19 ++++++++++++ .../components/Markdown/MarkdownToolBox.vue | 30 ++++++++++++++----- lib/galaxy/managers/markdown_parse.py | 1 + lib/galaxy/managers/markdown_util.py | 19 ++++++++++-- 6 files changed, 78 insertions(+), 11 deletions(-) create mode 100644 client/src/components/Markdown/Elements/HistoryImport.vue diff --git a/client/src/components/Markdown/Elements/HistoryImport.vue b/client/src/components/Markdown/Elements/HistoryImport.vue new file mode 100644 index 00000000000..b7a1cd457d7 --- /dev/null +++ b/client/src/components/Markdown/Elements/HistoryImport.vue @@ -0,0 +1,17 @@ + + + diff --git a/client/src/components/Markdown/Markdown.vue b/client/src/components/Markdown/Markdown.vue index 7f69d806748..ef8a84bca12 100644 --- a/client/src/components/Markdown/Markdown.vue +++ b/client/src/components/Markdown/Markdown.vue @@ -44,6 +44,7 @@
{{ getTime }}
+ @@ -105,6 +106,7 @@ import HistoryDatasetLink from "./Elements/HistoryDatasetLink"; import HistoryDatasetIndex from "./Elements/HistoryDatasetIndex"; import HistoryDatasetCollectionDisplay from "./Elements/HistoryDatasetCollection/CollectionDisplay"; import HistoryDatasetDetails from "./Elements/HistoryDatasetDetails"; +import HistoryImport from "./Elements/HistoryImport"; import InvocationTime from "./Elements/InvocationTime"; import JobMetrics from "./Elements/JobMetrics"; import JobParameters from "./Elements/JobParameters"; @@ -137,6 +139,7 @@ export default { HistoryDatasetDisplay, HistoryDatasetIndex, HistoryDatasetLink, + HistoryImport, JobMetrics, JobParameters, LoadingSpan, diff --git a/client/src/components/Markdown/MarkdownDialog.vue b/client/src/components/Markdown/MarkdownDialog.vue index ebc68a614be..5028d0b48fa 100644 --- a/client/src/components/Markdown/MarkdownDialog.vue +++ b/client/src/components/Markdown/MarkdownDialog.vue @@ -54,6 +54,14 @@ @onOk="onWorkflow" @onCancel="onCancel" /> + @@ -120,9 +128,11 @@ export default { jobsUrl: `${getAppRoot()}api/jobs`, workflowsUrl: `${getAppRoot()}api/workflows`, invocationsUrl: `${getAppRoot()}api/invocations`, + historiesUrl: `${getAppRoot()}api/histories?view=detailed&q=published&qv=True`, selectedShow: false, visualizationShow: false, workflowShow: false, + historyShow: false, jobShow: false, invocationShow: false, dataShow: false, @@ -148,6 +158,9 @@ export default { getWorkflows() { return axios.get(this.workflowsUrl); }, + getHistories() { + return axios.get(this.historiesUrl); + }, onData(response) { this.dataShow = false; this.$emit("onInsert", `${this.argumentName}(history_dataset_id=${response})`); @@ -164,6 +177,10 @@ export default { this.invocationShow = false; this.$emit("onInsert", `${this.argumentName}(invocation_id=${response.id})`); }, + onHistory(response) { + this.historyShow = false; + this.$emit("onInsert", `history_import(history_id=${response.id})`); + }, onWorkflow(response) { this.workflowShow = false; this.$emit("onInsert", `workflow_display(workflow_id=${response.id})`); @@ -175,6 +192,8 @@ export default { onCreate() { if (this.argumentType == "workflow_id") { this.workflowShow = true; + } else if (this.argumentType == "history_id") { + this.historyShow = true; } else if (this.argumentType == "history_dataset_id") { if (this.useLabels) { this.selectedShow = true; diff --git a/client/src/components/Markdown/MarkdownToolBox.vue b/client/src/components/Markdown/MarkdownToolBox.vue index 5019acd9bcf..df1c78013c2 100644 --- a/client/src/components/Markdown/MarkdownToolBox.vue +++ b/client/src/components/Markdown/MarkdownToolBox.vue @@ -69,6 +69,7 @@ export default { selectedType: null, selectedLabels: null, selectedShow: false, + selectedPayload: null, visualizationIndex: {}, error: null, historySection: { @@ -78,7 +79,7 @@ export default { { id: "history_dataset_display", name: "Dataset", - emitter: "onHistoryId", + emitter: "onHistoryDatasetId", }, { id: "history_dataset_collection_display", @@ -88,41 +89,46 @@ export default { { id: "history_dataset_as_image", name: "Image", - emitter: "onHistoryId", + emitter: "onHistoryDatasetId", }, { id: "history_dataset_index", name: "Dataset Index", - emitter: "onHistoryId", + emitter: "onHistoryDatasetId", }, { id: "history_dataset_embedded", name: "Embedded Dataset", - emitter: "onHistoryId", + emitter: "onHistoryDatasetId", }, { id: "history_dataset_type", name: "Dataset Type", - emitter: "onHistoryId", + emitter: "onHistoryDatasetId", }, { id: "history_dataset_link", name: "Link to Dataset", - emitter: "onHistoryId", + emitter: "onHistoryDatasetId", }, { id: "history_dataset_name", name: "Name of Dataset", - emitter: "onHistoryId", + emitter: "onHistoryDatasetId", }, { id: "history_dataset_peek", name: "Peek into Dataset", - emitter: "onHistoryId", + emitter: "onHistoryDatasetId", }, { id: "history_dataset_info", name: "Dataset Details", + emitter: "onHistoryDatasetId", + }, + { + id: "history_import", + name: "Link to Import", emitter: "onHistoryId", }, ], @@ -264,6 +270,9 @@ export default { }, onClick(item) { switch (item.emitter) { + case "onHistoryDatasetId": + this.onHistoryDatasetId(item.id); + break; case "onHistoryId": this.onHistoryId(item.id); break; @@ -304,6 +313,11 @@ export default { this.selectedShow = true; }, onHistoryId(argumentName) { + this.selectedArgumentName = argumentName; + this.selectedType = "history_id"; + this.selectedShow = true; + }, + onHistoryDatasetId(argumentName) { this.selectedArgumentName = argumentName; this.selectedType = "history_dataset_id"; this.selectedLabels = this.getOutputs(); diff --git a/lib/galaxy/managers/markdown_parse.py b/lib/galaxy/managers/markdown_parse.py index 19e7559d604..3c6702c4388 100644 --- a/lib/galaxy/managers/markdown_parse.py +++ b/lib/galaxy/managers/markdown_parse.py @@ -15,6 +15,7 @@ GALAXY_FLAVORED_MARKDOWN_CONTAINER_LINE_PATTERN = re.compile( VALID_CONTAINER_END_PATTERN = re.compile(r"^```\s*$") DYNAMIC_ARGUMENTS = object() VALID_ARGUMENTS = { + "history_import": ["history_id"], "history_dataset_display": ["input", "output", "history_dataset_id"], "history_dataset_embedded": ["input", "output", "history_dataset_id"], "history_dataset_as_image": ["input", "output", "history_dataset_id", "path"], diff --git a/lib/galaxy/managers/markdown_util.py b/lib/galaxy/managers/markdown_util.py index 5ccb5f28e37..c2afe7f1550 100644 --- a/lib/galaxy/managers/markdown_util.py +++ b/lib/galaxy/managers/markdown_util.py @@ -36,6 +36,7 @@ from galaxy.managers.jobs import ( summarize_job_metrics, summarize_job_parameters, ) +from galaxy.managers.histories import HistoryManager from galaxy.model.item_attrs import get_item_annotation_str from galaxy.model.orm.now import now from galaxy.util.sanitize_html import sanitize_html @@ -49,8 +50,8 @@ INPUT_LABEL_PATTERN = re.compile(r'input=\s*%s\s*' % ARG_VAL_CAPTURED_REGEX) STEP_LABEL_PATTERN = re.compile(r'step=\s*%s\s*' % ARG_VAL_CAPTURED_REGEX) PATH_LABEL_PATTERN = re.compile(r'path=\s*%s\s*' % ARG_VAL_CAPTURED_REGEX) # STEP_OUTPUT_LABEL_PATTERN = re.compile(r'step_output=([\w_\-]+)/([\w_\-]+)') -UNENCODED_ID_PATTERN = re.compile(r'(workflow_id|history_dataset_id|history_dataset_collection_id|job_id|invocation_id)=([\d]+)') -ENCODED_ID_PATTERN = re.compile(r'(workflow_id|history_dataset_id|history_dataset_collection_id|job_id|invocation_id)=([a-z0-9]+)') +UNENCODED_ID_PATTERN = re.compile(r'(history_id|workflow_id|history_dataset_id|history_dataset_collection_id|job_id|invocation_id)=([\d]+)') +ENCODED_ID_PATTERN = re.compile(r'(history_id|workflow_id|history_dataset_id|history_dataset_collection_id|job_id|invocation_id)=([a-z0-9]+)') INVOCATION_SECTION_MARKDOWN_CONTAINER_LINE_PATTERN = re.compile( r"```\s*galaxy\s*" ) @@ -80,6 +81,7 @@ class GalaxyInternalMarkdownDirectiveHandler(metaclass=abc.ABCMeta): def walk(self, trans, internal_galaxy_markdown): hda_manager = trans.app.hda_manager + history_manager = trans.app.history_manager workflow_manager = trans.app.workflow_manager job_manager = JobManager(trans.app) collection_manager = trans.app.dataset_collections_service @@ -96,7 +98,11 @@ class GalaxyInternalMarkdownDirectiveHandler(metaclass=abc.ABCMeta): object_id = int(id_match.group(2)) encoded_id = trans.security.encode_id(object_id) line = line.replace(id_match.group(), "{}={}".format(id_match.group(1), encoded_id)) - if container == "history_dataset_display": + if container == "history_import": + _check_object(object_id, line) + history = history_manager.get_accessible(object_id, trans.user) + rval = self.handle_history_import(line, history) + elif container == "history_dataset_display": _check_object(object_id, line) hda = hda_manager.get_accessible(object_id, trans.user) rval = self.handle_dataset_display(line, hda) @@ -176,6 +182,10 @@ class GalaxyInternalMarkdownDirectiveHandler(metaclass=abc.ABCMeta): export_markdown = _remap_galaxy_markdown_calls(_remap_container, internal_galaxy_markdown) return export_markdown + @abc.abstractmethod + def handle_history_import(self, line, history): + pass + @abc.abstractmethod def handle_dataset_display(self, line, hda): pass @@ -292,6 +302,9 @@ class ReadyForExportMarkdownDirectiveHandler(GalaxyInternalMarkdownDirectiveHand # from the encoded ID. Don't implement a default on the base class though because # it is good to force both Client and PDF/HTML export to deal with each new directive # explicitly. + def handle_history_import(self, line, history): + pass + def handle_dataset_as_image(self, line, hda): pass From 2208de874aaebbd855886984656acbe9412ab061 Mon Sep 17 00:00:00 2001 From: guerler Date: Mon, 19 Apr 2021 13:46:45 -0400 Subject: [PATCH 02/10] Parse history name to page client, post import request to histories api --- .../Markdown/Elements/HistoryImport.vue | 51 +++++++++++++++++-- client/src/components/Markdown/Markdown.vue | 4 +- lib/galaxy/managers/markdown_util.py | 6 +-- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/client/src/components/Markdown/Elements/HistoryImport.vue b/client/src/components/Markdown/Elements/HistoryImport.vue index b7a1cd457d7..868e21b91cf 100644 --- a/client/src/components/Markdown/Elements/HistoryImport.vue +++ b/client/src/components/Markdown/Elements/HistoryImport.vue @@ -1,17 +1,62 @@ diff --git a/client/src/components/Markdown/Markdown.vue b/client/src/components/Markdown/Markdown.vue index ef8a84bca12..754ebe28b74 100644 --- a/client/src/components/Markdown/Markdown.vue +++ b/client/src/components/Markdown/Markdown.vue @@ -44,7 +44,7 @@
{{ getTime }}
- + @@ -168,6 +168,7 @@ export default { markdownObjects: [], markdownErrors: [], historyDatasets: {}, + histories: {}, historyDatasetCollections: {}, workflows: {}, jobs: {}, @@ -204,6 +205,7 @@ export default { this.markdownErrors = config.errors || []; this.markdownObjects = this.splitMarkdown(markdown); this.historyDatasets = config.history_datasets || {}; + this.histories = config.histories || {}; this.historyDatasetCollections = config.history_dataset_collections || {}; this.workflows = config.workflows || {}; this.jobs = config.jobs || {}; diff --git a/lib/galaxy/managers/markdown_util.py b/lib/galaxy/managers/markdown_util.py index c2afe7f1550..18f14a43159 100644 --- a/lib/galaxy/managers/markdown_util.py +++ b/lib/galaxy/managers/markdown_util.py @@ -298,13 +298,13 @@ class ReadyForExportMarkdownDirectiveHandler(GalaxyInternalMarkdownDirectiveHand def handle_tool_stderr(self, line, job): self.ensure_rendering_data_for("jobs", job)["tool_stderr"] = job.tool_stderr or "*No Standard Error Available*" + def handle_history_import(self, line, history): + self.ensure_rendering_data_for("histories", history)["name"] = history.name + # Following three cases - the client side widgets have everything they need # from the encoded ID. Don't implement a default on the base class though because # it is good to force both Client and PDF/HTML export to deal with each new directive # explicitly. - def handle_history_import(self, line, history): - pass - def handle_dataset_as_image(self, line, hda): pass From b29cd4e824268b72012694fdc6353bbeac78ce2e Mon Sep 17 00:00:00 2001 From: guerler Date: Mon, 19 Apr 2021 13:52:56 -0400 Subject: [PATCH 03/10] Remove unused import --- lib/galaxy/managers/markdown_util.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/galaxy/managers/markdown_util.py b/lib/galaxy/managers/markdown_util.py index 18f14a43159..498ceb9e628 100644 --- a/lib/galaxy/managers/markdown_util.py +++ b/lib/galaxy/managers/markdown_util.py @@ -36,7 +36,6 @@ from galaxy.managers.jobs import ( summarize_job_metrics, summarize_job_parameters, ) -from galaxy.managers.histories import HistoryManager from galaxy.model.item_attrs import get_item_annotation_str from galaxy.model.orm.now import now from galaxy.util.sanitize_html import sanitize_html From f00479e8471a1ec7d80a02c38070f47599c0adc5 Mon Sep 17 00:00:00 2001 From: guerler Date: Mon, 19 Apr 2021 14:06:43 -0400 Subject: [PATCH 04/10] Add error details to output message if importing history fails. --- .../src/components/Markdown/Elements/HistoryImport.vue | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/client/src/components/Markdown/Elements/HistoryImport.vue b/client/src/components/Markdown/Elements/HistoryImport.vue index 868e21b91cf..2dae9780de5 100644 --- a/client/src/components/Markdown/Elements/HistoryImport.vue +++ b/client/src/components/Markdown/Elements/HistoryImport.vue @@ -5,9 +5,10 @@ Successfully Imported History! - + Failed to Import History! + {{ error }} @@ -18,6 +19,7 @@ import { getAppRoot } from "onload/loadConfig"; import Vue from "vue"; import BootstrapVue from "bootstrap-vue"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; +import { errorMessageAsString } from "utils/simple-error"; Vue.use(BootstrapVue); @@ -38,7 +40,7 @@ export default { data() { return { imported: false, - failed: false, + error: false, }; }, computed: { @@ -50,11 +52,11 @@ export default { onClick() { axios .post(`${getAppRoot()}api/histories`, { history_id: this.args.history_id }) - .then(({ data }) => { + .then(() => { this.imported = true; }) .catch((e) => { - this.failed = true; + this.error = errorMessageAsString(e); }); }, }, From 452b61f2044b9e5d665e380ad016fd552cdc6276 Mon Sep 17 00:00:00 2001 From: guerler Date: Mon, 19 Apr 2021 14:19:24 -0400 Subject: [PATCH 05/10] Use new line to show import message --- .../src/components/Markdown/Elements/HistoryImport.vue | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/components/Markdown/Elements/HistoryImport.vue b/client/src/components/Markdown/Elements/HistoryImport.vue index 2dae9780de5..b9d4cb1b5aa 100644 --- a/client/src/components/Markdown/Elements/HistoryImport.vue +++ b/client/src/components/Markdown/Elements/HistoryImport.vue @@ -1,15 +1,15 @@ From 1abdead26905c6e37c394bdd5fda5124ac385276 Mon Sep 17 00:00:00 2001 From: guerler Date: Mon, 19 Apr 2021 14:21:49 -0400 Subject: [PATCH 06/10] Hide import link with resulting import message --- .../src/components/Markdown/Elements/HistoryImport.vue | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/client/src/components/Markdown/Elements/HistoryImport.vue b/client/src/components/Markdown/Elements/HistoryImport.vue index b9d4cb1b5aa..6974fb7cea1 100644 --- a/client/src/components/Markdown/Elements/HistoryImport.vue +++ b/client/src/components/Markdown/Elements/HistoryImport.vue @@ -1,13 +1,13 @@