@multiplatform.one/frappe-ui 7.7.4 → 7.8.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/dist/cjs/ChartCard.native.js.map +1 -1
- package/dist/cjs/FileBrowser/AttachLibrary.native.js.map +1 -1
- package/dist/cjs/FileBrowser/folderTree.native.js.map +1 -1
- package/dist/cjs/FileBrowser/index.native.js.map +1 -1
- package/dist/cjs/FileBrowser/types.native.js.map +1 -1
- package/dist/cjs/FileBrowser/viewPersistence.native.js.map +1 -1
- package/dist/cjs/FormSidebar.native.js.map +1 -1
- package/dist/cjs/FrappeAssignment.cjs +1 -0
- package/dist/cjs/FrappeAssignment.native.js +1 -0
- package/dist/cjs/FrappeAssignment.native.js.map +1 -1
- package/dist/cjs/FrappeCalendar.cjs +22 -18
- package/dist/cjs/FrappeCalendar.native.js +24 -22
- package/dist/cjs/FrappeCalendar.native.js.map +1 -1
- package/dist/cjs/FrappeChartCard.cjs +1 -0
- package/dist/cjs/FrappeChartCard.native.js +1 -0
- package/dist/cjs/FrappeChartCard.native.js.map +1 -1
- package/dist/cjs/FrappeConnectionIndicator.native.js.map +1 -1
- package/dist/cjs/FrappeDashboard.cjs +1 -0
- package/dist/cjs/FrappeDashboard.native.js +1 -0
- package/dist/cjs/FrappeDashboard.native.js.map +1 -1
- package/dist/cjs/FrappeForm.cjs +3 -2
- package/dist/cjs/FrappeForm.native.js +4 -3
- package/dist/cjs/FrappeForm.native.js.map +1 -1
- package/dist/cjs/FrappeGantt.cjs +27 -35
- package/dist/cjs/FrappeGantt.native.js +29 -39
- package/dist/cjs/FrappeGantt.native.js.map +1 -1
- package/dist/cjs/FrappeImageView.cjs +6 -3
- package/dist/cjs/FrappeImageView.native.js +10 -5
- package/dist/cjs/FrappeImageView.native.js.map +1 -1
- package/dist/cjs/FrappeKPICard.cjs +27 -1
- package/dist/cjs/FrappeKPICard.native.js +27 -1
- package/dist/cjs/FrappeKPICard.native.js.map +1 -1
- package/dist/cjs/FrappeKanban.cjs +18 -18
- package/dist/cjs/FrappeKanban.native.js +20 -22
- package/dist/cjs/FrappeKanban.native.js.map +1 -1
- package/dist/cjs/FrappeLikedBy.cjs +2 -1
- package/dist/cjs/FrappeLikedBy.native.js +2 -1
- package/dist/cjs/FrappeLikedBy.native.js.map +1 -1
- package/dist/cjs/FrappeList.cjs +4 -3
- package/dist/cjs/FrappeList.native.js +4 -3
- package/dist/cjs/FrappeList.native.js.map +1 -1
- package/dist/cjs/FrappeListView.cjs +1 -0
- package/dist/cjs/FrappeListView.native.js +1 -0
- package/dist/cjs/FrappeListView.native.js.map +1 -1
- package/dist/cjs/FrappeProvider.cjs +3 -1
- package/dist/cjs/FrappeProvider.native.js +3 -1
- package/dist/cjs/FrappeProvider.native.js.map +1 -1
- package/dist/cjs/FrappeReconnectIndicator.native.js.map +1 -1
- package/dist/cjs/FrappeReportBuilder.cjs +3 -2
- package/dist/cjs/FrappeReportBuilder.native.js +3 -2
- package/dist/cjs/FrappeReportBuilder.native.js.map +1 -1
- package/dist/cjs/FrappeReportView.cjs +2 -1
- package/dist/cjs/FrappeReportView.native.js +5 -4
- package/dist/cjs/FrappeReportView.native.js.map +1 -1
- package/dist/cjs/FrappeTable.cjs +37 -39
- package/dist/cjs/FrappeTable.native.js +40 -40
- package/dist/cjs/FrappeTable.native.js.map +1 -1
- package/dist/cjs/FrappeTreeView.cjs +87 -51
- package/dist/cjs/FrappeTreeView.native.js +131 -51
- package/dist/cjs/FrappeTreeView.native.js.map +1 -1
- package/dist/cjs/SyncErrorNotice.native.js.map +1 -1
- package/dist/cjs/commentActions.cjs +1 -1
- package/dist/cjs/commentActions.native.js +1 -1
- package/dist/cjs/commentActions.native.js.map +1 -1
- package/dist/cjs/components/attachments.cjs +1 -0
- package/dist/cjs/components/attachments.native.js +1 -0
- package/dist/cjs/components/attachments.native.js.map +1 -1
- package/dist/cjs/components/tags.cjs +1 -0
- package/dist/cjs/components/tags.native.js +1 -0
- package/dist/cjs/components/tags.native.js.map +1 -1
- package/dist/cjs/components/timeline.cjs +2 -1
- package/dist/cjs/components/timeline.native.js +2 -1
- package/dist/cjs/components/timeline.native.js.map +1 -1
- package/dist/cjs/dependsOn.native.js.map +1 -1
- package/dist/cjs/desk/DeskFormPage.native.js.map +1 -1
- package/dist/cjs/desk/DeskFormSidebar.cjs +1 -0
- package/dist/cjs/desk/DeskFormSidebar.native.js +1 -0
- package/dist/cjs/desk/DeskFormSidebar.native.js.map +1 -1
- package/dist/cjs/desk/DeskListPage.native.js.map +1 -1
- package/dist/cjs/desk/DeskShell.cjs +2 -0
- package/dist/cjs/desk/DeskShell.native.js +2 -0
- package/dist/cjs/desk/DeskShell.native.js.map +1 -1
- package/dist/cjs/desk/DeskSidebar.cjs +1 -0
- package/dist/cjs/desk/DeskSidebar.native.js +1 -0
- package/dist/cjs/desk/DeskSidebar.native.js.map +1 -1
- package/dist/cjs/desk/awesomebar.cjs +2 -1
- package/dist/cjs/desk/awesomebar.native.js +2 -1
- package/dist/cjs/desk/awesomebar.native.js.map +1 -1
- package/dist/cjs/fieldOverrides.native.js.map +1 -1
- package/dist/cjs/fieldRegistry.cjs +1 -0
- package/dist/cjs/fieldRegistry.native.js +32 -31
- package/dist/cjs/fieldRegistry.native.js.map +1 -1
- package/dist/cjs/fields/Barcode/index.native.js.map +1 -1
- package/dist/cjs/fields/Check/index.native.js.map +1 -1
- package/dist/cjs/fields/CodeEditor/index.native.js.map +1 -1
- package/dist/cjs/fields/Color/index.native.js.map +1 -1
- package/dist/cjs/fields/Data/index.native.js.map +1 -1
- package/dist/cjs/fields/Date/sheetKeyboard.native.js.map +1 -1
- package/dist/cjs/fields/Date/types.native.js.map +1 -1
- package/dist/cjs/fields/Date/wire.native.js.map +1 -1
- package/dist/cjs/fields/DateRange/index.native.js.map +1 -1
- package/dist/cjs/fields/Duration/index.native.js.map +1 -1
- package/dist/cjs/fields/DynamicLink.native.js.map +1 -1
- package/dist/cjs/fields/FileUpload.cjs +1 -0
- package/dist/cjs/fields/FileUpload.native.js +1 -0
- package/dist/cjs/fields/FileUpload.native.js.map +1 -1
- package/dist/cjs/fields/FileUploadField/index.native.js.map +1 -1
- package/dist/cjs/fields/Geolocation/index.native.js.map +1 -1
- package/dist/cjs/fields/HTML/index.native.js.map +1 -1
- package/dist/cjs/fields/Heading/index.native.js.map +1 -1
- package/dist/cjs/fields/Icon/index.native.js.map +1 -1
- package/dist/cjs/fields/Link.cjs +1 -0
- package/dist/cjs/fields/Link.native.js +1 -0
- package/dist/cjs/fields/Link.native.js.map +1 -1
- package/dist/cjs/fields/LinkTree.cjs +2 -1
- package/dist/cjs/fields/LinkTree.native.js +2 -1
- package/dist/cjs/fields/LinkTree.native.js.map +1 -1
- package/dist/cjs/fields/LongText/index.native.js.map +1 -1
- package/dist/cjs/fields/MentionInput/index.cjs +4 -1
- package/dist/cjs/fields/MentionInput/index.native.js +4 -1
- package/dist/cjs/fields/MentionInput/index.native.js.map +1 -1
- package/dist/cjs/fields/Numeric/index.native.js.map +1 -1
- package/dist/cjs/fields/OTPInput/index.native.js.map +1 -1
- package/dist/cjs/fields/Password/index.native.js.map +1 -1
- package/dist/cjs/fields/Phone/index.native.js.map +1 -1
- package/dist/cjs/fields/Progress/index.native.js.map +1 -1
- package/dist/cjs/fields/RadioGroup/index.native.js.map +1 -1
- package/dist/cjs/fields/Rating/index.native.js.map +1 -1
- package/dist/cjs/fields/ReadOnly/index.native.js.map +1 -1
- package/dist/cjs/fields/Select/index.native.js.map +1 -1
- package/dist/cjs/fields/Signature/index.native.js.map +1 -1
- package/dist/cjs/fields/Slider/index.native.js.map +1 -1
- package/dist/cjs/fields/SmallText/index.native.js.map +1 -1
- package/dist/cjs/fields/Switch/index.native.js.map +1 -1
- package/dist/cjs/fields/TableMultiSelect.cjs +1 -0
- package/dist/cjs/fields/TableMultiSelect.native.js +1 -0
- package/dist/cjs/fields/TableMultiSelect.native.js.map +1 -1
- package/dist/cjs/fields/TextEditor/types.native.js.map +1 -1
- package/dist/cjs/fields/TimePicker/index.native.js.map +1 -1
- package/dist/cjs/fields/ToggleGroup/index.native.js.map +1 -1
- package/dist/cjs/fields/shared/EditorPreviewPanes.native.js.map +1 -1
- package/dist/cjs/filterFields.native.js.map +1 -1
- package/dist/cjs/formEngine/createPrefill.native.js.map +1 -1
- package/dist/cjs/formEngine/dirtyTracking.native.js.map +1 -1
- package/dist/cjs/formEngine/doctypeMeta.native.js.map +1 -1
- package/dist/cjs/formEngine/fetchFrom.native.js.map +1 -1
- package/dist/cjs/formEngine/fieldPermissions.native.js.map +1 -1
- package/dist/cjs/formEngine/formActions.native.js.map +1 -1
- package/dist/cjs/formEngine/formLayout.native.js.map +1 -1
- package/dist/cjs/formEngine/index.native.js.map +1 -1
- package/dist/cjs/formEngine/useFormEngine.native.js.map +1 -1
- package/dist/cjs/frappeEventColor.native.js.map +1 -1
- package/dist/cjs/frappeStoryTarget.native.js.map +1 -1
- package/dist/cjs/frappeUsers.cjs +1 -0
- package/dist/cjs/frappeUsers.native.js +1 -0
- package/dist/cjs/frappeUsers.native.js.map +1 -1
- package/dist/cjs/index.cjs +4 -0
- package/dist/cjs/index.native.js +38 -34
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/liveErrors.native.js.map +1 -1
- package/dist/cjs/resolveControl.native.js.map +1 -1
- package/dist/cjs/schemaForm/SchemaWizard.native.js.map +1 -1
- package/dist/cjs/schemaForm/applyFieldOrder.native.js.map +1 -1
- package/dist/cjs/schemaForm/index.cjs +10 -9
- package/dist/cjs/schemaForm/index.native.js +11 -10
- package/dist/cjs/schemaForm/index.native.js.map +1 -1
- package/dist/cjs/shared/devWarn.cjs +40 -0
- package/dist/cjs/shared/devWarn.native.js +45 -0
- package/dist/cjs/shared/devWarn.native.js.map +1 -0
- package/dist/cjs/shared/useKeyboardInset.native.js.map +1 -1
- package/dist/cjs/syncError.native.js.map +1 -1
- package/dist/cjs/useFrappeAggregate.cjs +15 -8
- package/dist/cjs/useFrappeAggregate.native.js +15 -9
- package/dist/cjs/useFrappeAggregate.native.js.map +1 -1
- package/dist/cjs/useFrappeFacets.cjs +10 -9
- package/dist/cjs/useFrappeFacets.native.js +10 -10
- package/dist/cjs/useFrappeFacets.native.js.map +1 -1
- package/dist/cjs/useFrappePagination.native.js.map +1 -1
- package/dist/cjs/useFrappeRows.cjs +113 -0
- package/dist/cjs/useFrappeRows.native.js +129 -0
- package/dist/cjs/useFrappeRows.native.js.map +1 -0
- package/dist/esm/ChartCard.native.js.map +1 -1
- package/dist/esm/FileBrowser/AttachLibrary.native.js.map +1 -1
- package/dist/esm/FileBrowser/folderTree.native.js.map +1 -1
- package/dist/esm/FileBrowser/index.native.js.map +1 -1
- package/dist/esm/FileBrowser/types.native.js.map +1 -1
- package/dist/esm/FileBrowser/viewPersistence.native.js.map +1 -1
- package/dist/esm/FormSidebar.native.js.map +1 -1
- package/dist/esm/FrappeAssignment.mjs +1 -0
- package/dist/esm/FrappeAssignment.mjs.map +1 -1
- package/dist/esm/FrappeAssignment.native.js +1 -0
- package/dist/esm/FrappeAssignment.native.js.map +1 -1
- package/dist/esm/FrappeCalendar.mjs +22 -18
- package/dist/esm/FrappeCalendar.mjs.map +1 -1
- package/dist/esm/FrappeCalendar.native.js +24 -22
- package/dist/esm/FrappeCalendar.native.js.map +1 -1
- package/dist/esm/FrappeChartCard.mjs +1 -0
- package/dist/esm/FrappeChartCard.mjs.map +1 -1
- package/dist/esm/FrappeChartCard.native.js +1 -0
- package/dist/esm/FrappeChartCard.native.js.map +1 -1
- package/dist/esm/FrappeConnectionIndicator.native.js.map +1 -1
- package/dist/esm/FrappeDashboard.mjs +1 -0
- package/dist/esm/FrappeDashboard.mjs.map +1 -1
- package/dist/esm/FrappeDashboard.native.js +1 -0
- package/dist/esm/FrappeDashboard.native.js.map +1 -1
- package/dist/esm/FrappeForm.mjs +3 -2
- package/dist/esm/FrappeForm.mjs.map +1 -1
- package/dist/esm/FrappeForm.native.js +3 -2
- package/dist/esm/FrappeForm.native.js.map +1 -1
- package/dist/esm/FrappeGantt.mjs +29 -37
- package/dist/esm/FrappeGantt.mjs.map +1 -1
- package/dist/esm/FrappeGantt.native.js +31 -41
- package/dist/esm/FrappeGantt.native.js.map +1 -1
- package/dist/esm/FrappeImageView.mjs +7 -4
- package/dist/esm/FrappeImageView.mjs.map +1 -1
- package/dist/esm/FrappeImageView.native.js +11 -6
- package/dist/esm/FrappeImageView.native.js.map +1 -1
- package/dist/esm/FrappeKPICard.mjs +28 -2
- package/dist/esm/FrappeKPICard.mjs.map +1 -1
- package/dist/esm/FrappeKPICard.native.js +28 -2
- package/dist/esm/FrappeKPICard.native.js.map +1 -1
- package/dist/esm/FrappeKanban.mjs +18 -18
- package/dist/esm/FrappeKanban.mjs.map +1 -1
- package/dist/esm/FrappeKanban.native.js +20 -22
- package/dist/esm/FrappeKanban.native.js.map +1 -1
- package/dist/esm/FrappeLikedBy.mjs +2 -1
- package/dist/esm/FrappeLikedBy.mjs.map +1 -1
- package/dist/esm/FrappeLikedBy.native.js +2 -1
- package/dist/esm/FrappeLikedBy.native.js.map +1 -1
- package/dist/esm/FrappeList.mjs +4 -3
- package/dist/esm/FrappeList.mjs.map +1 -1
- package/dist/esm/FrappeList.native.js +4 -3
- package/dist/esm/FrappeList.native.js.map +1 -1
- package/dist/esm/FrappeListView.mjs +1 -0
- package/dist/esm/FrappeListView.mjs.map +1 -1
- package/dist/esm/FrappeListView.native.js +1 -0
- package/dist/esm/FrappeListView.native.js.map +1 -1
- package/dist/esm/FrappeProvider.mjs +3 -1
- package/dist/esm/FrappeProvider.mjs.map +1 -1
- package/dist/esm/FrappeProvider.native.js +3 -1
- package/dist/esm/FrappeProvider.native.js.map +1 -1
- package/dist/esm/FrappeReconnectIndicator.native.js.map +1 -1
- package/dist/esm/FrappeReportBuilder.mjs +3 -2
- package/dist/esm/FrappeReportBuilder.mjs.map +1 -1
- package/dist/esm/FrappeReportBuilder.native.js +3 -2
- package/dist/esm/FrappeReportBuilder.native.js.map +1 -1
- package/dist/esm/FrappeReportView.mjs +2 -1
- package/dist/esm/FrappeReportView.mjs.map +1 -1
- package/dist/esm/FrappeReportView.native.js +2 -1
- package/dist/esm/FrappeReportView.native.js.map +1 -1
- package/dist/esm/FrappeTable.mjs +38 -40
- package/dist/esm/FrappeTable.mjs.map +1 -1
- package/dist/esm/FrappeTable.native.js +41 -41
- package/dist/esm/FrappeTable.native.js.map +1 -1
- package/dist/esm/FrappeTreeView.mjs +91 -56
- package/dist/esm/FrappeTreeView.mjs.map +1 -1
- package/dist/esm/FrappeTreeView.native.js +135 -56
- package/dist/esm/FrappeTreeView.native.js.map +1 -1
- package/dist/esm/SyncErrorNotice.native.js.map +1 -1
- package/dist/esm/commentActions.mjs +1 -1
- package/dist/esm/commentActions.mjs.map +1 -1
- package/dist/esm/commentActions.native.js +1 -1
- package/dist/esm/commentActions.native.js.map +1 -1
- package/dist/esm/components/attachments.mjs +1 -0
- package/dist/esm/components/attachments.mjs.map +1 -1
- package/dist/esm/components/attachments.native.js +1 -0
- package/dist/esm/components/attachments.native.js.map +1 -1
- package/dist/esm/components/tags.mjs +1 -0
- package/dist/esm/components/tags.mjs.map +1 -1
- package/dist/esm/components/tags.native.js +1 -0
- package/dist/esm/components/tags.native.js.map +1 -1
- package/dist/esm/components/timeline.mjs +2 -1
- package/dist/esm/components/timeline.mjs.map +1 -1
- package/dist/esm/components/timeline.native.js +2 -1
- package/dist/esm/components/timeline.native.js.map +1 -1
- package/dist/esm/dependsOn.native.js.map +1 -1
- package/dist/esm/desk/DeskFormPage.native.js.map +1 -1
- package/dist/esm/desk/DeskFormSidebar.mjs +1 -0
- package/dist/esm/desk/DeskFormSidebar.mjs.map +1 -1
- package/dist/esm/desk/DeskFormSidebar.native.js +1 -0
- package/dist/esm/desk/DeskFormSidebar.native.js.map +1 -1
- package/dist/esm/desk/DeskListPage.native.js.map +1 -1
- package/dist/esm/desk/DeskShell.mjs +2 -0
- package/dist/esm/desk/DeskShell.mjs.map +1 -1
- package/dist/esm/desk/DeskShell.native.js +2 -0
- package/dist/esm/desk/DeskShell.native.js.map +1 -1
- package/dist/esm/desk/DeskSidebar.mjs +1 -0
- package/dist/esm/desk/DeskSidebar.mjs.map +1 -1
- package/dist/esm/desk/DeskSidebar.native.js +1 -0
- package/dist/esm/desk/DeskSidebar.native.js.map +1 -1
- package/dist/esm/desk/awesomebar.mjs +2 -1
- package/dist/esm/desk/awesomebar.mjs.map +1 -1
- package/dist/esm/desk/awesomebar.native.js +2 -1
- package/dist/esm/desk/awesomebar.native.js.map +1 -1
- package/dist/esm/fieldOverrides.native.js.map +1 -1
- package/dist/esm/fieldRegistry.mjs +1 -0
- package/dist/esm/fieldRegistry.mjs.map +1 -1
- package/dist/esm/fieldRegistry.native.js +1 -0
- package/dist/esm/fieldRegistry.native.js.map +1 -1
- package/dist/esm/fields/Barcode/index.native.js.map +1 -1
- package/dist/esm/fields/Check/index.native.js.map +1 -1
- package/dist/esm/fields/CodeEditor/index.native.js.map +1 -1
- package/dist/esm/fields/Color/index.native.js.map +1 -1
- package/dist/esm/fields/Data/index.native.js.map +1 -1
- package/dist/esm/fields/Date/sheetKeyboard.native.js.map +1 -1
- package/dist/esm/fields/Date/types.native.js.map +1 -1
- package/dist/esm/fields/Date/wire.native.js.map +1 -1
- package/dist/esm/fields/DateRange/index.native.js.map +1 -1
- package/dist/esm/fields/Duration/index.native.js.map +1 -1
- package/dist/esm/fields/DynamicLink.native.js.map +1 -1
- package/dist/esm/fields/FileUpload.mjs +1 -0
- package/dist/esm/fields/FileUpload.mjs.map +1 -1
- package/dist/esm/fields/FileUpload.native.js +1 -0
- package/dist/esm/fields/FileUpload.native.js.map +1 -1
- package/dist/esm/fields/FileUploadField/index.native.js.map +1 -1
- package/dist/esm/fields/Geolocation/index.native.js.map +1 -1
- package/dist/esm/fields/HTML/index.native.js.map +1 -1
- package/dist/esm/fields/Heading/index.native.js.map +1 -1
- package/dist/esm/fields/Icon/index.native.js.map +1 -1
- package/dist/esm/fields/Link.mjs +1 -0
- package/dist/esm/fields/Link.mjs.map +1 -1
- package/dist/esm/fields/Link.native.js +1 -0
- package/dist/esm/fields/Link.native.js.map +1 -1
- package/dist/esm/fields/LinkTree.mjs +2 -1
- package/dist/esm/fields/LinkTree.mjs.map +1 -1
- package/dist/esm/fields/LinkTree.native.js +2 -1
- package/dist/esm/fields/LinkTree.native.js.map +1 -1
- package/dist/esm/fields/LongText/index.native.js.map +1 -1
- package/dist/esm/fields/MentionInput/index.mjs +4 -1
- package/dist/esm/fields/MentionInput/index.mjs.map +1 -1
- package/dist/esm/fields/MentionInput/index.native.js +4 -1
- package/dist/esm/fields/MentionInput/index.native.js.map +1 -1
- package/dist/esm/fields/Numeric/index.native.js.map +1 -1
- package/dist/esm/fields/OTPInput/index.native.js.map +1 -1
- package/dist/esm/fields/Password/index.native.js.map +1 -1
- package/dist/esm/fields/Phone/index.native.js.map +1 -1
- package/dist/esm/fields/Progress/index.native.js.map +1 -1
- package/dist/esm/fields/RadioGroup/index.native.js.map +1 -1
- package/dist/esm/fields/Rating/index.native.js.map +1 -1
- package/dist/esm/fields/ReadOnly/index.native.js.map +1 -1
- package/dist/esm/fields/Select/index.native.js.map +1 -1
- package/dist/esm/fields/Signature/index.native.js.map +1 -1
- package/dist/esm/fields/Slider/index.native.js.map +1 -1
- package/dist/esm/fields/SmallText/index.native.js.map +1 -1
- package/dist/esm/fields/Switch/index.native.js.map +1 -1
- package/dist/esm/fields/TableMultiSelect.mjs +1 -0
- package/dist/esm/fields/TableMultiSelect.mjs.map +1 -1
- package/dist/esm/fields/TableMultiSelect.native.js +1 -0
- package/dist/esm/fields/TableMultiSelect.native.js.map +1 -1
- package/dist/esm/fields/TextEditor/types.native.js.map +1 -1
- package/dist/esm/fields/TimePicker/index.native.js.map +1 -1
- package/dist/esm/fields/ToggleGroup/index.native.js.map +1 -1
- package/dist/esm/fields/shared/EditorPreviewPanes.native.js.map +1 -1
- package/dist/esm/filterFields.native.js.map +1 -1
- package/dist/esm/formEngine/createPrefill.native.js.map +1 -1
- package/dist/esm/formEngine/dirtyTracking.native.js.map +1 -1
- package/dist/esm/formEngine/doctypeMeta.native.js.map +1 -1
- package/dist/esm/formEngine/fetchFrom.native.js.map +1 -1
- package/dist/esm/formEngine/fieldPermissions.native.js.map +1 -1
- package/dist/esm/formEngine/formActions.mjs.map +1 -1
- package/dist/esm/formEngine/formActions.native.js.map +1 -1
- package/dist/esm/formEngine/formLayout.native.js.map +1 -1
- package/dist/esm/formEngine/index.native.js.map +1 -1
- package/dist/esm/formEngine/useFormEngine.native.js.map +1 -1
- package/dist/esm/frappeEventColor.native.js.map +1 -1
- package/dist/esm/frappeStoryTarget.native.js.map +1 -1
- package/dist/esm/frappeUsers.mjs +1 -0
- package/dist/esm/frappeUsers.mjs.map +1 -1
- package/dist/esm/frappeUsers.native.js +1 -0
- package/dist/esm/frappeUsers.native.js.map +1 -1
- package/dist/esm/index.mjs +2 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +2 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/liveErrors.native.js.map +1 -1
- package/dist/esm/resolveControl.native.js.map +1 -1
- package/dist/esm/schemaForm/SchemaWizard.native.js.map +1 -1
- package/dist/esm/schemaForm/applyFieldOrder.native.js.map +1 -1
- package/dist/esm/schemaForm/index.mjs +8 -7
- package/dist/esm/schemaForm/index.mjs.map +1 -1
- package/dist/esm/schemaForm/index.native.js +8 -7
- package/dist/esm/schemaForm/index.native.js.map +1 -1
- package/dist/esm/shared/devWarn.mjs +14 -0
- package/dist/esm/shared/devWarn.mjs.map +1 -0
- package/dist/esm/shared/devWarn.native.js +16 -0
- package/dist/esm/shared/devWarn.native.js.map +1 -0
- package/dist/esm/shared/useKeyboardInset.native.js.map +1 -1
- package/dist/esm/syncError.native.js.map +1 -1
- package/dist/esm/useFrappeAggregate.mjs +15 -8
- package/dist/esm/useFrappeAggregate.mjs.map +1 -1
- package/dist/esm/useFrappeAggregate.native.js +15 -9
- package/dist/esm/useFrappeAggregate.native.js.map +1 -1
- package/dist/esm/useFrappeFacets.mjs +10 -9
- package/dist/esm/useFrappeFacets.mjs.map +1 -1
- package/dist/esm/useFrappeFacets.native.js +10 -10
- package/dist/esm/useFrappeFacets.native.js.map +1 -1
- package/dist/esm/useFrappePagination.native.js.map +1 -1
- package/dist/esm/useFrappeRows.mjs +86 -0
- package/dist/esm/useFrappeRows.mjs.map +1 -0
- package/dist/esm/useFrappeRows.native.js +99 -0
- package/dist/esm/useFrappeRows.native.js.map +1 -0
- package/dist/jsx/FrappeAssignment.mjs +1 -0
- package/dist/jsx/FrappeAssignment.mjs.map +1 -1
- package/dist/jsx/FrappeAssignment.native.js +1 -0
- package/dist/jsx/FrappeAssignment.native.js.map +1 -1
- package/dist/jsx/FrappeCalendar.mjs +22 -18
- package/dist/jsx/FrappeCalendar.mjs.map +1 -1
- package/dist/jsx/FrappeCalendar.native.js +24 -22
- package/dist/jsx/FrappeCalendar.native.js.map +1 -1
- package/dist/jsx/FrappeChartCard.mjs +1 -0
- package/dist/jsx/FrappeChartCard.mjs.map +1 -1
- package/dist/jsx/FrappeChartCard.native.js +1 -0
- package/dist/jsx/FrappeChartCard.native.js.map +1 -1
- package/dist/jsx/FrappeDashboard.mjs +1 -0
- package/dist/jsx/FrappeDashboard.mjs.map +1 -1
- package/dist/jsx/FrappeDashboard.native.js +1 -0
- package/dist/jsx/FrappeDashboard.native.js.map +1 -1
- package/dist/jsx/FrappeForm.mjs +3 -2
- package/dist/jsx/FrappeForm.mjs.map +1 -1
- package/dist/jsx/FrappeForm.native.js +3 -2
- package/dist/jsx/FrappeForm.native.js.map +1 -1
- package/dist/jsx/FrappeGantt.mjs +29 -37
- package/dist/jsx/FrappeGantt.mjs.map +1 -1
- package/dist/jsx/FrappeGantt.native.js +29 -39
- package/dist/jsx/FrappeGantt.native.js.map +1 -1
- package/dist/jsx/FrappeImageView.mjs +7 -4
- package/dist/jsx/FrappeImageView.mjs.map +1 -1
- package/dist/jsx/FrappeImageView.native.js +10 -5
- package/dist/jsx/FrappeImageView.native.js.map +1 -1
- package/dist/jsx/FrappeKPICard.mjs +28 -2
- package/dist/jsx/FrappeKPICard.mjs.map +1 -1
- package/dist/jsx/FrappeKPICard.native.js +27 -1
- package/dist/jsx/FrappeKPICard.native.js.map +1 -1
- package/dist/jsx/FrappeKanban.mjs +18 -18
- package/dist/jsx/FrappeKanban.mjs.map +1 -1
- package/dist/jsx/FrappeKanban.native.js +20 -22
- package/dist/jsx/FrappeKanban.native.js.map +1 -1
- package/dist/jsx/FrappeLikedBy.mjs +2 -1
- package/dist/jsx/FrappeLikedBy.mjs.map +1 -1
- package/dist/jsx/FrappeLikedBy.native.js +2 -1
- package/dist/jsx/FrappeLikedBy.native.js.map +1 -1
- package/dist/jsx/FrappeList.mjs +4 -3
- package/dist/jsx/FrappeList.mjs.map +1 -1
- package/dist/jsx/FrappeList.native.js +4 -3
- package/dist/jsx/FrappeList.native.js.map +1 -1
- package/dist/jsx/FrappeListView.mjs +1 -0
- package/dist/jsx/FrappeListView.mjs.map +1 -1
- package/dist/jsx/FrappeListView.native.js +1 -0
- package/dist/jsx/FrappeListView.native.js.map +1 -1
- package/dist/jsx/FrappeProvider.mjs +3 -1
- package/dist/jsx/FrappeProvider.mjs.map +1 -1
- package/dist/jsx/FrappeProvider.native.js +3 -1
- package/dist/jsx/FrappeProvider.native.js.map +1 -1
- package/dist/jsx/FrappeReportBuilder.mjs +3 -2
- package/dist/jsx/FrappeReportBuilder.mjs.map +1 -1
- package/dist/jsx/FrappeReportBuilder.native.js +3 -2
- package/dist/jsx/FrappeReportBuilder.native.js.map +1 -1
- package/dist/jsx/FrappeReportView.mjs +2 -1
- package/dist/jsx/FrappeReportView.mjs.map +1 -1
- package/dist/jsx/FrappeReportView.native.js +2 -1
- package/dist/jsx/FrappeReportView.native.js.map +1 -1
- package/dist/jsx/FrappeTable.mjs +38 -40
- package/dist/jsx/FrappeTable.mjs.map +1 -1
- package/dist/jsx/FrappeTable.native.js +40 -40
- package/dist/jsx/FrappeTable.native.js.map +1 -1
- package/dist/jsx/FrappeTreeView.mjs +91 -56
- package/dist/jsx/FrappeTreeView.mjs.map +1 -1
- package/dist/jsx/FrappeTreeView.native.js +131 -51
- package/dist/jsx/FrappeTreeView.native.js.map +1 -1
- package/dist/jsx/commentActions.mjs +1 -1
- package/dist/jsx/commentActions.mjs.map +1 -1
- package/dist/jsx/commentActions.native.js +1 -1
- package/dist/jsx/commentActions.native.js.map +1 -1
- package/dist/jsx/components/attachments.mjs +1 -0
- package/dist/jsx/components/attachments.mjs.map +1 -1
- package/dist/jsx/components/attachments.native.js +1 -0
- package/dist/jsx/components/attachments.native.js.map +1 -1
- package/dist/jsx/components/tags.mjs +1 -0
- package/dist/jsx/components/tags.mjs.map +1 -1
- package/dist/jsx/components/tags.native.js +1 -0
- package/dist/jsx/components/tags.native.js.map +1 -1
- package/dist/jsx/components/timeline.mjs +2 -1
- package/dist/jsx/components/timeline.mjs.map +1 -1
- package/dist/jsx/components/timeline.native.js +2 -1
- package/dist/jsx/components/timeline.native.js.map +1 -1
- package/dist/jsx/desk/DeskFormSidebar.mjs +1 -0
- package/dist/jsx/desk/DeskFormSidebar.mjs.map +1 -1
- package/dist/jsx/desk/DeskFormSidebar.native.js +1 -0
- package/dist/jsx/desk/DeskFormSidebar.native.js.map +1 -1
- package/dist/jsx/desk/DeskShell.mjs +2 -0
- package/dist/jsx/desk/DeskShell.mjs.map +1 -1
- package/dist/jsx/desk/DeskShell.native.js +2 -0
- package/dist/jsx/desk/DeskShell.native.js.map +1 -1
- package/dist/jsx/desk/DeskSidebar.mjs +1 -0
- package/dist/jsx/desk/DeskSidebar.mjs.map +1 -1
- package/dist/jsx/desk/DeskSidebar.native.js +1 -0
- package/dist/jsx/desk/DeskSidebar.native.js.map +1 -1
- package/dist/jsx/desk/awesomebar.mjs +2 -1
- package/dist/jsx/desk/awesomebar.mjs.map +1 -1
- package/dist/jsx/desk/awesomebar.native.js +2 -1
- package/dist/jsx/desk/awesomebar.native.js.map +1 -1
- package/dist/jsx/fieldRegistry.mjs +1 -0
- package/dist/jsx/fieldRegistry.mjs.map +1 -1
- package/dist/jsx/fieldRegistry.native.js +1 -0
- package/dist/jsx/fieldRegistry.native.js.map +1 -1
- package/dist/jsx/fields/FileUpload.mjs +1 -0
- package/dist/jsx/fields/FileUpload.mjs.map +1 -1
- package/dist/jsx/fields/FileUpload.native.js +1 -0
- package/dist/jsx/fields/FileUpload.native.js.map +1 -1
- package/dist/jsx/fields/Link.mjs +1 -0
- package/dist/jsx/fields/Link.mjs.map +1 -1
- package/dist/jsx/fields/Link.native.js +1 -0
- package/dist/jsx/fields/Link.native.js.map +1 -1
- package/dist/jsx/fields/LinkTree.mjs +2 -1
- package/dist/jsx/fields/LinkTree.mjs.map +1 -1
- package/dist/jsx/fields/LinkTree.native.js +2 -1
- package/dist/jsx/fields/LinkTree.native.js.map +1 -1
- package/dist/jsx/fields/MentionInput/index.mjs +4 -1
- package/dist/jsx/fields/MentionInput/index.mjs.map +1 -1
- package/dist/jsx/fields/MentionInput/index.native.js +4 -1
- package/dist/jsx/fields/MentionInput/index.native.js.map +1 -1
- package/dist/jsx/fields/TableMultiSelect.mjs +1 -0
- package/dist/jsx/fields/TableMultiSelect.mjs.map +1 -1
- package/dist/jsx/fields/TableMultiSelect.native.js +1 -0
- package/dist/jsx/fields/TableMultiSelect.native.js.map +1 -1
- package/dist/jsx/formEngine/formActions.mjs.map +1 -1
- package/dist/jsx/formEngine/formActions.native.js.map +1 -1
- package/dist/jsx/frappeUsers.mjs +1 -0
- package/dist/jsx/frappeUsers.mjs.map +1 -1
- package/dist/jsx/frappeUsers.native.js +1 -0
- package/dist/jsx/frappeUsers.native.js.map +1 -1
- package/dist/jsx/index.js +2 -1
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +2 -1
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +4 -0
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/schemaForm/index.mjs +8 -7
- package/dist/jsx/schemaForm/index.mjs.map +1 -1
- package/dist/jsx/schemaForm/index.native.js +10 -9
- package/dist/jsx/schemaForm/index.native.js.map +1 -1
- package/dist/jsx/shared/devWarn.mjs +14 -0
- package/dist/jsx/shared/devWarn.mjs.map +1 -0
- package/dist/jsx/shared/devWarn.native.js +45 -0
- package/dist/jsx/shared/devWarn.native.js.map +1 -0
- package/dist/jsx/useFrappeAggregate.mjs +15 -8
- package/dist/jsx/useFrappeAggregate.mjs.map +1 -1
- package/dist/jsx/useFrappeAggregate.native.js +15 -9
- package/dist/jsx/useFrappeAggregate.native.js.map +1 -1
- package/dist/jsx/useFrappeFacets.mjs +10 -9
- package/dist/jsx/useFrappeFacets.mjs.map +1 -1
- package/dist/jsx/useFrappeFacets.native.js +10 -10
- package/dist/jsx/useFrappeFacets.native.js.map +1 -1
- package/dist/jsx/useFrappeRows.mjs +86 -0
- package/dist/jsx/useFrappeRows.mjs.map +1 -0
- package/dist/jsx/useFrappeRows.native.js +129 -0
- package/dist/jsx/useFrappeRows.native.js.map +1 -0
- package/package.json +17 -16
- package/src/FileBrowser/FileBrowser.spec.tsx +11 -1
- package/src/FrappeAssignment.tsx +1 -0
- package/src/FrappeCalendar.tsx +27 -22
- package/src/FrappeChartCard.tsx +1 -0
- package/src/FrappeDashboard.tsx +3 -0
- package/src/FrappeForm.tsx +9 -3
- package/src/FrappeGantt.tsx +31 -39
- package/src/FrappeImageView.tsx +7 -3
- package/src/FrappeKPICard.spec.tsx +128 -0
- package/src/FrappeKPICard.tsx +45 -4
- package/src/FrappeKanban.tsx +26 -17
- package/src/FrappeLikedBy.tsx +2 -1
- package/src/FrappeList.tsx +5 -2
- package/src/FrappeListView.tsx +1 -0
- package/src/FrappeProvider.fixturesOnly.spec.tsx +129 -0
- package/src/FrappeProvider.realtime.spec.tsx +59 -0
- package/src/FrappeProvider.tsx +33 -7
- package/src/FrappeReportBuilder.tsx +5 -2
- package/src/FrappeReportView.tsx +5 -2
- package/src/FrappeTable.autoHeight.spec.tsx +142 -0
- package/src/FrappeTable.rowAccumulator.spec.tsx +110 -0
- package/src/FrappeTable.tsx +77 -48
- package/src/FrappeTreeView.stories.tsx +59 -0
- package/src/FrappeTreeView.tsx +168 -56
- package/src/commentActions.ts +1 -1
- package/src/components/attachments.tsx +1 -0
- package/src/components/tags.tsx +1 -0
- package/src/components/timeline.tsx +2 -1
- package/src/desk/DeskFormSidebar.tsx +1 -0
- package/src/desk/DeskShell.tsx +2 -0
- package/src/desk/DeskSidebar.tsx +6 -1
- package/src/desk/awesomebar.tsx +11 -3
- package/src/fieldRegistry.ts +1 -0
- package/src/fields/CodeEditor/CodeEditor.spec.tsx +10 -9
- package/src/fields/Date/typeParity.spec.tsx +19 -9
- package/src/fields/Duration/Duration.spec.tsx +73 -0
- package/src/fields/FileUpload.tsx +1 -0
- package/src/fields/Link.tsx +6 -1
- package/src/fields/LinkTree.tsx +2 -1
- package/src/fields/MentionInput/MentionInput.spec.tsx +110 -0
- package/src/fields/MentionInput/index.tsx +4 -1
- package/src/fields/Password/index.tsx +1 -1
- package/src/fields/Progress/Progress.spec.tsx +9 -0
- package/src/fields/RadioGroup/RadioGroup.spec.tsx +93 -0
- package/src/fields/Signature/Signature.spec.tsx +105 -0
- package/src/fields/Slider/Slider.spec.tsx +73 -0
- package/src/fields/Switch/Switch.spec.tsx +65 -0
- package/src/fields/TableMultiSelect.tsx +1 -0
- package/src/fields/TextEditor/TextEditor.spec.tsx +2 -3
- package/src/fields/TextEditor/TextEditor.stories.tsx +31 -1
- package/src/fields/ToggleGroup/ToggleGroup.spec.tsx +110 -0
- package/src/formEngine/formActions.ts +2 -0
- package/src/frappeUsers.ts +1 -0
- package/src/frappeViews.designLaw.spec.ts +11 -7
- package/src/index.ts +13 -0
- package/src/schemaForm/index.tsx +6 -7
- package/src/shared/devWarn.ts +42 -0
- package/src/useFrappeAggregate.ts +19 -11
- package/src/useFrappeFacets.ts +17 -10
- package/src/useFrappeRows.spec.tsx +176 -0
- package/src/useFrappeRows.ts +293 -0
- package/types/FrappeAssignment.d.ts.map +1 -1
- package/types/FrappeCalendar.d.ts.map +1 -1
- package/types/FrappeChartCard.d.ts.map +1 -1
- package/types/FrappeDashboard.d.ts.map +1 -1
- package/types/FrappeForm.d.ts +6 -2
- package/types/FrappeForm.d.ts.map +1 -1
- package/types/FrappeGantt.d.ts.map +1 -1
- package/types/FrappeImageView.d.ts.map +1 -1
- package/types/FrappeKPICard.d.ts +9 -1
- package/types/FrappeKPICard.d.ts.map +1 -1
- package/types/FrappeKanban.d.ts.map +1 -1
- package/types/FrappeLikedBy.d.ts.map +1 -1
- package/types/FrappeList.d.ts.map +1 -1
- package/types/FrappeListView.d.ts.map +1 -1
- package/types/FrappeProvider.d.ts +21 -7
- package/types/FrappeProvider.d.ts.map +1 -1
- package/types/FrappeReportBuilder.d.ts.map +1 -1
- package/types/FrappeReportView.d.ts.map +1 -1
- package/types/FrappeTable.d.ts +20 -1
- package/types/FrappeTable.d.ts.map +1 -1
- package/types/FrappeTreeView.d.ts +38 -1
- package/types/FrappeTreeView.d.ts.map +1 -1
- package/types/components/attachments.d.ts.map +1 -1
- package/types/components/tags.d.ts.map +1 -1
- package/types/components/timeline.d.ts.map +1 -1
- package/types/desk/DeskFormSidebar.d.ts.map +1 -1
- package/types/desk/DeskShell.d.ts.map +1 -1
- package/types/desk/DeskSidebar.d.ts.map +1 -1
- package/types/desk/awesomebar.d.ts.map +1 -1
- package/types/fieldRegistry.d.ts.map +1 -1
- package/types/fields/FileUpload.d.ts.map +1 -1
- package/types/fields/Link.d.ts.map +1 -1
- package/types/fields/LinkTree.d.ts.map +1 -1
- package/types/fields/MentionInput/index.d.ts.map +1 -1
- package/types/fields/Password/index.d.ts +1 -1
- package/types/fields/Password/index.d.ts.map +1 -1
- package/types/fields/TableMultiSelect.d.ts.map +1 -1
- package/types/formEngine/formActions.d.ts +2 -0
- package/types/formEngine/formActions.d.ts.map +1 -1
- package/types/frappeUsers.d.ts.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/schemaForm/index.d.ts.map +1 -1
- package/types/shared/devWarn.d.ts +23 -0
- package/types/shared/devWarn.d.ts.map +1 -0
- package/types/useFrappeAggregate.d.ts +4 -1
- package/types/useFrappeAggregate.d.ts.map +1 -1
- package/types/useFrappeFacets.d.ts +2 -1
- package/types/useFrappeFacets.d.ts.map +1 -1
- package/types/useFrappeRows.d.ts +186 -0
- package/types/useFrappeRows.d.ts.map +1 -0
package/src/FrappeTable.tsx
CHANGED
|
@@ -3,9 +3,7 @@ import {
|
|
|
3
3
|
Order,
|
|
4
4
|
matchesFilters,
|
|
5
5
|
useDocTypeMeta,
|
|
6
|
-
useFrappeCollection,
|
|
7
6
|
useFrappeDoctypeEvents,
|
|
8
|
-
useLiveQuery,
|
|
9
7
|
} from "@multiplatform.one/frappe";
|
|
10
8
|
import {
|
|
11
9
|
DataTable,
|
|
@@ -25,12 +23,31 @@ import { FilterManager, SavedFilterDropdown, useSavedFilters } from "@multiplatf
|
|
|
25
23
|
import { useFrappeConfig } from "./FrappeProvider";
|
|
26
24
|
import { FrappeReconnectIndicator } from "./FrappeReconnectIndicator";
|
|
27
25
|
import { docFieldsToFilterFields } from "./filterFields";
|
|
28
|
-
import {
|
|
26
|
+
import { useFrappeRows } from "./useFrappeRows";
|
|
29
27
|
|
|
30
28
|
/**
|
|
31
29
|
* Props for the FrappeTable component.
|
|
32
30
|
*
|
|
33
|
-
*
|
|
31
|
+
* `data` is omitted because FrappeTable fetches its own rows. Everything else
|
|
32
|
+
* on `DataTableProps` passes straight through — including `rowAccumulator`
|
|
33
|
+
* (MPO-250), so a Frappe-bound table CAN carry a folded column (a running
|
|
34
|
+
* balance, a per-row cumulative count) without the caller re-fetching the
|
|
35
|
+
* doctype and hand-assembling a DataTable. Declare the derived field on
|
|
36
|
+
* `TDoc` so a column can name it in `accessorKey`:
|
|
37
|
+
*
|
|
38
|
+
* ```tsx
|
|
39
|
+
* const balance: RowAccumulator<Partial<Posting>, string> = {
|
|
40
|
+
* initial: "0",
|
|
41
|
+
* reduce: (carried, row) => addMoney(carried, row.amount ?? "0"),
|
|
42
|
+
* derive: (carried) => ({ running: carried }),
|
|
43
|
+
* order: (a, b) => compareByDateThenName(a, b),
|
|
44
|
+
* };
|
|
45
|
+
* <FrappeTable<Posting & { running?: string }> doctype="Posting" rowAccumulator={balance} … />
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* The fold runs over the rows the table HOLDS, before pagination. In
|
|
49
|
+
* `serverSide` mode that is one page, so a running balance there needs the
|
|
50
|
+
* server to send the figure — the fold cannot invent rows it never got.
|
|
34
51
|
*/
|
|
35
52
|
export interface FrappeTableProps<TDoc extends { name: string; doctype: string }> extends Omit<
|
|
36
53
|
DataTableProps<Partial<TDoc>>,
|
|
@@ -310,8 +327,10 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
|
|
|
310
327
|
const finalAuth = auth ?? config?.auth;
|
|
311
328
|
const finalSyncOptions = syncOptions ?? config?.syncOptions;
|
|
312
329
|
|
|
313
|
-
|
|
314
|
-
|
|
330
|
+
// A fixture corpus is a complete data source, so it satisfies the same
|
|
331
|
+
// requirement a baseURL does: fixture mode never dials a server.
|
|
332
|
+
if (!finalBaseURL && !config?.fixtures) {
|
|
333
|
+
throw new Error("FrappeTable requires baseURL prop or FrappeProvider with baseURL or fixtures");
|
|
315
334
|
}
|
|
316
335
|
|
|
317
336
|
// One connection config for the live subscription (client mode), the
|
|
@@ -324,6 +343,7 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
|
|
|
324
343
|
socketBaseURL: config?.socketBaseURL,
|
|
325
344
|
auth: finalAuth,
|
|
326
345
|
syncOptions: finalSyncOptions,
|
|
346
|
+
realtime: config?.realtime,
|
|
327
347
|
fixtures: config?.fixtures,
|
|
328
348
|
}),
|
|
329
349
|
[
|
|
@@ -331,6 +351,7 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
|
|
|
331
351
|
config?.socketPort,
|
|
332
352
|
config?.siteName,
|
|
333
353
|
config?.socketBaseURL,
|
|
354
|
+
config?.realtime,
|
|
334
355
|
finalAuth,
|
|
335
356
|
finalSyncOptions,
|
|
336
357
|
config?.fixtures,
|
|
@@ -592,32 +613,31 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
|
|
|
592
613
|
// Always call the hook — toggling `savedFilters` must not change hook order (SB-M-012).
|
|
593
614
|
const savedFiltersHook = useSavedFilters({ userId });
|
|
594
615
|
|
|
595
|
-
//
|
|
596
|
-
//
|
|
597
|
-
//
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
)
|
|
606
|
-
},
|
|
616
|
+
// The client/live-collection read is the SHARED one (MPO-251): collection
|
|
617
|
+
// + live query + the honest error surface a bare collection swallows
|
|
618
|
+
// (without onSyncError a 403 or a dead server renders as an empty table).
|
|
619
|
+
// `limit: null` keeps the bench's own page length rather than the hook's
|
|
620
|
+
// default — FrappeTable paginates on the rows it is handed, and moving its
|
|
621
|
+
// row ceiling here would move it for every existing consumer.
|
|
622
|
+
const rowsMessages = useMemo(
|
|
623
|
+
() => ({
|
|
624
|
+
permission: t("You do not have permission to view {{doctype}}", { doctype }),
|
|
625
|
+
generic: t("Error loading {{doctype}}", { doctype }),
|
|
626
|
+
queryFailed: t("Failed to load {{doctype}}", { doctype }),
|
|
627
|
+
}),
|
|
607
628
|
[doctype, t],
|
|
608
629
|
);
|
|
609
|
-
|
|
610
|
-
const collection = useFrappeCollection<TDoc>(
|
|
611
|
-
serverSide ? undefined : connectionConfig,
|
|
612
|
-
serverSide ? "" : doctype,
|
|
613
|
-
serverSide ? undefined : { fields, filters: activeFilters, onSyncError: handleSyncError },
|
|
614
|
-
);
|
|
615
630
|
const {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
} =
|
|
620
|
-
|
|
631
|
+
rows: clientRows,
|
|
632
|
+
isQueryLoading: isRowsLoading,
|
|
633
|
+
error: liveError,
|
|
634
|
+
} = useFrappeRows<TDoc>(serverSide ? undefined : connectionConfig, doctype, {
|
|
635
|
+
fields,
|
|
636
|
+
filters: activeFilters,
|
|
637
|
+
limit: null,
|
|
638
|
+
enabled: !serverSide,
|
|
639
|
+
messages: rowsMessages,
|
|
640
|
+
});
|
|
621
641
|
|
|
622
642
|
// Keep-rows-and-reconcile for client/live-collection mode: a filter change
|
|
623
643
|
// swaps the collection (new subscription), which reports loading from
|
|
@@ -659,19 +679,6 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
|
|
|
659
679
|
? !infiniteServerMode && serverLoading && hasLoadedOnce
|
|
660
680
|
: isRowsLoading && lastGoodClientRows.current !== null;
|
|
661
681
|
|
|
662
|
-
// Reset stale errors when the underlying collection changes (new doctype
|
|
663
|
-
// or filters) so a recovered query doesn't keep showing the old failure.
|
|
664
|
-
useEffect(() => {
|
|
665
|
-
if (!serverSide) setErrorState(null);
|
|
666
|
-
}, [collection, serverSide]);
|
|
667
|
-
|
|
668
|
-
// Fallback surface for live-query failures the collection itself reports
|
|
669
|
-
// (onSyncError above carries the specific message when available).
|
|
670
|
-
useEffect(() => {
|
|
671
|
-
if (serverSide || !isLiveError) return;
|
|
672
|
-
setErrorState((prev) => prev ?? new Error(t("Failed to load {{doctype}}", { doctype })));
|
|
673
|
-
}, [serverSide, isLiveError, doctype, t]);
|
|
674
|
-
|
|
675
682
|
const handleSelectFilter = (filter: any) => {
|
|
676
683
|
if (filter) {
|
|
677
684
|
setActiveFilters(filter.filters);
|
|
@@ -695,8 +702,12 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
|
|
|
695
702
|
await savedFiltersHook.deleteFilter(name);
|
|
696
703
|
};
|
|
697
704
|
|
|
698
|
-
|
|
699
|
-
|
|
705
|
+
// serverSide failures come from the fetch above; client/live failures come
|
|
706
|
+
// from useFrappeRows. Only one path is ever live at a time.
|
|
707
|
+
const resolvedError = serverSide ? errorState : liveError;
|
|
708
|
+
|
|
709
|
+
if (resolvedError && error) {
|
|
710
|
+
return <>{error(resolvedError)}</>;
|
|
700
711
|
}
|
|
701
712
|
|
|
702
713
|
const rowData = rows ?? [];
|
|
@@ -704,8 +715,8 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
|
|
|
704
715
|
// Infinite serverSide delegates loading/empty chrome to DataTable.
|
|
705
716
|
// After the first load, NEVER replace DataTable with empty/loading chrome
|
|
706
717
|
// while a refetch is in flight — that was the named blank-the-list defect.
|
|
707
|
-
const boundaryState =
|
|
708
|
-
? { error:
|
|
718
|
+
const boundaryState = resolvedError
|
|
719
|
+
? { error: resolvedError }
|
|
709
720
|
: isRowsLoadingResolved
|
|
710
721
|
? { loading: loading ?? true }
|
|
711
722
|
: rowData.length === 0 && !infiniteServerMode && !isFetching
|
|
@@ -713,7 +724,16 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
|
|
|
713
724
|
: null;
|
|
714
725
|
if (boundaryState) {
|
|
715
726
|
return (
|
|
716
|
-
<YStack
|
|
727
|
+
<YStack
|
|
728
|
+
{...knobProps.gap}
|
|
729
|
+
// flexBasis auto, not flex={1}: a basis-0 chain resolves to 0 in an
|
|
730
|
+
// auto-height parent and collapses the table to a sliver. Same
|
|
731
|
+
// geometry as DataTableRoot's own root.
|
|
732
|
+
flexGrow={1}
|
|
733
|
+
flexShrink={1}
|
|
734
|
+
flexBasis="auto"
|
|
735
|
+
minHeight={0}
|
|
736
|
+
>
|
|
717
737
|
<FrappeReconnectIndicator config={connectionConfig} />
|
|
718
738
|
<AsyncBoundary
|
|
719
739
|
layout={layout === "list" || layout === "cards" ? "list" : "table"}
|
|
@@ -726,7 +746,16 @@ export function FrappeTable<TDoc extends { name: string; doctype: string }>({
|
|
|
726
746
|
}
|
|
727
747
|
|
|
728
748
|
return (
|
|
729
|
-
<YStack
|
|
749
|
+
<YStack
|
|
750
|
+
{...knobProps.gap}
|
|
751
|
+
// flexBasis auto, not flex={1}: a basis-0 chain resolves to 0 in an
|
|
752
|
+
// auto-height parent and collapses the table to a sliver. Same
|
|
753
|
+
// geometry as DataTableRoot's own root.
|
|
754
|
+
flexGrow={1}
|
|
755
|
+
flexShrink={1}
|
|
756
|
+
flexBasis="auto"
|
|
757
|
+
minHeight={0}
|
|
758
|
+
>
|
|
730
759
|
<FrappeReconnectIndicator config={connectionConfig} />
|
|
731
760
|
{savedFilters && savedFiltersHook && (
|
|
732
761
|
<XStack {...knobProps.gap} padding="$2">
|
|
@@ -75,10 +75,23 @@ function regionMeta(name: string, isTree: boolean) {
|
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
/** A chart of accounts: no parent field, no is_tree, the name is the path. */
|
|
79
|
+
function accountMeta(name: string) {
|
|
80
|
+
return {
|
|
81
|
+
name,
|
|
82
|
+
module: "QA",
|
|
83
|
+
title_field: "name",
|
|
84
|
+
is_tree: 0,
|
|
85
|
+
fields: [{ fieldname: "balance", fieldtype: "Currency", label: "Balance", in_list_view: 1 }],
|
|
86
|
+
permissions: [{ role: "All", read: 1 }],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
78
90
|
function handleMetaRequest(url: URL): Response | null {
|
|
79
91
|
const metaMatch = url.pathname.match(/^\/api\/resource\/DocType\/(.+)$/);
|
|
80
92
|
if (!metaMatch) return null;
|
|
81
93
|
const name = decodeURIComponent(metaMatch[1]);
|
|
94
|
+
if (name === "QaAccount") return jsonResponse({ data: accountMeta(name) });
|
|
82
95
|
return jsonResponse({ data: regionMeta(name, name !== "QaFlatDoc") });
|
|
83
96
|
}
|
|
84
97
|
|
|
@@ -143,6 +156,52 @@ export const NotATree = () => (
|
|
|
143
156
|
</FrappeProvider>
|
|
144
157
|
);
|
|
145
158
|
|
|
159
|
+
interface Account {
|
|
160
|
+
name: string;
|
|
161
|
+
doctype: string;
|
|
162
|
+
balance: string;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Seven rows, and every one of them is a leaf. "Assets", "Assets:Personal"
|
|
167
|
+
* and "Assets:Personal:Bank" are not documents at all.
|
|
168
|
+
*/
|
|
169
|
+
const accountDocs: Account[] = [
|
|
170
|
+
{ name: "Assets:Personal:Bank:Checking", doctype: "QaAccount", balance: "4,120.55" },
|
|
171
|
+
{ name: "Assets:Personal:Bank:Savings", doctype: "QaAccount", balance: "18,300.00" },
|
|
172
|
+
{ name: "Assets:Personal:Cash", doctype: "QaAccount", balance: "260.00" },
|
|
173
|
+
{ name: "Expenses:Groceries", doctype: "QaAccount", balance: "612.40" },
|
|
174
|
+
{ name: "Expenses:Utilities:Power", doctype: "QaAccount", balance: "148.90" },
|
|
175
|
+
{ name: "Income:Salary", doctype: "QaAccount", balance: "9,000.00" },
|
|
176
|
+
{ name: "Liabilities:Credit Card", doctype: "QaAccount", balance: "-732.10" },
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
/** Colon-path doctype: is_tree is 0, there is no parent field, tree renders. */
|
|
180
|
+
export const ColonPath = () => (
|
|
181
|
+
<FrappeProvider
|
|
182
|
+
baseURL={MOCK_HOST}
|
|
183
|
+
fixtures={new InMemoryFixtureProvider({ QaAccount: accountDocs })}
|
|
184
|
+
>
|
|
185
|
+
<FrappeTreeView
|
|
186
|
+
doctype="QaAccount"
|
|
187
|
+
pathSeparator=":"
|
|
188
|
+
pathField="name"
|
|
189
|
+
valueField="balance"
|
|
190
|
+
expandByDefault
|
|
191
|
+
onNodeClick={action("onNodeClick")}
|
|
192
|
+
onPathSelect={action("onPathSelect")}
|
|
193
|
+
/>
|
|
194
|
+
</FrappeProvider>
|
|
195
|
+
);
|
|
196
|
+
ColonPath.parameters = {
|
|
197
|
+
docs: {
|
|
198
|
+
description: {
|
|
199
|
+
story:
|
|
200
|
+
"The account IS its path (Assets:Personal:Bank:Checking). Meta reports is_tree 0 and the doctype has no parent field, so the parent-field path would paint the unsupported state instead. pathSeparator synthesises the branches client-side from each row's own key. A synthesised branch carries no document: clicking it fires onPathSelect with the path and no doc, and onNodeClick stays silent. The balances hang off the leaves, which are the only real rows.",
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
|
|
146
205
|
/** Tree doctype with zero root nodes: empty message. */
|
|
147
206
|
export const EmptyTree = () => (
|
|
148
207
|
<FrappeProvider baseURL={MOCK_HOST} fixtures={new InMemoryFixtureProvider({ QaRegionEmpty: [] })}>
|
package/src/FrappeTreeView.tsx
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { useDocTypeMeta
|
|
2
|
-
import { AsyncBoundary, TreeView, type TreeNode } from "@multiplatform.one/components";
|
|
1
|
+
import { useDocTypeMeta } from "@multiplatform.one/frappe";
|
|
2
|
+
import { AsyncBoundary, EmptyState, TreeView, type TreeNode } from "@multiplatform.one/components";
|
|
3
3
|
import { TreeStructureIcon } from "@phosphor-icons/react";
|
|
4
|
-
import React, { useCallback,
|
|
4
|
+
import React, { useCallback, useMemo, useState } from "react";
|
|
5
5
|
import { useTranslation } from "react-i18next";
|
|
6
6
|
import { Text, YStack, type YStackProps } from "tamagui";
|
|
7
|
-
import { useResolvedKnobs } from "@multiplatform.one/theme";
|
|
7
|
+
import { useGlyphColor, useResolvedKnobs } from "@multiplatform.one/theme";
|
|
8
8
|
import { formCommonColors } from "@multiplatform.one/forms";
|
|
9
9
|
import { useFrappeConfig } from "./FrappeProvider";
|
|
10
10
|
import { FrappeReconnectIndicator } from "./FrappeReconnectIndicator";
|
|
11
|
-
import {
|
|
11
|
+
import { useFrappeRows } from "./useFrappeRows";
|
|
12
12
|
|
|
13
13
|
export interface FrappeTreeViewProps<TDoc extends { name: string; doctype: string }> extends Omit<
|
|
14
14
|
YStackProps,
|
|
@@ -16,11 +16,32 @@ export interface FrappeTreeViewProps<TDoc extends { name: string; doctype: strin
|
|
|
16
16
|
> {
|
|
17
17
|
doctype: string;
|
|
18
18
|
parentField?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Separator that splits {@link FrappeTreeViewProps.pathField} into levels,
|
|
21
|
+
* e.g. ":" for an account named `Assets:Personal:Bank:Checking`. Setting it
|
|
22
|
+
* switches the tree to path mode: the branches between root and leaf are
|
|
23
|
+
* synthesised from the segments, `parentField` is neither read nor fetched,
|
|
24
|
+
* and the `is_tree` gate is skipped. A doctype whose hierarchy lives in the
|
|
25
|
+
* row's own key has no parent field and the server will never report
|
|
26
|
+
* `is_tree`.
|
|
27
|
+
*/
|
|
28
|
+
pathSeparator?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Row field holding the path. Path mode only; defaults to `name`. Path mode
|
|
31
|
+
* fetches `name`, this field, `valueField` and whatever `fields` adds, so a
|
|
32
|
+
* caller who needs more on the `onNodeClick` document asks for it there.
|
|
33
|
+
*/
|
|
34
|
+
pathField?: string;
|
|
19
35
|
titleField?: string;
|
|
20
36
|
valueField?: string;
|
|
21
37
|
fields?: readonly (keyof TDoc & string)[];
|
|
22
38
|
filters?: Partial<TDoc> | Array<[keyof TDoc & string, string, any]>;
|
|
23
39
|
onNodeClick?: (doc: Partial<TDoc>) => void;
|
|
40
|
+
/**
|
|
41
|
+
* Path-mode selection, fired for synthesised branches as well as documents.
|
|
42
|
+
* `doc` is present only when a document actually sits at that path.
|
|
43
|
+
*/
|
|
44
|
+
onPathSelect?: (path: string, doc?: Partial<TDoc>) => void;
|
|
24
45
|
/** Reserved for future DnD reparenting; not wired yet. */
|
|
25
46
|
enableDragDrop?: boolean;
|
|
26
47
|
/** Expand every branch on first paint (passed through to TreeView). */
|
|
@@ -88,20 +109,94 @@ export function buildTreeNodes<TDoc extends { name: string }>(
|
|
|
88
109
|
return sortDocs(roots).map(buildNode);
|
|
89
110
|
}
|
|
90
111
|
|
|
112
|
+
/** One level of the path forest, before it becomes TreeNodes. */
|
|
113
|
+
interface PathBucket<TDoc> {
|
|
114
|
+
path: string;
|
|
115
|
+
segment: string;
|
|
116
|
+
doc?: TDoc;
|
|
117
|
+
children: Map<string, PathBucket<TDoc>>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Build a TreeNode forest from paths held on the rows themselves, e.g.
|
|
122
|
+
* `Assets:Personal:Bank:Checking` split on ":".
|
|
123
|
+
*
|
|
124
|
+
* The branches between root and leaf are not rows, so they are synthesised:
|
|
125
|
+
* a synthesised node carries no `data` and its `id` is the path prefix it
|
|
126
|
+
* stands for. A row whose path value is empty falls back to a single segment
|
|
127
|
+
* of its own name, so nothing is silently dropped.
|
|
128
|
+
*/
|
|
129
|
+
export function buildPathTreeNodes<TDoc extends { name: string }>(
|
|
130
|
+
docs: TDoc[],
|
|
131
|
+
pathField: string,
|
|
132
|
+
separator: string,
|
|
133
|
+
): TreeNode<Record<string, unknown>>[] {
|
|
134
|
+
const roots = new Map<string, PathBucket<TDoc>>();
|
|
135
|
+
|
|
136
|
+
const splitPath = (doc: TDoc): string[] => {
|
|
137
|
+
const raw = (doc as Record<string, unknown>)[pathField];
|
|
138
|
+
const value = raw == null ? "" : String(raw);
|
|
139
|
+
// An empty separator would split the value into single characters.
|
|
140
|
+
const segments = separator ? value.split(separator) : [value];
|
|
141
|
+
const cleaned = segments.map((segment) => segment.trim()).filter((segment) => segment !== "");
|
|
142
|
+
return cleaned.length > 0 ? cleaned : [doc.name];
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
for (const doc of docs) {
|
|
146
|
+
let level = roots;
|
|
147
|
+
let prefix = "";
|
|
148
|
+
let bucket: PathBucket<TDoc> | undefined;
|
|
149
|
+
for (const segment of splitPath(doc)) {
|
|
150
|
+
prefix = prefix ? `${prefix}${separator}${segment}` : segment;
|
|
151
|
+
bucket = level.get(segment);
|
|
152
|
+
if (!bucket) {
|
|
153
|
+
bucket = { path: prefix, segment, children: new Map() };
|
|
154
|
+
level.set(segment, bucket);
|
|
155
|
+
}
|
|
156
|
+
level = bucket.children;
|
|
157
|
+
}
|
|
158
|
+
// Two rows on one path: the first keeps the node rather than the last
|
|
159
|
+
// row the live query happened to deliver.
|
|
160
|
+
if (bucket && !bucket.doc) bucket.doc = doc;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const toNodes = (level: Map<string, PathBucket<TDoc>>): TreeNode<Record<string, unknown>>[] =>
|
|
164
|
+
Array.from(level.values())
|
|
165
|
+
.sort((a, b) => a.segment.localeCompare(b.segment))
|
|
166
|
+
.map((bucket) => {
|
|
167
|
+
const children = toNodes(bucket.children);
|
|
168
|
+
return {
|
|
169
|
+
id: bucket.path,
|
|
170
|
+
label: bucket.segment,
|
|
171
|
+
data: bucket.doc as unknown as Record<string, unknown> | undefined,
|
|
172
|
+
children: children.length > 0 ? children : undefined,
|
|
173
|
+
};
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
return toNodes(roots);
|
|
177
|
+
}
|
|
178
|
+
|
|
91
179
|
/**
|
|
92
180
|
* Thin Frappe wrapper around the generic TreeView component.
|
|
93
181
|
*
|
|
94
182
|
* Fetches the full DocType list via `useFrappeCollection` / `useLiveQuery`
|
|
95
183
|
* (realtime-backed), then builds a `TreeNode` forest from the parent field.
|
|
184
|
+
*
|
|
185
|
+
* Pass `pathSeparator` instead when the hierarchy lives in the row's own key
|
|
186
|
+
* (`Assets:Personal:Bank:Checking`). The branches are synthesised client-side,
|
|
187
|
+
* so no parent field and no `is_tree` are needed.
|
|
96
188
|
*/
|
|
97
189
|
export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
98
190
|
doctype,
|
|
99
191
|
parentField: parentFieldProp,
|
|
192
|
+
pathSeparator,
|
|
193
|
+
pathField,
|
|
100
194
|
titleField: titleFieldProp,
|
|
101
195
|
valueField,
|
|
102
196
|
fields,
|
|
103
197
|
filters,
|
|
104
198
|
onNodeClick,
|
|
199
|
+
onPathSelect,
|
|
105
200
|
enableDragDrop: _enableDragDrop = false,
|
|
106
201
|
expandByDefault = false,
|
|
107
202
|
display = "default",
|
|
@@ -116,6 +211,7 @@ export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
|
116
211
|
|
|
117
212
|
const config = useFrappeConfig();
|
|
118
213
|
const { knobProps } = useResolvedKnobs();
|
|
214
|
+
const emptyIconColor = useGlyphColor(formCommonColors.muted);
|
|
119
215
|
const { t } = useTranslation();
|
|
120
216
|
const [selectedId, setSelectedId] = useState<string | undefined>();
|
|
121
217
|
|
|
@@ -123,8 +219,10 @@ export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
|
123
219
|
const finalAuth = auth ?? config?.auth;
|
|
124
220
|
const finalSyncOptions = syncOptions ?? config?.syncOptions;
|
|
125
221
|
|
|
126
|
-
if (!finalBaseURL) {
|
|
127
|
-
throw new Error(
|
|
222
|
+
if (!finalBaseURL && !config?.fixtures) {
|
|
223
|
+
throw new Error(
|
|
224
|
+
"FrappeTreeView requires baseURL prop or FrappeProvider with baseURL or fixtures",
|
|
225
|
+
);
|
|
128
226
|
}
|
|
129
227
|
|
|
130
228
|
const appConfig = useMemo(
|
|
@@ -135,6 +233,7 @@ export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
|
135
233
|
socketBaseURL: config?.socketBaseURL,
|
|
136
234
|
auth: finalAuth,
|
|
137
235
|
syncOptions: finalSyncOptions,
|
|
236
|
+
realtime: config?.realtime,
|
|
138
237
|
fixtures: config?.fixtures,
|
|
139
238
|
}),
|
|
140
239
|
[
|
|
@@ -142,6 +241,7 @@ export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
|
142
241
|
config?.socketPort,
|
|
143
242
|
config?.siteName,
|
|
144
243
|
config?.socketBaseURL,
|
|
244
|
+
config?.realtime,
|
|
145
245
|
finalAuth,
|
|
146
246
|
finalSyncOptions,
|
|
147
247
|
config?.fixtures,
|
|
@@ -150,6 +250,8 @@ export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
|
150
250
|
|
|
151
251
|
const { meta, isLoading: isMetaLoading, error: metaError } = useDocTypeMeta(appConfig, doctype);
|
|
152
252
|
|
|
253
|
+
const isPathMode = !!pathSeparator;
|
|
254
|
+
const effectivePathField = pathField ?? "name";
|
|
153
255
|
const effectiveTitleField = titleFieldProp ?? meta?.title_field ?? "name";
|
|
154
256
|
const effectiveParentField =
|
|
155
257
|
parentFieldProp ?? `parent_${doctype.toLowerCase().replace(/ /g, "_")}`;
|
|
@@ -158,67 +260,75 @@ export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
|
158
260
|
// lets callers continue (Guest peek / offline). Successful meta always
|
|
159
261
|
// wins for the is_tree gate — including rejecting flat DocTypes that
|
|
160
262
|
// happened to pass parentField.
|
|
161
|
-
|
|
162
|
-
|
|
263
|
+
//
|
|
264
|
+
// Path mode is the exception: the hierarchy comes from the row's own key,
|
|
265
|
+
// so there is nothing for is_tree to be right about.
|
|
266
|
+
const isKnownNotTree = !isPathMode && !!meta && !meta.is_tree;
|
|
267
|
+
const canProceed = isPathMode || !!meta?.is_tree || (!!metaError && !meta && !!parentFieldProp);
|
|
163
268
|
|
|
164
269
|
const effectiveFields = useMemo(() => {
|
|
165
270
|
const fieldSet = new Set<string>(fields as string[] | undefined);
|
|
166
271
|
fieldSet.add("name");
|
|
167
|
-
|
|
168
|
-
|
|
272
|
+
if (isPathMode) {
|
|
273
|
+
// The parent field does not exist on a path-shaped doctype; asking for
|
|
274
|
+
// it would fail the read on a live bench.
|
|
275
|
+
fieldSet.add(effectivePathField);
|
|
276
|
+
} else {
|
|
277
|
+
fieldSet.add(effectiveTitleField);
|
|
278
|
+
fieldSet.add(effectiveParentField);
|
|
279
|
+
}
|
|
169
280
|
if (valueField) fieldSet.add(valueField);
|
|
170
281
|
return Array.from(fieldSet) as (keyof TDoc & string)[];
|
|
171
|
-
}, [
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
toLiveLoadError(err, {
|
|
180
|
-
permissionMessage: t("You do not have permission to view {{doctype}}", { doctype }),
|
|
181
|
-
genericMessage: t("Failed to load {{doctype}} tree", { doctype }),
|
|
182
|
-
}),
|
|
183
|
-
);
|
|
184
|
-
},
|
|
185
|
-
[doctype, t],
|
|
186
|
-
);
|
|
282
|
+
}, [
|
|
283
|
+
fields,
|
|
284
|
+
isPathMode,
|
|
285
|
+
effectivePathField,
|
|
286
|
+
effectiveTitleField,
|
|
287
|
+
effectiveParentField,
|
|
288
|
+
valueField,
|
|
289
|
+
]);
|
|
187
290
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
291
|
+
// The shared doctype read (MPO-251): collection + live query + the honest
|
|
292
|
+
// error surface a bare collection swallows — without it a 403 or a network
|
|
293
|
+
// failure renders as an empty tree. `limit: null` keeps the tree on the
|
|
294
|
+
// bench's own page length, as it was before the hook existed.
|
|
295
|
+
const rowsMessages = useMemo(
|
|
296
|
+
() => ({
|
|
297
|
+
permission: t("You do not have permission to view {{doctype}}", { doctype }),
|
|
298
|
+
generic: t("Failed to load {{doctype}} tree", { doctype }),
|
|
299
|
+
}),
|
|
300
|
+
[doctype, t],
|
|
192
301
|
);
|
|
193
|
-
|
|
194
|
-
// A new collection (doctype/filter change) starts with a clean slate.
|
|
195
|
-
useEffect(() => {
|
|
196
|
-
setSyncError(null);
|
|
197
|
-
}, [collection]);
|
|
198
|
-
|
|
199
302
|
const {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
} =
|
|
204
|
-
|
|
205
|
-
|
|
303
|
+
rows: docs,
|
|
304
|
+
isQueryLoading: isDataLoading,
|
|
305
|
+
error: queryError,
|
|
306
|
+
} = useFrappeRows<TDoc>(appConfig, doctype, {
|
|
307
|
+
fields: effectiveFields,
|
|
308
|
+
filters,
|
|
309
|
+
limit: null,
|
|
310
|
+
enabled: canProceed && !isKnownNotTree,
|
|
311
|
+
messages: rowsMessages,
|
|
312
|
+
});
|
|
206
313
|
|
|
207
314
|
const treeNodes = useMemo(
|
|
208
|
-
() =>
|
|
209
|
-
|
|
315
|
+
() =>
|
|
316
|
+
pathSeparator
|
|
317
|
+
? buildPathTreeNodes(docs, effectivePathField, pathSeparator)
|
|
318
|
+
: buildTreeNodes(docs, effectiveParentField, effectiveTitleField),
|
|
319
|
+
[docs, pathSeparator, effectivePathField, effectiveParentField, effectiveTitleField],
|
|
210
320
|
);
|
|
211
321
|
|
|
212
|
-
const queryError =
|
|
213
|
-
syncError ?? (isError ? new Error(t("Failed to load {{doctype}} tree", { doctype })) : null);
|
|
214
|
-
|
|
215
322
|
const handleNodeSelect = useCallback(
|
|
216
323
|
(node: TreeNode<Record<string, unknown>>) => {
|
|
217
324
|
setSelectedId(node.id);
|
|
325
|
+
if (isPathMode) onPathSelect?.(node.id, node.data as Partial<TDoc> | undefined);
|
|
326
|
+
// A synthesised branch is not a document, so onNodeClick stays silent
|
|
327
|
+
// rather than handing a caller a name that would 404 on open.
|
|
218
328
|
if (!node.data) return;
|
|
219
329
|
onNodeClick?.(node.data as Partial<TDoc>);
|
|
220
330
|
},
|
|
221
|
-
[onNodeClick],
|
|
331
|
+
[isPathMode, onNodeClick, onPathSelect],
|
|
222
332
|
);
|
|
223
333
|
|
|
224
334
|
if (isMetaLoading) {
|
|
@@ -226,7 +336,7 @@ export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
|
226
336
|
return <AsyncBoundary layout="list" loading {...stackProps} />;
|
|
227
337
|
}
|
|
228
338
|
|
|
229
|
-
if (metaError && !meta && !parentFieldProp) {
|
|
339
|
+
if (metaError && !meta && !parentFieldProp && !isPathMode) {
|
|
230
340
|
if (error) return <>{error(metaError)}</>;
|
|
231
341
|
return (
|
|
232
342
|
<AsyncBoundary
|
|
@@ -241,12 +351,14 @@ export function FrappeTreeView<TDoc extends { name: string; doctype: string }>({
|
|
|
241
351
|
if (isKnownNotTree) {
|
|
242
352
|
const iconSize = Number(knobProps.controlIcon?.width) || 16;
|
|
243
353
|
return (
|
|
244
|
-
<
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
354
|
+
<EmptyState
|
|
355
|
+
title={t("This DocType does not support tree view")}
|
|
356
|
+
description={t(
|
|
357
|
+
"Pass pathSeparator and pathField to build the hierarchy from a path-shaped value on each row. parentField alone does not, because a flat DocType has no parent field.",
|
|
358
|
+
)}
|
|
359
|
+
icon={<TreeStructureIcon size={iconSize * 2} color={emptyIconColor} />}
|
|
360
|
+
{...stackProps}
|
|
361
|
+
/>
|
|
250
362
|
);
|
|
251
363
|
}
|
|
252
364
|
|
package/src/commentActions.ts
CHANGED
|
@@ -67,7 +67,7 @@ export function useFrappeCommentActions(
|
|
|
67
67
|
): FrappeCommentActions {
|
|
68
68
|
return useMemo(() => {
|
|
69
69
|
const app =
|
|
70
|
-
config && !config.fixtures
|
|
70
|
+
config?.baseURL && !config.fixtures
|
|
71
71
|
? new FrappeApp(config.baseURL, (config.auth ?? {}) as Record<string, unknown>)
|
|
72
72
|
: undefined;
|
|
73
73
|
|
package/src/components/tags.tsx
CHANGED
|
@@ -130,6 +130,7 @@ export function Timeline({
|
|
|
130
130
|
auth: config.auth,
|
|
131
131
|
syncOptions: config.syncOptions,
|
|
132
132
|
socketOptions: config.socketOptions,
|
|
133
|
+
realtime: config.realtime,
|
|
133
134
|
fixtures: config.fixtures,
|
|
134
135
|
}
|
|
135
136
|
: undefined;
|
|
@@ -207,7 +208,7 @@ export function Timeline({
|
|
|
207
208
|
|
|
208
209
|
const resolveSessionUser = useCallback(async (): Promise<string> => {
|
|
209
210
|
if (sessionUserRef.current) return sessionUserRef.current;
|
|
210
|
-
if (config && !config.fixtures) {
|
|
211
|
+
if (config?.baseURL && !config.fixtures) {
|
|
211
212
|
const app = new FrappeApp(config.baseURL, (config.auth ?? {}) as Record<string, unknown>);
|
|
212
213
|
sessionUserRef.current = await app.auth().getLoggedInUser();
|
|
213
214
|
} else {
|