diff --git a/package-lock.json b/package-lock.json index 1b1acb325a1172a46b933993fbcda1ca3689a8fa..d350098699cdc047044744c7a67918b781d20f08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2680,12 +2680,12 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.18.tgz", - "integrity": "sha512-F7YK8lMK0iv6b9/Gdk15A67wM0KKZvxDxed0RR60C1z9tIJTKta+urs4j0RTN5XqHISzI3etN3mX0uHhjmoqjQ==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.19.tgz", + "integrity": "sha512-gj81785z0JNzRcU0Mq98E56e4ltO1yf8k5PQ+tV/7YHnbZkrM0fyFyuttnN8ngJZjbpofWE/m4qjKBiLl8Ju4w==", "dependencies": { "@babel/parser": "^7.23.9", - "@vue/shared": "3.4.18", + "@vue/shared": "3.4.19", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.0.2" @@ -2697,24 +2697,24 @@ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "node_modules/@vue/compiler-dom": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.18.tgz", - "integrity": "sha512-24Eb8lcMfInefvQ6YlEVS18w5Q66f4+uXWVA+yb7praKbyjHRNuKVWGuinfSSjM0ZIiPi++QWukhkgznBaqpEA==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.19.tgz", + "integrity": "sha512-vm6+cogWrshjqEHTzIDCp72DKtea8Ry/QVpQRYoyTIg9k7QZDX6D8+HGURjtmatfgM8xgCFtJJaOlCaRYRK3QA==", "dependencies": { - "@vue/compiler-core": "3.4.18", - "@vue/shared": "3.4.18" + "@vue/compiler-core": "3.4.19", + "@vue/shared": "3.4.19" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.18.tgz", - "integrity": "sha512-rG5tqtnzwrVpMqAQ7FHtvHaV70G6LLfJIWLYZB/jZ9m/hrnZmIQh+H3ewnC5onwe/ibljm9+ZupxeElzqCkTAw==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.19.tgz", + "integrity": "sha512-LQ3U4SN0DlvV0xhr1lUsgLCYlwQfUfetyPxkKYu7dkfvx7g3ojrGAkw0AERLOKYXuAGnqFsEuytkdcComei3Yg==", "dependencies": { "@babel/parser": "^7.23.9", - "@vue/compiler-core": "3.4.18", - "@vue/compiler-dom": "3.4.18", - "@vue/compiler-ssr": "3.4.18", - "@vue/shared": "3.4.18", + "@vue/compiler-core": "3.4.19", + "@vue/compiler-dom": "3.4.19", + "@vue/compiler-ssr": "3.4.19", + "@vue/shared": "3.4.19", "estree-walker": "^2.0.2", "magic-string": "^0.30.6", "postcss": "^8.4.33", @@ -2738,12 +2738,12 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.18.tgz", - "integrity": "sha512-hSlv20oUhPxo2UYUacHgGaxtqP0tvFo6ixxxD6JlXIkwzwoZ9eKK6PFQN4hNK/R13JlNyldwWt/fqGBKgWJ6nQ==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.19.tgz", + "integrity": "sha512-P0PLKC4+u4OMJ8sinba/5Z/iDT84uMRRlrWzadgLA69opCpI1gG4N55qDSC+dedwq2fJtzmGald05LWR5TFfLw==", "dependencies": { - "@vue/compiler-dom": "3.4.18", - "@vue/shared": "3.4.18" + "@vue/compiler-dom": "3.4.19", + "@vue/shared": "3.4.19" } }, "node_modules/@vue/devtools-api": { @@ -2839,48 +2839,48 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.18.tgz", - "integrity": "sha512-7uda2/I0jpLiRygprDo5Jxs2HJkOVXcOMlyVlY54yRLxoycBpwGJRwJT9EdGB4adnoqJDXVT2BilUAYwI7qvmg==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.19.tgz", + "integrity": "sha512-+VcwrQvLZgEclGZRHx4O2XhyEEcKaBi50WbxdVItEezUf4fqRh838Ix6amWTdX0CNb/b6t3Gkz3eOebfcSt+UA==", "dependencies": { - "@vue/shared": "3.4.18" + "@vue/shared": "3.4.19" } }, "node_modules/@vue/runtime-core": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.18.tgz", - "integrity": "sha512-7mU9diCa+4e+8/wZ7Udw5pwTH10A11sZ1nldmHOUKJnzCwvZxfJqAtw31mIf4T5H2FsLCSBQT3xgioA9vIjyDQ==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.19.tgz", + "integrity": "sha512-/Z3tFwOrerJB/oyutmJGoYbuoadphDcJAd5jOuJE86THNZji9pYjZroQ2NFsZkTxOq0GJbb+s2kxTYToDiyZzw==", "dependencies": { - "@vue/reactivity": "3.4.18", - "@vue/shared": "3.4.18" + "@vue/reactivity": "3.4.19", + "@vue/shared": "3.4.19" } }, "node_modules/@vue/runtime-dom": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.18.tgz", - "integrity": "sha512-2y1Mkzcw1niSfG7z3Qx+2ir9Gb4hdTkZe5p/I8x1aTIKQE0vY0tPAEUPhZm5tx6183gG3D/KwHG728UR0sIufA==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.19.tgz", + "integrity": "sha512-IyZzIDqfNCF0OyZOauL+F4yzjMPN2rPd8nhqPP2N1lBn3kYqJpPHHru+83Rkvo2lHz5mW+rEeIMEF9qY3PB94g==", "dependencies": { - "@vue/runtime-core": "3.4.18", - "@vue/shared": "3.4.18", + "@vue/runtime-core": "3.4.19", + "@vue/shared": "3.4.19", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.18.tgz", - "integrity": "sha512-YJd1wa7mzUN3NRqLEsrwEYWyO+PUBSROIGlCc3J/cvn7Zu6CxhNLgXa8Z4zZ5ja5/nviYO79J1InoPeXgwBTZA==", + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.19.tgz", + "integrity": "sha512-eAj2p0c429RZyyhtMRnttjcSToch+kTWxFPHlzGMkR28ZbF1PDlTcmGmlDxccBuqNd9iOQ7xPRPAGgPVj+YpQw==", "dependencies": { - "@vue/compiler-ssr": "3.4.18", - "@vue/shared": "3.4.18" + "@vue/compiler-ssr": "3.4.19", + "@vue/shared": "3.4.19" }, "peerDependencies": { - "vue": "3.4.18" + "vue": "3.4.19" } }, "node_modules/@vue/shared": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.18.tgz", - "integrity": "sha512-CxouGFxxaW5r1WbrSmWwck3No58rApXgRSBxrqgnY1K+jk20F6DrXJkHdH9n4HVT+/B6G2CAn213Uq3npWiy8Q==" + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz", + "integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==" }, "node_modules/@vue/tsconfig": { "version": "0.5.1", @@ -3138,15 +3138,16 @@ } }, "node_modules/call-bind": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", - "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "set-function-length": "^1.2.0" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -3367,18 +3368,21 @@ "dev": true }, "node_modules/define-data-property": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.2.tgz", - "integrity": "sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.3.tgz", + "integrity": "sha512-h3GBouC+RPtNX2N0hHVLo2ZwPYurq8mLmXpOLTsw71gr7lHt5VaI4vVkDUNOfiWmm48JEXe3VM7PmLX45AMmmg==", "dev": true, "dependencies": { "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.2", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-properties": { @@ -3509,6 +3513,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", @@ -4332,12 +4348,12 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6931,15 +6947,15 @@ } }, "node_modules/vue": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.18.tgz", - "integrity": "sha512-0zLRYamFRe0wF4q2L3O24KQzLyLpL64ye1RUToOgOxuWZsb/FhaNRdGmeozdtVYLz6tl94OXLaK7/WQIrVCw1A==", - "dependencies": { - "@vue/compiler-dom": "3.4.18", - "@vue/compiler-sfc": "3.4.18", - "@vue/runtime-dom": "3.4.18", - "@vue/server-renderer": "3.4.18", - "@vue/shared": "3.4.18" + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.19.tgz", + "integrity": "sha512-W/7Fc9KUkajFU8dBeDluM4sRGc/aa4YJnOYck8dkjgZoXtVsn3OeTGni66FV1l3+nvPA7VBFYtPioaGKUmEADw==", + "dependencies": { + "@vue/compiler-dom": "3.4.19", + "@vue/compiler-sfc": "3.4.19", + "@vue/runtime-dom": "3.4.19", + "@vue/server-renderer": "3.4.19", + "@vue/shared": "3.4.19" }, "peerDependencies": { "typescript": "*" diff --git a/src/components/NavbarTop.vue b/src/components/NavbarTop.vue index 0cb939d9815cc761f00d5390e64aa65ab9ccace3..4a85939c356b18e119d4a9c9d858be44a1df86a7 100644 --- a/src/components/NavbarTop.vue +++ b/src/components/NavbarTop.vue @@ -189,7 +189,7 @@ watch( <router-link class="dropdown-item" :to="{ name: 'resource-review' }" - >Review + >Reviews </router-link> </li> </ul> diff --git a/src/components/modals/BootstrapModal.vue b/src/components/modals/BootstrapModal.vue index 7f3a55ec324e5f73e427cdde92a120ba705de49d..cf6664ba3194bd13886f557cf8df54ca29f994d9 100644 --- a/src/components/modals/BootstrapModal.vue +++ b/src/components/modals/BootstrapModal.vue @@ -36,7 +36,7 @@ const modalSizeClass = computed<string>(() => { <div class="modal-title fs-5" :id="modalLabel"> <slot name="header" /> </div> - <div> + <div class="d-flex align-items-center"> <slot name="extra-button" /> <button type="button" diff --git a/src/components/object-storage/modals/BucketDetailModal.vue b/src/components/object-storage/modals/BucketDetailModal.vue index 49eef5918ab7e1e2f26d7a49e876d9a95f386be1..3ceebc6ed78d77aee57dcb89986b87c124abadf2 100644 --- a/src/components/object-storage/modals/BucketDetailModal.vue +++ b/src/components/object-storage/modals/BucketDetailModal.vue @@ -15,6 +15,7 @@ const props = defineProps<{ :modalId="modalID" :static-backdrop="false" modal-label="Bucket Detail Modal" + size-modifier="lg" > <template v-slot:header> <h4> diff --git a/src/components/parameter-schema/ParameterSchemaFormComponent.vue b/src/components/parameter-schema/ParameterSchemaFormComponent.vue index c100465a47a38563f851b23c60ce74d9e212aa4c..4048dacc6c9dd8031c6ffeab933946c22fac5454 100644 --- a/src/components/parameter-schema/ParameterSchemaFormComponent.vue +++ b/src/components/parameter-schema/ParameterSchemaFormComponent.vue @@ -180,7 +180,6 @@ function startWorkflow() { errorToast?.hide(); formState.validated = true; formState.errorType = undefined; - console.log(formState.formInput); if (launchForm.value?.checkValidity()) { const schemaValid = validateSchema(formState.formInput); diff --git a/src/components/workflows/WorkflowWithVersionsCard.vue b/src/components/workflows/WorkflowWithVersionsCard.vue index 3def45d055d420f97e23571f1c666704ef63fde8..e0a960a263aab9a7839bc3734d99a2ac7b03c018 100644 --- a/src/components/workflows/WorkflowWithVersionsCard.vue +++ b/src/components/workflows/WorkflowWithVersionsCard.vue @@ -125,39 +125,7 @@ onMounted(() => { /> <span>{{ props.workflow.name }}</span> </div> - <div> - <router-link - :to="{ - name: 'workflows-clowminfo', - query: { - workflow_id: workflow.workflow_id, - workflow_version_id: sortedVersions(props.workflow.versions)[0] - ?.workflow_version_id, - }, - }" - class="btn btn-primary" - >Clowm - </router-link> - <button - type="button" - class="btn btn-outline-info me-2" - @click="emit('workflow-update-credentials-click', props.workflow)" - :class="{ disabled: props.loading }" - data-bs-toggle="modal" - data-bs-target="#updateWorkflowCredentialsModal" - > - <font-awesome-icon icon="fa-solid fa-key" /> - </button> - <button - type="button" - class="btn btn-outline-danger me-2" - @click="emit('workflow-delete-click', props.workflow)" - :class="{ disabled: props.loading }" - data-bs-toggle="modal" - data-bs-target="#deleteWorkflowModal" - > - <font-awesome-icon icon="fa-solid fa-trash" /> - </button> + <div class="btn-group"> <button type="button" class="btn btn-success" @@ -168,6 +136,56 @@ onMounted(() => { > Update </button> + <button + type="button" + class="btn btn-success dropdown-toggle dropdown-toggle-split" + data-bs-toggle="dropdown" + aria-expanded="false" + > + <span class="visually-hidden">Toggle Dropdown</span> + </button> + <ul class="dropdown-menu z-3"> + <li> + <a + class="dropdown-item" + href="#" + @click.prevent=" + emit('workflow-update-credentials-click', props.workflow) + " + :class="{ disabled: props.loading }" + data-bs-toggle="modal" + data-bs-target="#updateWorkflowCredentialsModal" + >Update Credentials</a + > + </li> + <li> + <router-link + :to="{ + name: 'workflows-clowminfo', + query: { + workflow_id: workflow.workflow_id, + workflow_version_id: sortedVersions( + props.workflow.versions, + )[0]?.workflow_version_id, + }, + }" + class="btn btn-primary dropdown-item" + >Add Metadata + </router-link> + </li> + <li> + <a + class="dropdown-item text-danger" + href="#" + @click.prevent="emit('workflow-delete-click', props.workflow)" + :class="{ disabled: props.loading }" + data-bs-toggle="modal" + data-bs-target="#deleteWorkflowModal" + >Delete + <font-awesome-icon icon="fa-solid fa-trash" class="ms-2" /> + </a> + </li> + </ul> </div> </div> <p class="card-text" :class="{ 'text-truncate': truncateDescription }"> @@ -343,7 +361,6 @@ onMounted(() => { } .card-hover:hover { - transform: translate(0, -5px); box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; } diff --git a/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue b/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue index 5da2ca963e29050db358258498879e0ea1eb3dad..43f6a6129bdd87084aee581def2f23a99bf85636 100644 --- a/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue +++ b/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue @@ -139,6 +139,7 @@ onMounted(() => { :modalId="modalID" :static-backdrop="true" modal-label="Update Workflow Version Icon Modal" + size-modifier="lg" v-on="{ 'hidden.bs.modal': modalClosed }" > <template #header> @@ -147,7 +148,7 @@ onMounted(() => { </template> <template #extra-button v-if="props.workflow.private"> <button - class="btn delete-icon" + class="btn delete-icon px-1" data-bs-toggle="modal" :data-bs-target="'#delete-credentials-modal' + randomIDSuffix" > diff --git a/src/components/workflows/modals/UpdateWorkflowModal.vue b/src/components/workflows/modals/UpdateWorkflowModal.vue index f1510662ccea47672de4f55bbd86d0ea007a6354..e47ea0c79939bbfa43e58c5e984e3816d79473aa 100644 --- a/src/components/workflows/modals/UpdateWorkflowModal.vue +++ b/src/components/workflows/modals/UpdateWorkflowModal.vue @@ -316,6 +316,7 @@ onMounted(() => { :static-backdrop="true" modal-label="Update Workflow Modal" v-on="{ 'hidden.bs.modal': modalClosed }" + size-modifier="lg" > <template #header> Update Workflow diff --git a/src/views/workflows/CreateClowmInfoView.vue b/src/views/workflows/CreateClowmInfoView.vue index 0c2c089514946dac78011cb384acec08593870d5..8137d54631b55a798489e39194196d132c6049b5 100644 --- a/src/views/workflows/CreateClowmInfoView.vue +++ b/src/views/workflows/CreateClowmInfoView.vue @@ -1,13 +1,6 @@ <script setup lang="ts"> import CopyToClipboardIcon from "@/components/CopyToClipboardIcon.vue"; -import { - computed, - onMounted, - onBeforeMount, - reactive, - watch, - onUnmounted, -} from "vue"; +import { computed, onMounted, reactive, watch } from "vue"; import { createDownloadUrl } from "@/utils/DownloadJson"; import type { ClowmInfo } from "@/types/ClowmInfo"; import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; @@ -70,8 +63,10 @@ const downloadUrl = computed<string>(() => watch( () => workflowRepository.documentationFiles[props.workflow_version_id ?? ""], - (newVal) => { - updateParameterPools(newVal); + (newVal, old) => { + if (newVal != old && newVal?.parameter_schema != undefined) { + updateParameterPools(newVal); + } }, { deep: true, @@ -91,7 +86,7 @@ function updateParameterPools(newVal?: Record<DocumentationEnum, any>) { infoState.exampleParameters = undefined; infoState.resourceParameters = undefined; } - if (newVal?.clowm_info) { + if (newVal?.clowm_info && Object.keys(newVal.clowm_info).length > 0) { Object.assign(infoState, JSON.parse(JSON.stringify(newVal.clowm_info))); parameterPools.input = parameterPools.input.filter( (param) => !infoState.inputParameters.includes(param), @@ -137,39 +132,103 @@ function removeDoi(index: number) { infoState.dois?.splice(index, 1); } -onBeforeMount(() => { - if (props.workflow_id && props.workflow_version_id) { - workflowRepository.fetchWorkflowDocumentation( - props.workflow_id, - props.workflow_version_id, - DocumentationEnum.PARAMETER_SCHEMA, - ); - workflowRepository.fetchWorkflowDocumentation( - props.workflow_id, - props.workflow_version_id, - DocumentationEnum.CLOWM_INFO, - ); +function addExampleParameter(param: string, index: number) { + if (infoState.exampleParameters == undefined) { + infoState.exampleParameters = {}; } -}); + parameterPools.examples.splice(index, 1); + switch (getParameterType(param)) { + case "integer": { + infoState.exampleParameters[param] = 0; + break; + } + case "number": { + infoState.exampleParameters[param] = 0; + break; + } + case "boolean": { + infoState.exampleParameters[param] = true; + break; + } + case "string": { + infoState.exampleParameters[param] = + parameterSchema.value[param]?.["enum"]?.[0] ?? ""; + break; + } + default: { + infoState.exampleParameters[param] = ""; + break; + } + } +} + +function deleteExampleParameter(param: string) { + delete infoState.exampleParameters?.[param]; + parameterPools.examples.push(param); + if (Object.keys(infoState.exampleParameters ?? {}).length === 0) { + infoState.exampleParameters = undefined; + } +} onMounted(() => { if (props.workflow_id && props.workflow_version_id) { - updateParameterPools( - workflowRepository.documentationFiles[props.workflow_version_id], - ); + Promise.all([ + workflowRepository.fetchWorkflowDocumentation( + props.workflow_id, + props.workflow_version_id, + DocumentationEnum.PARAMETER_SCHEMA, + ), + workflowRepository.fetchWorkflowDocumentation( + props.workflow_id, + props.workflow_version_id, + DocumentationEnum.CLOWM_INFO, + ), + ]).finally(() => { + updateParameterPools( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + workflowRepository.documentationFiles[props.workflow_version_id!], + ); + }); } }); - -onUnmounted(() => { - console.log("Unmounted"); -}); </script> <template> <div class="row border-bottom mb-4"> - <h2 class="mb-2">Create <code>clowm_info.json</code></h2> + <h2 class="mb-2">Enhance your Workflow</h2> + </div> + <div> + Enhance your Workflow with CloWM: + <ul> + <li> + Maximize the potential of your workflow within CloWM by incorporating a + <code>clowm_info.json</code> file directly into your repository's root + directory. This simple addition empowers you to provide comprehensive + details about your workflow's parameters and overall structure, + enhancing its usability and user experience. + </li> + <li> + Customize Parameters: Infuse semantic meaning into various parameters, + enriching the understanding and functionality of your workflow. + </li> + <li> + Publication Linking: Seamlessly integrate a DOI link to your + publication, facilitating easy access to additional resources and + information. + </li> + <li> + Experience Enhanced Workflow: Elevate your workflow's presentation on + the CloWM platform by ensuring essential information is readily + available to users. + </li> + </ul> </div> - <div class="accordion mb-2" id="clowmInfoAccordion"> + <p> + Unlock the full potential of your workflow in CloWM by exploring the tabs + below for guidance on creating and implementing the + <code>clowm_info.json</code> file. + </p> + <div class="accordion mb-4" id="clowmInfoAccordion"> <div class="accordion-item"> <h2 class="accordion-header"> <button @@ -189,6 +248,11 @@ onUnmounted(() => { data-bs-parent="#clowmInfoAccordion" > <div class="accordion-body"> + <p> + <b>Designate Parameters as Input Files</b>: Assign semantic meaning + to parameters by dragging them from the left side to the right side + to designate them as input files. + </p> <draggable-lists :left-list="parameterPools.input" :right-list="infoState.inputParameters" @@ -218,6 +282,11 @@ onUnmounted(() => { data-bs-parent="#clowmInfoAccordion" > <div class="accordion-body"> + <p> + <b>Designate Parameters as Output</b>: Assign semantic meaning to + parameters by dragging them from the left side to the right side to + designate them as output files. + </p> <draggable-lists :left-list="parameterPools.output" :right-list="infoState.outputParameters" @@ -247,6 +316,12 @@ onUnmounted(() => { data-bs-parent="#clowmInfoAccordion" > <div class="accordion-body"> + <p> + <b>Designate Parameters as Resources</b>: Drag parameters from the + left side to the right side to imbue them with semantic meaning as + resource parameters. CloWM automatically generates a specialized + form input for users to configure these parameters. + </p> <button v-if="infoState.resourceParameters == undefined" type="button" @@ -285,131 +360,122 @@ onUnmounted(() => { data-bs-parent="#clowmInfoAccordion" > <div class="accordion-body"> - <button - v-if="infoState.exampleParameters == undefined" - type="button" - class="btn btn-primary" - @click="infoState.exampleParameters = {}" + <p> + <b>Enhance Workflow Testing</b>: Incorporate example parameters + using publicly available test data. Easily achieve this by including + a sample dataset in your Git repository and linking its URL as the + input parameter. + </p> + <p> + <b>Guidance on Parameter Setting</b>: Avoid specifying parameters + that define output locations or resource paths, as these are heavily + dependent on the user or execution environment. + </p> + <div + class="d-flex flex-wrap overflow-y-scroll p-1 border rounded border-dashed mb-2" + style="max-height: 30vh" > - I have Examples - </button> - <template v-else> <div - class="d-flex flex-wrap overflow-y-scroll p-1 border rounded border-dashed mb-2" - style="max-height: 30vh" + class="w-fit border px-2 rounded cursor-pointer m-1 parameter-container" + v-for="(param, index) in parameterPools.examples" + :key="param" + @click="addExampleParameter(param, index)" > - <div - class="w-fit border px-2 rounded cursor-pointer m-1 parameter-container" - v-for="(param, index) in parameterPools.examples" + {{ param }} + </div> + </div> + <table class="table table-bordered"> + <thead> + <tr> + <th scope="col"><b>Parameter</b></th> + <th scope="col"><b>Value</b></th> + </tr> + </thead> + <tbody v-if="infoState.exampleParameters"> + <tr + v-for="param in Object.keys(infoState.exampleParameters)" :key="param" - @click=" - parameterPools.examples.splice(index, 1); - infoState.exampleParameters[param] = ''; - " > - {{ param }} - </div> - </div> - <table class="table table-bordered"> - <thead> - <tr> - <th scope="col"><b>Parameter</b></th> - <th scope="col"><b>Value</b></th> - </tr> - </thead> - <tbody> - <tr - v-for="param in Object.keys(infoState.exampleParameters)" - :key="param" - > - <td style="width: 10%">{{ param }}</td> - <td class="d-flex justify-content-between align-items-center"> - <input - v-if=" - getParameterType(param) === 'number' || - getParameterType(param) === 'integer' - " - type="number" - class="form-control form-control-sm flex-grow" - v-model="infoState.exampleParameters[param]" - :step="getParameterType(param) === 'integer' ? 1 : 0.0001" - :min="parameterSchema[param]['minimum']" - :max="parameterSchema[param]['maximum']" - /> - <div - v-else-if="getParameterType(param) === 'boolean'" - class="flex-grow" - > - <div class="form-check form-check-inline"> - <label - class="form-check-label" - :for="'trueOption' + param.replace(/\./g, '')" - >True</label - > - <input - class="form-check-input" - type="radio" - :name=" - 'inlineRadioOptions' + param.replace(/\./g, '') - " - :id="'trueOption' + param.replace(/\./g, '')" - :value="true" - v-model="infoState.exampleParameters[param]" - /> - </div> - <div class="form-check form-check-inline"> - <input - class="form-check-input" - type="radio" - :name=" - 'inlineRadioOptions' + param.replace(/\./g, '') - " - :id="'falseOption' + param.replace(/\./g, '')" - :value="false" - v-model="infoState.exampleParameters[param]" - /> - <label - class="form-check-label" - :for="'falseOption' + param.replace(/\./g, '')" - >False</label - > - </div> + <td style="width: 10%">{{ param }}</td> + <td class="d-flex justify-content-between align-items-center"> + <input + v-if=" + getParameterType(param) === 'number' || + getParameterType(param) === 'integer' + " + type="number" + class="form-control form-control-sm flex-grow" + v-model="infoState.exampleParameters[param]" + :step="getParameterType(param) === 'integer' ? 1 : 0.0001" + :min="parameterSchema[param]['minimum']" + :max="parameterSchema[param]['maximum']" + /> + <div + v-else-if="getParameterType(param) === 'boolean'" + class="flex-grow" + > + <div class="form-check form-check-inline"> + <label + class="form-check-label" + :for="'trueOption' + param.replace(/\./g, '')" + >True</label + > + <input + class="form-check-input" + type="radio" + :name="'inlineRadioOptions' + param.replace(/\./g, '')" + :id="'trueOption' + param.replace(/\./g, '')" + :value="true" + v-model="infoState.exampleParameters[param]" + /> </div> - <select - v-else-if="parameterSchema[param]?.['enum']" - class="form-select form-select-sm flex-grow" - v-model="infoState.exampleParameters[param]" - > - <option - v-for="option in parameterSchema[param]?.['enum']" - :key="option" - :value="option" + <div class="form-check form-check-inline"> + <input + class="form-check-input" + type="radio" + :name="'inlineRadioOptions' + param.replace(/\./g, '')" + :id="'falseOption' + param.replace(/\./g, '')" + :value="false" + v-model="infoState.exampleParameters[param]" + /> + <label + class="form-check-label" + :for="'falseOption' + param.replace(/\./g, '')" + >False</label > - {{ option }} - </option> - </select> - <input - v-else - type="text" - class="form-control form-control-sm flex-grow" - v-model="infoState.exampleParameters[param]" - :pattern="parameterSchema[param]?.['pattern']" - /> - <button - type="button" - class="btn btn-outline-danger btn-sm ms-2" - @click=" - delete infoState.exampleParameters[param]; - parameterPools.examples.push(param); - " + </div> + </div> + <select + v-else-if="parameterSchema[param]?.['enum']" + class="form-select form-select-sm flex-grow" + v-model="infoState.exampleParameters[param]" + > + <option + v-for="option in parameterSchema[param]?.['enum']" + :key="option" + :value="option" > - Remove - </button> - </td> - </tr> - </tbody> - </table> - </template> + {{ option }} + </option> + </select> + <input + v-else + type="text" + class="form-control form-control-sm flex-grow" + v-model="infoState.exampleParameters[param]" + :pattern="parameterSchema[param]?.['pattern']" + /> + <button + type="button" + class="btn btn-outline-danger btn-sm ms-2" + @click="deleteExampleParameter(param)" + > + Remove + </button> + </td> + </tr> + </tbody> + </table> </div> </div> </div> @@ -432,6 +498,11 @@ onUnmounted(() => { data-bs-parent="#clowmInfoAccordion" > <div class="accordion-body"> + <p> + <b>Share Publications Easily</b>: Include the DOI for your + workflow's related publications and watch as the generated links + seamlessly appear on your workflow's dedicated page. + </p> <button type="button" class="btn btn-primary" @click="addDoi"> Add DOI </button> @@ -456,13 +527,17 @@ onUnmounted(() => { style="max-width: 400px" /> <div class="align-self-center"> - Link: + DOI Link: <a :href="'https://doi.org/' + doi" target="_blank" class="align-self-center" - >{{ doi }}</a - > + >https://doi.org/{{ doi }} + <font-awesome-icon + icon="fa-solid fa-arrow-up-right-from-square" + class="ms-1" + /> + </a> </div> </div> </div> @@ -470,7 +545,12 @@ onUnmounted(() => { </div> </div> </div> + <h5>Generated <code>clowm_info.json</code></h5> <pre class="rounded w-100"><code>{{ infoState }}</code></pre> + <p> + Add this file to your Git repository, commit and push your changes and + register the new workflow version in CloWM + </p> <copy-to-clipboard-icon button :text="infoStateString" /> <a class="btn btn-primary ms-2" :href="downloadUrl" download="clowm_info.json" >Download to file