diff --git a/package-lock.json b/package-lock.json
index 6c5d9d153c15480d63ff60691439d6e7fc67eb2a..922c7405a885a92f0df0070321471aa13c9cc70c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -214,9 +214,9 @@
       "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
     },
     "node_modules/@aws-sdk/client-s3": {
-      "version": "3.535.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.535.0.tgz",
-      "integrity": "sha512-qcFCP9a695ZvAbm+hRMyfE2PjqnSkq0Bl57X7z8gHUg4TIjKJHTP7mtND21A4YaWigegQL6OA5kMXMZbCcugLA==",
+      "version": "3.536.0",
+      "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.536.0.tgz",
+      "integrity": "sha512-UM5txJxq8qKzLDVuW9c904bpb7+u1jOeyJITLz79WpyHSOP6ERHoTx/ltEuGJ4zQVazfkgthqR0lIn09sXEEuw==",
       "dependencies": {
         "@aws-crypto/sha1-browser": "3.0.0",
         "@aws-crypto/sha256-browser": "3.0.0",
@@ -572,9 +572,9 @@
       }
     },
     "node_modules/@aws-sdk/lib-storage": {
-      "version": "3.535.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.535.0.tgz",
-      "integrity": "sha512-JlamsgeokOPq3lRBH6yQBkjJQ/ak4sBCvZjs4yl2sGpzcOzq75x5qL9Ms1skY9nShPv+UeowzI7K9ia11rNDnw==",
+      "version": "3.536.0",
+      "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.536.0.tgz",
+      "integrity": "sha512-jeHnxHy02n2oEaXZx0fwNbZwnA1LZvSC6mEQZYlz3trhhqE3Ryn8HnODGR+cUKb8i+iyVCWdKRa4mfz1Xu+sQw==",
       "dependencies": {
         "@smithy/abort-controller": "^2.2.0",
         "@smithy/middleware-endpoint": "^2.5.0",
@@ -775,9 +775,9 @@
       }
     },
     "node_modules/@aws-sdk/s3-request-presigner": {
-      "version": "3.535.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.535.0.tgz",
-      "integrity": "sha512-lO8uVkiXUuAu3qvLxXoToLrWp7afxH8JzX+acYxWLQdQE10LIFykKGX3NEysCA9YkyCRwEfplqaJKiVQAC3fOw==",
+      "version": "3.536.0",
+      "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.536.0.tgz",
+      "integrity": "sha512-bMz7nxYfSjCkw72Hah40o0c9scwU2LQWoT3CkTcWs9OCrG4MCzMTBJNlzRUpxOpfGTZqVzrCaUGINIjh3jP/tQ==",
       "dependencies": {
         "@aws-sdk/signature-v4-multi-region": "3.535.0",
         "@aws-sdk/types": "3.535.0",
@@ -940,9 +940,9 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.24.0",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz",
-      "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==",
+      "version": "7.24.1",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz",
+      "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==",
       "bin": {
         "parser": "bin/babel-parser.js"
       },
@@ -2464,9 +2464,9 @@
       }
     },
     "node_modules/@types/node": {
-      "version": "20.11.28",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.28.tgz",
-      "integrity": "sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA==",
+      "version": "20.11.30",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz",
+      "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==",
       "dev": true,
       "dependencies": {
         "undici-types": "~5.26.4"
@@ -2497,16 +2497,16 @@
       "dev": true
     },
     "node_modules/@typescript-eslint/eslint-plugin": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.2.0.tgz",
-      "integrity": "sha512-mdekAHOqS9UjlmyF/LSs6AIEvfceV749GFxoBAjwAv0nkevfKHWQFDMcBZWUiIC5ft6ePWivXoS36aKQ0Cy3sw==",
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.3.1.tgz",
+      "integrity": "sha512-STEDMVQGww5lhCuNXVSQfbfuNII5E08QWkvAw5Qwf+bj2WT+JkG1uc+5/vXA3AOYMDHVOSpL+9rcbEUiHIm2dw==",
       "dev": true,
       "dependencies": {
         "@eslint-community/regexpp": "^4.5.1",
-        "@typescript-eslint/scope-manager": "7.2.0",
-        "@typescript-eslint/type-utils": "7.2.0",
-        "@typescript-eslint/utils": "7.2.0",
-        "@typescript-eslint/visitor-keys": "7.2.0",
+        "@typescript-eslint/scope-manager": "7.3.1",
+        "@typescript-eslint/type-utils": "7.3.1",
+        "@typescript-eslint/utils": "7.3.1",
+        "@typescript-eslint/visitor-keys": "7.3.1",
         "debug": "^4.3.4",
         "graphemer": "^1.4.0",
         "ignore": "^5.2.4",
@@ -2515,7 +2515,7 @@
         "ts-api-utils": "^1.0.1"
       },
       "engines": {
-        "node": "^16.0.0 || >=18.0.0"
+        "node": "^18.18.0 || >=20.0.0"
       },
       "funding": {
         "type": "opencollective",
@@ -2532,19 +2532,19 @@
       }
     },
     "node_modules/@typescript-eslint/parser": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz",
-      "integrity": "sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==",
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.3.1.tgz",
+      "integrity": "sha512-Rq49+pq7viTRCH48XAbTA+wdLRrB/3sRq4Lpk0oGDm0VmnjBrAOVXH/Laalmwsv2VpekiEfVFwJYVk6/e8uvQw==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/scope-manager": "7.2.0",
-        "@typescript-eslint/types": "7.2.0",
-        "@typescript-eslint/typescript-estree": "7.2.0",
-        "@typescript-eslint/visitor-keys": "7.2.0",
+        "@typescript-eslint/scope-manager": "7.3.1",
+        "@typescript-eslint/types": "7.3.1",
+        "@typescript-eslint/typescript-estree": "7.3.1",
+        "@typescript-eslint/visitor-keys": "7.3.1",
         "debug": "^4.3.4"
       },
       "engines": {
-        "node": "^16.0.0 || >=18.0.0"
+        "node": "^18.18.0 || >=20.0.0"
       },
       "funding": {
         "type": "opencollective",
@@ -2560,16 +2560,16 @@
       }
     },
     "node_modules/@typescript-eslint/scope-manager": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz",
-      "integrity": "sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==",
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.3.1.tgz",
+      "integrity": "sha512-fVS6fPxldsKY2nFvyT7IP78UO1/I2huG+AYu5AMjCT9wtl6JFiDnsv4uad4jQ0GTFzcUV5HShVeN96/17bTBag==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "7.2.0",
-        "@typescript-eslint/visitor-keys": "7.2.0"
+        "@typescript-eslint/types": "7.3.1",
+        "@typescript-eslint/visitor-keys": "7.3.1"
       },
       "engines": {
-        "node": "^16.0.0 || >=18.0.0"
+        "node": "^18.18.0 || >=20.0.0"
       },
       "funding": {
         "type": "opencollective",
@@ -2577,18 +2577,18 @@
       }
     },
     "node_modules/@typescript-eslint/type-utils": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.2.0.tgz",
-      "integrity": "sha512-xHi51adBHo9O9330J8GQYQwrKBqbIPJGZZVQTHHmy200hvkLZFWJIFtAG/7IYTWUyun6DE6w5InDReePJYJlJA==",
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.3.1.tgz",
+      "integrity": "sha512-iFhaysxFsMDQlzJn+vr3OrxN8NmdQkHks4WaqD4QBnt5hsq234wcYdyQ9uquzJJIDAj5W4wQne3yEsYA6OmXGw==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/typescript-estree": "7.2.0",
-        "@typescript-eslint/utils": "7.2.0",
+        "@typescript-eslint/typescript-estree": "7.3.1",
+        "@typescript-eslint/utils": "7.3.1",
         "debug": "^4.3.4",
         "ts-api-utils": "^1.0.1"
       },
       "engines": {
-        "node": "^16.0.0 || >=18.0.0"
+        "node": "^18.18.0 || >=20.0.0"
       },
       "funding": {
         "type": "opencollective",
@@ -2604,12 +2604,12 @@
       }
     },
     "node_modules/@typescript-eslint/types": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.2.0.tgz",
