diff --git a/client/gulpfile.js b/client/gulpfile.js index 06d918958288..5338acac958a 100644 --- a/client/gulpfile.js +++ b/client/gulpfile.js @@ -43,6 +43,7 @@ const INSTALL_PLUGIN_BUILD_IDS = [ "phylocanvas", "plotly", "venn", + "vitessce", "vizarr", ]; // todo: derive from XML const DIST_PLUGIN_BUILD_IDS = ["new_user"]; diff --git a/client/src/components/WorkflowInvocationState/VegaWrapper.vue b/client/src/components/Common/VegaWrapper.vue similarity index 100% rename from client/src/components/WorkflowInvocationState/VegaWrapper.vue rename to client/src/components/Common/VegaWrapper.vue diff --git a/client/src/components/Markdown/Markdown.vue b/client/src/components/Markdown/Markdown.vue index 4d15b58b7e42..1115196098e4 100644 --- a/client/src/components/Markdown/Markdown.vue +++ b/client/src/components/Markdown/Markdown.vue @@ -1,3 +1,116 @@ + + - - diff --git a/client/src/components/Markdown/Elements/HistoryDatasetAsImage.vue b/client/src/components/Markdown/Sections/Elements/HistoryDatasetAsImage.vue similarity index 100% rename from client/src/components/Markdown/Elements/HistoryDatasetAsImage.vue rename to client/src/components/Markdown/Sections/Elements/HistoryDatasetAsImage.vue diff --git a/client/src/components/Markdown/Elements/HistoryDatasetAsTable.vue b/client/src/components/Markdown/Sections/Elements/HistoryDatasetAsTable.vue similarity index 100% rename from client/src/components/Markdown/Elements/HistoryDatasetAsTable.vue rename to client/src/components/Markdown/Sections/Elements/HistoryDatasetAsTable.vue diff --git a/client/src/components/Markdown/Elements/HistoryDatasetCollection/CollectionDisplay.vue b/client/src/components/Markdown/Sections/Elements/HistoryDatasetCollection/CollectionDisplay.vue similarity index 100% rename from client/src/components/Markdown/Elements/HistoryDatasetCollection/CollectionDisplay.vue rename to client/src/components/Markdown/Sections/Elements/HistoryDatasetCollection/CollectionDisplay.vue diff --git a/client/src/components/Markdown/Elements/HistoryDatasetCollection/CollectionTree.vue b/client/src/components/Markdown/Sections/Elements/HistoryDatasetCollection/CollectionTree.vue similarity index 100% rename from client/src/components/Markdown/Elements/HistoryDatasetCollection/CollectionTree.vue rename to client/src/components/Markdown/Sections/Elements/HistoryDatasetCollection/CollectionTree.vue diff --git a/client/src/components/Markdown/Elements/HistoryDatasetDetails.vue b/client/src/components/Markdown/Sections/Elements/HistoryDatasetDetails.vue similarity index 100% rename from client/src/components/Markdown/Elements/HistoryDatasetDetails.vue rename to client/src/components/Markdown/Sections/Elements/HistoryDatasetDetails.vue diff --git a/client/src/components/Markdown/Elements/HistoryDatasetDisplay.test.js b/client/src/components/Markdown/Sections/Elements/HistoryDatasetDisplay.test.js similarity index 100% rename from client/src/components/Markdown/Elements/HistoryDatasetDisplay.test.js rename to client/src/components/Markdown/Sections/Elements/HistoryDatasetDisplay.test.js diff --git a/client/src/components/Markdown/Elements/HistoryDatasetDisplay.vue b/client/src/components/Markdown/Sections/Elements/HistoryDatasetDisplay.vue similarity index 100% rename from client/src/components/Markdown/Elements/HistoryDatasetDisplay.vue rename to client/src/components/Markdown/Sections/Elements/HistoryDatasetDisplay.vue diff --git a/client/src/components/Markdown/Elements/HistoryDatasetIndex.vue b/client/src/components/Markdown/Sections/Elements/HistoryDatasetIndex.vue similarity index 100% rename from client/src/components/Markdown/Elements/HistoryDatasetIndex.vue rename to client/src/components/Markdown/Sections/Elements/HistoryDatasetIndex.vue diff --git a/client/src/components/Markdown/Elements/HistoryDatasetLink.vue b/client/src/components/Markdown/Sections/Elements/HistoryDatasetLink.vue similarity index 100% rename from client/src/components/Markdown/Elements/HistoryDatasetLink.vue rename to client/src/components/Markdown/Sections/Elements/HistoryDatasetLink.vue diff --git a/client/src/components/Markdown/Elements/HistoryLink.vue b/client/src/components/Markdown/Sections/Elements/HistoryLink.vue similarity index 100% rename from client/src/components/Markdown/Elements/HistoryLink.vue rename to client/src/components/Markdown/Sections/Elements/HistoryLink.vue diff --git a/client/src/components/Markdown/Elements/InstanceUrl.vue b/client/src/components/Markdown/Sections/Elements/InstanceUrl.vue similarity index 100% rename from client/src/components/Markdown/Elements/InstanceUrl.vue rename to client/src/components/Markdown/Sections/Elements/InstanceUrl.vue diff --git a/client/src/components/Markdown/Elements/InvocationTime.vue b/client/src/components/Markdown/Sections/Elements/InvocationTime.vue similarity index 100% rename from client/src/components/Markdown/Elements/InvocationTime.vue rename to client/src/components/Markdown/Sections/Elements/InvocationTime.vue diff --git a/client/src/components/Markdown/Elements/JobMetrics.vue b/client/src/components/Markdown/Sections/Elements/JobMetrics.vue similarity index 100% rename from client/src/components/Markdown/Elements/JobMetrics.vue rename to client/src/components/Markdown/Sections/Elements/JobMetrics.vue diff --git a/client/src/components/Markdown/Elements/JobParameters.vue b/client/src/components/Markdown/Sections/Elements/JobParameters.vue similarity index 100% rename from client/src/components/Markdown/Elements/JobParameters.vue rename to client/src/components/Markdown/Sections/Elements/JobParameters.vue diff --git a/client/src/components/Markdown/Elements/JobSelection.vue b/client/src/components/Markdown/Sections/Elements/JobSelection.vue similarity index 100% rename from client/src/components/Markdown/Elements/JobSelection.vue rename to client/src/components/Markdown/Sections/Elements/JobSelection.vue diff --git a/client/src/components/Markdown/Elements/ToolStd.vue b/client/src/components/Markdown/Sections/Elements/ToolStd.vue similarity index 100% rename from client/src/components/Markdown/Elements/ToolStd.vue rename to client/src/components/Markdown/Sections/Elements/ToolStd.vue diff --git a/client/src/components/Markdown/Elements/Visualization.vue b/client/src/components/Markdown/Sections/Elements/Visualization.vue similarity index 100% rename from client/src/components/Markdown/Elements/Visualization.vue rename to client/src/components/Markdown/Sections/Elements/Visualization.vue diff --git a/client/src/components/Markdown/Elements/Workflow/WorkflowDisplay.test.js b/client/src/components/Markdown/Sections/Elements/Workflow/WorkflowDisplay.test.js similarity index 100% rename from client/src/components/Markdown/Elements/Workflow/WorkflowDisplay.test.js rename to client/src/components/Markdown/Sections/Elements/Workflow/WorkflowDisplay.test.js diff --git a/client/src/components/Markdown/Elements/Workflow/WorkflowDisplay.vue b/client/src/components/Markdown/Sections/Elements/Workflow/WorkflowDisplay.vue similarity index 100% rename from client/src/components/Markdown/Elements/Workflow/WorkflowDisplay.vue rename to client/src/components/Markdown/Sections/Elements/Workflow/WorkflowDisplay.vue diff --git a/client/src/components/Markdown/Elements/Workflow/WorkflowImage.vue b/client/src/components/Markdown/Sections/Elements/Workflow/WorkflowImage.vue similarity index 100% rename from client/src/components/Markdown/Elements/Workflow/WorkflowImage.vue rename to client/src/components/Markdown/Sections/Elements/Workflow/WorkflowImage.vue diff --git a/client/src/components/Markdown/Elements/Workflow/WorkflowLicense.vue b/client/src/components/Markdown/Sections/Elements/Workflow/WorkflowLicense.vue similarity index 100% rename from client/src/components/Markdown/Elements/Workflow/WorkflowLicense.vue rename to client/src/components/Markdown/Sections/Elements/Workflow/WorkflowLicense.vue diff --git a/client/src/components/Markdown/Elements/Workflow/WorkflowTree.vue b/client/src/components/Markdown/Sections/Elements/Workflow/WorkflowTree.vue similarity index 100% rename from client/src/components/Markdown/Elements/Workflow/WorkflowTree.vue rename to client/src/components/Markdown/Sections/Elements/Workflow/WorkflowTree.vue diff --git a/client/src/components/Markdown/Elements/handlesMappingJobs.ts b/client/src/components/Markdown/Sections/Elements/handlesMappingJobs.ts similarity index 100% rename from client/src/components/Markdown/Elements/handlesMappingJobs.ts rename to client/src/components/Markdown/Sections/Elements/handlesMappingJobs.ts diff --git a/client/src/components/Markdown/Sections/MarkdownDefault.vue b/client/src/components/Markdown/Sections/MarkdownDefault.vue new file mode 100644 index 000000000000..2d3c81891741 --- /dev/null +++ b/client/src/components/Markdown/Sections/MarkdownDefault.vue @@ -0,0 +1,23 @@ + + + diff --git a/client/src/components/Markdown/MarkdownContainer.test.js b/client/src/components/Markdown/Sections/MarkdownGalaxy.test.js similarity index 98% rename from client/src/components/Markdown/MarkdownContainer.test.js rename to client/src/components/Markdown/Sections/MarkdownGalaxy.test.js index a40f1d810176..1a224dc7ab6f 100644 --- a/client/src/components/Markdown/MarkdownContainer.test.js +++ b/client/src/components/Markdown/Sections/MarkdownGalaxy.test.js @@ -5,7 +5,7 @@ import flushPromises from "flush-promises"; import { getLocalVue } from "tests/jest/helpers"; import { withPrefix } from "utils/redirect"; -import MountTarget from "./MarkdownContainer.vue"; +import MountTarget from "./MarkdownGalaxy.vue"; // mock routes jest.mock("utils/redirect"); diff --git a/client/src/components/Markdown/MarkdownContainer.vue b/client/src/components/Markdown/Sections/MarkdownGalaxy.vue similarity index 96% rename from client/src/components/Markdown/MarkdownContainer.vue rename to client/src/components/Markdown/Sections/MarkdownGalaxy.vue index 72f487deb26e..8d6da96eef49 100644 --- a/client/src/components/Markdown/MarkdownContainer.vue +++ b/client/src/components/Markdown/Sections/MarkdownGalaxy.vue @@ -2,6 +2,7 @@ import { computed, ref } from "vue"; import { useConfig } from "@/composables/config"; +import { getArgs } from "@/components/Markdown/parse"; import HistoryDatasetAsImage from "./Elements/HistoryDatasetAsImage.vue"; import HistoryDatasetAsTable from "./Elements/HistoryDatasetAsTable.vue"; @@ -25,14 +26,10 @@ const { config, isConfigLoaded } = useConfig(); const toggle = ref(false); const props = defineProps({ - name: { + content: { type: String, required: true, }, - args: { - type: Object, - required: true, - }, datasets: { type: Object, default: null, @@ -63,7 +60,11 @@ const props = defineProps({ }, }); -const isCollapsible = computed(() => props.args.collapse !== undefined); +const parsedArgs = computed(() => getArgs(props.content)); +const args = computed(() => parsedArgs.value.args); +const name = computed(() => parsedArgs.value.name); + +const isCollapsible = computed(() => args.value.collapse !== undefined); const isVisible = computed(() => !isCollapsible.value || toggle.value); function argToBoolean(args, name, booleanDefault) { diff --git a/client/src/components/Markdown/Sections/MarkdownVega.vue b/client/src/components/Markdown/Sections/MarkdownVega.vue new file mode 100644 index 000000000000..dbd55571e18a --- /dev/null +++ b/client/src/components/Markdown/Sections/MarkdownVega.vue @@ -0,0 +1,17 @@ + + + diff --git a/client/src/components/Markdown/Sections/MarkdownVitessce.vue b/client/src/components/Markdown/Sections/MarkdownVitessce.vue new file mode 100644 index 000000000000..4d79dc55ae6d --- /dev/null +++ b/client/src/components/Markdown/Sections/MarkdownVitessce.vue @@ -0,0 +1,20 @@ + + + diff --git a/client/src/components/Markdown/parse.test.js b/client/src/components/Markdown/parse.test.js index 50b1ae99397d..33e5673cc072 100644 --- a/client/src/components/Markdown/parse.test.js +++ b/client/src/components/Markdown/parse.test.js @@ -1,4 +1,4 @@ -import { getArgs, replaceLabel, splitMarkdown } from "./parse"; +import { getArgs, parseMarkdown, replaceLabel, splitMarkdown } from "./parse"; describe("parse.ts", () => { describe("getArgs", () => { @@ -20,6 +20,23 @@ describe("parse.ts", () => { }); }); + describe("parseSections", () => { + it("strip leading whitespace by default", () => { + const sections = parseMarkdown( + "```galaxy\njob_metrics(job_id=THISFAKEID)\n```\n DEFAULT_CONTENT \n```special\n SPECIAL_CONTENT \n```\n MORE_DEFAULT_CONTENT" + ); + expect(sections.length).toBe(4); + expect(sections[0].name).toBe("galaxy"); + expect(sections[0].content).toBe("job_metrics(job_id=THISFAKEID)"); + expect(sections[1].name).toBe("default"); + expect(sections[1].content).toBe("DEFAULT_CONTENT"); + expect(sections[2].name).toBe("special"); + expect(sections[2].content).toBe("SPECIAL_CONTENT"); + expect(sections[3].name).toBe("default"); + expect(sections[3].content).toBe("MORE_DEFAULT_CONTENT"); + }); + }); + describe("splitMarkdown", () => { it("strip leading whitespace by default", () => { const { sections } = splitMarkdown("\n```galaxy\njob_metrics(job_id=THISFAKEID)\n```"); diff --git a/client/src/components/Markdown/parse.ts b/client/src/components/Markdown/parse.ts index e001e1861a0d..58e664ada52f 100644 --- a/client/src/components/Markdown/parse.ts +++ b/client/src/components/Markdown/parse.ts @@ -13,6 +13,29 @@ type WorkflowLabelKind = "input" | "output" | "step"; const SINGLE_QUOTE = "'"; const DOUBLE_QUOTE = '"'; +export function parseMarkdown(input: string): { name: string; content: string }[] { + const result: { name: string; content: string }[] = []; + const lines = input.split("\n"); + let currentName: string = "default"; + let currentContent: string[] = []; + lines.forEach((line) => { + const sectionMatch = line.match(/^```(.*)$/); + if (sectionMatch) { + if (currentContent.length > 0) { + result.push({ name: currentName, content: currentContent.join("\n").trim() }); + } + currentName = sectionMatch[1] || "default"; + currentContent = []; + } else { + currentContent.push(line); + } + }); + if (currentContent.length > 0) { + result.push({ name: currentName, content: currentContent.join("\n").trim() }); + } + return result; +} + export function splitMarkdown(markdown: string, preserveWhitespace = false) { const sections: Section[] = []; const markdownErrors = []; diff --git a/client/src/components/Visualizations/VisualizationWrapper.vue b/client/src/components/Visualizations/VisualizationWrapper.vue new file mode 100644 index 000000000000..938d91123f79 --- /dev/null +++ b/client/src/components/Visualizations/VisualizationWrapper.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/client/src/components/WorkflowInvocationState/WorkflowInvocationMetrics.vue b/client/src/components/WorkflowInvocationState/WorkflowInvocationMetrics.vue index 91782651b709..db1c58667e5c 100644 --- a/client/src/components/WorkflowInvocationState/WorkflowInvocationMetrics.vue +++ b/client/src/components/WorkflowInvocationState/WorkflowInvocationMetrics.vue @@ -6,7 +6,7 @@ import { type ComputedRef } from "vue"; import { type components, GalaxyApi } from "@/api"; import { errorMessageAsString } from "@/utils/simple-error"; -const VegaWrapper = () => import("./VegaWrapper.vue"); +const VegaWrapper = () => import("@/components/Common/VegaWrapper.vue"); const props = defineProps({ invocationId: { diff --git a/config/plugins/visualizations/vitessce/config/vitessce.xml b/config/plugins/visualizations/vitessce/config/vitessce.xml new file mode 100644 index 000000000000..2c33e0102807 --- /dev/null +++ b/config/plugins/visualizations/vitessce/config/vitessce.xml @@ -0,0 +1,19 @@ + + + + Visual integration tool for exploration of spatial single cell experiments. + + + HistoryDatasetAssociation + json + dataset_id + + + + dataset_id + + + + + + \ No newline at end of file diff --git a/config/plugins/visualizations/vitessce/static/logo.png b/config/plugins/visualizations/vitessce/static/logo.png new file mode 100644 index 000000000000..79cebd6025f4 Binary files /dev/null and b/config/plugins/visualizations/vitessce/static/logo.png differ