Skip to content

Commit

Permalink
Merge pull request #17105 from jmchilton/tool_link
Browse files Browse the repository at this point in the history
 Expose more tool information / navigability in UI.
  • Loading branch information
bgruening authored Dec 23, 2023
2 parents 436754a + debd68e commit a735ec2
Show file tree
Hide file tree
Showing 17 changed files with 510 additions and 77 deletions.
126 changes: 126 additions & 0 deletions client/src/components/Markdown/Elements/HistoryDatasetAsTable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<script setup lang="ts">
import { computed } from "vue";
import { UrlDataProvider } from "@/components/providers/UrlDataProvider.js";
import LoadingSpan from "@/components/LoadingSpan.vue";
interface HistoryDatasetAsTableProps {
historyDatasetId: string;
compact: boolean;
showColumnHeaders: boolean;
title?: string;
footer?: string;
}
const props = withDefaults(defineProps<HistoryDatasetAsTableProps>(), {
compact: false,
showColumnHeaders: true,
title: undefined,
footer: undefined,
});
const itemUrl = computed(() => {
return `/api/datasets/${props.historyDatasetId}/get_content_as_text`;
});
const metaUrl = computed(() => {
return `/api/datasets/${props.historyDatasetId}`;
});
const expanded = false;
const contentClass = computed(() => {
if (expanded) {
return "embedded-dataset-expanded";
} else {
return "embedded-dataset";
}
});
function getFields(metaData: any) {
const fields = [];
const columnNames = metaData.metadata_column_names || [];
const columnCount = metaData.metadata_columns;
for (let i = 0; i < columnCount; i++) {
fields.push({
key: `${i}`,
label: columnNames[i] || i,
sortable: true,
});
}
return fields;
}
function getItems(textData: any, metaData: any) {
const tableData: object[] = [];
const delimiter: string = metaData.metadata_delimiter || "\t";
const comments: number = metaData.metadata_comment_lines || 0;
const lines = textData.split("\n");
lines.forEach((line: string, i: number) => {
if (i >= comments) {
const tabs = line.split(delimiter);
const rowData: string[] = [];
let hasData = false;
tabs.forEach((cellData: string, j: number) => {
const cellDataTrimmed = cellData.trim();
if (cellDataTrimmed) {
hasData = true;
}
rowData[j] = cellDataTrimmed;
});
if (hasData) {
tableData.push(rowData);
}
}
});
return tableData;
}
</script>

<template>
<b-card :no-body="props.compact">
<b-card-title v-if="title">
<b>{{ title }}</b>
</b-card-title>
<UrlDataProvider v-slot="{ result: itemContent, loading, error }" :url="itemUrl">
<LoadingSpan v-if="loading" message="Loading Dataset" />
<div v-else-if="error">{{ error }}</div>
<div v-else :class="contentClass">
<div v-if="itemContent.item_data">
<div>
<UrlDataProvider
v-slot="{ result: metaData, loading: metaLoading, error: metaError }"
:url="metaUrl">
<LoadingSpan v-if="metaLoading" message="Loading Metadata" />
<div v-else-if="metaError">{{ metaError }}</div>
<b-table
v-else
:thead-class="props.showColumnHeaders ? '' : 'd-none'"
striped
hover
:fields="getFields(metaData)"
:items="getItems(itemContent.item_data, metaData)" />
</UrlDataProvider>
</div>
</div>
<div v-else>No content found.</div>
<b-link v-if="itemContent.truncated" :href="itemContent.item_url"> Show More... </b-link>
</div>
</UrlDataProvider>
<b-card-footer v-if="footer">
{{ footer }}
</b-card-footer>
</b-card>
</template>

