@swiss-ai-hub/web 0.290.11
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/LICENSE +661 -0
- package/README.md +479 -0
- package/app.config.ts +1 -0
- package/app.vue +52 -0
- package/assets/css/main.css +4 -0
- package/assets/images/logo.png +0 -0
- package/components/Agent/Avatar.vue +40 -0
- package/components/Agent/Card.vue +139 -0
- package/components/Agent/Configuration.vue +20 -0
- package/components/Agent/CreateModal.vue +287 -0
- package/components/Agent/EmptyCard.vue +35 -0
- package/components/Agent/List.vue +85 -0
- package/components/Agent/TemplateCard.vue +58 -0
- package/components/AppLoader.vue +55 -0
- package/components/Chat/Message.vue +90 -0
- package/components/Chat/SourceNodes.vue +120 -0
- package/components/Chat/Thread.vue +134 -0
- package/components/Costs/Table.vue +56 -0
- package/components/Dashboard/Component/BarChart.vue +46 -0
- package/components/Dashboard/Component/LineChart.vue +138 -0
- package/components/Dashboard/Component/Number.vue +31 -0
- package/components/Dashboard/Grid.vue +214 -0
- package/components/Dashboard/Item.vue +75 -0
- package/components/Dashboard/Trend.vue +34 -0
- package/components/Display/List/DisplayList.vue +93 -0
- package/components/Evaluation/Dataset/Card.vue +70 -0
- package/components/Evaluation/Dataset/Create.vue +81 -0
- package/components/Evaluation/Dataset/Edit.vue +132 -0
- package/components/Event/Display/AddMemoryToChatHistoryEvent.vue +60 -0
- package/components/Event/Display/AgentInTheLoopRequestEvent.vue +56 -0
- package/components/Event/Display/AgentInTheLoopResponseEvent.vue +17 -0
- package/components/Event/Display/Base.vue +125 -0
- package/components/Event/Display/BaseRetrieveMemoryEvent.vue +101 -0
- package/components/Event/Display/BaseStoreMemoryEvent.vue +182 -0
- package/components/Event/Display/ChunkEvent.vue +40 -0
- package/components/Event/Display/EmbeddingEvent.vue +25 -0
- package/components/Event/Display/ExceptionEvent.vue +21 -0
- package/components/Event/Display/GuardAcceptEvent.vue +25 -0
- package/components/Event/Display/GuardEvent.vue +17 -0
- package/components/Event/Display/GuardRejectionEvent.vue +25 -0
- package/components/Event/Display/HumanInTheLoopRequestEvent.vue +53 -0
- package/components/Event/Display/HumanInTheLoopResponseEvent.vue +40 -0
- package/components/Event/Display/LLMCostEvent.vue +25 -0
- package/components/Event/Display/LLMEvent.vue +92 -0
- package/components/Event/Display/LimitChatHistoryEvent.vue +60 -0
- package/components/Event/Display/RAGFailureStopEvent.vue +28 -0
- package/components/Event/Display/RAGStartEvent.vue +77 -0
- package/components/Event/Display/RAGSuccessStopEvent.vue +16 -0
- package/components/Event/Display/RawDataContent.vue +69 -0
- package/components/Event/Display/RerankerEvent.vue +39 -0
- package/components/Event/Display/RetrieverEvent.vue +22 -0
- package/components/Event/Display/RouterEvent.vue +54 -0
- package/components/Event/Display/StandaloneQuestionCondenserEvent.vue +38 -0
- package/components/Event/Display/StopEvent.vue +16 -0
- package/components/Event/Display/ThoughtEvent.vue +20 -0
- package/components/Event/Display/ToolEvent.vue +38 -0
- package/components/Event/Display/UnknownEvent.vue +17 -0
- package/components/Event/Display/UserMessageEvent.vue +35 -0
- package/components/Event/List/EventList.vue +249 -0
- package/components/Event/Statistics.vue +49 -0
- package/components/Event/Timeseries.vue +224 -0
- package/components/FormKit/AgentSelector.vue +307 -0
- package/components/FormKit/ChipsInput.vue +62 -0
- package/components/FormKit/DynamicConfiguration.vue +155 -0
- package/components/FormKit/IconSelector.vue +72 -0
- package/components/FormKit/KnowledgeDatabaseSelector.vue +92 -0
- package/components/FormKit/LocaleInput.vue +150 -0
- package/components/FormKit/ModelSelect.vue +110 -0
- package/components/FormKit/Repeater.vue +93 -0
- package/components/FormKit/VectorStoreInput.vue +247 -0
- package/components/Knowledge/Document/List.vue +140 -0
- package/components/Knowledge/Document/Overview.vue +28 -0
- package/components/Knowledge/Document/UploadModal.vue +298 -0
- package/components/Knowledge/Document/WithNodes.vue +105 -0
- package/components/Knowledge/Namespace/Card.vue +108 -0
- package/components/Knowledge/Namespace/CreateModal.vue +203 -0
- package/components/Knowledge/Namespace/EditModal.vue +134 -0
- package/components/Knowledge/Namespace/EmptyCard.vue +35 -0
- package/components/Knowledge/Node/Content.vue +71 -0
- package/components/Markdown/Renderer.vue +87 -0
- package/components/Memory/DetailPage.vue +48 -0
- package/components/Memory/Edit.vue +241 -0
- package/components/Memory/Graph.vue +318 -0
- package/components/Memory/List.vue +155 -0
- package/components/Memory/MemoryManagementPage.vue +178 -0
- package/components/Memory/OpenWebUIContent.vue +96 -0
- package/components/Memory/PageLayout.vue +72 -0
- package/components/Models/ModelDetailsPanel.vue +250 -0
- package/components/Models/NamespaceCard.vue +79 -0
- package/components/Navigation/Left.vue +85 -0
- package/components/Navigation/Top.vue +31 -0
- package/components/Notification/Item.vue +88 -0
- package/components/Notification/NotificationsOverlay.vue +164 -0
- package/components/Process/Card.vue +119 -0
- package/components/Process/Configuration.vue +20 -0
- package/components/Process/CreateModal.vue +276 -0
- package/components/Process/EmptyCard.vue +35 -0
- package/components/Process/Form.vue +153 -0
- package/components/Process/Starts.vue +44 -0
- package/components/Process/Walkthrough/List.vue +162 -0
- package/components/Role/AccessRulesEditor.vue +132 -0
- package/components/Role/Card.vue +68 -0
- package/components/Role/Create.vue +55 -0
- package/components/Role/Edit.vue +82 -0
- package/components/Role/UsageLimitsEditor.vue +225 -0
- package/components/Service/Selection.vue +148 -0
- package/components/Structural/Column.vue +74 -0
- package/components/Structural/Screen.vue +10 -0
- package/components/Structural/Substructure.vue +5 -0
- package/components/Tenant/Switcher.vue +102 -0
- package/components/Thread/Details.vue +135 -0
- package/components/Thread/Hierarchy.vue +136 -0
- package/components/Thread/Info.vue +41 -0
- package/components/Thread/List.vue +136 -0
- package/components/User/Bar.vue +74 -0
- package/components/User/List.vue +86 -0
- package/components/User/RoleChips.vue +83 -0
- package/components/User/Settings.vue +79 -0
- package/components/Workflow/Modal.vue +39 -0
- package/components/Workflow/NodeCard.vue +41 -0
- package/components/Workflow/StartNode.vue +24 -0
- package/components/Workflow/StepNode.vue +27 -0
- package/components/Workflow/StopNode.vue +24 -0
- package/components/Workflow/Visualization.vue +265 -0
- package/components/mdc/MarkdownFigure.vue +9 -0
- package/components/mdc/MarkdownTable.vue +9 -0
- package/components/mdc/ResolveImageComponent.vue +58 -0
- package/composables/agent/useAgentClass.ts +27 -0
- package/composables/agent/useAgentClassInstances.ts +27 -0
- package/composables/agent/useAgentClasses.ts +27 -0
- package/composables/agent/useAgentIconFromThread.ts +8 -0
- package/composables/agent/useAgentInstance.ts +28 -0
- package/composables/agent/useAgentInstanceThreads.ts +76 -0
- package/composables/agent/useAgentInstances.ts +25 -0
- package/composables/agent/useAgentNavigation.ts +35 -0
- package/composables/agent/useCreateAgentInstance.ts +33 -0
- package/composables/agent/useDeleteAgentInstance.ts +31 -0
- package/composables/agent/useUpdateAgentInstance.ts +40 -0
- package/composables/auth/useAuth.ts +54 -0
- package/composables/auth/useAuthProviders.ts +14 -0
- package/composables/chat/useChatCompletions.ts +30 -0
- package/composables/dashboard/useAgentNameFromDashboardWidget.ts +27 -0
- package/composables/dashboard/useDashboardComponent.ts +27 -0
- package/composables/dashboard/useSaveDashboard.ts +21 -0
- package/composables/document/useCreateNamespace.ts +26 -0
- package/composables/document/useDatabases.ts +23 -0
- package/composables/document/useDocument.ts +29 -0
- package/composables/document/useDocumentUrl.ts +20 -0
- package/composables/document/useDocuments.ts +107 -0
- package/composables/document/useNodes.ts +29 -0
- package/composables/document/useSummaryNodes.ts +32 -0
- package/composables/document/useUpdateNamespace.ts +22 -0
- package/composables/evaluation/useCreateDataset.ts +19 -0
- package/composables/evaluation/useDataset.ts +26 -0
- package/composables/evaluation/useDatasets.ts +25 -0
- package/composables/evaluation/useUpdateDataset.ts +23 -0
- package/composables/event/useBasicEventStatistics.ts +83 -0
- package/composables/event/useEventColor.ts +25 -0
- package/composables/event/useEventComponent.ts +87 -0
- package/composables/event/useEventTimeseries.ts +39 -0
- package/composables/event/useEventTimeseriesStats.ts +26 -0
- package/composables/file/useFileUpload.ts +91 -0
- package/composables/file/useSupportedFileTypes.ts +22 -0
- package/composables/form/useCreateInstanceForm.ts +251 -0
- package/composables/form/useFormKitTransform.ts +753 -0
- package/composables/memory/useMemoryCRUD.ts +88 -0
- package/composables/memory/useMemoryFactory.ts +319 -0
- package/composables/memory/useMemorySearchFilter.ts +74 -0
- package/composables/models/useModelsList.ts +24 -0
- package/composables/models/useSingleModel.ts +30 -0
- package/composables/notification/useNotificationPoller.ts +58 -0
- package/composables/notification/useNotifications.ts +57 -0
- package/composables/notification/useUpdateMultipleNotifications.ts +17 -0
- package/composables/notification/useUpdateNotification.ts +17 -0
- package/composables/process/useCreateProcessInstance.ts +32 -0
- package/composables/process/useDeleteProcessInstance.ts +31 -0
- package/composables/process/useProcessClasses.ts +27 -0
- package/composables/process/useProcessInstance.ts +28 -0
- package/composables/process/useProcessInstances.ts +27 -0
- package/composables/process/useProcessWalkthroughs.ts +73 -0
- package/composables/process/useSendProcessStartForm.ts +43 -0
- package/composables/process/useUpdateProcessInstance.ts +40 -0
- package/composables/role/useCreateRole.ts +19 -0
- package/composables/role/useDeleteRole.ts +21 -0
- package/composables/role/useRole.ts +30 -0
- package/composables/role/useRoles.ts +25 -0
- package/composables/role/useUpdateRole.ts +22 -0
- package/composables/suite/useApps.ts +31 -0
- package/composables/suite/useSuite.ts +26 -0
- package/composables/tenant/useActiveTenant.ts +27 -0
- package/composables/tenant/useSysadminNavigation.ts +19 -0
- package/composables/tenant/useTenant.ts +38 -0
- package/composables/tenant/useTenantMemberships.ts +15 -0
- package/composables/tenant/useTenantPath.ts +20 -0
- package/composables/tenant/useTenantPolling.ts +30 -0
- package/composables/tenant/useTenantReady.ts +12 -0
- package/composables/theme/useDarkMode.ts +5 -0
- package/composables/thread/useThread.ts +27 -0
- package/composables/thread/useThreadEvents.ts +91 -0
- package/composables/thread/useThreadUtils.ts +49 -0
- package/composables/thread/useThreads.ts +64 -0
- package/composables/thread/useThreadsInfinite.ts +56 -0
- package/composables/translation/useTranslate.ts +20 -0
- package/composables/useRouteReady.ts +21 -0
- package/composables/useTimeAgo.ts +40 -0
- package/composables/user/useAssignRoleToUser.ts +22 -0
- package/composables/user/useMyUser.ts +25 -0
- package/composables/user/useRevokeRoleFromUser.ts +21 -0
- package/composables/user/useUser.ts +30 -0
- package/composables/user/useUsers.ts +63 -0
- package/composables/utils/useJsonTree.ts +138 -0
- package/formkit.config.ts +44 -0
- package/i18n/locales/de.yaml +815 -0
- package/i18n/locales/en.yaml +804 -0
- package/i18n/locales/fr.yaml +812 -0
- package/i18n/locales/it.yaml +808 -0
- package/layouts/anonymous.vue +8 -0
- package/layouts/default.vue +116 -0
- package/middleware/auth.global.ts +62 -0
- package/nuxt.config.ts +145 -0
- package/package.json +114 -0
- package/pages/[tenant]/index.vue +31 -0
- package/pages/[tenant]/notifications/index.vue +235 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/chat.vue +67 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/configuration.vue +122 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/memories/[memory_id].vue +3 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/memories.vue +20 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/overview.vue +72 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/threads.vue +52 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id]/workflow.vue +19 -0
- package/pages/[tenant]/service/agents/[agent_class]-[agent_id].vue +63 -0
- package/pages/[tenant]/service/agents/templates.vue +102 -0
- package/pages/[tenant]/service/agents.vue +185 -0
- package/pages/[tenant]/service/datasets/[dataset_id].vue +81 -0
- package/pages/[tenant]/service/datasets.vue +53 -0
- package/pages/[tenant]/service/health/index.vue +3 -0
- package/pages/[tenant]/service/knowledge/[db]/[namespace]/[document_id]/nodes.vue +20 -0
- package/pages/[tenant]/service/knowledge/[db]/[namespace]/[document_id]/overview.vue +40 -0
- package/pages/[tenant]/service/knowledge/[db]/[namespace]/[document_id]/summary.vue +88 -0
- package/pages/[tenant]/service/knowledge/[db]/[namespace]/[document_id].vue +48 -0
- package/pages/[tenant]/service/knowledge/[db]/[namespace].vue +144 -0
- package/pages/[tenant]/service/knowledge.vue +126 -0
- package/pages/[tenant]/service/models/[model_name].vue +84 -0
- package/pages/[tenant]/service/models.vue +61 -0
- package/pages/[tenant]/service/my-account.vue +117 -0
- package/pages/[tenant]/service/openai/[thread_id]/[display_id]/memories.vue +66 -0
- package/pages/[tenant]/service/openai/[thread_id]/[display_id]/sources.vue +100 -0
- package/pages/[tenant]/service/openai/[thread_id]/[display_id]/tracing.vue +49 -0
- package/pages/[tenant]/service/openai.vue +101 -0
- package/pages/[tenant]/service/organization-memories/graph.vue +97 -0
- package/pages/[tenant]/service/organization-memories/list/[memory_id].vue +3 -0
- package/pages/[tenant]/service/organization-memories/list.vue +150 -0
- package/pages/[tenant]/service/organization-memories.vue +3 -0
- package/pages/[tenant]/service/processes/[process_class]-[process_id]/[process_walkthrough_id].vue +7 -0
- package/pages/[tenant]/service/processes/[process_class]-[process_id]/configuration.vue +106 -0
- package/pages/[tenant]/service/processes/[process_class]-[process_id]/overview.vue +67 -0
- package/pages/[tenant]/service/processes/[process_class]-[process_id]/start.vue +26 -0
- package/pages/[tenant]/service/processes/[process_class]-[process_id]/walkthroughs/[process_walkthrough_id]/overview.vue +14 -0
- package/pages/[tenant]/service/processes/[process_class]-[process_id]/walkthroughs.vue +54 -0
- package/pages/[tenant]/service/processes/[process_class]-[process_id].vue +60 -0
- package/pages/[tenant]/service/processes.vue +129 -0
- package/pages/[tenant]/service/roles/[role_id].vue +54 -0
- package/pages/[tenant]/service/roles.vue +84 -0
- package/pages/[tenant]/service/threads/[thread_id]/chat.vue +51 -0
- package/pages/[tenant]/service/threads/[thread_id]/display/[display_id].vue +21 -0
- package/pages/[tenant]/service/threads/[thread_id]/display.vue +29 -0
- package/pages/[tenant]/service/threads/[thread_id]/hierarchy.vue +14 -0
- package/pages/[tenant]/service/threads/[thread_id]/memories/[memory_id].vue +3 -0
- package/pages/[tenant]/service/threads/[thread_id]/memories.vue +19 -0
- package/pages/[tenant]/service/threads/[thread_id]/overview.vue +100 -0
- package/pages/[tenant]/service/threads/[thread_id].vue +54 -0
- package/pages/[tenant]/service/threads.vue +52 -0
- package/pages/[tenant]/service/user-memories/graph.vue +97 -0
- package/pages/[tenant]/service/user-memories/list/[memory_id].vue +3 -0
- package/pages/[tenant]/service/user-memories/list.vue +150 -0
- package/pages/[tenant]/service/user-memories.vue +3 -0
- package/pages/[tenant]/service/users/[user_id].vue +117 -0
- package/pages/[tenant]/service/users.vue +88 -0
- package/pages/auth/callback.vue +52 -0
- package/pages/auth/login.vue +80 -0
- package/pages/auth/renew.vue +24 -0
- package/pages/index.vue +59 -0
- package/pages/select-tenant.vue +76 -0
- package/plugins/0.runtime-config.client.ts +55 -0
- package/plugins/apexcharts.client.ts +5 -0
- package/plugins/api-client.client.ts +38 -0
- package/plugins/dark-mode.client.ts +12 -0
- package/plugins/keycloak-client.ts +41 -0
- package/plugins/oidc-client.ts +78 -0
- package/sdk/client/client/client.gen.ts +237 -0
- package/sdk/client/client/index.ts +24 -0
- package/sdk/client/client/types.gen.ts +213 -0
- package/sdk/client/client/utils.gen.ts +407 -0
- package/sdk/client/client.gen.ts +25 -0
- package/sdk/client/core/auth.gen.ts +42 -0
- package/sdk/client/core/bodySerializer.gen.ts +96 -0
- package/sdk/client/core/params.gen.ts +181 -0
- package/sdk/client/core/pathSerializer.gen.ts +180 -0
- package/sdk/client/core/queryKeySerializer.gen.ts +136 -0
- package/sdk/client/core/serverSentEvents.gen.ts +265 -0
- package/sdk/client/core/types.gen.ts +118 -0
- package/sdk/client/core/utils.gen.ts +143 -0
- package/sdk/client/index.ts +1013 -0
- package/sdk/client/schemas.gen.ts +35395 -0
- package/sdk/client/sdk.gen.ts +3438 -0
- package/sdk/client/transformers.gen.ts +143 -0
- package/sdk/client/types.gen.ts +27567 -0
- package/tailwind.config.mjs +27 -0
- package/themes/aihub-theme.ts +125 -0
- package/types/DashboardWidget.ts +13 -0
- package/types/EventChartInput.ts +7 -0
- package/types/NavItem.ts +6 -0
- package/types/TimeseriesInput.ts +7 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { useToast } from 'primevue/usetoast'
|
|
2
|
+
import { useRouter } from 'vue-router'
|
|
3
|
+
|
|
4
|
+
import type { ComputedRef } from 'vue'
|
|
5
|
+
|
|
6
|
+
export interface UseMemoryCRUDOptions {
|
|
7
|
+
selectedMemory: ComputedRef<{ id: string } | undefined>
|
|
8
|
+
updateMemory: (params: { memoryId: string, data: string }) => Promise<void>
|
|
9
|
+
deleteMemory: (params: { memoryId: string }) => Promise<void>
|
|
10
|
+
closeRoute: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Shared composable for memory CRUD operations with toast notifications.
|
|
15
|
+
* Eliminates duplication across user/org detail pages.
|
|
16
|
+
*
|
|
17
|
+
* Provides:
|
|
18
|
+
* - Update handler with success/error toasts (matches MemoryEdit @update signature)
|
|
19
|
+
* - Delete handler with success/error toasts + navigation (matches MemoryEdit @delete signature)
|
|
20
|
+
* - Close handler for navigation back to list (matches MemoryEdit @close signature)
|
|
21
|
+
*
|
|
22
|
+
* @param options - Selected memory ref, CRUD mutation functions, and close route
|
|
23
|
+
* @returns CRUD handlers with toast notifications
|
|
24
|
+
*/
|
|
25
|
+
export function useMemoryCRUD(options: UseMemoryCRUDOptions) {
|
|
26
|
+
const { t } = useI18n()
|
|
27
|
+
const toast = useToast()
|
|
28
|
+
const router = useRouter()
|
|
29
|
+
const tenantPath = useTenantPath()
|
|
30
|
+
|
|
31
|
+
const handleUpdate = async (data: string) => {
|
|
32
|
+
if (!options.selectedMemory.value) return
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
await options.updateMemory({ memoryId: options.selectedMemory.value.id, data })
|
|
36
|
+
toast.add({
|
|
37
|
+
severity: 'success',
|
|
38
|
+
summary: t('memory.update.success.title'),
|
|
39
|
+
detail: t('memory.update.success.message'),
|
|
40
|
+
life: 3000,
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
console.error('Failed to update memory:', error)
|
|
45
|
+
toast.add({
|
|
46
|
+
severity: 'error',
|
|
47
|
+
summary: t('memory.update.error.title'),
|
|
48
|
+
detail: t('memory.update.error.message'),
|
|
49
|
+
life: 5000,
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const handleDelete = async () => {
|
|
55
|
+
if (!options.selectedMemory.value) return
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
await options.deleteMemory({ memoryId: options.selectedMemory.value.id })
|
|
59
|
+
toast.add({
|
|
60
|
+
severity: 'success',
|
|
61
|
+
summary: t('memory.delete.success.title'),
|
|
62
|
+
detail: t('memory.delete.success.message'),
|
|
63
|
+
life: 3000,
|
|
64
|
+
})
|
|
65
|
+
// Navigate back to list after successful deletion
|
|
66
|
+
router.push(tenantPath(options.closeRoute))
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error('Failed to delete memory:', error)
|
|
70
|
+
toast.add({
|
|
71
|
+
severity: 'error',
|
|
72
|
+
summary: t('memory.delete.error.title'),
|
|
73
|
+
detail: t('memory.delete.error.message'),
|
|
74
|
+
life: 5000,
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const handleClose = () => {
|
|
80
|
+
router.push(tenantPath(options.closeRoute))
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
handleUpdate,
|
|
85
|
+
handleDelete,
|
|
86
|
+
handleClose,
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getUserMemories,
|
|
3
|
+
searchUserMemories,
|
|
4
|
+
updateUserMemory,
|
|
5
|
+
deleteUserMemory,
|
|
6
|
+
deleteAllUserMemories,
|
|
7
|
+
getOrganizationMemories,
|
|
8
|
+
searchOrganizationMemories,
|
|
9
|
+
updateOrganizationMemory,
|
|
10
|
+
deleteOrganizationMemory,
|
|
11
|
+
deleteAllOrganizationMemories,
|
|
12
|
+
} from '@core/sdk/client'
|
|
13
|
+
import { minutesToMilliseconds } from 'date-fns'
|
|
14
|
+
import { computed, ref } from 'vue'
|
|
15
|
+
|
|
16
|
+
import type { MemoriesResponse, MemorySearchResponse } from '@core/sdk/client'
|
|
17
|
+
|
|
18
|
+
type MemoryType = 'user' | 'organization'
|
|
19
|
+
|
|
20
|
+
interface MemoryContext {
|
|
21
|
+
type: MemoryType
|
|
22
|
+
agent_class?: string
|
|
23
|
+
agent_id?: string
|
|
24
|
+
thread_id?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Factory function to create memory composables for both user and organization memory types.
|
|
29
|
+
* This eliminates code duplication by generating type-specific hooks from a single implementation.
|
|
30
|
+
*
|
|
31
|
+
* @param context - Memory context specifying type (user/organization)
|
|
32
|
+
* @returns Object containing all memory-related composables
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* // User memory
|
|
36
|
+
* const { useMemories, useMemorySearch } = createMemoryComposables({ type: 'user' })
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* // Organization memory (tenant from env-var)
|
|
40
|
+
* const { useMemories, useMemorySearch } = createMemoryComposables({ type: 'organization' })
|
|
41
|
+
*/
|
|
42
|
+
export function createMemoryComposables(context: MemoryContext) {
|
|
43
|
+
const { type, agent_class, agent_id, thread_id } = context
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Generate cache keys with proper scoping for user vs organization memory.
|
|
47
|
+
* Includes the tenant prefix for hierarchical cache invalidation.
|
|
48
|
+
*/
|
|
49
|
+
const getCacheKey = (operation: string, params: Record<string, unknown> = {}) => {
|
|
50
|
+
const baseParams = { ...params, agent_class, agent_id, thread_id }
|
|
51
|
+
const memoryType = type === 'user' ? 'user' : 'organization'
|
|
52
|
+
return ['tenant', params.tenant, 'memories', memoryType, operation, baseParams]
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Composable for fetching and paginating memories
|
|
57
|
+
*/
|
|
58
|
+
const useMemories = () => {
|
|
59
|
+
const { tenantId } = useTenant()
|
|
60
|
+
const currentPage = ref(1)
|
|
61
|
+
const pageSize = ref(20)
|
|
62
|
+
|
|
63
|
+
const {
|
|
64
|
+
data: memoriesData,
|
|
65
|
+
isPending: memoriesAreLoading,
|
|
66
|
+
} = useQuery<MemoriesResponse>({
|
|
67
|
+
key: () => getCacheKey('list', { tenant: tenantId.value, page: currentPage.value }),
|
|
68
|
+
staleTime: minutesToMilliseconds(5),
|
|
69
|
+
enabled: useTenantReady(),
|
|
70
|
+
query: async () => {
|
|
71
|
+
// Use search endpoint when filters are provided (agent_class/agent_id/thread_id)
|
|
72
|
+
const hasFilters = agent_class || agent_id || thread_id
|
|
73
|
+
|
|
74
|
+
if (type === 'user') {
|
|
75
|
+
if (hasFilters) {
|
|
76
|
+
// Search endpoint supports filtering
|
|
77
|
+
return await searchUserMemories({
|
|
78
|
+
composable: '$fetch',
|
|
79
|
+
path: { tenant_id: tenantId.value! },
|
|
80
|
+
query: {
|
|
81
|
+
query: '', // Empty query returns all memories
|
|
82
|
+
limit: 1000,
|
|
83
|
+
agent_class: agent_class || null,
|
|
84
|
+
agent_id: agent_id || null,
|
|
85
|
+
thread_id: thread_id || null,
|
|
86
|
+
},
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
return await getUserMemories({
|
|
90
|
+
composable: '$fetch',
|
|
91
|
+
path: { tenant_id: tenantId.value! },
|
|
92
|
+
query: { limit: 1000 },
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (hasFilters) {
|
|
97
|
+
return await searchOrganizationMemories({
|
|
98
|
+
composable: '$fetch',
|
|
99
|
+
path: { tenant_id: tenantId.value! },
|
|
100
|
+
query: {
|
|
101
|
+
query: '', // Empty query returns all memories
|
|
102
|
+
limit: 1000,
|
|
103
|
+
agent_class: agent_class || null,
|
|
104
|
+
agent_id: agent_id || null,
|
|
105
|
+
thread_id: thread_id || null,
|
|
106
|
+
},
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
return await getOrganizationMemories({
|
|
110
|
+
composable: '$fetch',
|
|
111
|
+
path: { tenant_id: tenantId.value! },
|
|
112
|
+
query: {
|
|
113
|
+
limit: 1000,
|
|
114
|
+
},
|
|
115
|
+
})
|
|
116
|
+
},
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
const paginatedMemories = computed(() => {
|
|
120
|
+
if (!memoriesData.value) return []
|
|
121
|
+
const start = (currentPage.value - 1) * pageSize.value
|
|
122
|
+
const end = start + pageSize.value
|
|
123
|
+
return memoriesData.value.memories.slice(start, end)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
const totalPages = computed(() => {
|
|
127
|
+
if (!memoriesData.value) return 0
|
|
128
|
+
return Math.ceil(memoriesData.value.memories.length / pageSize.value)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
const allRelations = computed(() => {
|
|
132
|
+
return memoriesData.value?.relations || []
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
const nextPage = () => {
|
|
136
|
+
if (currentPage.value < totalPages.value) {
|
|
137
|
+
currentPage.value++
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const prevPage = () => {
|
|
142
|
+
if (currentPage.value > 1) {
|
|
143
|
+
currentPage.value--
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
memoriesData,
|
|
149
|
+
memoriesAreLoading,
|
|
150
|
+
paginatedMemories,
|
|
151
|
+
allRelations,
|
|
152
|
+
currentPage,
|
|
153
|
+
pageSize,
|
|
154
|
+
totalPages,
|
|
155
|
+
nextPage,
|
|
156
|
+
prevPage,
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Composable for semantic memory search
|
|
162
|
+
*/
|
|
163
|
+
const useMemorySearch = () => {
|
|
164
|
+
const { tenantId } = useTenant()
|
|
165
|
+
const query = ref<string>('')
|
|
166
|
+
const limit = ref(100)
|
|
167
|
+
|
|
168
|
+
const {
|
|
169
|
+
data: searchData,
|
|
170
|
+
isPending: searchIsLoading,
|
|
171
|
+
} = useQuery<MemorySearchResponse>({
|
|
172
|
+
key: () => getCacheKey('search', { tenant: tenantId.value, query: query.value, limit: limit.value }),
|
|
173
|
+
staleTime: minutesToMilliseconds(1),
|
|
174
|
+
enabled: () => !!query.value && !!tenantId.value,
|
|
175
|
+
query: async () => {
|
|
176
|
+
if (type === 'user') {
|
|
177
|
+
return await searchUserMemories({
|
|
178
|
+
composable: '$fetch',
|
|
179
|
+
path: { tenant_id: tenantId.value! },
|
|
180
|
+
query: {
|
|
181
|
+
query: query.value,
|
|
182
|
+
limit: limit.value,
|
|
183
|
+
agent_class: agent_class || null,
|
|
184
|
+
agent_id: agent_id || null,
|
|
185
|
+
thread_id: thread_id || null,
|
|
186
|
+
},
|
|
187
|
+
})
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return await searchOrganizationMemories({
|
|
191
|
+
composable: '$fetch',
|
|
192
|
+
path: { tenant_id: tenantId.value! },
|
|
193
|
+
query: {
|
|
194
|
+
query: query.value,
|
|
195
|
+
limit: limit.value,
|
|
196
|
+
agent_class: agent_class || null,
|
|
197
|
+
agent_id: agent_id || null,
|
|
198
|
+
thread_id: thread_id || null,
|
|
199
|
+
},
|
|
200
|
+
})
|
|
201
|
+
},
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
const isSearchActive = computed(() => !!query.value)
|
|
205
|
+
|
|
206
|
+
const setSearchQuery = (q: string) => {
|
|
207
|
+
query.value = q
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const clearSearch = () => {
|
|
211
|
+
query.value = ''
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
searchData,
|
|
216
|
+
searchIsLoading,
|
|
217
|
+
query,
|
|
218
|
+
isSearchActive,
|
|
219
|
+
setSearchQuery,
|
|
220
|
+
clearSearch,
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Composable for updating memory content
|
|
226
|
+
*/
|
|
227
|
+
const useUpdateMemory = () => {
|
|
228
|
+
const queryCache = useQueryCache()
|
|
229
|
+
const { tenantId } = useTenant()
|
|
230
|
+
|
|
231
|
+
const { mutate: updateMemoryMutation } = useMutation({
|
|
232
|
+
mutation: async ({ memoryId, data }: { memoryId: string, data: string }) => {
|
|
233
|
+
const tenant = tenantId.value!
|
|
234
|
+
if (type === 'user') {
|
|
235
|
+
await updateUserMemory({
|
|
236
|
+
composable: '$fetch',
|
|
237
|
+
path: { tenant_id: tenant, memory_id: memoryId },
|
|
238
|
+
body: { data },
|
|
239
|
+
})
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
await updateOrganizationMemory({
|
|
243
|
+
composable: '$fetch',
|
|
244
|
+
path: { tenant_id: tenant, memory_id: memoryId },
|
|
245
|
+
body: { data },
|
|
246
|
+
})
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Invalidate cache to trigger refetch
|
|
250
|
+
queryCache.invalidateQueries({ key: getCacheKey('list', { tenant }) })
|
|
251
|
+
},
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
return { updateMemory: updateMemoryMutation }
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Composable for deleting memories
|
|
259
|
+
*/
|
|
260
|
+
const useDeleteMemory = () => {
|
|
261
|
+
const queryCache = useQueryCache()
|
|
262
|
+
const { tenantId } = useTenant()
|
|
263
|
+
|
|
264
|
+
const { mutate: deleteMemoryMutation } = useMutation({
|
|
265
|
+
mutation: async ({ memoryId }: { memoryId: string }) => {
|
|
266
|
+
const tenant = tenantId.value!
|
|
267
|
+
if (type === 'user') {
|
|
268
|
+
await deleteUserMemory({
|
|
269
|
+
composable: '$fetch',
|
|
270
|
+
path: { tenant_id: tenant, memory_id: memoryId },
|
|
271
|
+
})
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
await deleteOrganizationMemory({
|
|
275
|
+
composable: '$fetch',
|
|
276
|
+
path: { tenant_id: tenant, memory_id: memoryId },
|
|
277
|
+
})
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Invalidate cache to trigger refetch
|
|
281
|
+
queryCache.invalidateQueries({ key: getCacheKey('list', { tenant }) })
|
|
282
|
+
},
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
const { mutate: deleteAllMemoriesMutation } = useMutation({
|
|
286
|
+
mutation: async () => {
|
|
287
|
+
const tenant = tenantId.value!
|
|
288
|
+
if (type === 'user') {
|
|
289
|
+
await deleteAllUserMemories({
|
|
290
|
+
composable: '$fetch',
|
|
291
|
+
path: { tenant_id: tenant },
|
|
292
|
+
})
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
await deleteAllOrganizationMemories({
|
|
296
|
+
composable: '$fetch',
|
|
297
|
+
path: { tenant_id: tenant },
|
|
298
|
+
})
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Invalidate both list and search cache
|
|
302
|
+
queryCache.invalidateQueries({ key: getCacheKey('list', { tenant }) })
|
|
303
|
+
queryCache.invalidateQueries({ key: getCacheKey('search', { tenant }) })
|
|
304
|
+
},
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
return {
|
|
308
|
+
deleteMemory: deleteMemoryMutation,
|
|
309
|
+
deleteAllMemories: deleteAllMemoriesMutation,
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return {
|
|
314
|
+
useMemories,
|
|
315
|
+
useMemorySearch,
|
|
316
|
+
useUpdateMemory,
|
|
317
|
+
useDeleteMemory,
|
|
318
|
+
}
|
|
319
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { computed, onMounted } from 'vue'
|
|
2
|
+
|
|
3
|
+
import type { Ref } from 'vue'
|
|
4
|
+
|
|
5
|
+
export interface UseMemorySearchFilterOptions {
|
|
6
|
+
searchData: Ref<{ memories: unknown[] } | undefined>
|
|
7
|
+
paginatedMemories: Ref<unknown[]>
|
|
8
|
+
isSearchActive: Ref<boolean>
|
|
9
|
+
setSearchQuery: (query: string) => void
|
|
10
|
+
clearSearch: () => void
|
|
11
|
+
searchIsLoading: Ref<boolean>
|
|
12
|
+
currentPage?: Ref<number>
|
|
13
|
+
totalPages?: Ref<number>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Shared composable for memory search and filtering logic.
|
|
18
|
+
* Eliminates duplication across user/org list and graph pages.
|
|
19
|
+
*
|
|
20
|
+
* Provides:
|
|
21
|
+
* - Search input synced with URL query param
|
|
22
|
+
* - Displayed memories (search results or paginated)
|
|
23
|
+
* - Search/clear handlers
|
|
24
|
+
* - Loading states
|
|
25
|
+
*
|
|
26
|
+
* @param options - Memory search composable outputs from factory
|
|
27
|
+
* @returns Search filter state and handlers
|
|
28
|
+
*/
|
|
29
|
+
export function useMemorySearchFilter(options: UseMemorySearchFilterOptions) {
|
|
30
|
+
const searchInput = useRouteQuery('q', '')
|
|
31
|
+
const isSearchButtonLoading = computed(() =>
|
|
32
|
+
options.isSearchActive.value && options.searchIsLoading.value,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
// Sync URL query param with search on mount
|
|
36
|
+
onMounted(() => {
|
|
37
|
+
if (searchInput.value) {
|
|
38
|
+
options.setSearchQuery(searchInput.value as string)
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const displayedMemories = computed(() => {
|
|
43
|
+
return options.isSearchActive.value && options.searchData.value
|
|
44
|
+
? options.searchData.value.memories
|
|
45
|
+
: options.paginatedMemories.value
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const displayedCurrentPage = computed(() => {
|
|
49
|
+
return options.isSearchActive.value ? 1 : (options.currentPage?.value ?? 1)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const displayedTotalPages = computed(() => {
|
|
53
|
+
return options.isSearchActive.value ? 1 : (options.totalPages?.value ?? 1)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const handleSearch = () => {
|
|
57
|
+
options.setSearchQuery(searchInput.value)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const handleClearSearch = () => {
|
|
61
|
+
searchInput.value = null
|
|
62
|
+
options.clearSearch()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
searchInput,
|
|
67
|
+
isSearchButtonLoading,
|
|
68
|
+
displayedMemories,
|
|
69
|
+
displayedCurrentPage,
|
|
70
|
+
displayedTotalPages,
|
|
71
|
+
handleSearch,
|
|
72
|
+
handleClearSearch,
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getLitellmModels, type ModelTypeGroupDto } from '@core/sdk/client'
|
|
2
|
+
import { minutesToMilliseconds } from 'date-fns'
|
|
3
|
+
|
|
4
|
+
export const useModelsList = defineQuery(() => {
|
|
5
|
+
const { tenantId } = useTenant()
|
|
6
|
+
|
|
7
|
+
const { data: modelTypes, isPending: modelsAreLoading, error } = useQuery<ModelTypeGroupDto[]>({
|
|
8
|
+
key: () => ['tenant', tenantId.value, 'models'],
|
|
9
|
+
staleTime: minutesToMilliseconds(5),
|
|
10
|
+
enabled: useTenantReady(),
|
|
11
|
+
query: async () => {
|
|
12
|
+
return await getLitellmModels({
|
|
13
|
+
composable: '$fetch',
|
|
14
|
+
path: { tenant_id: tenantId.value! },
|
|
15
|
+
})
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
modelTypes,
|
|
21
|
+
modelsAreLoading,
|
|
22
|
+
error,
|
|
23
|
+
}
|
|
24
|
+
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getLitellmModel, type ModelDto } from '@core/sdk/client'
|
|
2
|
+
import { minutesToMilliseconds } from 'date-fns'
|
|
3
|
+
|
|
4
|
+
export const useSingleModel = () => {
|
|
5
|
+
const route = useRoute()
|
|
6
|
+
const { tenantId } = useTenant()
|
|
7
|
+
|
|
8
|
+
const modelName = computed<string>(() => decodeURIComponent(route.params?.model_name as string))
|
|
9
|
+
|
|
10
|
+
const { data: model, isPending: modelIsLoading, error } = useQuery<ModelDto>({
|
|
11
|
+
key: () => ['tenant', tenantId.value, 'model', modelName.value],
|
|
12
|
+
staleTime: minutesToMilliseconds(5),
|
|
13
|
+
enabled: useTenantReady('model_name'),
|
|
14
|
+
query: async () => {
|
|
15
|
+
return await getLitellmModel({
|
|
16
|
+
composable: '$fetch',
|
|
17
|
+
path: {
|
|
18
|
+
tenant_id: tenantId.value!,
|
|
19
|
+
model_name: modelName.value,
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
},
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
model,
|
|
27
|
+
modelIsLoading,
|
|
28
|
+
error,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { getNotifications, type NotificationDto } from '@core/sdk/client'
|
|
2
|
+
import { useIntervalFn } from '@vueuse/core'
|
|
3
|
+
import { useToast } from 'primevue/usetoast'
|
|
4
|
+
|
|
5
|
+
export const useNotificationPoller = (options?: {
|
|
6
|
+
pollingInterval?: number
|
|
7
|
+
enabled?: boolean
|
|
8
|
+
}) => {
|
|
9
|
+
const { tenantId } = useTenant()
|
|
10
|
+
const toast = useToast()
|
|
11
|
+
const queryCache = useQueryCache()
|
|
12
|
+
|
|
13
|
+
const knownUnreadIds = ref(new Set<string>())
|
|
14
|
+
|
|
15
|
+
const { data: unreadResponse, refetch } = useQuery({
|
|
16
|
+
key: () => ['tenant', tenantId.value, 'notifications_poller_data'],
|
|
17
|
+
query: () =>
|
|
18
|
+
getNotifications({
|
|
19
|
+
composable: '$fetch',
|
|
20
|
+
path: { tenant_id: tenantId.value! },
|
|
21
|
+
query: { read: false, page_size: 100 },
|
|
22
|
+
}),
|
|
23
|
+
enabled: useTenantReady(),
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
watch(unreadResponse, (newData) => {
|
|
27
|
+
const newNotifications = newData?.notifications
|
|
28
|
+
if (!newNotifications) return
|
|
29
|
+
|
|
30
|
+
let hasNew = false
|
|
31
|
+
newNotifications.forEach((notification: NotificationDto) => {
|
|
32
|
+
if (!knownUnreadIds.value.has(notification.id)) {
|
|
33
|
+
hasNew = true
|
|
34
|
+
toast.add({
|
|
35
|
+
severity: notification.type,
|
|
36
|
+
summary: notification.title,
|
|
37
|
+
detail: notification.message,
|
|
38
|
+
life: 5000,
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
knownUnreadIds.value = new Set(newNotifications.map(n => n.id))
|
|
44
|
+
|
|
45
|
+
if (hasNew) {
|
|
46
|
+
queryCache.invalidateQueries({ key: ['tenant', tenantId.value, 'notifications'] })
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
const pollingInterval = options?.pollingInterval ?? 30_000
|
|
51
|
+
const enabled = options?.enabled ?? true
|
|
52
|
+
|
|
53
|
+
useIntervalFn(() => {
|
|
54
|
+
if (tenantId.value) {
|
|
55
|
+
refetch()
|
|
56
|
+
}
|
|
57
|
+
}, pollingInterval, { immediate: enabled })
|
|
58
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { getNotifications, type PaginatedNotificationsResponse } from '@core/sdk/client'
|
|
2
|
+
|
|
3
|
+
export const useNotifications = (options: {
|
|
4
|
+
currentPage: Ref<number>
|
|
5
|
+
pageSize: Ref<number>
|
|
6
|
+
filters?: {
|
|
7
|
+
read?: Ref<boolean | undefined>
|
|
8
|
+
done?: Ref<boolean | undefined>
|
|
9
|
+
types?: Ref<string[] | undefined>
|
|
10
|
+
severities?: Ref<string[] | undefined>
|
|
11
|
+
}
|
|
12
|
+
}) => {
|
|
13
|
+
const { tenantId } = useTenant()
|
|
14
|
+
const { currentPage, pageSize, filters } = options
|
|
15
|
+
|
|
16
|
+
const key = () => [
|
|
17
|
+
'tenant',
|
|
18
|
+
tenantId.value,
|
|
19
|
+
'notifications',
|
|
20
|
+
{
|
|
21
|
+
page: currentPage.value,
|
|
22
|
+
pageSize: pageSize.value,
|
|
23
|
+
read: filters?.read?.value,
|
|
24
|
+
done: filters?.done?.value,
|
|
25
|
+
types: filters?.types?.value,
|
|
26
|
+
severities: filters?.severities?.value,
|
|
27
|
+
},
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
const query = useQuery<PaginatedNotificationsResponse>({
|
|
31
|
+
key,
|
|
32
|
+
enabled: useTenantReady(),
|
|
33
|
+
query: () =>
|
|
34
|
+
getNotifications({
|
|
35
|
+
composable: '$fetch',
|
|
36
|
+
path: { tenant_id: tenantId.value! },
|
|
37
|
+
query: {
|
|
38
|
+
page: currentPage.value,
|
|
39
|
+
page_size: pageSize.value,
|
|
40
|
+
read: filters?.read?.value,
|
|
41
|
+
done: filters?.done?.value,
|
|
42
|
+
types: filters?.types?.value,
|
|
43
|
+
severities: filters?.severities?.value,
|
|
44
|
+
},
|
|
45
|
+
}),
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const notifications = computed(() => query.data.value?.notifications ?? [])
|
|
49
|
+
const totalRecords = computed(() => query.data.value?.total ?? 0)
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
notifications,
|
|
53
|
+
isLoading: query.isPending,
|
|
54
|
+
refetch: query.refetch,
|
|
55
|
+
totalRecords,
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type UpdateNotificationRequest, updateNotificationsBulk } from '@core/sdk/client'
|
|
2
|
+
|
|
3
|
+
export const useUpdateMultipleNotifications = defineMutation(() => {
|
|
4
|
+
const queryCache = useQueryCache()
|
|
5
|
+
const { tenantId } = useTenant()
|
|
6
|
+
return useMutation({
|
|
7
|
+
mutation: ({ ids, payload, tenantId }: { ids: string[], payload: Ref<UpdateNotificationRequest>, tenantId: string }) =>
|
|
8
|
+
updateNotificationsBulk({
|
|
9
|
+
composable: '$fetch',
|
|
10
|
+
path: { tenant_id: tenantId },
|
|
11
|
+
body: { notification_ids: ids, updates: payload },
|
|
12
|
+
}),
|
|
13
|
+
onSuccess: () => {
|
|
14
|
+
queryCache.invalidateQueries({ key: ['tenant', tenantId.value, 'notifications'] })
|
|
15
|
+
},
|
|
16
|
+
})
|
|
17
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { updateNotification, type UpdateNotificationRequest } from '@core/sdk/client'
|
|
2
|
+
|
|
3
|
+
export const useUpdateNotification = defineMutation(() => {
|
|
4
|
+
const queryCache = useQueryCache()
|
|
5
|
+
const { tenantId } = useTenant()
|
|
6
|
+
return useMutation({
|
|
7
|
+
mutation: ({ id, payload, tenantId }: { id: string, payload: Ref<UpdateNotificationRequest>, tenantId: string }) =>
|
|
8
|
+
updateNotification({
|
|
9
|
+
composable: '$fetch',
|
|
10
|
+
path: { tenant_id: tenantId, notification_id: id },
|
|
11
|
+
body: payload,
|
|
12
|
+
}),
|
|
13
|
+
onSuccess: () => {
|
|
14
|
+
queryCache.invalidateQueries({ key: ['tenant', tenantId.value, 'notifications'] })
|
|
15
|
+
},
|
|
16
|
+
})
|
|
17
|
+
})
|