From 81ef48978ad10dfb90596e702f9b71b7b1200346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20G=C3=B6bel?= <dgoebel@techfak.uni-bielefeld.de> Date: Wed, 19 Jun 2024 14:11:11 +0000 Subject: [PATCH] Add option to select the nextflow version for workflow versions #131 --- src/client/index.ts | 1 + src/client/models/DevWorkflowExecutionIn.ts | 5 +++ src/client/models/NextflowVersion.ts | 18 +++++++++ src/client/models/UserOutExtended.ts | 2 +- src/client/models/WorkflowIn.ts | 5 +++ src/client/models/WorkflowUpdate.ts | 5 +++ src/client/models/WorkflowVersion.ts | 5 +++ src/components/AppHeader.vue | 7 ---- .../workflows/WorkflowWithVersionsCard.vue | 6 ++- .../modals/ArbitraryWorkflowModal.vue | 26 ++++++++++++- .../workflows/modals/CreateWorkflowModal.vue | 30 ++++++++++++++- .../workflows/modals/UpdateWorkflowModal.vue | 37 +++++++++++++++---- src/views/admin/AdminUsersView.vue | 6 --- src/views/workflows/ArbitraryWorkflowView.vue | 4 +- src/views/workflows/MyWorkflowsView.vue | 10 ++++- 15 files changed, 138 insertions(+), 29 deletions(-) create mode 100644 src/client/models/NextflowVersion.ts diff --git a/src/client/index.ts b/src/client/index.ts index 98752ac..77aaffd 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -26,6 +26,7 @@ export type { ErrorDetail } from './models/ErrorDetail'; export { FileTree } from './models/FileTree'; export type { HTTPValidationError } from './models/HTTPValidationError'; export type { IconUpdateOut } from './models/IconUpdateOut'; +export { NextflowVersion } from './models/NextflowVersion'; export { OIDCProvider } from './models/OIDCProvider'; export type { ParameterExtension } from './models/ParameterExtension'; export { Permission } from './models/Permission'; diff --git a/src/client/models/DevWorkflowExecutionIn.ts b/src/client/models/DevWorkflowExecutionIn.ts index f65f6eb..e075238 100644 --- a/src/client/models/DevWorkflowExecutionIn.ts +++ b/src/client/models/DevWorkflowExecutionIn.ts @@ -2,6 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ +import type { NextflowVersion } from './NextflowVersion'; import type { WorkflowModeIn } from './WorkflowModeIn'; export type DevWorkflowExecutionIn = { /** @@ -36,5 +37,9 @@ export type DevWorkflowExecutionIn = { * Mode of the workflow with an alternative entrypoint */ mode?: (WorkflowModeIn | null); + /** + * The version of Nextflow this workflow execution requires + */ + nextflow_version: NextflowVersion; }; diff --git a/src/client/models/NextflowVersion.ts b/src/client/models/NextflowVersion.ts new file mode 100644 index 0000000..e16dfe9 --- /dev/null +++ b/src/client/models/NextflowVersion.ts @@ -0,0 +1,18 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export enum NextflowVersion { + _23_04_0 = '23.04.0', + _23_04_1 = '23.04.1', + _23_04_2 = '23.04.2', + _23_04_3 = '23.04.3', + _23_04_4 = '23.04.4', + _23_04_5 = '23.04.5', + _23_10_0 = '23.10.0', + _23_10_1 = '23.10.1', + _23_10_2 = '23.10.2', + _23_10_3 = '23.10.3', + _24_04_1 = '24.04.1', + _24_04_2 = '24.04.2', +} diff --git a/src/client/models/UserOutExtended.ts b/src/client/models/UserOutExtended.ts index a05ecb6..709361b 100644 --- a/src/client/models/UserOutExtended.ts +++ b/src/client/models/UserOutExtended.ts @@ -27,6 +27,6 @@ export type UserOutExtended = { /** * URL to the gravatar avatar based on the users email */ - gravatar_url?: (string | null); + gravatar_url: string; }; diff --git a/src/client/models/WorkflowIn.ts b/src/client/models/WorkflowIn.ts index acc74b5..f433bf9 100644 --- a/src/client/models/WorkflowIn.ts +++ b/src/client/models/WorkflowIn.ts @@ -2,6 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ +import type { NextflowVersion } from './NextflowVersion'; import type { WorkflowModeIn } from './WorkflowModeIn'; export type WorkflowIn = { /** @@ -32,5 +33,9 @@ export type WorkflowIn = { * List of modes with alternative entrypoint the new workflow has */ modes?: Array<WorkflowModeIn>; + /** + * The version of Nextflow this workflow version requires + */ + nextflow_version: NextflowVersion; }; diff --git a/src/client/models/WorkflowUpdate.ts b/src/client/models/WorkflowUpdate.ts index 9b3dac3..a67749a 100644 --- a/src/client/models/WorkflowUpdate.ts +++ b/src/client/models/WorkflowUpdate.ts @@ -2,6 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ +import type { NextflowVersion } from './NextflowVersion'; import type { WorkflowModeIn } from './WorkflowModeIn'; export type WorkflowUpdate = { /** @@ -20,5 +21,9 @@ export type WorkflowUpdate = { * Delete modes for the new workflow version. */ delete_modes?: Array<string>; + /** + * The version of Nextflow this new workflow version requires. + */ + nextflow_version: NextflowVersion; }; diff --git a/src/client/models/WorkflowVersion.ts b/src/client/models/WorkflowVersion.ts index 1974ff1..3e3138e 100644 --- a/src/client/models/WorkflowVersion.ts +++ b/src/client/models/WorkflowVersion.ts @@ -2,6 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ +import type { NextflowVersion } from './NextflowVersion'; import type { ParameterExtension } from './ParameterExtension'; import type { WorkflowVersionStatus } from './WorkflowVersionStatus'; export type WorkflowVersion = { @@ -37,5 +38,9 @@ export type WorkflowVersion = { * Parameter extension specific for this CloWM instance */ parameter_extension?: (ParameterExtension | null); + /** + * The version of Nextflow this workflow version requires + */ + nextflow_version: NextflowVersion; }; diff --git a/src/components/AppHeader.vue b/src/components/AppHeader.vue index 97d73da..331c790 100644 --- a/src/components/AppHeader.vue +++ b/src/components/AppHeader.vue @@ -3,7 +3,6 @@ import { useUserStore } from "@/stores/users"; import { useRoute, useRouter } from "vue-router"; import { watch, ref, computed } from "vue"; import { OpenAPI } from "@/client"; -import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; const userRepository = useUserStore(); const route = useRoute(); @@ -266,18 +265,12 @@ watch( > <strong class="me-2">{{ userRepository.user.display_name }}</strong> <img - v-if="userRepository.user.gravatar_url" :src="userRepository.user.gravatar_url + '?d=mp&s=32'" class="rounded-circle" height="32" width="32" alt="profile picture" /> - <font-awesome-icon - v-else - icon="fa-solid fa-circle-user" - class="text-secondary fs-4" - /> </a> <ul class="dropdown-menu text-small shadow" diff --git a/src/components/workflows/WorkflowWithVersionsCard.vue b/src/components/workflows/WorkflowWithVersionsCard.vue index cae0ee5..a5a95f2 100644 --- a/src/components/workflows/WorkflowWithVersionsCard.vue +++ b/src/components/workflows/WorkflowWithVersionsCard.vue @@ -215,6 +215,7 @@ onMounted(() => { <th scope="col">Version</th> <th scope="col">Status</th> <th scope="col">Updated at</th> + <th scope="col">Nextflow version</th> <th scope="col" class="text-align-center">Usage</th> <th scope="col" class="text-align-center">Icon</th> <th scope="col"></th> @@ -246,6 +247,9 @@ onMounted(() => { <td> {{ dayjs.unix(version.created_at).format("DD MMM YYYY") }} </td> + <td class="text-align-center"> + {{ version.nextflow_version }} + </td> <td class="text-align-center"> <span class="text-success me-1" @@ -351,7 +355,7 @@ onMounted(() => { </tr> <tr> <th scope="row" class="fw-bold">Overall</th> - <td colspan="2"></td> + <td colspan="3"></td> <td class="text-align-center"> <span class="text-success me-1" diff --git a/src/components/workflows/modals/ArbitraryWorkflowModal.vue b/src/components/workflows/modals/ArbitraryWorkflowModal.vue index 6399ce3..749dcd9 100644 --- a/src/components/workflows/modals/ArbitraryWorkflowModal.vue +++ b/src/components/workflows/modals/ArbitraryWorkflowModal.vue @@ -10,7 +10,7 @@ import { } from "@/utils/GitRepository"; import { Collapse, Modal } from "bootstrap"; import { useWorkflowStore } from "@/stores/workflows"; -import type { WorkflowModeOut } from "@/client"; +import { NextflowVersion, type WorkflowModeOut } from "@/client"; import { environment } from "@/environment"; import { useS3KeyStore } from "@/stores/s3keys"; import { useResourceStore } from "@/stores/resources"; @@ -38,9 +38,12 @@ const resourceStore = useResourceStore(); const workflow = reactive<{ repository_url: string; git_commit_hash: string; + nextflow_version: NextflowVersion; }>({ repository_url: "", git_commit_hash: "", + nextflow_version: + Object.values(NextflowVersion)[Object.values(NextflowVersion).length - 1], }); const repositoryCredentials = reactive<{ @@ -504,7 +507,7 @@ onMounted(() => { /> </div> <div id="gitRepoProviderHelp" class="form-text"> - We support Github and GitLab Repositories + We support Github and (self-hosted) GitLab Repositories </div> <div class="text-danger"> <div v-if="formState.unsupportedRepository"> @@ -555,6 +558,25 @@ onMounted(() => { </li> </ul> </div> + <div class="mb-3"> + <label for="workflowNextflowVersionInput" class="form-label" + >Nextflow version</label + > + <select + class="form-select" + id="workflowNextflowVersionInput" + required + v-model="workflow.nextflow_version" + > + <option + v-for="version in Object.values(NextflowVersion).reverse()" + :key="version" + :value="version" + > + {{ version }} + </option> + </select> + </div> <div class="mb-3"> <div class="form-check fs-5"> <input diff --git a/src/components/workflows/modals/CreateWorkflowModal.vue b/src/components/workflows/modals/CreateWorkflowModal.vue index 61398ea..c1ec15a 100644 --- a/src/components/workflows/modals/CreateWorkflowModal.vue +++ b/src/components/workflows/modals/CreateWorkflowModal.vue @@ -1,7 +1,12 @@ <script setup lang="ts"> import { computed, onMounted, reactive, ref, watch } from "vue"; import { Modal, Toast, Collapse, Tooltip } from "bootstrap"; -import type { WorkflowIn, WorkflowOut, WorkflowModeOut } from "@/client"; +import { + type WorkflowIn, + type WorkflowOut, + type WorkflowModeOut, + NextflowVersion, +} from "@/client"; import BootstrapModal from "@/components/modals/BootstrapModal.vue"; import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; import { ApiError } from "@/client"; @@ -61,6 +66,8 @@ const workflow = reactive<WorkflowIn>({ initial_version: undefined, token: undefined, modes: [], + nextflow_version: + Object.values(NextflowVersion)[Object.values(NextflowVersion).length - 1], }); const formState = reactive<{ @@ -410,7 +417,7 @@ onMounted(() => { </div> </div> <div id="gitRepoProviderHelp" class="form-text"> - We support GitHub and GitLab Repositories + We support GitHub and (self-hosted) GitLab Repositories </div> <div class="text-danger"> <div v-if="formState.unsupportedRepository"> @@ -501,6 +508,25 @@ onMounted(() => { </div> </div> </div> + <div class="mb-3"> + <label for="createWorkflowNextflowVersionInput" class="form-label" + >Nextflow version</label + > + <select + class="form-select" + id="createWorkflowNextflowVersionInput" + required + v-model="workflow.nextflow_version" + > + <option + v-for="version in Object.values(NextflowVersion).reverse()" + :key="version" + :value="version" + > + {{ version }} + </option> + </select> + </div> <div class="mb-3"> <div class="form-check fs-5"> <input diff --git a/src/components/workflows/modals/UpdateWorkflowModal.vue b/src/components/workflows/modals/UpdateWorkflowModal.vue index 55d13e7..7347855 100644 --- a/src/components/workflows/modals/UpdateWorkflowModal.vue +++ b/src/components/workflows/modals/UpdateWorkflowModal.vue @@ -1,13 +1,14 @@ <script setup lang="ts"> import { computed, onMounted, reactive, ref, watch } from "vue"; import { Collapse, Modal, Toast } from "bootstrap"; -import type { - WorkflowUpdate, - WorkflowOut, - WorkflowModeIn, - WorkflowModeOut, - WorkflowVersion, - ApiError, +import { + type WorkflowUpdate, + type WorkflowOut, + type WorkflowModeIn, + type WorkflowModeOut, + type WorkflowVersion, + type ApiError, + NextflowVersion, } from "@/client"; import BootstrapModal from "@/components/modals/BootstrapModal.vue"; import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; @@ -59,6 +60,8 @@ const workflowUpdate = reactive<WorkflowUpdate>({ git_commit_hash: "", delete_modes: [], append_modes: [], + nextflow_version: + Object.values(NextflowVersion)[Object.values(NextflowVersion).length - 1], }); const workflowModes = reactive<{ @@ -96,6 +99,7 @@ watch( () => { resetForm(); formState.modesEnabled = (latestVersion.value.modes ?? []).length > 0; + workflowUpdate.nextflow_version = latestVersion.value.nextflow_version; if (props.workflow.private) { formState.loadCredentials = true; WorkflowCredentialsService.workflowCredentialsGetWorkflowCredentials( @@ -431,6 +435,25 @@ onMounted(() => { </div> </div> </div> + <div class="mb-3"> + <label for="updateWorkflowNextflowVersionInput" class="form-label" + >Nextflow version</label + > + <select + class="form-select" + id="updateWorkflowNextflowVersionInput" + required + v-model="workflowUpdate.nextflow_version" + > + <option + v-for="version in Object.values(NextflowVersion).reverse()" + :key="version" + :value="version" + > + {{ version }} + </option> + </select> + </div> <div class="mb-3"> <div class="form-check fs-5"> <input diff --git a/src/views/admin/AdminUsersView.vue b/src/views/admin/AdminUsersView.vue index 69fa6ea..498e36f 100644 --- a/src/views/admin/AdminUsersView.vue +++ b/src/views/admin/AdminUsersView.vue @@ -213,18 +213,12 @@ onMounted(() => { <tr v-for="(user, index) in userState.users" :key="user.uid"> <th scope="row"> <img - v-if="user.gravatar_url" :src="user.gravatar_url + '?d=mp&s=32'" class="rounded-circle" height="32" width="32" alt="profile picture" /> - <font-awesome-icon - v-else - icon="fa-solid fa-circle-user" - class="text-secondary fs-4" - /> <span class="ms-2">{{ user.display_name }}</span> </th> <td>{{ user.uid }}</td> diff --git a/src/views/workflows/ArbitraryWorkflowView.vue b/src/views/workflows/ArbitraryWorkflowView.vue index 45f1b3e..3a58992 100644 --- a/src/views/workflows/ArbitraryWorkflowView.vue +++ b/src/views/workflows/ArbitraryWorkflowView.vue @@ -121,6 +121,7 @@ function startWorkflow( debug_s3_path: metaParameters.debug_s3_path, provenance_s3_path: metaParameters.provenance_s3_path, repository_url: workflowState.workflow.repository_url, + nextflow_version: workflowState.workflow.nextflow_version, token: workflowState.workflow.token ?? undefined, mode: (workflowState.workflow.modes ?? []).length > 0 @@ -185,8 +186,9 @@ onMounted(() => { workflowState.workflow?.repository_url }}</a> </h5> + <h5>Git Commit Hash: {{ workflowState.workflow?.git_commit_hash }}</h5> <h5 :class="{ 'mb-5': workflowState.workflow.modes!.length < 1 }"> - Git Commit Hash: {{ workflowState.workflow?.git_commit_hash }} + Nextflow version: {{ workflowState.workflow?.nextflow_version }} </h5> <template v-if="workflowState.workflow.modes!.length > 0"> <h5>Entrypoint: {{ workflowState.workflow?.modes?.[0].entrypoint }}</h5> diff --git a/src/views/workflows/MyWorkflowsView.vue b/src/views/workflows/MyWorkflowsView.vue index 9ad162d..7ccfeb4 100644 --- a/src/views/workflows/MyWorkflowsView.vue +++ b/src/views/workflows/MyWorkflowsView.vue @@ -1,7 +1,11 @@ <script setup lang="ts"> import { computed, onMounted, reactive } from "vue"; -import type { WorkflowOut, WorkflowVersion } from "@/client"; -import { WorkflowVersionStatus } from "@/client"; +import { + NextflowVersion, + type WorkflowOut, + type WorkflowVersion, + WorkflowVersionStatus, +} from "@/client"; import WorkflowWithVersionsCard from "@/components/workflows/WorkflowWithVersionsCard.vue"; import CreateWorkflowModal from "@/components/workflows/modals/CreateWorkflowModal.vue"; import CardTransitionGroup from "@/components/transitions/CardTransitionGroup.vue"; @@ -37,6 +41,7 @@ const workflowsState = reactive<{ workflow_id: "", icon_url: "", modes: [], + nextflow_version: NextflowVersion._24_04_2, }, ], repository_url: "", @@ -52,6 +57,7 @@ const workflowsState = reactive<{ icon_url: null, created_at: 0, status: WorkflowVersionStatus.CREATED, + nextflow_version: NextflowVersion._24_04_2, }, }); -- GitLab