First try at refactoring again
This commit is contained in:
@@ -13,7 +13,8 @@
|
|||||||
<i class="fas fa-list"></i> List VMs
|
<i class="fas fa-list"></i> List VMs
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="search-box">
|
<!-- Search box - visible when drawer is open -->
|
||||||
|
<div v-if="showList" class="search-box">
|
||||||
<i class="fas fa-search search-icon"></i>
|
<i class="fas fa-search search-icon"></i>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -36,6 +37,21 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- VM Display - visible when drawer is closed -->
|
||||||
|
<div v-else class="vm-display" @click="openSearchDrawer">
|
||||||
|
<button
|
||||||
|
v-if="selectedVMName"
|
||||||
|
class="vm-clear-btn"
|
||||||
|
@click.stop="clearSelectedVM"
|
||||||
|
title="Clear selected VM"
|
||||||
|
>
|
||||||
|
<i class="fas fa-times"></i>
|
||||||
|
</button>
|
||||||
|
<i class="fas fa-desktop vm-icon"></i>
|
||||||
|
<span class="vm-name">{{ selectedVMName || 'Select a VM...' }}</span>
|
||||||
|
<i class="fas fa-search search-icon-right"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="filter-dropdown" ref="filterDropdown">
|
<div class="filter-dropdown" ref="filterDropdown">
|
||||||
<button
|
<button
|
||||||
class="btn btn-outline-secondary dropdown-toggle"
|
class="btn btn-outline-secondary dropdown-toggle"
|
||||||
@@ -197,6 +213,11 @@ const isVMSelected = (vmName) => {
|
|||||||
localStorage.getItem('selectedVMId') === vmName;
|
localStorage.getItem('selectedVMId') === vmName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Computed property for the selected VM name
|
||||||
|
const selectedVMName = computed(() => {
|
||||||
|
return props.selectedVM || props.vmFromUrl || localStorage.getItem('selectedVMId') || '';
|
||||||
|
});
|
||||||
|
|
||||||
// Initialize the component
|
// Initialize the component
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// Set up click outside handler
|
// Set up click outside handler
|
||||||
@@ -304,35 +325,68 @@ const handleBlur = (event) => {
|
|||||||
|
|
||||||
// Handle click on search input
|
// Handle click on search input
|
||||||
const handleSearchClick = () => {
|
const handleSearchClick = () => {
|
||||||
if (props.showList) {
|
// When clicking the search input, activate filtering mode
|
||||||
// When clicking the search input while list is open, activate filtering
|
if (props.showList && !isFilterActive.value) {
|
||||||
isFilterActive.value = true;
|
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
|
// Toggle the VM list
|
||||||
const toggleList = () => {
|
const toggleList = () => {
|
||||||
emit('toggle-list');
|
// If the list is already open, toggle filtering instead of closing
|
||||||
|
if (props.showList) {
|
||||||
// When toggling the list, ensure search text is preserved
|
// If we're in list mode (not filtering) and the button is clicked, close the drawer
|
||||||
const savedSearchText = localStorage.getItem('vmSearchText');
|
if (!isFilterActive.value) {
|
||||||
|
// Save the current search text before closing
|
||||||
if (!props.showList) {
|
if (props.modelValue) {
|
||||||
// When opening the list, restore search text if available
|
searchText.value = props.modelValue;
|
||||||
if (savedSearchText && !inputValue.value) {
|
// Save to localStorage
|
||||||
|
localStorage.setItem('vmSearchText', props.modelValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the drawer
|
||||||
|
emit('toggle-list');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle filtering mode
|
||||||
|
isFilterActive.value = !isFilterActive.value;
|
||||||
|
|
||||||
|
// If we're turning filtering on, make sure the search text is applied
|
||||||
|
if (isFilterActive.value && searchText.value) {
|
||||||
|
inputValue.value = searchText.value;
|
||||||
|
emit('update:modelValue', searchText.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're turning filtering off (switching to list mode), scroll to selected VM
|
||||||
|
if (!isFilterActive.value) {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
inputValue.value = savedSearchText;
|
scrollToSelectedVM();
|
||||||
searchText.value = savedSearchText;
|
|
||||||
emit('update:modelValue', savedSearchText);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No need to emit toggle-list since we're not closing the list
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the list is closed, open it without filtering
|
||||||
|
if (!props.showList) {
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schedule scrolling to selected VM after the list opens
|
||||||
|
nextTick(() => {
|
||||||
|
scrollToSelectedVM();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('toggle-list');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle clear button click
|
// Handle clear button click
|
||||||
@@ -372,23 +426,9 @@ const clearSearch = () => {
|
|||||||
|
|
||||||
// Clear selected VM
|
// Clear selected VM
|
||||||
const clearSelectedVM = () => {
|
const clearSelectedVM = () => {
|
||||||
// Clear the input value
|
|
||||||
inputValue.value = '';
|
|
||||||
|
|
||||||
// Clear from localStorage
|
// Clear from localStorage
|
||||||
localStorage.removeItem('selectedVMId');
|
localStorage.removeItem('selectedVMId');
|
||||||
|
|
||||||
// Don't clear vmSearchText - that's for search history
|
|
||||||
// Only clear if the input value matches the selected VM
|
|
||||||
const savedVMId = localStorage.getItem('selectedVMId');
|
|
||||||
const savedSearchText = localStorage.getItem('vmSearchText');
|
|
||||||
if (savedSearchText === savedVMId) {
|
|
||||||
localStorage.removeItem('vmSearchText');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show the VM list
|
|
||||||
emit('toggle-list');
|
|
||||||
|
|
||||||
// Emit event to parent component
|
// Emit event to parent component
|
||||||
emit('clear-vm');
|
emit('clear-vm');
|
||||||
};
|
};
|
||||||
@@ -663,6 +703,26 @@ const loadFiltersFromLocalStorage = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Method to open the search drawer
|
||||||
|
const openSearchDrawer = () => {
|
||||||
|
// Only open if it's not already open
|
||||||
|
if (!props.showList) {
|
||||||
|
// Set filter active to true to indicate we're in search mode
|
||||||
|
isFilterActive.value = true;
|
||||||
|
|
||||||
|
// Emit toggle-list to open the drawer
|
||||||
|
emit('toggle-list');
|
||||||
|
|
||||||
|
// Focus the search input after the drawer opens
|
||||||
|
nextTick(() => {
|
||||||
|
const searchInput = document.querySelector('.search-input');
|
||||||
|
if (searchInput) {
|
||||||
|
searchInput.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -976,4 +1036,66 @@ const loadFiltersFromLocalStorage = () => {
|
|||||||
border-color: #0d6efd;
|
border-color: #0d6efd;
|
||||||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add these styles for the VM display */
|
||||||
|
.vm-display {
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 200px;
|
||||||
|
height: 38px;
|
||||||
|
padding: 0.375rem 0.75rem;
|
||||||
|
padding-left: 40px;
|
||||||
|
padding-right: 30px;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vm-display:hover {
|
||||||
|
background-color: #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vm-clear-btn {
|
||||||
|
position: absolute;
|
||||||
|
left: 8px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: #6c757d;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
transition: color 0.2s;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vm-clear-btn:hover {
|
||||||
|
color: #dc3545;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vm-icon {
|
||||||
|
color: #6c757d;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vm-name {
|
||||||
|
font-weight: 500;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-icon-right {
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
Reference in New Issue
Block a user