Skip to content

Commit

Permalink
Render useful Markdown components for mapped over steps.
Browse files Browse the repository at this point in the history
API functionality to fetch and query ImplicitCollectionJobs' jobs.
  • Loading branch information
jmchilton committed Dec 15, 2023
1 parent 8749274 commit 96573ce
Show file tree
Hide file tree
Showing 16 changed files with 286 additions and 39 deletions.
2 changes: 2 additions & 0 deletions client/src/api/schema/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15660,6 +15660,7 @@ export interface operations {
/** @description Limit listing of jobs to those that match the history_id. If none, jobs from any history may be returned. */
/** @description Limit listing of jobs to those that match the specified workflow ID. If none, jobs from any workflow (or from no workflows) may be returned. */
/** @description Limit listing of jobs to those that match the specified workflow invocation ID. If none, jobs from any workflow invocation (or from no workflows) may be returned. */
/** @description Limit listing of jobs to those that match the specified implicit collection job ID. If none, jobs from any implicit collection execution (or from no implicit collection execution) may be returned. */
/** @description Sort results by specified field. */
/**
* @description A mix of free text and GitHub-style tags used to filter the index operation.
Expand Down Expand Up @@ -15711,6 +15712,7 @@ export interface operations {
history_id?: string;
workflow_id?: string;
invocation_id?: string;
implicit_collection_jobs_id?: string;
order_by?: components["schemas"]["JobIndexSortByEnum"];
search?: string;
limit?: number;
Expand Down
11 changes: 9 additions & 2 deletions client/src/components/JobMetrics/JobMetrics.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed, ref, unref } from "vue";
import { computed, ref, unref, watch } from "vue";
import { useJobMetricsStore } from "@/stores/jobMetricsStore";
Expand Down Expand Up @@ -60,7 +60,14 @@ async function getJobMetrics() {
await jobMetricsStore.fetchJobMetricsForDatasetId(props.datasetId, props.datasetType);
}
}
getJobMetrics();
watch(
props,
() => {
getJobMetrics();
},
{ immediate: true }
);
const ec2Instances = ref<EC2[]>();
import("./awsEc2ReferenceData.js").then((data) => (ec2Instances.value = data.ec2Instances));
Expand Down
24 changes: 16 additions & 8 deletions client/src/components/JobParameters/JobParameters.vue
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,25 @@ export default {
return parameter ? parameter.value : `Parameter "${this.param}" is not found!`;
},
},
watch: {
jobId: function (newValue) {
this.initJob();
},
},
created: function () {
let url;
if (this.jobId) {
url = `${getAppRoot()}api/jobs/${this.jobId}/parameters_display`;
} else {
url = `${getAppRoot()}api/datasets/${this.datasetId}/parameters_display?hda_ldda=${this.datasetType}`;
}
this.ajaxCall(url);
this.isSingleParam = this.param !== undefined && this.param !== "undefined";
this.initJob();
},
methods: {
initJob() {
let url;
if (this.jobId) {
url = `${getAppRoot()}api/jobs/${this.jobId}/parameters_display`;
} else {
url = `${getAppRoot()}api/datasets/${this.datasetId}/parameters_display?hda_ldda=${this.datasetType}`;
}
this.ajaxCall(url);
this.isSingleParam = this.param !== undefined && this.param !== "undefined";
},
appRoot: function () {
return getAppRoot();
},
Expand Down
51 changes: 40 additions & 11 deletions client/src/components/Markdown/Elements/JobMetrics.vue
Original file line number Diff line number Diff line change
@@ -1,35 +1,57 @@
<script setup lang="ts">
import { computed, watch } from "vue";
import { computed, toRef, watch } from "vue";
import { useJobStore } from "@/stores/jobStore";
import { useMappingJobs } from "./handlesMappingJobs";
import JobSelection from "./JobSelection.vue";
import JobMetrics from "@/components/JobMetrics/JobMetrics.vue";
import ToolLinkPopover from "@/components/Tool/ToolLinkPopover.vue";
interface JobMetricsProps {
jobId: string;
jobId?: string;
implicitCollectionJobsId?: string;
title?: string;
footer?: string;
}
const props = withDefaults(defineProps<JobMetricsProps>(), {
jobId: null,
implicitCollectionJobsId: null,
title: null,
footer: null,
});
const jobStore = useJobStore();
const toolId = computed(() => {
return jobStore.getJob(props.jobId)?.tool_id;
if (targetJobId.value) {
return jobStore.getJob(targetJobId.value)?.tool_id;
}
return undefined;
});
const toolVersion = computed(() => {
return jobStore.getJob(props.jobId)?.tool_version;
if (targetJobId.value) {
return jobStore.getJob(targetJobId.value)?.tool_version;
}
return undefined;
});
const jobIdRef = toRef(props, "jobId");
const implicitCollectionJobsIdRef = toRef(props, "implicitCollectionJobsId");
const { selectJobOptions, selectedJob, targetJobId } = useMappingJobs(jobIdRef, implicitCollectionJobsIdRef);
async function init() {
if (targetJobId.value) {
jobStore.fetchJob(targetJobId.value);
}
}
watch(
props,
targetJobId,
() => {
jobStore.fetchJob(props.jobId);
init();
},
{ immediate: true }
);
Expand All @@ -42,12 +64,19 @@ watch(
<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"
<JobSelection
v-model="selectedJob"
:job-id="jobId"
:should-show-aws-estimate="false"
:should-show-carbon-emissions-estimates="false"
:include-title="false" />
:implicit-collection-jobs-id="implicitCollectionJobsId"
:select-job-options="selectJobOptions">
<JobMetrics
v-if="targetJobId"
class="job-metrics"
:job-id="targetJobId"
:should-show-aws-estimate="false"
:should-show-carbon-emissions-estimates="false"
:include-title="false" />
</JobSelection>
<b-card-footer v-if="footer">
{{ footer }}
</b-card-footer>
Expand Down
43 changes: 36 additions & 7 deletions client/src/components/Markdown/Elements/JobParameters.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
<script setup lang="ts">
import { computed, watch } from "vue";
import { computed, toRef, watch } from "vue";
import { useJobStore } from "@/stores/jobStore";
import { useMappingJobs } from "./handlesMappingJobs";
import JobSelection from "./JobSelection.vue";
import JobParameters from "@/components/JobParameters/JobParameters.vue";
import ToolLinkPopover from "@/components/Tool/ToolLinkPopover.vue";
interface JobParametersProps {
jobId: string;
jobId?: string;
implicitCollectionJobsId?: string;
param?: string;
title?: string;
footer?: string;
}
const props = withDefaults(defineProps<JobParametersProps>(), {
jobId: null,
implicitCollectionJobsId: null,
param: undefined,
title: null,
footer: null,
Expand All @@ -22,16 +28,32 @@ const props = withDefaults(defineProps<JobParametersProps>(), {
const jobStore = useJobStore();
const toolId = computed(() => {
return jobStore.getJob(props.jobId)?.tool_id;
if (targetJobId.value) {
return jobStore.getJob(targetJobId.value)?.tool_id;
}
return undefined;
});
const toolVersion = computed(() => {
return jobStore.getJob(props.jobId)?.tool_version;
if (targetJobId.value) {
return jobStore.getJob(targetJobId.value)?.tool_version;
}
return undefined;
});
const jobIdRef = toRef(props, "jobId");
const implicitCollectionJobsIdRef = toRef(props, "implicitCollectionJobsId");
const { selectJobOptions, selectedJob, targetJobId } = useMappingJobs(jobIdRef, implicitCollectionJobsIdRef);
async function init() {
if (targetJobId.value) {
jobStore.fetchJob(targetJobId.value);
}
}
watch(
props,
targetJobId,
() => {
jobStore.fetchJob(props.jobId);
init();
},
{ immediate: true }
);
Expand All @@ -44,7 +66,14 @@ watch(
<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" />
<JobSelection
v-model="selectedJob"
:job-id="jobId"
:implicit-collection-jobs-id="implicitCollectionJobsId"
:select-job-options="selectJobOptions">
<JobParameters class="job-parameters" :job-id="targetJobId" :param="param" :include-title="false" />
{{ targetJobId }}
</JobSelection>
<b-card-footer v-if="footer">
{{ footer }}
</b-card-footer>
Expand Down
44 changes: 44 additions & 0 deletions client/src/components/Markdown/Elements/JobSelection.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<script setup lang="ts">
import { SelectOption } from "./handlesMappingJobs";
interface JobSelectionProps {
jobId?: string;
implicitCollectionJobsId?: string;
selectJobOptions: SelectOption[];
value?: String | undefined;
}
const emit = defineEmits<{
(e: "input", id: string | undefined): void;
}>();
function handleInput(value: string | undefined) {
emit("input", value);
}
defineProps<JobSelectionProps>();
</script>

<template>
<div>
<slot v-if="jobId"> </slot>
<div v-else>
<b-navbar>
<b-collapse id="nav-text-collapse" is-nav>
<b-navbar-nav>
<b-nav-text>Select Job</b-nav-text>
</b-navbar-nav>
<b-nav-form>
<b-input-group size="sm">
<b-form-select
:value="value"
class="text-right"
:options="selectJobOptions"
@input="handleInput"></b-form-select>
</b-input-group>
</b-nav-form>
</b-collapse>
</b-navbar>
<slot />
</div>
</div>
</template>
51 changes: 51 additions & 0 deletions client/src/components/Markdown/Elements/handlesMappingJobs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { format, parseISO } from "date-fns";
import { computed, Ref, ref, watch } from "vue";

import { fetcher } from "@/api/schema";

const jobsFetcher = fetcher.path("/api/jobs").method("get").create();

export interface SelectOption {
value: string;
text: string;
}

interface Job {
id: string;
create_time: string;
}

export function useMappingJobs(
singleJobId: Ref<string | undefined>,
implicitCollectionJobsId: Ref<string | undefined>
) {
const selectJobOptions = ref<SelectOption[]>([]);
const selectedJob = ref<string | undefined>(undefined);
const targetJobId = computed<string | undefined>(() => {
if (singleJobId.value) {
return singleJobId.value;
} else {
return selectedJob.value;
}
});
watch(
implicitCollectionJobsId,
async () => {
if (implicitCollectionJobsId.value) {
const response = await jobsFetcher({ implicit_collection_jobs_id: implicitCollectionJobsId.value });
const jobs: Job[] = response.data as unknown as Job[];
selectJobOptions.value = jobs.map((value, index) => {
const isoCreateTime = parseISO(`${value.create_time}Z`);
const prettyTime = format(isoCreateTime, "eeee MMM do H:mm:ss yyyy zz");
return { value: value.id, text: `${index + 1}: ${prettyTime}` };
});
if (jobs[0]) {
const job: Job = jobs[0];
selectedJob.value = job.id;
}
}
},
{ immediate: true }
);
return { selectJobOptions, selectedJob, targetJobId };
}
2 changes: 2 additions & 0 deletions client/src/components/Markdown/MarkdownContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,13 @@ function argToBoolean(args, name, booleanDefault) {
<JobMetrics
v-else-if="name == 'job_metrics'"
:job-id="args.job_id"
:implicit-collection-jobs-id="args.implicit_collection_jobs_id"
:title="args.title"
:footer="args.footer" />
<JobParameters
v-else-if="name == 'job_parameters'"
:job-id="args.job_id"
:implicit-collection-jobs-id="args.implicit_collection_jobs_id"
:param="args.param || undefined"
:title="args.title"
:footer="args.footer" />
Expand Down
5 changes: 5 additions & 0 deletions lib/galaxy/managers/collections_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ def dictify_dataset_collection_instance(
else:
element_func = dictify_element_reference
dict_value["elements"] = [element_func(_, rank_fuzzy_counts=rest_fuzzy_counts) for _ in elements]
icj = dataset_collection_instance.implicit_collection_jobs
if icj:
dict_value["implicit_collection_jobs_id"] = icj.id
else:
dict_value["implicit_collection_jobs_id"] = None

security.encode_all_ids(dict_value, recursive=True) # TODO: Use Kyle's recursive formulation of this.
return dict_value
Expand Down
Loading

0 comments on commit 96573ce

Please sign in to comment.