Fix VM search displaying

This commit is contained in:
Joshua Boniface 2025-03-02 13:54:25 -05:00
parent 0107197b2b
commit f879fddd95
3 changed files with 114 additions and 43 deletions

View File

@ -14,7 +14,7 @@
<input <input
type="text" type="text"
placeholder="Search VMs..." placeholder="Search VMs..."
:value="!showList ? selectedVM : modelValue" :value="inputValue"
@input="handleSearch" @input="handleSearch"
@focus="handleFocus" @focus="handleFocus"
@blur="handleBlur" @blur="handleBlur"
@ -91,7 +91,7 @@
v-for="vm in filteredVMs" v-for="vm in filteredVMs"
:key="vm.name" :key="vm.name"
class="vm-list-item" class="vm-list-item"
:class="{ 'active': selectedVM === vm.name }" :class="{ 'active': selectedVM === vm.name || vmFromUrl === vm.name }"
@click="handleVMSelect(vm)" @click="handleVMSelect(vm)"
> >
<div class="vm-item-content"> <div class="vm-item-content">
@ -130,9 +130,22 @@ const props = defineProps({
selectedVM: { selectedVM: {
type: String, type: String,
default: '' default: ''
},
vmFromUrl: {
type: String,
default: ''
} }
}); });
// Direct debug log of props
console.log('VMSearchBar props:', {
modelValue: props.modelValue,
showList: props.showList,
selectedVM: props.selectedVM,
vmFromUrl: props.vmFromUrl,
vmListLength: props.vmList.length
});
const emit = defineEmits([ const emit = defineEmits([
'update:modelValue', 'update:modelValue',
'search', 'search',
@ -159,6 +172,31 @@ const appliedFilters = ref({
// Add new ref for tracking search active state // Add new ref for tracking search active state
const searchActive = ref(false); const searchActive = ref(false);
// Local ref to track input value
const inputValue = ref('');
// 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) {
// When list is closed, show selected VM or VM from URL
inputValue.value = effectiveVM;
} else {
// When list is open, show search query
inputValue.value = props.modelValue || '';
}
}, { immediate: true }
);
// Watch modelValue to update input when searching
watch(() => props.modelValue, (newVal) => {
if (props.showList) {
inputValue.value = newVal || '';
}
});
// Calculate available states from vmList // Calculate available states from vmList
const availableStates = computed(() => { const availableStates = computed(() => {
const states = new Set(); const states = new Set();
@ -274,9 +312,11 @@ const filteredVMs = computed(() => {
// Methods // Methods
const handleSearch = (event) => { const handleSearch = (event) => {
searchActive.value = true; if (props.showList) {
emit('update:modelValue', event.target.value); searchActive.value = true;
emit('search', event.target.value); emit('update:modelValue', event.target.value);
emit('search', event.target.value);
}
}; };
const handleFocus = (event) => { const handleFocus = (event) => {
@ -294,6 +334,7 @@ const clearSearch = () => {
}; };
const toggleList = () => { const toggleList = () => {
console.log('toggleList called, showList:', props.showList);
searchActive.value = false; searchActive.value = false;
if (props.showList) { if (props.showList) {
// If we're closing the list, clear the search // If we're closing the list, clear the search
@ -303,6 +344,8 @@ const toggleList = () => {
}; };
const handleVMSelect = (vm) => { const handleVMSelect = (vm) => {
console.log('handleVMSelect called with:', vm);
emit('update:modelValue', ''); // Clear search query
emit('select-vm', vm); emit('select-vm', vm);
}; };
@ -347,6 +390,15 @@ onMounted(() => {
onUnmounted(() => { onUnmounted(() => {
document.removeEventListener('click', handleClickOutside); document.removeEventListener('click', handleClickOutside);
}); });
// Add a watcher for selectedVM with a debug log
watch(() => props.selectedVM, (newVal, oldVal) => {
console.log('VMSearchBar selectedVM changed:', { newVal, oldVal });
// Update input value when selectedVM changes
if (!props.showList && newVal) {
inputValue.value = newVal;
}
}, { immediate: true });
</script> </script>
<style scoped> <style scoped>

View File

@ -1,11 +1,13 @@
<template> <template>
<div class="overview-container"> <div class="overview-container">
<VMSearchBar <VMSearchBar
:key="searchBarKey"
v-model="searchQuery" v-model="searchQuery"
:selected-vm="selectedVM"
:vm-from-url="route.query.vm"
:show-list="showVMList" :show-list="showVMList"
:show-clear-button="true" :show-clear-button="true"
:vm-list="props.vmData" :vm-list="props.vmData"
:selected-vm="selectedVM"
@search="handleSearch" @search="handleSearch"
@focus="handleSearchFocus" @focus="handleSearchFocus"
@blur="handleSearchBlur" @blur="handleSearchBlur"
@ -139,11 +141,15 @@ const props = defineProps({
type: Object, type: Object,
required: true, required: true,
default: () => ({}) default: () => ({})
},
loading: {
type: Boolean,
default: false
} }
}); });
// State // Use ref and sync with route
const selectedVM = ref(''); const selectedVM = ref(route.query.vm || '');
const searchQuery = ref(''); const searchQuery = ref('');
const showVMList = ref(true); const showVMList = ref(true);
const searchActive = ref(false); const searchActive = ref(false);
@ -194,21 +200,11 @@ const toggleVMList = () => {
// Select a VM // Select a VM
const selectVM = (vm) => { const selectVM = (vm) => {
isLoading.value = true; // Update the ref first
nextTick(() => { selectedVM.value = vm.name;
const vmExists = props.vmData.some(vm => vm.name === vm.name); invalidVMSelected.value = false;
if (vmExists) { showVMList.value = false;
selectedVM.value = vm.name; router.push({ query: { vm: vm.name } });
invalidVMSelected.value = false;
showVMList.value = false;
} else {
selectedVM.value = '';
invalidVMSelected.value = true;
showVMList.value = false;
}
router.push({ query: { vm: vm.name } });
isLoading.value = false;
});
}; };
// Clear search // Clear search
@ -219,22 +215,22 @@ const clearSearch = () => {
// Lifecycle hooks // Lifecycle hooks
onMounted(() => { onMounted(() => {
// Initialize with URL state if present console.log('VMOverview mounted, route.query.vm:', route.query.vm);
const vmFromQuery = route.query.vm; const vmFromQuery = route.query.vm;
if (vmFromQuery) { if (vmFromQuery) {
console.log('Setting selectedVM to:', vmFromQuery);
selectedVM.value = vmFromQuery;
isLoading.value = true; isLoading.value = true;
// Check if we already have data showVMList.value = false;
// If we have data, verify the VM exists
if (props.vmData.length) { if (props.vmData.length) {
selectVM({ name: vmFromQuery }); const vmExists = props.vmData.some(v => v.name === vmFromQuery);
} else { invalidVMSelected.value = !vmExists;
// If no data yet, set the VM but mark as pending verification
selectedVM.value = vmFromQuery;
showVMList.value = false;
// Don't set invalidVMSelected yet - wait for data
} }
isLoading.value = false;
} else if (props.vmData.length > 0) { } else if (props.vmData.length > 0) {
showVMList.value = true; showVMList.value = true;
selectedVM.value = '';
invalidVMSelected.value = false; invalidVMSelected.value = false;
} }
}); });
@ -243,16 +239,19 @@ onUnmounted(() => {
// Remove event listeners and clean up resources // Remove event listeners and clean up resources
}); });
// Watch for route changes to update selected VM // Watch for route changes to update selectedVM
watch(() => route.query.vm, (newVm) => { watch(() => route.query.vm, (newVm) => {
// Explicitly update the ref when route changes
selectedVM.value = newVm || '';
if (newVm) { if (newVm) {
selectVM({ name: newVm }); // Just update UI state, don't trigger another route change
invalidVMSelected.value = false;
showVMList.value = false;
} else if (props.vmData.length > 0) { } else if (props.vmData.length > 0) {
selectedVM.value = '';
showVMList.value = true; showVMList.value = true;
invalidVMSelected.value = false; invalidVMSelected.value = false;
} }
}); }, { immediate: true });
// Watch for changes in the VM list visibility // Watch for changes in the VM list visibility
watch(() => showVMList.value, (isVisible) => { watch(() => showVMList.value, (isVisible) => {
@ -266,17 +265,32 @@ watch(() => showVMList.value, (isVisible) => {
// Add watcher for vmData to handle loading state // Add watcher for vmData to handle loading state
watch(() => props.vmData, (newData) => { watch(() => props.vmData, (newData) => {
if (isLoading.value && selectedVM.value) { if (selectedVM.value && newData.length) {
const vmExists = newData.some(vm => vm.name === selectedVM.value); const vmExists = newData.some(vm => vm.name === selectedVM.value);
if (!vmExists) { invalidVMSelected.value = !vmExists;
invalidVMSelected.value = true;
} else {
invalidVMSelected.value = false;
}
isLoading.value = false;
} }
}, { immediate: true }); }, { immediate: true });
// Add debug watcher
watch(() => selectedVM.value, (newVal) => {
console.log('VMOverview selectedVM changed:', newVal);
}, { immediate: true });
// Watch for vmData changes to update VMSearchBar
watch(() => props.vmData, (newData) => {
if (newData.length && selectedVM.value) {
console.log('VM data loaded, updating VMSearchBar with selectedVM:', selectedVM.value);
// Force a refresh of the VMSearchBar by toggling a key
nextTick(() => {
// This will force the VMSearchBar to re-render with the correct data
searchBarKey.value = Date.now();
});
}
});
// Add a key to force VMSearchBar to re-render when data changes
const searchBarKey = ref(0);
// Helper functions // Helper functions
const getStateColor = (state) => { const getStateColor = (state) => {
if (!state) return ''; if (!state) return '';

View File

@ -5,6 +5,7 @@
:vmData="vmData" :vmData="vmData"
:metricsData="metricsData" :metricsData="metricsData"
:clusterData="clusterData" :clusterData="clusterData"
:loading="isLoading"
/> />
</div> </div>
</template> </template>
@ -29,6 +30,10 @@ const props = defineProps({
type: Object, type: Object,
required: true, required: true,
default: () => ({}) default: () => ({})
},
isLoading: {
type: Boolean,
default: false
} }
}); });
</script> </script>