-      "integrity": "sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==",
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.3.1.tgz",
+      "integrity": "sha512-2tUf3uWggBDl4S4183nivWQ2HqceOZh1U4hhu4p1tPiIJoRRXrab7Y+Y0p+dozYwZVvLPRI6r5wKe9kToF9FIw==",
       "dev": true,
       "engines": {
-        "node": "^16.0.0 || >=18.0.0"
+        "node": "^18.18.0 || >=20.0.0"
       },
       "funding": {
         "type": "opencollective",
@@ -2617,13 +2617,13 @@
       }
     },
     "node_modules/@typescript-eslint/typescript-estree": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz",
-      "integrity": "sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==",
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.3.1.tgz",
+      "integrity": "sha512-tLpuqM46LVkduWP7JO7yVoWshpJuJzxDOPYIVWUUZbW+4dBpgGeUdl/fQkhuV0A8eGnphYw3pp8d2EnvPOfxmQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "7.2.0",
-        "@typescript-eslint/visitor-keys": "7.2.0",
+        "@typescript-eslint/types": "7.3.1",
+        "@typescript-eslint/visitor-keys": "7.3.1",
         "debug": "^4.3.4",
         "globby": "^11.1.0",
         "is-glob": "^4.0.3",
@@ -2632,7 +2632,7 @@
         "ts-api-utils": "^1.0.1"
       },
       "engines": {
-        "node": "^16.0.0 || >=18.0.0"
+        "node": "^18.18.0 || >=20.0.0"
       },
       "funding": {
         "type": "opencollective",
@@ -2645,21 +2645,21 @@
       }
     },
     "node_modules/@typescript-eslint/utils": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.2.0.tgz",
-      "integrity": "sha512-YfHpnMAGb1Eekpm3XRK8hcMwGLGsnT6L+7b2XyRv6ouDuJU1tZir1GS2i0+VXRatMwSI1/UfcyPe53ADkU+IuA==",
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.3.1.tgz",
+      "integrity": "sha512-jIERm/6bYQ9HkynYlNZvXpzmXWZGhMbrOvq3jJzOSOlKXsVjrrolzWBjDW6/TvT5Q3WqaN4EkmcfdQwi9tDjBQ==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.4.0",
         "@types/json-schema": "^7.0.12",
         "@types/semver": "^7.5.0",
-        "@typescript-eslint/scope-manager": "7.2.0",
-        "@typescript-eslint/types": "7.2.0",
-        "@typescript-eslint/typescript-estree": "7.2.0",
+        "@typescript-eslint/scope-manager": "7.3.1",
+        "@typescript-eslint/types": "7.3.1",
+        "@typescript-eslint/typescript-estree": "7.3.1",
         "semver": "^7.5.4"
       },
       "engines": {
-        "node": "^16.0.0 || >=18.0.0"
+        "node": "^18.18.0 || >=20.0.0"
       },
       "funding": {
         "type": "opencollective",
@@ -2670,16 +2670,16 @@
       }
     },
     "node_modules/@typescript-eslint/visitor-keys": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz",
