Fix search bar behaviour (step 1)
This commit is contained in:
parent
4e5274c6f0
commit
e588df9fca
@ -94,7 +94,7 @@
|
|||||||
:data-vm-name="vm.name"
|
:data-vm-name="vm.name"
|
||||||
class="vm-list-item"
|
class="vm-list-item"
|
||||||
:class="{ 'active': selectedVM === vm.name || vmFromUrl === vm.name }"
|
:class="{ 'active': selectedVM === vm.name || vmFromUrl === vm.name }"
|
||||||
@click="() => { console.log('VM clicked:', vm); handleVMSelect(vm); }"
|
@click="handleVMSelect(vm)"
|
||||||
>
|
>
|
||||||
<div v-if="selectedVM === vm.name || vmFromUrl === vm.name" class="active-indicator"></div>
|
<div v-if="selectedVM === vm.name || vmFromUrl === vm.name" class="active-indicator"></div>
|
||||||
<div class="vm-item-content">
|
<div class="vm-item-content">
|
||||||
@ -140,15 +140,6 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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',
|
||||||
@ -161,71 +152,187 @@ const emit = defineEmits([
|
|||||||
'reset-filters'
|
'reset-filters'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// UI state refs
|
||||||
const showFilterMenu = ref(false);
|
const showFilterMenu = ref(false);
|
||||||
const filterDropdown = ref(null);
|
const filterDropdown = ref(null);
|
||||||
const filterMenu = ref(null);
|
const filterMenu = ref(null);
|
||||||
const controlsBar = ref(null);
|
const controlsBar = ref(null);
|
||||||
|
const vmListContainer = ref(null);
|
||||||
|
|
||||||
// Add local state for filters
|
// Search state refs
|
||||||
|
const inputValue = ref('');
|
||||||
|
const searchText = ref('');
|
||||||
|
const isFilterActive = ref(false);
|
||||||
|
|
||||||
|
// Filter state
|
||||||
const appliedFilters = ref({
|
const appliedFilters = ref({
|
||||||
states: {},
|
states: {},
|
||||||
nodes: {}
|
nodes: {}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add new ref for tracking search active state
|
// Initialize the component
|
||||||
const searchActive = ref(false);
|
onMounted(() => {
|
||||||
|
// Set up click outside handler
|
||||||
|
document.addEventListener('click', handleClickOutside);
|
||||||
|
|
||||||
// Local ref to track input value
|
// Initialize input value based on selected VM
|
||||||
const inputValue = ref('');
|
if (!props.showList && (props.selectedVM || props.vmFromUrl)) {
|
||||||
|
inputValue.value = props.selectedVM || props.vmFromUrl;
|
||||||
|
} else if (props.showList && props.modelValue) {
|
||||||
|
inputValue.value = props.modelValue;
|
||||||
|
searchText.value = props.modelValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Add a ref to the VM list container
|
onUnmounted(() => {
|
||||||
const vmListContainer = ref(null);
|
document.removeEventListener('click', handleClickOutside);
|
||||||
|
});
|
||||||
|
|
||||||
// Add a ref to store the last search query
|
// Handle search input
|
||||||
const lastSearchQuery = ref('');
|
const handleSearch = (event) => {
|
||||||
|
const value = event.target.value;
|
||||||
|
inputValue.value = value;
|
||||||
|
searchText.value = value;
|
||||||
|
isFilterActive.value = true;
|
||||||
|
|
||||||
// Add a flag to track if filtering should be applied
|
emit('update:modelValue', value);
|
||||||
const filterActive = ref(false);
|
emit('search', value);
|
||||||
|
};
|
||||||
|
|
||||||
// Add a flag to track if a search has been performed
|
// Handle focus on search input
|
||||||
const hasSearched = ref(false);
|
const handleFocus = (event) => {
|
||||||
|
// If the list is not shown, show it
|
||||||
|
if (!props.showList) {
|
||||||
|
emit('toggle-list');
|
||||||
|
} else {
|
||||||
|
// If the list is already shown, activate filtering
|
||||||
|
isFilterActive.value = true;
|
||||||
|
|
||||||
// Add a flag to track if we should maintain focus after list refresh
|
// Restore search text if available
|
||||||
const maintainFocusAfterRefresh = ref(false);
|
if (searchText.value) {
|
||||||
|
inputValue.value = searchText.value;
|
||||||
// Watch both showList and selectedVM to update input value
|
emit('update:modelValue', searchText.value);
|
||||||
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
|
|
||||||
const effectiveVM = selectedVM || vmFromUrl;
|
|
||||||
if (effectiveVM) {
|
|
||||||
inputValue.value = effectiveVM;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 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 }
|
|
||||||
);
|
|
||||||
|
|
||||||
// Watch modelValue to update input when searching
|
|
||||||
watch(() => props.modelValue, (newVal) => {
|
|
||||||
if (newVal) {
|
|
||||||
lastSearchQuery.value = newVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit('focus', event);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle blur on search input
|
||||||
|
const handleBlur = (event) => {
|
||||||
|
emit('blur', event);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle click on search input
|
||||||
|
const handleSearchClick = () => {
|
||||||
if (props.showList) {
|
if (props.showList) {
|
||||||
inputValue.value = newVal || '';
|
// When clicking the search input while list is open, activate filtering
|
||||||
|
isFilterActive.value = true;
|
||||||
|
|
||||||
|
// Restore search text if available
|
||||||
|
if (searchText.value && searchText.value !== inputValue.value) {
|
||||||
|
inputValue.value = searchText.value;
|
||||||
|
emit('update:modelValue', searchText.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Toggle the VM list
|
||||||
|
const toggleList = () => {
|
||||||
|
if (props.showList) {
|
||||||
|
// If we're closing the list, save the search text
|
||||||
|
if (props.modelValue) {
|
||||||
|
searchText.value = props.modelValue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If we're opening the list, deactivate filtering
|
||||||
|
isFilterActive.value = false;
|
||||||
|
|
||||||
|
// Restore search text in the input, but don't apply filtering
|
||||||
|
if (searchText.value) {
|
||||||
|
inputValue.value = searchText.value;
|
||||||
|
emit('update:modelValue', searchText.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('toggle-list');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clear search
|
||||||
|
const clearSearch = () => {
|
||||||
|
inputValue.value = '';
|
||||||
|
searchText.value = '';
|
||||||
|
isFilterActive.value = false;
|
||||||
|
emit('update:modelValue', '');
|
||||||
|
emit('clear');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Select a VM
|
||||||
|
const handleVMSelect = (vm) => {
|
||||||
|
console.log('Selecting VM:', vm);
|
||||||
|
emit('select-vm', vm);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle click outside
|
||||||
|
const handleClickOutside = (event) => {
|
||||||
|
if (showFilterMenu.value &&
|
||||||
|
filterMenu.value &&
|
||||||
|
!filterMenu.value.contains(event.target) &&
|
||||||
|
!filterDropdown.value.contains(event.target)) {
|
||||||
|
showFilterMenu.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Toggle filter menu
|
||||||
|
const toggleFilterMenu = () => {
|
||||||
|
showFilterMenu.value = !showFilterMenu.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Filter toggle
|
||||||
|
const handleFilterToggle = (type, value) => {
|
||||||
|
appliedFilters.value[type][value] = !appliedFilters.value[type][value];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reset filters
|
||||||
|
const handleResetFilters = () => {
|
||||||
|
Object.keys(appliedFilters.value.states).forEach(state => {
|
||||||
|
appliedFilters.value.states[state] = false;
|
||||||
|
});
|
||||||
|
Object.keys(appliedFilters.value.nodes).forEach(node => {
|
||||||
|
appliedFilters.value.nodes[node] = false;
|
||||||
|
});
|
||||||
|
showFilterMenu.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Computed properties
|
||||||
|
const filteredVMs = computed(() => {
|
||||||
|
let filtered = [...props.vmList];
|
||||||
|
|
||||||
|
// Apply text filter only if filtering is active
|
||||||
|
if (isFilterActive.value && 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)
|
||||||
|
.map(([state]) => state);
|
||||||
|
if (activeStates.length > 0) {
|
||||||
|
filtered = filtered.filter(vm => activeStates.includes(vm.state));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply node filters
|
||||||
|
const activeNodes = Object.entries(appliedFilters.value.nodes)
|
||||||
|
.filter(([_, isActive]) => isActive)
|
||||||
|
.map(([node]) => node);
|
||||||
|
if (activeNodes.length > 0) {
|
||||||
|
filtered = filtered.filter(vm => activeNodes.includes(vm.node));
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Calculate available states from vmList
|
// Calculate available states from vmList
|
||||||
@ -234,23 +341,7 @@ const availableStates = computed(() => {
|
|||||||
props.vmList.forEach(vm => {
|
props.vmList.forEach(vm => {
|
||||||
if (vm.state) states.add(vm.state);
|
if (vm.state) states.add(vm.state);
|
||||||
});
|
});
|
||||||
const statesArray = Array.from(states);
|
return Array.from(states).sort();
|
||||||
|
|
||||||
// Remove 'start' if it exists
|
|
||||||
const startIndex = statesArray.indexOf('start');
|
|
||||||
if (startIndex !== -1) {
|
|
||||||
statesArray.splice(startIndex, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort remaining states
|
|
||||||
statesArray.sort();
|
|
||||||
|
|
||||||
// Add 'start' back at beginning if it was present
|
|
||||||
if (startIndex !== -1) {
|
|
||||||
statesArray.unshift('start');
|
|
||||||
}
|
|
||||||
|
|
||||||
return statesArray;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Calculate available nodes from vmList
|
// Calculate available nodes from vmList
|
||||||
@ -279,24 +370,7 @@ watch([availableStates, availableNodes], ([states, nodes]) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update handleFilterToggle to work with local state
|
// Count active filters
|
||||||
const handleFilterToggle = (type, value) => {
|
|
||||||
searchActive.value = true;
|
|
||||||
appliedFilters.value[type][value] = !appliedFilters.value[type][value];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update handleResetFilters
|
|
||||||
const handleResetFilters = () => {
|
|
||||||
Object.keys(appliedFilters.value.states).forEach(state => {
|
|
||||||
appliedFilters.value.states[state] = false;
|
|
||||||
});
|
|
||||||
Object.keys(appliedFilters.value.nodes).forEach(node => {
|
|
||||||
appliedFilters.value.nodes[node] = false;
|
|
||||||
});
|
|
||||||
showFilterMenu.value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Computed
|
|
||||||
const activeFiltersCount = computed(() => {
|
const activeFiltersCount = computed(() => {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
Object.values(appliedFilters.value.states).forEach(isActive => {
|
Object.values(appliedFilters.value.states).forEach(isActive => {
|
||||||
@ -308,307 +382,47 @@ const activeFiltersCount = computed(() => {
|
|||||||
return count;
|
return count;
|
||||||
});
|
});
|
||||||
|
|
||||||
const filteredVMs = computed(() => {
|
// Status class helper
|
||||||
let filtered = [...props.vmList];
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only apply other filters if search is active
|
|
||||||
if (searchActive.value) {
|
|
||||||
// Apply state filters
|
|
||||||
const activeStates = Object.entries(appliedFilters.value.states)
|
|
||||||
.filter(([_, isActive]) => isActive)
|
|
||||||
.map(([state]) => state);
|
|
||||||
if (activeStates.length > 0) {
|
|
||||||
filtered = filtered.filter(vm => activeStates.includes(vm.state));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply node filters
|
|
||||||
const activeNodes = Object.entries(appliedFilters.value.nodes)
|
|
||||||
.filter(([_, isActive]) => isActive)
|
|
||||||
.map(([node]) => node);
|
|
||||||
if (activeNodes.length > 0) {
|
|
||||||
filtered = filtered.filter(vm => activeNodes.includes(vm.node));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Methods
|
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
const clearSearch = () => {
|
|
||||||
emit('update:modelValue', '');
|
|
||||||
emit('clear');
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleList = () => {
|
|
||||||
console.log('toggleList called, showList:', props.showList);
|
|
||||||
|
|
||||||
// If we're opening the list (currently closed)
|
|
||||||
if (!props.showList) {
|
|
||||||
// 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
|
|
||||||
if (props.modelValue) {
|
|
||||||
lastSearchQuery.value = props.modelValue;
|
|
||||||
// Don't clear the model value when closing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit('toggle-list');
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleVMSelect = (vm) => {
|
|
||||||
console.log('Selecting VM:', vm);
|
|
||||||
|
|
||||||
// Don't clear the search query or change filter state
|
|
||||||
// Just emit the select-vm event
|
|
||||||
emit('select-vm', vm);
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleFilterMenu = () => {
|
|
||||||
showFilterMenu.value = !showFilterMenu.value;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getStatusClass = (state) => {
|
const getStatusClass = (state) => {
|
||||||
if (!state) return '';
|
if (!state) return 'status-unknown';
|
||||||
|
|
||||||
switch(state.toLowerCase()) {
|
switch(state.toLowerCase()) {
|
||||||
case 'start':
|
case 'start': return 'status-running';
|
||||||
return 'status-running';
|
case 'stop': return 'status-stopped';
|
||||||
case 'stop':
|
case 'disable': return 'status-paused';
|
||||||
return 'status-stopped';
|
default: return 'status-unknown';
|
||||||
case 'disable':
|
|
||||||
return 'status-disabled';
|
|
||||||
default:
|
|
||||||
return '';
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update click outside handling to close both filter menu and list
|
// Watch for changes in showList
|
||||||
const handleClickOutside = (event) => {
|
watch(() => props.showList, (isVisible) => {
|
||||||
// If click is outside the controls bar
|
if (!isVisible) {
|
||||||
if (!controlsBar.value?.contains(event.target)) {
|
// When list is closed, show selected VM
|
||||||
if (props.showList) {
|
|
||||||
emit('toggle-list'); // Close the list
|
|
||||||
}
|
|
||||||
showFilterMenu.value = false; // Close filter menu
|
|
||||||
}
|
|
||||||
// If click is inside controls bar but outside filter dropdown
|
|
||||||
else if (showFilterMenu.value && !filterDropdown.value?.contains(event.target)) {
|
|
||||||
showFilterMenu.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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(() => {
|
|
||||||
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 });
|
|
||||||
|
|
||||||
// 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' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update the watch for showList to handle search state
|
|
||||||
watch(() => props.showList, (isOpen) => {
|
|
||||||
if (isOpen) {
|
|
||||||
// When list opens, restore the last search query
|
|
||||||
nextTick(() => {
|
|
||||||
if (lastSearchQuery.value) {
|
|
||||||
inputValue.value = lastSearchQuery.value;
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Also scroll to selected VM
|
|
||||||
scrollToSelectedVM();
|
|
||||||
} else {
|
|
||||||
// When list closes, show the selected VM but preserve search
|
|
||||||
const effectiveVM = props.selectedVM || props.vmFromUrl;
|
const effectiveVM = props.selectedVM || props.vmFromUrl;
|
||||||
if (effectiveVM) {
|
if (effectiveVM) {
|
||||||
inputValue.value = effectiveVM;
|
inputValue.value = effectiveVM;
|
||||||
}
|
}
|
||||||
// Reset filter active state when closing
|
} else {
|
||||||
filterActive.value = false;
|
// When list is opened, show search text if available
|
||||||
|
if (searchText.value) {
|
||||||
|
inputValue.value = searchText.value;
|
||||||
|
} else {
|
||||||
|
inputValue.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only activate filtering if opened via search input, not List VMs button
|
||||||
|
// This is handled in handleFocus and toggleList
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Also call it when selectedVM or vmFromUrl changes
|
// Watch for changes in selectedVM or vmFromUrl
|
||||||
watch([() => props.selectedVM, () => props.vmFromUrl], () => {
|
watch([() => props.selectedVM, () => props.vmFromUrl], ([selectedVM, vmFromUrl]) => {
|
||||||
if (props.showList) {
|
if (!props.showList) {
|
||||||
scrollToSelectedVM();
|
const effectiveVM = selectedVM || vmFromUrl;
|
||||||
}
|
if (effectiveVM) {
|
||||||
});
|
inputValue.value = effectiveVM;
|
||||||
|
|
||||||
// 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>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user