diff --git a/ui/app/components/TextareaAutocomplete.vue b/ui/app/components/TextareaAutocomplete.vue
index d833d3a8..ca0d7535 100644
--- a/ui/app/components/TextareaAutocomplete.vue
+++ b/ui/app/components/TextareaAutocomplete.vue
@@ -77,10 +77,22 @@ const appendFlag = (flag: string) => {
}
const onInput = () => {
- showList.value = true
- highlightedIndex.value = filteredOptions.value.length ? 0 : -1
+ const lastWord = localValue.value.split(/\s+/).pop() || ''
+ showList.value = lastWord.length > 0
+ highlightedIndex.value = (showList.value && filteredOptions.value.length && lastWord.length > 0) ? 0 : -1
}
+// Reset scroll position when filtered options change
+watch(filteredOptions, () => {
+ highlightedIndex.value = filteredOptions.value.length > 0 && showList.value ? 0 : -1
+ nextTick(() => {
+ const dropdown = document.querySelector('.dropdown-content')
+ if (dropdown) {
+ dropdown.scrollTop = 0
+ }
+ })
+})
+
const hideList = () => setTimeout(() => { showList.value = false; highlightedIndex.value = -1 }, 100)
const onKeydown = (e: KeyboardEvent) => {
@@ -119,9 +131,11 @@ const onKeydown = (e: KeyboardEvent) => {
if (el) el.scrollIntoView({ block: 'nearest' })
})
} else if (e.key === 'Enter' || e.key === 'Tab') {
+ const lastWord = localValue.value.split(/\s+/).pop() || ''
const selected = highlightedIndex.value >= 0 && highlightedIndex.value < filteredOptions.value.length ?
filteredOptions.value[highlightedIndex.value] : undefined
- if (selected) {
+ // Only autocomplete if there's a partial word being typed
+ if (selected && lastWord.trim().length > 0) {
e.preventDefault()
appendFlag(selected.value)
}
diff --git a/ui/app/layouts/default.vue b/ui/app/layouts/default.vue
index 0b8e5a3c..492b5307 100644
--- a/ui/app/layouts/default.vue
+++ b/ui/app/layouts/default.vue
@@ -104,7 +104,15 @@
loadImage(true)" />
-
+
+
+ Loading application configuration. This usually takes less than a second.
+
+ If this is taking too long, please check that the backend server is running and that the WebSocket
+ connection is functional.
+
+
diff --git a/ui/app/pages/browser/[...slug].vue b/ui/app/pages/browser/[...slug].vue
index c70ac7a0..f1e06e18 100644
--- a/ui/app/pages/browser/[...slug].vue
+++ b/ui/app/pages/browser/[...slug].vue
@@ -221,6 +221,14 @@ const table_container = ref(false)
const search = ref('')
const show_filter = ref(false)
+watch(() => config.app.basic_mode, async v => {
+ if (!config.isLoaded() || !v) {
+ return
+ }
+ await navigateTo('/')
+},{ immediate: true })
+
+
const filteredItems = computed(() => {
if (!search.value) {
return sortedItems(items.value)
diff --git a/ui/app/pages/conditions.vue b/ui/app/pages/conditions.vue
index 97fa328e..64cf6964 100644
--- a/ui/app/pages/conditions.vue
+++ b/ui/app/pages/conditions.vue
@@ -131,12 +131,12 @@ const initialLoad = ref(true)
const addInProgress = ref(false)
const remove_keys = ['in_progress', 'raw']
-watch(() => config.app.basic_mode, async () => {
- if (!config.app.basic_mode) {
+watch(() => config.app.basic_mode, async v => {
+ if (!config.isLoaded() || !v) {
return
}
await navigateTo("/")
-})
+}, { immediate: true })
watch(() => socket.isConnected, async () => {
if (socket.isConnected && initialLoad.value) {
diff --git a/ui/app/pages/console.vue b/ui/app/pages/console.vue
index 466849a9..de8309e8 100644
--- a/ui/app/pages/console.vue
+++ b/ui/app/pages/console.vue
@@ -82,11 +82,11 @@ watch(() => isLoading.value, async value => {
}, { immediate: true })
watch(() => config.app.basic_mode, async () => {
- if (!config.app.basic_mode) {
+ if (!config.isLoaded() || !config.app.basic_mode) {
return
}
await navigateTo('/')
-})
+}, { immediate: true })
watch(() => config.app.console_enabled, async () => {
if (config.app.console_enabled) {
diff --git a/ui/app/pages/logs.vue b/ui/app/pages/logs.vue
index 3950f042..a61c22d1 100644
--- a/ui/app/pages/logs.vue
+++ b/ui/app/pages/logs.vue
@@ -156,11 +156,11 @@ watch(toggleFilter, () => {
});
watch(() => config.app.basic_mode, async v => {
- if (!v) {
+ if (!config.isLoaded() || !v) {
return
}
await navigateTo('/')
-})
+}, { immediate: true })
watch(() => config.app.file_logging, async v => {
if (v) {
diff --git a/ui/app/pages/notifications.vue b/ui/app/pages/notifications.vue
index cbcf0638..a7325da6 100644
--- a/ui/app/pages/notifications.vue
+++ b/ui/app/pages/notifications.vue
@@ -223,12 +223,12 @@ const isLoading = ref(false)
const initialLoad = ref(true)
const addInProgress = ref(false)
-watch(() => config.app.basic_mode, async () => {
- if (!config.app.basic_mode) {
+watch(() => config.app.basic_mode, async v => {
+ if (!config.isLoaded() || !v) {
return
}
await navigateTo('/')
-})
+}, { immediate: true })
watch(() => socket.isConnected, async () => {
if (socket.isConnected && initialLoad.value) {
diff --git a/ui/app/pages/presets.vue b/ui/app/pages/presets.vue
index 6600dcca..a66dec20 100644
--- a/ui/app/pages/presets.vue
+++ b/ui/app/pages/presets.vue
@@ -226,15 +226,12 @@ const remove_keys = ['raw', 'toggle_description']
const presetsNoDefault = computed(() => presets.value.filter((t) => !t.default))
-watch(
- () => config.app.basic_mode,
- async () => {
- if (!config.app.basic_mode) {
- return
- }
- await navigateTo('/')
- },
-)
+watch(() => config.app.basic_mode, async v => {
+ if (!config.isLoaded() || !v) {
+ return
+ }
+ await navigateTo('/')
+}, { immediate: true })
watch(() => socket.isConnected, async () => {
if (socket.isConnected && initialLoad.value) {
diff --git a/ui/app/pages/tasks.vue b/ui/app/pages/tasks.vue
index 4ced6601..f7b21fb4 100644
--- a/ui/app/pages/tasks.vue
+++ b/ui/app/pages/tasks.vue
@@ -423,12 +423,12 @@ watch(masterSelectAll, value => {
}
})
-watch(() => config.app.basic_mode, async () => {
- if (!config.app.basic_mode) {
+watch(() => config.app.basic_mode, async v => {
+ if (!config.isLoaded() || !v) {
return
}
await navigateTo('/')
-})
+},{ immediate: true })
watch(() => socket.isConnected, async () => {
if (socket.isConnected && initialLoad.value) {