Slightly less cursed version selector handling

This commit is contained in:
Nassim Jahnke 2023-02-14 14:36:05 +01:00
parent 8e75016312
commit 036c2ee380
No known key found for this signature in database
GPG Key ID: 6BE3B555EBC5982B
2 changed files with 85 additions and 70 deletions

View File

@ -1,8 +1,9 @@
<script lang="ts" setup>
import { computed, watch } from "vue";
import { computed, Ref, watch } from "vue";
import { PlatformVersion } from "hangar-internal";
import InputCheckbox from "~/lib/components/ui/InputCheckbox.vue";
import ArrowSpoiler from "~/lib/components/design/ArrowSpoiler.vue";
import { ref } from "#imports";
const props = defineProps<{
versions: PlatformVersion[];
@ -18,21 +19,22 @@ const selected = computed({
set: (value) => emit("update:modelValue", value),
});
const selectedParents: Ref<string[]> = ref([]);
const selectedSub: Ref<string[]> = ref([]);
// TODO All of this is horrible
watch(selected, (oldValue, newValue) => {
handleRemoved([...newValue.filter((x) => !oldValue.includes(x))]);
handleAdded([...oldValue.filter((x) => !newValue.includes(x))]);
watch(selectedParents, (oldValue, newValue) => {
handleRemovedParent([...newValue.filter((x) => !oldValue.includes(x))]);
handleAddedParent([...oldValue.filter((x) => !newValue.includes(x))]);
});
watch(selectedSub, (oldValue, newValue) => {
handleRemovedSub([...newValue.filter((x) => !oldValue.includes(x))]);
handleAddedSub([...oldValue.filter((x) => !newValue.includes(x))]);
});
function handleRemoved(removedVersions: string[]) {
function handleRemovedParent(removedVersions: string[]) {
for (const version of removedVersions) {
if (!version.endsWith(".x")) {
handleRemovedSubVersion(version);
continue;
}
const parentVersion = version.substring(0, version.length - 2);
const platformVersion = props.versions.find((v) => v.version === parentVersion);
const platformVersion = props.versions.find((v) => v.version === version);
if (!platformVersion) {
continue;
}
@ -40,92 +42,100 @@ function handleRemoved(removedVersions: string[]) {
// Remove all sub versions
for (const subVersion of platformVersion.subVersions) {
selected.value.splice(selected.value.indexOf(subVersion), 1);
selectedSub.value.splice(selectedSub.value.indexOf(subVersion), 1);
}
}
}
function handleAdded(addedVersions: string[]) {
function handleAddedParent(addedVersions: string[]) {
for (const version of addedVersions) {
if (!version.endsWith(".x")) {
handleAddedSubVersion(version);
continue;
}
const parentVersion = version.substring(0, version.length - 2);
const platformVersion = props.versions.find((v) => v.version === parentVersion);
const platformVersion = props.versions.find((v) => v.version === version);
if (!platformVersion) {
continue;
}
// Add all sub versions
for (const subVersion of platformVersion.subVersions) {
if (!selected.value.includes(subVersion)) {
selected.value.push(subVersion);
selected.value.push(subVersion);
selectedSub.value.push(subVersion);
}
}
}
function handleRemovedSub(removedVersions: string[]) {
for (const version of removedVersions) {
const lastSeparator = version.lastIndexOf(".");
if (lastSeparator === -1) {
continue;
}
const cutVersion = version.substring(0, lastSeparator);
const platformVersion = props.versions.find((v) => v.version === cutVersion || v.version === version);
if (!platformVersion) {
continue;
}
// Unselect parent
if (selectedParents.value.includes(platformVersion.version)) {
selectedParents.value.splice(selectedParents.value.indexOf(platformVersion.version), 1);
}
if (selected.value.includes(platformVersion.version)) {
selected.value.splice(selected.value.indexOf(platformVersion.version), 1);
}
}
}
function handleAddedSub(removedVersions: string[]) {
for (const version of removedVersions) {
const lastSeparator = version.lastIndexOf(".");
if (lastSeparator === -1) {
continue;
}
const cutVersion = version.substring(0, lastSeparator);
const platformVersion = props.versions.find((v) => v.version === cutVersion || v.version === version);
if (!platformVersion) {
continue;
}
// Select parent if all subversions are selected
let selectedAll = true;
for (const v of platformVersion.subVersions) {
if (!selectedSub.value.includes(v)) {
selectedAll = false;
break;
}
}
if (selectedAll) {
if (!selectedParents.value.includes(platformVersion.version)) {
selectedParents.value.push(platformVersion.version);
}
if (!selected.value.includes(platformVersion.version)) {
selected.value.push(platformVersion.version);
}
}
}
}
function handleRemovedSubVersion(version: string) {
const lastSeparator = version.lastIndexOf(".");
if (lastSeparator === -1) {
return;
}
const cutVersion = version.substring(0, lastSeparator);
const platformVersion = props.versions.find((v) => v.version === cutVersion || v.version === version);
if (!platformVersion || !selected.value.includes(platformVersion.version + ".x")) {
return;
}
for (const subVersion of platformVersion.subVersions) {
if (selected.value.includes(subVersion)) {
// Uncheck parent box
selected.value.splice(selected.value.indexOf(platformVersion.version + ".x"), 1);
return;
}
}
}
function handleAddedSubVersion(version: string) {
const lastSeparator = version.lastIndexOf(".");
if (lastSeparator === -1) {
return;
}
const cutVersion = version.substring(0, lastSeparator);
const platformVersion = props.versions.find((v) => v.version === cutVersion || v.version === version);
if (!platformVersion || selected.value.includes(platformVersion.version + ".x")) {
return;
}
for (const subVersion of platformVersion.subVersions) {
if (!selected.value.includes(subVersion)) {
return;
}
}
// Check parent box
selected.value.push(platformVersion.version + ".x");
}
</script>
<template>
<div v-for="version in versions" :key="version.version">
<div v-if="version.subVersions.length !== 0">
<div v-if="!version.subVersions">HUH {{ version }}</div>
<div v-else-if="version.subVersions.length !== 0">
<ArrowSpoiler :open="open">
<template #title>
<div class="mr-8">
<InputCheckbox v-model="selected" :value="version.version + '.x'" :label="version.version" />
<InputCheckbox v-model="selectedParents" :value="version.version" :label="version.version" />
</div>
</template>
<template #content>
<div class="ml-5">
<InputCheckbox v-for="subversion in version.subVersions" :key="subversion" v-model="selected" :value="subversion" :label="subversion" />
<InputCheckbox v-for="subversion in version.subVersions" :key="subversion" v-model="selectedSub" :value="subversion" :label="subversion" />
</div>
</template>
</ArrowSpoiler>
</div>
<InputCheckbox v-else v-model="selected" :value="version.version" :label="version.version" />
<InputCheckbox v-else v-model="selectedSub" :value="version.version" :label="version.version" />
</div>
</template>

View File

@ -217,7 +217,12 @@ useHead(meta);
<div class="platforms">
<h4 class="font-bold mb-1">
{{ i18n.t("hangar.projectSearch.platforms") }}
<span v-if="filters.platform" class="font-normal text-sm hover:(underline) text-gray-600 dark:text-gray-400" @click="filters.platform = null">
<span
v-if="filters.platform"
class="font-normal text-sm hover:(underline) text-gray-600 dark:text-gray-400"
cursor="pointer"
@click="filters.platform = null"
>
{{ i18n.t("hangar.projectSearch.clear") }}
</span>
</h4>