- DeviceDetail: display compliance status with badge + parameter diffs - Home: show compliance badge in device list - ConfigurationDetail: compliance report tab with device list + diffs - ConfigurationEdit: bumpType selector (patch/minor/major), remove version field - ConfigurationsList: tag filter, name search, compliance column - ComplianceBadge: pending/compliant/in_progress/failed/non_compliant states - CriteriaEditor: parameterCriteria editor with autocomplete on parameter names - AutocompleteInput: new reusable autocomplete component - i18n: compliance labels in fr/en Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
80 lines
1.9 KiB
Vue
80 lines
1.9 KiB
Vue
<script setup lang="ts">
|
|
import { ref, computed } from 'vue'
|
|
|
|
const props = defineProps<{
|
|
modelValue: string
|
|
suggestions?: string[]
|
|
placeholder?: string
|
|
id?: string
|
|
monospace?: boolean
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'update:modelValue', value: string): void
|
|
}>()
|
|
|
|
const isOpen = ref(false)
|
|
const input = ref<HTMLInputElement | null>(null)
|
|
|
|
const filtered = computed(() => {
|
|
if (!props.suggestions?.length) return []
|
|
const q = props.modelValue.toLowerCase()
|
|
return props.suggestions.filter((s) => s.toLowerCase().includes(q))
|
|
})
|
|
|
|
function onInput(e: Event) {
|
|
emit('update:modelValue', (e.target as HTMLInputElement).value)
|
|
isOpen.value = true
|
|
}
|
|
|
|
function select(val: string) {
|
|
emit('update:modelValue', val)
|
|
isOpen.value = false
|
|
input.value?.blur()
|
|
}
|
|
|
|
function onBlur() {
|
|
setTimeout(() => { isOpen.value = false }, 150)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="autocomplete-wrapper position-relative">
|
|
<input
|
|
:id="id"
|
|
ref="input"
|
|
type="text"
|
|
class="form-control form-control-sm"
|
|
:class="{ 'font-monospace': monospace }"
|
|
:value="modelValue"
|
|
:placeholder="placeholder"
|
|
autocomplete="off"
|
|
@input="onInput"
|
|
@focus="isOpen = true"
|
|
@blur="onBlur"
|
|
@keydown.escape="isOpen = false"
|
|
/>
|
|
<ul
|
|
v-if="isOpen && filtered.length > 0"
|
|
class="autocomplete-dropdown list-unstyled mb-0 position-absolute w-100 border rounded shadow-sm bg-white"
|
|
style="top: 100%; left: 0; z-index: 1000; max-height: 200px; overflow-y: auto;"
|
|
>
|
|
<li
|
|
v-for="val in filtered"
|
|
:key="val"
|
|
class="autocomplete-item px-3 py-1 small font-monospace"
|
|
style="cursor: pointer;"
|
|
@mousedown.prevent="select(val)"
|
|
>
|
|
{{ val }}
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.autocomplete-item:hover {
|
|
background-color: #f0f0f0;
|
|
}
|
|
</style>
|