@swiss-ai-hub/web 0.310.5 → 0.311.0
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.
- package/components/Agent/Card.vue +10 -0
- package/components/Knowledge/Document/List.vue +13 -15
- package/composables/agent/useExportAgentInstance.ts +33 -0
- package/i18n/locales/de.yaml +2 -0
- package/i18n/locales/en.yaml +2 -0
- package/i18n/locales/fr.yaml +2 -0
- package/i18n/locales/it.yaml +2 -0
- package/package.json +1 -1
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/configuration.vue +18 -3
|
@@ -43,6 +43,15 @@
|
|
|
43
43
|
size="small"
|
|
44
44
|
@click.stop="emit('clone', agent)"
|
|
45
45
|
/>
|
|
46
|
+
<Button
|
|
47
|
+
v-tooltip.top="t('agent.export.button')"
|
|
48
|
+
icon="pi pi-download"
|
|
49
|
+
severity="secondary"
|
|
50
|
+
text
|
|
51
|
+
rounded
|
|
52
|
+
size="small"
|
|
53
|
+
@click.stop="exportAgentInstance(agent)"
|
|
54
|
+
/>
|
|
46
55
|
<Button
|
|
47
56
|
v-if="showDelete"
|
|
48
57
|
icon="pi pi-trash"
|
|
@@ -93,6 +102,7 @@ const toast = useToast()
|
|
|
93
102
|
const confirm = useConfirm()
|
|
94
103
|
const { tenantId } = useTenant()
|
|
95
104
|
const { deleteAgentInstance, isDeleting } = useDeleteAgentInstance()
|
|
105
|
+
const { exportAgentInstance } = useExportAgentInstance()
|
|
96
106
|
|
|
97
107
|
const isActive = computed(() => {
|
|
98
108
|
return route.params.agent_id === props.agent.agent_id && route.params.agent_class === props.agent.agent_class
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
:sort-order="sortOrder"
|
|
25
25
|
removable-sort
|
|
26
26
|
size="small"
|
|
27
|
+
:select-all="allDeletableSelected"
|
|
28
|
+
@select-all-change="onSelectAllChange"
|
|
27
29
|
@row-click="handleRowClick"
|
|
28
30
|
@sort="handleSort"
|
|
29
31
|
>
|
|
@@ -38,9 +40,7 @@
|
|
|
38
40
|
>
|
|
39
41
|
<template #body="{ data }">
|
|
40
42
|
<div class="flex items-center gap-2">
|
|
41
|
-
<p
|
|
42
|
-
class="font-bold"
|
|
43
|
-
>
|
|
43
|
+
<p class="font-bold">
|
|
44
44
|
{{ data.document_title }}
|
|
45
45
|
</p>
|
|
46
46
|
<div
|
|
@@ -91,9 +91,7 @@
|
|
|
91
91
|
:header="t('document.list.number_of_pages')"
|
|
92
92
|
>
|
|
93
93
|
<template #body="{ data }">
|
|
94
|
-
<Badge
|
|
95
|
-
:value="data.number_of_pages ?? '-'"
|
|
96
|
-
/>
|
|
94
|
+
<Badge :value="data.number_of_pages ?? '-'" />
|
|
97
95
|
</template>
|
|
98
96
|
</Column>
|
|
99
97
|
<Column
|
|
@@ -184,17 +182,16 @@ watch(
|
|
|
184
182
|
{ immediate: true },
|
|
185
183
|
)
|
|
186
184
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
() => checkedDocuments.value.
|
|
191
|
-
(nonDeletableCount) => {
|
|
192
|
-
if (nonDeletableCount > 0) {
|
|
193
|
-
checkedDocuments.value = checkedDocuments.value.filter(isDocumentDeletable)
|
|
194
|
-
}
|
|
195
|
-
},
|
|
185
|
+
const deletableDocuments = computed(() => props.documents.filter(isDocumentDeletable))
|
|
186
|
+
|
|
187
|
+
const allDeletableSelected = computed(
|
|
188
|
+
() => deletableDocuments.value.length > 0 && checkedDocuments.value.length === deletableDocuments.value.length,
|
|
196
189
|
)
|
|
197
190
|
|
|
191
|
+
const onSelectAllChange = ({ checked }: { checked: boolean }) => {
|
|
192
|
+
checkedDocuments.value = checked ? [...deletableDocuments.value] : []
|
|
193
|
+
}
|
|
194
|
+
|
|
198
195
|
const handleRowClick = (event: DataTableRowClickEvent) => {
|
|
199
196
|
const document = event.data as DocumentDto
|
|
200
197
|
if (document.is_ingested && !isDocumentDeleting(document)) {
|
|
@@ -243,6 +240,7 @@ const handleDelete = async (document: DocumentDto) => {
|
|
|
243
240
|
documentId: document.id,
|
|
244
241
|
})
|
|
245
242
|
schedule([document.id])
|
|
243
|
+
checkedDocuments.value = checkedDocuments.value.filter(selected => selected.id !== document.id)
|
|
246
244
|
toast.add({
|
|
247
245
|
severity: 'success',
|
|
248
246
|
summary: t('document.delete.success'),
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { FullAgentInstanceDto } from '@core/sdk/client'
|
|
2
|
+
|
|
3
|
+
const EXPORT_SCHEMA_VERSION = '1.0'
|
|
4
|
+
|
|
5
|
+
type AgentConfigExport = {
|
|
6
|
+
schemaVersion: string
|
|
7
|
+
agentClass: string
|
|
8
|
+
agentId: string
|
|
9
|
+
configuration: Record<string, unknown>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const useExportAgentInstance = () => {
|
|
13
|
+
const buildExport = (instance: FullAgentInstanceDto): AgentConfigExport => ({
|
|
14
|
+
schemaVersion: EXPORT_SCHEMA_VERSION,
|
|
15
|
+
agentClass: instance.agent_class,
|
|
16
|
+
agentId: instance.agent_id,
|
|
17
|
+
configuration: instance.configuration ?? {},
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const exportAgentInstance = (instance: FullAgentInstanceDto): void => {
|
|
21
|
+
const blob = new Blob([JSON.stringify(buildExport(instance), null, 2)], { type: 'application/json' })
|
|
22
|
+
const url = URL.createObjectURL(blob)
|
|
23
|
+
|
|
24
|
+
const anchor = document.createElement('a')
|
|
25
|
+
anchor.href = url
|
|
26
|
+
anchor.download = `${instance.agent_config.name}_${instance.agent_id}_config.json`
|
|
27
|
+
anchor.click()
|
|
28
|
+
|
|
29
|
+
URL.revokeObjectURL(url)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return { exportAgentInstance }
|
|
33
|
+
}
|
package/i18n/locales/de.yaml
CHANGED
package/i18n/locales/en.yaml
CHANGED
package/i18n/locales/fr.yaml
CHANGED
package/i18n/locales/it.yaml
CHANGED
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.
|
|
6
|
+
"version": "0.311.0",
|
|
7
7
|
"description": "Swiss AI Hub - Admin & Management UI (Nuxt 3 layer)",
|
|
8
8
|
"main": "./nuxt.config.ts",
|
|
9
9
|
"repository": {
|
|
@@ -6,9 +6,19 @@
|
|
|
6
6
|
size="normal"
|
|
7
7
|
>
|
|
8
8
|
<div class="flex flex-col gap-3">
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
<div class="mb-4 flex items-start justify-between gap-4">
|
|
10
|
+
<p class="text-sm text-surface-500 dark:text-surface-400">
|
|
11
|
+
{{ t('agent.configuration.description') }}
|
|
12
|
+
</p>
|
|
13
|
+
<Button
|
|
14
|
+
icon="pi pi-download"
|
|
15
|
+
severity="secondary"
|
|
16
|
+
:label="t('agent.export.button')"
|
|
17
|
+
class="shrink-0"
|
|
18
|
+
:disabled="!agentInstance"
|
|
19
|
+
@click="exportAgent"
|
|
20
|
+
/>
|
|
21
|
+
</div>
|
|
12
22
|
<AgentConfiguration
|
|
13
23
|
v-if="hasLoaded && configForm && configForm.length > 0"
|
|
14
24
|
:title="t('agent.configuration.runtimeSettings')"
|
|
@@ -40,9 +50,14 @@ const route = useRoute()
|
|
|
40
50
|
const { tenantId } = useTenant()
|
|
41
51
|
const { agentInstance, agentInstanceIsLoading } = useAgentInstance()
|
|
42
52
|
const { updateAgentInstance } = useUpdateAgentInstance()
|
|
53
|
+
const { exportAgentInstance } = useExportAgentInstance()
|
|
43
54
|
const { t } = useI18n()
|
|
44
55
|
const toast = useToast()
|
|
45
56
|
|
|
57
|
+
const exportAgent = () => {
|
|
58
|
+
if (agentInstance.value) exportAgentInstance(agentInstance.value)
|
|
59
|
+
}
|
|
60
|
+
|
|
46
61
|
// Latch so a background refetch or transient `enabled` flip can't remount the form and
|
|
47
62
|
// re-seed it from server data, dropping unsaved edits (issue #38).
|
|
48
63
|
const hasLoaded = ref(false)
|