Skip to content
Snippets Groups Projects
ParameterGroupForm.vue 6.23 KiB
Newer Older
  • Learn to ignore specific revisions
  • <script setup lang="ts">
    import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
    import { computed, watch } 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";
    
    const props = defineProps({
      parameterGroup: {
        type: Object,
        required: true,
        validator(value: Record<string, never>) {
          return "object" === value["type"];
        },
      },
      parameterGroupName: {
        type: String,
        required: true,
      },
      modelValue: {
        type: Object,
        required: true,
      },
    });
    const title = computed<string>(() => props.parameterGroup["title"]);
    const icon = computed<string>(() => props.parameterGroup["fa_icon"]);
    const description = computed<string>(() => props.parameterGroup["description"]);
    const groupHidden = computed<boolean>(() =>
      Object.keys(parameters.value).reduce(
        (acc: boolean, val: string) => acc && parameters.value[val]["hidden"],
        true
      )
    );
    const parameters = computed<Record<string, never>>(
      () => props.parameterGroup["properties"]
    );
    
    const formInput = computed(() => props.modelValue);
    const emit = defineEmits<{
      (
        e: "update:modelValue",
        value: Record<string, number | string | boolean | undefined>
      ): void;
    }>();
    
    function parameterRequired(
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      parameterGroup: Record<string, any>,
      parameterName: string
    ): boolean {
      return (
        parameterGroup["required"]?.includes(parameterName) || // parameter is required
        parameterGroup["dependentRequired"]?.[parameterName] // parameter is required when another parameter is set
          ?.map((param: string) => formInput.value[param])
          ?.reduce((acc: boolean, val: string) => acc || val, false)
      );
    }
    
    watch(
      formInput,
      (newVal) => {
        //console.log("Group", props.parameterGroupName, newVal);
        emit("update:modelValue", newVal);
      },
      {
        deep: true,
      }
    );
    </script>
    
    <template>
      <div class="card bg-dark mb-3" v-if="!groupHidden">
        <h2 class="card-header" :id="props.parameterGroupName">
          <font-awesome-icon :icon="icon" class="me-2" v-if="icon" />
          {{ title }}
        </h2>
        <div class="card-body">
          <h5 class="card-title" v-if="description">{{ description }}</h5>
          <template
            v-for="(parameter, parameterName) in parameters"
            :key="parameterName"
          >
            <template v-if="!parameter['hidden']">
              <div class="input-group">
                <span class="input-group-text" :id="parameterName + '-help'">
                  <font-awesome-icon
                    class="me-2 text-dark"
                    :icon="parameter['fa_icon']"
                    v-if="parameter['fa_icon']"
                  />
                  <code>--{{ parameterName }}</code>
                </span>
                <parameter-number-input
                  v-if="
                    parameter['type'] === 'number' ||
                    parameter['type'] === 'integer'
                  "
                  :parameter-name="parameterName"
                  :parameter="parameter"
                  :help-id="parameterName + '-help'"
                  :required="parameterRequired(parameterGroup, parameterName)"
                  :model-value="formInput[parameterName]"
                  @update:model-value="
                    (newValue) => (formInput[parameterName] = newValue)
                  "
                />
                <parameter-boolean-input
                  v-else-if="parameter['type'] === 'boolean'"
                  :parameter-name="parameterName"
                  :parameter="parameter"
                  :help-id="parameterName + '-help'"
                  :model-value="formInput[parameterName]"
                  @update:model-value="
                    (newValue) => (formInput[parameterName] = newValue)
                  "
                />
                <template v-else-if="parameter['type'] === 'string'">
                  <parameter-enum-input
                    v-if="parameter['enum']"
                    :parameter-name="parameterName"
                    :parameter="parameter"
                    :model-value="formInput[parameterName]"
                    :required="parameterRequired(parameterGroup, parameterName)"
                    @update:model-value="
                      (newValue) => (formInput[parameterName] = newValue)
                    "
                  />
                  <parameter-string-input
                    v-else
                    :parameter-name="parameterName"
                    :parameter="parameter"
                    :model-value="formInput[parameterName]"
                    :required="parameterRequired(parameterGroup, parameterName)"
                    @update:model-value="
                      (newValue) => (formInput[parameterName] = newValue)
                    "
                  />
                </template>
                <span
                  class="input-group-text cursor-pointer px-2"
                  v-if="parameter['help_text']"
                  data-bs-toggle="collapse"
                  :data-bs-target="'#helpCollapse' + parameterName"
                  aria-expanded="false"
                  aria-controls="collapseExample"
                >
                  <font-awesome-icon
                    class="cursor-pointer"
                    icon="fa-solid fa-circle-question"
                  />
                </span>
              </div>
              <label v-if="parameter['description']"
                ><markdown-renderer :markdown="parameter['description']"
              /></label>
              <div
                class="collapse p-2 pb-0 bg-dark mx-2 mt-1 flex-shrink-1"
                :id="'helpCollapse' + parameterName"
                v-if="parameter['help_text']"
              >
                <markdown-renderer
                  class="helpTextCode"
                  :markdown="parameter['help_text']"
                />
                <p v-if="parameter['pattern']">
                  Pattern: <code>{{ parameter["pattern"] }}</code>
                </p>
              </div>
            </template>
          </template>
        </div>
      </div>
    </template>
    
    <style scoped>
    div.card-body {
    
      backdrop-filter: brightness(1.2);
    
    }
    span.cursor-pointer:hover {
      color: var(--bs-info);
      background: var(--bs-light);
    }
    </style>