-      "integrity": "sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==",
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.3.1.tgz",
+      "integrity": "sha512-9RMXwQF8knsZvfv9tdi+4D/j7dMG28X/wMJ8Jj6eOHyHWwDW4ngQJcqEczSsqIKKjFiLFr40Mnr7a5ulDD3vmw==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "7.2.0",
+        "@typescript-eslint/types": "7.3.1",
         "eslint-visitor-keys": "^3.4.1"
       },
       "engines": {
-        "node": "^16.0.0 || >=18.0.0"
+        "node": "^18.18.0 || >=20.0.0"
       },
       "funding": {
         "type": "opencollective",
@@ -3519,9 +3519,9 @@
       }
     },
     "node_modules/dompurify": {
-      "version": "3.0.9",
-      "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.9.tgz",
-      "integrity": "sha512-uyb4NDIvQ3hRn6NiC+SIFaP4mJ/MdXlvtunaqK9Bn6dD3RuB/1S/gasEjDHD8eiaqdSael2vBv+hOs7Y+jhYOQ=="
+      "version": "3.0.10",
+      "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.10.tgz",
+      "integrity": "sha512-WZDL8ZHTliEVP3Lk4phtvjg8SNQ3YMc5WVstxE8cszKZrFjzI4PF4ZTIk9VGAc9vZADO7uGO2V/ZiStcRSAT4Q=="
     },
     "node_modules/entities": {
       "version": "4.5.0",
diff --git a/src/components/modals/BootstrapModal.vue b/src/components/modals/BootstrapModal.vue
index 63806ef19d8f804f709b31185083703de16dcb67..7d6cc6cd2efbf855c48defec2e51adda0b16cbce 100644
--- a/src/components/modals/BootstrapModal.vue
+++ b/src/components/modals/BootstrapModal.vue
@@ -1,21 +1,22 @@
 <script setup lang="ts">
 import { computed } from "vue";
+import type { SizeModifierType } from "@/types/PropTypes";
 
 const props = defineProps<{
   modalId: string;
   modalLabel: string;
   staticBackdrop?: boolean;
-  sizeModifier?: sizeModifierType; // https://getbootstrap.com/docs/5.3/components/modal/#optional-sizes, e.g. sm, lg and xl
+  sizeModifierModal?: sizeModifierModalType; // https://getbootstrap.com/docs/5.3/components/modal/#optional-sizes, e.g. sm, lg and xl
   trackModalValue?: string;
 }>();
 
-type sizeModifierType = "sm" | "lg" | "xl";
+type sizeModifierModalType = SizeModifierType | "xl";
 
 const modalSizeClass = computed<string>(() => {
-  if (props.sizeModifier == undefined) {
+  if (props.sizeModifierModal == undefined) {
     return "";
   }
-  return "modal-" + props.sizeModifier;
+  return "modal-" + props.sizeModifierModal;
 });
 
 function trackModalShow() {
diff --git a/src/components/parameter-schema/ParameterSchemaFormComponent.vue b/src/components/parameter-schema/ParameterSchemaFormComponent.vue
index 3a77eafb79c39ada5d2a545da4137f5f0433cd97..1322357f2266aa4bc15925bac3d1b42edbd9d3a2 100644
--- a/src/components/parameter-schema/ParameterSchemaFormComponent.vue
+++ b/src/components/parameter-schema/ParameterSchemaFormComponent.vue
@@ -4,7 +4,7 @@ import ParameterGroupForm from "@/components/parameter-schema/form-mode/Paramete
 import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
 import Ajv from "ajv";
 import type { ValidateFunction } from "ajv";
-import ParameterStringInput from "@/components/parameter-schema/form-mode/ParameterStringInput.vue";
+import ParameterInput from "@/components/parameter-schema/form-mode/ParameterInput.vue";
 import { Toast, Tooltip } from "bootstrap";
 import { useBucketStore } from "@/stores/buckets";
 import { useS3KeyStore } from "@/stores/s3keys";
@@ -331,14 +331,13 @@ onMounted(() => {
               <span class="input-group-text border border-secondary">
                 <font-awesome-icon icon="fa-solid fa-folder" />
               </span>
-              <parameter-string-input
-                parameter-name="logs_s3_path"
+              <parameter-input
                 v-model="formState.metaParameters.logs_s3_path"
                 :parameter="{
                   format: 'directory-path',
                   type: 'string',
                 }"
-                remove-advanced
+                border
               />
             </div>
             <label class="mb-3" for="logsS3Path">
@@ -354,14 +353,13 @@ onMounted(() => {
               <span class="input-group-text border border-secondary">
                 <font-awesome-icon icon="fa-solid fa-folder" />
               </span>
-              <parameter-string-input
-                parameter-name="provenance_s3_path"
+              <parameter-input
                 v-model="formState.metaParameters.provenance_s3_path"
                 :parameter="{
                   format: 'directory-path',
                   type: 'string',
                 }"
-                remove-advanced
+                border
               />
             </div>
             <label class="mb-3" for="provenanceS3Path">
@@ -378,14 +376,13 @@ onMounted(() => {
               <span class="input-group-text border border-secondary">
                 <font-awesome-icon icon="fa-solid fa-folder" />
               </span>
-              <parameter-string-input
-                parameter-name="debug_s3_path"
+              <parameter-input
                 v-model="formState.metaParameters.debug_s3_path"
                 :parameter="{
                   format: 'directory-path',
                   type: 'string',
                 }"
-                remove-advanced
+                border
               />
             </div>
             <label class="mb-3" for="debugS3Path">
diff --git a/src/components/parameter-schema/form-mode/ParameterBooleanInput.vue b/src/components/parameter-schema/form-mode/ParameterBooleanInput.vue
index 54e519ccd40a64f2ab9801973389ae525ea3d97f..f78d2bbf736b69eee4ecf74045a965c8a993fd32 100644
--- a/src/components/parameter-schema/form-mode/ParameterBooleanInput.vue
+++ b/src/components/parameter-schema/form-mode/ParameterBooleanInput.vue
@@ -11,28 +11,35 @@ const props = defineProps({
       return "number" === value["type"];
     },
   },
-  required: Boolean,
-  parameterName: {
-    type: String,
-    required: true,
-  },
-  helpId: {
-    type: String,
-  },
+  border: Boolean,
 });
 
 const randomIDSuffix = Math.random().toString(16).substring(2, 8);
 
 const helpTextPresent = computed<boolean>(() => props.parameter["help_text"]);
 const iconPresent = computed<boolean>(() => props.parameter["fa_icon"]);
+
+const dynamicCssClasses = computed<string[]>(() => {
+  const cssClasses = [];
+  if (props.border) {
+    cssClasses.push("border", "border-secondary", "text-bg-light");
+  }
+  if (!helpTextPresent.value) {
+    cssClasses.push("rounded-end");
+  }
+  if (!iconPresent.value) {
+    cssClasses.push("rounded-start");
+  }
+  return cssClasses;
+});
 </script>
 
 <template>
   <div
-    class="flex-fill mb-0 text-bg-light fs-6 ps-4 d-flex align-items-center justify-content-start py-1 border border-secondary"
-    :class="{ 'rounded-end': !helpTextPresent, 'rounded-start': !iconPresent }"
+    class="flex-fill mb-0 fs-6 d-flex align-items-center justify-content-start py-1 ps-4"
+    :class="dynamicCssClasses"
   >
-    <div class="form-check form-check-inline">
+    <div class="form-check form-check-inline mb-0">
       <label class="form-check-label" :for="'trueOption' + randomIDSuffix"
         >True</label
       >
@@ -45,7 +52,7 @@ const iconPresent = computed<boolean>(() => props.parameter["fa_icon"]);
         v-model="model"
       />
     </div>
-    <div class="form-check form-check-inline">
+    <div class="form-check form-check-inline mb-0">
       <input
         class="form-check-input"
         type="radio"
diff --git a/src/components/parameter-schema/form-mode/ParameterEnumInput.vue b/src/components/parameter-schema/form-mode/ParameterEnumInput.vue
index a92092cc77d4a17a2665bbbb46a979ba2ef18f29..dcd17309d546a985fd1b19f11b90de3f031123fd 100644
--- a/src/components/parameter-schema/form-mode/ParameterEnumInput.vue
+++ b/src/components/parameter-schema/form-mode/ParameterEnumInput.vue
@@ -1,5 +1,6 @@
 <script setup lang="ts">
-import { computed } from "vue";
+import { computed, type PropType } from "vue";
+import type { SizeModifierType } from "@/types/PropTypes";
 
 const model = defineModel<string | undefined>({ required: true });
 
@@ -12,23 +13,35 @@ const props = defineProps({
     },
   },
   required: Boolean,
-  parameterName: {
-    type: String,
-    required: true,
-  },
   helpId: {
     type: String,
   },
+  sizeModifier: {
+    type: String as PropType<SizeModifierType>,
+  },
+  border: Boolean,
 });
 
 const possibleValues = computed<string[]>(() => props.parameter["enum"]);
+
+const dynamicCssClasses = computed<string[]>(() => {
+  const cssClasses = [];
+  if (props.sizeModifier) {
+    cssClasses.push(`form-select-${props.sizeModifier}`);
+  }
+  if (props.border) {
+    cssClasses.push("border", "border-secondary");
+  }
+  return cssClasses;
+});
 </script>
 
 <template>
   <select
     ref="enumSelection"
     v-model="model"
-    class="form-select border border-secondary"
+    class="form-select"
+    :class="dynamicCssClasses"
     :required="required"
     :aria-describedby="props.helpId"
   >
diff --git a/src/components/parameter-schema/form-mode/ParameterFileInput.vue b/src/components/parameter-schema/form-mode/ParameterFileInput.vue
new file mode 100644
index 0000000000000000000000000000000000000000..6ca9c8b9e23533d70daa450951cc98c77422e1d5
--- /dev/null
+++ b/src/components/parameter-schema/form-mode/ParameterFileInput.vue
@@ -0,0 +1,159 @@
+<script setup lang="ts">
+import { computed, type PropType, reactive, watch } from "vue";
+import { useS3ObjectStore } from "@/stores/s3objects";
+import { useBucketStore } from "@/stores/buckets";
+import type { SizeModifierType } from "@/types/PropTypes";
+
+const model = defineModel<string | undefined>({ required: true });
+
+const props = defineProps({
+  parameter: {
+    type: Object,
+    required: true,
+    validator(value: Record<string, never>) {
+      return value["format"] != undefined;
+    },
+  },
+  required: Boolean,
+  helpId: {
+    type: String,
+  },
+  sizeModifier: {
+    type: String as PropType<SizeModifierType>,
+  },
+  border: Boolean,
+});
+
+const s3ObjectRepository = useS3ObjectStore();
+const bucketRepository = useBucketStore();
+const randomIDSuffix = Math.random().toString(16).substring(2, 8);
+
+const baseDynamicClass = computed<string[]>(() =>
+  props.border ? ["border", "border-secondary"] : [],
+);
+
+const selectDynamicClass = computed<string[]>(() => {
+  const cssClasses = [...baseDynamicClass.value];
+  if (props.sizeModifier) {
+    cssClasses.push(`form-select-${props.sizeModifier}`);
+  }
+  return cssClasses;
+});
+const inputDynamicClass = computed<string[]>(() => {
+  const cssClasses = [...baseDynamicClass.value];
+  if (props.sizeModifier) {
+    cssClasses.push(`form-control-${props.sizeModifier}`);
+  }
+  if (!helpTextPresent.value) {
+    cssClasses.push("rounded-end");
+  }
+  return cssClasses;
+});
+
+const s3Path = reactive<{
+  bucket: string;
+  key?: string;
+}>({
+  bucket: "",
+  key: undefined,
+});
+
+const helpTextPresent = computed<boolean>(() => props.parameter["help_text"]);
+
+const foldersInBucket = computed<string[]>(() =>
+  (s3ObjectRepository.objectMapping[s3Path.bucket ?? ""] ?? [])
+    .filter((obj) => obj.Key != undefined)
+    .map((obj) => {
+      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+      const parts = obj.Key!.split("/");
+      return parts
+        .slice(0, parts.length - 1)
+        .map((part, index) =>
+          parts.slice(0, index + 1).reduce((acc, val) => `${acc}/${val}`),
+        );
+    })
+    .flat()
+    .filter((val, index, array) => array.indexOf(val) === index),
+);
+
+const filesInBucket = computed<string[]>(() =>
+  (s3ObjectRepository.objectMapping[s3Path.bucket ?? ""] ?? [])
+    .filter((obj) => !obj.Key?.endsWith("/"))
+    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+    .map((obj) => obj.Key!),
+);
+
+const filesAndFoldersInBucket = computed<string[]>(() =>
+  filesInBucket.value.concat(foldersInBucket.value),
+);
+
+const keyDataList = computed<string[]>(() => {
+  switch (props.parameter["format"]) {
+    case "file-path":
+      return filesInBucket.value;
+    case "directory-path":
+      return foldersInBucket.value;
+    case "path":
+      return filesAndFoldersInBucket.value;
+    default:
+      return [];
+  }
+});
+
+watch(
+  () => s3Path.key,
+  (newVal, oldVal) => {
+    if (newVal !== oldVal) {
+      updateModel(s3Path.bucket, newVal);
+    }
+  },
+);
+
+function updateBucket(bucket: string) {
+  s3Path.bucket = bucket;
+  updateModel(bucket, s3Path.key);
+  s3ObjectRepository.fetchS3Objects(
+    bucket,
+    bucketRepository.ownPermissions[bucket]?.file_prefix ?? undefined,
+  );
+}
+
+function updateModel(bucket: string, key?: string) {
+  model.value = !bucket ? undefined : `s3://${bucket}${key ? "/" + key : ""}`;
+}
+</script>
+
+<template>
+  <select
+    class="form-select"
+    :class="selectDynamicClass"
+    :required="props.required"
+    :value="s3Path.bucket"
+    @change="
+      (event) => updateBucket((event.target as HTMLSelectElement)?.value)
+    "
+  >
+    <option selected disabled value="">Please select a bucket</option>
+    <option
+      v-for="bucket in bucketRepository.ownBucketsAndFullPermissions"
+      :key="bucket"
+      :value="bucket"
+    >
+      {{ bucket }}
+    </option>
+  </select>
+  <input
+    class="form-control"
+    :list="'keys-options-' + randomIDSuffix"
+    :class="inputDynamicClass"
+    placeholder="Type to search in bucket..."
+    :required="props.required && props.parameter['format'] === 'file-path'"
+    v-model="s3Path.key"
+    :pattern="props.parameter['pattern']"
+  />
+  <datalist :id="'keys-options-' + randomIDSuffix">
+    <option v-for="obj in keyDataList" :value="obj" :key="obj" />
+  </datalist>
+</template>
+
+<style scoped></style>
diff --git a/src/components/parameter-schema/form-mode/ParameterGroupForm.vue b/src/components/parameter-schema/form-mode/ParameterGroupForm.vue
index 9d4b0f398b7cf79348714c6bcabdf6f013d0d74f..dc75ea44f2a1d6937b4167ca4ed50b781010aec2 100644
--- a/src/components/parameter-schema/form-mode/ParameterGroupForm.vue
+++ b/src/components/parameter-schema/form-mode/ParameterGroupForm.vue
@@ -1,12 +1,9 @@
 <script setup lang="ts">
 import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
 import { computed, type PropType } from "vue";
-import ParameterNumberInput from "@/components/parameter-schema/form-mode/ParameterNumberInput.vue";
 import MarkdownRenderer from "@/components/MarkdownRenderer.vue";
-import ParameterBooleanInput from "@/components/parameter-schema/form-mode/ParameterBooleanInput.vue";
-import ParameterEnumInput from "@/components/parameter-schema/form-mode/ParameterEnumInput.vue";
-import ParameterStringInput from "@/components/parameter-schema/form-mode/ParameterStringInput.vue";
 import type { WorkflowParameters } from "@/types/WorkflowParameters";
+import ParameterInput from "@/components/parameter-schema/form-mode/ParameterInput.vue";
 
 const model = defineModel<WorkflowParameters>({ required: true });
 
@@ -63,6 +60,10 @@ function parameterRequired(
       ?.reduce((acc: boolean, val: string) => acc || val, false)
   );
 }
+
+function parameterId(parameterName: string): string {
+  return parameterName.replace(/\./g, "");
+}
 </script>
 
 <template>
@@ -101,61 +102,19 @@ function parameterRequired(
             >
               <font-awesome-icon :icon="parameter['fa_icon']" />
             </span>
-            <template
-              v-if="
-                parameter['type'] === 'number' ||
-                parameter['type'] === 'integer'
-              "
-            >
-              <!-- @vue-ignore -->
-              <parameter-number-input
-                :parameter-name="parameterName"
-                :parameter="parameter"
-                :help-id="parameterName + '-help'"
-                :required="parameterRequired(parameterGroup, parameterName)"
-                v-model="model[parameterName]"
-              />
-            </template>
-            <template v-else-if="parameter['type'] === 'boolean'">
-              <!-- @vue-ignore -->
-              <parameter-boolean-input
-                :parameter-name="parameterName"
-                :parameter="parameter"
-                :help-id="parameterName + '-help'"
-                v-model="model[parameterName]"
-              />
-            </template>
-            <template v-else-if="parameter['type'] === 'string'">
-              <!-- @vue-ignore -->
-              <template v-if="parameter['enum']">
-                <!-- @vue-ignore -->
-                <parameter-enum-input
-                  :parameter-name="parameterName"
-                  :parameter="parameter"
-                  :required="parameterRequired(parameterGroup, parameterName)"
-                  v-model="model[parameterName]"
-                />
-              </template>
-              <!-- @vue-ignore -->
-              <parameter-string-input
-                v-else
-                :parameter-name="parameterName"
-                :parameter="parameter"
-                :required="parameterRequired(parameterGroup, parameterName)"
-                v-model="model[parameterName]"
-                :remove-advanced="!showOptional"
-                :clowm-resource="resourceParameters?.includes(parameterName)"
-              />
-            </template>
+            <parameter-input
+              :parameter="parameter"
+              v-model="model[parameterName]"
+              :required="parameterRequired(parameterGroup, parameterName)"
+              border
+            />
             <span
               class="input-group-text cursor-pointer px-2 border border-secondary"
               v-if="parameter['help_text']"
               data-bs-toggle="collapse"
-              :data-bs-target="
-                '#helpCollapse' + parameterName.replace(/\./g, '')
-              "
+              :data-bs-target="'#help-collapse-' + parameterId(parameterName)"
               aria-expanded="false"
-              :aria-controls="'helpCollapse' + parameterName.replace(/\./g, '')"
+              :aria-controls="'help-collapse-' + parameterId(parameterName)"
             >
               <font-awesome-icon
                 class="cursor-pointer"
@@ -168,7 +127,7 @@ function parameterRequired(
           </label>
           <div
             class="collapse"
-            :id="'helpCollapse' + parameterName.replace(/\./g, '')"
+            :id="'help-collapse-' + parameterId(parameterName)"
             v-if="parameter['help_text']"
           >
             <div class="p-2 pb-0 mx-2 mb-3 flex-shrink-1 border rounded">
diff --git a/src/components/parameter-schema/form-mode/ParameterInput.vue b/src/components/parameter-schema/form-mode/ParameterInput.vue
new file mode 100644
index 0000000000000000000000000000000000000000..ca67de093b6fc7906b53971b925458583e2b672b
--- /dev/null
+++ b/src/components/parameter-schema/form-mode/ParameterInput.vue
@@ -0,0 +1,87 @@
+<script setup lang="ts">
+import { computed } from "vue";
+import ParameterResourceInput from "@/components/parameter-schema/form-mode/ParameterResourceInput.vue";
+import ParameterNumberInput from "@/components/parameter-schema/form-mode/ParameterNumberInput.vue";
+import ParameterBooleanInput from "@/components/parameter-schema/form-mode/ParameterBooleanInput.vue";
+import ParameterEnumInput from "@/components/parameter-schema/form-mode/ParameterEnumInput.vue";
+import ParameterFileInput from "@/components/parameter-schema/form-mode/ParameterFileInput.vue";
+import ParameterStringInput from "@/components/parameter-schema/form-mode/ParameterStringInput.vue";
+import type { SizeModifierType } from "@/types/PropTypes";
+import type { ResourcePath_Input } from "@/client/workflow";
+
+const model = defineModel<
+  number | string | boolean | ResourcePath_Input | undefined
+>({
+  required: true,
+});
+
+const props = defineProps<{
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  parameter: Record<string, any>;
+  required?: boolean;
+  resourceParameter?: boolean;
+  advanced?: boolean;
+  rawModel?: boolean;
+  sizeModifier?: SizeModifierType;
+  border?: boolean;
+}>();
+
+const parameterType = computed<string>(
+  () => props.parameter["type"] ?? "string",
+);
+</script>
+
+<template>
+  <parameter-number-input
+    v-if="parameterType === 'number' || parameterType === 'integer'"
+    :parameter="parameter"
+    v-model="model as number"
+    :required="required"
+    :size-modifier="sizeModifier"
+    :border="border"
+  />
+  <parameter-boolean-input
+    v-else-if="parameterType === 'boolean'"
+    :parameter="parameter"
+    v-model="model as boolean"
+    :border="border"
+  />
+  <parameter-enum-input
+    v-else-if="parameter['enum']"
+    :required="required"
+    :parameter="parameter"
+    v-model="model as string"
+    :size-modifier="sizeModifier"
+    :border="border"
+  />
+  <template v-else>
+    <parameter-resource-input
+      v-if="resourceParameter && !advanced"
+      :parameter="parameter"
+      :required="required"
+      v-model="model as ResourcePath_Input"
+      :rawModel="rawModel"
+      :size-modifier="sizeModifier"
+      :border="border"
+    />
+    <parameter-file-input
+      v-else-if="parameter['format'] && !advanced"
+      class="border border-secondary"
+      :required="required"
+      :parameter="parameter"
+      v-model="model as string"
+      :size-modifier="sizeModifier"
+      :border="border"
+    />
+    <parameter-string-input
+      v-else
+      :parameter="parameter"
+      :required="required"
+      v-model="model as string"
+      :size-modifier="sizeModifier"
+      :border="border"
+    />
+  </template>
+</template>
+
+<style scoped></style>
diff --git a/src/components/parameter-schema/form-mode/ParameterNumberInput.vue b/src/components/parameter-schema/form-mode/ParameterNumberInput.vue
index 0cc7ca60dd195a5c999b6570d88af7e85bb3b117..194bcb291ab958e914a4efaed6955dac17a6f7c5 100644
--- a/src/components/parameter-schema/form-mode/ParameterNumberInput.vue
+++ b/src/components/parameter-schema/form-mode/ParameterNumberInput.vue
@@ -1,4 +1,7 @@
 <script setup lang="ts">
+import { computed, type PropType } from "vue";
+import type { SizeModifierType } from "@/types/PropTypes";
+
 const model = defineModel<number | undefined>({ required: true });
 
 const props = defineProps({
@@ -10,19 +13,31 @@ const props = defineProps({
     },
   },
   required: Boolean,
-  parameterName: {
-    type: String,
-    required: true,
-  },
   helpId: {
     type: String,
   },
+  sizeModifier: {
+    type: String as PropType<SizeModifierType>,
+  },
+  border: Boolean,
+});
+
+const dynamicCssClasses = computed<string[]>(() => {
+  const cssClasses = [];
+  if (props.sizeModifier) {
+    cssClasses.push(`form-control-${props.sizeModifier}`);
+  }
+  if (props.border) {
+    cssClasses.push("border", "border-secondary");
+  }
+  return cssClasses;
 });
 </script>
 
 <template>
   <input
-    class="form-control border border-secondary"
+    class="form-control flex-fill"
+    :class="dynamicCssClasses"
     type="number"
     :max="props.parameter['maximum']"
     :min="props.parameter['minimum']"
diff --git a/src/components/parameter-schema/form-mode/ParameterResourceInput.vue b/src/components/parameter-schema/form-mode/ParameterResourceInput.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4dfeaae237d9357d495e3db62a253142379efe68
--- /dev/null
+++ b/src/components/parameter-schema/form-mode/ParameterResourceInput.vue
@@ -0,0 +1,154 @@
+<script setup lang="ts">
+import type { ResourcePath_Input } from "@/client/workflow";
+import { Status } from "@/client/resource";
+import { computed, reactive, watch } from "vue";
+import { useResourceStore } from "@/stores/resources";
+import type { SizeModifierType } from "@/types/PropTypes";
+
+const model = defineModel<string | ResourcePath_Input>({
+  required: true,
+});
+
+const props = defineProps<{
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  parameter: Record<string, any>;
+  required?: boolean;
+  helpId?: string;
+  rawModel?: boolean;
+  sizeModifier?: SizeModifierType;
+  border?: boolean;
+}>();
+
+const resourceRepository = useResourceStore();
+const randomIDSuffix = Math.random().toString(16).substring(2, 8);
+
+const resource = reactive<ResourcePath_Input>({
+  resource_id: "",
+  resource_version_id: "",
+  suffix: undefined,
+});
+
+const baseDynamicClass = computed<string[]>(() =>
+  props.border ? ["border", "border-secondary"] : [],
+);
+
+const selectDynamicClass = computed<string[]>(() => {
+  const cssClasses = [...baseDynamicClass.value];
+  if (props.sizeModifier) {
+    cssClasses.push(`form-select-${props.sizeModifier}`);
+  }
+  return cssClasses;
+});
+const inputDynamicClass = computed<string[]>(() => {
+  const cssClasses = [...baseDynamicClass.value];
+  if (props.sizeModifier) {
+    cssClasses.push(`form-control-${props.sizeModifier}`);
+  }
+  return cssClasses;
+});
+
+function updateResourceId(rid: string) {
+  resource.resource_id = rid;
+  resource.resource_version_id = "";
+  updateModel();
+}
+
+function updateResourceVersionId(rvid: string) {
+  resource.resource_version_id = rvid;
+  updateModel();
+  resourceRepository.fetchResourceTree(resource.resource_id, rvid);
+}
+
+watch(
+  () => resource.suffix,
+  (newVal, oldVal) => {
+    if (newVal !== oldVal) {
+      updateModel();
+    }
+  },
+);
+
+function updateModel() {
+  if (props.rawModel) {
+    model.value = resource;
+    return;
+  }
+  if (resource.resource_version_id.length === 0) {
+    model.value = "";
+    return;
+  }
+  let val =
+    resourceRepository.versionMapping[resource.resource_version_id]
+      ?.cluster_path ?? "";
+  if (resource.suffix != undefined && val.length > 0) {
+    val = val + resource.suffix;
+  }
+  model.value = val;
+}
+</script>
+
+<template>
+  <select
+    class="form-select"
+    :class="selectDynamicClass"
+    :required="props.required"
+    :value="resource.resource_id"
+    @change="
+      (event) => updateResourceId((event.target as HTMLSelectElement)?.value)
+    "
+  >
+    >
+    <option selected disabled value="">Please select a resource</option>
+    <option
+      v-for="resource in resourceRepository.resources"
+      :key="resource.resource_id"
+      :value="resource.resource_id"
+    >
+      {{ resource.name }}
+    </option>
+  </select>
+  <select
+    class="form-select"
+    :class="selectDynamicClass"
+    :required="resource.resource_id.length > 0"
+    :value="resource.resource_version_id"
+    @change="
+      (event) =>
+        updateResourceVersionId((event.target as HTMLSelectElement)?.value)
+    "
+    :disabled="resource.resource_id.length === 0"
+  >
+    <option disabled selected value="">Please select a version</option>
+    <option
+      v-for="version in resourceRepository.resourceMapping[resource.resource_id]
+        ?.versions ?? []"
+      :key="version.resource_version_id"
+      :value="version.resource_version_id"
+    >
+      {{ version.release }}
+      {{ version.status === Status.LATEST ? "- Latest" : "" }}
+    </option>
+  </select>
+  <input
+    type="text"
+    class="form-control rounded-end"
+    :class="inputDynamicClass"
+    placeholder="/optional/path/in/resource/..."
+    minlength="2"
+    maxlength="256"
+    pattern="\/\S*"
+    v-model="resource.suffix"
+    :list="'resource-tree-options-' + randomIDSuffix"
+  />
+  <datalist :id="'resource-tree-options-' + randomIDSuffix">
+    <option
+      v-for="file in resourceRepository.resourceTreeList[
+        resource.resource_version_id
+      ] ?? []"
+      :value="file"
+      :key="file"
+    />
+  </datalist>
+</template>
+
+<style scoped></style>
diff --git a/src/components/parameter-schema/form-mode/ParameterStringInput.vue b/src/components/parameter-schema/form-mode/ParameterStringInput.vue
index a41cc04f692ad9733e06bba04c1fa0ae2697c061..85e6eee21e2c23f2c53a6f58bbb5b2cb855e520d 100644
--- a/src/components/parameter-schema/form-mode/ParameterStringInput.vue
+++ b/src/components/parameter-schema/form-mode/ParameterStringInput.vue
@@ -1,15 +1,8 @@
 <script setup lang="ts">
-import { computed, watch, onMounted, reactive, ref } from "vue";
-import { useBucketStore } from "@/stores/buckets";
-import { useS3ObjectStore } from "@/stores/s3objects";
-import { useResourceStore } from "@/stores/resources";
-import { Status } from "@/client/resource";
-
-const bucketRepository = useBucketStore();
-const s3objectRepository = useS3ObjectStore();
-const resourceRepository = useResourceStore();
-const randomIDSuffix = Math.random().toString(16).substring(2, 8);
+import { computed, type PropType, ref } from "vue";
+import type { SizeModifierType } from "@/types/PropTypes";
 
+const model = defineModel<string | undefined>({ required: true });
 const props = defineProps({
   parameter: {
     type: Object,
@@ -19,273 +12,45 @@ const props = defineProps({
     },
   },
   required: Boolean,
-  parameterName: {
-    type: String,
-    required: true,
-  },
-  modelValue: {
-    type: String,
-  },
   helpId: {
     type: String,
   },
-  removeAdvanced: {
-    type: Boolean,
-    default: false,
-  },
-  clowmResource: {
-    type: Boolean,
-    default: false,
+  sizeModifier: {
+    type: String as PropType<SizeModifierType>,
   },
+  border: Boolean,
 });
 
-const emit = defineEmits<{
-  (e: "update:modelValue", value?: string): void;
-}>();
-
-const s3Path = reactive<{
-  bucket: string;
-  key?: string;
-}>({
-  bucket: "",
-  key: undefined,
-});
-
-const selectedResource = reactive<{
-  resourceId: string;
-  resourceVersionIndex: number;
-}>({
-  resourceId: "",
-  resourceVersionIndex: 0,
-});
-
-const formState = reactive<{
-  advancedInput: boolean;
-  stringVal?: string;
-}>({
-  advancedInput: false,
-  stringVal: undefined,
-});
-
-const stringInput = ref<HTMLInputElement | undefined>(undefined);
-const pattern = computed<string>(() => props.parameter["pattern"]);
-const dataFormat = computed<string | undefined>(
-  () => props.parameter["format"],
-);
-const dataPath = computed<boolean>(() => dataFormat.value != undefined);
-const clowmResource = computed<boolean>(() => props.clowmResource ?? false);
-const helpTextPresent = computed<boolean>(() => props.parameter["help_text"]);
-
-const filesInBucket = computed<string[]>(() =>
-  (s3objectRepository.objectMapping[s3Path.bucket ?? ""] ?? [])
-    .filter((obj) => !obj.Key?.endsWith("/"))
-    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    .map((obj) => obj.Key!),
-);
-
-const foldersInBucket = computed<string[]>(() =>
-  (s3objectRepository.objectMapping[s3Path.bucket ?? ""] ?? [])
-    .filter((obj) => obj.Key != undefined)
-    .map((obj) => {
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      const parts = obj.Key!.split("/");
-      return parts
-        .slice(0, parts.length - 1)
-        .map((part, index) =>
-          parts.slice(0, index + 1).reduce((acc, val) => `${acc}/${val}`),
-        );
-    })
-    .flat()
-    .filter((val, index, array) => array.indexOf(val) === index),
-);
-
-const filesAndFoldersInBucket = computed<string[]>(() =>
-  filesInBucket.value.concat(foldersInBucket.value),
-);
-
-const keyDataList = computed<string[]>(() => {
-  switch (dataFormat.value) {
-    case "file-path":
-      return filesInBucket.value;
-    case "directory-path":
-      return foldersInBucket.value;
-    case "path":
-      return filesAndFoldersInBucket.value;
-    default:
-      return [];
+const dynamicCssClass = computed<string[]>(() => {
+  const cssClasses = [];
+  if (props.sizeModifier) {
+    cssClasses.push(`form-control-${props.sizeModifier}`);
   }
-});
-
-watch(s3Path, () => {
-  if (dataPath.value && !formState.advancedInput) {
-    updateStringFromS3();
+  if (!helpTextPresent.value) {
+    cssClasses.push("rounded-end");
   }
-});
-
-watch(
-  () => s3Path.bucket,
-  (newVal, oldVal) => {
-    if (newVal !== oldVal) {
-      updateKeysInBucket(newVal);
-    }
-  },
-);
-
-watch(() => formState.stringVal, updateValue);
-watch(selectedResource, () => {
-  if (clowmResource.value && !formState.advancedInput) {
-    updateStringFromResource();
+  if (props.border) {
+    cssClasses.push("border", "border-secondary");
   }
+  return cssClasses;
 });
 
-watch(
-  () => props.modelValue,
-  (newVal) => {
-    if (formState.stringVal != newVal) {
-      formState.stringVal = newVal;
-      formState.advancedInput = true;
-    }
-  },
-);
-
-watch(
-  () => formState.advancedInput,
-  (newVal, oldValue) => {
-    if (newVal != oldValue && !newVal) {
-      if (clowmResource.value) {
-        updateStringFromResource();
-      } else if (dataPath.value) {
-        updateStringFromS3();
-      }
-    }
-  },
-);
-
-function updateValue() {
-  emit("update:modelValue", formState.stringVal);
-}
-
-function updateStringFromS3() {
-  formState.stringVal = !s3Path.bucket
-    ? undefined
-    : `s3://${s3Path.bucket}${s3Path.key ? "/" + s3Path.key : ""}`;
-}
-
-function updateStringFromResource() {
-  formState.stringVal =
-    resourceRepository.resourceMapping[selectedResource.resourceId]?.versions[
-      selectedResource.resourceVersionIndex
-    ]?.cluster_path ?? undefined;
-}
-
-function updateKeysInBucket(bucketName?: string) {
-  if (bucketName != null) {
-    s3objectRepository.fetchS3Objects(
-      bucketName,
-      bucketRepository.ownPermissions[bucketName]?.file_prefix ?? undefined,
-    );
-  }
-}
-
-onMounted(() => {
-  formState.stringVal = props.modelValue;
-  if (formState.stringVal) {
-    formState.advancedInput = true;
-  }
-});
+const stringInput = ref<HTMLInputElement | undefined>(undefined);
+const pattern = computed<string>(() => props.parameter["pattern"]);
+const helpTextPresent = computed<boolean>(() => props.parameter["help_text"]);
 </script>
 
 <template>
-  <template v-if="clowmResource && !formState.advancedInput">
-    <select
-      class="form-select border border-secondary"
-      :required="props.required"
-      v-model="selectedResource.resourceId"
-    >
-      <option selected disabled value="">Please select a resource</option>
-      <option
-        v-for="resource in resourceRepository.resources"
-        :key="resource.resource_id"
-        :value="resource.resource_id"
-      >
-        {{ resource.name }}
-      </option>
-    </select>
-    <select
-      class="form-select border border-secondary"
-      :class="{ 'rounded-end': props.removeAdvanced && !helpTextPresent }"
-      :required="props.required || selectedResource.resourceId != undefined"
-      v-model="selectedResource.resourceVersionIndex"
-      :disabled="selectedResource.resourceId.length === 0"
-    >
-      <option disabled>Please select a version</option>
-      <option
-        v-for="(version, index) in resourceRepository.resourceMapping[
-          selectedResource.resourceId
-        ]?.versions ?? []"
-        :key="version.resource_version_id"
-        :value="index"
-      >
-        {{ version.release }}
-        {{ version.status === Status.LATEST ? "- Latest" : "" }}
-      </option>
-    </select>
-  </template>
-  <template v-else-if="dataPath && !formState.advancedInput">
-    <select
-      class="form-select border border-secondary"
-      :required="props.required"
-      v-model="s3Path.bucket"
-    >
-      <option selected disabled value="">Please select a bucket</option>
-      <option
-        v-for="bucket in bucketRepository.ownBucketsAndFullPermissions"
-        :key="bucket"
-        :value="bucket"
-      >
-        {{ bucket }}
-      </option>
-    </select>
-    <input
-      class="form-control border-top border-secondary"
-      :list="'datalistOptions2' + randomIDSuffix"
-      :class="{ 'rounded-end': props.removeAdvanced && !helpTextPresent }"
-      placeholder="Type to search in bucket..."
-      :required="props.required && dataFormat === 'file-path'"
-      v-model="s3Path.key"
-      :pattern="pattern"
-    />
-    <datalist :id="'datalistOptions2' + randomIDSuffix">
-      <option v-for="obj in keyDataList" :value="obj" :key="obj" />
-    </datalist>
-  </template>
-  <template v-else>
-    <input
-      ref="stringInput"
-      class="form-control border border-secondary"
-      :class="{ 'rounded-end': props.removeAdvanced && !helpTextPresent }"
-      type="text"
-      v-model="formState.stringVal"
-      :required="props.required"
-      :aria-describedby="props.helpId"
-      :pattern="pattern"
-    />
-  </template>
-  <div v-if="(clowmResource || dataPath) && !props.removeAdvanced">
-    <input
-      type="checkbox"
-      class="btn-check"
-      :id="'flexCheckDefault' + randomIDSuffix"
-      autocomplete="off"
-      v-model="formState.advancedInput"
-    />
-    <label
-      class="btn btn-outline-secondary rounded-0"
-      :class="{ 'rounded-end': !helpTextPresent }"
-      :for="'flexCheckDefault' + randomIDSuffix"
-      >Advanced</label
-    >
-  </div>
+  <input
+    ref="stringInput"
+    class="form-control"
+    :class="dynamicCssClass"
+    type="text"
+    v-model="model"
+    :required="props.required"
+    :aria-describedby="props.helpId"
+    :pattern="pattern"
+  />
 </template>
 
 <style scoped></style>
diff --git a/src/components/resources/modals/UploadResourceInfoModal.vue b/src/components/resources/modals/UploadResourceInfoModal.vue
index 3b33bd34cb50e96858aeb700eb73d2ff096c97fa..52174003972327cf7d4b87c4a355dda4d5785ddd 100644
--- a/src/components/resources/modals/UploadResourceInfoModal.vue
+++ b/src/components/resources/modals/UploadResourceInfoModal.vue
@@ -137,7 +137,7 @@ onMounted(() => {
   <bootstrap-modal
     :modalId="props.modalId"
     modal-label="Upload Resource Info Modal"
-    sizeModifier="lg"
+    sizeModifierModal="lg"
     :track-modal-value="resourceVersion?.resource_version_id"
   >
     <template #header>How to upload a resource to the cluster</template>
diff --git a/src/stores/resources.ts b/src/stores/resources.ts
index ee419a29020337957bbe9e866e777e4fc1148186..31cbaf40311e61851a07d07d677bc9ab16a244f6 100644
--- a/src/stores/resources.ts
+++ b/src/stores/resources.ts
@@ -56,6 +56,15 @@ export const useResourceStore = defineStore({
     resources(): ResourceOut[] {
       return Object.values(this.resourceMapping);
     },
+    versionMapping(): Record<string, ResourceVersionOut> {
+      const mapping: Record<string, ResourceVersionOut> = {};
+      for (const resource of this.resources) {
+        for (const version of resource.versions) {
+          mapping[version.resource_version_id] = version;
+        }
+      }
+      return mapping;
+    },
     ownResources(): ResourceOut[] {
       return Object.values(this.ownResourceMapping);
     },
diff --git a/src/types/PropTypes.ts b/src/types/PropTypes.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a937fe2c84e2fb896e30c3045fff6caf1f568f8f
--- /dev/null
+++ b/src/types/PropTypes.ts
@@ -0,0 +1 @@
+export type SizeModifierType = "sm" | "lg";
diff --git a/src/views/workflows/CreateParameterTranslationView.vue b/src/views/workflows/CreateParameterTranslationView.vue
index 6c025bb454eaec78f55c3d399a1850c65d5b9c2e..33f14ba17310f0019efe95fc4b78589a8c1d1512 100644
--- a/src/views/workflows/CreateParameterTranslationView.vue
+++ b/src/views/workflows/CreateParameterTranslationView.vue
@@ -5,11 +5,10 @@ import { computed, onMounted, reactive, ref, watch } from "vue";
 import {
   DocumentationEnum,
   type ParameterExtension_Input,
-  type ResourcePath_Input,
 } from "@/client/workflow";
 import type { ClowmInfo } from "@/types/ClowmInfo";
 import { useResourceStore } from "@/stores/resources";
-import { Status } from "@/client/resource";
+import ParameterInput from "@/components/parameter-schema/form-mode/ParameterInput.vue";
 
 const props = defineProps<{
   versionId: string;
@@ -141,7 +140,6 @@ function addDefaultParameter(param: string, index: number) {
         parameterState.extension.defaults[param] = {
           resource_id: "",
           resource_version_id: "",
-          suffix: "",
         };
         break;
       }
@@ -158,59 +156,23 @@ function addDefaultParameter(param: string, index: number) {
   }
 }
 
-function updateDefaultResourceParam(param: string, resource_id?: string) {
-  if (
-    parameterState.extension.defaults &&
-    resource_id &&
-    isResource(parameterState.extension.defaults[param])
-  ) {
-    (
-      parameterState.extension.defaults[param] as ResourcePath_Input
-    ).resource_version_id = "";
-    (
-      parameterState.extension.defaults[param] as ResourcePath_Input
-    ).resource_id = resource_id;
-  }
-}
-
-function updateDefaultResourceVersionParam(
-  param: string,
-  resource_version_id?: string,
-) {
-  if (
-    parameterState.extension.defaults &&
-    resource_version_id &&
-    isResource(parameterState.extension.defaults[param])
-  ) {
-    (
-      parameterState.extension.defaults[param] as ResourcePath_Input
-    ).resource_version_id = resource_version_id;
-    resourceRepository.fetchResourceTree(
-      (parameterState.extension.defaults[param] as ResourcePath_Input)
-        .resource_id,
-      resource_version_id,
-    );
-  }
-}
-
-function isResource(
-  param: ResourcePath_Input | string | number | boolean | undefined,
-): param is ResourcePath_Input {
-  return typeof param === "object";
-}
-
 function makeResourceParameter(param: string) {
   parameterState.formValidated = false;
   parameterState.resourceParameters.add(param);
   parameterState.extension.defaults![param] = {
     resource_id: "",
     resource_version_id: "",
-    suffix: "",
   };
 }
 
 function deleteDefaultParameter(param: string) {
-  parameterState.resourceParameters.delete(param);
+  if (
+    !workflowRepository.documentationFiles[
+      props.versionId
+    ]?.clowm_info?.resourceParameters?.includes(param)
+  ) {
+    parameterState.resourceParameters.delete(param);
+  }
   delete parameterState.extension.defaults?.[param];
   parameterPools.defaults.push(param);
   if (Object.keys(parameterState.extension.defaults ?? {}).length === 0) {
@@ -304,7 +266,7 @@ onMounted(() => {
     novalidate
     @submit.prevent="submitForm()"
   >
-    <table class="table table-bordered">
+    <table class="table table-bordered align-middle">
       <thead>
         <tr>
           <th scope="col"><b>Parameter</b></th>
@@ -313,201 +275,34 @@ onMounted(() => {
       </thead>
       <tbody v-if="parameterState.extension.defaults" id="defaultParamsTable">
         <tr
-          v-for="(param, index) in Object.keys(
-            parameterState.extension.defaults,
-          )"
+          v-for="param in Object.keys(parameterState.extension.defaults)"
           :key="param"
         >
           <td style="width: 10%">{{ param }}</td>
           <td class="d-flex justify-content-between align-items-center">
-            <input
+            <div class="flex-fill input-group">
+              <parameter-input
+                :parameter="parameterSchema[param]"
+                v-model="parameterState.extension.defaults[param]"
+                size-modifier="sm"
+                :resource-parameter="
+                  parameterState.resourceParameters.has(param)
+                "
+                :advanced="!parameterState.resourceParameters.has(param)"
+                raw-model
+              />
+            </div>
+            <button
               v-if="
-                getParameterType(param) === 'number' ||
-                getParameterType(param) === 'integer'
+                !parameterState.resourceParameters.has(param) &&
+                getParameterType(param) === 'string'
               "
-              type="number"
-              required
-              class="form-control form-control-sm flex-grow"
-              v-model="parameterState.extension.defaults[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="parameterState.extension.defaults[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="parameterState.extension.defaults[param]"
-                />
-                <label
-                  class="form-check-label"
-                  :for="'falseOption' + param.replace(/\./g, '')"
-                  >False</label
-                >
-              </div>
-            </div>
-            <select
-              v-else-if="parameterSchema[param]?.['enum']"
-              class="form-select form-select-sm flex-grow"
-              required
-              v-model="parameterState.extension.defaults[param]"
+              class="btn btn-primary btn-sm ms-2"
+              type="button"
+              @click="makeResourceParameter(param)"
             >
-              <option
-                v-for="option in parameterSchema[param]?.['enum']"
-                :key="option"
-                :value="option"
-              >
-                {{ option }}
-              </option>
-            </select>
-            <template v-else>
-              <div
-                class="input-group"
-                v-if="parameterState.resourceParameters.has(param)"
-              >
-                <select
-                  class="form-select form-select-sm"
-                  required
-                  :value="
-                    (
-                      parameterState.extension.defaults[
-                        param
-                      ] as ResourcePath_Input
-                    ).resource_id
-                  "
-                  @change="
-                    (event) =>
-                      updateDefaultResourceParam(
-                        param,
-                        (event.target as HTMLSelectElement)?.value,
-                      )
-                  "
-                >
-                  >
-                  <option selected disabled value="">
-                    Please select a resource
-                  </option>
-                  <option
-                    v-for="resource in resourceRepository.resources"
-                    :key="resource.resource_id"
-                    :value="resource.resource_id"
-                  >
-                    {{ resource.name }}
-                  </option>
-                </select>
-                <select
-                  class="form-select form-select-sm"
-                  required
-                  :value="
-                    (
-                      parameterState.extension.defaults[
-                        param
-                      ] as ResourcePath_Input
-                    ).resource_version_id
-                  "
-                  @change="
-                    (event) =>
-                      updateDefaultResourceVersionParam(
-                        param,
-                        (event.target as HTMLSelectElement)?.value,
-                      )
-                  "
-                  :disabled="
-                    (
-                      parameterState.extension.defaults[
-                        param
-                      ] as ResourcePath_Input
-                    ).resource_id?.length === 0
-                  "
-                >
-                  <option disabled selected value="">
-                    Please select a version
-                  </option>
-                  <option
-                    v-for="version in resourceRepository.resourceMapping[
-                      (
-                        parameterState.extension.defaults[
-                          param
-                        ] as ResourcePath_Input
-                      ).resource_id
-                    ]?.versions ?? []"
-                    :key="version.resource_version_id"
-                    :value="version.resource_version_id"
-                  >
-                    {{ version.release }}
-                    {{ version.status === Status.LATEST ? "- Latest" : "" }}
-                  </option>
-                </select>
-                <input
-                  type="text"
-                  class="form-control rounded-end form-control-sm"
-                  placeholder="/optional/path/in/resource/..."
-                  minlength="2"
-                  maxlength="256"
-                  pattern="\/\S*"
-                  v-model="
-                    (
-                      parameterState.extension.defaults[
-                        param
-                      ] as ResourcePath_Input
-                    ).suffix
-                  "
-                  :list="'datalistOptions-' + index"
-                />
-                <datalist :id="'datalistOptions-' + index">
-                  <option
-                    v-for="file in resourceRepository.resourceTreeList[
-                      (
-                        parameterState.extension.defaults[
-                          param
-                        ] as ResourcePath_Input
-                      ).resource_version_id
-                    ] ?? []"
-                    :value="file"
-                    :key="file"
-                  />
-                </datalist>
-              </div>
-              <template v-else>
-                <input
-                  type="text"
-                  class="form-control form-control-sm flex-grow"
-                  v-model="parameterState.extension.defaults[param]"
-                  :pattern="parameterSchema[param]?.['pattern']"
-                />
-                <button
-                  v-if="!parameterState.resourceParameters.has(param)"
-                  class="btn btn-primary btn-sm ms-2"
-                  type="button"
-                  :id="'make-resource-param-' + param.replace(/\./g, '')"
-                  @click="makeResourceParameter(param)"
-                >
-                  Resource
-                </button>
-              </template>
-            </template>
+              Resource
+            </button>
             <button
               type="button"
               class="btn btn-outline-danger btn-sm ms-2"