Fix list highlighting

This commit is contained in:
Joshua Boniface 2025-03-02 14:01:34 -05:00
parent f879fddd95
commit 493dd94f21

View File

@ -86,14 +86,16 @@
<div v-if="filteredVMs.length === 0" class="no-vms-message">
<p>No VMs match your search criteria</p>
</div>
<div v-else class="vm-list">
<div v-else class="vm-list" ref="vmListContainer">
<button
v-for="vm in filteredVMs"
:key="vm.name"
:data-vm-name="vm.name"
class="vm-list-item"
:class="{ 'active': selectedVM === vm.name || vmFromUrl === vm.name }"
@click="handleVMSelect(vm)"
>
<div v-if="selectedVM === vm.name || vmFromUrl === vm.name" class="active-indicator"></div>
<div class="vm-item-content">
<div class="vm-name">{{ vm.name }}</div>
<div class="vm-status" :class="getStatusClass(vm.state)">
@ -108,7 +110,7 @@
</template>
<script setup>
import { ref, computed, onMounted, onUnmounted, watch } from 'vue';
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue';
const props = defineProps({
modelValue: {
@ -175,17 +177,29 @@ const searchActive = ref(false);
// Local ref to track input value
const inputValue = ref('');
// Add a ref to the VM list container
const vmListContainer = ref(null);
// Watch both showList and selectedVM to update input value
watch([() => props.showList, () => props.selectedVM, () => props.vmFromUrl],
([showList, selectedVM, vmFromUrl]) => {
console.log('Watch triggered:', { showList, selectedVM, vmFromUrl });
const effectiveVM = selectedVM || vmFromUrl;
if (!showList && effectiveVM) {
watch([() => props.showList, () => props.selectedVM, () => props.vmFromUrl, () => props.modelValue],
([showList, selectedVM, vmFromUrl, modelValue]) => {
console.log('Watch triggered:', { showList, selectedVM, vmFromUrl, modelValue });
if (!showList) {
// When list is closed, show selected VM or VM from URL
inputValue.value = effectiveVM;
const effectiveVM = selectedVM || vmFromUrl;
if (effectiveVM) {
inputValue.value = effectiveVM;
}
} else {
// When list is open, show search query
inputValue.value = props.modelValue || '';
// When list is open, show search query if it exists
if (modelValue) {
inputValue.value = modelValue;
searchActive.value = true;
} else {
// If no search query, show placeholder
inputValue.value = '';
}
}
}, { immediate: true }
);
@ -280,16 +294,16 @@ const activeFiltersCount = computed(() => {
const filteredVMs = computed(() => {
let filtered = [...props.vmList];
// Only apply filters if search is active
// Always apply search filter if there's a query
if (props.modelValue) {
const query = props.modelValue.toLowerCase();
filtered = filtered.filter(vm =>
vm.name.toLowerCase().includes(query)
);
}
// Only apply other filters if search is active
if (searchActive.value) {
// Apply search filter
if (props.modelValue) {
const query = props.modelValue.toLowerCase();
filtered = filtered.filter(vm =>
vm.name.toLowerCase().includes(query)
);
}
// Apply state filters
const activeStates = Object.entries(appliedFilters.value.states)
.filter(([_, isActive]) => isActive)
@ -312,15 +326,18 @@ const filteredVMs = computed(() => {
// Methods
const handleSearch = (event) => {
if (props.showList) {
searchActive.value = true;
emit('update:modelValue', event.target.value);
emit('search', event.target.value);
}
// Always update the model value to preserve search
searchActive.value = true;
emit('update:modelValue', event.target.value);
emit('search', event.target.value);
};
const handleFocus = (event) => {
searchActive.value = true;
// If there's a saved search, make sure it's applied
if (props.modelValue) {
inputValue.value = props.modelValue;
}
emit('focus', event);
};
@ -335,10 +352,12 @@ const clearSearch = () => {
const toggleList = () => {
console.log('toggleList called, showList:', props.showList);
searchActive.value = false;
if (props.showList) {
// If we're closing the list, clear the search
emit('update:modelValue', '');
// If we're opening the list
if (!props.showList) {
// Restore previous search if any
if (props.modelValue) {
searchActive.value = true;
}
}
emit('toggle-list');
};
@ -399,6 +418,33 @@ watch(() => props.selectedVM, (newVal, oldVal) => {
inputValue.value = newVal;
}
}, { immediate: true });
// Add a function to scroll to the selected VM
const scrollToSelectedVM = () => {
if (!props.showList || (!props.selectedVM && !props.vmFromUrl)) return;
nextTick(() => {
const selectedVMName = props.selectedVM || props.vmFromUrl;
const activeElement = document.querySelector(`.vm-list-item[data-vm-name="${selectedVMName}"]`);
if (activeElement && vmListContainer.value) {
activeElement.scrollIntoView({ block: 'center', behavior: 'smooth' });
}
});
};
// Call scrollToSelectedVM when the list becomes visible
watch(() => props.showList, (isVisible) => {
if (isVisible) {
scrollToSelectedVM();
}
});
// Also call it when selectedVM or vmFromUrl changes
watch([() => props.selectedVM, () => props.vmFromUrl], () => {
if (props.showList) {
scrollToSelectedVM();
}
});
</script>
<style scoped>
@ -497,7 +543,7 @@ watch(() => props.selectedVM, (newVal, oldVal) => {
display: flex;
align-items: center;
padding: 0.75rem 1rem;
border: none;
border: none !important;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
background-color: white;
text-align: left;
@ -507,16 +553,43 @@ watch(() => props.selectedVM, (newVal, oldVal) => {
}
.vm-list-item:last-child {
border-bottom: none;
border-bottom: none !important;
}
.vm-list-item:hover {
background-color: rgba(0, 0, 0, 0.03);
background-color: rgba(0, 0, 0, 0.03) !important;
}
.vm-list-item.active {
background-color: rgba(13, 110, 253, 0.1);
border-left: 3px solid #0d6efd;
background-color: rgba(13, 110, 253, 0.15) !important;
position: relative !important;
z-index: 1 !important;
}
.vm-list-item.active::before {
content: '';
position: absolute !important;
left: 0 !important;
top: 0 !important;
bottom: 0 !important;
width: 4px !important;
background-color: #0d6efd !important;
z-index: 2 !important;
}
.controls-bar .vm-list-container .vm-list .vm-list-item.active {
background-color: rgba(13, 110, 253, 0.15) !important;
position: relative !important;
}
.controls-bar .vm-list-container .vm-list .vm-list-item.active::before {
content: '';
position: absolute !important;
left: 0 !important;
top: 0 !important;
bottom: 0 !important;
width: 4px !important;
background-color: #0d6efd !important;
}
.vm-item-content {
@ -639,4 +712,14 @@ watch(() => props.selectedVM, (newVal, oldVal) => {
padding-top: 0.5rem;
margin-top: 0.5rem;
}
.active-indicator {
position: absolute !important;
left: 0 !important;
top: 0 !important;
bottom: 0 !important;
width: 4px !important;
background-color: #0d6efd !important;
z-index: 2 !important;
}
</style>