-
Daniel Göbel authored
#105
Daniel Göbel authored#105
ParameterResourceInput.vue 5.83 KiB
<script setup lang="ts">
import { Status } from "@/client/resource";
import { computed, onMounted, reactive, watch } from "vue";
import { useResourceStore } from "@/stores/resources";
import type { ExtendedColors, SizeModifierType } from "@/types/PropTypes";
const model = defineModel<string | undefined>({
required: true,
});
const resourceRegex = /CLDB-([\da-f]{32})\/(latest|[\da-f]{32})([/\S]*)/g;
const props = defineProps<{
// eslint-disable-next-line @typescript-eslint/no-explicit-any
parameter: Record<string, any>;
required?: boolean;
sizeModifier?: SizeModifierType;
border?: ExtendedColors;
allowRaw?: boolean;
}>();
const emit = defineEmits<{
(e: "switch-to-raw"): void;
}>();
const resourceRepository = useResourceStore();
const randomIDSuffix = Math.random().toString(16).substring(2, 8);
type ResourcePath = {
resource_id: string;
resource_version_id: string;
suffix?: string;
};
const resource = reactive<ResourcePath>({
resource_id: "",
resource_version_id: "",
suffix: undefined,
});
const helpTextPresent = computed<boolean>(() => props.parameter["help_text"]);
const baseDynamicClass = computed<string[]>(() =>
props.border ? ["border", `border-${props.border}`] : [],
);
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 && !props.allowRaw) {
cssClasses.push("rounded-end");
}
return cssClasses;
});
function updateResourceId(rid: string) {
resource.resource_id = rid;
resource.resource_version_id = "";
model.value = translateToModel();
}
function updateResourceVersionId(rvid: string) {
resource.resource_version_id = rvid;
model.value = translateToModel();
resourceRepository.fetchResourceTree(resource.resource_id, rvid);
}
watch(model, (newVal, oldVal) => {
if (newVal != oldVal && newVal !== translateToModel()) {
parseModel(newVal);
}
});
function parseModel(val?: string) {
if (val == undefined || val.length === 0) {
Object.assign(resource, {
resource_id: "",
resource_version_id: "",
suffix: undefined,
});
} else {
const match = resourceRegex.exec(val);
if (match) {
const tempResource: ResourcePath = {
resource_id: "",
resource_version_id: "",
};
tempResource.resource_id = hexToUUID(match[1]);
tempResource.suffix = match[3];
tempResource.resource_version_id =
match[2].length === 32
? hexToUUID(match[2])
: resourceRepository.getLatestVersion(resource.resource_id);
if (
resourceRepository.resourceMapping[tempResource.resource_id] ==
undefined ||
resourceRepository.versionMapping[tempResource.resource_version_id] ==
undefined
) {
// Missing resource
emit("switch-to-raw");
return;
}
Object.assign(resource, tempResource);
} else {
// Not resource path
emit("switch-to-raw");
}
}
}
function hexToUUID(hex?: string): string {
if (hex) {
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
}
return "";
}
watch(
() => resource.suffix,
(newVal, oldVal) => {
if (newVal !== oldVal) {
model.value = translateToModel();
}
},
);
function translateToModel(): string {
if (resource.resource_version_id.length === 0) {
return "";
}
let val =
resourceRepository.versionMapping[resource.resource_version_id]
?.cluster_path ?? "";
if (resource.suffix != undefined && val.length > 0) {
val = val + resource.suffix;
}
return val;
}
onMounted(() => {
parseModel(model.value);
});
</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"
: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>
<button
v-if="allowRaw"
type="button"
class="btn btn-outline-secondary"
@click="emit('switch-to-raw')"
>
Advanced
</button>
</template>
<style scoped></style>