Skip to content

Commit

Permalink
Implement instance URLs in Galaxy markdown.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmchilton committed Sep 12, 2023
1 parent 3c60283 commit 8ff3702
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 5 deletions.
31 changes: 31 additions & 0 deletions client/src/components/Markdown/Elements/InstanceUrl.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script setup lang="ts">
import { computed } from "vue";
import ExternalLink from "@/components/ExternalLink.vue";
import LoadingSpan from "@/components/LoadingSpan.vue";
interface InstanceUrlProps {
href?: string;
title?: string;
loading: boolean;
}
const props = withDefaults(defineProps<InstanceUrlProps>(), {
href: null,
title: null,
});
const effectiveTitle = computed(() => {
return props.title ? props.title : props.href;
});
</script>

<template>
<p>
<LoadingSpan v-if="props.loading" message="Loading instance configuration"> </LoadingSpan>
<ExternalLink v-else-if="props.href" :href="props.href">
{{ effectiveTitle }}
</ExternalLink>
<i v-else> Configuration value unset, please contact Galaxy admin. </i>
</p>
</template>
7 changes: 7 additions & 0 deletions client/src/components/Markdown/MarkdownContainer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ import MountTarget from "./MarkdownContainer.vue";
jest.mock("utils/redirect");
withPrefix.mockImplementation((url) => url);

jest.mock("@/composables/config", () => ({
useConfig: jest.fn(() => ({
config: {},
isConfigLoaded: true,
})),
}));

const localVue = getLocalVue();
const axiosMock = new MockAdapter(axios);