<style scoped>
.embedded-dataset {
max-height: 20rem;
overflow-y: auto;
}
.embedded-dataset-expanded {
max-height: 40rem;
overflow-y: auto;
}
</style>
63 changes: 46 additions & 17 deletions client/src/components/Markdown/Elements/JobMetrics.vue
Original file line number Diff line number Diff line change
@@ -1,26 +1,55 @@
<script setup lang="ts">
import { computed, watch } from "vue";
import { useJobStore } from "@/stores/jobStore";
import JobMetrics from "@/components/JobMetrics/JobMetrics.vue";
import ToolLinkPopover from "@/components/Tool/ToolLinkPopover.vue";
interface JobMetricsProps {
jobId: string;
title?: string;
footer?: string;
}
const props = withDefaults(defineProps<JobMetricsProps>(), {
title: undefined,
footer: undefined,
});
const jobStore = useJobStore();
const toolId = computed(() => {
return jobStore.getJob(props.jobId)?.tool_id;
});
const toolVersion = computed(() => {
return jobStore.getJob(props.jobId)?.tool_version;
});
watch(
props,
() => {
jobStore.fetchJob(props.jobId);
},
{ immediate: true }
);
</script>

<template>
<b-card nobody>
<b-card-title v-if="title">
<b>{{ title }}</b>
<icon ref="info" icon="info-circle" size="sm" />
<ToolLinkPopover :target="() => $refs.info" :tool-id="toolId" :tool-version="toolVersion" />
</b-card-title>
<JobMetrics
class="job-metrics"
:job-id="args.job_id"
:job-id="jobId"
:should-show-aws-estimate="false"
:should-show-carbon-emissions-estimates="false"
:include-title="false" />
<b-card-footer v-if="footer">
{{ footer }}
</b-card-footer>
</b-card>
</template>

