@vertesia/ui 0.59.0 → 0.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/core/components/FormItem.js +9 -0
- package/lib/esm/core/components/FormItem.js.map +1 -0
- package/lib/esm/core/components/InputList.js +4 -3
- package/lib/esm/core/components/InputList.js.map +1 -1
- package/lib/esm/core/components/index.js +3 -3
- package/lib/esm/core/components/index.js.map +1 -1
- package/lib/esm/core/components/shadcn/button.js +37 -7
- package/lib/esm/core/components/shadcn/button.js.map +1 -1
- package/lib/esm/core/components/shadcn/dialog.js +3 -3
- package/lib/esm/core/components/shadcn/dialog.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/DynamicLabel.js +38 -0
- package/lib/esm/core/components/shadcn/filters/DynamicLabel.js.map +1 -0
- package/lib/esm/core/components/shadcn/filters/comboBox.js +24 -26
- package/lib/esm/core/components/shadcn/filters/comboBox.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/dateFilter.js +12 -12
- package/lib/esm/core/components/shadcn/filters/dateFilter.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/filterBar.js +49 -36
- package/lib/esm/core/components/shadcn/filters/filterBar.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/filters.js +31 -23
- package/lib/esm/core/components/shadcn/filters/filters.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/selectFilter.js +33 -24
- package/lib/esm/core/components/shadcn/filters/selectFilter.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/textFilter.js +2 -2
- package/lib/esm/core/components/shadcn/filters/textFilter.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/types.js.map +1 -1
- package/lib/esm/core/components/shadcn/input.js +4 -4
- package/lib/esm/core/components/shadcn/input.js.map +1 -1
- package/lib/esm/core/components/shadcn/selectBox.js +72 -6
- package/lib/esm/core/components/shadcn/selectBox.js.map +1 -1
- package/lib/esm/core/components/styles.js +1 -1
- package/lib/esm/core/components/styles.js.map +1 -1
- package/lib/esm/core/components/table/index.js +3 -0
- package/lib/esm/core/components/table/index.js.map +1 -1
- package/lib/esm/core/index.js +2 -1
- package/lib/esm/core/index.js.map +1 -1
- package/lib/esm/core/utils/cn.js +6 -0
- package/lib/esm/core/utils/cn.js.map +1 -0
- package/lib/esm/core/utils/index.js +2 -0
- package/lib/esm/core/utils/index.js.map +1 -0
- package/lib/esm/features/agent/PayloadBuilder.js +174 -0
- package/lib/esm/features/agent/PayloadBuilder.js.map +1 -0
- package/lib/esm/features/agent/chat/AnimatedThinkingDots.js +207 -0
- package/lib/esm/features/agent/chat/AnimatedThinkingDots.js.map +1 -0
- package/lib/esm/features/agent/chat/JumpingDots.js +6 -0
- package/lib/esm/features/agent/chat/JumpingDots.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentConversation.js +409 -0
- package/lib/esm/features/agent/chat/ModernAgentConversation.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +129 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js +66 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlideInPanel.js +29 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlideInPanel.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js +97 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageInput.js +46 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageInput.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js +352 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessagesContainer.js +20 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessagesContainer.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/PlanPanel.js +62 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/PlanPanel.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/SlideInPanel.js +23 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/SlideInPanel.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/SlidingMessages.js +51 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/SlidingMessages.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.js +82 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/StackedMessages.js +13 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/StackedMessages.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +105 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/utils.js +154 -0
- package/lib/esm/features/agent/chat/ModernAgentOutput/utils.js.map +1 -0
- package/lib/esm/features/agent/chat/SlidingThinkingIndicator.js +266 -0
- package/lib/esm/features/agent/chat/SlidingThinkingIndicator.js.map +1 -0
- package/lib/esm/features/agent/chat/WaitingMessages.js +60 -0
- package/lib/esm/features/agent/chat/WaitingMessages.js.map +1 -0
- package/lib/esm/features/agent/chat/index.js +5 -0
- package/lib/esm/features/agent/chat/index.js.map +1 -0
- package/lib/esm/features/agent/index.js +3 -0
- package/lib/esm/features/agent/index.js.map +1 -0
- package/lib/esm/features/errors/PanelErrorBoundary.js +11 -0
- package/lib/esm/features/errors/PanelErrorBoundary.js.map +1 -0
- package/lib/esm/features/errors/RowErrorBoundary.js +9 -0
- package/lib/esm/features/errors/RowErrorBoundary.js.map +1 -0
- package/lib/esm/features/errors/VertesiaErrorBoundary.js +15 -0
- package/lib/esm/features/errors/VertesiaErrorBoundary.js.map +1 -0
- package/lib/esm/features/errors/WidgetErrorBoundary.js +11 -0
- package/lib/esm/features/errors/WidgetErrorBoundary.js.map +1 -0
- package/lib/esm/features/errors/index.js +5 -0
- package/lib/esm/features/errors/index.js.map +1 -0
- package/lib/esm/features/facets/EnvironmentFacet.js +39 -0
- package/lib/esm/features/facets/EnvironmentFacet.js.map +1 -0
- package/lib/esm/features/facets/FacetsNav.js +8 -0
- package/lib/esm/features/facets/FacetsNav.js.map +1 -0
- package/lib/esm/features/facets/InteractionFacet.js +39 -0
- package/lib/esm/features/facets/InteractionFacet.js.map +1 -0
- package/lib/esm/features/facets/StringFacet.js +12 -0
- package/lib/esm/features/facets/StringFacet.js.map +1 -0
- package/lib/esm/features/facets/StringListFacet.js +11 -0
- package/lib/esm/features/facets/StringListFacet.js.map +1 -0
- package/lib/esm/features/facets/TypeFacet.js +42 -0
- package/lib/esm/features/facets/TypeFacet.js.map +1 -0
- package/lib/esm/features/facets/TypeOptions.js +19 -0
- package/lib/esm/features/facets/TypeOptions.js.map +1 -0
- package/lib/esm/features/facets/UserFacet.js +33 -0
- package/lib/esm/features/facets/UserFacet.js.map +1 -0
- package/lib/esm/features/facets/VFacetsNav.js +114 -0
- package/lib/esm/features/facets/VFacetsNav.js.map +1 -0
- package/lib/esm/features/facets/VStringFacet.js +17 -0
- package/lib/esm/features/facets/VStringFacet.js.map +1 -0
- package/lib/esm/features/facets/VTypeFacet.js +56 -0
- package/lib/esm/features/facets/VTypeFacet.js.map +1 -0
- package/lib/esm/features/facets/VUserFacet.js +31 -0
- package/lib/esm/features/facets/VUserFacet.js.map +1 -0
- package/lib/esm/features/facets/index.js +12 -0
- package/lib/esm/features/facets/index.js.map +1 -0
- package/lib/esm/features/facets/utils.js +7 -0
- package/lib/esm/features/facets/utils.js.map +1 -0
- package/lib/esm/features/index.js +9 -1
- package/lib/esm/features/index.js.map +1 -1
- package/lib/esm/features/layout/GenericPageNavHeader.js +11 -0
- package/lib/esm/features/layout/GenericPageNavHeader.js.map +1 -0
- package/lib/esm/features/layout/NotFoundView.js +5 -0
- package/lib/esm/features/layout/NotFoundView.js.map +1 -0
- package/lib/esm/features/layout/index.js +3 -0
- package/lib/esm/features/layout/index.js.map +1 -0
- package/lib/esm/features/magic-pdf/DownloadPopover.js +13 -0
- package/lib/esm/features/magic-pdf/DownloadPopover.js.map +1 -0
- package/lib/esm/features/magic-pdf/MagicPdfView.js +44 -0
- package/lib/esm/features/magic-pdf/MagicPdfView.js.map +1 -0
- package/lib/esm/features/magic-pdf/PageSlider.js +57 -0
- package/lib/esm/features/magic-pdf/PageSlider.js.map +1 -0
- package/lib/esm/features/magic-pdf/PdfPageProvider.js +133 -0
- package/lib/esm/features/magic-pdf/PdfPageProvider.js.map +1 -0
- package/lib/esm/features/magic-pdf/TextPageView.js +45 -0
- package/lib/esm/features/magic-pdf/TextPageView.js.map +1 -0
- package/lib/esm/features/magic-pdf/index.js +2 -0
- package/lib/esm/features/magic-pdf/index.js.map +1 -0
- package/lib/esm/features/magic-pdf/types.js +2 -0
- package/lib/esm/features/magic-pdf/types.js.map +1 -0
- package/lib/esm/features/magic-pdf/useResizeOnDrag.js +34 -0
- package/lib/esm/features/magic-pdf/useResizeOnDrag.js.map +1 -0
- package/lib/esm/features/store/collections/BrowseCollectionView.js +37 -0
- package/lib/esm/features/store/collections/BrowseCollectionView.js.map +1 -0
- package/lib/esm/features/store/collections/CollectionView.js +53 -0
- package/lib/esm/features/store/collections/CollectionView.js.map +1 -0
- package/lib/esm/features/store/collections/CollectionsTable.js +60 -0
- package/lib/esm/features/store/collections/CollectionsTable.js.map +1 -0
- package/lib/esm/features/store/collections/CollectionsView.js +94 -0
- package/lib/esm/features/store/collections/CollectionsView.js.map +1 -0
- package/lib/esm/features/store/collections/EditCollectionView.js +161 -0
- package/lib/esm/features/store/collections/EditCollectionView.js.map +1 -0
- package/lib/esm/features/store/collections/index.js +6 -0
- package/lib/esm/features/store/collections/index.js.map +1 -0
- package/lib/esm/features/store/index.js +4 -0
- package/lib/esm/features/store/index.js.map +1 -0
- package/lib/esm/features/store/objects/DocumentPreviewPanel.js +150 -0
- package/lib/esm/features/store/objects/DocumentPreviewPanel.js.map +1 -0
- package/lib/esm/features/store/objects/DocumentSearchResults.js +123 -0
- package/lib/esm/features/store/objects/DocumentSearchResults.js.map +1 -0
- package/lib/esm/features/store/objects/DocumentSelectionProvider.js +81 -0
- package/lib/esm/features/store/objects/DocumentSelectionProvider.js.map +1 -0
- package/lib/esm/features/store/objects/DocumentTable.js +278 -0
- package/lib/esm/features/store/objects/DocumentTable.js.map +1 -0
- package/lib/esm/features/store/objects/ExportPropertiesModal.js +31 -0
- package/lib/esm/features/store/objects/ExportPropertiesModal.js.map +1 -0
- package/lib/esm/features/store/objects/components/ContentDispositionButton.js +31 -0
- package/lib/esm/features/store/objects/components/ContentDispositionButton.js.map +1 -0
- package/lib/esm/features/store/objects/components/ContentOverview.js +195 -0
- package/lib/esm/features/store/objects/components/ContentOverview.js.map +1 -0
- package/lib/esm/features/store/objects/components/DocumentIcon.js +28 -0
- package/lib/esm/features/store/objects/components/DocumentIcon.js.map +1 -0
- package/lib/esm/features/store/objects/components/DocumentInput.js +52 -0
- package/lib/esm/features/store/objects/components/DocumentInput.js.map +1 -0
- package/lib/esm/features/store/objects/components/PropertiesEditorModal.js +169 -0
- package/lib/esm/features/store/objects/components/PropertiesEditorModal.js.map +1 -0
- package/lib/esm/features/store/objects/components/SaveVersionConfirmModal.js +45 -0
- package/lib/esm/features/store/objects/components/SaveVersionConfirmModal.js.map +1 -0
- package/lib/esm/features/store/objects/components/SelectDocument.js +39 -0
- package/lib/esm/features/store/objects/components/SelectDocument.js.map +1 -0
- package/lib/esm/features/store/objects/components/SelectDocumentModal.js +7 -0
- package/lib/esm/features/store/objects/components/SelectDocumentModal.js.map +1 -0
- package/lib/esm/features/store/objects/components/VectorSearchWidget.js +85 -0
- package/lib/esm/features/store/objects/components/VectorSearchWidget.js.map +1 -0
- package/lib/esm/features/store/objects/components/index.js +10 -0
- package/lib/esm/features/store/objects/components/index.js.map +1 -0
- package/lib/esm/features/store/objects/components/useDownloadObject.js +21 -0
- package/lib/esm/features/store/objects/components/useDownloadObject.js.map +1 -0
- package/lib/esm/features/store/objects/index.js +11 -0
- package/lib/esm/features/store/objects/index.js.map +1 -0
- package/lib/esm/features/store/objects/layout/DocumentTableColumn.js +74 -0
- package/lib/esm/features/store/objects/layout/DocumentTableColumn.js.map +1 -0
- package/lib/esm/features/store/objects/layout/documentLayout.js +16 -0
- package/lib/esm/features/store/objects/layout/documentLayout.js.map +1 -0
- package/lib/esm/features/store/objects/layout/index.js +3 -0
- package/lib/esm/features/store/objects/layout/index.js.map +1 -0
- package/lib/esm/features/store/objects/layout/renderers.js +128 -0
- package/lib/esm/features/store/objects/layout/renderers.js.map +1 -0
- package/lib/esm/features/store/objects/search/DocumentSearchContext.js +150 -0
- package/lib/esm/features/store/objects/search/DocumentSearchContext.js.map +1 -0
- package/lib/esm/features/store/objects/search/DocumentSearchProvider.js +41 -0
- package/lib/esm/features/store/objects/search/DocumentSearchProvider.js.map +1 -0
- package/lib/esm/features/store/objects/search/index.js +3 -0
- package/lib/esm/features/store/objects/search/index.js.map +1 -0
- package/lib/esm/features/store/objects/selection/ObjectsActionContext.js +149 -0
- package/lib/esm/features/store/objects/selection/ObjectsActionContext.js.map +1 -0
- package/lib/esm/features/store/objects/selection/ObjectsActionSpec.js +2 -0
- package/lib/esm/features/store/objects/selection/ObjectsActionSpec.js.map +1 -0
- package/lib/esm/features/store/objects/selection/SelectionActions.js +75 -0
- package/lib/esm/features/store/objects/selection/SelectionActions.js.map +1 -0
- package/lib/esm/features/store/objects/selection/actions/AddToCollectionAction.js +64 -0
- package/lib/esm/features/store/objects/selection/actions/AddToCollectionAction.js.map +1 -0
- package/lib/esm/features/store/objects/selection/actions/ChangeTypeAction.js +53 -0
- package/lib/esm/features/store/objects/selection/actions/ChangeTypeAction.js.map +1 -0
- package/lib/esm/features/store/objects/selection/actions/ConfirmAction.js +30 -0
- package/lib/esm/features/store/objects/selection/actions/ConfirmAction.js.map +1 -0
- package/lib/esm/features/store/objects/selection/actions/DeleteObjectsAction.js +66 -0
- package/lib/esm/features/store/objects/selection/actions/DeleteObjectsAction.js.map +1 -0
- package/lib/esm/features/store/objects/selection/actions/ExportPropertiesAction.js +106 -0
- package/lib/esm/features/store/objects/selection/actions/ExportPropertiesAction.js.map +1 -0
- package/lib/esm/features/store/objects/selection/actions/RemoveFromCollectionAction.js +64 -0
- package/lib/esm/features/store/objects/selection/actions/RemoveFromCollectionAction.js.map +1 -0
- package/lib/esm/features/store/objects/selection/actions/StartWorkflowComponent.js +72 -0
- package/lib/esm/features/store/objects/selection/actions/StartWorkflowComponent.js.map +1 -0
- package/lib/esm/features/store/objects/selection/actions/index.js +8 -0
- package/lib/esm/features/store/objects/selection/actions/index.js.map +1 -0
- package/lib/esm/features/store/objects/selection/index.js +5 -0
- package/lib/esm/features/store/objects/selection/index.js.map +1 -0
- package/lib/esm/features/store/objects/upload/DocumentUploadModal.js +476 -0
- package/lib/esm/features/store/objects/upload/DocumentUploadModal.js.map +1 -0
- package/lib/esm/features/store/objects/upload/index.js +4 -0
- package/lib/esm/features/store/objects/upload/index.js.map +1 -0
- package/lib/esm/features/store/objects/upload/useSmartFileUploadProcessing.js +201 -0
- package/lib/esm/features/store/objects/upload/useSmartFileUploadProcessing.js.map +1 -0
- package/lib/esm/features/store/objects/upload/useUploadHandler.js +230 -0
- package/lib/esm/features/store/objects/upload/useUploadHandler.js.map +1 -0
- package/lib/esm/features/store/types/ContentObjectTypeView.js +158 -0
- package/lib/esm/features/store/types/ContentObjectTypeView.js.map +1 -0
- package/lib/esm/features/store/types/ContentObjectTypesSearch.js +82 -0
- package/lib/esm/features/store/types/ContentObjectTypesSearch.js.map +1 -0
- package/lib/esm/features/store/types/ContentObjectTypesTable.js +11 -0
- package/lib/esm/features/store/types/ContentObjectTypesTable.js.map +1 -0
- package/lib/esm/features/store/types/ContentObjectTypesView.js +55 -0
- package/lib/esm/features/store/types/ContentObjectTypesView.js.map +1 -0
- package/lib/esm/features/store/types/CreateOrUpdateTypeModal.js +26 -0
- package/lib/esm/features/store/types/CreateOrUpdateTypeModal.js.map +1 -0
- package/lib/esm/features/store/types/ObjectSchemaEditor.js +89 -0
- package/lib/esm/features/store/types/ObjectSchemaEditor.js.map +1 -0
- package/lib/esm/features/store/types/SelectContentType.js +43 -0
- package/lib/esm/features/store/types/SelectContentType.js.map +1 -0
- package/lib/esm/features/store/types/SelectContentTypeModal.js +28 -0
- package/lib/esm/features/store/types/SelectContentTypeModal.js.map +1 -0
- package/lib/esm/features/store/types/TableLayoutEditor.js +78 -0
- package/lib/esm/features/store/types/TableLayoutEditor.js.map +1 -0
- package/lib/esm/features/store/types/index.js +11 -0
- package/lib/esm/features/store/types/index.js.map +1 -0
- package/lib/esm/features/store/types/search/ObjectTypeSearchContext.js +98 -0
- package/lib/esm/features/store/types/search/ObjectTypeSearchContext.js.map +1 -0
- package/lib/esm/features/store/types/search/ObjectTypeSearchProvider.js +15 -0
- package/lib/esm/features/store/types/search/ObjectTypeSearchProvider.js.map +1 -0
- package/lib/esm/features/store/types/search/index.js +3 -0
- package/lib/esm/features/store/types/search/index.js.map +1 -0
- package/lib/esm/features/user/UserAvatar.js +18 -0
- package/lib/esm/features/user/UserAvatar.js.map +1 -0
- package/lib/esm/features/user/UserInfo.js +88 -0
- package/lib/esm/features/user/UserInfo.js.map +1 -0
- package/lib/esm/features/user/index.js +3 -0
- package/lib/esm/features/user/index.js.map +1 -0
- package/lib/esm/features/utils/index.js +4 -0
- package/lib/esm/features/utils/index.js.map +1 -0
- package/lib/esm/features/utils/mimeType.js +9 -0
- package/lib/esm/features/utils/mimeType.js.map +1 -0
- package/lib/esm/features/utils/rendition.js +47 -0
- package/lib/esm/features/utils/rendition.js.map +1 -0
- package/lib/esm/features/utils/text.js +10 -0
- package/lib/esm/features/utils/text.js.map +1 -0
- package/lib/esm/layout/FullHeightLayout.js +1 -1
- package/lib/esm/layout/FullHeightLayout.js.map +1 -1
- package/lib/esm/layout/Sidebar.js +12 -2
- package/lib/esm/layout/Sidebar.js.map +1 -1
- package/lib/esm/widgets/Progress.js +5 -0
- package/lib/esm/widgets/Progress.js.map +1 -0
- package/lib/esm/widgets/codemirror/CodeMirrorEditor.js +1 -1
- package/lib/esm/widgets/codemirror/CodeMirrorEditor.js.map +1 -1
- package/lib/esm/widgets/form/Form.js +2 -2
- package/lib/esm/widgets/form/Form.js.map +1 -1
- package/lib/esm/widgets/form/schema.js +11 -5
- package/lib/esm/widgets/form/schema.js.map +1 -1
- package/lib/esm/widgets/index.js +4 -0
- package/lib/esm/widgets/index.js.map +1 -1
- package/lib/esm/widgets/popover/Popover.js +73 -0
- package/lib/esm/widgets/popover/Popover.js.map +1 -0
- package/lib/esm/widgets/popover/context.js +7 -0
- package/lib/esm/widgets/popover/context.js.map +1 -0
- package/lib/esm/widgets/popover/index.js +3 -0
- package/lib/esm/widgets/popover/index.js.map +1 -0
- package/lib/esm/widgets/popover/slots.js +22 -0
- package/lib/esm/widgets/popover/slots.js.map +1 -0
- package/lib/esm/widgets/properties/PropertiesView.js +6 -0
- package/lib/esm/widgets/properties/PropertiesView.js.map +1 -0
- package/lib/esm/widgets/properties/index.js +2 -0
- package/lib/esm/widgets/properties/index.js.map +1 -0
- package/lib/esm/widgets/schema-editor/JSONSchemaEditorModal.js +1 -2
- package/lib/esm/widgets/schema-editor/JSONSchemaEditorModal.js.map +1 -1
- package/lib/esm/widgets/schema-editor/editor/Editable.js +9 -10
- package/lib/esm/widgets/schema-editor/editor/Editable.js.map +1 -1
- package/lib/esm/widgets/schema-editor/editor/PropertyViewer.js +1 -1
- package/lib/esm/widgets/schema-editor/editor/PropertyViewer.js.map +1 -1
- package/lib/esm/widgets/schema-editor/editor/SchemaEditor.js +2 -2
- package/lib/esm/widgets/schema-editor/editor/SchemaEditor.js.map +1 -1
- package/lib/esm/widgets/upload/DropZone.js +162 -0
- package/lib/esm/widgets/upload/DropZone.js.map +1 -0
- package/lib/esm/widgets/upload/UploadResultCategory.js +19 -0
- package/lib/esm/widgets/upload/UploadResultCategory.js.map +1 -0
- package/lib/esm/widgets/upload/UploadSummary.js +30 -0
- package/lib/esm/widgets/upload/UploadSummary.js.map +1 -0
- package/lib/esm/widgets/upload/index.js +4 -0
- package/lib/esm/widgets/upload/index.js.map +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types/core/components/FormItem.d.ts +11 -0
- package/lib/types/core/components/index.d.ts +3 -3
- package/lib/types/core/components/shadcn/button.d.ts +13 -2
- package/lib/types/core/components/shadcn/command.d.ts +7 -7
- package/lib/types/core/components/shadcn/filters/DynamicLabel.d.ts +8 -0
- package/lib/types/core/components/shadcn/filters/comboBox.d.ts +5 -5
- package/lib/types/core/components/shadcn/filters/dateFilter.d.ts +3 -4
- package/lib/types/core/components/shadcn/filters/types.d.ts +7 -1
- package/lib/types/core/components/shadcn/input.d.ts +4 -4
- package/lib/types/core/components/shadcn/selectBox.d.ts +13 -4
- package/lib/types/core/components/table/index.d.ts +1 -0
- package/lib/types/core/index.d.ts +2 -1
- package/lib/types/core/utils/cn.d.ts +2 -0
- package/lib/types/core/utils/index.d.ts +1 -0
- package/lib/types/features/agent/PayloadBuilder.d.ts +53 -0
- package/lib/types/features/agent/chat/AnimatedThinkingDots.d.ts +37 -0
- package/lib/types/features/agent/chat/JumpingDots.d.ts +6 -0
- package/lib/types/features/agent/chat/ModernAgentConversation.d.ts +24 -0
- package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +21 -0
- package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts +18 -0
- package/lib/types/features/agent/chat/ModernAgentOutput/InlineSlideInPanel.d.ts +10 -0
- package/lib/types/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.d.ts +15 -0
- package/lib/types/features/agent/chat/ModernAgentOutput/MessageInput.d.ts +12 -0
- package/lib/types/features/agent/chat/ModernAgentOutput/MessageItem.d.ts +7 -0
- package/lib/types/features/agent/chat/ModernAgentOutput/MessagesContainer.d.ts +9 -0
- package/lib/types/features/agent/chat/ModernAgentOutput/PlanPanel.d.ts +8 -0
- package/lib/types/features/agent/chat/ModernAgentOutput/SlideInPanel.d.ts +10 -0
- package/lib/types/features/agent/chat/ModernAgentOutput/SlidingMessages.d.ts +7 -0
- package/lib/types/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.d.ts +9 -0
- package/lib/types/features/agent/chat/ModernAgentOutput/StackedMessages.d.ts +7 -0
- package/lib/types/features/agent/chat/ModernAgentOutput/WorkstreamTabs.d.ts +21 -0
- package/lib/types/features/agent/chat/ModernAgentOutput/utils.d.ts +23 -0
- package/lib/types/features/agent/chat/SlidingThinkingIndicator.d.ts +17 -0
- package/lib/types/features/agent/chat/WaitingMessages.d.ts +1 -0
- package/lib/types/features/agent/chat/index.d.ts +4 -0
- package/lib/types/features/agent/index.d.ts +2 -0
- package/lib/types/features/errors/PanelErrorBoundary.d.ts +4 -0
- package/lib/types/features/errors/RowErrorBoundary.d.ts +7 -0
- package/lib/types/features/errors/VertesiaErrorBoundary.d.ts +11 -0
- package/lib/types/features/errors/WidgetErrorBoundary.d.ts +4 -0
- package/lib/types/features/errors/index.d.ts +4 -0
- package/lib/types/features/facets/EnvironmentFacet.d.ts +9 -0
- package/lib/types/features/facets/FacetsNav.d.ts +6 -0
- package/lib/types/features/facets/InteractionFacet.d.ts +9 -0
- package/lib/types/features/facets/StringFacet.d.ts +10 -0
- package/lib/types/features/facets/StringListFacet.d.ts +10 -0
- package/lib/types/features/facets/TypeFacet.d.ts +15 -0
- package/lib/types/features/facets/TypeOptions.d.ts +3 -0
- package/lib/types/features/facets/UserFacet.d.ts +11 -0
- package/lib/types/features/facets/VFacetsNav.d.ts +7 -0
- package/lib/types/features/facets/VStringFacet.d.ts +15 -0
- package/lib/types/features/facets/VTypeFacet.d.ts +8 -0
- package/lib/types/features/facets/VUserFacet.d.ts +9 -0
- package/lib/types/features/facets/index.d.ts +11 -0
- package/lib/types/features/facets/utils.d.ts +3 -0
- package/lib/types/features/index.d.ts +9 -1
- package/lib/types/features/layout/GenericPageNavHeader.d.ts +12 -0
- package/lib/types/features/layout/NotFoundView.d.ts +4 -0
- package/lib/types/features/layout/index.d.ts +2 -0
- package/lib/types/features/magic-pdf/DownloadPopover.d.ts +6 -0
- package/lib/types/features/magic-pdf/MagicPdfView.d.ts +6 -0
- package/lib/types/features/magic-pdf/PageSlider.d.ts +7 -0
- package/lib/types/features/magic-pdf/PdfPageProvider.d.ts +28 -0
- package/lib/types/features/magic-pdf/TextPageView.d.ts +7 -0
- package/lib/types/features/magic-pdf/index.d.ts +1 -0
- package/lib/types/features/magic-pdf/types.d.ts +1 -0
- package/lib/types/features/magic-pdf/useResizeOnDrag.d.ts +8 -0
- package/lib/types/features/store/collections/BrowseCollectionView.d.ts +6 -0
- package/lib/types/features/store/collections/CollectionView.d.ts +5 -0
- package/lib/types/features/store/collections/CollectionsTable.d.ts +5 -0
- package/lib/types/features/store/collections/CollectionsView.d.ts +10 -0
- package/lib/types/features/store/collections/EditCollectionView.d.ts +7 -0
- package/lib/types/features/store/collections/index.d.ts +5 -0
- package/lib/types/features/store/index.d.ts +3 -0
- package/lib/types/features/store/objects/DocumentPreviewPanel.d.ts +7 -0
- package/lib/types/features/store/objects/DocumentSearchResults.d.ts +19 -0
- package/lib/types/features/store/objects/DocumentSelectionProvider.d.ts +32 -0
- package/lib/types/features/store/objects/DocumentTable.d.ts +20 -0
- package/lib/types/features/store/objects/ExportPropertiesModal.d.ts +11 -0
- package/lib/types/features/store/objects/components/ContentDispositionButton.d.ts +8 -0
- package/lib/types/features/store/objects/components/ContentOverview.d.ts +7 -0
- package/lib/types/features/store/objects/components/DocumentIcon.d.ts +10 -0
- package/lib/types/features/store/objects/components/DocumentInput.d.ts +7 -0
- package/lib/types/features/store/objects/components/PropertiesEditorModal.d.ts +7 -0
- package/lib/types/features/store/objects/components/SaveVersionConfirmModal.d.ts +8 -0
- package/lib/types/features/store/objects/components/SelectDocument.d.ts +8 -0
- package/lib/types/features/store/objects/components/SelectDocumentModal.d.ts +8 -0
- package/lib/types/features/store/objects/components/VectorSearchWidget.d.ts +10 -0
- package/lib/types/features/store/objects/components/index.d.ts +9 -0
- package/lib/types/features/store/objects/components/useDownloadObject.d.ts +3 -0
- package/lib/types/features/store/objects/index.d.ts +10 -0
- package/lib/types/features/store/objects/layout/DocumentTableColumn.d.ts +16 -0
- package/lib/types/features/store/objects/layout/documentLayout.d.ts +17 -0
- package/lib/types/features/store/objects/layout/index.d.ts +2 -0
- package/lib/types/features/store/objects/layout/renderers.d.ts +2 -0
- package/lib/types/features/store/objects/search/DocumentSearchContext.d.ts +48 -0
- package/lib/types/features/store/objects/search/DocumentSearchProvider.d.ts +15 -0
- package/lib/types/features/store/objects/search/index.d.ts +2 -0
- package/lib/types/features/store/objects/selection/ObjectsActionContext.d.ts +25 -0
- package/lib/types/features/store/objects/selection/ObjectsActionSpec.d.ts +27 -0
- package/lib/types/features/store/objects/selection/SelectionActions.d.ts +4 -0
- package/lib/types/features/store/objects/selection/actions/AddToCollectionAction.d.ts +3 -0
- package/lib/types/features/store/objects/selection/actions/ChangeTypeAction.d.ts +3 -0
- package/lib/types/features/store/objects/selection/actions/ConfirmAction.d.ts +15 -0
- package/lib/types/features/store/objects/selection/actions/DeleteObjectsAction.d.ts +2 -0
- package/lib/types/features/store/objects/selection/actions/ExportPropertiesAction.d.ts +3 -0
- package/lib/types/features/store/objects/selection/actions/RemoveFromCollectionAction.d.ts +2 -0
- package/lib/types/features/store/objects/selection/actions/StartWorkflowComponent.d.ts +3 -0
- package/lib/types/features/store/objects/selection/actions/index.d.ts +7 -0
- package/lib/types/features/store/objects/selection/index.d.ts +4 -0
- package/lib/types/features/store/objects/upload/DocumentUploadModal.d.ts +37 -0
- package/lib/types/features/store/objects/upload/index.d.ts +3 -0
- package/lib/types/features/store/objects/upload/useSmartFileUploadProcessing.d.ts +29 -0
- package/lib/types/features/store/objects/upload/useUploadHandler.d.ts +49 -0
- package/lib/types/features/store/types/ContentObjectTypeView.d.ts +5 -0
- package/lib/types/features/store/types/ContentObjectTypesSearch.d.ts +5 -0
- package/lib/types/features/store/types/ContentObjectTypesTable.d.ts +7 -0
- package/lib/types/features/store/types/ContentObjectTypesView.d.ts +8 -0
- package/lib/types/features/store/types/CreateOrUpdateTypeModal.d.ts +14 -0
- package/lib/types/features/store/types/ObjectSchemaEditor.d.ts +7 -0
- package/lib/types/features/store/types/SelectContentType.d.ts +10 -0
- package/lib/types/features/store/types/SelectContentTypeModal.d.ts +32 -0
- package/lib/types/features/store/types/TableLayoutEditor.d.ts +8 -0
- package/lib/types/features/store/types/index.d.ts +10 -0
- package/lib/types/features/store/types/search/ObjectTypeSearchContext.d.ts +35 -0
- package/lib/types/features/store/types/search/ObjectTypeSearchProvider.d.ts +10 -0
- package/lib/types/features/store/types/search/index.d.ts +2 -0
- package/lib/types/features/user/UserAvatar.d.ts +8 -0
- package/lib/types/features/user/UserInfo.d.ts +36 -0
- package/lib/types/features/user/index.d.ts +2 -0
- package/lib/types/features/utils/index.d.ts +3 -0
- package/lib/types/features/utils/mimeType.d.ts +4 -0
- package/lib/types/features/utils/rendition.d.ts +3 -0
- package/lib/types/features/utils/text.d.ts +2 -0
- package/lib/types/layout/Sidebar.d.ts +2 -1
- package/lib/types/widgets/Progress.d.ts +5 -0
- package/lib/types/widgets/form/schema.d.ts +4 -3
- package/lib/types/widgets/index.d.ts +4 -0
- package/lib/types/widgets/popover/Popover.d.ts +37 -0
- package/lib/types/widgets/popover/context.d.ts +7 -0
- package/lib/types/widgets/popover/index.d.ts +2 -0
- package/lib/types/widgets/popover/slots.d.ts +4 -0
- package/lib/types/widgets/properties/PropertiesView.d.ts +10 -0
- package/lib/types/widgets/properties/index.d.ts +1 -0
- package/lib/types/widgets/upload/DropZone.d.ts +40 -0
- package/lib/types/widgets/upload/UploadResultCategory.d.ts +25 -0
- package/lib/types/widgets/upload/UploadSummary.d.ts +37 -0
- package/lib/types/widgets/upload/index.d.ts +3 -0
- package/lib/vertesia-ui-core.js +1 -1
- package/lib/vertesia-ui-core.js.map +1 -1
- package/lib/vertesia-ui-features.js +1 -1
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-layout.js +1 -1
- package/lib/vertesia-ui-layout.js.map +1 -1
- package/lib/vertesia-ui-router.js.map +1 -1
- package/lib/vertesia-ui-session.js.map +1 -1
- package/lib/vertesia-ui-widgets.js +1 -1
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/package.json +13 -5
- package/src/core/components/FormItem.tsx +35 -0
- package/src/core/components/InputList.tsx +4 -3
- package/src/core/components/index.ts +3 -3
- package/src/core/components/shadcn/button.tsx +68 -8
- package/src/core/components/shadcn/dialog.tsx +3 -3
- package/src/core/components/shadcn/filters/DynamicLabel.tsx +45 -0
- package/src/core/components/shadcn/filters/comboBox.tsx +56 -52
- package/src/core/components/shadcn/filters/dateFilter.tsx +24 -25
- package/src/core/components/shadcn/filters/filterBar.tsx +53 -47
- package/src/core/components/shadcn/filters/filters.tsx +43 -30
- package/src/core/components/shadcn/filters/selectFilter.tsx +53 -34
- package/src/core/components/shadcn/filters/textFilter.tsx +6 -3
- package/src/core/components/shadcn/filters/types.ts +8 -1
- package/src/core/components/shadcn/input.tsx +5 -5
- package/src/core/components/shadcn/selectBox.tsx +138 -33
- package/src/core/components/styles.ts +1 -1
- package/src/core/components/table/index.tsx +8 -0
- package/src/core/index.ts +2 -1
- package/src/core/utils/cn.ts +6 -0
- package/src/core/utils/index.ts +1 -0
- package/src/features/agent/PayloadBuilder.tsx +208 -0
- package/src/features/agent/chat/AnimatedThinkingDots.tsx +350 -0
- package/src/features/agent/chat/JumpingDots.tsx +16 -0
- package/src/features/agent/chat/ModernAgentConversation.tsx +708 -0
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +246 -0
- package/src/features/agent/chat/ModernAgentOutput/Header.tsx +231 -0
- package/src/features/agent/chat/ModernAgentOutput/InlineSlideInPanel.tsx +66 -0
- package/src/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.tsx +282 -0
- package/src/features/agent/chat/ModernAgentOutput/MessageInput.tsx +125 -0
- package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +562 -0
- package/src/features/agent/chat/ModernAgentOutput/MessagesContainer.tsx +51 -0
- package/src/features/agent/chat/ModernAgentOutput/PlanPanel.tsx +123 -0
- package/src/features/agent/chat/ModernAgentOutput/README-image-support.md +43 -0
- package/src/features/agent/chat/ModernAgentOutput/SlideInPanel.tsx +72 -0
- package/src/features/agent/chat/ModernAgentOutput/SlidingMessages.tsx +96 -0
- package/src/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.tsx +185 -0
- package/src/features/agent/chat/ModernAgentOutput/StackedMessages.tsx +33 -0
- package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +167 -0
- package/src/features/agent/chat/ModernAgentOutput/utils.ts +195 -0
- package/src/features/agent/chat/ModernAgentOutput/with-types.d.ts +15 -0
- package/src/features/agent/chat/SlidingThinkingIndicator.tsx +459 -0
- package/src/features/agent/chat/WaitingMessages.ts +66 -0
- package/src/features/agent/chat/index.ts +4 -0
- package/src/features/agent/index.ts +2 -0
- package/src/features/errors/PanelErrorBoundary.tsx +30 -0
- package/src/features/errors/RowErrorBoundary.tsx +28 -0
- package/src/features/errors/VertesiaErrorBoundary.tsx +28 -0
- package/src/features/errors/WidgetErrorBoundary.tsx +27 -0
- package/src/features/errors/index.ts +4 -0
- package/src/features/facets/EnvironmentFacet.tsx +53 -0
- package/src/features/facets/FacetsNav.tsx +19 -0
- package/src/features/facets/InteractionFacet.tsx +53 -0
- package/src/features/facets/StringFacet.tsx +23 -0
- package/src/features/facets/StringListFacet.tsx +22 -0
- package/src/features/facets/TypeFacet.tsx +59 -0
- package/src/features/facets/TypeOptions.tsx +22 -0
- package/src/features/facets/UserFacet.tsx +61 -0
- package/src/features/facets/VFacetsNav.tsx +139 -0
- package/src/features/facets/VStringFacet.tsx +34 -0
- package/src/features/facets/VTypeFacet.tsx +72 -0
- package/src/features/facets/VUserFacet.tsx +47 -0
- package/src/features/facets/index.ts +11 -0
- package/src/features/facets/utils.tsx +9 -0
- package/src/features/index.ts +9 -1
- package/src/features/layout/GenericPageNavHeader.tsx +48 -0
- package/src/features/layout/NotFoundView.tsx +11 -0
- package/src/features/layout/index.ts +2 -0
- package/src/features/magic-pdf/DownloadPopover.tsx +32 -0
- package/src/features/magic-pdf/MagicPdfView.tsx +102 -0
- package/src/features/magic-pdf/PageSlider.tsx +112 -0
- package/src/features/magic-pdf/PdfPageProvider.tsx +229 -0
- package/src/features/magic-pdf/TextPageView.tsx +65 -0
- package/src/features/magic-pdf/index.ts +1 -0
- package/src/features/magic-pdf/types.ts +1 -0
- package/src/features/magic-pdf/useResizeOnDrag.ts +42 -0
- package/src/features/store/collections/BrowseCollectionView.tsx +45 -0
- package/src/features/store/collections/CollectionView.tsx +94 -0
- package/src/features/store/collections/CollectionsTable.tsx +115 -0
- package/src/features/store/collections/CollectionsView.tsx +166 -0
- package/src/features/store/collections/EditCollectionView.tsx +253 -0
- package/src/features/store/collections/index.ts +5 -0
- package/src/features/store/index.ts +3 -0
- package/src/features/store/objects/DocumentPreviewPanel.tsx +417 -0
- package/src/features/store/objects/DocumentSearchResults.tsx +209 -0
- package/src/features/store/objects/DocumentSelectionProvider.tsx +99 -0
- package/src/features/store/objects/DocumentTable.tsx +409 -0
- package/src/features/store/objects/ExportPropertiesModal.tsx +89 -0
- package/src/features/store/objects/components/ContentDispositionButton.tsx +45 -0
- package/src/features/store/objects/components/ContentOverview.tsx +466 -0
- package/src/features/store/objects/components/DocumentIcon.tsx +87 -0
- package/src/features/store/objects/components/DocumentInput.tsx +90 -0
- package/src/features/store/objects/components/PropertiesEditorModal.tsx +253 -0
- package/src/features/store/objects/components/SaveVersionConfirmModal.tsx +136 -0
- package/src/features/store/objects/components/SelectDocument.tsx +69 -0
- package/src/features/store/objects/components/SelectDocumentModal.tsx +20 -0
- package/src/features/store/objects/components/VectorSearchWidget.tsx +115 -0
- package/src/features/store/objects/components/index.ts +9 -0
- package/src/features/store/objects/components/useDownloadObject.ts +24 -0
- package/src/features/store/objects/index.ts +10 -0
- package/src/features/store/objects/layout/DocumentTableColumn.tsx +84 -0
- package/src/features/store/objects/layout/documentLayout.tsx +69 -0
- package/src/features/store/objects/layout/index.ts +2 -0
- package/src/features/store/objects/layout/knowledge.md +238 -0
- package/src/features/store/objects/layout/renderers.tsx +139 -0
- package/src/features/store/objects/search/DocumentSearchContext.ts +181 -0
- package/src/features/store/objects/search/DocumentSearchProvider.tsx +54 -0
- package/src/features/store/objects/search/index.ts +2 -0
- package/src/features/store/objects/selection/ObjectsActionContext.tsx +196 -0
- package/src/features/store/objects/selection/ObjectsActionSpec.ts +31 -0
- package/src/features/store/objects/selection/SelectionActions.tsx +160 -0
- package/src/features/store/objects/selection/actions/AddToCollectionAction.tsx +114 -0
- package/src/features/store/objects/selection/actions/ChangeTypeAction.tsx +76 -0
- package/src/features/store/objects/selection/actions/ConfirmAction.tsx +46 -0
- package/src/features/store/objects/selection/actions/DeleteObjectsAction.tsx +77 -0
- package/src/features/store/objects/selection/actions/ExportPropertiesAction.tsx +117 -0
- package/src/features/store/objects/selection/actions/RemoveFromCollectionAction.tsx +77 -0
- package/src/features/store/objects/selection/actions/StartWorkflowComponent.tsx +122 -0
- package/src/features/store/objects/selection/actions/index.ts +7 -0
- package/src/features/store/objects/selection/index.ts +4 -0
- package/src/features/store/objects/upload/DocumentUploadModal.tsx +970 -0
- package/src/features/store/objects/upload/index.ts +3 -0
- package/src/features/store/objects/upload/useSmartFileUploadProcessing.ts +250 -0
- package/src/features/store/objects/upload/useUploadHandler.ts +325 -0
- package/src/features/store/types/ContentObjectTypeView.tsx +244 -0
- package/src/features/store/types/ContentObjectTypesSearch.tsx +111 -0
- package/src/features/store/types/ContentObjectTypesTable.tsx +38 -0
- package/src/features/store/types/ContentObjectTypesView.tsx +71 -0
- package/src/features/store/types/CreateOrUpdateTypeModal.tsx +70 -0
- package/src/features/store/types/ObjectSchemaEditor.tsx +127 -0
- package/src/features/store/types/SelectContentType.tsx +88 -0
- package/src/features/store/types/SelectContentTypeModal.tsx +142 -0
- package/src/features/store/types/TableLayoutEditor.tsx +104 -0
- package/src/features/store/types/index.ts +10 -0
- package/src/features/store/types/search/ObjectTypeSearchContext.tsx +119 -0
- package/src/features/store/types/search/ObjectTypeSearchProvider.tsx +24 -0
- package/src/features/store/types/search/index.ts +2 -0
- package/src/features/user/UserAvatar.tsx +34 -0
- package/src/features/user/UserInfo.tsx +215 -0
- package/src/features/user/index.ts +2 -0
- package/src/features/utils/index.ts +3 -0
- package/src/features/utils/mimeType.ts +9 -0
- package/src/features/utils/rendition.ts +75 -0
- package/src/features/utils/text.ts +10 -0
- package/src/layout/FullHeightLayout.tsx +1 -1
- package/src/layout/Sidebar.tsx +12 -2
- package/src/widgets/Progress.tsx +10 -0
- package/src/widgets/codemirror/CodeMirrorEditor.tsx +1 -1
- package/src/widgets/form/Form.tsx +2 -2
- package/src/widgets/form/schema.ts +14 -7
- package/src/widgets/index.ts +5 -1
- package/src/widgets/popover/Popover.tsx +171 -0
- package/src/widgets/popover/context.ts +15 -0
- package/src/widgets/popover/index.ts +2 -0
- package/src/widgets/popover/slots.ts +24 -0
- package/src/widgets/properties/PropertiesView.tsx +26 -0
- package/src/widgets/properties/index.ts +1 -0
- package/src/widgets/schema-editor/JSONSchemaEditorModal.tsx +1 -2
- package/src/widgets/schema-editor/editor/Editable.tsx +12 -13
- package/src/widgets/schema-editor/editor/PropertyViewer.tsx +1 -1
- package/src/widgets/schema-editor/editor/SchemaEditor.tsx +4 -4
- package/src/widgets/upload/DropZone.tsx +257 -0
- package/src/widgets/upload/UploadResultCategory.tsx +81 -0
- package/src/widgets/upload/UploadSummary.tsx +116 -0
- package/src/widgets/upload/index.ts +3 -0
- package/lib/esm/code/index.js +0 -3
- package/lib/esm/code/index.js.map +0 -1
- package/lib/esm/core/components/Input.js +0 -16
- package/lib/esm/core/components/Input.js.map +0 -1
- package/lib/esm/form/index.js +0 -3
- package/lib/esm/form/index.js.map +0 -1
- package/lib/types/code/index.d.ts +0 -0
- package/lib/types/core/components/Input.d.ts +0 -8
- package/lib/types/form/index.d.ts +0 -0
- package/lib/vertesia-ui-code.js +0 -2
- package/lib/vertesia-ui-code.js.map +0 -1
- package/lib/vertesia-ui-form.js +0 -2
- package/lib/vertesia-ui-form.js.map +0 -1
- package/src/code/index.ts +0 -1
- package/src/core/components/Input.tsx +0 -43
- package/src/form/index.ts +0 -1
|
@@ -0,0 +1,970 @@
|
|
|
1
|
+
import { Collection, ContentObjectTypeItem, DynamicCollection } from "@vertesia/common";
|
|
2
|
+
import { Button, Modal, ModalBody, ModalFooter, ModalTitle, SelectBox, Spinner, useToast } from "@vertesia/ui/core";
|
|
3
|
+
import { useUserSession } from "@vertesia/ui/session";
|
|
4
|
+
import { DropZone, UploadSummary } from '@vertesia/ui/widgets';
|
|
5
|
+
import { AlertCircleIcon, CheckCircleIcon, FileIcon, FolderIcon, UploadIcon, XCircleIcon } from "lucide-react";
|
|
6
|
+
import { ReactNode, useEffect, useMemo, useState } from "react";
|
|
7
|
+
import { FileUploadAction, FileWithMetadata, useSmartFileUploadProcessing } from "./useSmartFileUploadProcessing";
|
|
8
|
+
import { DocumentUploadResult } from "./useUploadHandler";
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* File upload status for tracking individual files during upload
|
|
13
|
+
*/
|
|
14
|
+
interface FileUploadStatus {
|
|
15
|
+
file: File;
|
|
16
|
+
status: "pending" | "uploading" | "success" | "error";
|
|
17
|
+
progress: number;
|
|
18
|
+
message?: string;
|
|
19
|
+
id?: string;
|
|
20
|
+
// Track whether this was an update, skip, or new creation
|
|
21
|
+
action?: "create" | "update" | "skip";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Props for the unified UploadModal component
|
|
26
|
+
*/
|
|
27
|
+
interface DocumentUploadModalProps {
|
|
28
|
+
/** Whether the modal is open */
|
|
29
|
+
isOpen: boolean;
|
|
30
|
+
/** Callback when the modal is closed */
|
|
31
|
+
onClose: () => void;
|
|
32
|
+
/** Optional initial files to upload */
|
|
33
|
+
files?: File[];
|
|
34
|
+
/** Collection ID to upload to */
|
|
35
|
+
collectionId?: string;
|
|
36
|
+
/** Selected folder for uploaded files */
|
|
37
|
+
selectedFolder?: string | null;
|
|
38
|
+
/** Title for the modal */
|
|
39
|
+
title?: string;
|
|
40
|
+
/** Children to render in the modal */
|
|
41
|
+
children?: ReactNode;
|
|
42
|
+
/** Callback when upload is complete */
|
|
43
|
+
onUploadComplete?: (result: DocumentUploadResult) => void;
|
|
44
|
+
/** Hide the file selection step and proceed directly to type selection */
|
|
45
|
+
hideFileSelection?: boolean;
|
|
46
|
+
/** Show only the type selection, used for type change operations */
|
|
47
|
+
showTypeSelectionOnly?: boolean;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Unified upload modal that handles the complete upload process:
|
|
52
|
+
* 1. File selection (if no files provided)
|
|
53
|
+
* 2. Smart file processing to detect duplicates
|
|
54
|
+
* 3. Type selection
|
|
55
|
+
* 4. Upload with progress tracking
|
|
56
|
+
* 5. Result display
|
|
57
|
+
*/
|
|
58
|
+
export function DocumentUploadModal({
|
|
59
|
+
isOpen,
|
|
60
|
+
onClose,
|
|
61
|
+
files: initialFiles,
|
|
62
|
+
collectionId,
|
|
63
|
+
selectedFolder,
|
|
64
|
+
title = "Upload Files",
|
|
65
|
+
children,
|
|
66
|
+
onUploadComplete,
|
|
67
|
+
hideFileSelection = false,
|
|
68
|
+
showTypeSelectionOnly = false,
|
|
69
|
+
}: DocumentUploadModalProps) {
|
|
70
|
+
const { client, typeRegistry } = useUserSession();
|
|
71
|
+
const toast = useToast();
|
|
72
|
+
const [files, setFiles] = useState<File[]>([]);
|
|
73
|
+
const [processedFiles, setProcessedFiles] = useState<FileWithMetadata[]>([]);
|
|
74
|
+
const [processingDone, setProcessingDone] = useState(false);
|
|
75
|
+
const [selectedType, setSelectedType] = useState<ContentObjectTypeItem | null>(null);
|
|
76
|
+
const [fileStatuses, setFileStatuses] = useState<FileUploadStatus[]>([]);
|
|
77
|
+
const [isUploading, setIsUploading] = useState(false);
|
|
78
|
+
const [uploadComplete, setUploadComplete] = useState(false);
|
|
79
|
+
const [overallProgress, setOverallProgress] = useState(0);
|
|
80
|
+
const [modalKey, setModalKey] = useState(Date.now());
|
|
81
|
+
const [collectionData, setCollectionData] = useState<Collection | DynamicCollection | undefined>(undefined);
|
|
82
|
+
|
|
83
|
+
// Fetch collection details if a collectionId is provided
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
if (!collectionId) return;
|
|
86
|
+
client.store.collections.retrieve(collectionId).then(setCollectionData);
|
|
87
|
+
}, [collectionId]);
|
|
88
|
+
|
|
89
|
+
// Helper function to render collection and folder information
|
|
90
|
+
const renderLocationInfo = () => {
|
|
91
|
+
if (!collectionData && !selectedFolder) return null;
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<div className="mb-4 p-3 bg-blue-50 rounded-md border border-blue-100">
|
|
95
|
+
<div className="flex items-center text-blue-700">
|
|
96
|
+
<FolderIcon className="h-5 w-5 mr-2" />
|
|
97
|
+
<span className="font-medium">Upload Location:</span>
|
|
98
|
+
</div>
|
|
99
|
+
<div className="ml-7 text-sm text-blue-700 mt-1">
|
|
100
|
+
{collectionData && (
|
|
101
|
+
<div className="flex items-center">
|
|
102
|
+
<span className="mr-1">Collection:</span>
|
|
103
|
+
<span className="font-medium">{collectionData.name}</span>
|
|
104
|
+
</div>
|
|
105
|
+
)}
|
|
106
|
+
{selectedFolder && (
|
|
107
|
+
<div className="flex items-center mt-1">
|
|
108
|
+
<span className="mr-1">Folder:</span>
|
|
109
|
+
<span className="font-medium">{selectedFolder}</span>
|
|
110
|
+
</div>
|
|
111
|
+
)}
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Statistics for upload processing
|
|
118
|
+
const [processingStats, setProcessingStats] = useState<{
|
|
119
|
+
toCreate: number;
|
|
120
|
+
toUpdate: number;
|
|
121
|
+
toSkip: number;
|
|
122
|
+
}>({ toCreate: 0, toUpdate: 0, toSkip: 0 });
|
|
123
|
+
|
|
124
|
+
// Get the smart file processing utility
|
|
125
|
+
const { checkDocumentProcessing } = useSmartFileUploadProcessing();
|
|
126
|
+
|
|
127
|
+
// Get available types from the registry
|
|
128
|
+
const types = useMemo(() => {
|
|
129
|
+
return typeRegistry?.types || [];
|
|
130
|
+
}, [typeRegistry?.types]);
|
|
131
|
+
|
|
132
|
+
// Reset state when modal opens/closes
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
if (isOpen) {
|
|
135
|
+
// Set initial files if provided
|
|
136
|
+
if (initialFiles && initialFiles.length > 0) {
|
|
137
|
+
setFiles(initialFiles);
|
|
138
|
+
processFiles(initialFiles);
|
|
139
|
+
} else {
|
|
140
|
+
// Reset state
|
|
141
|
+
setFiles([]);
|
|
142
|
+
setProcessedFiles([]);
|
|
143
|
+
setProcessingDone(false);
|
|
144
|
+
setSelectedType(null);
|
|
145
|
+
setFileStatuses([]);
|
|
146
|
+
setIsUploading(false);
|
|
147
|
+
setUploadComplete(false);
|
|
148
|
+
setOverallProgress(0);
|
|
149
|
+
setProcessingStats({ toCreate: 0, toUpdate: 0, toSkip: 0 });
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Create a new key to ensure the modal is fresh
|
|
153
|
+
setModalKey(Date.now());
|
|
154
|
+
}
|
|
155
|
+
}, [isOpen, initialFiles]);
|
|
156
|
+
|
|
157
|
+
// Complete cleanup when modal closes
|
|
158
|
+
const handleClose = () => {
|
|
159
|
+
// Reset all state to initial values to prevent memory leaks
|
|
160
|
+
setFiles([]);
|
|
161
|
+
setProcessedFiles([]);
|
|
162
|
+
setProcessingDone(false);
|
|
163
|
+
setSelectedType(null);
|
|
164
|
+
setFileStatuses([]);
|
|
165
|
+
setIsUploading(false);
|
|
166
|
+
setUploadComplete(false);
|
|
167
|
+
setOverallProgress(0);
|
|
168
|
+
setProcessingStats({ toCreate: 0, toUpdate: 0, toSkip: 0 });
|
|
169
|
+
|
|
170
|
+
// Call the provided onClose function
|
|
171
|
+
onClose();
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// Handle file drop/selection
|
|
175
|
+
const handleFileSelect = (newFiles: File[]) => {
|
|
176
|
+
if (newFiles && newFiles.length > 0) {
|
|
177
|
+
setFiles(newFiles);
|
|
178
|
+
processFiles(newFiles);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// Process files to determine create/update/skip status
|
|
183
|
+
const processFiles = async (filesToProcess: File[]) => {
|
|
184
|
+
if (!filesToProcess.length) return;
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
console.log(`Processing ${filesToProcess.length} files to determine required actions...`);
|
|
188
|
+
|
|
189
|
+
// Get the document processing results
|
|
190
|
+
const processed = await checkDocumentProcessing(filesToProcess, selectedFolder, collectionId);
|
|
191
|
+
setProcessedFiles(processed);
|
|
192
|
+
|
|
193
|
+
// Count files by action
|
|
194
|
+
const toCreate = processed.filter((f) => f.action === FileUploadAction.CREATE).length;
|
|
195
|
+
const toUpdate = processed.filter((f) => f.action === FileUploadAction.UPDATE).length;
|
|
196
|
+
const toSkip = processed.filter((f) => f.action === FileUploadAction.SKIP).length;
|
|
197
|
+
|
|
198
|
+
// Update stats for UI feedback
|
|
199
|
+
setProcessingStats({
|
|
200
|
+
toCreate,
|
|
201
|
+
toUpdate,
|
|
202
|
+
toSkip,
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// Show processing results to user
|
|
206
|
+
toast({
|
|
207
|
+
title: "Files analyzed",
|
|
208
|
+
description: `${filesToProcess.length} file(s): ${toCreate} new, ${toUpdate} to update, ${toSkip} to skip`,
|
|
209
|
+
status: "info",
|
|
210
|
+
duration: 4000,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Set processing as complete
|
|
214
|
+
setProcessingDone(true);
|
|
215
|
+
} catch (error) {
|
|
216
|
+
console.error("Error processing files:", error);
|
|
217
|
+
toast({
|
|
218
|
+
title: "Error",
|
|
219
|
+
description: "There was an error analyzing the files",
|
|
220
|
+
status: "error",
|
|
221
|
+
duration: 5000,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
// Handle type selection and start the upload
|
|
227
|
+
const handleUpload = async () => {
|
|
228
|
+
if (!processedFiles.length) return;
|
|
229
|
+
|
|
230
|
+
const typeId = selectedType?.id || null;
|
|
231
|
+
|
|
232
|
+
// Initialize file statuses
|
|
233
|
+
const initialStatuses = processedFiles.map((fileInfo) => ({
|
|
234
|
+
file: fileInfo.file,
|
|
235
|
+
status: "pending" as const,
|
|
236
|
+
progress: 0,
|
|
237
|
+
action:
|
|
238
|
+
fileInfo.action === FileUploadAction.CREATE
|
|
239
|
+
? ("create" as const)
|
|
240
|
+
: fileInfo.action === FileUploadAction.UPDATE
|
|
241
|
+
? ("update" as const)
|
|
242
|
+
: ("skip" as const),
|
|
243
|
+
}));
|
|
244
|
+
|
|
245
|
+
setFileStatuses(initialStatuses);
|
|
246
|
+
setIsUploading(true);
|
|
247
|
+
setUploadComplete(false);
|
|
248
|
+
|
|
249
|
+
// Process files in batches
|
|
250
|
+
const filesToSkip = processedFiles.filter((f) => f.action === FileUploadAction.SKIP);
|
|
251
|
+
const filesToUpdate = processedFiles.filter((f) => f.action === FileUploadAction.UPDATE);
|
|
252
|
+
const filesToCreate = processedFiles.filter((f) => f.action === FileUploadAction.CREATE);
|
|
253
|
+
|
|
254
|
+
const result: DocumentUploadResult = {
|
|
255
|
+
success: true,
|
|
256
|
+
objectIds: [],
|
|
257
|
+
uploadedFiles: [],
|
|
258
|
+
skippedFiles: [],
|
|
259
|
+
failedFiles: [],
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
// Process SKIP files
|
|
263
|
+
for (const fileInfo of filesToSkip) {
|
|
264
|
+
if (fileInfo.existingId) {
|
|
265
|
+
result.objectIds.push(fileInfo.existingId);
|
|
266
|
+
result.skippedFiles.push({
|
|
267
|
+
id: fileInfo.existingId,
|
|
268
|
+
name: fileInfo.name,
|
|
269
|
+
type: typeId,
|
|
270
|
+
status: "skipped",
|
|
271
|
+
location: fileInfo.location,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// Update the file status
|
|
275
|
+
setFileStatuses((current) =>
|
|
276
|
+
current.map((status) =>
|
|
277
|
+
status.file === fileInfo.file
|
|
278
|
+
? { ...status, status: "success", progress: 100, id: fileInfo.existingId }
|
|
279
|
+
: status,
|
|
280
|
+
),
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Process files in batches of 50
|
|
286
|
+
const BATCH_SIZE = 50;
|
|
287
|
+
|
|
288
|
+
// Helper function to process a batch of files
|
|
289
|
+
const processBatch = async (files: FileWithMetadata[], action: "create" | "update") => {
|
|
290
|
+
const batches = [];
|
|
291
|
+
for (let i = 0; i < files.length; i += BATCH_SIZE) {
|
|
292
|
+
batches.push(files.slice(i, i + BATCH_SIZE));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
for (let batchIndex = 0; batchIndex < batches.length; batchIndex++) {
|
|
296
|
+
const batch = batches[batchIndex];
|
|
297
|
+
console.log(`Processing ${action} batch ${batchIndex + 1}/${batches.length} (${batch.length} files)`);
|
|
298
|
+
|
|
299
|
+
// Show progress for larger file sets
|
|
300
|
+
if (files.length > BATCH_SIZE) {
|
|
301
|
+
const processedCount = batchIndex * BATCH_SIZE;
|
|
302
|
+
toast({
|
|
303
|
+
title: `Processing files (${action})`,
|
|
304
|
+
description: `Processed ${processedCount}/${files.length} files...`,
|
|
305
|
+
status: "info",
|
|
306
|
+
duration: 2000,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Process the batch
|
|
311
|
+
await Promise.all(
|
|
312
|
+
batch.map(async (fileInfo) => {
|
|
313
|
+
try {
|
|
314
|
+
// Update status to uploading
|
|
315
|
+
setFileStatuses((current) =>
|
|
316
|
+
current.map((status) =>
|
|
317
|
+
status.file === fileInfo.file
|
|
318
|
+
? { ...status, status: "uploading", progress: 20 }
|
|
319
|
+
: status,
|
|
320
|
+
),
|
|
321
|
+
);
|
|
322
|
+
|
|
323
|
+
if (action === "update" && fileInfo.existingId) {
|
|
324
|
+
// Update existing file
|
|
325
|
+
await client.store.objects.update(
|
|
326
|
+
fileInfo.existingId,
|
|
327
|
+
{
|
|
328
|
+
type: typeId || undefined,
|
|
329
|
+
content: fileInfo.file,
|
|
330
|
+
location: fileInfo.location,
|
|
331
|
+
name: fileInfo.name,
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
createRevision: true,
|
|
335
|
+
revisionLabel: "upload on " + new Date().toISOString(),
|
|
336
|
+
},
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
// Update status to success
|
|
340
|
+
setFileStatuses((current) =>
|
|
341
|
+
current.map((status) =>
|
|
342
|
+
status.file === fileInfo.file
|
|
343
|
+
? { ...status, status: "success", progress: 100, id: fileInfo.existingId }
|
|
344
|
+
: status,
|
|
345
|
+
),
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
// Add to result
|
|
349
|
+
result.objectIds.push(fileInfo.existingId);
|
|
350
|
+
result.uploadedFiles.push({
|
|
351
|
+
id: fileInfo.existingId,
|
|
352
|
+
name: fileInfo.name,
|
|
353
|
+
type: typeId,
|
|
354
|
+
status: "updated",
|
|
355
|
+
location: fileInfo.location,
|
|
356
|
+
});
|
|
357
|
+
} else {
|
|
358
|
+
// Create new file
|
|
359
|
+
const createResult = await client.store.objects.create(
|
|
360
|
+
{
|
|
361
|
+
type: typeId || undefined,
|
|
362
|
+
content: fileInfo.file,
|
|
363
|
+
location:
|
|
364
|
+
fileInfo.location || fileInfo.file.webkitRelativePath || fileInfo.name,
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
collection_id: collectionId,
|
|
368
|
+
},
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
// Update status to success
|
|
372
|
+
setFileStatuses((current) =>
|
|
373
|
+
current.map((status) =>
|
|
374
|
+
status.file === fileInfo.file
|
|
375
|
+
? { ...status, status: "success", progress: 100, id: createResult.id }
|
|
376
|
+
: status,
|
|
377
|
+
),
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
// Add to result
|
|
381
|
+
result.objectIds.push(createResult.id);
|
|
382
|
+
result.uploadedFiles.push({
|
|
383
|
+
id: createResult.id,
|
|
384
|
+
name: fileInfo.name,
|
|
385
|
+
type: typeId,
|
|
386
|
+
status: "created",
|
|
387
|
+
location: fileInfo.location,
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
} catch (error: any) {
|
|
391
|
+
console.error(`Failed to process file ${fileInfo.name}:`, error);
|
|
392
|
+
|
|
393
|
+
// Update status to error
|
|
394
|
+
setFileStatuses((current) =>
|
|
395
|
+
current.map((status) =>
|
|
396
|
+
status.file === fileInfo.file
|
|
397
|
+
? {
|
|
398
|
+
...status,
|
|
399
|
+
status: "error",
|
|
400
|
+
progress: 100,
|
|
401
|
+
message: error.message || "Unknown error",
|
|
402
|
+
}
|
|
403
|
+
: status,
|
|
404
|
+
),
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
// Add to failed result
|
|
408
|
+
result.failedFiles.push({
|
|
409
|
+
name: fileInfo.name,
|
|
410
|
+
error: error.message || "Unknown error",
|
|
411
|
+
status: "failed",
|
|
412
|
+
location: fileInfo.location,
|
|
413
|
+
type: typeId,
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
// Mark the overall success as false if any file fails
|
|
417
|
+
result.success = false;
|
|
418
|
+
}
|
|
419
|
+
}),
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
// Calculate overall progress after each batch completion
|
|
423
|
+
const completedFiles = fileStatuses.filter(
|
|
424
|
+
(f) => f.status === "success" || f.status === "error",
|
|
425
|
+
).length;
|
|
426
|
+
const totalFiles = fileStatuses.length;
|
|
427
|
+
const progress = Math.round((completedFiles / totalFiles) * 100);
|
|
428
|
+
setOverallProgress(progress);
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
// Process UPDATE files first, then CREATE files
|
|
433
|
+
if (filesToUpdate.length > 0) {
|
|
434
|
+
await processBatch(filesToUpdate, "update");
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (filesToCreate.length > 0) {
|
|
438
|
+
await processBatch(filesToCreate, "create");
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Finalize the upload
|
|
442
|
+
// Ensure all files are accounted for before completing
|
|
443
|
+
setFileStatuses((current) => {
|
|
444
|
+
// Check for any pending files that might have been missed
|
|
445
|
+
const missingStatuses = current
|
|
446
|
+
.filter((status) => status.status === "pending")
|
|
447
|
+
.map((status) => ({
|
|
448
|
+
...status,
|
|
449
|
+
status: "error" as const,
|
|
450
|
+
progress: 100,
|
|
451
|
+
message: "Upload process interrupted",
|
|
452
|
+
}));
|
|
453
|
+
|
|
454
|
+
if (missingStatuses.length > 0) {
|
|
455
|
+
// Add missing files to the failed files list
|
|
456
|
+
missingStatuses.forEach((status) => {
|
|
457
|
+
result.failedFiles.push({
|
|
458
|
+
name: status.file.name,
|
|
459
|
+
error: "Upload process interrupted",
|
|
460
|
+
status: "failed",
|
|
461
|
+
type: selectedType?.id || null,
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
// Update the success flag if any files failed
|
|
466
|
+
result.success = false;
|
|
467
|
+
|
|
468
|
+
// Return updated statuses
|
|
469
|
+
return current.map((status) =>
|
|
470
|
+
status.status === "pending"
|
|
471
|
+
? {
|
|
472
|
+
...status,
|
|
473
|
+
status: "error" as const,
|
|
474
|
+
progress: 100,
|
|
475
|
+
message: "Upload process interrupted",
|
|
476
|
+
}
|
|
477
|
+
: status,
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
return current;
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
setIsUploading(false);
|
|
485
|
+
setUploadComplete(true);
|
|
486
|
+
|
|
487
|
+
// Show summary toast
|
|
488
|
+
const createdCount = result.uploadedFiles.filter((f) => f.status === "created").length;
|
|
489
|
+
const updatedCount = result.uploadedFiles.filter((f) => f.status === "updated").length;
|
|
490
|
+
const skippedCount = result.skippedFiles.length;
|
|
491
|
+
const failedCount = result.failedFiles.length;
|
|
492
|
+
|
|
493
|
+
let statusMessage = "";
|
|
494
|
+
if (createdCount > 0) statusMessage += `${createdCount} file${createdCount !== 1 ? "s" : ""} uploaded`;
|
|
495
|
+
if (updatedCount > 0) {
|
|
496
|
+
statusMessage += statusMessage ? ", " : "";
|
|
497
|
+
statusMessage += `${updatedCount} file${updatedCount !== 1 ? "s" : ""} updated`;
|
|
498
|
+
}
|
|
499
|
+
if (skippedCount > 0) {
|
|
500
|
+
statusMessage += statusMessage ? ", " : "";
|
|
501
|
+
statusMessage += `${skippedCount} file${skippedCount !== 1 ? "s" : ""} skipped`;
|
|
502
|
+
}
|
|
503
|
+
if (failedCount > 0) {
|
|
504
|
+
statusMessage += statusMessage ? ", " : "";
|
|
505
|
+
statusMessage += `${failedCount} file${failedCount !== 1 ? "s" : ""} failed`;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
toast({
|
|
509
|
+
title: "Upload Complete",
|
|
510
|
+
description: statusMessage,
|
|
511
|
+
status: failedCount > 0 ? "warning" : "success",
|
|
512
|
+
duration: 5000,
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
// Call the uploadComplete callback if provided
|
|
516
|
+
if (onUploadComplete) {
|
|
517
|
+
onUploadComplete(result);
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
// Determine what content to show based on the current state
|
|
522
|
+
const renderModalContent = () => {
|
|
523
|
+
// When showing only type selection, skip directly to the type selection UI
|
|
524
|
+
if (showTypeSelectionOnly) {
|
|
525
|
+
return (
|
|
526
|
+
<ModalBody className="p-6">
|
|
527
|
+
{children}
|
|
528
|
+
|
|
529
|
+
{/* Collection and folder information if available */}
|
|
530
|
+
{renderLocationInfo()}
|
|
531
|
+
|
|
532
|
+
{/* Type selection */}
|
|
533
|
+
<div className="mb-4">
|
|
534
|
+
<label className="block text-sm font-medium mb-2">
|
|
535
|
+
Content Type <span className="text-gray-500 font-normal">(Optional)</span>
|
|
536
|
+
</label>
|
|
537
|
+
<SelectBox
|
|
538
|
+
options={types}
|
|
539
|
+
value={selectedType}
|
|
540
|
+
optionLabel={(type) => (type ? type.name : "Select a content type")}
|
|
541
|
+
placeholder="Select a content type or leave empty for automatic detection"
|
|
542
|
+
onChange={(selected) => setSelectedType(selected === undefined ? null : selected)}
|
|
543
|
+
filterBy="name"
|
|
544
|
+
isClearable
|
|
545
|
+
/>
|
|
546
|
+
|
|
547
|
+
<div className="mt-2 text-sm text-blue-600 flex items-center">
|
|
548
|
+
<CheckCircleIcon className="h-4 w-4 mr-1" />
|
|
549
|
+
<span>
|
|
550
|
+
<strong>Type selection is optional.</strong> Leave empty to let Vertesia choose the
|
|
551
|
+
appropriate type
|
|
552
|
+
</span>
|
|
553
|
+
</div>
|
|
554
|
+
</div>
|
|
555
|
+
|
|
556
|
+
{selectedType ? (
|
|
557
|
+
<div className="text-sm text-gray-500 bg-gray-50 p-3 rounded-md mb-4">
|
|
558
|
+
<div className="font-medium">{selectedType.name}</div>
|
|
559
|
+
{selectedType.description && <div className="mt-1">{selectedType.description}</div>}
|
|
560
|
+
</div>
|
|
561
|
+
) : (
|
|
562
|
+
<div className="text-sm text-blue-600 bg-blue-50 p-3 rounded-md mb-4">
|
|
563
|
+
<div className="font-medium flex items-center">
|
|
564
|
+
<CheckCircleIcon className="h-5 w-5 mr-1" />
|
|
565
|
+
Automatic Type Detection
|
|
566
|
+
</div>
|
|
567
|
+
<div className="mt-1">
|
|
568
|
+
<p>
|
|
569
|
+
<strong>
|
|
570
|
+
Vertesia will analyze the content and select the most appropriate type.
|
|
571
|
+
</strong>
|
|
572
|
+
</p>
|
|
573
|
+
<p className="mt-1">
|
|
574
|
+
This is recommended for most uploads and ensures optimal processing.
|
|
575
|
+
</p>
|
|
576
|
+
</div>
|
|
577
|
+
</div>
|
|
578
|
+
)}
|
|
579
|
+
</ModalBody>
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// Step 1: File selection
|
|
584
|
+
if (files.length === 0 && !hideFileSelection) {
|
|
585
|
+
return (
|
|
586
|
+
<ModalBody className="flex flex-col items-center justify-center p-8">
|
|
587
|
+
{/* Collection and folder information if available */}
|
|
588
|
+
{renderLocationInfo()}
|
|
589
|
+
|
|
590
|
+
<DropZone
|
|
591
|
+
onDrop={handleFileSelect}
|
|
592
|
+
message="Drag and drop files here or click to select"
|
|
593
|
+
buttonLabel="Select Files"
|
|
594
|
+
className="w-full h-64"
|
|
595
|
+
/>
|
|
596
|
+
{children}
|
|
597
|
+
</ModalBody>
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// Step 2: File processing and type selection
|
|
602
|
+
if (!isUploading && !uploadComplete) {
|
|
603
|
+
return (
|
|
604
|
+
<ModalBody className="p-6">
|
|
605
|
+
{!processingDone ? (
|
|
606
|
+
// File processing in progress
|
|
607
|
+
<div className="flex flex-col items-center justify-center py-8">
|
|
608
|
+
<Spinner size="lg" className="mb-4" />
|
|
609
|
+
<div className="text-lg font-medium">Analyzing files...</div>
|
|
610
|
+
<div className="text-sm text-muted mt-2">
|
|
611
|
+
Checking for duplicates and updates
|
|
612
|
+
</div>
|
|
613
|
+
</div>
|
|
614
|
+
) : (
|
|
615
|
+
// Processing complete, show type selection
|
|
616
|
+
<>
|
|
617
|
+
{/* Collection and folder information if available */}
|
|
618
|
+
{renderLocationInfo()}
|
|
619
|
+
|
|
620
|
+
<div className="mb-4">
|
|
621
|
+
<div className="flex justify-between items-center mb-2">
|
|
622
|
+
<div className="text-lg font-medium">File Analysis Results</div>
|
|
623
|
+
<div className="text-sm text-muted">
|
|
624
|
+
{files.length} file{files.length !== 1 ? "s" : ""}
|
|
625
|
+
</div>
|
|
626
|
+
</div>
|
|
627
|
+
|
|
628
|
+
{/* File statistics */}
|
|
629
|
+
<div className="bg-color-muted/10 p-4 rounded-md mb-4">
|
|
630
|
+
<div className="grid grid-cols-3 gap-4">
|
|
631
|
+
<div className="flex flex-col items-center">
|
|
632
|
+
<div className="flex items-center">
|
|
633
|
+
<UploadIcon className="h-5 w-5 text-blue-500 mr-2" />
|
|
634
|
+
<span className="font-medium">New</span>
|
|
635
|
+
</div>
|
|
636
|
+
<div className="text-2xl font-semibold">{processingStats.toCreate}</div>
|
|
637
|
+
</div>
|
|
638
|
+
<div className="flex flex-col items-center">
|
|
639
|
+
<div className="flex items-center">
|
|
640
|
+
<CheckCircleIcon className="h-5 w-5 text-green-500 mr-2" />
|
|
641
|
+
<span className="font-medium">Update</span>
|
|
642
|
+
</div>
|
|
643
|
+
<div className="text-2xl font-semibold">{processingStats.toUpdate}</div>
|
|
644
|
+
</div>
|
|
645
|
+
<div className="flex flex-col items-center">
|
|
646
|
+
<div className="flex items-center">
|
|
647
|
+
<AlertCircleIcon className="h-5 w-5 text-yellow-500 mr-2" />
|
|
648
|
+
<span className="font-medium">Skip</span>
|
|
649
|
+
</div>
|
|
650
|
+
<div className="text-2xl font-semibold">{processingStats.toSkip}</div>
|
|
651
|
+
</div>
|
|
652
|
+
</div>
|
|
653
|
+
</div>
|
|
654
|
+
</div>
|
|
655
|
+
|
|
656
|
+
{/* Type selection */}
|
|
657
|
+
<div className="mb-4">
|
|
658
|
+
<label className="block text-sm font-medium mb-2">
|
|
659
|
+
Content Type <span className="text-gray-500 font-normal">(Optional)</span>
|
|
660
|
+
</label>
|
|
661
|
+
<SelectBox
|
|
662
|
+
options={types}
|
|
663
|
+
value={selectedType}
|
|
664
|
+
optionLabel={(type) => (type ? type.name : "Select a content type")}
|
|
665
|
+
placeholder="Select a content type or leave empty for automatic detection"
|
|
666
|
+
onChange={(selected) => setSelectedType(selected === undefined ? null : selected)}
|
|
667
|
+
filterBy="name"
|
|
668
|
+
isClearable
|
|
669
|
+
/>
|
|
670
|
+
|
|
671
|
+
<div className="mt-2 text-sm text-blue-600 flex items-center">
|
|
672
|
+
<CheckCircleIcon className="h-4 w-4 mr-1" />
|
|
673
|
+
<span>
|
|
674
|
+
<strong>Type selection is optional.</strong> Leave empty to let Vertesia choose
|
|
675
|
+
the appropriate type
|
|
676
|
+
</span>
|
|
677
|
+
</div>
|
|
678
|
+
</div>
|
|
679
|
+
|
|
680
|
+
{selectedType ? (
|
|
681
|
+
<div className="p-4 bg-gray-50 rounded-md border border-gray-100 mb-4">
|
|
682
|
+
<div className="font-medium mb-2">Files to process with selected type:</div>
|
|
683
|
+
<div className="text-sm">
|
|
684
|
+
{processingStats.toCreate + processingStats.toUpdate > 0 ? (
|
|
685
|
+
<div className="space-y-1">
|
|
686
|
+
<p>
|
|
687
|
+
{processingStats.toCreate + processingStats.toUpdate} file(s) ready
|
|
688
|
+
to process
|
|
689
|
+
{processingStats.toSkip > 0 &&
|
|
690
|
+
` (${processingStats.toSkip} will be skipped as they already exist)`}
|
|
691
|
+
</p>
|
|
692
|
+
<p className="text-green-600">
|
|
693
|
+
Files will be uploaded with type:{" "}
|
|
694
|
+
<strong>{selectedType.name}</strong>
|
|
695
|
+
</p>
|
|
696
|
+
{selectedType.description && (
|
|
697
|
+
<p className="text-gray-500 mt-1">{selectedType.description}</p>
|
|
698
|
+
)}
|
|
699
|
+
</div>
|
|
700
|
+
) : processingStats.toSkip > 0 ? (
|
|
701
|
+
<span>
|
|
702
|
+
All {processingStats.toSkip} file(s) already exist in the system and
|
|
703
|
+
will be skipped. You can proceed to view the results.
|
|
704
|
+
</span>
|
|
705
|
+
) : (
|
|
706
|
+
<span>No files to process.</span>
|
|
707
|
+
)}
|
|
708
|
+
</div>
|
|
709
|
+
</div>
|
|
710
|
+
) : (
|
|
711
|
+
<div className="p-4 bg-blue-50 rounded-md border border-blue-100 mb-4">
|
|
712
|
+
<div className="font-medium mb-2 flex items-center text-blue-700">
|
|
713
|
+
<CheckCircleIcon className="h-5 w-5 mr-1" />
|
|
714
|
+
Automatic Type Detection
|
|
715
|
+
</div>
|
|
716
|
+
<div className="text-sm text-blue-700">
|
|
717
|
+
{processingStats.toCreate + processingStats.toUpdate > 0 ? (
|
|
718
|
+
<div className="space-y-1">
|
|
719
|
+
<p>
|
|
720
|
+
{processingStats.toCreate + processingStats.toUpdate} file(s) ready
|
|
721
|
+
to process
|
|
722
|
+
{processingStats.toSkip > 0 &&
|
|
723
|
+
` (${processingStats.toSkip} will be skipped as they already exist)`}
|
|
724
|
+
</p>
|
|
725
|
+
<p className="mt-2">
|
|
726
|
+
<strong>
|
|
727
|
+
Vertesia will analyze each file and select the most appropriate
|
|
728
|
+
type.
|
|
729
|
+
</strong>
|
|
730
|
+
</p>
|
|
731
|
+
<p className="mt-1">
|
|
732
|
+
This is recommended for most uploads and ensures optimal processing.
|
|
733
|
+
</p>
|
|
734
|
+
</div>
|
|
735
|
+
) : processingStats.toSkip > 0 ? (
|
|
736
|
+
<span>
|
|
737
|
+
All {processingStats.toSkip} file(s) already exist in the system and
|
|
738
|
+
will be skipped. You can proceed to view the results.
|
|
739
|
+
</span>
|
|
740
|
+
) : (
|
|
741
|
+
<span>No files to process.</span>
|
|
742
|
+
)}
|
|
743
|
+
</div>
|
|
744
|
+
</div>
|
|
745
|
+
)}
|
|
746
|
+
</>
|
|
747
|
+
)}
|
|
748
|
+
</ModalBody>
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
// Step 3: Upload in progress
|
|
753
|
+
if (isUploading) {
|
|
754
|
+
return (
|
|
755
|
+
<ModalBody className="p-6">
|
|
756
|
+
{/* Collection and folder information if available */}
|
|
757
|
+
{renderLocationInfo()}
|
|
758
|
+
|
|
759
|
+
<div className="mb-4">
|
|
760
|
+
<div className="flex justify-between items-center mb-2">
|
|
761
|
+
<div className="text-lg font-medium">Uploading Files</div>
|
|
762
|
+
<div className="text-sm text-muted">
|
|
763
|
+
{Math.round(overallProgress)}% complete
|
|
764
|
+
</div>
|
|
765
|
+
</div>
|
|
766
|
+
|
|
767
|
+
{/* Progress bar */}
|
|
768
|
+
<div className="h-2 bg-color-muted/20 rounded-full overflow-hidden">
|
|
769
|
+
<div
|
|
770
|
+
className="h-full bg-color-primary rounded-full"
|
|
771
|
+
style={{ width: `${overallProgress}%` }}
|
|
772
|
+
/>
|
|
773
|
+
</div>
|
|
774
|
+
</div>
|
|
775
|
+
|
|
776
|
+
{/* File status list */}
|
|
777
|
+
<div className="max-h-96 overflow-y-auto">
|
|
778
|
+
{fileStatuses.map((fileStatus, index) => (
|
|
779
|
+
<div
|
|
780
|
+
key={`${fileStatus.file.name}-${index}`}
|
|
781
|
+
className="flex items-center py-2 border-b border-color-border last:border-b-0"
|
|
782
|
+
>
|
|
783
|
+
<div className="mr-3">
|
|
784
|
+
{fileStatus.status === "pending" && (
|
|
785
|
+
<FileIcon className="h-5 w-5 text-muted" />
|
|
786
|
+
)}
|
|
787
|
+
{fileStatus.status === "uploading" && <Spinner size="sm" />}
|
|
788
|
+
{fileStatus.status === "success" && (
|
|
789
|
+
<CheckCircleIcon className="h-5 w-5 text-green-500" />
|
|
790
|
+
)}
|
|
791
|
+
{fileStatus.status === "error" && <XCircleIcon className="h-5 w-5 text-red-500" />}
|
|
792
|
+
</div>
|
|
793
|
+
<div className="flex-1 min-w-0">
|
|
794
|
+
<div className="truncate font-medium">{fileStatus.file.name}</div>
|
|
795
|
+
<div className="text-xs text-muted">
|
|
796
|
+
{fileStatus.status === "pending" && "Waiting..."}
|
|
797
|
+
{fileStatus.status === "uploading" && "Uploading..."}
|
|
798
|
+
{fileStatus.status === "success" &&
|
|
799
|
+
(fileStatus.action === "create"
|
|
800
|
+
? "Created"
|
|
801
|
+
: fileStatus.action === "update"
|
|
802
|
+
? "Updated"
|
|
803
|
+
: "Skipped")}
|
|
804
|
+
{fileStatus.status === "error" && fileStatus.message}
|
|
805
|
+
</div>
|
|
806
|
+
</div>
|
|
807
|
+
</div>
|
|
808
|
+
))}
|
|
809
|
+
</div>
|
|
810
|
+
</ModalBody>
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
// Step 4: Upload complete, show results
|
|
815
|
+
return (
|
|
816
|
+
<ModalBody className="p-6">
|
|
817
|
+
<div className="mb-4">
|
|
818
|
+
<div className="text-lg font-medium mb-2">Upload Complete</div>
|
|
819
|
+
|
|
820
|
+
{/* Collection and folder information if available */}
|
|
821
|
+
{renderLocationInfo()}
|
|
822
|
+
|
|
823
|
+
<UploadSummary
|
|
824
|
+
files={fileStatuses.map((f) => {
|
|
825
|
+
// Map fileStatus to the expected ProcessedFile format
|
|
826
|
+
let status: "success" | "updated" | "skipped" | "failed";
|
|
827
|
+
|
|
828
|
+
if (f.status === "success") {
|
|
829
|
+
if (f.action === "create") {
|
|
830
|
+
status = "success";
|
|
831
|
+
} else if (f.action === "update") {
|
|
832
|
+
status = "updated";
|
|
833
|
+
} else {
|
|
834
|
+
status = "skipped";
|
|
835
|
+
}
|
|
836
|
+
} else {
|
|
837
|
+
status = "failed";
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
return {
|
|
841
|
+
name: f.file.name,
|
|
842
|
+
status,
|
|
843
|
+
error: f.status === "error" ? f.message : undefined,
|
|
844
|
+
};
|
|
845
|
+
})}
|
|
846
|
+
location={selectedFolder || undefined}
|
|
847
|
+
collection={collectionData?.name}
|
|
848
|
+
/>
|
|
849
|
+
</div>
|
|
850
|
+
</ModalBody>
|
|
851
|
+
);
|
|
852
|
+
};
|
|
853
|
+
|
|
854
|
+
const renderModalFooter = () => {
|
|
855
|
+
// Type-selection-only mode
|
|
856
|
+
if (showTypeSelectionOnly) {
|
|
857
|
+
return (
|
|
858
|
+
<ModalFooter>
|
|
859
|
+
<Button variant="ghost" onClick={handleClose}>
|
|
860
|
+
Cancel
|
|
861
|
+
</Button>
|
|
862
|
+
<Button
|
|
863
|
+
onClick={() => {
|
|
864
|
+
// Create minimal result with the selected type (or null)
|
|
865
|
+
const result: DocumentUploadResult = {
|
|
866
|
+
success: true,
|
|
867
|
+
objectIds: [],
|
|
868
|
+
uploadedFiles: [
|
|
869
|
+
{
|
|
870
|
+
name: "type-selection",
|
|
871
|
+
type: selectedType?.id || null,
|
|
872
|
+
status: "created",
|
|
873
|
+
},
|
|
874
|
+
],
|
|
875
|
+
skippedFiles: [],
|
|
876
|
+
failedFiles: [],
|
|
877
|
+
};
|
|
878
|
+
|
|
879
|
+
if (onUploadComplete) {
|
|
880
|
+
onUploadComplete(result);
|
|
881
|
+
}
|
|
882
|
+
handleClose();
|
|
883
|
+
}}
|
|
884
|
+
>
|
|
885
|
+
{selectedType ? `Use ${selectedType.name}` : "Use Automatic Type Detection"}
|
|
886
|
+
</Button>
|
|
887
|
+
</ModalFooter>
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// File selection step - only show cancel
|
|
892
|
+
if (files.length === 0 && !hideFileSelection) {
|
|
893
|
+
return (
|
|
894
|
+
<ModalFooter>
|
|
895
|
+
<Button variant="ghost" onClick={handleClose}>
|
|
896
|
+
Cancel
|
|
897
|
+
</Button>
|
|
898
|
+
</ModalFooter>
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// Processing and type selection step
|
|
903
|
+
if (!isUploading && !uploadComplete) {
|
|
904
|
+
// Allow upload even without a type (Vertesia will choose one)
|
|
905
|
+
const canUpload = processingDone;
|
|
906
|
+
|
|
907
|
+
return (
|
|
908
|
+
<ModalFooter>
|
|
909
|
+
<Button variant="ghost" onClick={handleClose}>
|
|
910
|
+
Cancel
|
|
911
|
+
</Button>
|
|
912
|
+
<Button
|
|
913
|
+
disabled={!canUpload}
|
|
914
|
+
onClick={handleUpload}
|
|
915
|
+
className={!selectedType ? "bg-blue-600 hover:bg-blue-700" : ""}
|
|
916
|
+
>
|
|
917
|
+
{processingStats.toCreate + processingStats.toUpdate > 0
|
|
918
|
+
? selectedType
|
|
919
|
+
? `Upload with ${selectedType.name}`
|
|
920
|
+
: "Upload with Automatic Type Detection"
|
|
921
|
+
: "Continue"}
|
|
922
|
+
</Button>
|
|
923
|
+
</ModalFooter>
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
// Upload in progress - can't cancel
|
|
928
|
+
if (isUploading) {
|
|
929
|
+
return (
|
|
930
|
+
<ModalFooter>
|
|
931
|
+
<Button variant="ghost" disabled>
|
|
932
|
+
Uploading...
|
|
933
|
+
</Button>
|
|
934
|
+
</ModalFooter>
|
|
935
|
+
);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// Upload complete - close or upload more
|
|
939
|
+
return (
|
|
940
|
+
<ModalFooter>
|
|
941
|
+
<Button
|
|
942
|
+
variant="ghost"
|
|
943
|
+
onClick={() => {
|
|
944
|
+
// Reset state and start over
|
|
945
|
+
setFiles([]);
|
|
946
|
+
setProcessedFiles([]);
|
|
947
|
+
setProcessingDone(false);
|
|
948
|
+
setSelectedType(null);
|
|
949
|
+
setFileStatuses([]);
|
|
950
|
+
setIsUploading(false);
|
|
951
|
+
setUploadComplete(false);
|
|
952
|
+
setOverallProgress(0);
|
|
953
|
+
setProcessingStats({ toCreate: 0, toUpdate: 0, toSkip: 0 });
|
|
954
|
+
}}
|
|
955
|
+
>
|
|
956
|
+
Upload More
|
|
957
|
+
</Button>
|
|
958
|
+
<Button onClick={handleClose}>Close</Button>
|
|
959
|
+
</ModalFooter>
|
|
960
|
+
);
|
|
961
|
+
};
|
|
962
|
+
|
|
963
|
+
return (
|
|
964
|
+
<Modal key={modalKey} isOpen={isOpen} onClose={handleClose} className="w-full max-w-3xl mx-auto">
|
|
965
|
+
<ModalTitle>{title}</ModalTitle>
|
|
966
|
+
{renderModalContent()}
|
|
967
|
+
{renderModalFooter()}
|
|
968
|
+
</Modal>
|
|
969
|
+
);
|
|
970
|
+
}
|