This commit is contained in:
Joshua Boniface 2025-03-02 14:06:38 -05:00
parent bcf0e98b54
commit adfc1d8269
2 changed files with 149 additions and 11 deletions

View File

@ -18,6 +18,7 @@
@input="handleSearch"
@focus="handleFocus"
@blur="handleBlur"
@click="handleSearchClick"
class="form-control search-input"
>
<button
@ -183,6 +184,15 @@ const vmListContainer = ref(null);
// Add a ref to store the last search query
const lastSearchQuery = ref('');
// Add a flag to track if filtering should be applied
const filterActive = ref(false);
// Add a flag to track if a search has been performed
const hasSearched = ref(false);
// Add a flag to track if we should maintain focus after list refresh
const maintainFocusAfterRefresh = ref(false);
// Watch both showList and selectedVM to update input value
watch([() => props.showList, () => props.selectedVM, () => props.vmFromUrl, () => props.modelValue],
([showList, selectedVM, vmFromUrl, modelValue]) => {
@ -301,8 +311,8 @@ const activeFiltersCount = computed(() => {
const filteredVMs = computed(() => {
let filtered = [...props.vmList];
// Always apply search filter if there's a query
if (props.modelValue) {
// Apply search filter if filtering is active OR if a search has been performed
if ((filterActive.value || hasSearched.value) && props.modelValue) {
const query = props.modelValue.toLowerCase();
filtered = filtered.filter(vm =>
vm.name.toLowerCase().includes(query)
@ -335,21 +345,45 @@ const filteredVMs = computed(() => {
const handleSearch = (event) => {
// Always update the model value to preserve search
searchActive.value = true;
filterActive.value = true; // Activate filtering when typing in search
lastSearchQuery.value = event.target.value;
hasSearched.value = true; // Mark that a search has been performed
maintainFocusAfterRefresh.value = true; // Maintain focus after refresh
emit('update:modelValue', event.target.value);
emit('search', event.target.value);
};
const handleFocus = (event) => {
searchActive.value = true;
filterActive.value = true; // Activate filtering when focusing the search bar
maintainFocusAfterRefresh.value = true; // Maintain focus after refresh
// If there's a saved search, make sure it's applied
if (props.modelValue) {
inputValue.value = props.modelValue;
// Force a re-evaluation of the filteredVMs computed property
nextTick(() => {
// This is a hack to force Vue to re-evaluate the computed property
const temp = filteredVMs.value.length;
console.log('Forcing filter application, filtered count:', temp);
});
}
emit('focus', event);
};
const handleBlur = (event) => {
// Only deactivate filtering if no search has been performed
if (!hasSearched.value) {
filterActive.value = false;
}
// Check if the blur was caused by a click outside the component
const isClickOutside = !controlsBar.value?.contains(event.relatedTarget);
if (isClickOutside) {
maintainFocusAfterRefresh.value = false;
}
emit('blur', event);
};
@ -363,21 +397,27 @@ const toggleList = () => {
// If we're opening the list (currently closed)
if (!props.showList) {
// When opening the list, restore the last search query
nextTick(() => {
if (lastSearchQuery.value) {
inputValue.value = lastSearchQuery.value;
searchActive.value = true;
// When opening the list via List VMs button, don't apply filtering initially
// Only deactivate filtering if no search has been performed
if (!hasSearched.value) {
filterActive.value = false;
}
// But always restore the previous search text
if (lastSearchQuery.value) {
// Ensure the model value is preserved
if (props.modelValue !== lastSearchQuery.value) {
emit('update:modelValue', lastSearchQuery.value);
}
});
}
}
// If we're closing the list (currently open)
else {
// When closing, save the current search but don't clear it
// When closing, save the current search
if (props.modelValue) {
lastSearchQuery.value = props.modelValue;
// Don't clear the model value when closing
}
// Don't emit update:modelValue here to preserve the search
}
emit('toggle-list');
@ -425,6 +465,17 @@ const handleClickOutside = (event) => {
onMounted(() => {
document.addEventListener('click', handleClickOutside);
// Add click handler for search input
const searchInput = document.querySelector('.search-input');
if (searchInput) {
searchInput.addEventListener('click', () => {
if (props.showList && props.modelValue) {
filterActive.value = true;
applyFilter();
}
});
}
});
onUnmounted(() => {
@ -460,7 +511,13 @@ watch(() => props.showList, (isOpen) => {
nextTick(() => {
if (lastSearchQuery.value) {
inputValue.value = lastSearchQuery.value;
searchActive.value = true;
// If the user clicked on the search bar to open it, apply the filter
if (document.activeElement &&
document.activeElement.classList.contains('search-input')) {
filterActive.value = true;
applyFilter();
}
}
});
@ -472,6 +529,8 @@ watch(() => props.showList, (isOpen) => {
if (effectiveVM) {
inputValue.value = effectiveVM;
}
// Reset filter active state when closing
filterActive.value = false;
}
});
@ -481,6 +540,73 @@ watch([() => props.selectedVM, () => props.vmFromUrl], () => {
scrollToSelectedVM();
}
});
// Add a method to explicitly apply the filter
const applyFilter = () => {
filterActive.value = true;
// Force computed property re-evaluation
nextTick(() => {
const temp = filteredVMs.value.length;
console.log('Filter applied, filtered count:', temp);
});
};
// Update the watch for props.vmList to maintain focus
watch(() => props.vmList, () => {
// When VM list refreshes, ensure search is preserved
if (props.showList && lastSearchQuery.value) {
// Make sure the model value is preserved
if (props.modelValue !== lastSearchQuery.value) {
emit('update:modelValue', lastSearchQuery.value);
}
// If a search has been performed, keep filtering active
if (hasSearched.value && props.modelValue) {
filterActive.value = true;
// If we should maintain focus, refocus the search input
if (maintainFocusAfterRefresh.value) {
nextTick(() => {
const searchInput = document.querySelector('.search-input');
if (searchInput) {
searchInput.focus();
}
});
}
nextTick(() => {
applyFilter();
});
}
}
});
// Update handleSearchClick to set maintainFocusAfterRefresh
const handleSearchClick = () => {
if (props.showList) {
// When clicking the search input while list is open, always apply filtering
filterActive.value = true;
maintainFocusAfterRefresh.value = true; // Maintain focus after refresh
// If there's a saved search, make sure it's applied to the model
if (lastSearchQuery.value && !props.modelValue) {
emit('update:modelValue', lastSearchQuery.value);
}
// Force filter application
applyFilter();
}
};
// Add a method to force focus on the search input
const focusSearchInput = () => {
nextTick(() => {
const searchInput = document.querySelector('.search-input');
if (searchInput) {
searchInput.focus();
}
});
};
</script>
<style scoped>

View File

@ -173,6 +173,10 @@ const selectedVMData = computed(() => {
const handleSearch = (value) => {
searchQuery.value = value;
searchActive.value = true;
// Store the search query in localStorage for persistence
if (value) {
localStorage.setItem('vmSearchQuery', value);
}
};
// Handle search focus
@ -211,12 +215,20 @@ const selectVM = (vm) => {
const clearSearch = () => {
searchQuery.value = '';
searchActive.value = false;
localStorage.removeItem('vmSearchQuery');
};
// Lifecycle hooks
onMounted(() => {
console.log('VMOverview mounted, route.query.vm:', route.query.vm);
const vmFromQuery = route.query.vm;
// Restore previous search query from localStorage if available
const savedSearch = localStorage.getItem('vmSearchQuery');
if (savedSearch) {
searchQuery.value = savedSearch;
}
if (vmFromQuery) {
console.log('Setting selectedVM to:', vmFromQuery);
selectedVM.value = vmFromQuery;