@peers-app/peers-ui 0.0.14
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/.github/README.md +52 -0
- package/.github/workflows/publish.yml +45 -0
- package/babel.config.js +7 -0
- package/dist/app.d.ts +9 -0
- package/dist/app.js +54 -0
- package/dist/command-palette/command-palette-ui.d.ts +2 -0
- package/dist/command-palette/command-palette-ui.js +192 -0
- package/dist/command-palette/command-palette.d.ts +23 -0
- package/dist/command-palette/command-palette.js +371 -0
- package/dist/components/checkbox.d.ts +7 -0
- package/dist/components/checkbox.js +20 -0
- package/dist/components/group-switcher.d.ts +6 -0
- package/dist/components/group-switcher.js +301 -0
- package/dist/components/input-date.d.ts +7 -0
- package/dist/components/input-date.js +19 -0
- package/dist/components/input-datetime.d.ts +7 -0
- package/dist/components/input-datetime.js +35 -0
- package/dist/components/input-number.d.ts +9 -0
- package/dist/components/input-number.js +87 -0
- package/dist/components/input.d.ts +7 -0
- package/dist/components/input.js +20 -0
- package/dist/components/io-schema-values.d.ts +15 -0
- package/dist/components/io-schema-values.js +105 -0
- package/dist/components/io-schema.d.ts +13 -0
- package/dist/components/io-schema.js +163 -0
- package/dist/components/lazy-list.d.ts +13 -0
- package/dist/components/lazy-list.js +91 -0
- package/dist/components/lazy-sortable-list.d.ts +29 -0
- package/dist/components/lazy-sortable-list.js +12 -0
- package/dist/components/left-bar.d.ts +3 -0
- package/dist/components/left-bar.js +130 -0
- package/dist/components/list-screen.d.ts +16 -0
- package/dist/components/list-screen.js +100 -0
- package/dist/components/loading-indicator.d.ts +2 -0
- package/dist/components/loading-indicator.js +12 -0
- package/dist/components/main-content-container.d.ts +2 -0
- package/dist/components/main-content-container.js +90 -0
- package/dist/components/markdown-editor/autolink-plugin.d.ts +2 -0
- package/dist/components/markdown-editor/autolink-plugin.js +29 -0
- package/dist/components/markdown-editor/editor-inline.d.ts +3 -0
- package/dist/components/markdown-editor/editor-inline.js +13 -0
- package/dist/components/markdown-editor/editor.d.ts +18 -0
- package/dist/components/markdown-editor/editor.js +143 -0
- package/dist/components/markdown-editor/markdown-plugin.d.ts +9 -0
- package/dist/components/markdown-editor/markdown-plugin.js +194 -0
- package/dist/components/markdown-editor/mention-node.d.ts +21 -0
- package/dist/components/markdown-editor/mention-node.js +160 -0
- package/dist/components/markdown-editor/mentions-plugin.d.ts +7 -0
- package/dist/components/markdown-editor/mentions-plugin.js +268 -0
- package/dist/components/markdown-editor/theme.d.ts +46 -0
- package/dist/components/markdown-editor/theme.js +48 -0
- package/dist/components/markdown-editor/toolbar.d.ts +10 -0
- package/dist/components/markdown-editor/toolbar.js +112 -0
- package/dist/components/markdown-with-mentions.d.ts +4 -0
- package/dist/components/markdown-with-mentions.js +140 -0
- package/dist/components/message-logs/message-logs.d.ts +6 -0
- package/dist/components/message-logs/message-logs.js +307 -0
- package/dist/components/messages/avatar.d.ts +10 -0
- package/dist/components/messages/avatar.js +65 -0
- package/dist/components/messages/channel-message-list.d.ts +14 -0
- package/dist/components/messages/channel-message-list.js +158 -0
- package/dist/components/messages/channel-view.d.ts +6 -0
- package/dist/components/messages/channel-view.js +82 -0
- package/dist/components/messages/message-compose.d.ts +11 -0
- package/dist/components/messages/message-compose.js +152 -0
- package/dist/components/messages/message-display.d.ts +10 -0
- package/dist/components/messages/message-display.js +152 -0
- package/dist/components/messages/thread-message-list.d.ts +11 -0
- package/dist/components/messages/thread-message-list.js +122 -0
- package/dist/components/messages/thread-view.d.ts +6 -0
- package/dist/components/messages/thread-view.js +174 -0
- package/dist/components/off-canvas.d.ts +13 -0
- package/dist/components/off-canvas.js +89 -0
- package/dist/components/router.d.ts +6 -0
- package/dist/components/router.js +240 -0
- package/dist/components/save-button.d.ts +13 -0
- package/dist/components/save-button.js +75 -0
- package/dist/components/sortable-list.d.ts +36 -0
- package/dist/components/sortable-list.js +77 -0
- package/dist/components/tabs.d.ts +11 -0
- package/dist/components/tabs.js +69 -0
- package/dist/components/text-list-editor.tsx/text-list-editor.d.ts +6 -0
- package/dist/components/text-list-editor.tsx/text-list-editor.js +13 -0
- package/dist/components/tooltip.d.ts +11 -0
- package/dist/components/tooltip.js +20 -0
- package/dist/components/top-bar.d.ts +2 -0
- package/dist/components/top-bar.js +51 -0
- package/dist/components/typeahead/mentions-plugin.d.ts +7 -0
- package/dist/components/typeahead/mentions-plugin.js +203 -0
- package/dist/components/typeahead/typeahead-editor.d.ts +15 -0
- package/dist/components/typeahead/typeahead-editor.js +134 -0
- package/dist/components/typeahead/typeahead.d.ts +12 -0
- package/dist/components/typeahead/typeahead.js +94 -0
- package/dist/components/typeahead.d.ts +22 -0
- package/dist/components/typeahead.js +270 -0
- package/dist/globals.d.ts +29 -0
- package/dist/globals.js +148 -0
- package/dist/hooks.d.ts +34 -0
- package/dist/hooks.js +137 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +20 -0
- package/dist/layout-vars.d.ts +6 -0
- package/dist/layout-vars.js +10 -0
- package/dist/mention-configs.d.ts +18 -0
- package/dist/mention-configs.js +149 -0
- package/dist/screens/assistants/assistant-config.d.ts +5 -0
- package/dist/screens/assistants/assistant-config.js +52 -0
- package/dist/screens/assistants/assistant-details.d.ts +4 -0
- package/dist/screens/assistants/assistant-details.js +85 -0
- package/dist/screens/assistants/assistant-info.d.ts +6 -0
- package/dist/screens/assistants/assistant-info.js +28 -0
- package/dist/screens/assistants/assistant-list.d.ts +2 -0
- package/dist/screens/assistants/assistant-list.js +114 -0
- package/dist/screens/assistants/assistant-tools.d.ts +5 -0
- package/dist/screens/assistants/assistant-tools.js +38 -0
- package/dist/screens/contacts/contact-details.d.ts +6 -0
- package/dist/screens/contacts/contact-details.js +100 -0
- package/dist/screens/contacts/contact-list.d.ts +2 -0
- package/dist/screens/contacts/contact-list.js +213 -0
- package/dist/screens/contacts/index.d.ts +4 -0
- package/dist/screens/contacts/index.js +21 -0
- package/dist/screens/events/cron.d.ts +3 -0
- package/dist/screens/events/cron.js +77 -0
- package/dist/screens/events/event-details.d.ts +6 -0
- package/dist/screens/events/event-details.js +112 -0
- package/dist/screens/events/event-handlers.d.ts +7 -0
- package/dist/screens/events/event-handlers.js +84 -0
- package/dist/screens/events/event-info.d.ts +5 -0
- package/dist/screens/events/event-info.js +19 -0
- package/dist/screens/events/event-list.d.ts +2 -0
- package/dist/screens/events/event-list.js +107 -0
- package/dist/screens/events/event-schedule.d.ts +5 -0
- package/dist/screens/events/event-schedule.js +124 -0
- package/dist/screens/groups/group-details.d.ts +6 -0
- package/dist/screens/groups/group-details.js +218 -0
- package/dist/screens/groups/group-list.d.ts +2 -0
- package/dist/screens/groups/group-list.js +275 -0
- package/dist/screens/groups/group-members.d.ts +8 -0
- package/dist/screens/groups/group-members.js +315 -0
- package/dist/screens/groups/index.d.ts +6 -0
- package/dist/screens/groups/index.js +23 -0
- package/dist/screens/knowledge/knowledge-frame-details.bk.d.ts +6 -0
- package/dist/screens/knowledge/knowledge-frame-details.bk.js +84 -0
- package/dist/screens/knowledge/knowledge-frame-details.d.ts +8 -0
- package/dist/screens/knowledge/knowledge-frame-details.js +143 -0
- package/dist/screens/knowledge/knowledge-frame-list.d.ts +2 -0
- package/dist/screens/knowledge/knowledge-frame-list.js +45 -0
- package/dist/screens/knowledge/knowledge-value-details.d.ts +6 -0
- package/dist/screens/knowledge/knowledge-value-details.js +150 -0
- package/dist/screens/knowledge/knowledge-value-list-item.d.ts +5 -0
- package/dist/screens/knowledge/knowledge-value-list-item.js +39 -0
- package/dist/screens/knowledge/knowledge-value-list.d.ts +3 -0
- package/dist/screens/knowledge/knowledge-value-list.js +123 -0
- package/dist/screens/packages/package-details.d.ts +6 -0
- package/dist/screens/packages/package-details.js +82 -0
- package/dist/screens/packages/package-info.d.ts +5 -0
- package/dist/screens/packages/package-info.js +42 -0
- package/dist/screens/packages/package-list.d.ts +2 -0
- package/dist/screens/packages/package-list.js +182 -0
- package/dist/screens/packages/package-new-local.d.ts +2 -0
- package/dist/screens/packages/package-new-local.js +82 -0
- package/dist/screens/peer-types/peer-type-details.d.ts +10 -0
- package/dist/screens/peer-types/peer-type-details.js +126 -0
- package/dist/screens/peer-types/peer-type-list.d.ts +2 -0
- package/dist/screens/peer-types/peer-type-list.js +57 -0
- package/dist/screens/predicates/predicate-details.d.ts +6 -0
- package/dist/screens/predicates/predicate-details.js +103 -0
- package/dist/screens/predicates/predicate-list.d.ts +2 -0
- package/dist/screens/predicates/predicate-list.js +46 -0
- package/dist/screens/profile.d.ts +2 -0
- package/dist/screens/profile.js +66 -0
- package/dist/screens/search/global-search.d.ts +2 -0
- package/dist/screens/search/global-search.js +186 -0
- package/dist/screens/settings/color-mode-dropdown.d.ts +6 -0
- package/dist/screens/settings/color-mode-dropdown.js +63 -0
- package/dist/screens/settings/settings-page.d.ts +2 -0
- package/dist/screens/settings/settings-page.js +49 -0
- package/dist/screens/setup-user.d.ts +2 -0
- package/dist/screens/setup-user.js +270 -0
- package/dist/screens/tools/tool-code.d.ts +5 -0
- package/dist/screens/tools/tool-code.js +32 -0
- package/dist/screens/tools/tool-details.d.ts +6 -0
- package/dist/screens/tools/tool-details.js +68 -0
- package/dist/screens/tools/tool-info.d.ts +5 -0
- package/dist/screens/tools/tool-info.js +74 -0
- package/dist/screens/tools/tool-list.d.ts +2 -0
- package/dist/screens/tools/tool-list.js +123 -0
- package/dist/screens/tools/tool-schema.d.ts +5 -0
- package/dist/screens/tools/tool-schema.js +30 -0
- package/dist/screens/tools/tool-test-details.d.ts +4 -0
- package/dist/screens/tools/tool-test-details.js +54 -0
- package/dist/screens/tools/tool-test-list.d.ts +4 -0
- package/dist/screens/tools/tool-test-list.js +82 -0
- package/dist/screens/variables/variable-details.d.ts +6 -0
- package/dist/screens/variables/variable-details.js +140 -0
- package/dist/screens/variables/variable-list.d.ts +2 -0
- package/dist/screens/variables/variable-list.js +58 -0
- package/dist/screens/workflows/workflow-details.d.ts +6 -0
- package/dist/screens/workflows/workflow-details.js +122 -0
- package/dist/screens/workflows/workflow-info.d.ts +5 -0
- package/dist/screens/workflows/workflow-info.js +18 -0
- package/dist/screens/workflows/workflow-instructions.d.ts +5 -0
- package/dist/screens/workflows/workflow-instructions.js +118 -0
- package/dist/screens/workflows/workflow-list.d.ts +2 -0
- package/dist/screens/workflows/workflow-list.js +109 -0
- package/dist/screens/workflows/workflow-subscriptions.d.ts +6 -0
- package/dist/screens/workflows/workflow-subscriptions.js +81 -0
- package/dist/setupTests.d.ts +1 -0
- package/dist/setupTests.js +31 -0
- package/dist/system-apps/assistants.app.d.ts +2 -0
- package/dist/system-apps/assistants.app.js +8 -0
- package/dist/system-apps/contacts.app.d.ts +2 -0
- package/dist/system-apps/contacts.app.js +9 -0
- package/dist/system-apps/events.app.d.ts +2 -0
- package/dist/system-apps/events.app.js +8 -0
- package/dist/system-apps/groups.app.d.ts +2 -0
- package/dist/system-apps/groups.app.js +9 -0
- package/dist/system-apps/index.d.ts +19 -0
- package/dist/system-apps/index.js +90 -0
- package/dist/system-apps/knowledge-frames.app.d.ts +2 -0
- package/dist/system-apps/knowledge-frames.app.js +9 -0
- package/dist/system-apps/knowledge-values.app.d.ts +2 -0
- package/dist/system-apps/knowledge-values.app.js +9 -0
- package/dist/system-apps/packages.app.d.ts +2 -0
- package/dist/system-apps/packages.app.js +8 -0
- package/dist/system-apps/predicates.app.d.ts +2 -0
- package/dist/system-apps/predicates.app.js +8 -0
- package/dist/system-apps/profile.app.d.ts +2 -0
- package/dist/system-apps/profile.app.js +8 -0
- package/dist/system-apps/search.app.d.ts +2 -0
- package/dist/system-apps/search.app.js +9 -0
- package/dist/system-apps/settings.app.d.ts +2 -0
- package/dist/system-apps/settings.app.js +8 -0
- package/dist/system-apps/threads.app.d.ts +2 -0
- package/dist/system-apps/threads.app.js +8 -0
- package/dist/system-apps/tools.app.d.ts +2 -0
- package/dist/system-apps/tools.app.js +8 -0
- package/dist/system-apps/types.app.d.ts +2 -0
- package/dist/system-apps/types.app.js +8 -0
- package/dist/system-apps/variables.app.d.ts +2 -0
- package/dist/system-apps/variables.app.js +8 -0
- package/dist/system-apps/workflows.app.d.ts +2 -0
- package/dist/system-apps/workflows.app.js +8 -0
- package/dist/tabs-layout/tabs-layout.d.ts +5 -0
- package/dist/tabs-layout/tabs-layout.js +374 -0
- package/dist/tabs-layout/tabs-state.d.ts +26 -0
- package/dist/tabs-layout/tabs-state.js +239 -0
- package/dist/three-bar-layout/left-bar-content.d.ts +7 -0
- package/dist/three-bar-layout/left-bar-content.js +151 -0
- package/dist/three-bar-layout/right-bar-content.d.ts +2 -0
- package/dist/three-bar-layout/right-bar-content.js +64 -0
- package/dist/three-bar-layout/three-bar-layout.d.ts +5 -0
- package/dist/three-bar-layout/three-bar-layout.js +218 -0
- package/dist/ui-defaults/index.d.ts +2 -0
- package/dist/ui-defaults/index.js +4 -0
- package/dist/ui-defaults/list-screen.d.ts +6 -0
- package/dist/ui-defaults/list-screen.js +74 -0
- package/dist/ui-defaults/notes-editor.d.ts +7 -0
- package/dist/ui-defaults/notes-editor.js +41 -0
- package/dist/ui-router/routes-loader.d.ts +25 -0
- package/dist/ui-router/routes-loader.js +97 -0
- package/dist/ui-router/ui-loader.d.ts +18 -0
- package/dist/ui-router/ui-loader.js +481 -0
- package/dist/utils.d.ts +9 -0
- package/dist/utils.js +250 -0
- package/docs/conversation-tab.md +201 -0
- package/docs/getting-started.md +284 -0
- package/docs/knowledge.md +187 -0
- package/docs/tabs-ui.md +696 -0
- package/docs/user-contacts-ui.md +384 -0
- package/jest.config.js +25 -0
- package/package.json +109 -0
- package/src/app.tsx +59 -0
- package/src/command-palette/command-palette-ui.tsx +264 -0
- package/src/command-palette/command-palette.ts +364 -0
- package/src/components/checkbox.tsx +22 -0
- package/src/components/group-switcher.tsx +469 -0
- package/src/components/input-date.tsx +28 -0
- package/src/components/input-datetime.tsx +41 -0
- package/src/components/input-number.tsx +67 -0
- package/src/components/input.tsx +22 -0
- package/src/components/io-schema-values.tsx +122 -0
- package/src/components/io-schema.tsx +234 -0
- package/src/components/lazy-list.tsx +98 -0
- package/src/components/lazy-sortable-list.tsx +51 -0
- package/src/components/left-bar.tsx +264 -0
- package/src/components/list-screen.tsx +105 -0
- package/src/components/loading-indicator.tsx +9 -0
- package/src/components/main-content-container.tsx +76 -0
- package/src/components/markdown-editor/autolink-plugin.tsx +36 -0
- package/src/components/markdown-editor/editor-inline.tsx +10 -0
- package/src/components/markdown-editor/editor.tsx +152 -0
- package/src/components/markdown-editor/markdown-plugin.tsx +224 -0
- package/src/components/markdown-editor/mention-node.ts +199 -0
- package/src/components/markdown-editor/mentions-plugin.tsx +356 -0
- package/src/components/markdown-editor/theme.ts +47 -0
- package/src/components/markdown-editor/toolbar.tsx +263 -0
- package/src/components/markdown-with-mentions.tsx +183 -0
- package/src/components/message-logs/message-logs.tsx +406 -0
- package/src/components/messages/avatar.tsx +95 -0
- package/src/components/messages/channel-message-list.tsx +177 -0
- package/src/components/messages/channel-view.tsx +74 -0
- package/src/components/messages/message-compose.tsx +162 -0
- package/src/components/messages/message-display.tsx +217 -0
- package/src/components/messages/thread-message-list.tsx +126 -0
- package/src/components/messages/thread-view.tsx +214 -0
- package/src/components/off-canvas.tsx +83 -0
- package/src/components/router.tsx +224 -0
- package/src/components/save-button.tsx +109 -0
- package/src/components/sortable-list.tsx +102 -0
- package/src/components/tabs.tsx +70 -0
- package/src/components/text-list-editor.tsx/text-list-editor.tsx +13 -0
- package/src/components/tooltip.tsx +50 -0
- package/src/components/top-bar.tsx +119 -0
- package/src/components/typeahead/mentions-plugin.tsx +265 -0
- package/src/components/typeahead/typeahead-editor.tsx +140 -0
- package/src/components/typeahead/typeahead.tsx +77 -0
- package/src/components/typeahead.tsx +359 -0
- package/src/globals.tsx +162 -0
- package/src/hooks.ts +144 -0
- package/src/index.tsx +8 -0
- package/src/layout-vars.ts +8 -0
- package/src/mention-configs.ts +166 -0
- package/src/screens/assistants/assistant-config.tsx +80 -0
- package/src/screens/assistants/assistant-details.tsx +77 -0
- package/src/screens/assistants/assistant-info.tsx +45 -0
- package/src/screens/assistants/assistant-list.tsx +115 -0
- package/src/screens/assistants/assistant-tools.tsx +61 -0
- package/src/screens/contacts/contact-details.tsx +175 -0
- package/src/screens/contacts/contact-list.tsx +251 -0
- package/src/screens/contacts/index.ts +6 -0
- package/src/screens/events/cron.ts +74 -0
- package/src/screens/events/event-details.tsx +117 -0
- package/src/screens/events/event-handlers.tsx +61 -0
- package/src/screens/events/event-info.tsx +29 -0
- package/src/screens/events/event-list.tsx +104 -0
- package/src/screens/events/event-schedule.tsx +130 -0
- package/src/screens/groups/group-details.tsx +306 -0
- package/src/screens/groups/group-list.tsx +366 -0
- package/src/screens/groups/group-members.tsx +455 -0
- package/src/screens/groups/index.ts +9 -0
- package/src/screens/knowledge/knowledge-frame-details.bk.tsx +160 -0
- package/src/screens/knowledge/knowledge-frame-details.tsx +176 -0
- package/src/screens/knowledge/knowledge-frame-list.tsx +49 -0
- package/src/screens/knowledge/knowledge-value-details.tsx +181 -0
- package/src/screens/knowledge/knowledge-value-list-item.tsx +48 -0
- package/src/screens/knowledge/knowledge-value-list.tsx +131 -0
- package/src/screens/packages/package-details.tsx +117 -0
- package/src/screens/packages/package-info.tsx +83 -0
- package/src/screens/packages/package-list.tsx +191 -0
- package/src/screens/packages/package-new-local.tsx +93 -0
- package/src/screens/peer-types/peer-type-details.tsx +162 -0
- package/src/screens/peer-types/peer-type-list.tsx +74 -0
- package/src/screens/predicates/predicate-details.tsx +125 -0
- package/src/screens/predicates/predicate-list.tsx +50 -0
- package/src/screens/profile.tsx +68 -0
- package/src/screens/search/global-search.tsx +274 -0
- package/src/screens/settings/color-mode-dropdown.tsx +57 -0
- package/src/screens/settings/settings-page.tsx +76 -0
- package/src/screens/setup-user.tsx +367 -0
- package/src/screens/tools/tool-code.tsx +35 -0
- package/src/screens/tools/tool-details.tsx +101 -0
- package/src/screens/tools/tool-info.tsx +60 -0
- package/src/screens/tools/tool-list.tsx +121 -0
- package/src/screens/tools/tool-schema.tsx +42 -0
- package/src/screens/tools/tool-test-details.tsx +100 -0
- package/src/screens/tools/tool-test-list.tsx +74 -0
- package/src/screens/variables/variable-details.tsx +183 -0
- package/src/screens/variables/variable-list.tsx +74 -0
- package/src/screens/workflows/workflow-details.tsx +130 -0
- package/src/screens/workflows/workflow-info.tsx +29 -0
- package/src/screens/workflows/workflow-instructions.tsx +127 -0
- package/src/screens/workflows/workflow-list.tsx +107 -0
- package/src/screens/workflows/workflow-subscriptions.tsx +58 -0
- package/src/setupTests.ts +32 -0
- package/src/system-apps/assistants.app.ts +7 -0
- package/src/system-apps/contacts.app.ts +8 -0
- package/src/system-apps/events.app.ts +7 -0
- package/src/system-apps/groups.app.ts +8 -0
- package/src/system-apps/index.ts +79 -0
- package/src/system-apps/knowledge-frames.app.ts +8 -0
- package/src/system-apps/knowledge-values.app.ts +8 -0
- package/src/system-apps/packages.app.ts +7 -0
- package/src/system-apps/predicates.app.ts +7 -0
- package/src/system-apps/profile.app.ts +7 -0
- package/src/system-apps/search.app.ts +8 -0
- package/src/system-apps/settings.app.ts +7 -0
- package/src/system-apps/threads.app.ts +7 -0
- package/src/system-apps/tools.app.ts +7 -0
- package/src/system-apps/types.app.ts +7 -0
- package/src/system-apps/variables.app.ts +7 -0
- package/src/system-apps/workflows.app.ts +7 -0
- package/src/tabs-layout/tabs-layout.tsx +672 -0
- package/src/tabs-layout/tabs-state.ts +269 -0
- package/src/three-bar-layout/left-bar-content.tsx +202 -0
- package/src/three-bar-layout/right-bar-content.tsx +67 -0
- package/src/three-bar-layout/three-bar-layout.tsx +297 -0
- package/src/ui-defaults/index.ts +3 -0
- package/src/ui-defaults/list-screen.tsx +92 -0
- package/src/ui-defaults/notes-editor.tsx +51 -0
- package/src/ui-router/routes-loader.ts +98 -0
- package/src/ui-router/ui-loader.tsx +497 -0
- package/src/utils.ts +266 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
import { GroupMembers, getUserContext, IUserWithSource, usersCursor, getUserById, Users, TrustLevel, GroupMemberRole, getUserRole, getRoleLabel, Groups, UserContext } from "@peers-app/peers-sdk";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { LoadingIndicator } from "../../components/loading-indicator";
|
|
4
|
+
import { Typeahead, TypeaheadItem } from "../../components/typeahead";
|
|
5
|
+
import { usePromise } from "../../hooks";
|
|
6
|
+
|
|
7
|
+
interface GroupMembersUIProps {
|
|
8
|
+
groupId: string;
|
|
9
|
+
userContext: UserContext;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const GroupMembersUI = (props: GroupMembersUIProps) => {
|
|
13
|
+
const { groupId, userContext } = props;
|
|
14
|
+
|
|
15
|
+
// Get the group's data context and tables
|
|
16
|
+
const groupDataContext = userContext.getDataContext(groupId);
|
|
17
|
+
const groupMembersTable = GroupMembers(groupDataContext);
|
|
18
|
+
const groupUsersTable = Users(groupDataContext);
|
|
19
|
+
|
|
20
|
+
// State for refreshing the component
|
|
21
|
+
const [refreshKey, setRefreshKey] = React.useState(0);
|
|
22
|
+
|
|
23
|
+
// Load group members with user details and check current user permissions
|
|
24
|
+
const membersData = usePromise(async () => {
|
|
25
|
+
const members = await groupMembersTable.list({ deleted: { $ne: true } });
|
|
26
|
+
|
|
27
|
+
// Get user details for each member using the group context
|
|
28
|
+
const membersWithUsers = await Promise.all(
|
|
29
|
+
members.map(async (member) => {
|
|
30
|
+
const user = await getUserById(member.userId, {
|
|
31
|
+
currentDataContext: groupDataContext
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// If user found from external source, save to current group
|
|
35
|
+
if (user && user.source !== 'currentDataContext') {
|
|
36
|
+
try {
|
|
37
|
+
const newGroupUser = await groupUsersTable.initRecord({
|
|
38
|
+
userId: user.userId,
|
|
39
|
+
name: user.name,
|
|
40
|
+
publicKey: user.publicKey || '',
|
|
41
|
+
publicBoxKey: user.publicBoxKey || '',
|
|
42
|
+
trustLevel: TrustLevel.NewUser
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
await groupUsersTable.save(newGroupUser);
|
|
46
|
+
|
|
47
|
+
// Update user reference to reflect it's now in current group
|
|
48
|
+
user.trustLevel = TrustLevel.NewUser;
|
|
49
|
+
user.source = 'currentDataContext';
|
|
50
|
+
} catch (saveErr) {
|
|
51
|
+
console.error('Failed to save user to group context:', saveErr);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
member,
|
|
57
|
+
user: user || null
|
|
58
|
+
};
|
|
59
|
+
})
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
return membersWithUsers;
|
|
63
|
+
}, [], [groupId, refreshKey]);
|
|
64
|
+
|
|
65
|
+
// Check if current user has admin privileges in this group
|
|
66
|
+
const userPermissions = usePromise(async () => {
|
|
67
|
+
const currentUserContext = await getUserContext();
|
|
68
|
+
const currentUserId = currentUserContext.userId();
|
|
69
|
+
const userRole = await getUserRole(groupId, currentUserId);
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
isMember: !!userRole,
|
|
73
|
+
canEdit: userRole >= GroupMemberRole.Admin,
|
|
74
|
+
userRole: userRole,
|
|
75
|
+
currentUserId: currentUserId
|
|
76
|
+
};
|
|
77
|
+
}, undefined, [groupId]);
|
|
78
|
+
|
|
79
|
+
// Load group and founder information
|
|
80
|
+
const founderData = usePromise(async () => {
|
|
81
|
+
const groupsTable = Groups(groupDataContext);
|
|
82
|
+
const group = await groupsTable.get(groupId) || await Groups(userContext.userDataContext).get(groupId);
|
|
83
|
+
|
|
84
|
+
if (!group) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Try to get founder user details
|
|
89
|
+
const founderUser = await getUserById(group.founderUserId, {
|
|
90
|
+
currentDataContext: groupDataContext
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
group,
|
|
95
|
+
founderUser,
|
|
96
|
+
founderUserId: group.founderUserId
|
|
97
|
+
};
|
|
98
|
+
}, undefined, [groupId, refreshKey]);
|
|
99
|
+
|
|
100
|
+
const [newMemberRole, setNewMemberRole] = React.useState<GroupMemberRole>(GroupMemberRole.Reader);
|
|
101
|
+
const [addingMember, setAddingMember] = React.useState(false);
|
|
102
|
+
const [selectedContacts, setSelectedContacts] = React.useState<IUserWithSource[]>([]);
|
|
103
|
+
|
|
104
|
+
// Search function for typeahead
|
|
105
|
+
const searchContacts = async (query: string): Promise<(IUserWithSource & TypeaheadItem)[]> => {
|
|
106
|
+
try {
|
|
107
|
+
const cursor = await usersCursor({ name: { $matchWords: query } });
|
|
108
|
+
const results: IUserWithSource[] = [];
|
|
109
|
+
|
|
110
|
+
// Get first 10 results
|
|
111
|
+
for await (const contact of cursor) {
|
|
112
|
+
results.push(contact);
|
|
113
|
+
if (results.length >= 10) break;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Filter out users who are already members
|
|
117
|
+
const currentMembers = membersData?.map(m => m.member.userId) || [];
|
|
118
|
+
const filteredResults = results.filter(contact =>
|
|
119
|
+
!currentMembers.includes(contact.userId)
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
return filteredResults.map(contact => ({
|
|
123
|
+
...contact,
|
|
124
|
+
id: contact.userId
|
|
125
|
+
}));
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('Error searching contacts:', error);
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// Render function for typeahead results
|
|
133
|
+
const renderContactItem = (contact: IUserWithSource & TypeaheadItem, isSelected: boolean) => (
|
|
134
|
+
<div className="d-flex align-items-center">
|
|
135
|
+
<i className="bi-person-circle me-2" style={{ fontSize: '20px' }} />
|
|
136
|
+
<div className="flex-grow-1">
|
|
137
|
+
<div className="fw-semibold">{contact.name}</div>
|
|
138
|
+
<small className="text-muted">{contact.userId}</small>
|
|
139
|
+
</div>
|
|
140
|
+
<div>
|
|
141
|
+
<small className="text-info">
|
|
142
|
+
<i className={`bi-${getSourceIcon(contact.source)} me-1`} />
|
|
143
|
+
{getSourceLabel(contact.source)}
|
|
144
|
+
</small>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
// Helper functions for contact sources
|
|
150
|
+
const getSourceLabel = (source: string) => {
|
|
151
|
+
switch (source) {
|
|
152
|
+
case 'userDataContext': return 'Personal';
|
|
153
|
+
case 'currentDataContext': return 'Current';
|
|
154
|
+
case 'otherDataContexts': return 'Groups';
|
|
155
|
+
default: return source;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const getSourceIcon = (source: string) => {
|
|
160
|
+
switch (source) {
|
|
161
|
+
case 'userDataContext': return 'person-fill';
|
|
162
|
+
case 'currentDataContext': return 'house-fill';
|
|
163
|
+
case 'otherDataContexts': return 'people-fill';
|
|
164
|
+
default: return 'question-circle';
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const addMember = async () => {
|
|
169
|
+
if (selectedContacts.length === 0) return;
|
|
170
|
+
|
|
171
|
+
setAddingMember(true);
|
|
172
|
+
try {
|
|
173
|
+
// Add all selected contacts with the chosen role
|
|
174
|
+
for (const contact of selectedContacts) {
|
|
175
|
+
let member = await groupMembersTable.findOne({ userId: contact.userId, groupId });
|
|
176
|
+
if (member) {
|
|
177
|
+
member.role = newMemberRole;
|
|
178
|
+
member.deleted = false;
|
|
179
|
+
} else {
|
|
180
|
+
member = await groupMembersTable.initRecord({
|
|
181
|
+
groupId: groupId,
|
|
182
|
+
userId: contact.userId,
|
|
183
|
+
role: newMemberRole
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
await groupMembersTable.save(member);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Reset form
|
|
190
|
+
setSelectedContacts([]);
|
|
191
|
+
setNewMemberRole(GroupMemberRole.Reader);
|
|
192
|
+
|
|
193
|
+
// Refresh the members list
|
|
194
|
+
setRefreshKey(prev => prev + 1);
|
|
195
|
+
} catch (err) {
|
|
196
|
+
console.error('Failed to add member:', err);
|
|
197
|
+
alert('Failed to add member. They may already be in the group.');
|
|
198
|
+
} finally {
|
|
199
|
+
setAddingMember(false);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// Render function for contact badges
|
|
204
|
+
const renderContactBadge = (contact: IUserWithSource) => (
|
|
205
|
+
<span>{contact.name}</span>
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
const updateRole = async (memberId: string, newRole: GroupMemberRole) => {
|
|
209
|
+
try {
|
|
210
|
+
const member = await groupMembersTable.get(memberId);
|
|
211
|
+
if (member) {
|
|
212
|
+
member.role = newRole;
|
|
213
|
+
await groupMembersTable.save(member);
|
|
214
|
+
setRefreshKey(prev => prev + 1);
|
|
215
|
+
}
|
|
216
|
+
} catch (err) {
|
|
217
|
+
console.error('Failed to update role:', err);
|
|
218
|
+
alert('Failed to update member role.');
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const removeMember = async (memberId: string) => {
|
|
223
|
+
if (!confirm('Remove this member from the group?')) return;
|
|
224
|
+
|
|
225
|
+
try {
|
|
226
|
+
await groupMembersTable.delete(memberId);
|
|
227
|
+
setRefreshKey(prev => prev + 1);
|
|
228
|
+
} catch (err) {
|
|
229
|
+
console.error('Failed to remove member:', err);
|
|
230
|
+
alert('Failed to remove member.');
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
if (!membersData || !userPermissions || !founderData) {
|
|
235
|
+
return <LoadingIndicator />;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const { canEdit, userRole, currentUserId } = userPermissions;
|
|
239
|
+
|
|
240
|
+
return (
|
|
241
|
+
<div>
|
|
242
|
+
<div className="d-flex justify-content-between align-items-center mb-3">
|
|
243
|
+
<h6 className="mb-0">Group Members</h6>
|
|
244
|
+
<div className="d-flex align-items-center gap-2">
|
|
245
|
+
<div className={`alert alert-${userRole ? 'primary' : 'warning'} py-2 px-3 mb-0 d-flex align-items-center`}>
|
|
246
|
+
<i className={`bi ${userRole ? 'bi-person-badge' : 'bi-exclamation-triangle'} me-2`}></i>
|
|
247
|
+
<strong>Your role: {getRoleLabel(userRole)}</strong>
|
|
248
|
+
</div>
|
|
249
|
+
{/* Founder info - only show if current user is NOT the founder */}
|
|
250
|
+
{founderData && founderData.founderUserId !== currentUserId && (
|
|
251
|
+
<a
|
|
252
|
+
href={`#contacts/${founderData.founderUserId}`}
|
|
253
|
+
className="alert alert-warning py-2 px-3 mb-0 d-flex align-items-center text-decoration-none"
|
|
254
|
+
style={{ cursor: 'pointer' }}
|
|
255
|
+
>
|
|
256
|
+
<i className="bi bi-crown-fill me-2"></i>
|
|
257
|
+
<strong>Founder: {founderData.founderUser?.name || founderData.founderUserId}</strong>
|
|
258
|
+
</a>
|
|
259
|
+
)}
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
|
|
263
|
+
{/* Add New Member - Only for admins/owners */}
|
|
264
|
+
{canEdit && (
|
|
265
|
+
<div className="card mb-3">
|
|
266
|
+
<div className="card-body">
|
|
267
|
+
<h6 className="card-title">Add Member</h6>
|
|
268
|
+
<div className="row g-2">
|
|
269
|
+
<div className="col-md-6">
|
|
270
|
+
<Typeahead
|
|
271
|
+
placeholder="Search contacts to add..."
|
|
272
|
+
searchFn={searchContacts}
|
|
273
|
+
onSelectionChange={(items) => setSelectedContacts(items as IUserWithSource[])}
|
|
274
|
+
renderItem={renderContactItem}
|
|
275
|
+
renderBadge={renderContactBadge}
|
|
276
|
+
selectedItems={selectedContacts.map(contact => ({...contact, id: contact.userId}))}
|
|
277
|
+
multiSelect={true}
|
|
278
|
+
disabled={addingMember}
|
|
279
|
+
/>
|
|
280
|
+
</div>
|
|
281
|
+
<div className="col-md-3">
|
|
282
|
+
<select
|
|
283
|
+
className="form-select"
|
|
284
|
+
value={newMemberRole}
|
|
285
|
+
onChange={(e) => setNewMemberRole(Number(e.target.value) || 0 as GroupMemberRole)}
|
|
286
|
+
disabled={addingMember}
|
|
287
|
+
>
|
|
288
|
+
<option value={GroupMemberRole.None}>None</option>
|
|
289
|
+
<option value={GroupMemberRole.Reader}>Reader</option>
|
|
290
|
+
<option value={GroupMemberRole.Writer}>Writer</option>
|
|
291
|
+
<option value={GroupMemberRole.Admin}>Admin</option>
|
|
292
|
+
<option value={GroupMemberRole.Owner}>Owner</option>
|
|
293
|
+
</select>
|
|
294
|
+
</div>
|
|
295
|
+
<div className="col-md-3">
|
|
296
|
+
<button
|
|
297
|
+
className="btn btn-primary w-100"
|
|
298
|
+
onClick={addMember}
|
|
299
|
+
disabled={addingMember || selectedContacts.length === 0}
|
|
300
|
+
>
|
|
301
|
+
{addingMember ? 'Adding...' :
|
|
302
|
+
selectedContacts.length === 1 ? 'Add Member' :
|
|
303
|
+
selectedContacts.length > 1 ? `Add ${selectedContacts.length} Members` : 'Add'}
|
|
304
|
+
</button>
|
|
305
|
+
</div>
|
|
306
|
+
</div>
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
)}
|
|
310
|
+
|
|
311
|
+
{!canEdit && userRole && (
|
|
312
|
+
<div className="alert alert-info">
|
|
313
|
+
<i className="bi bi-info-circle me-2"></i>
|
|
314
|
+
You can view group members, but only admins and owners can manage membership.
|
|
315
|
+
</div>
|
|
316
|
+
)}
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
{/* Members List */}
|
|
320
|
+
{membersData.length === 0 ? (
|
|
321
|
+
<div className="alert alert-info">
|
|
322
|
+
No members in this group yet. Add the first member above.
|
|
323
|
+
</div>
|
|
324
|
+
) : (
|
|
325
|
+
<div className="list-group">
|
|
326
|
+
{membersData.map(({ member, user }) => (
|
|
327
|
+
<div key={member.groupMemberId} className="list-group-item">
|
|
328
|
+
<div className="d-flex justify-content-between align-items-center">
|
|
329
|
+
<div className="flex-grow-1">
|
|
330
|
+
<div className="d-flex align-items-center">
|
|
331
|
+
<i className="bi bi-person-fill me-2"></i>
|
|
332
|
+
<div>
|
|
333
|
+
<div className="d-flex align-items-center">
|
|
334
|
+
<strong>
|
|
335
|
+
{user?.name || member.userId}
|
|
336
|
+
{member.userId === currentUserId && ' (You)'}
|
|
337
|
+
</strong>
|
|
338
|
+
{user?.source === 'userDataContext' && (
|
|
339
|
+
<span className="badge bg-info ms-2" style={{ fontSize: '0.7rem' }}>
|
|
340
|
+
<i className="bi bi-person me-1"></i>
|
|
341
|
+
Personal
|
|
342
|
+
</span>
|
|
343
|
+
)}
|
|
344
|
+
{user?.source === 'otherDataContexts' && (
|
|
345
|
+
<span className="badge bg-secondary ms-2" style={{ fontSize: '0.7rem' }}>
|
|
346
|
+
<i className="bi bi-people me-1"></i>
|
|
347
|
+
Other Groups
|
|
348
|
+
</span>
|
|
349
|
+
)}
|
|
350
|
+
</div>
|
|
351
|
+
{user && user.userId !== user.name && (
|
|
352
|
+
<small className="text-muted d-block">{member.userId}</small>
|
|
353
|
+
)}
|
|
354
|
+
</div>
|
|
355
|
+
</div>
|
|
356
|
+
</div>
|
|
357
|
+
|
|
358
|
+
<div className="d-flex align-items-center">
|
|
359
|
+
{<TrustLevelBadge level={user?.trustLevel || TrustLevel.Unknown} />}
|
|
360
|
+
|
|
361
|
+
{/* View button - Always visible */}
|
|
362
|
+
<a href={`#contacts/${member.userId}`} className="btn btn-outline-primary btn-sm me-2">
|
|
363
|
+
<i className="bi-eye me-1" />
|
|
364
|
+
View
|
|
365
|
+
</a>
|
|
366
|
+
|
|
367
|
+
{canEdit ? (
|
|
368
|
+
<>
|
|
369
|
+
{/* Role Selector - Only for admins/owners */}
|
|
370
|
+
<select
|
|
371
|
+
className="form-select form-select-sm me-2"
|
|
372
|
+
style={{ width: '120px' }}
|
|
373
|
+
value={member.role}
|
|
374
|
+
onChange={(e) => updateRole(member.groupMemberId, Number(e.target.value) || 0 as GroupMemberRole)}
|
|
375
|
+
>
|
|
376
|
+
<option value={GroupMemberRole.None}>None</option>
|
|
377
|
+
<option value={GroupMemberRole.Reader}>Reader</option>
|
|
378
|
+
<option value={GroupMemberRole.Writer}>Writer</option>
|
|
379
|
+
<option value={GroupMemberRole.Admin}>Admin</option>
|
|
380
|
+
<option value={GroupMemberRole.Owner}>Owner</option>
|
|
381
|
+
</select>
|
|
382
|
+
|
|
383
|
+
{/* Remove Button - Only for admins/owners */}
|
|
384
|
+
<button
|
|
385
|
+
className="btn btn-outline-danger btn-sm"
|
|
386
|
+
onClick={() => removeMember(member.groupMemberId)}
|
|
387
|
+
title="Remove member"
|
|
388
|
+
>
|
|
389
|
+
<i className="bi bi-trash"></i>
|
|
390
|
+
</button>
|
|
391
|
+
</>
|
|
392
|
+
) : (
|
|
393
|
+
/* Read-only role display for non-admins */
|
|
394
|
+
<span className="badge bg-secondary text-capitalize">
|
|
395
|
+
{getRoleLabel(member.role)}
|
|
396
|
+
</span>
|
|
397
|
+
)}
|
|
398
|
+
</div>
|
|
399
|
+
</div>
|
|
400
|
+
</div>
|
|
401
|
+
))}
|
|
402
|
+
</div>
|
|
403
|
+
)}
|
|
404
|
+
|
|
405
|
+
{/* Role Descriptions */}
|
|
406
|
+
<div className="mt-4">
|
|
407
|
+
<small className="text-muted">
|
|
408
|
+
<strong>Roles:</strong><br/>
|
|
409
|
+
<strong>Reader:</strong> Can view group content<br/>
|
|
410
|
+
<strong>Writer:</strong> Can create and edit content<br/>
|
|
411
|
+
<strong>Admin:</strong> Can manage members and settings<br/>
|
|
412
|
+
<strong>Owner:</strong> Full control including group deletion
|
|
413
|
+
</small>
|
|
414
|
+
</div>
|
|
415
|
+
</div>
|
|
416
|
+
);
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
interface TrustLevelBadgeProps {
|
|
420
|
+
level: TrustLevel;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const TrustLevelBadge = ({ level }: TrustLevelBadgeProps) => {
|
|
424
|
+
// Define trust level configurations with their numeric values
|
|
425
|
+
const trustLevelConfigs = [
|
|
426
|
+
{ value: TrustLevel.Self, color: 'success', icon: 'bi-shield-fill-check', text: 'Self' },
|
|
427
|
+
{ value: TrustLevel.Trusted, color: 'success', icon: 'bi-shield-check', text: 'Trusted' },
|
|
428
|
+
{ value: TrustLevel.Known, color: 'info', icon: 'bi-shield-check', text: 'Known' },
|
|
429
|
+
{ value: TrustLevel.NewDevice, color: 'primary', icon: 'bi-shield-plus', text: 'New Device' },
|
|
430
|
+
{ value: TrustLevel.NewUser, color: 'primary', icon: 'bi-shield-plus', text: 'New User' },
|
|
431
|
+
{ value: TrustLevel.Unknown, color: 'warning', icon: 'bi-shield-exclamation', text: 'Unknown' },
|
|
432
|
+
{ value: TrustLevel.Untrusted, color: 'danger', icon: 'bi-shield-x', text: 'Untrusted' },
|
|
433
|
+
{ value: TrustLevel.Malicious, color: 'danger', icon: 'bi-shield-x', text: 'Malicious' }
|
|
434
|
+
];
|
|
435
|
+
|
|
436
|
+
// Sort by trust level value (ascending, so lowest first)
|
|
437
|
+
const sortedConfigs = trustLevelConfigs.sort((a, b) => a.value - b.value);
|
|
438
|
+
|
|
439
|
+
// Find the highest trust level that is at or below the current level
|
|
440
|
+
let config = { color: 'secondary', icon: 'bi-shield', text: 'Unknown' };
|
|
441
|
+
for (const trustConfig of sortedConfigs) {
|
|
442
|
+
if (level >= trustConfig.value) {
|
|
443
|
+
config = trustConfig;
|
|
444
|
+
} else {
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
return (
|
|
450
|
+
<span className={`badge bg-${config.color} d-flex align-items-center gap-1 me-2`} style={{ fontSize: '0.7rem' }}>
|
|
451
|
+
<i className={config.icon} />
|
|
452
|
+
{config.text}
|
|
453
|
+
</span>
|
|
454
|
+
);
|
|
455
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { observable } from "@peers-app/peers-sdk";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { IKnowledgeFrame, KnowledgeFrames, KnowledgeValues, IDoc } from "@peers-app/peers-sdk";
|
|
4
|
+
import { SaveButton } from "../../components/save-button";
|
|
5
|
+
import { TextListEditor } from "../../components/text-list-editor.tsx/text-list-editor";
|
|
6
|
+
import { LoadingIndicator } from "../../components/loading-indicator";
|
|
7
|
+
import { useObservable, useObservableState, usePromise, useSubscription } from "../../hooks";
|
|
8
|
+
import { Input } from "../../components/input";
|
|
9
|
+
|
|
10
|
+
interface IProps {
|
|
11
|
+
knowledgeFrameId: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const KnowledgeFrameDetails = (props: IProps) => {
|
|
15
|
+
|
|
16
|
+
const frame = usePromise(async () => {
|
|
17
|
+
const frame = await KnowledgeFrames().get(props.knowledgeFrameId);
|
|
18
|
+
if (!frame) {
|
|
19
|
+
throw new Error('Knowledge Frame not found');
|
|
20
|
+
}
|
|
21
|
+
return KnowledgeFrames().initDoc(frame);
|
|
22
|
+
}, undefined, [props.knowledgeFrameId]);
|
|
23
|
+
|
|
24
|
+
const bodyObs = frame?.qs.body || observable('');
|
|
25
|
+
// useEffect
|
|
26
|
+
let p = setTimeout(() => {}, 0);
|
|
27
|
+
useSubscription(bodyObs, () => {
|
|
28
|
+
clearTimeout(p);
|
|
29
|
+
p = setTimeout(() => {
|
|
30
|
+
// todo update frames knowledgeIds that are linked in the body
|
|
31
|
+
frame?.save();
|
|
32
|
+
}, 2000);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
if (!frame) {
|
|
36
|
+
return <LoadingIndicator />;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div className="container-fluid p-3">
|
|
41
|
+
|
|
42
|
+
<div className="d-flex">
|
|
43
|
+
<div>
|
|
44
|
+
<h4>
|
|
45
|
+
<i className="me-2 bi bi-window-dock"></i>
|
|
46
|
+
</h4>
|
|
47
|
+
</div>
|
|
48
|
+
<div className="flex-grow-1">
|
|
49
|
+
<h4>
|
|
50
|
+
<Input
|
|
51
|
+
key={frame.knowledgeFrameId}
|
|
52
|
+
className='border border-0'
|
|
53
|
+
style={{ width: '100%', outline: 'none', backgroundColor: 'transparent' }}
|
|
54
|
+
value={frame.qs.name}
|
|
55
|
+
/>
|
|
56
|
+
</h4>
|
|
57
|
+
</div>
|
|
58
|
+
<div>
|
|
59
|
+
<SaveButton
|
|
60
|
+
key={frame.knowledgeFrameId}
|
|
61
|
+
doc={frame}
|
|
62
|
+
/>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<br />
|
|
67
|
+
|
|
68
|
+
{/* <MarkdownEditorInline
|
|
69
|
+
value={frame.qs.body}
|
|
70
|
+
maxHeight={'calc(100vh - 130px)'}
|
|
71
|
+
/> */}
|
|
72
|
+
|
|
73
|
+
{/* <KnowledgeEntriesList frame={frame} /> */}
|
|
74
|
+
|
|
75
|
+
<TextListEditor value={bodyObs} maxHeight={'calc(100vh - 130px)'} />
|
|
76
|
+
|
|
77
|
+
{/* <KnowledgeEntryEditor /> */}
|
|
78
|
+
|
|
79
|
+
</div>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
interface IKnowledgeEntriesListProps {
|
|
84
|
+
frame: IDoc<IKnowledgeFrame>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const KnowledgeEntriesList = (props: IKnowledgeEntriesListProps) => {
|
|
88
|
+
const { frame } = props;
|
|
89
|
+
|
|
90
|
+
useObservable(frame.qs.knowledgeValueIds);
|
|
91
|
+
|
|
92
|
+
const knowledgeEntries = usePromise(async () => {
|
|
93
|
+
return KnowledgeValues().list({ knowledgeValueId: frame.knowledgeValueIds } );
|
|
94
|
+
}, [], [frame.knowledgeValueIds]);
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<div>
|
|
98
|
+
<NewKnowledgeEntry frame={frame} />
|
|
99
|
+
|
|
100
|
+
<div>
|
|
101
|
+
{knowledgeEntries?.map(entry => {
|
|
102
|
+
return (
|
|
103
|
+
<div key={entry.knowledgeValueId}>
|
|
104
|
+
{JSON.stringify(entry, null, 2)}
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
})}
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
</div>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
interface INewKnowledgeEntryProps {
|
|
115
|
+
defaultSubjectId?: string;
|
|
116
|
+
defaultPredicateId?: string;
|
|
117
|
+
frame: IDoc<IKnowledgeFrame>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const NewKnowledgeEntry = (props: INewKnowledgeEntryProps) => {
|
|
121
|
+
const { defaultSubjectId, defaultPredicateId, frame } = props;
|
|
122
|
+
|
|
123
|
+
const valueStr = useObservableState('', true);
|
|
124
|
+
|
|
125
|
+
const addKnowledgeEntry = async (e: React.FormEvent) => {
|
|
126
|
+
e.preventDefault();
|
|
127
|
+
const value = valueStr().trim();
|
|
128
|
+
throw new Error('Not implemented');
|
|
129
|
+
// const entry = await KnowledgeValues().insert({
|
|
130
|
+
// knowledgeValueId: newid(),
|
|
131
|
+
// peerTypeId: 'string',
|
|
132
|
+
// value,
|
|
133
|
+
// // predicateId: defaultPredicateId,
|
|
134
|
+
// // subjectId: defaultSubjectId,
|
|
135
|
+
// // modified: Date.now(),
|
|
136
|
+
|
|
137
|
+
// });
|
|
138
|
+
|
|
139
|
+
// frame.knowledgeValueIds = [...frame.knowledgeValueIds, entry.knowledgeValueId];
|
|
140
|
+
// await frame.save();
|
|
141
|
+
// valueStr('');
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<div>
|
|
146
|
+
<form
|
|
147
|
+
onSubmit={addKnowledgeEntry}
|
|
148
|
+
>
|
|
149
|
+
<Input
|
|
150
|
+
value={valueStr}
|
|
151
|
+
className="form-control sm"
|
|
152
|
+
type="text"
|
|
153
|
+
placeholder="Add Entry"
|
|
154
|
+
/>
|
|
155
|
+
</form>
|
|
156
|
+
|
|
157
|
+
</div>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|