@solidxai/core-ui 0.1.19 → 0.1.20-beta.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.
- package/dist/components/common/Link.d.ts.map +1 -1
- package/dist/components/common/Link.js +2 -1
- package/dist/components/common/Link.js.map +1 -1
- package/dist/components/common/Link.tsx +2 -1
- package/dist/components/common/SolidSettings/LlmSettings/AiModelConfigTab.d.ts +1 -0
- package/dist/components/common/SolidSettings/LlmSettings/AiModelConfigTab.d.ts.map +1 -1
- package/dist/components/common/SolidSettings/LlmSettings/AiModelConfigTab.js +109 -23
- package/dist/components/common/SolidSettings/LlmSettings/AiModelConfigTab.js.map +1 -1
- package/dist/components/common/SolidSettings/LlmSettings/AiModelConfigTab.tsx +155 -34
- package/dist/components/core/chatter/SolidChatter.js +2 -2
- package/dist/components/core/chatter/SolidChatter.js.map +1 -1
- package/dist/components/core/chatter/SolidChatter.tsx +2 -2
- package/dist/components/core/common/SolidGenericImport/SolidImportTransaction.js +20 -19
- package/dist/components/core/common/SolidGenericImport/SolidImportTransaction.js.map +1 -1
- package/dist/components/core/common/SolidGenericImport/SolidImportTransaction.tsx +16 -16
- package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.d.ts.map +1 -1
- package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.js +3 -10
- package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.js.map +1 -1
- package/dist/components/core/extension/solid-core/agentRegistry/card/AgentResourceCardWidget.tsx +3 -8
- package/dist/components/core/extension/solid-core/moduleMetadata/list/ExportModulePackageRowAction.d.ts.map +1 -1
- package/dist/components/core/extension/solid-core/moduleMetadata/list/ExportModulePackageRowAction.js +36 -9
- package/dist/components/core/extension/solid-core/moduleMetadata/list/ExportModulePackageRowAction.js.map +1 -1
- package/dist/components/core/extension/solid-core/moduleMetadata/list/ExportModulePackageRowAction.tsx +78 -7
- package/dist/components/core/extension/solid-core/moduleMetadata/list/ModuleImportListHeaderAction.d.ts +1 -0
- package/dist/components/core/extension/solid-core/moduleMetadata/list/ModuleImportListHeaderAction.d.ts.map +1 -1
- package/dist/components/core/extension/solid-core/moduleMetadata/list/ModuleImportListHeaderAction.js +1 -1
- package/dist/components/core/extension/solid-core/moduleMetadata/list/ModuleImportListHeaderAction.js.map +1 -1
- package/dist/components/core/extension/solid-core/moduleMetadata/list/ModuleImportListHeaderAction.tsx +1 -1
- package/dist/components/core/extension/solid-core/moduleMetadata/list/RestoreModulePackageRowAction.d.ts +4 -0
- package/dist/components/core/extension/solid-core/moduleMetadata/list/RestoreModulePackageRowAction.d.ts.map +1 -0
- package/dist/components/core/extension/solid-core/moduleMetadata/list/RestoreModulePackageRowAction.js +131 -0
- package/dist/components/core/extension/solid-core/moduleMetadata/list/RestoreModulePackageRowAction.js.map +1 -0
- package/dist/components/core/extension/solid-core/moduleMetadata/list/RestoreModulePackageRowAction.tsx +151 -0
- package/dist/components/core/extension/solid-core/moduleMetadata/list/UpdateModulePackageRowAction.d.ts +4 -0
- package/dist/components/core/extension/solid-core/moduleMetadata/list/UpdateModulePackageRowAction.d.ts.map +1 -0
- package/dist/components/core/extension/solid-core/moduleMetadata/list/UpdateModulePackageRowAction.js +13 -0
- package/dist/components/core/extension/solid-core/moduleMetadata/list/UpdateModulePackageRowAction.js.map +1 -0
- package/dist/components/core/extension/solid-core/moduleMetadata/list/UpdateModulePackageRowAction.tsx +20 -0
- package/dist/components/core/form/SolidFormView.d.ts.map +1 -1
- package/dist/components/core/form/SolidFormView.js +4 -0
- package/dist/components/core/form/SolidFormView.js.map +1 -1
- package/dist/components/core/form/SolidFormView.tsx +4 -0
- package/dist/components/core/kanban/SolidKanbanView.d.ts.map +1 -1
- package/dist/components/core/kanban/SolidKanbanView.js +50 -15
- package/dist/components/core/kanban/SolidKanbanView.js.map +1 -1
- package/dist/components/core/kanban/SolidKanbanView.tsx +22 -3
- package/dist/components/core/list/SolidListView.d.ts.map +1 -1
- package/dist/components/core/list/SolidListView.js +16 -3
- package/dist/components/core/list/SolidListView.js.map +1 -1
- package/dist/components/core/list/SolidListView.tsx +16 -2
- package/dist/components/core/list/columns/SolidMediaMultipleColumn.d.ts.map +1 -1
- package/dist/components/core/list/columns/SolidMediaMultipleColumn.js +4 -1
- package/dist/components/core/list/columns/SolidMediaMultipleColumn.js.map +1 -1
- package/dist/components/core/list/columns/SolidMediaMultipleColumn.tsx +4 -1
- package/dist/components/core/module/ModulePackageDialog.css +102 -0
- package/dist/components/core/module/ModulePackageDialog.d.ts +2 -1
- package/dist/components/core/module/ModulePackageDialog.d.ts.map +1 -1
- package/dist/components/core/module/ModulePackageDialog.js +216 -68
- package/dist/components/core/module/ModulePackageDialog.js.map +1 -1
- package/dist/components/core/module/ModulePackageDialog.tsx +356 -76
- package/dist/components/core/solid-agent/SolidAgentChat.d.ts.map +1 -1
- package/dist/components/core/solid-agent/SolidAgentChat.js +9 -3
- package/dist/components/core/solid-agent/SolidAgentChat.js.map +1 -1
- package/dist/components/core/solid-agent/SolidAgentChat.tsx +9 -4
- package/dist/components/core/solid-agent/SolidAgentMarkdown.d.ts.map +1 -1
- package/dist/components/core/solid-agent/SolidAgentMarkdown.js +25 -6
- package/dist/components/core/solid-agent/SolidAgentMarkdown.js.map +1 -1
- package/dist/components/core/solid-agent/SolidAgentMarkdown.tsx +15 -1
- package/dist/components/core/solid-agent/client/agentRuntime.d.ts +5 -0
- package/dist/components/core/solid-agent/client/agentRuntime.d.ts.map +1 -1
- package/dist/components/core/solid-agent/client/agentRuntime.js +77 -20
- package/dist/components/core/solid-agent/client/agentRuntime.js.map +1 -1
- package/dist/components/core/solid-agent/client/agentRuntime.ts +29 -1
- package/dist/components/core/solid-agent/client/agentSocket.d.ts +5 -1
- package/dist/components/core/solid-agent/client/agentSocket.d.ts.map +1 -1
- package/dist/components/core/solid-agent/client/agentSocket.js +27 -4
- package/dist/components/core/solid-agent/client/agentSocket.js.map +1 -1
- package/dist/components/core/solid-agent/client/agentSocket.ts +14 -3
- package/dist/components/core/solid-agent/embed/AgentEmbeddingPanel.js +2 -2
- package/dist/components/core/solid-agent/embed/AgentEmbeddingPanel.js.map +1 -1
- package/dist/components/core/solid-agent/embed/AgentEmbeddingPanel.tsx +5 -5
- package/dist/components/core/solid-agent/embed/agentEmbedProtocol.d.ts +2 -0
- package/dist/components/core/solid-agent/embed/agentEmbedProtocol.d.ts.map +1 -1
- package/dist/components/core/solid-agent/embed/agentEmbedProtocol.js +2 -2
- package/dist/components/core/solid-agent/embed/agentEmbedProtocol.js.map +1 -1
- package/dist/components/core/solid-agent/embed/agentEmbedProtocol.ts +4 -4
- package/dist/components/core/solid-agent/thread/AgentThread.d.ts.map +1 -1
- package/dist/components/core/solid-agent/thread/AgentThread.js +61 -26
- package/dist/components/core/solid-agent/thread/AgentThread.js.map +1 -1
- package/dist/components/core/solid-agent/thread/AgentThread.tsx +74 -40
- package/dist/components/core/solid-agent/thread/SolidAgentChatItem.d.ts +2 -1
- package/dist/components/core/solid-agent/thread/SolidAgentChatItem.d.ts.map +1 -1
- package/dist/components/core/solid-agent/thread/SolidAgentChatItem.js +2 -1
- package/dist/components/core/solid-agent/thread/SolidAgentChatItem.js.map +1 -1
- package/dist/components/core/solid-agent/thread/SolidAgentChatItem.tsx +3 -1
- package/dist/components/core/solid-agent/types.d.ts +3 -0
- package/dist/components/core/solid-agent/types.d.ts.map +1 -1
- package/dist/components/core/solid-agent/types.js +0 -9
- package/dist/components/core/solid-agent/types.js.map +1 -1
- package/dist/components/core/solid-agent/types.ts +4 -2
- package/dist/components/core/solid-agent/widgets/DefaultAssistantMessageChatWidget.d.ts +1 -1
- package/dist/components/core/solid-agent/widgets/DefaultAssistantMessageChatWidget.d.ts.map +1 -1
- package/dist/components/core/solid-agent/widgets/DefaultAssistantMessageChatWidget.js +5 -2
- package/dist/components/core/solid-agent/widgets/DefaultAssistantMessageChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/DefaultAssistantMessageChatWidget.tsx +11 -5
- package/dist/components/core/solid-agent/widgets/DefaultErrorChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/DefaultErrorChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/DefaultErrorChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/DefaultNoticeChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/DefaultNoticeChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/DefaultNoticeChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/DefaultThinkingChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/DefaultThinkingChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/DefaultThinkingChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/DefaultToolCallChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/DefaultToolCallChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/DefaultToolCallChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/DefaultUnknownChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/DefaultUnknownChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/DefaultUnknownChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/DefaultUserMessageChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/DefaultUserMessageChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/DefaultUserMessageChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/SolidChecklistChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/SolidChecklistChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/SolidChecklistChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/SolidCodeChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/SolidCodeChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/SolidCodeChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/SolidDiffListChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/SolidDiffListChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/SolidDiffListChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/SolidGalleryChatWidget.js +19 -0
- package/dist/components/core/solid-agent/widgets/SolidGalleryChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/SolidGalleryChatWidget.tsx +20 -0
- package/dist/components/core/solid-agent/widgets/SolidJsonChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/SolidJsonChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/SolidJsonChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/SolidLinkCardChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/SolidLinkCardChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/SolidLinkCardChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/SolidMarkdownChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/SolidMarkdownChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/SolidMarkdownChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/SolidProgressChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/SolidProgressChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/SolidProgressChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/SolidQuestionChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/SolidQuestionChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/SolidQuestionChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/SolidStatusChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/SolidStatusChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/SolidStatusChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/SolidTableChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/SolidTableChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/SolidTableChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/SolidToolActivityChatWidget.js +3 -0
- package/dist/components/core/solid-agent/widgets/SolidToolActivityChatWidget.js.map +1 -1
- package/dist/components/core/solid-agent/widgets/SolidToolActivityChatWidget.tsx +4 -0
- package/dist/components/core/solid-agent/widgets/solidChatWidgets.module.css +9 -1
- package/dist/components/core/users/CreateUser.d.ts.map +1 -1
- package/dist/components/core/users/CreateUser.js +23 -8
- package/dist/components/core/users/CreateUser.js.map +1 -1
- package/dist/components/core/users/CreateUser.tsx +10 -6
- package/dist/components/layout/AdminHeaderActions.d.ts.map +1 -1
- package/dist/components/layout/AdminHeaderActions.js +1 -29
- package/dist/components/layout/AdminHeaderActions.js.map +1 -1
- package/dist/components/layout/AdminHeaderActions.tsx +0 -42
- package/dist/components/layout/AdminTopHeader.js +2 -2
- package/dist/components/layout/AdminTopHeader.js.map +1 -1
- package/dist/components/layout/AdminTopHeader.tsx +2 -2
- package/dist/components/layout/AppSidebar.d.ts.map +1 -1
- package/dist/components/layout/AppSidebar.js +21 -5
- package/dist/components/layout/AppSidebar.js.map +1 -1
- package/dist/components/layout/AppSidebar.tsx +24 -6
- package/dist/components/layout/SolidAiStudioLayout.d.ts +0 -1
- package/dist/components/layout/SolidAiStudioLayout.d.ts.map +1 -1
- package/dist/components/layout/SolidAiStudioLayout.js +8 -161
- package/dist/components/layout/SolidAiStudioLayout.js.map +1 -1
- package/dist/components/layout/SolidAiStudioLayout.tsx +6 -136
- package/dist/components/layout/user-profile-menu.js +10 -10
- package/dist/components/layout/user-profile-menu.js.map +1 -1
- package/dist/components/layout/user-profile-menu.tsx +3 -3
- package/dist/components/shad-cn-ui/SolidLightbox.d.ts +2 -1
- package/dist/components/shad-cn-ui/SolidLightbox.d.ts.map +1 -1
- package/dist/components/shad-cn-ui/SolidLightbox.js +11 -4
- package/dist/components/shad-cn-ui/SolidLightbox.js.map +1 -1
- package/dist/components/shad-cn-ui/SolidLightbox.tsx +14 -1
- package/dist/helpers/modelViewPersistence.d.ts +2 -0
- package/dist/helpers/modelViewPersistence.d.ts.map +1 -1
- package/dist/helpers/modelViewPersistence.js +72 -0
- package/dist/helpers/modelViewPersistence.js.map +1 -1
- package/dist/helpers/modelViewPersistence.ts +79 -0
- package/dist/helpers/registry.d.ts +6 -2
- package/dist/helpers/registry.d.ts.map +1 -1
- package/dist/helpers/registry.js +68 -3
- package/dist/helpers/registry.js.map +1 -1
- package/dist/helpers/registry.ts +62 -4
- package/dist/hooks/useModelsDevModels.d.ts +43 -0
- package/dist/hooks/useModelsDevModels.d.ts.map +1 -0
- package/dist/hooks/useModelsDevModels.js +81 -0
- package/dist/hooks/useModelsDevModels.js.map +1 -0
- package/dist/hooks/useModelsDevModels.ts +106 -0
- package/dist/hooks/useRouter.d.ts.map +1 -1
- package/dist/hooks/useRouter.js +3 -2
- package/dist/hooks/useRouter.js.map +1 -1
- package/dist/hooks/useRouter.ts +3 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.ts +4 -1
- package/dist/modules/solidUiModule.d.ts +3 -2
- package/dist/modules/solidUiModule.d.ts.map +1 -1
- package/dist/modules/solidUiModule.js +1 -1
- package/dist/modules/solidUiModule.js.map +1 -1
- package/dist/modules/solidUiModule.ts +5 -1
- package/dist/redux/api/moduleApi.d.ts +12 -2
- package/dist/redux/api/moduleApi.d.ts.map +1 -1
- package/dist/redux/api/moduleApi.js +33 -3
- package/dist/redux/api/moduleApi.js.map +1 -1
- package/dist/redux/api/moduleApi.ts +17 -2
- package/dist/redux/api/solidChatterMessageApi.d.ts +3 -1
- package/dist/redux/api/solidChatterMessageApi.d.ts.map +1 -1
- package/dist/redux/api/solidChatterMessageApi.js +9 -1
- package/dist/redux/api/solidChatterMessageApi.js.map +1 -1
- package/dist/redux/api/solidChatterMessageApi.ts +9 -1
- package/dist/redux/store/defaultStoreConfig.d.ts +9 -1
- package/dist/redux/store/defaultStoreConfig.d.ts.map +1 -1
- package/dist/resources/globals.css +30 -0
- package/dist/resources/solid-custom.css +10 -6
- package/dist/resources/solid-tailwind-generated.css +1 -1
- package/dist/routes/AppEventListener.d.ts.map +1 -1
- package/dist/routes/AppEventListener.js +3 -3
- package/dist/routes/AppEventListener.js.map +1 -1
- package/dist/routes/AppEventListener.tsx +2 -3
- package/dist/routes/pages/admin/core/AgentHubTagsField.css +21 -0
- package/dist/routes/pages/admin/core/AgentHubTagsField.d.ts +17 -0
- package/dist/routes/pages/admin/core/AgentHubTagsField.d.ts.map +1 -0
- package/dist/routes/pages/admin/core/AgentHubTagsField.js +171 -0
- package/dist/routes/pages/admin/core/AgentHubTagsField.js.map +1 -0
- package/dist/routes/pages/admin/core/AgentHubTagsField.tsx +125 -0
- package/dist/routes/pages/admin/core/AgentPersonaHistory.css +130 -0
- package/dist/routes/pages/admin/core/AgentPersonaHistory.d.ts +7 -0
- package/dist/routes/pages/admin/core/AgentPersonaHistory.d.ts.map +1 -0
- package/dist/routes/pages/admin/core/AgentPersonaHistory.js +228 -0
- package/dist/routes/pages/admin/core/AgentPersonaHistory.js.map +1 -0
- package/dist/routes/pages/admin/core/AgentPersonaHistory.tsx +234 -0
- package/dist/routes/pages/admin/core/AgentRegistryEditorPage.css +13 -14
- package/dist/routes/pages/admin/core/AgentRegistryEditorPage.d.ts.map +1 -1
- package/dist/routes/pages/admin/core/AgentRegistryEditorPage.js +218 -165
- package/dist/routes/pages/admin/core/AgentRegistryEditorPage.js.map +1 -1
- package/dist/routes/pages/admin/core/AgentRegistryEditorPage.tsx +221 -127
- package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.d.ts.map +1 -1
- package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.js +14 -69
- package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.js.map +1 -1
- package/dist/routes/pages/admin/core/AgentSkillRegistryEditorPage.tsx +15 -83
- package/dist/routes/pages/admin/core/AgentToolActivationDialog.d.ts +11 -0
- package/dist/routes/pages/admin/core/AgentToolActivationDialog.d.ts.map +1 -0
- package/dist/routes/pages/admin/core/AgentToolActivationDialog.js +166 -0
- package/dist/routes/pages/admin/core/AgentToolActivationDialog.js.map +1 -0
- package/dist/routes/pages/admin/core/AgentToolActivationDialog.tsx +140 -0
- package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.css +26 -0
- package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.d.ts.map +1 -1
- package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.js +94 -71
- package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.js.map +1 -1
- package/dist/routes/pages/admin/core/AgentToolRegistryEditorPage.tsx +60 -52
- package/dist/routes/pages/admin/core/ArchivedChatterMessagesPage.d.ts +2 -0
- package/dist/routes/pages/admin/core/ArchivedChatterMessagesPage.d.ts.map +1 -0
- package/dist/routes/pages/admin/core/ArchivedChatterMessagesPage.js +108 -0
- package/dist/routes/pages/admin/core/ArchivedChatterMessagesPage.js.map +1 -0
- package/dist/routes/pages/admin/core/ArchivedChatterMessagesPage.tsx +96 -0
- package/dist/routes/solidRoutes.d.ts.map +1 -1
- package/dist/routes/solidRoutes.js +2 -0
- package/dist/routes/solidRoutes.js.map +1 -1
- package/dist/routes/solidRoutes.tsx +2 -0
- package/dist/types/extension-registry.d.ts +12 -0
- package/dist/types/extension-registry.d.ts.map +1 -1
- package/dist/types/extension-registry.js.map +1 -1
- package/dist/types/extension-registry.ts +15 -0
- package/dist/types/solid-core.d.ts +2 -0
- package/package.json +2 -1
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { ArrowLeft,
|
|
2
|
+
import { ArrowLeft, RefreshCw } from "lucide-react";
|
|
3
3
|
import { useDispatch } from "react-redux";
|
|
4
4
|
import { useNavigate, useParams } from "react-router-dom";
|
|
5
5
|
import { createSolidEntityApi } from "../../../../redux/api/solidEntityApi";
|
|
6
6
|
import { showToast } from "../../../../redux/features/toastSlice";
|
|
7
|
+
import { solidPatch } from "../../../../http/solidHttp";
|
|
7
8
|
import { AgentRegistryAuditPanel } from "./AgentRegistryAuditPanel";
|
|
9
|
+
import { AgentHubTagsField, agentHubTagsFrom, agentHubTagsPayload, type AgentHubTag } from "./AgentHubTagsField";
|
|
10
|
+
import { AgentToolActivationDialog } from "./AgentToolActivationDialog";
|
|
8
11
|
import { AgentToolSessionsPanel } from "../../../../components/core/extension/solid-core/agentToolRegistry/AgentToolSessionsPanel";
|
|
9
12
|
import { AgentRegistryCardWidget } from "../../../../components/core/extension/solid-core/agentRegistry/card/AgentRegistryCardWidget";
|
|
10
13
|
import { SolidButton, SolidCodeEditor, SolidDialog, SolidDialogBody, SolidIconPicker, SolidInput, SolidTabGroup } from "../../../../components/shad-cn-ui";
|
|
@@ -19,11 +22,12 @@ type ToolRecord = {
|
|
|
19
22
|
name?: string;
|
|
20
23
|
iconName?: string | null;
|
|
21
24
|
description?: string;
|
|
22
|
-
tags?:
|
|
25
|
+
tags?: AgentHubTag[];
|
|
23
26
|
type?: string;
|
|
24
27
|
status?: string | null;
|
|
25
28
|
lastLoadError?: string | null;
|
|
26
29
|
sourceCode?: string;
|
|
30
|
+
checksum?: string;
|
|
27
31
|
agentTools?: AgentToolLink[] | AgentToolLink | null;
|
|
28
32
|
};
|
|
29
33
|
|
|
@@ -38,17 +42,6 @@ function extractEntityRecord(response: unknown): Record<string, any> | undefined
|
|
|
38
42
|
return candidate && typeof candidate === "object" ? candidate as Record<string, any> : undefined;
|
|
39
43
|
}
|
|
40
44
|
|
|
41
|
-
function parseTags(value: unknown): string[] {
|
|
42
|
-
if (Array.isArray(value)) return value.map(String).map((tag) => tag.trim()).filter(Boolean);
|
|
43
|
-
if (typeof value !== "string" || !value.trim()) return [];
|
|
44
|
-
try {
|
|
45
|
-
const parsed = JSON.parse(value);
|
|
46
|
-
return Array.isArray(parsed) ? parsed.map(String).map((tag) => tag.trim()).filter(Boolean) : [];
|
|
47
|
-
} catch {
|
|
48
|
-
return value === "{}" ? [] : value.split(",").map((tag) => tag.trim()).filter(Boolean);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
45
|
async function sha256Hex(value: string): Promise<string> {
|
|
53
46
|
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
|
|
54
47
|
return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
@@ -86,7 +79,7 @@ export function AgentToolRegistryEditorPage() {
|
|
|
86
79
|
const entityApi = React.useMemo(() => createSolidEntityApi("agentToolRegistry"), []);
|
|
87
80
|
const { useCreateSolidEntityMutation, useGetSolidEntityByIdQuery, useUpdateSolidEntityMutation } = entityApi;
|
|
88
81
|
const { data: response, isLoading, isFetching, refetch } = useGetSolidEntityByIdQuery(
|
|
89
|
-
{ id, qs: "populate[0]=agentTools&populate[1]=agentTools.agentRegistry" },
|
|
82
|
+
{ id, qs: "populate[0]=agentTools&populate[1]=agentTools.agentRegistry&populate[2]=tags" },
|
|
90
83
|
{ skip: !id || id === "new" },
|
|
91
84
|
);
|
|
92
85
|
const [createTool, { isLoading: isCreating }] = useCreateSolidEntityMutation();
|
|
@@ -98,44 +91,38 @@ export function AgentToolRegistryEditorPage() {
|
|
|
98
91
|
const [description, setDescription] = React.useState("");
|
|
99
92
|
const [type, setType] = React.useState("custom");
|
|
100
93
|
const [sourceCode, setSourceCode] = React.useState("");
|
|
101
|
-
const [tags, setTags] = React.useState<
|
|
102
|
-
const [
|
|
94
|
+
const [tags, setTags] = React.useState<AgentHubTag[]>([]);
|
|
95
|
+
const [creatingTag, setCreatingTag] = React.useState(false);
|
|
103
96
|
const [fieldErrors, setFieldErrors] = React.useState<Record<string, string>>({});
|
|
104
97
|
const [auditRefreshVersion, setAuditRefreshVersion] = React.useState(0);
|
|
105
98
|
const [confirmRefresh, setConfirmRefresh] = React.useState(false);
|
|
99
|
+
const [activationOpen, setActivationOpen] = React.useState(false);
|
|
100
|
+
const [activationTool, setActivationTool] = React.useState<{ id: number; checksum: string; name: string } | null>(null);
|
|
101
|
+
const preparingActivation = React.useRef(false);
|
|
106
102
|
const baseline = React.useRef("");
|
|
107
103
|
|
|
108
|
-
const currentForm = () => JSON.stringify({ name, iconName, description, type, sourceCode, tags
|
|
104
|
+
const currentForm = () => JSON.stringify({ name, iconName, description, type, sourceCode, tags });
|
|
109
105
|
|
|
110
106
|
React.useEffect(() => {
|
|
111
|
-
const nextTags =
|
|
107
|
+
const nextTags = agentHubTagsFrom(record?.tags);
|
|
112
108
|
setName(record?.name ?? "");
|
|
113
109
|
setIconName(record?.iconName ?? "");
|
|
114
110
|
setDescription(record?.description ?? "");
|
|
115
111
|
setType(record?.type ?? "custom");
|
|
116
112
|
setSourceCode(record?.sourceCode ?? "");
|
|
117
113
|
setTags(nextTags);
|
|
118
|
-
|
|
119
|
-
baseline.current = JSON.stringify({ name: record?.name ?? "", iconName: record?.iconName ?? "", description: record?.description ?? "", type: record?.type ?? "custom", sourceCode: record?.sourceCode ?? "", tags: nextTags, tagDraft: "" });
|
|
114
|
+
baseline.current = JSON.stringify({ name: record?.name ?? "", iconName: record?.iconName ?? "", description: record?.description ?? "", type: record?.type ?? "custom", sourceCode: record?.sourceCode ?? "", tags: nextTags });
|
|
120
115
|
}, [record]);
|
|
121
116
|
|
|
122
117
|
const isReadOnly = record?.type === "solidx";
|
|
123
118
|
const isDirty = Boolean(record?.id) && currentForm() !== baseline.current;
|
|
124
119
|
const requestRefresh = () => isDirty ? setConfirmRefresh(true) : void refetch();
|
|
125
120
|
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
if (!next) return;
|
|
129
|
-
if (!tags.some((tag) => tag.toLowerCase() === next.toLowerCase())) setTags((current) => [...current, next]);
|
|
130
|
-
setTagDraft("");
|
|
131
|
-
setFieldErrors((current) => ({ ...current, tags: "" }));
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
const save = async (nextStatus?: "active" | "inactive") => {
|
|
121
|
+
const save = async (nextStatus?: "inactive") => {
|
|
122
|
+
if (creatingTag) return;
|
|
135
123
|
const nextErrors: Record<string, string> = {};
|
|
136
124
|
if (!name.trim()) nextErrors.name = "Name is required.";
|
|
137
125
|
if (!description.trim()) nextErrors.description = "Description is required.";
|
|
138
|
-
if (tags.length === 0) nextErrors.tags = "At least one tag is required.";
|
|
139
126
|
if (!type.trim()) nextErrors.type = "Tool type is required.";
|
|
140
127
|
if (!sourceCode.trim()) nextErrors.sourceCode = "Tool source code is required.";
|
|
141
128
|
|
|
@@ -147,19 +134,18 @@ export function AgentToolRegistryEditorPage() {
|
|
|
147
134
|
}
|
|
148
135
|
const payload = {
|
|
149
136
|
name: name.trim(), iconName: iconName || null, description: description.trim(), type,
|
|
150
|
-
sourceCode,
|
|
151
|
-
...(
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
status: nextStatus ?? (record?.status === "load_failed" ? "active" : record?.status ?? "active"),
|
|
155
|
-
...((nextStatus === "active" || (!nextStatus && record?.status === "load_failed")) ? { lastLoadError: null } : {}),
|
|
137
|
+
sourceCode, ...agentHubTagsPayload(tags),
|
|
138
|
+
...(["custom", "thirdparty"].includes(type) ? { checksum: await sha256Hex(sourceCode) } : {}),
|
|
139
|
+
status: nextStatus ?? (record && (sourceCode !== record.sourceCode || name.trim() !== record.name || type !== record.type)
|
|
140
|
+
? "inactive" : record?.status ?? "inactive"),
|
|
156
141
|
};
|
|
157
142
|
try {
|
|
158
143
|
if (record?.id) {
|
|
159
|
-
await updateTool({ id: record.id, data: payload }).unwrap();
|
|
144
|
+
const result = await updateTool({ id: record.id, data: payload }).unwrap();
|
|
160
145
|
dispatch(showToast({ severity: "success", summary: nextStatus ? "Tool status updated" : "Saved", detail: nextStatus ? `Tool moved to ${nextStatus}. Restart linked agent processes to apply the change.` : "Tool updated successfully." }));
|
|
161
146
|
setAuditRefreshVersion((version) => version + 1);
|
|
162
147
|
refetch();
|
|
148
|
+
return (extractEntityRecord(result) ?? { ...record, ...payload }) as ToolRecord;
|
|
163
149
|
} else {
|
|
164
150
|
const result: any = await createTool(payload).unwrap();
|
|
165
151
|
const createdId = result?.data?.id ?? result?.id;
|
|
@@ -170,7 +156,7 @@ export function AgentToolRegistryEditorPage() {
|
|
|
170
156
|
const errorDetail = getSaveErrorMessage(error);
|
|
171
157
|
const serverFieldErrors: Record<string, string> = {};
|
|
172
158
|
if (/required|not be empty|cannot be empty|should not be empty/i.test(errorDetail)) {
|
|
173
|
-
for (const field of ["name", "description", "
|
|
159
|
+
for (const field of ["name", "description", "type", "sourceCode"]) {
|
|
174
160
|
if (!new RegExp(`\\b${field}\\b`, "i").test(errorDetail)) continue;
|
|
175
161
|
const label = field === "sourceCode" ? "Tool source code" : field[0].toUpperCase() + field.slice(1);
|
|
176
162
|
serverFieldErrors[field] = `${label} is required.`;
|
|
@@ -184,6 +170,23 @@ export function AgentToolRegistryEditorPage() {
|
|
|
184
170
|
}
|
|
185
171
|
};
|
|
186
172
|
|
|
173
|
+
const beginActivation = async () => {
|
|
174
|
+
if (isReadOnly) return;
|
|
175
|
+
if (!record || activationOpen || isSaving || preparingActivation.current) return;
|
|
176
|
+
preparingActivation.current = true;
|
|
177
|
+
try {
|
|
178
|
+
const saved = isDirty || record.status === "load_failed" ? await save("inactive") : record;
|
|
179
|
+
if (!saved?.id) return;
|
|
180
|
+
const checksum = await sha256Hex(saved.sourceCode ?? sourceCode);
|
|
181
|
+
setActivationTool({ id: saved.id, checksum, name: saved.name ?? name });
|
|
182
|
+
setActivationOpen(true);
|
|
183
|
+
} catch {
|
|
184
|
+
dispatch(showToast({ severity: "error", summary: "Activation failed", detail: "Could not prepare the saved tool source for checks." }));
|
|
185
|
+
} finally {
|
|
186
|
+
preparingActivation.current = false;
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
|
|
187
190
|
const agents = React.useMemo(() => {
|
|
188
191
|
const relatedTools = record?.agentTools;
|
|
189
192
|
const links = Array.isArray(relatedTools) ? relatedTools : relatedTools ? [relatedTools] : [];
|
|
@@ -212,36 +215,33 @@ export function AgentToolRegistryEditorPage() {
|
|
|
212
215
|
<div className="agent-tool-editor__field"><span>Icon</span><SolidIconPicker value={iconName} onChange={setIconName} /></div>
|
|
213
216
|
<label className="agent-tool-editor__field"><span>Description <b>*</b></span><SolidInput value={description} aria-invalid={Boolean(fieldErrors.description)} aria-describedby={fieldErrors.description ? "agent-tool-description-error" : undefined} className={fieldErrors.description ? "agent-tool-editor__input--invalid" : undefined} onChange={(e) => { setDescription(e.target.value); setFieldErrors((current) => ({ ...current, description: "" })); }} />{fieldErrors.description && <small id="agent-tool-description-error" className="agent-tool-editor__field-error">{fieldErrors.description}</small>}</label>
|
|
214
217
|
</div>
|
|
218
|
+
{!record?.id && <label className="agent-tool-editor__field"><span>Tool status</span><select value="inactive" disabled aria-label="Tool status"><option value="inactive">Inactive</option></select><small>New tools start inactive. Run configuration and initialization checks to activate.</small></label>}
|
|
215
219
|
<label className="agent-tool-editor__field"><span>Tool type <b>*</b></span><select value={type} aria-invalid={Boolean(fieldErrors.type)} aria-describedby={fieldErrors.type ? "agent-tool-type-error" : undefined} className={fieldErrors.type ? "agent-tool-editor__input--invalid" : undefined} onChange={(e) => { setType(e.target.value); setFieldErrors((current) => ({ ...current, type: "" })); }}>
|
|
216
220
|
{isReadOnly && <option value="solidx">SolidX</option>}<option value="thirdparty">Third Party</option><option value="custom">Custom</option>
|
|
217
221
|
</select>{fieldErrors.type && <small id="agent-tool-type-error" className="agent-tool-editor__field-error">{fieldErrors.type}</small>}</label>
|
|
218
|
-
<
|
|
219
|
-
{tags.map((tag, index) => <span className="agent-tool-editor__tag" key={`${tag}-${index}`}>{tag}<button type="button" aria-label={`Remove ${tag}`} onClick={() => setTags((current) => { const next = current.filter((_, i) => i !== index); if (next.length) setFieldErrors((errors) => ({ ...errors, tags: "" })); return next; })}><X size={13} /></button></span>)}
|
|
220
|
-
<input value={tagDraft} aria-label="Add a tag" placeholder="Type a tag and press Enter" onChange={(e) => setTagDraft(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); addTag(); } }} />
|
|
221
|
-
<SolidButton type="button" variant="secondary" size="small" onClick={addTag}><Plus size={14} /> Add</SolidButton>
|
|
222
|
-
</div>{fieldErrors.tags && <small className="agent-tool-editor__field-error">{fieldErrors.tags}</small>}<small>Tags are saved as a JSON array.</small></div>
|
|
222
|
+
<AgentHubTagsField value={tags} onChange={setTags} disabled={isReadOnly || isCreating || isSaving} onBusyChange={setCreatingTag} />
|
|
223
223
|
{record?.id && <section className="agent-tool-editor__workflow" aria-labelledby="agent-tool-lifecycle-title">
|
|
224
|
-
<div className="agent-tool-editor__workflow-head"><div><h2 id="agent-tool-lifecycle-title">Tool lifecycle</h2><p>
|
|
225
|
-
<div className="agent-tool-editor__workflow-stages" aria-label={`Current tool stage: ${(record.status ?? "
|
|
224
|
+
<div className="agent-tool-editor__workflow-head"><div><h2 id="agent-tool-lifecycle-title">Tool lifecycle</h2><p>Configuration and initialization must pass before this tool can be activated.</p></div></div>
|
|
225
|
+
<div className="agent-tool-editor__workflow-stages" aria-label={`Current tool stage: ${(record.status ?? "inactive").replace(/[_-]+/g, " ")}`}>
|
|
226
226
|
{([ ["active", "Active", "Enabled for loading into linked agents."], ["inactive", "Inactive", "Not loaded for linked agents."], ["load_failed", "Load failed", "AgentHub could not load this tool."] ] as const).map(([value, label, description], index) => {
|
|
227
|
-
const currentStatus = record.status ?? "
|
|
227
|
+
const currentStatus = record.status ?? "inactive";
|
|
228
228
|
const isCurrent = currentStatus === value;
|
|
229
229
|
const canRetry = value === "load_failed" && isCurrent;
|
|
230
|
-
const disabled = isCreating || isSaving || (!canRetry && (value === "load_failed" || isCurrent));
|
|
230
|
+
const disabled = isReadOnly || activationOpen || isCreating || isSaving || (!canRetry && (value === "load_failed" || isCurrent));
|
|
231
231
|
return <React.Fragment key={value}>
|
|
232
232
|
{index > 0 && <div className="agent-tool-editor__workflow-connector" aria-hidden="true" />}
|
|
233
233
|
<button type="button" className={`agent-tool-editor__workflow-stage agent-tool-editor__workflow-stage--${value}${isCurrent ? " is-current" : ""}`}
|
|
234
234
|
aria-current={isCurrent ? "step" : undefined} aria-pressed={isCurrent} disabled={disabled}
|
|
235
|
-
onClick={() =>
|
|
235
|
+
onClick={() => value === "inactive" ? void save("inactive") : void beginActivation()}>
|
|
236
236
|
<span className="agent-tool-editor__workflow-mark">{index + 1}</span>
|
|
237
|
-
<span className="agent-tool-editor__workflow-copy"><strong>{label}</strong><small>{description}</small><small className="agent-tool-editor__workflow-cta">{canRetry ? "
|
|
237
|
+
<span className="agent-tool-editor__workflow-copy"><strong>{label}</strong><small>{description}</small><small className="agent-tool-editor__workflow-cta">{canRetry ? "Run checks and retry activation" : isCurrent ? "Current stage" : value === "load_failed" ? "Set automatically by AgentHub" : value === "active" ? "Run checks to activate" : "Click to deactivate"}</small></span>
|
|
238
238
|
{isCurrent && <span className="agent-tool-editor__workflow-current">Current</span>}
|
|
239
239
|
</button>
|
|
240
240
|
</React.Fragment>;
|
|
241
241
|
})}
|
|
242
242
|
</div>
|
|
243
|
-
{record.status === "load_failed" && <small className="agent-tool-editor__workflow-hint">Fix the source or checksum
|
|
244
|
-
<small className="agent-tool-editor__workflow-hint">
|
|
243
|
+
{record.status === "load_failed" && <small className="agent-tool-editor__workflow-hint">Fix the source or checksum, then run configuration and initialization checks before retrying activation.</small>}
|
|
244
|
+
<small className="agent-tool-editor__workflow-hint">Activation checks use the saved tool configuration. Restart linked agent processes to apply status changes.</small>
|
|
245
245
|
</section>}
|
|
246
246
|
</fieldset> },
|
|
247
247
|
{ value: "tool", label: "Tool", content: <div className="agent-tool-editor__tool">
|
|
@@ -260,12 +260,20 @@ export function AgentToolRegistryEditorPage() {
|
|
|
260
260
|
return <main className="agent-tool-editor">
|
|
261
261
|
<header className="agent-tool-editor__header"><div><div className="agent-tool-editor__heading-with-refresh"><h1>{record ? "Edit Tool" : "Create Tool"}</h1>{record?.id && <button type="button" className={`agent-tool-editor__refresh${isFetching ? " is-loading" : ""}`} aria-label="Refresh tool" title="Refresh tool" disabled={isFetching || isSaving} onClick={requestRefresh}><RefreshCw size={14} /></button>}</div></div><div className="agent-tool-editor__actions">
|
|
262
262
|
<SolidButton variant="secondary" leftIcon={<ArrowLeft size={16} />} onClick={() => navigate(-1)}>Back</SolidButton>
|
|
263
|
-
{!isReadOnly && <SolidButton loading={isCreating || isSaving} onClick={() => void save()}>Save Tool</SolidButton>}
|
|
263
|
+
{!isReadOnly && <SolidButton disabled={activationOpen || creatingTag} loading={isCreating || isSaving} onClick={() => void save()}>Save Tool</SolidButton>}
|
|
264
264
|
</div></header>
|
|
265
265
|
<SolidDialog open={confirmRefresh} onOpenChange={setConfirmRefresh} header="Discard unsaved changes?" style={{ width: "min(28rem, 94vw)" }}
|
|
266
266
|
footer={<><SolidButton type="button" variant="secondary" onClick={() => setConfirmRefresh(false)}>Cancel</SolidButton><SolidButton type="button" disabled={isFetching} onClick={() => { setConfirmRefresh(false); void refetch(); }}>Refresh and discard</SolidButton></>}>
|
|
267
267
|
<SolidDialogBody><p>You have unsaved changes. Refreshing will discard them and load the latest tool content.</p></SolidDialogBody>
|
|
268
268
|
</SolidDialog>
|
|
269
|
+
{activationOpen && activationTool && <AgentToolActivationDialog open={activationOpen} onOpenChange={setActivationOpen}
|
|
270
|
+
toolId={activationTool.id} checksum={activationTool.checksum} toolName={activationTool.name}
|
|
271
|
+
onActivated={async () => {
|
|
272
|
+
await solidPatch(`/agent-tool-registry/${activationTool.id}`, { status: "active", checksum: activationTool.checksum });
|
|
273
|
+
setAuditRefreshVersion((version) => version + 1);
|
|
274
|
+
void refetch();
|
|
275
|
+
dispatch(showToast({ severity: "success", summary: "Tool activated", detail: "Configuration and initialization checks passed." }));
|
|
276
|
+
}} />}
|
|
269
277
|
{isLoading ? <div className="agent-tool-editor__loading">Loading tool…</div> : record?.id ? (
|
|
270
278
|
<AgentRegistryAuditPanel modelSingularName="agentToolRegistry" recordId={record.id} refreshVersion={auditRefreshVersion} modelUserKey={record.name}>
|
|
271
279
|
<SolidTabGroup tabs={tabs} value={activeTab} onValueChange={setActiveTab} className="agent-tool-editor__tabs" listClassName="agent-tool-editor__tab-list" panelClassName="agent-tool-editor__tab-panel" />
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArchivedChatterMessagesPage.d.ts","sourceRoot":"","sources":["../../../../../src/routes/pages/admin/core/ArchivedChatterMessagesPage.tsx"],"names":[],"mappings":"AASA,wBAAgB,2BAA2B,4CAsF1C"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
14
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
22
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
23
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
24
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
25
|
+
function step(op) {
|
|
26
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
27
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
28
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
29
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
30
|
+
switch (op[0]) {
|
|
31
|
+
case 0: case 1: t = op; break;
|
|
32
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
33
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
34
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
35
|
+
default:
|
|
36
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
37
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
38
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
39
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
40
|
+
if (t[2]) _.ops.pop();
|
|
41
|
+
_.trys.pop(); continue;
|
|
42
|
+
}
|
|
43
|
+
op = body.call(thisArg, _);
|
|
44
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
45
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
49
|
+
import React from 'react';
|
|
50
|
+
import qs from 'qs';
|
|
51
|
+
import { ChevronLeft, ChevronRight, Loader2 } from 'lucide-react';
|
|
52
|
+
import { SolidButton } from '../../../../components/shad-cn-ui';
|
|
53
|
+
import { useGetArchivedChatterMessagesQuery, useLazyGetArchivedChatterMessageQuery } from '../../../../redux/api/solidChatterMessageApi';
|
|
54
|
+
var PAGE_SIZE = 25;
|
|
55
|
+
export function ArchivedChatterMessagesPage() {
|
|
56
|
+
var _this = this;
|
|
57
|
+
var _a, _b, _c, _d, _e;
|
|
58
|
+
var _f = React.useState({ entityName: '', entityId: '', messageType: '', messageSubType: '', user: '', from: '', to: '' }), filters = _f[0], setFilters = _f[1];
|
|
59
|
+
var _g = React.useState(0), offset = _g[0], setOffset = _g[1];
|
|
60
|
+
var _h = React.useState(null), selectedId = _h[0], setSelectedId = _h[1];
|
|
61
|
+
var queryString = React.useMemo(function () {
|
|
62
|
+
var query = { limit: PAGE_SIZE, offset: offset };
|
|
63
|
+
var where = {};
|
|
64
|
+
if (filters.entityName.trim())
|
|
65
|
+
where.coModelName = { $containsi: filters.entityName.trim() };
|
|
66
|
+
if (filters.entityId.trim() && Number.isFinite(Number(filters.entityId)))
|
|
67
|
+
where.coModelEntityId = { $eq: Number(filters.entityId) };
|
|
68
|
+
if (filters.messageType)
|
|
69
|
+
where.messageType = { $eq: filters.messageType };
|
|
70
|
+
if (filters.messageSubType.trim())
|
|
71
|
+
where.messageSubType = { $containsi: filters.messageSubType.trim() };
|
|
72
|
+
if (filters.user.trim())
|
|
73
|
+
where.user = { fullName: { $containsi: filters.user.trim() } };
|
|
74
|
+
if (filters.from || filters.to) {
|
|
75
|
+
where.createdAt = {};
|
|
76
|
+
if (filters.from)
|
|
77
|
+
where.createdAt.$gte = new Date(filters.from).toISOString();
|
|
78
|
+
if (filters.to)
|
|
79
|
+
where.createdAt.$lte = new Date(filters.to).toISOString();
|
|
80
|
+
}
|
|
81
|
+
if (Object.keys(where).length)
|
|
82
|
+
query.filters = where;
|
|
83
|
+
query.sort = ['createdAt:DESC'];
|
|
84
|
+
return qs.stringify(query, { encodeValuesOnly: true });
|
|
85
|
+
}, [filters, offset]);
|
|
86
|
+
var _j = useGetArchivedChatterMessagesQuery(queryString), data = _j.data, isLoading = _j.isLoading, isFetching = _j.isFetching, error = _j.error;
|
|
87
|
+
var _k = useLazyGetArchivedChatterMessageQuery(), fetchOne = _k[0], _l = _k[1], detailData = _l.data, detailLoading = _l.isFetching;
|
|
88
|
+
var records = (_a = data === null || data === void 0 ? void 0 : data.records) !== null && _a !== void 0 ? _a : [];
|
|
89
|
+
var meta = (_b = data === null || data === void 0 ? void 0 : data.meta) !== null && _b !== void 0 ? _b : {};
|
|
90
|
+
var openRecord = function (id) { return __awaiter(_this, void 0, void 0, function () {
|
|
91
|
+
return __generator(this, function (_a) {
|
|
92
|
+
switch (_a.label) {
|
|
93
|
+
case 0:
|
|
94
|
+
setSelectedId(id);
|
|
95
|
+
return [4 /*yield*/, fetchOne(id)];
|
|
96
|
+
case 1:
|
|
97
|
+
_a.sent();
|
|
98
|
+
return [2 /*return*/];
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}); };
|
|
102
|
+
var selected = detailData === null || detailData === void 0 ? void 0 : detailData.record;
|
|
103
|
+
return _jsxs("main", { className: "mx-auto flex w-full max-w-7xl flex-col gap-5 p-6", children: [_jsxs("header", { children: [_jsx("h1", { className: "m-0 text-2xl font-semibold", children: "Archived Messages" }), _jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Search chatter messages moved to the configured archive store." })] }), (data === null || data === void 0 ? void 0 : data.available) === false ? _jsxs("section", { className: "rounded-lg border p-6", role: "status", children: [_jsx("h2", { className: "m-0 text-lg font-semibold", children: "Chatter archival is not enabled" }), _jsx("p", { className: "mb-0 mt-2 text-sm text-muted-foreground", children: "Configure and register an IChatterMessageArchive provider in the consuming project to archive and browse messages." })] }) : _jsxs(_Fragment, { children: [_jsxs("section", { className: "grid grid-cols-1 gap-3 rounded-lg border p-4 sm:grid-cols-2 lg:grid-cols-7", "aria-label": "Archive filters", children: [_jsxs("label", { className: "flex flex-col gap-1 text-sm", children: ["Entity name", _jsx("input", { className: "rounded border px-3 py-2", value: filters.entityName, onChange: function (e) { setOffset(0); setFilters(__assign(__assign({}, filters), { entityName: e.target.value })); }, placeholder: "e.g. customer" })] }), _jsxs("label", { className: "flex flex-col gap-1 text-sm", children: ["Entity ID", _jsx("input", { className: "rounded border px-3 py-2", inputMode: "numeric", value: filters.entityId, onChange: function (e) { setOffset(0); setFilters(__assign(__assign({}, filters), { entityId: e.target.value })); }, placeholder: "Record ID" })] }), _jsxs("label", { className: "flex flex-col gap-1 text-sm", children: ["Message type", _jsxs("select", { className: "rounded border px-3 py-2", value: filters.messageType, onChange: function (e) { setOffset(0); setFilters(__assign(__assign({}, filters), { messageType: e.target.value })); }, children: [_jsx("option", { value: "", children: "All types" }), _jsx("option", { value: "audit", children: "Audit" }), _jsx("option", { value: "custom", children: "Custom" })] })] }), _jsxs("label", { className: "flex flex-col gap-1 text-sm", children: ["Message subtype", _jsx("input", { className: "rounded border px-3 py-2", value: filters.messageSubType, onChange: function (e) { setOffset(0); setFilters(__assign(__assign({}, filters), { messageSubType: e.target.value })); }, placeholder: "e.g. audit_update" })] }), _jsxs("label", { className: "flex flex-col gap-1 text-sm", children: ["Changed by", _jsx("input", { className: "rounded border px-3 py-2", value: filters.user, onChange: function (e) { setOffset(0); setFilters(__assign(__assign({}, filters), { user: e.target.value })); }, placeholder: "User name" })] }), _jsxs("label", { className: "flex flex-col gap-1 text-sm", children: ["From", _jsx("input", { className: "rounded border px-3 py-2", type: "datetime-local", value: filters.from, onChange: function (e) { setOffset(0); setFilters(__assign(__assign({}, filters), { from: e.target.value })); } })] }), _jsxs("label", { className: "flex flex-col gap-1 text-sm", children: ["To", _jsx("input", { className: "rounded border px-3 py-2", type: "datetime-local", value: filters.to, onChange: function (e) { setOffset(0); setFilters(__assign(__assign({}, filters), { to: e.target.value })); } })] })] }), error && _jsx("p", { role: "alert", className: "text-sm text-red-600", children: "Unable to load archived messages. Check provider availability and try again." }), _jsx("section", { className: "overflow-hidden rounded-lg border", children: isLoading ? _jsxs("div", { className: "flex items-center gap-2 p-8", children: [_jsx(Loader2, { className: "animate-spin", size: 18 }), "Loading archived messages\u2026"] }) : records.length === 0 ? _jsx("p", { className: "p-8 text-center text-sm text-muted-foreground", children: "No archived messages match these filters." }) : _jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full border-collapse text-left text-sm", children: [_jsx("thead", { className: "bg-muted/50", children: _jsxs("tr", { children: [_jsx("th", { className: "p-3", children: "Date" }), _jsx("th", { className: "p-3", children: "Entity" }), _jsx("th", { className: "p-3", children: "Entity ID" }), _jsx("th", { className: "p-3", children: "Type" }), _jsx("th", { className: "p-3", children: "User" }), _jsx("th", { className: "p-3", children: "Message" })] }) }), _jsx("tbody", { children: records.map(function (message) {
|
|
104
|
+
var _a;
|
|
105
|
+
return _jsxs("tr", { className: "border-t hover:bg-muted/30", children: [_jsx("td", { className: "whitespace-nowrap p-3", children: message.createdAt ? new Date(message.createdAt).toLocaleString() : '—' }), _jsx("td", { className: "p-3", children: message.modelDisplayName || message.coModelName }), _jsx("td", { className: "p-3", children: message.coModelEntityId }), _jsx("td", { className: "p-3", children: message.messageSubType || message.messageType }), _jsx("td", { className: "p-3", children: ((_a = message.user) === null || _a === void 0 ? void 0 : _a.fullName) || 'System' }), _jsx("td", { className: "max-w-md p-3", children: _jsx("button", { type: "button", className: "text-left text-primary underline", onClick: function () { return openRecord(message.id); }, children: message.messageBody || 'View message' }) })] }, message.id);
|
|
106
|
+
}) })] }) }) }), _jsxs("footer", { className: "flex items-center justify-between", children: [_jsxs("span", { className: "text-sm text-muted-foreground", children: [(_c = meta.totalRecords) !== null && _c !== void 0 ? _c : records.length, " archived messages", isFetching ? ' · Updating…' : ''] }), _jsxs("div", { className: "flex gap-2", children: [_jsxs(SolidButton, { variant: "outline", disabled: offset === 0 || isFetching, onClick: function () { return setOffset(Math.max(0, offset - PAGE_SIZE)); }, children: [_jsx(ChevronLeft, { size: 16 }), "Previous"] }), _jsxs(SolidButton, { variant: "outline", disabled: records.length < PAGE_SIZE || isFetching, onClick: function () { return setOffset(offset + PAGE_SIZE); }, children: ["Next", _jsx(ChevronRight, { size: 16 })] })] })] })] }), selectedId !== null && _jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4", role: "presentation", onClick: function () { return setSelectedId(null); }, children: _jsxs("section", { role: "dialog", "aria-modal": "true", "aria-label": "Archived chatter message", className: "max-h-[85vh] w-full max-w-3xl overflow-auto rounded-lg bg-background p-6 shadow-xl", onClick: function (e) { return e.stopPropagation(); }, children: [_jsxs("div", { className: "mb-4 flex items-start justify-between", children: [_jsxs("h2", { className: "m-0 text-xl font-semibold", children: ["Archived message #", selectedId] }), _jsx("button", { type: "button", className: "rounded px-2 py-1 hover:bg-muted", onClick: function () { return setSelectedId(null); }, children: "Close" })] }), detailLoading ? _jsx("p", { children: "Loading message\u2026" }) : selected ? _jsxs(_Fragment, { children: [_jsxs("dl", { className: "grid grid-cols-2 gap-3 text-sm", children: [_jsx("dt", { children: "Entity" }), _jsx("dd", { children: selected.modelDisplayName || selected.coModelName }), _jsx("dt", { children: "Entity ID" }), _jsx("dd", { children: selected.coModelEntityId }), _jsx("dt", { children: "Date" }), _jsx("dd", { children: selected.createdAt ? new Date(selected.createdAt).toLocaleString() : '—' }), _jsx("dt", { children: "User" }), _jsx("dd", { children: ((_d = selected.user) === null || _d === void 0 ? void 0 : _d.fullName) || 'System' }), _jsx("dt", { children: "Subtype" }), _jsx("dd", { children: selected.messageSubType })] }), _jsx("h3", { className: "mt-5 text-base font-semibold", children: "Message" }), _jsx("pre", { className: "whitespace-pre-wrap break-words rounded bg-muted p-3 text-sm", children: selected.messageBody || '' }), !!((_e = selected.chatterMessageDetails) === null || _e === void 0 ? void 0 : _e.length) && _jsxs(_Fragment, { children: [_jsx("h3", { className: "mt-5 text-base font-semibold", children: "Change details" }), _jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full text-left text-sm", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { className: "p-2", children: "Field" }), _jsx("th", { className: "p-2", children: "Previous" }), _jsx("th", { className: "p-2", children: "Current" })] }) }), _jsx("tbody", { children: selected.chatterMessageDetails.map(function (detail, index) { var _a, _b, _c, _d, _e; return _jsxs("tr", { className: "border-t", children: [_jsx("td", { className: "p-2", children: detail.fieldDisplayName || detail.fieldName }), _jsx("td", { className: "p-2", children: (_b = (_a = detail.oldValueDisplay) !== null && _a !== void 0 ? _a : detail.oldValue) !== null && _b !== void 0 ? _b : '—' }), _jsx("td", { className: "p-2", children: (_d = (_c = detail.newValueDisplay) !== null && _c !== void 0 ? _c : detail.newValue) !== null && _d !== void 0 ? _d : '—' })] }, (_e = detail.id) !== null && _e !== void 0 ? _e : index); }) })] }) })] })] }) : _jsx("p", { role: "alert", children: "Could not load this archived message." })] }) })] });
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=ArchivedChatterMessagesPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArchivedChatterMessagesPage.js","sourceRoot":"","sources":["../../../../../src/routes/pages/admin/core/ArchivedChatterMessagesPage.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport qs from 'qs';\nimport { ChevronLeft, ChevronRight, Loader2 } from 'lucide-react';\nimport { SolidButton } from '../../../../components/shad-cn-ui';\nimport { useGetArchivedChatterMessagesQuery, useLazyGetArchivedChatterMessageQuery } from '../../../../redux/api/solidChatterMessageApi';\n\nconst PAGE_SIZE = 25;\ntype Filters = { entityName: string; entityId: string; messageType: string; messageSubType: string; user: string; from: string; to: string };\n\nexport function ArchivedChatterMessagesPage() {\n const [filters, setFilters] = React.useState<Filters>({ entityName: '', entityId: '', messageType: '', messageSubType: '', user: '', from: '', to: '' });\n const [offset, setOffset] = React.useState(0);\n const [selectedId, setSelectedId] = React.useState<number | null>(null);\n\n const queryString = React.useMemo(() => {\n const query: any = { limit: PAGE_SIZE, offset };\n const where: Record<string, any> = {};\n if (filters.entityName.trim()) where.coModelName = { $containsi: filters.entityName.trim() };\n if (filters.entityId.trim() && Number.isFinite(Number(filters.entityId))) where.coModelEntityId = { $eq: Number(filters.entityId) };\n if (filters.messageType) where.messageType = { $eq: filters.messageType };\n if (filters.messageSubType.trim()) where.messageSubType = { $containsi: filters.messageSubType.trim() };\n if (filters.user.trim()) where.user = { fullName: { $containsi: filters.user.trim() } };\n if (filters.from || filters.to) {\n where.createdAt = {};\n if (filters.from) where.createdAt.$gte = new Date(filters.from).toISOString();\n if (filters.to) where.createdAt.$lte = new Date(filters.to).toISOString();\n }\n if (Object.keys(where).length) query.filters = where;\n query.sort = ['createdAt:DESC'];\n return qs.stringify(query, { encodeValuesOnly: true });\n }, [filters, offset]);\n\n const { data, isLoading, isFetching, error } = useGetArchivedChatterMessagesQuery(queryString);\n const [fetchOne, { data: detailData, isFetching: detailLoading }] = useLazyGetArchivedChatterMessageQuery();\n const records = data?.records ?? [];\n const meta = data?.meta ?? {};\n\n const openRecord = async (id: number) => {\n setSelectedId(id);\n await fetchOne(id);\n };\n const selected = detailData?.record;\n\n return <main className=\"mx-auto flex w-full max-w-7xl flex-col gap-5 p-6\">\n <header>\n <h1 className=\"m-0 text-2xl font-semibold\">Archived Messages</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">Search chatter messages moved to the configured archive store.</p>\n </header>\n\n {data?.available === false ? <section className=\"rounded-lg border p-6\" role=\"status\">\n <h2 className=\"m-0 text-lg font-semibold\">Chatter archival is not enabled</h2>\n <p className=\"mb-0 mt-2 text-sm text-muted-foreground\">Configure and register an IChatterMessageArchive provider in the consuming project to archive and browse messages.</p>\n </section> : <>\n <section className=\"grid grid-cols-1 gap-3 rounded-lg border p-4 sm:grid-cols-2 lg:grid-cols-7\" aria-label=\"Archive filters\">\n <label className=\"flex flex-col gap-1 text-sm\">Entity name<input className=\"rounded border px-3 py-2\" value={filters.entityName} onChange={e => { setOffset(0); setFilters({ ...filters, entityName: e.target.value }); }} placeholder=\"e.g. customer\" /></label>\n <label className=\"flex flex-col gap-1 text-sm\">Entity ID<input className=\"rounded border px-3 py-2\" inputMode=\"numeric\" value={filters.entityId} onChange={e => { setOffset(0); setFilters({ ...filters, entityId: e.target.value }); }} placeholder=\"Record ID\" /></label>\n <label className=\"flex flex-col gap-1 text-sm\">Message type<select className=\"rounded border px-3 py-2\" value={filters.messageType} onChange={e => { setOffset(0); setFilters({ ...filters, messageType: e.target.value }); }}><option value=\"\">All types</option><option value=\"audit\">Audit</option><option value=\"custom\">Custom</option></select></label>\n <label className=\"flex flex-col gap-1 text-sm\">Message subtype<input className=\"rounded border px-3 py-2\" value={filters.messageSubType} onChange={e => { setOffset(0); setFilters({ ...filters, messageSubType: e.target.value }); }} placeholder=\"e.g. audit_update\" /></label>\n <label className=\"flex flex-col gap-1 text-sm\">Changed by<input className=\"rounded border px-3 py-2\" value={filters.user} onChange={e => { setOffset(0); setFilters({ ...filters, user: e.target.value }); }} placeholder=\"User name\" /></label>\n <label className=\"flex flex-col gap-1 text-sm\">From<input className=\"rounded border px-3 py-2\" type=\"datetime-local\" value={filters.from} onChange={e => { setOffset(0); setFilters({ ...filters, from: e.target.value }); }} /></label>\n <label className=\"flex flex-col gap-1 text-sm\">To<input className=\"rounded border px-3 py-2\" type=\"datetime-local\" value={filters.to} onChange={e => { setOffset(0); setFilters({ ...filters, to: e.target.value }); }} /></label>\n </section>\n\n {error && <p role=\"alert\" className=\"text-sm text-red-600\">Unable to load archived messages. Check provider availability and try again.</p>}\n <section className=\"overflow-hidden rounded-lg border\">\n {isLoading ? <div className=\"flex items-center gap-2 p-8\"><Loader2 className=\"animate-spin\" size={18} />Loading archived messages…</div> : records.length === 0 ? <p className=\"p-8 text-center text-sm text-muted-foreground\">No archived messages match these filters.</p> : <div className=\"overflow-x-auto\">\n <table className=\"w-full border-collapse text-left text-sm\">\n <thead className=\"bg-muted/50\"><tr><th className=\"p-3\">Date</th><th className=\"p-3\">Entity</th><th className=\"p-3\">Entity ID</th><th className=\"p-3\">Type</th><th className=\"p-3\">User</th><th className=\"p-3\">Message</th></tr></thead>\n <tbody>{records.map((message: any) => <tr key={message.id} className=\"border-t hover:bg-muted/30\">\n <td className=\"whitespace-nowrap p-3\">{message.createdAt ? new Date(message.createdAt).toLocaleString() : '—'}</td>\n <td className=\"p-3\">{message.modelDisplayName || message.coModelName}</td><td className=\"p-3\">{message.coModelEntityId}</td>\n <td className=\"p-3\">{message.messageSubType || message.messageType}</td><td className=\"p-3\">{message.user?.fullName || 'System'}</td>\n <td className=\"max-w-md p-3\"><button type=\"button\" className=\"text-left text-primary underline\" onClick={() => openRecord(message.id)}>{message.messageBody || 'View message'}</button></td>\n </tr>)}</tbody>\n </table>\n </div>}\n </section>\n\n <footer className=\"flex items-center justify-between\">\n <span className=\"text-sm text-muted-foreground\">{meta.totalRecords ?? records.length} archived messages{isFetching ? ' · Updating…' : ''}</span>\n <div className=\"flex gap-2\"><SolidButton variant=\"outline\" disabled={offset === 0 || isFetching} onClick={() => setOffset(Math.max(0, offset - PAGE_SIZE))}><ChevronLeft size={16} />Previous</SolidButton><SolidButton variant=\"outline\" disabled={records.length < PAGE_SIZE || isFetching} onClick={() => setOffset(offset + PAGE_SIZE)}>Next<ChevronRight size={16} /></SolidButton></div>\n </footer>\n </>}\n\n {selectedId !== null && <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4\" role=\"presentation\" onClick={() => setSelectedId(null)}>\n <section role=\"dialog\" aria-modal=\"true\" aria-label=\"Archived chatter message\" className=\"max-h-[85vh] w-full max-w-3xl overflow-auto rounded-lg bg-background p-6 shadow-xl\" onClick={e => e.stopPropagation()}>\n <div className=\"mb-4 flex items-start justify-between\"><h2 className=\"m-0 text-xl font-semibold\">Archived message #{selectedId}</h2><button type=\"button\" className=\"rounded px-2 py-1 hover:bg-muted\" onClick={() => setSelectedId(null)}>Close</button></div>\n {detailLoading ? <p>Loading message…</p> : selected ? <>\n <dl className=\"grid grid-cols-2 gap-3 text-sm\"><dt>Entity</dt><dd>{selected.modelDisplayName || selected.coModelName}</dd><dt>Entity ID</dt><dd>{selected.coModelEntityId}</dd><dt>Date</dt><dd>{selected.createdAt ? new Date(selected.createdAt).toLocaleString() : '—'}</dd><dt>User</dt><dd>{selected.user?.fullName || 'System'}</dd><dt>Subtype</dt><dd>{selected.messageSubType}</dd></dl>\n <h3 className=\"mt-5 text-base font-semibold\">Message</h3><pre className=\"whitespace-pre-wrap break-words rounded bg-muted p-3 text-sm\">{selected.messageBody || ''}</pre>\n {!!selected.chatterMessageDetails?.length && <><h3 className=\"mt-5 text-base font-semibold\">Change details</h3><div className=\"overflow-x-auto\"><table className=\"w-full text-left text-sm\"><thead><tr><th className=\"p-2\">Field</th><th className=\"p-2\">Previous</th><th className=\"p-2\">Current</th></tr></thead><tbody>{selected.chatterMessageDetails.map((detail: any, index: number) => <tr className=\"border-t\" key={detail.id ?? index}><td className=\"p-2\">{detail.fieldDisplayName || detail.fieldName}</td><td className=\"p-2\">{detail.oldValueDisplay ?? detail.oldValue ?? '—'}</td><td className=\"p-2\">{detail.newValueDisplay ?? detail.newValue ?? '—'}</td></tr>)}</tbody></table></div></>}\n </> : <p role=\"alert\">Could not load this archived message.</p>}\n </section>\n </div>}\n </main>;\n}\n"]}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import qs from 'qs';
|
|
3
|
+
import { ChevronLeft, ChevronRight, Loader2 } from 'lucide-react';
|
|
4
|
+
import { SolidButton } from '../../../../components/shad-cn-ui';
|
|
5
|
+
import { useGetArchivedChatterMessagesQuery, useLazyGetArchivedChatterMessageQuery } from '../../../../redux/api/solidChatterMessageApi';
|
|
6
|
+
|
|
7
|
+
const PAGE_SIZE = 25;
|
|
8
|
+
type Filters = { entityName: string; entityId: string; messageType: string; messageSubType: string; user: string; from: string; to: string };
|
|
9
|
+
|
|
10
|
+
export function ArchivedChatterMessagesPage() {
|
|
11
|
+
const [filters, setFilters] = React.useState<Filters>({ entityName: '', entityId: '', messageType: '', messageSubType: '', user: '', from: '', to: '' });
|
|
12
|
+
const [offset, setOffset] = React.useState(0);
|
|
13
|
+
const [selectedId, setSelectedId] = React.useState<number | null>(null);
|
|
14
|
+
|
|
15
|
+
const queryString = React.useMemo(() => {
|
|
16
|
+
const query: any = { limit: PAGE_SIZE, offset };
|
|
17
|
+
const where: Record<string, any> = {};
|
|
18
|
+
if (filters.entityName.trim()) where.coModelName = { $containsi: filters.entityName.trim() };
|
|
19
|
+
if (filters.entityId.trim() && Number.isFinite(Number(filters.entityId))) where.coModelEntityId = { $eq: Number(filters.entityId) };
|
|
20
|
+
if (filters.messageType) where.messageType = { $eq: filters.messageType };
|
|
21
|
+
if (filters.messageSubType.trim()) where.messageSubType = { $containsi: filters.messageSubType.trim() };
|
|
22
|
+
if (filters.user.trim()) where.user = { fullName: { $containsi: filters.user.trim() } };
|
|
23
|
+
if (filters.from || filters.to) {
|
|
24
|
+
where.createdAt = {};
|
|
25
|
+
if (filters.from) where.createdAt.$gte = new Date(filters.from).toISOString();
|
|
26
|
+
if (filters.to) where.createdAt.$lte = new Date(filters.to).toISOString();
|
|
27
|
+
}
|
|
28
|
+
if (Object.keys(where).length) query.filters = where;
|
|
29
|
+
query.sort = ['createdAt:DESC'];
|
|
30
|
+
return qs.stringify(query, { encodeValuesOnly: true });
|
|
31
|
+
}, [filters, offset]);
|
|
32
|
+
|
|
33
|
+
const { data, isLoading, isFetching, error } = useGetArchivedChatterMessagesQuery(queryString);
|
|
34
|
+
const [fetchOne, { data: detailData, isFetching: detailLoading }] = useLazyGetArchivedChatterMessageQuery();
|
|
35
|
+
const records = data?.records ?? [];
|
|
36
|
+
const meta = data?.meta ?? {};
|
|
37
|
+
|
|
38
|
+
const openRecord = async (id: number) => {
|
|
39
|
+
setSelectedId(id);
|
|
40
|
+
await fetchOne(id);
|
|
41
|
+
};
|
|
42
|
+
const selected = detailData?.record;
|
|
43
|
+
|
|
44
|
+
return <main className="mx-auto flex w-full max-w-7xl flex-col gap-5 p-6">
|
|
45
|
+
<header>
|
|
46
|
+
<h1 className="m-0 text-2xl font-semibold">Archived Messages</h1>
|
|
47
|
+
<p className="mt-1 text-sm text-muted-foreground">Search chatter messages moved to the configured archive store.</p>
|
|
48
|
+
</header>
|
|
49
|
+
|
|
50
|
+
{data?.available === false ? <section className="rounded-lg border p-6" role="status">
|
|
51
|
+
<h2 className="m-0 text-lg font-semibold">Chatter archival is not enabled</h2>
|
|
52
|
+
<p className="mb-0 mt-2 text-sm text-muted-foreground">Configure and register an IChatterMessageArchive provider in the consuming project to archive and browse messages.</p>
|
|
53
|
+
</section> : <>
|
|
54
|
+
<section className="grid grid-cols-1 gap-3 rounded-lg border p-4 sm:grid-cols-2 lg:grid-cols-7" aria-label="Archive filters">
|
|
55
|
+
<label className="flex flex-col gap-1 text-sm">Entity name<input className="rounded border px-3 py-2" value={filters.entityName} onChange={e => { setOffset(0); setFilters({ ...filters, entityName: e.target.value }); }} placeholder="e.g. customer" /></label>
|
|
56
|
+
<label className="flex flex-col gap-1 text-sm">Entity ID<input className="rounded border px-3 py-2" inputMode="numeric" value={filters.entityId} onChange={e => { setOffset(0); setFilters({ ...filters, entityId: e.target.value }); }} placeholder="Record ID" /></label>
|
|
57
|
+
<label className="flex flex-col gap-1 text-sm">Message type<select className="rounded border px-3 py-2" value={filters.messageType} onChange={e => { setOffset(0); setFilters({ ...filters, messageType: e.target.value }); }}><option value="">All types</option><option value="audit">Audit</option><option value="custom">Custom</option></select></label>
|
|
58
|
+
<label className="flex flex-col gap-1 text-sm">Message subtype<input className="rounded border px-3 py-2" value={filters.messageSubType} onChange={e => { setOffset(0); setFilters({ ...filters, messageSubType: e.target.value }); }} placeholder="e.g. audit_update" /></label>
|
|
59
|
+
<label className="flex flex-col gap-1 text-sm">Changed by<input className="rounded border px-3 py-2" value={filters.user} onChange={e => { setOffset(0); setFilters({ ...filters, user: e.target.value }); }} placeholder="User name" /></label>
|
|
60
|
+
<label className="flex flex-col gap-1 text-sm">From<input className="rounded border px-3 py-2" type="datetime-local" value={filters.from} onChange={e => { setOffset(0); setFilters({ ...filters, from: e.target.value }); }} /></label>
|
|
61
|
+
<label className="flex flex-col gap-1 text-sm">To<input className="rounded border px-3 py-2" type="datetime-local" value={filters.to} onChange={e => { setOffset(0); setFilters({ ...filters, to: e.target.value }); }} /></label>
|
|
62
|
+
</section>
|
|
63
|
+
|
|
64
|
+
{error && <p role="alert" className="text-sm text-red-600">Unable to load archived messages. Check provider availability and try again.</p>}
|
|
65
|
+
<section className="overflow-hidden rounded-lg border">
|
|
66
|
+
{isLoading ? <div className="flex items-center gap-2 p-8"><Loader2 className="animate-spin" size={18} />Loading archived messages…</div> : records.length === 0 ? <p className="p-8 text-center text-sm text-muted-foreground">No archived messages match these filters.</p> : <div className="overflow-x-auto">
|
|
67
|
+
<table className="w-full border-collapse text-left text-sm">
|
|
68
|
+
<thead className="bg-muted/50"><tr><th className="p-3">Date</th><th className="p-3">Entity</th><th className="p-3">Entity ID</th><th className="p-3">Type</th><th className="p-3">User</th><th className="p-3">Message</th></tr></thead>
|
|
69
|
+
<tbody>{records.map((message: any) => <tr key={message.id} className="border-t hover:bg-muted/30">
|
|
70
|
+
<td className="whitespace-nowrap p-3">{message.createdAt ? new Date(message.createdAt).toLocaleString() : '—'}</td>
|
|
71
|
+
<td className="p-3">{message.modelDisplayName || message.coModelName}</td><td className="p-3">{message.coModelEntityId}</td>
|
|
72
|
+
<td className="p-3">{message.messageSubType || message.messageType}</td><td className="p-3">{message.user?.fullName || 'System'}</td>
|
|
73
|
+
<td className="max-w-md p-3"><button type="button" className="text-left text-primary underline" onClick={() => openRecord(message.id)}>{message.messageBody || 'View message'}</button></td>
|
|
74
|
+
</tr>)}</tbody>
|
|
75
|
+
</table>
|
|
76
|
+
</div>}
|
|
77
|
+
</section>
|
|
78
|
+
|
|
79
|
+
<footer className="flex items-center justify-between">
|
|
80
|
+
<span className="text-sm text-muted-foreground">{meta.totalRecords ?? records.length} archived messages{isFetching ? ' · Updating…' : ''}</span>
|
|
81
|
+
<div className="flex gap-2"><SolidButton variant="outline" disabled={offset === 0 || isFetching} onClick={() => setOffset(Math.max(0, offset - PAGE_SIZE))}><ChevronLeft size={16} />Previous</SolidButton><SolidButton variant="outline" disabled={records.length < PAGE_SIZE || isFetching} onClick={() => setOffset(offset + PAGE_SIZE)}>Next<ChevronRight size={16} /></SolidButton></div>
|
|
82
|
+
</footer>
|
|
83
|
+
</>}
|
|
84
|
+
|
|
85
|
+
{selectedId !== null && <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4" role="presentation" onClick={() => setSelectedId(null)}>
|
|
86
|
+
<section role="dialog" aria-modal="true" aria-label="Archived chatter message" className="max-h-[85vh] w-full max-w-3xl overflow-auto rounded-lg bg-background p-6 shadow-xl" onClick={e => e.stopPropagation()}>
|
|
87
|
+
<div className="mb-4 flex items-start justify-between"><h2 className="m-0 text-xl font-semibold">Archived message #{selectedId}</h2><button type="button" className="rounded px-2 py-1 hover:bg-muted" onClick={() => setSelectedId(null)}>Close</button></div>
|
|
88
|
+
{detailLoading ? <p>Loading message…</p> : selected ? <>
|
|
89
|
+
<dl className="grid grid-cols-2 gap-3 text-sm"><dt>Entity</dt><dd>{selected.modelDisplayName || selected.coModelName}</dd><dt>Entity ID</dt><dd>{selected.coModelEntityId}</dd><dt>Date</dt><dd>{selected.createdAt ? new Date(selected.createdAt).toLocaleString() : '—'}</dd><dt>User</dt><dd>{selected.user?.fullName || 'System'}</dd><dt>Subtype</dt><dd>{selected.messageSubType}</dd></dl>
|
|
90
|
+
<h3 className="mt-5 text-base font-semibold">Message</h3><pre className="whitespace-pre-wrap break-words rounded bg-muted p-3 text-sm">{selected.messageBody || ''}</pre>
|
|
91
|
+
{!!selected.chatterMessageDetails?.length && <><h3 className="mt-5 text-base font-semibold">Change details</h3><div className="overflow-x-auto"><table className="w-full text-left text-sm"><thead><tr><th className="p-2">Field</th><th className="p-2">Previous</th><th className="p-2">Current</th></tr></thead><tbody>{selected.chatterMessageDetails.map((detail: any, index: number) => <tr className="border-t" key={detail.id ?? index}><td className="p-2">{detail.fieldDisplayName || detail.fieldName}</td><td className="p-2">{detail.oldValueDisplay ?? detail.oldValue ?? '—'}</td><td className="p-2">{detail.newValueDisplay ?? detail.newValue ?? '—'}</td></tr>)}</tbody></table></div></>}
|
|
92
|
+
</> : <p role="alert">Could not load this archived message.</p>}
|
|
93
|
+
</section>
|
|
94
|
+
</div>}
|
|
95
|
+
</main>;
|
|
96
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"solidRoutes.d.ts","sourceRoot":"","sources":["../../src/routes/solidRoutes.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"solidRoutes.d.ts","sourceRoot":"","sources":["../../src/routes/solidRoutes.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAwCpD,OAAO,KAAK,EAAE,kBAAkB,EAAiB,MAAM,SAAS,CAAC;AAQjE,wBAAgB,cAAc,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,EAAE,CA6G9E"}
|
|
@@ -32,6 +32,7 @@ import { AgentToolRegistryEditorPage } from "./pages/admin/core/AgentToolRegistr
|
|
|
32
32
|
import { AgentRegistryEditorPage } from "./pages/admin/core/AgentRegistryEditorPage";
|
|
33
33
|
import { WorkflowExecutionDetailPage } from "./pages/admin/core/WorkflowExecutionDetailPage";
|
|
34
34
|
import { MediaUploadPage } from "./pages/admin/core/MediaUploadPage";
|
|
35
|
+
import { ArchivedChatterMessagesPage } from "./pages/admin/core/ArchivedChatterMessagesPage";
|
|
35
36
|
import { LoginPage } from "./pages/auth/LoginPage";
|
|
36
37
|
import { RegisterPage } from "./pages/auth/RegisterPage";
|
|
37
38
|
import { ForgotPasswordPage } from "./pages/auth/ForgotPasswordPage";
|
|
@@ -94,6 +95,7 @@ export function getSolidRoutes(options) {
|
|
|
94
95
|
{ path: "/admin/core/:moduleName/dashboard/:dashboardName", element: pick("dashboard", _jsx(DashboardPage, {})), handle: { title: "Dashboard", manageDocumentMeta: true } },
|
|
95
96
|
{ path: "/admin/core/:moduleName/:modelName/form/:id", element: pick("form", _jsx(FormPage, {})), handle: { title: "Form", manageDocumentMeta: true } },
|
|
96
97
|
{ path: "/admin/core/solid-core/media/upload", element: _jsx(MediaUploadPage, {}), handle: { title: "Upload Media", manageDocumentMeta: true } },
|
|
98
|
+
{ path: "/admin/core/solid-core/chatter/archived", element: _jsx(ArchivedChatterMessagesPage, {}), handle: { title: "Archived Messages", manageDocumentMeta: true } },
|
|
97
99
|
{ path: "/admin/core/solid-core/workflow-definition/editor/:id", element: _jsx(WorkflowDefinitionEditorPage, {}), handle: { title: "Workflow Definition Editor", manageDocumentMeta: true } },
|
|
98
100
|
{ path: "/admin/core/solid-core/agent-skill-registry/editor/:id", element: _jsx(AgentSkillRegistryEditorPage, {}), handle: { title: "Agent Skill Registry Editor", manageDocumentMeta: true } },
|
|
99
101
|
{ path: "/admin/core/solid-core/agent-tool-registry/editor/:id", element: _jsx(AgentToolRegistryEditorPage, {}), handle: { title: "Agent Tool Registry Editor", manageDocumentMeta: true } },
|