<script>
import JobMetrics from "components/JobMetrics/JobMetrics";
export default {
components: {
JobMetrics,
},
props: {
args: {
type: Object,
default: null,
},
},
};
</script>
65 changes: 48 additions & 17 deletions client/src/components/Markdown/Elements/JobParameters.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,52 @@
<template>
<b-card nobody>
<JobParameters class="job-parameters" :job-id="args.job_id" :param="args.param" :include-title="false" />
</b-card>
</template>
<script setup lang="ts">
import { computed, watch } from "vue";
<script>
import JobParameters from "components/JobParameters/JobParameters";
import { useJobStore } from "@/stores/jobStore";
export default {
components: {
JobParameters,
},
props: {
args: {
type: Object,
default: null,
},
import JobParameters from "@/components/JobParameters/JobParameters.vue";
import ToolLinkPopover from "@/components/Tool/ToolLinkPopover.vue";
interface JobParametersProps {
jobId: string;
param?: string;
title?: string;
footer?: string;
}
const props = withDefaults(defineProps<JobParametersProps>(), {
param: undefined,
title: undefined,
footer: undefined,
});
const jobStore = useJobStore();
const toolId = computed(() => {
return jobStore.getJob(props.jobId)?.tool_id;
});
const toolVersion = computed(() => {
return jobStore.getJob(props.jobId)?.tool_version;
});
watch(
props,
() => {
jobStore.fetchJob(props.jobId);
},
};
{ immediate: true }
);
</script>

<template>
<b-card nobody>
<b-card-title v-if="title">
<b>{{ title }}</b>
<icon ref="info" icon="info-circle" size="sm" />
<ToolLinkPopover :target="() => $refs.info" :tool-id="toolId" :tool-version="toolVersion" />
</b-card-title>
<JobParameters class="job-parameters" :job-id="jobId" :param="param" :include-title="false" />
<b-card-footer v-if="footer">
{{ footer }}
</b-card-footer>
</b-card>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { isEmpty } from "@/utils/utils";
import WorkflowTree from "./WorkflowTree.vue";
import LoadingSpan from "@/components/LoadingSpan.vue";
import ToolLinkPopover from "@/components/Tool/ToolLinkPopover.vue";
import WorkflowStepIcon from "@/components/WorkflowInvocationState/WorkflowStepIcon.vue";
import WorkflowStepTitle from "@/components/WorkflowInvocationState/WorkflowStepTitle.vue";
interface WorkflowDisplayProps {
workflowId: string;
Expand Down Expand Up @@ -102,7 +105,20 @@ onMounted(async () => {
</b-alert>
<div v-if="itemContent !== null">
<div v-for="step in itemContent?.steps" :key="step.order_index" class="mb-2">
<div>Step {{ step.order_index + 1 }}: {{ step.label }}</div>
<span :id="`step-icon-${step.order_index}`">
<WorkflowStepIcon v-if="step.type" :step-type="step.type" />
</span>
<ToolLinkPopover
v-if="step.type == 'tool'"
:target="`step-icon-${step.order_index}`"
:tool-id="step.tool_id"
:tool-version="step.tool_version" />
<WorkflowStepTitle
:step-tool-id="step.tool_id"
:step-subworkflow-id="step.subworkflow_id"
:step-label="step.label"
:step-type="step.type"
:step-index="step.order_index" />
<WorkflowTree :input="step" :skip-head="true" />
</div>
</div>
Expand Down
32 changes: 30 additions & 2 deletions client/src/components/Markdown/MarkdownContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { computed, ref } from "vue";
import { useConfig } from "@/composables/config";
import HistoryDatasetAsImage from "./Elements/HistoryDatasetAsImage.vue";
import HistoryDatasetAsTable from "./Elements/HistoryDatasetAsTable.vue";
import HistoryDatasetCollectionDisplay from "./Elements/HistoryDatasetCollection/CollectionDisplay.vue";
import HistoryDatasetDetails from "./Elements/HistoryDatasetDetails.vue";
import HistoryDatasetDisplay from "./Elements/HistoryDatasetDisplay.vue";
Expand Down Expand Up @@ -68,6 +69,17 @@ const props = defineProps({
const isCollapsible = computed(() => props.args.collapse !== undefined);
const isVisible = computed(() => !isCollapsible.value || toggle.value);
function argToBoolean(args, name, booleanDefault) {
const valueAsString = args[name];
if (valueAsString == "true") {
return true;
} else if (valueAsString == "false") {
return false;
} else {
return booleanDefault;
}
}
</script>

<template>
Expand Down Expand Up @@ -126,11 +138,27 @@ const isVisible = computed(() => !isCollapsible.value || toggle.value);
</InstanceUrl>
<HistoryLink v-else-if="name == 'history_link'" :args="args" :histories="histories" />
<HistoryDatasetAsImage v-else-if="name == 'history_dataset_as_image'" :args="args" />
<HistoryDatasetAsTable
v-else-if="name == 'history_dataset_as_table'"
:history-dataset-id="args.history_dataset_id"
:compact="argToBoolean(args, 'compact', false)"
:show-column-headers="argToBoolean(args, 'show_column_headers', true)"
:title="args.title"
:footer="args.footer" />
<HistoryDatasetLink v-else-if="name == 'history_dataset_link'" :args="args" />
<HistoryDatasetIndex v-else-if="name == 'history_dataset_index'" :args="args" />
<InvocationTime v-else-if="name == 'invocation_time'" :args="args" :invocations="invocations" />
<JobMetrics v-else-if="name == 'job_metrics'" :args="args" />
<JobParameters v-else-if="name == 'job_parameters'" :args="args" />
<JobMetrics
v-else-if="name == 'job_metrics'"
:job-id="args.job_id"
:title="args.title"
:footer="args.footer" />
<JobParameters
v-else-if="name == 'job_parameters'"
:job-id="args.job_id"
:param="args.param || undefined"
:title="args.title"
:footer="args.footer" />
<WorkflowDisplay
v-else-if="name == 'workflow_display'"
:workflow-id="args.workflow_id"
Expand Down
5 changes: 5 additions & 0 deletions client/src/components/Markdown/MarkdownToolBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ const historySharedElements = [
name: "Embedded Dataset",
emitter: "onHistoryDatasetId",
},
{
id: "history_dataset_as_table",
name: "Embedded Dataset (as table)",
emitter: "onHistoryDatasetId",
},
{
id: "history_dataset_type",
name: "Dataset Type",
Expand Down
Loading

0 comments on commit a735ec2

Please sign in to comment.