diff --git a/package-lock.json b/package-lock.json index d76765ea694c409d36cf95da85786ca88b79af43..c68aacf912c5c9f868404b79a09b5c97a29a891e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@aws-sdk/client-s3": "^3.440.0", "@aws-sdk/lib-storage": "^3.440.0", "@aws-sdk/s3-request-presigner": "^3.440.0", - "@fortawesome/fontawesome-free": "~6.4.2", + "@fortawesome/fontawesome-free": "~6.5.0", "@popperjs/core": "~2.11.8", "ajv": "~8.12.0", "bootstrap": "~5.3.0", @@ -48,8 +48,8 @@ "eslint-plugin-vue": "~9.19.0", "highlight.js": "^11.9.0", "npm-run-all": "~4.1.5", - "openapi-typescript-codegen": "^0.26.0", - "prettier": "~3.0.3", + "openapi-typescript-codegen": "^0.27.0", + "prettier": "~3.2.0", "rollup-plugin-node-polyfills": "~0.2.1", "sass": "~1.66.1", "typescript": "~5.1.6", @@ -67,13 +67,13 @@ } }, "node_modules/@apidevtools/json-schema-ref-parser": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.1.0.tgz", - "integrity": "sha512-g/VW9ZQEFJAOwAyUb8JFf7MLiLy2uEB4rU270rGzDwICxnxMlPy0O11KVePSgS36K1NI29gSlK84n5INGhd4Ag==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-10.1.0.tgz", + "integrity": "sha512-3e+viyMuXdrcK8v5pvP+SDoAQ77FH6OyRmuK48SZKmdHJRFm87RsSs8qm6kP39a/pOPURByJw+OXzQIqcfmKtA==", "dev": true, "dependencies": { "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.13", + "@types/json-schema": "^7.0.11", "@types/lodash.clonedeep": "^4.5.7", "js-yaml": "^4.1.0", "lodash.clonedeep": "^4.5.0" @@ -211,16 +211,16 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@aws-sdk/client-s3": { - "version": "3.502.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.502.0.tgz", - "integrity": "sha512-/xanrBWjDnvz1tVtTWhNcp68N8+3jrVc1RFdvbZqLs6uweCQM56xRCmUEel/rA6oBhKBiuGn51MdjHXs+gGhUA==", + "version": "3.504.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.504.0.tgz", + "integrity": "sha512-J8xPsnk7EDwalFSaDxPFNT2+x99nG2uQTpsLXAV3bWbT1nD/JZ+fase9GqxM11v6WngzqRvTQg26ljMn5hQSKA==", "dependencies": { "@aws-crypto/sha1-browser": "3.0.0", "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.502.0", + "@aws-sdk/client-sts": "3.504.0", "@aws-sdk/core": "3.496.0", - "@aws-sdk/credential-provider-node": "3.502.0", + "@aws-sdk/credential-provider-node": "3.504.0", "@aws-sdk/middleware-bucket-endpoint": "3.502.0", "@aws-sdk/middleware-expect-continue": "3.502.0", "@aws-sdk/middleware-flexible-checksums": "3.502.0", @@ -326,13 +326,13 @@ } }, "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.502.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.502.0.tgz", - "integrity": "sha512-Yc9tZqTOMWtdgpkrdjKShgWb9oKNsFQrItfoiN1xWDllaFFRPi2KTiZiR0AbSTrNasJy13d210DOxrIdte+kWQ==", + "version": "3.504.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.504.0.tgz", + "integrity": "sha512-ODA33/nm2srhV08EW0KZAP577UgV0qjyr7Xp2yEo8MXWL4ZqQZprk1c+QKBhjr4Djesrm0VPmSD/np0mtYP68A==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.502.0", + "@aws-sdk/client-sts": "3.504.0", "@aws-sdk/core": "3.496.0", "@aws-sdk/middleware-host-header": "3.502.0", "@aws-sdk/middleware-logger": "3.502.0", @@ -374,13 +374,13 @@ "node": ">=14.0.0" }, "peerDependencies": { - "@aws-sdk/credential-provider-node": "*" + "@aws-sdk/credential-provider-node": "^3.504.0" } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.502.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.502.0.tgz", - "integrity": "sha512-0q08gsvn6nuRqjK+i/e30PT/t7vvYwmGJS0PhJikZWv5yRDNSUxSYG0uDwKSbLDzmc2UX5+mLeyjPHlL4hbGlA==", + "version": "3.504.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.504.0.tgz", + "integrity": "sha512-IESs8FkL7B/uY+ml4wgoRkrr6xYo4PizcNw6JX17eveq1gRBCPKeGMjE6HTDOcIYZZ8rqz/UeuH3JD4UhrMOnA==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -426,7 +426,7 @@ "node": ">=14.0.0" }, "peerDependencies": { - "@aws-sdk/credential-provider-node": "*" + "@aws-sdk/credential-provider-node": "^3.504.0" } }, "node_modules/@aws-sdk/core": { @@ -459,16 +459,35 @@ "node": ">=14.0.0" } }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.503.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.503.1.tgz", + "integrity": "sha512-rTdlFFGoPPFMF2YjtlfRuSgKI+XsF49u7d98255hySwhsbwd3Xp+utTTPquxP+CwDxMHbDlI7NxDzFiFdsoZug==", + "dependencies": { + "@aws-sdk/types": "3.502.0", + "@smithy/fetch-http-handler": "^2.4.1", + "@smithy/node-http-handler": "^2.3.1", + "@smithy/property-provider": "^2.1.1", + "@smithy/protocol-http": "^3.1.1", + "@smithy/smithy-client": "^2.3.1", + "@smithy/types": "^2.9.1", + "@smithy/util-stream": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.502.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.502.0.tgz", - "integrity": "sha512-1wB/escbspUY6uRDEMp9AMMyypUSyuQ0AMO1yQNtXviV8cPf+CuRbqP/UVnimHO1RuX0n5BmjDVVjUIEU6kuGA==", + "version": "3.504.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.504.0.tgz", + "integrity": "sha512-ODICLXfr8xTUd3wweprH32Ge41yuBa+u3j0JUcLdTUO1N9ldczSMdo8zOPlP0z4doqD3xbnqMkjNQWgN/Q+5oQ==", "dependencies": { - "@aws-sdk/client-sts": "3.502.0", + "@aws-sdk/client-sts": "3.504.0", "@aws-sdk/credential-provider-env": "3.502.0", "@aws-sdk/credential-provider-process": "3.502.0", - "@aws-sdk/credential-provider-sso": "3.502.0", - "@aws-sdk/credential-provider-web-identity": "3.502.0", + "@aws-sdk/credential-provider-sso": "3.504.0", + "@aws-sdk/credential-provider-web-identity": "3.504.0", "@aws-sdk/types": "3.502.0", "@smithy/credential-provider-imds": "^2.2.1", "@smithy/property-provider": "^2.1.1", @@ -481,15 +500,16 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.502.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.502.0.tgz", - "integrity": "sha512-qg71UpYeFrjhu5hD+vdRqZ+EYFB11BeszsbfEJGaHhOMHmmTHNBaDAexW+bUnJSXcJL0a8vniCvca+rElbcAHQ==", + "version": "3.504.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.504.0.tgz", + "integrity": "sha512-6+V5hIh+tILmUjf2ZQWQINR3atxQVgH/bFrGdSR/sHSp/tEgw3m0xWL3IRslWU1e4/GtXrfg1iYnMknXy68Ikw==", "dependencies": { "@aws-sdk/credential-provider-env": "3.502.0", - "@aws-sdk/credential-provider-ini": "3.502.0", + "@aws-sdk/credential-provider-http": "3.503.1", + "@aws-sdk/credential-provider-ini": "3.504.0", "@aws-sdk/credential-provider-process": "3.502.0", - "@aws-sdk/credential-provider-sso": "3.502.0", - "@aws-sdk/credential-provider-web-identity": "3.502.0", + "@aws-sdk/credential-provider-sso": "3.504.0", + "@aws-sdk/credential-provider-web-identity": "3.504.0", "@aws-sdk/types": "3.502.0", "@smithy/credential-provider-imds": "^2.2.1", "@smithy/property-provider": "^2.1.1", @@ -517,12 +537,12 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.502.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.502.0.tgz", - "integrity": "sha512-/2Nyvo+cWQpH283lmZBimTJ9JDhES9FzQUkhUXZgxQo3Ez4sguLVi2V9xoFFyG0cMff5fuNivdKHfj4FeMGjZw==", + "version": "3.504.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.504.0.tgz", + "integrity": "sha512-4MgH2or2SjPzaxM08DCW+BjaX4DSsEGJlicHKmz6fh+w9JmLh750oXcTnbvgUeVz075jcs6qTKjvUcsdGM/t8Q==", "dependencies": { "@aws-sdk/client-sso": "3.502.0", - "@aws-sdk/token-providers": "3.502.0", + "@aws-sdk/token-providers": "3.504.0", "@aws-sdk/types": "3.502.0", "@smithy/property-provider": "^2.1.1", "@smithy/shared-ini-file-loader": "^2.3.1", @@ -534,11 +554,11 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.502.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.502.0.tgz", - "integrity": "sha512-veBAjDqjMMgA2Qxxf9ywDfHYLeJpaeHWLWCQ9XCHwJJ6ZIGWmAZPTq3he/UMr5JIQXooIccqqyqXMDIXPenXpA==", + "version": "3.504.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.504.0.tgz", + "integrity": "sha512-L1ljCvGpIEFdJk087ijf2ohg7HBclOeB1UgBxUBBzf4iPRZTQzd2chGaKj0hm2VVaXz7nglswJeURH5PFcS5oA==", "dependencies": { - "@aws-sdk/client-sts": "3.502.0", + "@aws-sdk/client-sts": "3.504.0", "@aws-sdk/types": "3.502.0", "@smithy/property-provider": "^2.1.1", "@smithy/types": "^2.9.1", @@ -549,9 +569,9 @@ } }, "node_modules/@aws-sdk/lib-storage": { - "version": "3.502.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.502.0.tgz", - "integrity": "sha512-0wz5OoXtpfrNNUQnZPxKD0tqNfxeJbxNQBSZtGtCoCihBqmKE/Oui85ptrdLyrjjTc2b+Hxu7xfyGdU2ILWBYA==", + "version": "3.504.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.504.0.tgz", + "integrity": "sha512-A2h/yHy+2JFhqiCL1vfSlKxLRIZyyQte58O8s0yAV/TDt7ElzeXMTVtCUvhcOrnjtdHKfh4F36jeZSh1ja/9HA==", "dependencies": { "@smithy/abort-controller": "^2.1.1", "@smithy/middleware-endpoint": "^2.4.1", @@ -752,9 +772,9 @@ } }, "node_modules/@aws-sdk/s3-request-presigner": { - "version": "3.502.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.502.0.tgz", - "integrity": "sha512-3RxMt3kZ9Dq/m+QNFTNtUlzJQXRlu2iK7NBSUv2HXT0edlVE3D8W4ILY9GQzaCCtnpy9OSsv0nkSetWi65v9yQ==", + "version": "3.504.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.504.0.tgz", + "integrity": "sha512-5FxVdRufiFLSUDJ/Qul5JFPHjhFFzo+C6u53bzbi7gaSshA6lLLhJ9KbVk2LmKE1mTR+nh2+JebI6y+3njtkzw==", "dependencies": { "@aws-sdk/signature-v4-multi-region": "3.502.0", "@aws-sdk/types": "3.502.0", @@ -786,11 +806,11 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.502.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.502.0.tgz", - "integrity": "sha512-RQgMgIXYlSf0xGl6EUeD+pqIPBlb7e29dbqHOBFc66hJVYUC2ULZX7Y+jLvcGIEaMiIaTPyvntZRFip+U+9hag==", + "version": "3.504.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.504.0.tgz", + "integrity": "sha512-YIJWWsZi2ClUiILS1uh5L6VjmCUSTI6KKMuL9DkGjYqJ0aI6M8bd8fT9Wm7QmXCyjcArTgr/Atkhia4T7oKvzQ==", "dependencies": { - "@aws-sdk/client-sso-oidc": "3.502.0", + "@aws-sdk/client-sso-oidc": "3.504.0", "@aws-sdk/types": "3.502.0", "@smithy/property-provider": "^2.1.1", "@smithy/shared-ini-file-loader": "^2.3.1", @@ -1419,9 +1439,9 @@ } }, "node_modules/@fortawesome/fontawesome-free": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.2.tgz", - "integrity": "sha512-m5cPn3e2+FDCOgi1mz0RexTUvvQibBebOUlUlW0+YrMjDTPkiJ6VTKukA1GRsvRw+12KyJndNjj0O4AgTxm2Pg==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.1.tgz", + "integrity": "sha512-CNy5vSwN3fsUStPRLX7fUYojyuzoEMSXPl7zSLJ8TgtRfjv24LOnOWKT2zYwaHZCJGkdyRnTmstR0P+Ah503Gw==", "hasInstallScript": true, "engines": { "node": ">=6" @@ -2396,9 +2416,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.10.tgz", - "integrity": "sha512-IZD8kAM02AW1HRDTPOlz3npFava678pr8Ie9Vp8uRhBROXAv8MXT2pCnGZZAKYdromsNQLHQcfWQ6EOatVLtqA==", + "version": "18.19.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.13.tgz", + "integrity": "sha512-kgnbRDj8ioDyGxoiaXsiu1Ybm/K14ajCgMOkwiqpHrnF7d7QiYRoRqHIpglMMs3DwXinlK4qJ8TZGlj4hfleJg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -2699,9 +2719,9 @@ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "node_modules/@vue/compiler-sfc/node_modules/magic-string": { - "version": "0.30.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", - "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "version": "0.30.6", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.6.tgz", + "integrity": "sha512-n62qCLbPjNjyo+owKtveQxZFZTBm+Ms6YoGD23Wew6Vw337PElFNifQpknPruVRQV57kVShPnLGo9vWxVhpPvA==", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, @@ -2989,9 +3009,9 @@ "dev": true }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", + "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==", "dev": true, "engines": { "node": ">= 0.4" @@ -4395,9 +4415,9 @@ ] }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -5239,12 +5259,12 @@ } }, "node_modules/openapi-typescript-codegen": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/openapi-typescript-codegen/-/openapi-typescript-codegen-0.26.0.tgz", - "integrity": "sha512-5D45xawBHu9efxaDdioeZAfAQGxE0v12aNk24dTymNHRA75A6bFP8tKUAIzx8+AKWN7d/S9RWD87yVWhlFLhDA==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/openapi-typescript-codegen/-/openapi-typescript-codegen-0.27.0.tgz", + "integrity": "sha512-QyQEod/vuel3zfnTRC3GgmYsqLPSBzB2OL4ojMYjO9hJmfYW02T+7tbQWEnuqWdhh2KSOBf3L8h59vLStr6vwA==", "dev": true, "dependencies": { - "@apidevtools/json-schema-ref-parser": "^11.1.0", + "@apidevtools/json-schema-ref-parser": "^10.1.0", "camelcase": "^6.3.0", "commander": "^11.1.0", "fs-extra": "^11.2.0", @@ -5438,9 +5458,9 @@ } }, "node_modules/pinia/node_modules/vue-demi": { - "version": "0.14.6", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", - "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", "hasInstallScript": true, "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", @@ -5512,9 +5532,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", + "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" diff --git a/package.json b/package.json index f1334915fbe36a246e49a509047a78ec69bb156a..48e0abaae2d914245cfd26074085b57924789922 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "dev": "vite", "build": "run-p type-check build-only", - "preview": "vite preview --port 4173", + "preview": "vite preview --port 5173", "build-only": "vite build", "type-check": "vue-tsc --noEmit", "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", @@ -19,7 +19,7 @@ "@aws-sdk/client-s3": "^3.440.0", "@aws-sdk/lib-storage": "^3.440.0", "@aws-sdk/s3-request-presigner": "^3.440.0", - "@fortawesome/fontawesome-free": "~6.4.2", + "@fortawesome/fontawesome-free": "~6.5.0", "@popperjs/core": "~2.11.8", "ajv": "~8.12.0", "bootstrap": "~5.3.0", @@ -55,8 +55,8 @@ "eslint-plugin-vue": "~9.19.0", "highlight.js": "^11.9.0", "npm-run-all": "~4.1.5", - "openapi-typescript-codegen": "^0.26.0", - "prettier": "~3.0.3", + "openapi-typescript-codegen": "^0.27.0", + "prettier": "~3.2.0", "rollup-plugin-node-polyfills": "~0.2.1", "sass": "~1.66.1", "typescript": "~5.1.6", diff --git a/src/App.vue b/src/App.vue index c04004c65b40a005adc33c84e624b26e0087440e..5d537e2a7205226dccc4df5e617a691914a32ed8 100644 --- a/src/App.vue +++ b/src/App.vue @@ -54,7 +54,10 @@ onBeforeMount(() => { to.name !== "login" ) { // redirect the user to the login page and preserve query params for login error message - return { name: "login", query: { ...to.query, return_path: encodeURI(to.path) } }; + return { + name: "login", + query: { ...to.query, return_path: encodeURI(to.path) }, + }; } else if ( to.meta.requiresDeveloperRole && !(store.workflowDev || store.admin) diff --git a/src/components/BootstrapToast.vue b/src/components/BootstrapToast.vue index 02b92fa3213f8d2e33e508645718abd4a6cadea4..e664cae362f1db0d35658f236b44d9c30f8f92b8 100644 --- a/src/components/BootstrapToast.vue +++ b/src/components/BootstrapToast.vue @@ -8,7 +8,7 @@ const props = defineProps({ }); const colorClassName = computed<string>(() => { - return "text-bg-" + props.colorClass; + return `text-bg-${props.colorClass}`; }); </script> @@ -23,31 +23,21 @@ const colorClassName = computed<string>(() => { data-bs-autohide="true" :id="props.toastId" > - <div v-if="slots.body" class="toast-header" :class="colorClassName"> - <div class="me-auto"> - <slot></slot> + <div class="toast-body"> + <div class="d-flex justify-content-between fs-6"> + <div class="flex-fill"> + <slot></slot> + </div> + <button + type="button" + class="btn-close btn-close-white me-2" + data-bs-dismiss="toast" + aria-label="Close" + ></button> </div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - <div v-else class="d-flex"> - <div class="toast-body"> - <slot></slot> + <div class="mt-2 pt-2 border-top" v-if="slots.body"> + <slot name="body"></slot> </div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - - <div class="toast-body" v-if="slots.body"> - <slot name="body"></slot> </div> </div> </Teleport> diff --git a/src/components/parameter-schema/ParameterSchemaFormComponent.vue b/src/components/parameter-schema/ParameterSchemaFormComponent.vue index aed548155d295a5a6e57765799f9626a3661e422..7c3881ca6fdb4a368b94acd15feaaa5352b78ba0 100644 --- a/src/components/parameter-schema/ParameterSchemaFormComponent.vue +++ b/src/components/parameter-schema/ParameterSchemaFormComponent.vue @@ -10,10 +10,13 @@ import { useBucketStore } from "@/stores/buckets"; import { useS3KeyStore } from "@/stores/s3keys"; import BootstrapToast from "@/components/BootstrapToast.vue"; import { useResourceStore } from "@/stores/resources"; +import { useRoute, useRouter } from "vue-router"; const bucketRepository = useBucketStore(); const resourceRepository = useResourceStore(); const keyRepository = useS3KeyStore(); +const router = useRouter(); +const route = useRoute(); // Props // ============================================================================= @@ -27,6 +30,13 @@ const props = defineProps({ allowNotes: { type: Boolean, }, + viewMode: { + type: String, + default: "simple", + validator(value: string) { + return ["simple", "advanced", "expert"].includes(value); + }, + }, }); const emit = defineEmits<{ @@ -74,7 +84,6 @@ const formState = reactive<{ debug_s3_path?: string; provenance_s3_path?: string; errorType?: string; - showHidden: boolean; }>({ formInput: {}, validated: false, @@ -83,7 +92,6 @@ const formState = reactive<{ debug_s3_path: undefined, provenance_s3_path: undefined, errorType: undefined, - showHidden: false, }); // Computed Properties @@ -101,7 +109,7 @@ const navParameterGroups = computed<ParameterGroup[]>(() => { icon: parameterGroups.value[group]["fa_icon"], }; }); - if (!formState.showHidden) { + if (!showHidden.value) { groups = groups.filter( // filter all groups that have only hidden parameters (group) => @@ -111,9 +119,22 @@ const navParameterGroups = computed<ParameterGroup[]>(() => { ).length > 0, ); } + if (!showOptional.value) { + groups = groups.filter( + // filter all groups that have no required parameter + (group) => + ( + (parameterGroups.value[group.group]["required"] as Array<string>) ?? + [] + ).length > 0, + ); + } return groups; }); +const showHidden = computed<boolean>(() => props.viewMode === "expert"); +const showOptional = computed<boolean>(() => props.viewMode !== "simple"); + // Watchers // ============================================================================= watch( @@ -177,6 +198,12 @@ function startWorkflow() { } } +function scroll(selectedAnchor: string) { + document.querySelector(selectedAnchor)?.scrollIntoView({ + behavior: "smooth", + }); +} + // Lifecycle Events // ============================================================================= onMounted(() => { @@ -191,7 +218,7 @@ onMounted(() => { <template> <bootstrap-toast toast-id="workflowExecutionErrorToast" color-class="danger"> - <template>Error starting workflow</template> + <template #default>Error starting workflow</template> <template #body> <template v-if="formState.errorType === 'form'"> Some inputs are not valid. @@ -221,7 +248,8 @@ onMounted(() => { v-if="formState.formInput[groupName]" :parameter-group-name="groupName" :parameter-group="group" - :showHidden="formState.showHidden" + :showHidden="showHidden" + :show-optional="showOptional" /> </template> <div class="card mb-3"> @@ -233,15 +261,21 @@ onMounted(() => { <h5 class="card-title"> General Options about the pipeline execution </h5> - <div v-if="props.allowNotes"> - <code class="bg-secondary-subtle p-2 rounded-top">--notes</code> + <div v-if="props.allowNotes" :hidden="!showOptional"> + <code + class="bg-secondary-subtle p-2 rounded-top border border-secondary" + >--notes</code + > <div class="input-group"> - <span class="input-group-text" id="pipelineNotes"> + <span + class="input-group-text border border-secondary" + id="pipelineNotes" + > <font-awesome-icon icon="fa-solid fa-sticky-note" /> </span> <textarea - class="form-control" - rows="1" + class="form-control border border-secondary" + rows="2" v-model="formState.pipelineNotes" /> </div> @@ -250,11 +284,12 @@ onMounted(() => { > </div> <div> - <code class="bg-secondary-subtle p-2 rounded-top" + <code + class="bg-secondary-subtle p-2 rounded-top border border-secondary" >--logs_s3_path</code > <div class="input-group"> - <span class="input-group-text"> + <span class="input-group-text border border-secondary"> <font-awesome-icon icon="fa-solid fa-folder" /> </span> <parameter-string-input @@ -272,11 +307,12 @@ onMounted(() => { </label> </div> <div> - <code class="bg-secondary-subtle p-2 rounded-top" + <code + class="bg-secondary-subtle p-2 rounded-top border border-secondary" >--provenance_s3_path</code > <div class="input-group"> - <span class="input-group-text"> + <span class="input-group-text border border-secondary"> <font-awesome-icon icon="fa-solid fa-folder" /> </span> <parameter-string-input @@ -294,12 +330,13 @@ onMounted(() => { workflow execution </label> </div> - <div> - <code class="bg-secondary-subtle p-2 rounded-top" + <div :hidden="!showHidden"> + <code + class="bg-secondary-subtle p-2 rounded-top border border-secondary" >--debug_s3_path</code > <div class="input-group"> - <span class="input-group-text"> + <span class="input-group-text border border-secondary"> <font-awesome-icon icon="fa-solid fa-folder" /> </span> <parameter-string-input @@ -345,25 +382,65 @@ onMounted(() => { class="col-3 sticky-top border shadow-sm rounded-1 px-0" style="top: 70px !important; max-height: calc(100vh - 150px)" > - <div class="d-flex pt-2"> - <button - type="submit" - form="launchWorkflowForm" - class="btn btn-success w-50 mx-2" - :disabled="props.loading || !props.schema" + <h5 class="mx-3 mt-2">Parameter View</h5> + <div class="mx-2"> + <div + class="btn-group my-1 w-100" + role="group" + aria-label="Basic radio toggle button group" > - <font-awesome-icon icon="fa-solid fa-rocket" class="me-2" /> - Launch - </button> - <router-link - role="button" - class="btn btn-success w-50 mx-2" - target="_blank" - :to="{ name: 'buckets' }" - > - <font-awesome-icon icon="fa-solid fa-upload" class="me-2" /> - Upload files - </router-link> + <input + type="radio" + class="btn-check w-100" + name="view-mode" + id="view-mode-simple" + autocomplete="off" + :checked="props.viewMode === 'simple'" + @click=" + router.replace({ + query: { viewMode: 'simple' }, + hash: route.hash, + }) + " + /> + <label class="btn btn-outline-primary" for="view-mode-simple" + >Simple</label + > + <input + type="radio" + class="btn-check" + name="view-mode" + id="view-mode-advanced" + autocomplete="off" + :checked="props.viewMode === 'advanced'" + @click=" + router.replace({ + query: { viewMode: 'advanced' }, + hash: route.hash, + }) + " + /> + <label class="btn btn-outline-primary" for="view-mode-advanced" + >Advanced</label + > + <input + type="radio" + class="btn-check" + name="view-mode" + id="view-mode-expert" + autocomplete="off" + :checked="props.viewMode === 'expert'" + @click=" + router.replace({ + query: { viewMode: 'expert' }, + hash: route.hash, + }) + " + /> + <label class="btn btn-outline-primary" for="view-mode-expert" + >Expert</label + > + </div> </div> <nav class="h-100"> <nav v-if="props.schema" class="nav"> @@ -373,41 +450,30 @@ onMounted(() => { v-for="group in navParameterGroups" :key="group.group" > - <a :href="'#' + group.group"> + <router-link + :to="{ hash: '#' + group.group, query: route.query }" + replace + @click="scroll('#' + group.group)" + > <font-awesome-icon :icon="group.icon" v-if="group.icon" class="me-2" /> - {{ group.title }}</a - > + {{ group.title }} + </router-link> </li> <li class="nav-link"> - <a href="#pipelineGeneralOptions"> + <router-link + :to="{ hash: '#pipelineGeneralOptions', query: route.query }" + replace + @click="scroll('#pipelineGeneralOptions')" + > <font-awesome-icon icon="fa-solid fa-gear" class="me-2" /> General Pipeline Options - </a> + </router-link> </li> </ul> - <div class="mx-auto mb-3"> - <input - type="checkbox" - class="btn-check ms-1" - id="btn-check-outlined" - v-model="formState.showHidden" - autocomplete="off" - /> - <label class="btn btn-outline-primary" for="btn-check-outlined"> - <font-awesome-icon - :icon=" - formState.showHidden - ? 'fa-solid fa-eye' - : 'fa-solid fa-eye-slash' - " - /> - Show hidden Parameters - </label> - </div> </nav> <!-- Loading nav links --> <div v-else class="placeholder-glow ps-3 pt-3"> @@ -418,6 +484,17 @@ onMounted(() => { ></span> </div> </nav> + <div class="d-grid gap-2 mb-2"> + <button + type="submit" + form="launchWorkflowForm" + class="btn btn-success btn-lg mx-2" + :disabled="props.loading || !props.schema" + > + <font-awesome-icon icon="fa-solid fa-play" class="me-2" /> + Launch + </button> + </div> </div> </div> </template> diff --git a/src/components/parameter-schema/description-mode/ParameterDescription.vue b/src/components/parameter-schema/description-mode/ParameterDescription.vue index 5769d9372eeace54a7c2c11394c6f750e0b65c52..7e3afda494539b73fc82a17732f878a3dfc487ee 100644 --- a/src/components/parameter-schema/description-mode/ParameterDescription.vue +++ b/src/components/parameter-schema/description-mode/ParameterDescription.vue @@ -30,11 +30,11 @@ const helpText = computed<string | undefined>( const parameterType = computed<string>(() => props.parameter["type"]); const icon = computed<string | undefined>(() => props.parameter["fa_icon"]); const description = computed<string>(() => props.parameter["description"]); -const defaultValue = computed<string | undefined>( - () => props.parameter["default"]?.toString(), +const defaultValue = computed<string | undefined>(() => + props.parameter["default"]?.toString(), ); -const enumValues = computed<string[] | undefined>( - () => props.parameter["enum"]?.map((val: string) => val.toString()), +const enumValues = computed<string[] | undefined>(() => + props.parameter["enum"]?.map((val: string) => val.toString()), ); const hidden = computed<boolean>(() => props.parameter["hidden"] ?? false); const parameterPattern = computed<string | undefined>( diff --git a/src/components/parameter-schema/form-mode/ParameterBooleanInput.vue b/src/components/parameter-schema/form-mode/ParameterBooleanInput.vue index a3db905214f3d271a513b256fcf681c91516d878..71f4c7f5ec6d23e63fe36d65e440d3db5b0021ca 100644 --- a/src/components/parameter-schema/form-mode/ParameterBooleanInput.vue +++ b/src/components/parameter-schema/form-mode/ParameterBooleanInput.vue @@ -36,7 +36,7 @@ const emit = defineEmits<{ <template> <div - class="flex-fill mb-0 text-bg-light fs-6 ps-4 d-flex align-items-center justify-content-start border" + class="flex-fill mb-0 text-bg-light fs-6 ps-4 d-flex align-items-center justify-content-start rounded py-1 border border-secondary" :class="{ 'rounded-end': !helpTextPresent }" > <div class="form-check form-check-inline"> diff --git a/src/components/parameter-schema/form-mode/ParameterEnumInput.vue b/src/components/parameter-schema/form-mode/ParameterEnumInput.vue index a2e20d7c16c872493b4b16e126bacd2889afab3c..44ce05cbe660c313e30eb7fc82a562cb77897dc9 100644 --- a/src/components/parameter-schema/form-mode/ParameterEnumInput.vue +++ b/src/components/parameter-schema/form-mode/ParameterEnumInput.vue @@ -42,7 +42,7 @@ function updateValue() { ref="enumSelection" :value="props.modelValue" @input="updateValue" - class="form-select" + class="form-select border border-secondary" :required="required" :aria-describedby="props.helpId" > diff --git a/src/components/parameter-schema/form-mode/ParameterGroupForm.vue b/src/components/parameter-schema/form-mode/ParameterGroupForm.vue index 7789da50ea7c040b399271b5d35d7cf5706a9fff..68927d7ece763013bbd196ff20559278a9f9e428 100644 --- a/src/components/parameter-schema/form-mode/ParameterGroupForm.vue +++ b/src/components/parameter-schema/form-mode/ParameterGroupForm.vue @@ -27,6 +27,10 @@ const props = defineProps({ type: Boolean, default: false, }, + showOptional: { + type: Boolean, + default: false, + }, }); const title = computed<string>(() => props.parameterGroup["title"]); const icon = computed<string>(() => props.parameterGroup["fa_icon"]); @@ -37,6 +41,9 @@ const groupHidden = computed<boolean>(() => true, ), ); +const groupRequired = computed<boolean>( + () => (props.parameterGroup["required"] ?? []).length > 0, +); const parameters = computed<Record<string, never>>( () => props.parameterGroup["properties"], ); @@ -74,7 +81,10 @@ watch( </script> <template> - <div class="card mb-3" :hidden="!showHidden && groupHidden"> + <div + class="card mb-3" + :hidden="(!showHidden && groupHidden) || (!showOptional && !groupRequired)" + > <h2 class="card-header" :id="props.parameterGroupName"> <font-awesome-icon :icon="icon" class="me-2" v-if="icon" /> {{ title }} @@ -85,12 +95,31 @@ watch( v-for="(parameter, parameterName) in parameters" :key="parameterName" > - <div :hidden="!showHidden && parameter['hidden']"> - <code class="bg-secondary-subtle p-2 rounded-top" + <div + :hidden=" + (!showHidden && parameter['hidden']) || + (!showOptional && !parameterRequired(parameterGroup, parameterName)) + " + > + <code + class="p-2 rounded-top border-bottom-0 border bg-secondary-subtle" + :class="{ + 'border-warning': parameterRequired( + parameterGroup, + parameterName, + ), + 'border-secondary': !parameterRequired( + parameterGroup, + parameterName, + ), + }" >--{{ parameter["name"] ?? parameterName }}</code > <div class="input-group"> - <span class="input-group-text" v-if="parameter['fa_icon']"> + <span + class="input-group-text border-end-0 border border-secondary" + v-if="parameter['fa_icon']" + > <font-awesome-icon :icon="parameter['fa_icon']" /> </span> <parameter-number-input @@ -137,10 +166,11 @@ watch( @update:model-value=" (newValue) => (formInput[parameterName] = newValue) " + :remove-advanced="!showOptional" /> </template> <span - class="input-group-text cursor-pointer px-2" + class="input-group-text cursor-pointer px-2 border border-secondary" v-if="parameter['help_text']" data-bs-toggle="collapse" :data-bs-target=" @@ -163,7 +193,7 @@ watch( :id="'helpCollapse' + parameterName.replace(/\./g, '')" v-if="parameter['help_text']" > - <div class="p-2 pb-0 mx-2 mb-2 mt-1 flex-shrink-1 border rounded"> + <div class="p-2 pb-0 mx-2 mb-3 flex-shrink-1 border rounded"> <markdown-renderer class="helpTextCode" :markdown="parameter['help_text']" diff --git a/src/components/parameter-schema/form-mode/ParameterNumberInput.vue b/src/components/parameter-schema/form-mode/ParameterNumberInput.vue index 42af376d9bfd24ea8e08e40613d9205abccb1caf..55963a26f8f584cffd91b542e8446d220b7c52bf 100644 --- a/src/components/parameter-schema/form-mode/ParameterNumberInput.vue +++ b/src/components/parameter-schema/form-mode/ParameterNumberInput.vue @@ -34,12 +34,12 @@ function updateValue() { <template> <input - class="form-control" + class="form-control border border-secondary" type="number" ref="numberInput" :max="props.parameter['maximum']" :min="props.parameter['minimum']" - :step="props.parameter['type'] === 'integer' ? 1 : 0.01" + :step="props.parameter['type'] === 'integer' ? 1 : 0.0001" :value="props.modelValue" :required="props.required" :aria-describedby="props.helpId" diff --git a/src/components/parameter-schema/form-mode/ParameterStringInput.vue b/src/components/parameter-schema/form-mode/ParameterStringInput.vue index 7d38aae038ea9d12f597f758a377fa08d7d42f81..7e3164fe523835254620cbb4396dd0a305254715 100644 --- a/src/components/parameter-schema/form-mode/ParameterStringInput.vue +++ b/src/components/parameter-schema/form-mode/ParameterStringInput.vue @@ -188,7 +188,7 @@ onMounted(() => { <template> <template v-if="clowmResource && !formState.advancedInput"> <select - class="form-select" + class="form-select border border-secondary" :required="props.required" v-model="selectedResource.resourceId" > @@ -202,7 +202,7 @@ onMounted(() => { </option> </select> <select - class="form-select" + class="form-select border border-secondary" :required="props.required || selectedResource.resourceId != undefined" v-model="selectedResource.resourceVersionIndex" :disabled="selectedResource.resourceId.length === 0" @@ -222,7 +222,7 @@ onMounted(() => { </template> <template v-else-if="dataPath && !formState.advancedInput"> <select - class="form-select" + class="form-select border border-secondary" :required="props.required" v-model="s3Path.bucket" > @@ -236,7 +236,7 @@ onMounted(() => { </option> </select> <input - class="form-control" + class="form-control border-top border-secondary" :list="'datalistOptions2' + randomIDSuffix" placeholder="Type to search in bucket..." :required="props.required && dataFormat === 'file-path'" @@ -250,7 +250,7 @@ onMounted(() => { <template v-else> <input ref="stringInput" - class="form-control" + class="form-control border border-secondary" type="text" v-model="formState.stringVal" :required="props.required" diff --git a/src/components/resources/modals/UploadResourceInfoModal.vue b/src/components/resources/modals/UploadResourceInfoModal.vue index 10463ea778ce2f0f11991e61470337f786da86aa..8146fe034ef63837b5dc9988e37aac76d7dc983f 100644 --- a/src/components/resources/modals/UploadResourceInfoModal.vue +++ b/src/components/resources/modals/UploadResourceInfoModal.vue @@ -64,7 +64,7 @@ const codeExample = computed<string>(() => { return `export AWS_REGION="us-west-1" export AWS_ACCESS_KEY_ID="${s3Key.value.access_key}" export AWS_SECRET_ACCESS_KEY="${s3Key.value.secret_key}" -export S3_ENDPOINT="${environment.S3_URL}" +export S3_ENDPOINT_URL="${environment.S3_URL}" s5cmd cp --show-progress /PATH/TO/RESOURCE \\ ${resourceS3Path.value}`; @@ -220,7 +220,7 @@ onMounted(() => { <span class="hljs-built_in">export</span> AWS_SECRET_ACCESS_KEY=<span class="hljs-string">"{{ s3Key.secret_key }}"</span> -<span class="hljs-built_in">export</span> S3_ENDPOINT=<span class="hljs-string">"{{ environment.S3_URL }}"</span> +<span class="hljs-built_in">export</span> S3_ENDPOINT_URL=<span class="hljs-string">"{{ environment.S3_URL }}"</span> <span class="hljs-built_in">s5cmd</span> cp --show-progress /PATH/TO/RESOURCE \ {{ resourceS3Path }}</code></pre> diff --git a/src/components/workflows/WorkflowDocumentationTabs.vue b/src/components/workflows/WorkflowDocumentationTabs.vue index 3fda291fab44159c7d03e553c828d9bb4d512fb2..2020831edf6eb340c5ca6226d325b22db2e21bb4 100644 --- a/src/components/workflows/WorkflowDocumentationTabs.vue +++ b/src/components/workflows/WorkflowDocumentationTabs.vue @@ -26,6 +26,7 @@ const activeTab = computed<string>( <router-link class="nav-link" aria-current="page" + replace :to="{ query: { ...route.query, tab: 'description' } }" :class="{ active: activeTab === 'description', @@ -37,6 +38,7 @@ const activeTab = computed<string>( <li class="nav-item"> <router-link class="nav-link" + replace :to="{ query: { ...route.query, tab: 'usage' } }" :class="{ active: activeTab === 'usage', @@ -48,6 +50,7 @@ const activeTab = computed<string>( <li class="nav-item"> <router-link class="nav-link" + replace :to="{ query: { ...route.query, tab: 'parameters' } }" :class="{ active: activeTab === 'parameters', @@ -59,6 +62,7 @@ const activeTab = computed<string>( <li class="nav-item"> <router-link class="nav-link" + replace :to="{ query: { ...route.query, tab: 'output' } }" :class="{ active: activeTab === 'output', @@ -70,6 +74,7 @@ const activeTab = computed<string>( <li class="nav-item"> <router-link class="nav-link" + replace :to="{ query: { ...route.query, tab: 'changes' } }" :class="{ active: activeTab === 'changes', @@ -95,7 +100,7 @@ const activeTab = computed<string>( ></span> </p> </div> - <div v-else class="px-2 pt-3 border border-top-0"> + <div v-else class="px-2 pt-3 border border-top-0 mb-2"> <div v-if="activeTab === 'description'"> <markdown-renderer v-if="props.descriptionMarkdown" diff --git a/src/components/workflows/modals/CreateWorkflowModal.vue b/src/components/workflows/modals/CreateWorkflowModal.vue index 3d7d1bcca8a6ed80cb6532d6c2b3628d52897e04..d82776236d2b09dec87b4fe60f1794439339629b 100644 --- a/src/components/workflows/modals/CreateWorkflowModal.vue +++ b/src/components/workflows/modals/CreateWorkflowModal.vue @@ -329,8 +329,8 @@ onMounted(() => { modal-label="Create Workflow Modal" v-on="{ 'hidden.bs.modal': modalClosed }" > - <template v-slot:header> Create new Workflow</template> - <template v-slot:body> + <template #header> Create new Workflow</template> + <template #body> <form id="workflowCreateForm" :class="{ 'was-validated': formState.validated }" diff --git a/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue b/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue index 9444f93ff64e8f5f1427a1d1bdd1ea2ab08f0f97..5da2ca963e29050db358258498879e0ea1eb3dad 100644 --- a/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue +++ b/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue @@ -141,11 +141,11 @@ onMounted(() => { modal-label="Update Workflow Version Icon Modal" v-on="{ 'hidden.bs.modal': modalClosed }" > - <template v-slot:header> + <template #header> Update git repository credentials for Workflow <span class="fw-bold">{{ props.workflow.name }}</span> </template> - <template v-slot:extra-button v-if="props.workflow.private"> + <template #extra-button v-if="props.workflow.private"> <button class="btn delete-icon" data-bs-toggle="modal" @@ -154,7 +154,7 @@ onMounted(() => { <font-awesome-icon icon="fa-solid fa-trash" /> </button> </template> - <template v-slot:body> + <template #body> <form ref="credentialsUpdateForm" id="credentialsUpdateForm" diff --git a/src/components/workflows/modals/UpdateWorkflowModal.vue b/src/components/workflows/modals/UpdateWorkflowModal.vue index 2961a8d5db685984b352fc55fb49f81b66bc88de..f1510662ccea47672de4f55bbd86d0ea007a6354 100644 --- a/src/components/workflows/modals/UpdateWorkflowModal.vue +++ b/src/components/workflows/modals/UpdateWorkflowModal.vue @@ -317,11 +317,11 @@ onMounted(() => { modal-label="Update Workflow Modal" v-on="{ 'hidden.bs.modal': modalClosed }" > - <template v-slot:header> + <template #header> Update Workflow <span class="fw-bold">{{ props.workflow.name }}</span> </template> - <template v-slot:body> + <template #body> <form id="workflowUpdateForm" :class="{ 'was-validated': formState.validated }" diff --git a/src/components/workflows/modals/UpdateWorkflowVersionIconModal.vue b/src/components/workflows/modals/UpdateWorkflowVersionIconModal.vue index 513c5636f5a4cdc5a394d81bb2c771d75f2e5acb..9f529d0c080f4c591d33162dab4953a449596031 100644 --- a/src/components/workflows/modals/UpdateWorkflowVersionIconModal.vue +++ b/src/components/workflows/modals/UpdateWorkflowVersionIconModal.vue @@ -145,8 +145,8 @@ onMounted(() => { @confirm-delete="deleteIcon()" /> <bootstrap-toast :toast-id="'successToast-' + randomIDSuffix"> - <div v-if="formState.uploadIcon">Successfully uploaded icon</div> - <div v-else>Successfully deleted icon</div> + <template v-if="formState.uploadIcon">Successfully uploaded icon</template> + <template v-else>Successfully deleted icon</template> </bootstrap-toast> <bootstrap-modal :modalId="modalID" @@ -154,13 +154,13 @@ onMounted(() => { modal-label="Update Workflow Version IconModal" v-on="{ 'hidden.bs.modal': modalClosed }" > - <template v-slot:header> + <template #header> Update Icon Workflow <span class="fw-bold" >{{ props.workflowName }}@{{ props.version.version }}</span > </template> - <template v-slot:extra-button v-if="props.version.icon_url"> + <template #extra-button v-if="props.version.icon_url"> <button class="btn delete-icon" data-bs-toggle="modal" @@ -169,7 +169,7 @@ onMounted(() => { <font-awesome-icon icon="fa-solid fa-trash" /> </button> </template> - <template v-slot:body> + <template #body> <form ref="iconUpdateForm" id="iconUpdateForm" diff --git a/src/router/workflowRoutes.ts b/src/router/workflowRoutes.ts index 9d53737130d2766e62b44667122b634c71713747..f4d076c7415dceedb613432c012cc830c341ea67 100644 --- a/src/router/workflowRoutes.ts +++ b/src/router/workflowRoutes.ts @@ -69,6 +69,7 @@ export const workflowRoutes: RouteRecordRaw[] = [ versionId: route.params.versionId, workflowId: route.params.workflowId, workflowModeId: route.query.workflowModeId ?? undefined, + viewMode: route.query.viewMode ?? undefined, }), }, ], diff --git a/src/views/LoginView.vue b/src/views/LoginView.vue index e60053bdd1903360f6dce759aa2ea5473ce0baff..eb991253dfbe6cb2d5faafbed602b4471a081dee 100644 --- a/src/views/LoginView.vue +++ b/src/views/LoginView.vue @@ -39,7 +39,7 @@ onMounted(() => { <template> <bootstrap-toast toast-id="loginErrorToast" color-class="danger"> - <template> Login Error</template> + <template #default> Login Error</template> <template #body> <p> There has been some kind of error during the login.<br /> diff --git a/src/views/admin/AdminResourcesView.vue b/src/views/admin/AdminResourcesView.vue index 9ff663eced269ab6edb8468a8849e5c3a5eafb16..2906d8507f98ad88efe1b781f3c9941d06bd38f0 100644 --- a/src/views/admin/AdminResourcesView.vue +++ b/src/views/admin/AdminResourcesView.vue @@ -24,6 +24,7 @@ const resourceState = reactive<{ resourceStatus: Status[]; inspectVersionIndex: number; inspectResource?: ResourceOut; + searched: boolean; }>({ loading: false, resources: [], @@ -32,6 +33,7 @@ const resourceState = reactive<{ resourceStatus: [], inspectVersionIndex: 0, inspectResource: undefined, + searched: false, }); function updateUser(user: User) { @@ -51,6 +53,7 @@ function searchResources() { }) .finally(() => { resourceState.loading = false; + resourceState.searched = true; }); } @@ -119,6 +122,7 @@ function resetForm() { resourceState.searchString = ""; resourceState.resourceStatus = []; resourceState.resources = []; + resourceState.searched = false; } </script> @@ -159,6 +163,9 @@ function resetForm() { >Name of the Resource</label > <div class="input-group"> + <div class="input-group-text"> + <font-awesome-icon icon="fa-solid fa-search" /> + </div> <input id="admin-resource-name-search" type="text" @@ -209,8 +216,8 @@ function resetForm() { <table class="table table-striped" v-if="resourceState.resources"> <thead> <tr> - <th scope="col"><b>Resource ID</b></th> - <th scope="col">Name</th> + <th scope="col"><b>Name</b></th> + <th scope="col">Resource ID</th> <th scope="col">Source</th> <th scope="col">Maintainer</th> </tr> @@ -218,7 +225,10 @@ function resetForm() { <tbody v-if="resourceState.resources.length === 0"> <tr> <td colspan="5" class="text-center fst-italic fw-light"> - Select a filter and search for Resources + <template v-if="resourceState.searched" + >No resource found with specified filters</template + > + <template v-else>Select a filter and search for Resources</template> </td> </tr> </tbody> @@ -228,8 +238,8 @@ function resetForm() { :key="resource.resource_id" > <tr> - <th scope="row">{{ resource.resource_id }}</th> - <td>{{ resource.name }}</td> + <th scope="row">{{ resource.name }}</th> + <td>{{ resource.resource_id }}</td> <td>{{ resource.source }}</td> <td>{{ nameRepository.getName(resource.maintainer_id) }}</td> </tr> @@ -238,8 +248,8 @@ function resetForm() { <table class="table mb-0 table-hover"> <thead> <tr> - <th scope="col"><b>Version ID</b></th> - <th scope="col">Release</th> + <th scope="col"><b>Release</b></th> + <th scope="col">Version ID</th> <th scope="col">Created At</th> <th scope="col">State</th> <th scope="col" class="text-end">Action</th> @@ -250,8 +260,8 @@ function resetForm() { v-for="(version, index) in resource.versions" :key="version.resource_version_id" > - <th scope="row">{{ version.resource_version_id }}</th> - <th>{{ version.release }}</th> + <th scope="row">{{ version.release }}</th> + <th>{{ version.resource_version_id }}</th> <th> {{ dayjs diff --git a/src/views/object-storage/BucketView.vue b/src/views/object-storage/BucketView.vue index 9f43cbc44fa1de1ed93971a2d578161526b85e18..fbd233e1e3407e53b68e7e2fe28565074acf4d32 100644 --- a/src/views/object-storage/BucketView.vue +++ b/src/views/object-storage/BucketView.vue @@ -79,8 +79,8 @@ const objectState = reactive<{ const filteredObjects = computed<(S3ObjectWithFolder | S3PseudoFolder)[]>( () => { return objectState.filterString.length > 0 - ? visibleObjects.value.filter( - (obj) => obj.Key?.includes(objectState.filterString), + ? visibleObjects.value.filter((obj) => + obj.Key?.includes(objectState.filterString), ) : visibleObjects.value; }, @@ -158,8 +158,8 @@ const currentSubFolders = computed<string[]>(() => { return props.subFolders instanceof Array ? props.subFolders : props.subFolders.length > 0 - ? [props.subFolders] - : []; + ? [props.subFolders] + : []; }); const visibleObjects = computed<(S3ObjectWithFolder | S3PseudoFolder)[]>(() => { diff --git a/src/views/object-storage/S3KeyView.vue b/src/views/object-storage/S3KeyView.vue index b0afc9668715d7f703a932d26f7bad0e63c6ed40..792a20097c486b07eabf925ed74ae0dba49d1e22 100644 --- a/src/views/object-storage/S3KeyView.vue +++ b/src/views/object-storage/S3KeyView.vue @@ -38,10 +38,9 @@ function deleteKeyTrigger() { </script> <template> - <DeleteModal + <delete-modal modalID="delete-key-modal" - :object-name-delete="props.s3key.access_key.slice(0, 5) + '...'" - :back-modal-id="undefined" + :object-name-delete="'S3 Key ' + props.s3key.access_key" @confirm-delete="deleteKeyTrigger" /> <h3>S3 Endpoint:</h3> diff --git a/src/views/object-storage/S3KeysView.vue b/src/views/object-storage/S3KeysView.vue index 8cd7900faebcc20e91d73576e63cd7b8b4054256..8fce1fef0f7c1f630e5de51f92e2e8d61fec0902 100644 --- a/src/views/object-storage/S3KeysView.vue +++ b/src/views/object-storage/S3KeysView.vue @@ -78,7 +78,7 @@ onMounted(() => { <template> <bootstrap-toast toast-id="successKeyToast"> - Successfully deleted S3 Key {{ keyState.deletedKey.slice(0, 5) }}... + Successfully deleted S3 Key {{ keyState.deletedKey }} </bootstrap-toast> <div class="row m-2 border-bottom mt-4"> <div class="col-12"></div> @@ -135,7 +135,7 @@ onMounted(() => { shadow: keyState.activeKey === index, }" > - {{ s3key.access_key.slice(0, 5) }}... + {{ s3key.access_key.slice(0, 8) }}... </button> </div> </div> diff --git a/src/views/workflows/ArbitraryWorkflowView.vue b/src/views/workflows/ArbitraryWorkflowView.vue index e31a3389eae4d7f2eeb571fb7202f47dc1d59e3b..c739aa57795aa1a3d19b78cd5395013065e31031 100644 --- a/src/views/workflows/ArbitraryWorkflowView.vue +++ b/src/views/workflows/ArbitraryWorkflowView.vue @@ -153,7 +153,7 @@ onMounted(() => { toast-id="arbitraryWorkflowExecutionViewErrorToast" color-class="danger" > - <template> Error starting workflow </template> + <template #default> Error starting workflow </template> <template #body> <template v-if="workflowExecutionState.errorType === 'limit'"> You have too many active workflow executions to start a new one. diff --git a/src/views/workflows/StartWorkflowView.vue b/src/views/workflows/StartWorkflowView.vue index df57bf879340959b425b0c5800c7848d26bfc36c..38f4f95e23edace76af8460554f130cf6947930d 100644 --- a/src/views/workflows/StartWorkflowView.vue +++ b/src/views/workflows/StartWorkflowView.vue @@ -17,6 +17,7 @@ const props = defineProps<{ versionId: string; workflowId: string; workflowModeId?: string; + viewMode: string; }>(); const parameterSchema = ref(undefined); @@ -113,7 +114,7 @@ onMounted(() => { toast-id="workflowExecutionViewErrorToast" color-class="danger" > - <template>Error starting workflow</template> + <template #default>Error starting workflow</template> <template #body> <template v-if="versionState.workflowExecutionError === 'limit'"> You have too many active workflow executions to start a new one. @@ -130,6 +131,7 @@ onMounted(() => { :loading="versionState.loading" allow-notes @start-workflow="startWorkflow" + :view-mode="viewMode" /> </template> diff --git a/src/views/workflows/WorkflowView.vue b/src/views/workflows/WorkflowView.vue index fe4a14c7b1c5ed3efb5abb25702a95c34ffcb7e2..e3984b484b877d7546febca7992d9fec824b5316 100644 --- a/src/views/workflows/WorkflowView.vue +++ b/src/views/workflows/WorkflowView.vue @@ -137,11 +137,10 @@ const latestVersion = computed<WorkflowVersion | undefined>(() => ) || [], ), ); -const activeVersion = computed<WorkflowVersion | undefined>( - () => - workflow.value?.versions.find( - (w) => w.workflow_version_id === workflowState.activeVersionId, - ), +const activeVersion = computed<WorkflowVersion | undefined>(() => + workflow.value?.versions.find( + (w) => w.workflow_version_id === workflowState.activeVersionId, + ), ); const activeVersionModeIds = computed<string[]>( @@ -178,6 +177,17 @@ const allowVersionDeprecation = computed<boolean>(() => { return false; }); +const repositoryUrl = computed<string>(() => { + if (workflow.value == undefined) { + return ""; + } + const url = workflow.value?.repository_url; + if (activeVersion.value != undefined) { + return url + `/tree/${activeVersion.value?.workflow_version_id}`; + } + return url; +}); + // Functions // ============================================================================= function updateWorkflow(workflowId: string) { @@ -317,10 +327,11 @@ onMounted(() => { }, query: { workflowModeId: workflowState.activeModeId, + viewMode: 'simple', }, }" > - <font-awesome-icon icon="fa-solid fa-rocket" class="me-2" /> + <font-awesome-icon icon="fa-solid fa-play" class="me-2" /> <span class="align-middle">Launch {{ activeVersionString }}</span> </router-link> <div @@ -349,12 +360,16 @@ onMounted(() => { </div> <div class="row w-100 mb-4 mt-2 mx-0 border-bottom pb-2"> <a - :href="workflow.repository_url" + :href="repositoryUrl" target="_blank" class="text-secondary text-decoration-none mx-auto w-fit p-0" > <font-awesome-icon :icon="gitIcon" class="me-1" /> <span class="align-middle"> {{ workflow.repository_url }}</span> + <font-awesome-icon + icon="fa-solid fa-arrow-up-right-from-square" + class="ms-1" + /> <font-awesome-icon v-if="workflow?.private" icon="fa-solid fa-lock"