Expand Down
38 changes: 38 additions & 0 deletions client/src/components/Markdown/MarkdownContainer.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
<script setup>
import { computed, ref } from "vue";
import { useConfig } from "@/composables/config";
import HistoryDatasetAsImage from "./Elements/HistoryDatasetAsImage.vue";
import HistoryDatasetCollectionDisplay from "./Elements/HistoryDatasetCollection/CollectionDisplay.vue";
import HistoryDatasetDetails from "./Elements/HistoryDatasetDetails.vue";
import HistoryDatasetDisplay from "./Elements/HistoryDatasetDisplay.vue";
import HistoryDatasetIndex from "./Elements/HistoryDatasetIndex.vue";
import HistoryDatasetLink from "./Elements/HistoryDatasetLink.vue";
import HistoryLink from "./Elements/HistoryLink.vue";
import InstanceUrl from "./Elements/InstanceUrl.vue";
import InvocationTime from "./Elements/InvocationTime.vue";
import JobMetrics from "./Elements/JobMetrics.vue";
import JobParameters from "./Elements/JobParameters.vue";
import ToolStd from "./Elements/ToolStd.vue";
import Visualization from "./Elements/Visualization.vue";
import WorkflowDisplay from "./Elements/Workflow/WorkflowDisplay.vue";
const { config, isConfigLoaded } = useConfig();
const toggle = ref(false);
const props = defineProps({
name: {
Expand Down Expand Up @@ -75,6 +80,39 @@ const isVisible = computed(() => !isCollapsible.value || toggle.value);
<div v-else-if="name == 'generate_time'" class="galaxy-time">
<pre><code>{{ time }}</code></pre>
</div>
<InstanceUrl
v-else-if="name == 'instance_citation_link'"
:href="config.citation_url"
:loading="!isConfigLoaded">
</InstanceUrl>
<InstanceUrl v-else-if="name == 'instance_terms_link'" :href="config.terms_url" :loading="!isConfigLoaded">
</InstanceUrl>
<InstanceUrl
v-else-if="name == 'instance_support_link'"
:href="config.support_url"
:loading="!isConfigLoaded">
</InstanceUrl>
<InstanceUrl
v-else-if="name == 'instance_help_link'"
:href="config.helpsite_url"
:loading="!isConfigLoaded">
</InstanceUrl>
<InstanceUrl
v-else-if="name == 'instance_resources_link'"
:href="config.instance_resource_url"
:loading="!isConfigLoaded">
</InstanceUrl>
<InstanceUrl
v-else-if="name == 'instance_access_link'"
:href="config.instance_access_url"
:loading="!isConfigLoaded">
</InstanceUrl>
<InstanceUrl
v-else-if="name == 'instance_organization_link'"
:href="config.ga4gh_service_organization_url"
:title="config.ga4gh_service_organization_name"
:loading="!isConfigLoaded">
</InstanceUrl>
<HistoryLink v-else-if="name == 'history_link'" :args="args" :histories="histories" />
<HistoryDatasetAsImage v-else-if="name == 'history_dataset_as_image'" :args="args" />
<HistoryDatasetLink v-else-if="name == 'history_dataset_link'" :args="args" />
Expand Down
43 changes: 43 additions & 0 deletions client/src/components/Markdown/MarkdownToolBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
:expanded="true"
@onClick="onClick" />
<ToolSection v-else :category="workflowSection" :expanded="true" @onClick="onClick" />
<ToolSection :category="linksSection" :expanded="false" @onClick="onClick" />
<ToolSection :category="otherSection" :expanded="true" @onClick="onClick" />
<ToolSection
v-if="hasVisualizations"
Expand Down Expand Up @@ -232,6 +233,48 @@ export default {
},
],
},
linksSection: {
title: "Galaxy Instance Links",
name: "links",
elems: [
{
id: "instance_access_link",
name: "Access",
description: "(link used to access this Galaxy)",
},
{
id: "instance_resources_link",
name: "Resources",
description: "(link for more information about this Galaxy)",
},
{
id: "instance_help_link",
name: "Help",
description: "(link for finding help content for this Galaxy)",
},
{
id: "instance_support_link",
name: "Support",
description: "(link for support for this Galaxy)",
},
{
id: "instance_citation_link",
name: "Citation",
description: "(link describing how cite this Galaxy instance)",
},
{
id: "instance_terms_link",
name: "Terms and Conditions",
description: "(link describing how terms and conditions for using this Galaxy instance)",
},
{
id: "instance_organization_link",
name: "Organization",
description: "(link describing organization that runs this Galaxy instance)",
},
],
},
visualizationSection: {
title: "Visualizations",
name: "visualizations",
Expand Down
4 changes: 3 additions & 1 deletion client/src/components/PageDisplay/PageDisplay.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
@onEdit="onEdit" />
<PageHtml v-else :page="page" />
</div>
<b-alert v-else variant="info" show>Unsupported page format.</b-alert>
<LoadingSpan v-else message="Loading Galaxy configuration" />
</template>
</PublishedItem>
</template>
Expand All @@ -23,10 +23,12 @@ import { urlData } from "@/utils/url";
import PageHtml from "./PageHtml.vue";
import PublishedItem from "@/components/Common/PublishedItem.vue";
import LoadingSpan from "@/components/LoadingSpan.vue";
import Markdown from "@/components/Markdown/Markdown.vue";
export default {
components: {
LoadingSpan,
Markdown,
PageHtml,
PublishedItem,
Expand Down
29 changes: 27 additions & 2 deletions lib/galaxy/config/schemas/config_schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1180,11 +1180,20 @@ mapping:
type: str
required: false
desc: |
URL of the support resource for the galaxy instance. Used in activation
emails.
URL of the support resource for the galaxy instance. Used outside of web contexts
such as in activation emails and in Galaxy markdown report generation.
Example value 'https://galaxyproject.org/'
instance_access_url:
type: str
required: false
desc: |
URL used to access this Galaxy server. Used outside of web contexts
such as in Galaxy markdown report generation.
Example value 'https://usegalaxy.org'
email_domain_blocklist_file:
type: str
required: false
Expand Down Expand Up @@ -2931,6 +2940,22 @@ mapping:
a real admin user account via API.
You should probably not set this on a production server.
organization_name:
type: str
required: false
desc: |
The name of the organization that operates this Galaxy instance. Serves as the
default for the GA4GH service organization name and can be exposed through Galaxy
markdown for reports and such. For instance, "Not Evil Corporation".
organization_url:
type: str
required: false
desc: |
The URL of the organization that operates this Galaxy instance. Serves as the
default for the GA4GH service organization name and can be exposed through Galaxy
markdown for reports and such. For instance, "notevilcorp.com".
ga4gh_service_id:
type: str
required: false
Expand Down
4 changes: 4 additions & 0 deletions lib/galaxy/managers/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ def _config_is_truthy(item, key, **context):
"tool_training_recommendations_link": _use_config,
"tool_training_recommendations_api_url": _use_config,
"enable_notification_system": _use_config,
"instance_resource_url": _use_config,
"instance_access_url": _use_config,
"organization_name": _use_config,
"organization_url": _use_config,
}


Expand Down
7 changes: 7 additions & 0 deletions lib/galaxy/managers/markdown_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ class DynamicArguments:
"tool_stdout": ["step", "job_id"],
"generate_galaxy_version": [],
"generate_time": [],
"instance_access_link": [],
"instance_resources_link": [],
"instance_help_link": [],
"instance_support_link": [],
"instance_citation_link": [],
"instance_terms_link": [],
"instance_organization_link": [],
"visualization": DYNAMIC_ARGUMENTS,
# Invocation Flavored Markdown
"invocation_time": ["invocation_id"],
Expand Down
100 changes: 100 additions & 0 deletions lib/galaxy/managers/markdown_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,28 @@ def _remap(container, line):
rval = self.handle_generate_galaxy_version(line, version)
elif container == "generate_time":
rval = self.handle_generate_time(line, now())
elif container == "instance_access_link":
url = trans.app.config.instance_access_url
rval = self.handle_instance_access_link(line, url)
elif container == "instance_resources_link":
url = trans.app.config.instance_resource_url
rval = self.handle_instance_resources_link(line, url)
elif container == "instance_help_link":
url = trans.app.config.helpsite_url
rval = self.handle_instance_help_link(line, url)
elif container == "instance_support_link":
url = trans.app.config.support_url
rval = self.handle_instance_support_link(line, url)
elif container == "instance_citation_link":
url = trans.app.config.citation_url
rval = self.handle_instance_citation_link(line, url)
elif container == "instance_terms_link":
url = trans.app.config.terms_url
rval = self.handle_instance_terms_link(line, url)
elif container == "instance_organization_link":
title = trans.app.config.organization_name
url = trans.app.config.organization_url
rval = self.handle_instance_organization_link(line, title, url)
elif container == "invocation_time":
invocation = workflow_manager.get_invocation(trans, object_id)
rval = self.handle_invocation_time(line, invocation)
Expand Down Expand Up @@ -270,6 +292,34 @@ def handle_generate_galaxy_version(self, line, galaxy_version):
def handle_generate_time(self, line, date):
pass

@abc.abstractmethod
def handle_instance_access_link(self, line, url):
pass

@abc.abstractmethod
def handle_instance_resources_link(self, line, url):
pass

@abc.abstractmethod
def handle_instance_help_link(self, line, url):
pass

@abc.abstractmethod
def handle_instance_support_link(self, line, url):
pass

@abc.abstractmethod
def handle_instance_citation_link(self, line, url):
pass

@abc.abstractmethod
def handle_instance_terms_link(self, line, url):
pass

@abc.abstractmethod
def handle_instance_organization_link(self, line, title, url):
pass

@abc.abstractmethod
def handle_invocation_time(self, line, date):
pass
Expand Down Expand Up @@ -346,6 +396,27 @@ def handle_generate_galaxy_version(self, line, generate_version):
def handle_generate_time(self, line, generate_time):
pass

def handle_instance_access_link(self, line, url):
pass

def handle_instance_resources_link(self, line, url):
pass

def handle_instance_help_link(self, line, url):
pass

def handle_instance_support_link(self, line, url):
pass

def handle_instance_citation_link(self, line, url):
pass

def handle_instance_terms_link(self, line, url):
pass

def handle_instance_organization_link(self, line, title, url):
pass

def handle_invocation_time(self, line, invocation):
self.ensure_rendering_data_for("invocations", invocation)["create_time"] = invocation.create_time.isoformat()

Expand Down Expand Up @@ -546,6 +617,35 @@ def handle_generate_time(self, line, generate_time):
content = literal_via_fence(generate_time.isoformat())
return (content, True)

def handle_instance_access_link(self, line, url):
return self._handle_link(url)

def handle_instance_resources_link(self, line, url):
return self._handle_link(url)

def handle_instance_help_link(self, line, url):
return self._handle_link(url)

def handle_instance_support_link(self, line, url):
return self._handle_link(url)

def handle_instance_citation_link(self, line, url):
return self._handle_link(url)

def handle_instance_terms_link(self, line, url):
return self._handle_link(url)

def handle_instance_organization_link(self, line, title, url):
return self._handle_link(url, title)

def _handle_link(self, url, title=None):
if not url:
content = "*Not configured, please contact Galaxy admin*"
return (content, True)
elif not title:
title = url
return (f"[{title}]({url})", True)

def handle_invocation_time(self, line, invocation):
content = literal_via_fence(invocation.create_time.isoformat())
return (content, True)
Expand Down
Loading

0 comments on commit 8ff3702

Please sign in to comment.