dashboard/new-dashboard/src/components/common/BranchSelect.vue (227 lines of code) (raw):
<template>
<MultiSelect
v-model="branchValue"
title="Branch"
:loading="branchConfigurator.state.loading"
:disabled="branchConfigurator.state.disabled"
:options="branchItems"
:placeholder="placeholder"
option-label="label"
option-value="value"
:show-toggle-all="false"
panel-class="w-fit"
panel-style="overflow: visible"
:selection-limit="selectionLimit"
:filter="hasManyElements"
@hide="clearSubMenu"
>
<template #value="slotProps">
<div class="group flex items-center gap-1">
<div class="w-4 h-4">
<BranchIcon />
</div>
<span v-if="!slotProps.value || slotProps.value.length === 0">
{{ placeholder }}
</span>
<span v-if="slotProps.value && slotProps.value.length === 1">
{{ slotProps.value[0] }}
</span>
<span v-if="slotProps.value && slotProps.value.length > 1">
{{ branchesSelectLabelFormat(slotProps.value) }}
</span>
<ChevronDownIcon
class="-mr-1 ml-1 h-5 w-5 shrink-0"
aria-hidden="true"
/>
</div>
</template>
<template #footer>
<div class="border-t border-solid border-neutral-200 relative">
<ul class="p-multiselect-items p-component">
<li
v-if="versionItems !== undefined && versionItems.length > 0"
class="p-multiselect-option flex items-center gap-2"
@click="openVersionSubmenu"
>
<span class="flex items-center gap-1 overflow-hidden">
Version type
<span
v-if="versionValue !== null && versionValue.length > 0"
class="truncate"
>
{{ versionValue?.length < 2 ? versionValue[0] : `Selected ${versionValue?.length}` }}
</span>
</span>
<span class="pi pi-angle-right ml-[auto]" />
</li>
<li
v-if="triggeredItems.length > 0"
class="p-multiselect-option flex items-center gap-2"
@click="openTriggeredSubmenu"
>
<span class="flex items-center gap-1 overflow-hidden">
Triggered by
<span
v-if="triggeredValueFiltered !== null && triggeredValueFiltered !== undefined && triggeredValueFiltered.length > 0"
class="truncate"
>
{{ triggeredValueFiltered?.length < 2 ? triggeredValueFiltered[0] : `Selected ${triggeredValueFiltered?.length}` }}
</span>
</span>
<span class="pi pi-angle-right ml-[auto]" />
</li>
</ul>
<div
v-if="activeSubMenu === SubMenu.VERSION_TYPE && versionItems.length > 0"
class="absolute p-multiselect-overlay p-component w-[270px] max-h-[200px] branch-select-dropdown"
style="left: 100%"
>
<ul class="p-multiselect-list">
<li
v-for="item in versionItems"
:key="item.label"
>
<div class="flex items-center p-multiselect-option p-component">
<Checkbox
v-model="versionValue"
:value="item.value"
:input-id="item.value"
class="field-checkbox"
/>
<label
class="w-full inline-block"
:for="item.value"
>
<span>{{ item.label }}</span>
</label>
</div>
</li>
</ul>
</div>
<div
v-if="activeSubMenu === SubMenu.TRIGGERED_BY && triggeredItems.length > 0"
class="absolute p-multiselect-overlay p-component w-[270px] max-h-[200px] branch-select-dropdown"
style="left: 100%"
>
<ul class="p-multiselect-items p-component">
<div v-if="triggeredItems.length === 0">No available options</div>
<li
v-for="item in triggeredItems"
:key="item.label"
>
<div class="flex items-center p-multiselect-option p-component">
<Checkbox
v-model="triggeredValue"
:value="item.value"
:input-id="item.value"
class="field-checkbox"
/>
<label
class="w-full inline-block"
:for="item.value"
>
<span>{{ item.label }}</span>
</label>
</div>
</li>
</ul>
</div>
</div>
</template>
<template #dropdownicon>
<span class="hidden" />
</template>
</MultiSelect>
</template>
<script setup lang="ts">
import { ChevronDownIcon } from "@heroicons/vue/20/solid"
import { computed, ref, toValue } from "vue"
import { sortBranches } from "../../configurators/BranchConfigurator"
import { DimensionConfigurator } from "../../configurators/DimensionConfigurator"
import { branchesSelectLabelFormat } from "../../shared/labels"
import { usePlaceholder } from "../charts/placeholder"
import BranchIcon from "./BranchIcon.vue"
interface Props {
branchConfigurator: DimensionConfigurator
releaseConfigurator?: DimensionConfigurator
triggeredByConfigurator?: DimensionConfigurator
selectionLimit?: number
}
const enum SubMenu {
TRIGGERED_BY,
VERSION_TYPE,
}
const triggeredValueFiltered = computed(() => {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
return triggeredValue.value?.filter((it) => it !== null)
})
const activeSubMenu = ref<SubMenu | null>(null)
const openVersionSubmenu = () => {
activeSubMenu.value = SubMenu.VERSION_TYPE
}
const openTriggeredSubmenu = () => {
activeSubMenu.value = SubMenu.TRIGGERED_BY
}
const clearSubMenu = () => {
activeSubMenu.value = null
}
const { branchConfigurator, releaseConfigurator = undefined, triggeredByConfigurator = undefined, selectionLimit = undefined } = defineProps<Props>()
function createItems(configurator?: DimensionConfigurator) {
return computed(() => {
if (configurator == undefined) {
return []
}
const values = (toValue(configurator.values) as string[]).sort((a, b) => {
if (toValue(configurator.selected)?.includes(b)) return 1
if (toValue(configurator.selected)?.includes(a)) return -1
return sortBranches(a, b)
})
return values.map((it) => {
return { label: it, value: it }
})
})
}
function createValueFrom(configurator?: DimensionConfigurator) {
return computed<string[] | null>({
get() {
if (configurator == null) {
return null
}
const values = toValue(configurator.values)
if (values.length === 0) {
return null
}
const value = configurator.selected.value
if (Array.isArray(value)) {
return value
}
return value == null || value === "" ? [] : [value]
},
set(value) {
if (configurator == null) return
configurator.selected.value = value == null || value.length === 0 ? null : value
},
})
}
const branchValue = createValueFrom(branchConfigurator)
const versionValue = createValueFrom(releaseConfigurator)
const triggeredValue = createValueFrom(triggeredByConfigurator)
const branchItems = createItems(branchConfigurator)
const versionItems = createItems(releaseConfigurator)
const triggeredItems = createItems(triggeredByConfigurator)
const placeholder = usePlaceholder(
{ label: "Branch" },
() => branchConfigurator.values.value,
() => branchConfigurator.selected.value
)
const hasManyElements = computed(() => {
return branchItems.value.length > 4
})
</script>
<style>
.branch-select-dropdown {
top: 0;
margin-top: 0;
border-top-left-radius: 0;
}
</style>