@swiss-ai-hub/web 0.306.0 → 0.306.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -9,6 +9,9 @@ export const useAgentClasses = defineQuery((options?: { online?: boolean }) => {
|
|
|
9
9
|
const { data: agentClasses, isPending: agentClassesAreLoading } = useQuery<AgentClassDto[]>({
|
|
10
10
|
key: () => ['tenant', tenantId.value, 'agent-classes', options?.online],
|
|
11
11
|
staleTime: minutesToMilliseconds(5),
|
|
12
|
+
// A focus refetch replaces the classes array with new object references, which would
|
|
13
|
+
// reset an in-progress create form (issue #38). Keep the cached value until invalidated.
|
|
14
|
+
refetchOnWindowFocus: false,
|
|
12
15
|
enabled: useTenantReady(),
|
|
13
16
|
query: async () => {
|
|
14
17
|
return await getAgentClasses({
|
|
@@ -9,6 +9,9 @@ export const useAgentInstance = defineQuery(() => {
|
|
|
9
9
|
const { data: agentInstance, isPending: agentInstanceIsLoading } = useQuery<FullAgentInstanceDto>({
|
|
10
10
|
key: () => ['tenant', tenantId.value, 'agent-instances', route.params.agent_class as string, route.params.agent_id as string],
|
|
11
11
|
staleTime: minutesToMilliseconds(5),
|
|
12
|
+
// A focus refetch after leaving the tab would flip the loading/enabled state and remount
|
|
13
|
+
// the configuration form, discarding unsaved edits (issue #38). Keep the cached value.
|
|
14
|
+
refetchOnWindowFocus: false,
|
|
12
15
|
enabled: useTenantReady('agent_id', 'agent_class'),
|
|
13
16
|
query: async () => {
|
|
14
17
|
return await getAgentInstance({
|
|
@@ -94,22 +94,30 @@ export function useCreateInstanceForm<T extends ClassDataLike>(options: CreateIn
|
|
|
94
94
|
setNestedValue(formData.value, path, value)
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
// Reseed only when the chosen class changes; a refetch hands back a new reference for the
|
|
98
|
+
// same class, and reseeding on that churn would wipe the user's input (issue #38).
|
|
99
|
+
let seededForClass: string | null = null
|
|
100
|
+
watch([selectedClass, selectedClassData], () => {
|
|
101
|
+
if (seededForClass === selectedClass.value) return
|
|
102
|
+
if (!selectedClassData.value) return
|
|
103
|
+
formData.value = selectedClassData.value.form && selectedClassData.value.form.length > 0
|
|
99
104
|
? hydrateFormData({}, configForm.value as FormElement[])
|
|
100
105
|
: {}
|
|
106
|
+
seededForClass = selectedClass.value
|
|
101
107
|
}, { immediate: true })
|
|
102
108
|
|
|
103
109
|
function applyInitialData(data: Record<string, unknown>) {
|
|
104
110
|
// Hydrate from the template/clone data: nullable toggles follow the data's null-ness,
|
|
105
111
|
// missing leaves fall back to their backend defaults — identical to the edit form.
|
|
106
112
|
formData.value = hydrateFormData(data, configForm.value as FormElement[])
|
|
113
|
+
seededForClass = selectedClass.value
|
|
107
114
|
}
|
|
108
115
|
|
|
109
116
|
function resetForm() {
|
|
110
117
|
selectedClass.value = initialClass()
|
|
111
118
|
formData.value = {}
|
|
112
119
|
activeStep.value = 0
|
|
120
|
+
seededForClass = null
|
|
113
121
|
}
|
|
114
122
|
|
|
115
123
|
return {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"license": "AGPL-3.0-or-later",
|
|
4
4
|
"author": "bbv Software Services AG (https://www.bbv.ch)",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"version": "0.306.
|
|
6
|
+
"version": "0.306.1",
|
|
7
7
|
"description": "Swiss AI Hub - Admin & Management UI (Nuxt 3 layer)",
|
|
8
8
|
"main": "./nuxt.config.ts",
|
|
9
9
|
"repository": {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<StructuralColumn
|
|
3
3
|
:title="t('agent.configuration.title')"
|
|
4
4
|
close-route="/service/agents"
|
|
5
|
-
:loading="agentInstanceIsLoading"
|
|
5
|
+
:loading="agentInstanceIsLoading && !hasLoaded"
|
|
6
6
|
size="normal"
|
|
7
7
|
>
|
|
8
8
|
<div class="flex flex-col gap-3">
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
{{ t('agent.configuration.description') }}
|
|
11
11
|
</p>
|
|
12
12
|
<AgentConfiguration
|
|
13
|
-
v-if="configForm && configForm.length > 0
|
|
13
|
+
v-if="hasLoaded && configForm && configForm.length > 0"
|
|
14
14
|
:title="t('agent.configuration.runtimeSettings')"
|
|
15
15
|
:description="agentInstance?.agent_config.description || ''"
|
|
16
16
|
:form="configForm"
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
@submit="submitConfiguration"
|
|
19
19
|
/>
|
|
20
20
|
<div
|
|
21
|
-
v-else-if="
|
|
21
|
+
v-else-if="!hasLoaded"
|
|
22
22
|
class="text-center text-sm text-surface-500 dark:text-surface-400"
|
|
23
23
|
>
|
|
24
24
|
{{ t('common.loading') }}
|
|
@@ -43,6 +43,20 @@ const { updateAgentInstance } = useUpdateAgentInstance()
|
|
|
43
43
|
const { t } = useI18n()
|
|
44
44
|
const toast = useToast()
|
|
45
45
|
|
|
46
|
+
// Latch so a background refetch or transient `enabled` flip can't remount the form and
|
|
47
|
+
// re-seed it from server data, dropping unsaved edits (issue #38).
|
|
48
|
+
const hasLoaded = ref(false)
|
|
49
|
+
watch(agentInstance, (value) => {
|
|
50
|
+
if (value) hasLoaded.value = true
|
|
51
|
+
}, { immediate: true })
|
|
52
|
+
|
|
53
|
+
// Nuxt reuses this instance across param changes; drop the latch on route identity change so
|
|
54
|
+
// the loading state shows until the new agent resolves, instead of the previous form lingering.
|
|
55
|
+
watch(
|
|
56
|
+
() => `${route.params.agent_class}/${route.params.agent_id}`,
|
|
57
|
+
() => { hasLoaded.value = false },
|
|
58
|
+
)
|
|
59
|
+
|
|
46
60
|
// Lock agent_id on edit: it is the immutable instance key, and a divergent value silently breaks
|
|
47
61
|
// the SSE completion check so the chat never finishes. The backend pins it on save too; this is UX.
|
|
48
62
|
const configForm = computed<FormkitElement[]>(() =>
|