@multiplatform.one/frappe-ui 7.11.0 → 7.16.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/README.md +2 -2
- package/dist/cjs/FrappeCalendar.cjs +1 -0
- package/dist/cjs/FrappeCalendar.native.js +1 -0
- package/dist/cjs/FrappeCalendar.native.js.map +1 -1
- package/dist/cjs/FrappeDashboard.cjs +8 -10
- package/dist/cjs/FrappeDashboard.native.js +8 -14
- package/dist/cjs/FrappeDashboard.native.js.map +1 -1
- package/dist/cjs/FrappeForm.cjs +465 -175
- package/dist/cjs/FrappeForm.native.js +611 -207
- package/dist/cjs/FrappeForm.native.js.map +1 -1
- package/dist/cjs/FrappeFormConnections.cjs +125 -0
- package/dist/cjs/FrappeFormConnections.native.js +149 -0
- package/dist/cjs/FrappeFormConnections.native.js.map +1 -0
- package/dist/cjs/FrappeImageView.cjs +7 -9
- package/dist/cjs/FrappeImageView.native.js +7 -13
- package/dist/cjs/FrappeImageView.native.js.map +1 -1
- package/dist/cjs/FrappeList.cjs +29 -4
- package/dist/cjs/FrappeList.native.js +37 -5
- package/dist/cjs/FrappeList.native.js.map +1 -1
- package/dist/cjs/FrappeListView.cjs +102 -29
- package/dist/cjs/FrappeListView.native.js +109 -29
- package/dist/cjs/FrappeListView.native.js.map +1 -1
- package/dist/cjs/FrappeProvider.cjs +7 -2
- package/dist/cjs/FrappeProvider.native.js +7 -2
- package/dist/cjs/FrappeProvider.native.js.map +1 -1
- package/dist/cjs/FrappeReportBuilder.cjs +10 -11
- package/dist/cjs/FrappeReportBuilder.native.js +10 -16
- package/dist/cjs/FrappeReportBuilder.native.js.map +1 -1
- package/dist/cjs/FrappeRowsReader.cjs +49 -0
- package/dist/cjs/FrappeRowsReader.native.js +53 -0
- package/dist/cjs/FrappeRowsReader.native.js.map +1 -0
- package/dist/cjs/FrappeTable.cjs +18 -6
- package/dist/cjs/FrappeTable.native.js +24 -6
- package/dist/cjs/FrappeTable.native.js.map +1 -1
- package/dist/cjs/fieldRegistry.cjs +36 -11
- package/dist/cjs/fieldRegistry.native.js +59 -11
- package/dist/cjs/fieldRegistry.native.js.map +1 -1
- package/dist/cjs/fields/Date/index.native.js +5 -2
- package/dist/cjs/fields/Date/index.native.js.map +1 -1
- package/dist/cjs/fields/Date/sheetKeyboard.cjs +2 -2
- package/dist/cjs/fields/Date/sheetKeyboard.native.js +2 -2
- package/dist/cjs/fields/Date/sheetKeyboard.native.js.map +1 -1
- package/dist/cjs/fields/DateRange/index.cjs +2 -1
- package/dist/cjs/fields/DateRange/index.native.js +4 -1
- package/dist/cjs/fields/DateRange/index.native.js.map +1 -1
- package/dist/cjs/fields/Password/index.cjs +1 -1
- package/dist/cjs/fields/Password/index.native.js +1 -1
- package/dist/cjs/formEngine/index.cjs +4 -2
- package/dist/cjs/formEngine/index.native.js +3 -1
- package/dist/cjs/formEngine/index.native.js.map +1 -1
- package/dist/cjs/formEngine/useSessionRoles.cjs +77 -0
- package/dist/cjs/formEngine/useSessionRoles.native.js +84 -0
- package/dist/cjs/formEngine/useSessionRoles.native.js.map +1 -0
- package/dist/cjs/frappeConnections.cjs +41 -0
- package/dist/cjs/frappeConnections.native.js +50 -0
- package/dist/cjs/frappeConnections.native.js.map +1 -0
- package/dist/cjs/frappeNavigation.cjs +107 -0
- package/dist/cjs/frappeNavigation.native.js +112 -0
- package/dist/cjs/frappeNavigation.native.js.map +1 -0
- package/dist/cjs/index.cjs +18 -1
- package/dist/cjs/index.native.js +18 -1
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/schemaForm/index.cjs +4 -1
- package/dist/cjs/schemaForm/index.native.js +4 -1
- package/dist/cjs/schemaForm/index.native.js.map +1 -1
- package/dist/cjs/useConnectionFilters.cjs +146 -0
- package/dist/cjs/useConnectionFilters.native.js +213 -0
- package/dist/cjs/useConnectionFilters.native.js.map +1 -0
- package/dist/cjs/useFrappePagination.cjs +37 -18
- package/dist/cjs/useFrappePagination.native.js +59 -23
- package/dist/cjs/useFrappePagination.native.js.map +1 -1
- package/dist/cjs/useFrappeRows.native.js.map +1 -1
- package/dist/esm/FrappeCalendar.mjs +1 -0
- package/dist/esm/FrappeCalendar.mjs.map +1 -1
- package/dist/esm/FrappeCalendar.native.js +1 -0
- package/dist/esm/FrappeCalendar.native.js.map +1 -1
- package/dist/esm/FrappeDashboard.mjs +9 -11
- package/dist/esm/FrappeDashboard.mjs.map +1 -1
- package/dist/esm/FrappeDashboard.native.js +9 -15
- package/dist/esm/FrappeDashboard.native.js.map +1 -1
- package/dist/esm/FrappeForm.mjs +471 -181
- package/dist/esm/FrappeForm.mjs.map +1 -1
- package/dist/esm/FrappeForm.native.js +599 -195
- package/dist/esm/FrappeForm.native.js.map +1 -1
- package/dist/esm/FrappeFormConnections.mjs +99 -0
- package/dist/esm/FrappeFormConnections.mjs.map +1 -0
- package/dist/esm/FrappeFormConnections.native.js +120 -0
- package/dist/esm/FrappeFormConnections.native.js.map +1 -0
- package/dist/esm/FrappeImageView.mjs +8 -10
- package/dist/esm/FrappeImageView.mjs.map +1 -1
- package/dist/esm/FrappeImageView.native.js +8 -14
- package/dist/esm/FrappeImageView.native.js.map +1 -1
- package/dist/esm/FrappeList.mjs +31 -6
- package/dist/esm/FrappeList.mjs.map +1 -1
- package/dist/esm/FrappeList.native.js +39 -7
- package/dist/esm/FrappeList.native.js.map +1 -1
- package/dist/esm/FrappeListView.mjs +103 -30
- package/dist/esm/FrappeListView.mjs.map +1 -1
- package/dist/esm/FrappeListView.native.js +110 -30
- package/dist/esm/FrappeListView.native.js.map +1 -1
- package/dist/esm/FrappeProvider.mjs +7 -2
- package/dist/esm/FrappeProvider.mjs.map +1 -1
- package/dist/esm/FrappeProvider.native.js +7 -2
- package/dist/esm/FrappeProvider.native.js.map +1 -1
- package/dist/esm/FrappeReportBuilder.mjs +11 -12
- package/dist/esm/FrappeReportBuilder.mjs.map +1 -1
- package/dist/esm/FrappeReportBuilder.native.js +11 -17
- package/dist/esm/FrappeReportBuilder.native.js.map +1 -1
- package/dist/esm/FrappeRowsReader.mjs +24 -0
- package/dist/esm/FrappeRowsReader.mjs.map +1 -0
- package/dist/esm/FrappeRowsReader.native.js +25 -0
- package/dist/esm/FrappeRowsReader.native.js.map +1 -0
- package/dist/esm/FrappeTable.mjs +18 -6
- package/dist/esm/FrappeTable.mjs.map +1 -1
- package/dist/esm/FrappeTable.native.js +24 -6
- package/dist/esm/FrappeTable.native.js.map +1 -1
- package/dist/esm/fieldRegistry.mjs +35 -12
- package/dist/esm/fieldRegistry.mjs.map +1 -1
- package/dist/esm/fieldRegistry.native.js +58 -12
- package/dist/esm/fieldRegistry.native.js.map +1 -1
- package/dist/esm/fields/Date/index.native.js +6 -3
- package/dist/esm/fields/Date/index.native.js.map +1 -1
- package/dist/esm/fields/Date/sheetKeyboard.mjs +2 -2
- package/dist/esm/fields/Date/sheetKeyboard.mjs.map +1 -1
- package/dist/esm/fields/Date/sheetKeyboard.native.js +2 -2
- package/dist/esm/fields/Date/sheetKeyboard.native.js.map +1 -1
- package/dist/esm/fields/DateRange/index.mjs +2 -1
- package/dist/esm/fields/DateRange/index.mjs.map +1 -1
- package/dist/esm/fields/DateRange/index.native.js +4 -1
- package/dist/esm/fields/DateRange/index.native.js.map +1 -1
- package/dist/esm/fields/Password/index.mjs +1 -1
- package/dist/esm/fields/Password/index.mjs.map +1 -1
- package/dist/esm/fields/Password/index.native.js +1 -1
- package/dist/esm/fields/Password/index.native.js.map +1 -1
- package/dist/esm/formEngine/index.mjs +2 -1
- package/dist/esm/formEngine/index.mjs.map +1 -1
- package/dist/esm/formEngine/index.native.js +2 -1
- package/dist/esm/formEngine/index.native.js.map +1 -1
- package/dist/esm/formEngine/useSessionRoles.mjs +52 -0
- package/dist/esm/formEngine/useSessionRoles.mjs.map +1 -0
- package/dist/esm/formEngine/useSessionRoles.native.js +56 -0
- package/dist/esm/formEngine/useSessionRoles.native.js.map +1 -0
- package/dist/esm/frappeConnections.mjs +15 -0
- package/dist/esm/frappeConnections.mjs.map +1 -0
- package/dist/esm/frappeConnections.native.js +21 -0
- package/dist/esm/frappeConnections.native.js.map +1 -0
- package/dist/esm/frappeNavigation.mjs +78 -0
- package/dist/esm/frappeNavigation.mjs.map +1 -0
- package/dist/esm/frappeNavigation.native.js +80 -0
- package/dist/esm/frappeNavigation.native.js.map +1 -0
- package/dist/esm/index.mjs +7 -3
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +7 -3
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/schemaForm/index.mjs +4 -1
- package/dist/esm/schemaForm/index.mjs.map +1 -1
- package/dist/esm/schemaForm/index.native.js +4 -1
- package/dist/esm/schemaForm/index.native.js.map +1 -1
- package/dist/esm/useConnectionFilters.mjs +121 -0
- package/dist/esm/useConnectionFilters.mjs.map +1 -0
- package/dist/esm/useConnectionFilters.native.js +185 -0
- package/dist/esm/useConnectionFilters.native.js.map +1 -0
- package/dist/esm/useFrappePagination.mjs +38 -19
- package/dist/esm/useFrappePagination.mjs.map +1 -1
- package/dist/esm/useFrappePagination.native.js +60 -24
- package/dist/esm/useFrappePagination.native.js.map +1 -1
- package/dist/esm/useFrappeRows.mjs.map +1 -1
- package/dist/esm/useFrappeRows.native.js.map +1 -1
- package/dist/jsx/FrappeCalendar.mjs +1 -0
- package/dist/jsx/FrappeCalendar.mjs.map +1 -1
- package/dist/jsx/FrappeCalendar.native.js +1 -0
- package/dist/jsx/FrappeCalendar.native.js.map +1 -1
- package/dist/jsx/FrappeDashboard.mjs +9 -11
- package/dist/jsx/FrappeDashboard.mjs.map +1 -1
- package/dist/jsx/FrappeDashboard.native.js +8 -14
- package/dist/jsx/FrappeDashboard.native.js.map +1 -1
- package/dist/jsx/FrappeForm.mjs +471 -181
- package/dist/jsx/FrappeForm.mjs.map +1 -1
- package/dist/jsx/FrappeForm.native.js +611 -207
- package/dist/jsx/FrappeForm.native.js.map +1 -1
- package/dist/jsx/FrappeFormConnections.mjs +99 -0
- package/dist/jsx/FrappeFormConnections.mjs.map +1 -0
- package/dist/jsx/FrappeFormConnections.native.js +149 -0
- package/dist/jsx/FrappeFormConnections.native.js.map +1 -0
- package/dist/jsx/FrappeImageView.mjs +8 -10
- package/dist/jsx/FrappeImageView.mjs.map +1 -1
- package/dist/jsx/FrappeImageView.native.js +7 -13
- package/dist/jsx/FrappeImageView.native.js.map +1 -1
- package/dist/jsx/FrappeList.mjs +31 -6
- package/dist/jsx/FrappeList.mjs.map +1 -1
- package/dist/jsx/FrappeList.native.js +37 -5
- package/dist/jsx/FrappeList.native.js.map +1 -1
- package/dist/jsx/FrappeListView.mjs +103 -30
- package/dist/jsx/FrappeListView.mjs.map +1 -1
- package/dist/jsx/FrappeListView.native.js +109 -29
- package/dist/jsx/FrappeListView.native.js.map +1 -1
- package/dist/jsx/FrappeProvider.mjs +7 -2
- package/dist/jsx/FrappeProvider.mjs.map +1 -1
- package/dist/jsx/FrappeProvider.native.js +7 -2
- package/dist/jsx/FrappeProvider.native.js.map +1 -1
- package/dist/jsx/FrappeReportBuilder.mjs +11 -12
- package/dist/jsx/FrappeReportBuilder.mjs.map +1 -1
- package/dist/jsx/FrappeReportBuilder.native.js +10 -16
- package/dist/jsx/FrappeReportBuilder.native.js.map +1 -1
- package/dist/jsx/FrappeRowsReader.mjs +24 -0
- package/dist/jsx/FrappeRowsReader.mjs.map +1 -0
- package/dist/jsx/FrappeRowsReader.native.js +53 -0
- package/dist/jsx/FrappeRowsReader.native.js.map +1 -0
- package/dist/jsx/FrappeTable.mjs +18 -6
- package/dist/jsx/FrappeTable.mjs.map +1 -1
- package/dist/jsx/FrappeTable.native.js +24 -6
- package/dist/jsx/FrappeTable.native.js.map +1 -1
- package/dist/jsx/fieldRegistry.mjs +35 -12
- package/dist/jsx/fieldRegistry.mjs.map +1 -1
- package/dist/jsx/fieldRegistry.native.js +59 -11
- package/dist/jsx/fieldRegistry.native.js.map +1 -1
- package/dist/jsx/fields/Date/index.native.js +5 -2
- package/dist/jsx/fields/Date/index.native.js.map +1 -1
- package/dist/jsx/fields/Date/sheetKeyboard.mjs +2 -2
- package/dist/jsx/fields/Date/sheetKeyboard.mjs.map +1 -1
- package/dist/jsx/fields/Date/sheetKeyboard.native.js +2 -2
- package/dist/jsx/fields/Date/sheetKeyboard.native.js.map +1 -1
- package/dist/jsx/fields/DateRange/index.mjs +2 -1
- package/dist/jsx/fields/DateRange/index.mjs.map +1 -1
- package/dist/jsx/fields/DateRange/index.native.js +4 -1
- package/dist/jsx/fields/DateRange/index.native.js.map +1 -1
- package/dist/jsx/fields/Password/index.mjs +1 -1
- package/dist/jsx/fields/Password/index.mjs.map +1 -1
- package/dist/jsx/fields/Password/index.native.js +1 -1
- package/dist/jsx/fields/Password/index.native.js.map +1 -1
- package/dist/jsx/formEngine/index.mjs +2 -1
- package/dist/jsx/formEngine/index.mjs.map +1 -1
- package/dist/jsx/formEngine/index.native.js +3 -1
- package/dist/jsx/formEngine/index.native.js.map +1 -1
- package/dist/jsx/formEngine/useSessionRoles.mjs +52 -0
- package/dist/jsx/formEngine/useSessionRoles.mjs.map +1 -0
- package/dist/jsx/formEngine/useSessionRoles.native.js +84 -0
- package/dist/jsx/formEngine/useSessionRoles.native.js.map +1 -0
- package/dist/jsx/frappeConnections.mjs +15 -0
- package/dist/jsx/frappeConnections.mjs.map +1 -0
- package/dist/jsx/frappeConnections.native.js +50 -0
- package/dist/jsx/frappeConnections.native.js.map +1 -0
- package/dist/jsx/frappeNavigation.mjs +78 -0
- package/dist/jsx/frappeNavigation.mjs.map +1 -0
- package/dist/jsx/frappeNavigation.native.js +112 -0
- package/dist/jsx/frappeNavigation.native.js.map +1 -0
- package/dist/jsx/index.js +7 -3
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +7 -3
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +18 -1
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/schemaForm/index.mjs +4 -1
- package/dist/jsx/schemaForm/index.mjs.map +1 -1
- package/dist/jsx/schemaForm/index.native.js +4 -1
- package/dist/jsx/schemaForm/index.native.js.map +1 -1
- package/dist/jsx/useConnectionFilters.mjs +121 -0
- package/dist/jsx/useConnectionFilters.mjs.map +1 -0
- package/dist/jsx/useConnectionFilters.native.js +213 -0
- package/dist/jsx/useConnectionFilters.native.js.map +1 -0
- package/dist/jsx/useFrappePagination.mjs +38 -19
- package/dist/jsx/useFrappePagination.mjs.map +1 -1
- package/dist/jsx/useFrappePagination.native.js +59 -23
- package/dist/jsx/useFrappePagination.native.js.map +1 -1
- package/dist/jsx/useFrappeRows.mjs.map +1 -1
- package/dist/jsx/useFrappeRows.native.js.map +1 -1
- package/package.json +24 -20
- package/src/FileBrowser/AttachLibrary.stories.tsx +23 -0
- package/src/FrappeCalendar.radius.spec.tsx +55 -0
- package/src/FrappeCalendar.tsx +1 -0
- package/src/FrappeDashboard.tsx +11 -16
- package/src/FrappeForm.connections.spec.tsx +280 -0
- package/src/FrappeForm.connections.stories.tsx +93 -0
- package/src/FrappeForm.deskSemantics.spec.tsx +284 -0
- package/src/FrappeForm.tsx +560 -145
- package/src/FrappeFormConnections.tsx +148 -0
- package/src/FrappeGuestMeta.spec.tsx +143 -0
- package/src/FrappeImageView.tsx +8 -12
- package/src/FrappeList.tsx +71 -15
- package/src/FrappeListView.cards.spec.tsx +175 -0
- package/src/FrappeListView.cards.stories.tsx +131 -0
- package/src/FrappeListView.connections.spec.tsx +192 -0
- package/src/FrappeListView.connections.stories.tsx +99 -0
- package/src/FrappeListView.seed.spec.tsx +228 -0
- package/src/FrappeListView.tsx +177 -31
- package/src/FrappeProvider.tsx +13 -1
- package/src/FrappeReportBuilder.tsx +11 -19
- package/src/FrappeRowsReader.tsx +38 -0
- package/src/FrappeTable.optionalProps.spec.tsx +249 -0
- package/src/FrappeTable.spec.tsx +32 -42
- package/src/FrappeTable.stories.spec.tsx +55 -0
- package/src/FrappeTable.stories.tsx +28 -37
- package/src/FrappeTable.tsx +108 -45
- package/src/childTableDependsOn.spec.tsx +85 -0
- package/src/desk/DeskFormSidebar.spec.tsx +20 -0
- package/src/desk/DeskFormSidebar.stories.tsx +42 -0
- package/src/fieldRegistry.spec.tsx +27 -64
- package/src/fieldRegistry.ts +71 -14
- package/src/fields/Date/index.native.tsx +4 -2
- package/src/fields/Date/sheetKeyboard.spec.ts +14 -5
- package/src/fields/Date/sheetKeyboard.ts +12 -4
- package/src/fields/DateRange/DateRange.spec.tsx +67 -0
- package/src/fields/DateRange/index.tsx +5 -1
- package/src/fields/LinkTree.spec.tsx +8 -0
- package/src/fields/LinkTree.stories.tsx +28 -5
- package/src/fields/Password/index.tsx +1 -1
- package/src/fields/Select/Select.hydration.spec.tsx +177 -0
- package/src/formEngine/doctypeMeta.ts +15 -114
- package/src/formEngine/index.ts +2 -0
- package/src/formEngine/seam.spec.ts +23 -4
- package/src/formEngine/useSessionRoles.ts +73 -0
- package/src/frappeConnections.ts +50 -0
- package/src/frappeNavigation.tsx +112 -0
- package/src/frappeRoutes.spec.tsx +335 -0
- package/src/index.ts +28 -1
- package/src/schemaForm/index.tsx +1 -0
- package/src/useConnectionFilters.tsx +157 -0
- package/src/useFrappePagination.ts +70 -26
- package/src/useFrappeRows.sharedPath.spec.tsx +206 -0
- package/src/useFrappeRows.ts +5 -4
- package/types/FrappeCalendar.d.ts.map +1 -1
- package/types/FrappeDashboard.d.ts +3 -4
- package/types/FrappeDashboard.d.ts.map +1 -1
- package/types/FrappeForm.d.ts +57 -5
- package/types/FrappeForm.d.ts.map +1 -1
- package/types/FrappeFormConnections.d.ts +18 -0
- package/types/FrappeFormConnections.d.ts.map +1 -0
- package/types/FrappeImageView.d.ts +2 -3
- package/types/FrappeImageView.d.ts.map +1 -1
- package/types/FrappeList.d.ts +20 -2
- package/types/FrappeList.d.ts.map +1 -1
- package/types/FrappeListView.d.ts +53 -3
- package/types/FrappeListView.d.ts.map +1 -1
- package/types/FrappeProvider.d.ts +8 -1
- package/types/FrappeProvider.d.ts.map +1 -1
- package/types/FrappeReportBuilder.d.ts.map +1 -1
- package/types/FrappeRowsReader.d.ts +26 -0
- package/types/FrappeRowsReader.d.ts.map +1 -0
- package/types/FrappeTable.d.ts +39 -8
- package/types/FrappeTable.d.ts.map +1 -1
- package/types/fieldRegistry.d.ts +17 -3
- package/types/fieldRegistry.d.ts.map +1 -1
- package/types/fields/Date/index.native.d.ts.map +1 -1
- package/types/fields/Date/sheetKeyboard.d.ts +4 -3
- package/types/fields/Date/sheetKeyboard.d.ts.map +1 -1
- package/types/fields/DateRange/index.d.ts.map +1 -1
- package/types/formEngine/doctypeMeta.d.ts +10 -114
- package/types/formEngine/doctypeMeta.d.ts.map +1 -1
- package/types/formEngine/index.d.ts +1 -0
- package/types/formEngine/index.d.ts.map +1 -1
- package/types/formEngine/useSessionRoles.d.ts +19 -0
- package/types/formEngine/useSessionRoles.d.ts.map +1 -0
- package/types/frappeConnections.d.ts +33 -0
- package/types/frappeConnections.d.ts.map +1 -0
- package/types/frappeNavigation.d.ts +49 -0
- package/types/frappeNavigation.d.ts.map +1 -0
- package/types/index.d.ts +7 -3
- package/types/index.d.ts.map +1 -1
- package/types/schemaForm/index.d.ts.map +1 -1
- package/types/useConnectionFilters.d.ts +34 -0
- package/types/useConnectionFilters.d.ts.map +1 -0
- package/types/useFrappePagination.d.ts +18 -5
- package/types/useFrappePagination.d.ts.map +1 -1
- package/types/useFrappeRows.d.ts +5 -4
- package/types/useFrappeRows.d.ts.map +1 -1
- package/src/FileBrowser/AttachLibrary.spec.tsx +0 -74
package/src/FrappeListView.tsx
CHANGED
|
@@ -6,12 +6,24 @@ import { useTranslation } from "react-i18next";
|
|
|
6
6
|
import { Button, SearchInput, Spinner } from "@multiplatform.one/forms";
|
|
7
7
|
import { Text, View, XStack, YStack, isWeb, useTheme, type YStackProps } from "tamagui";
|
|
8
8
|
import { SavedFilterDropdown, useSavedFilters, type ParsedFilter } from "@multiplatform.one/table";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
AsyncBoundary,
|
|
11
|
+
Avatar,
|
|
12
|
+
ListPageLayout,
|
|
13
|
+
PageHeader,
|
|
14
|
+
ViewSwitcher,
|
|
15
|
+
componentColors,
|
|
16
|
+
type ImageGridProps,
|
|
17
|
+
} from "@multiplatform.one/components";
|
|
10
18
|
import { pressTargetStyle, useResolvedKnobs } from "@multiplatform.one/theme";
|
|
11
19
|
import { storage } from "@multiplatform.one/store";
|
|
12
20
|
import { useFrappeConfig } from "./FrappeProvider";
|
|
13
|
-
import { FrappeList } from "./FrappeList";
|
|
21
|
+
import { FrappeList, type FrappeListProps } from "./FrappeList";
|
|
14
22
|
import { FrappeTable } from "./FrappeTable";
|
|
23
|
+
import { frappeRouteHref, useFrappeRouter } from "./frappeNavigation";
|
|
24
|
+
import { connectionsFromMeta, type FrappeConnection } from "./frappeConnections";
|
|
25
|
+
import { isPermissionError } from "./liveErrors";
|
|
26
|
+
import { useConnectionFilters, type FrappeDoctypeFilter } from "./useConnectionFilters";
|
|
15
27
|
|
|
16
28
|
interface ListFieldConfig {
|
|
17
29
|
key: string;
|
|
@@ -19,7 +31,7 @@ interface ListFieldConfig {
|
|
|
19
31
|
render?: (value: any, doc: any) => React.ReactNode;
|
|
20
32
|
}
|
|
21
33
|
|
|
22
|
-
export type ListViewMode = "list" | "table";
|
|
34
|
+
export type ListViewMode = "list" | "table" | "grid";
|
|
23
35
|
|
|
24
36
|
export interface FrappeListViewProps<TDoc extends { name: string; doctype: string }> extends Omit<
|
|
25
37
|
YStackProps,
|
|
@@ -27,12 +39,58 @@ export interface FrappeListViewProps<TDoc extends { name: string; doctype: strin
|
|
|
27
39
|
> {
|
|
28
40
|
doctype: string;
|
|
29
41
|
fields?: readonly (keyof TDoc & string)[];
|
|
30
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Doctypes linking back to this one (desk Connections). A four-part filter
|
|
44
|
+
* on one of them, `[doctype, field, operator, value]`, narrows this list to
|
|
45
|
+
* the records its matching rows name. Defaults to the doctype's meta.links.
|
|
46
|
+
*/
|
|
47
|
+
connections?: readonly FrappeConnection[];
|
|
48
|
+
filters?: Partial<TDoc> | Array<[keyof TDoc & string, string, unknown] | FrappeDoctypeFilter>;
|
|
31
49
|
defaultViewMode?: ListViewMode;
|
|
50
|
+
/** Controlled view mode; the stored per-doctype choice is then ignored. */
|
|
51
|
+
viewMode?: ListViewMode;
|
|
52
|
+
onViewModeChange?: (mode: ListViewMode) => void;
|
|
32
53
|
onItemClick?: (doc: Partial<TDoc>) => void;
|
|
33
54
|
onAdd?: () => void;
|
|
55
|
+
/**
|
|
56
|
+
* The path the doctype's pages live under (`/moves`). Given, the view is
|
|
57
|
+
* the doctype's list page: it carries the list page template with the
|
|
58
|
+
* doctype as its title, a row opens `route/<name>` and Add opens
|
|
59
|
+
* `route/new` through the FrappeProvider's navigation. Add waits for the
|
|
60
|
+
* doctype's meta, so a reader who cannot load it is not offered a form.
|
|
61
|
+
*/
|
|
62
|
+
route?: string;
|
|
63
|
+
/**
|
|
64
|
+
* The query the list reads, beyond fields and filters. Give a route loader
|
|
65
|
+
* the same order and limit (`loadDocList`) so its server page and the live
|
|
66
|
+
* page match; `initialRows` is that server page.
|
|
67
|
+
*/
|
|
68
|
+
orderBy?: FrappeListProps<TDoc>["orderBy"];
|
|
69
|
+
limit?: number;
|
|
70
|
+
initialRows?: readonly Partial<TDoc>[];
|
|
34
71
|
columns?: DataTableColumn<Partial<TDoc>>[];
|
|
35
72
|
displayFields?: ListFieldConfig[];
|
|
73
|
+
/**
|
|
74
|
+
* Per-row card slot. Given, the view gains a card grid (`grid` mode, the
|
|
75
|
+
* catalog ImageGrid) that draws each row with it; loading, empty and error
|
|
76
|
+
* stay the view's own states.
|
|
77
|
+
*/
|
|
78
|
+
renderCard?: (doc: Partial<TDoc>, index: number) => React.ReactNode;
|
|
79
|
+
/** Card grid: column count, tile rung and media aspect. */
|
|
80
|
+
gridProps?: Pick<ImageGridProps<Partial<TDoc>>, "columns" | "tileSize" | "mediaAspect">;
|
|
81
|
+
/** Replaces the default empty message in list and card modes. */
|
|
82
|
+
emptyState?: React.ReactNode;
|
|
83
|
+
/**
|
|
84
|
+
* Error-state retry. Defaults to remounting the list, which restarts its
|
|
85
|
+
* sync only when nothing else still holds the failed collection.
|
|
86
|
+
*/
|
|
87
|
+
onRetry?: () => void;
|
|
88
|
+
/** Rows revealed per page in list and card modes (default 20). */
|
|
89
|
+
pageSize?: number;
|
|
90
|
+
/** False drops the list/card search band (a screen that owns its own search). */
|
|
91
|
+
showSearch?: boolean;
|
|
92
|
+
/** False renders the view without its card surface, flush in the page. */
|
|
93
|
+
surface?: boolean;
|
|
36
94
|
showToolbar?: boolean;
|
|
37
95
|
showFilterSidebar?: boolean;
|
|
38
96
|
/** @deprecated The toolbar always renders the List/Table switcher now. */
|
|
@@ -90,7 +148,7 @@ function resolveImageUrl(value: unknown, baseURL: string): string {
|
|
|
90
148
|
async function getStoredViewMode(doctype: string): Promise<ListViewMode | null> {
|
|
91
149
|
try {
|
|
92
150
|
const stored = await Promise.resolve(storage.getItem(`${storageKeyPrefix}${doctype}`));
|
|
93
|
-
if (stored === "list" || stored === "table") return stored;
|
|
151
|
+
if (stored === "list" || stored === "table" || stored === "grid") return stored;
|
|
94
152
|
} catch {
|
|
95
153
|
// storage not available
|
|
96
154
|
}
|
|
@@ -114,12 +172,26 @@ async function setStoredViewMode(doctype: string, mode: ListViewMode): Promise<v
|
|
|
114
172
|
export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
115
173
|
doctype,
|
|
116
174
|
fields,
|
|
175
|
+
connections,
|
|
117
176
|
filters,
|
|
118
177
|
defaultViewMode = "list",
|
|
119
|
-
|
|
120
|
-
|
|
178
|
+
viewMode: controlledViewMode,
|
|
179
|
+
onViewModeChange,
|
|
180
|
+
onItemClick: onItemClickProp,
|
|
181
|
+
onAdd: onAddProp,
|
|
182
|
+
route,
|
|
183
|
+
orderBy,
|
|
184
|
+
limit,
|
|
185
|
+
initialRows,
|
|
121
186
|
columns,
|
|
122
187
|
displayFields,
|
|
188
|
+
renderCard,
|
|
189
|
+
gridProps,
|
|
190
|
+
emptyState,
|
|
191
|
+
onRetry,
|
|
192
|
+
pageSize,
|
|
193
|
+
showSearch = true,
|
|
194
|
+
surface = true,
|
|
123
195
|
showToolbar = true,
|
|
124
196
|
showFilterSidebar = false,
|
|
125
197
|
// deprecated: switcher always renders; destructured so it stays out of stackProps
|
|
@@ -130,6 +202,7 @@ export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
|
130
202
|
...stackProps
|
|
131
203
|
}: FrappeListViewProps<TDoc>) {
|
|
132
204
|
const config = useFrappeConfig();
|
|
205
|
+
const navigate = useFrappeRouter()?.navigate;
|
|
133
206
|
const { knobProps } = useResolvedKnobs();
|
|
134
207
|
const { t } = useTranslation();
|
|
135
208
|
const theme = useTheme();
|
|
@@ -153,7 +226,10 @@ export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
|
153
226
|
fixtures: config?.fixtures,
|
|
154
227
|
};
|
|
155
228
|
|
|
156
|
-
const [
|
|
229
|
+
const [storedViewMode, setViewModeState] = useState<ListViewMode>(defaultViewMode);
|
|
230
|
+
const requestedViewMode = controlledViewMode ?? storedViewMode;
|
|
231
|
+
const viewMode: ListViewMode =
|
|
232
|
+
requestedViewMode === "grid" && !renderCard ? "list" : requestedViewMode;
|
|
157
233
|
|
|
158
234
|
useEffect(() => {
|
|
159
235
|
let cancelled = false;
|
|
@@ -171,10 +247,12 @@ export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
|
171
247
|
|
|
172
248
|
const setViewMode = useCallback(
|
|
173
249
|
(mode: ListViewMode) => {
|
|
250
|
+
onViewModeChange?.(mode);
|
|
251
|
+
if (controlledViewMode !== undefined) return;
|
|
174
252
|
setViewModeState(mode);
|
|
175
253
|
void setStoredViewMode(doctype, mode);
|
|
176
254
|
},
|
|
177
|
-
[doctype],
|
|
255
|
+
[doctype, controlledViewMode, onViewModeChange],
|
|
178
256
|
);
|
|
179
257
|
|
|
180
258
|
const {
|
|
@@ -183,6 +261,27 @@ export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
|
183
261
|
error: metaError,
|
|
184
262
|
} = useDocTypeMeta(connectionConfig, doctype);
|
|
185
263
|
|
|
264
|
+
const onItemClick =
|
|
265
|
+
onItemClickProp ??
|
|
266
|
+
(route !== undefined && navigate
|
|
267
|
+
? (doc: Partial<TDoc>) => {
|
|
268
|
+
if (doc.name) navigate(frappeRouteHref(route, { mode: "view", name: doc.name }));
|
|
269
|
+
}
|
|
270
|
+
: undefined);
|
|
271
|
+
const onAdd =
|
|
272
|
+
onAddProp ??
|
|
273
|
+
(route !== undefined && navigate && meta
|
|
274
|
+
? () => navigate(frappeRouteHref(route, { mode: "create" }))
|
|
275
|
+
: undefined);
|
|
276
|
+
const asPage = (view: React.ReactElement) =>
|
|
277
|
+
route === undefined ? (
|
|
278
|
+
view
|
|
279
|
+
) : (
|
|
280
|
+
<ListPageLayout scroll={false} header={<PageHeader title={doctype} divider={false} />}>
|
|
281
|
+
{view}
|
|
282
|
+
</ListPageLayout>
|
|
283
|
+
);
|
|
284
|
+
|
|
186
285
|
// Guest fallback: DocType meta is permission-gated (Guests get 403) while
|
|
187
286
|
// the documents themselves are often guest-readable. Peek one doc with
|
|
188
287
|
// fields=["*"] and derive display fields from its keys so the views render
|
|
@@ -352,6 +451,18 @@ export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
|
352
451
|
setActiveFilters(filters);
|
|
353
452
|
}, [filters]);
|
|
354
453
|
|
|
454
|
+
const effectiveConnections = useMemo(
|
|
455
|
+
() => connections ?? (isMetaLoading ? undefined : connectionsFromMeta(meta)),
|
|
456
|
+
[connections, isMetaLoading, meta],
|
|
457
|
+
);
|
|
458
|
+
const linkFilters = useConnectionFilters(
|
|
459
|
+
connectionConfig,
|
|
460
|
+
doctype,
|
|
461
|
+
activeFilters as Parameters<typeof useConnectionFilters>[2],
|
|
462
|
+
effectiveConnections,
|
|
463
|
+
);
|
|
464
|
+
const resolvedFilters = linkFilters.filters as typeof activeFilters;
|
|
465
|
+
|
|
355
466
|
// List-mode search: a debounced server-side `like` on the doctype's title
|
|
356
467
|
// field, merged into the filters useFrappePagination already accepts (the
|
|
357
468
|
// pagination layer has no orFilters plumbing, so one well-chosen field
|
|
@@ -368,21 +479,21 @@ export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
|
368
479
|
|
|
369
480
|
const listFilters = useMemo(() => {
|
|
370
481
|
const query = debouncedSearch.trim();
|
|
371
|
-
if (!query) return
|
|
482
|
+
if (!query) return resolvedFilters;
|
|
372
483
|
const searchFilter = [searchField, "like", `%${query}%`] as [
|
|
373
484
|
keyof TDoc & string,
|
|
374
485
|
string,
|
|
375
486
|
unknown,
|
|
376
487
|
];
|
|
377
|
-
if (!
|
|
378
|
-
if (Array.isArray(
|
|
488
|
+
if (!resolvedFilters) return [searchFilter];
|
|
489
|
+
if (Array.isArray(resolvedFilters)) return [...resolvedFilters, searchFilter];
|
|
379
490
|
return [
|
|
380
|
-
...Object.entries(
|
|
491
|
+
...Object.entries(resolvedFilters).map(
|
|
381
492
|
([key, value]) => [key, "=", value] as [keyof TDoc & string, string, unknown],
|
|
382
493
|
),
|
|
383
494
|
searchFilter,
|
|
384
495
|
];
|
|
385
|
-
}, [
|
|
496
|
+
}, [resolvedFilters, debouncedSearch, searchField]);
|
|
386
497
|
|
|
387
498
|
// Axiom 6 / DG-TBL-06: zero rows under active filters or search must not
|
|
388
499
|
// render the same chrome as a truly empty doctype — the no-results message
|
|
@@ -423,8 +534,10 @@ export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
|
423
534
|
[savedFiltersHook],
|
|
424
535
|
);
|
|
425
536
|
|
|
426
|
-
|
|
427
|
-
|
|
537
|
+
// Named fields need no schema to read or draw: the view renders now (on
|
|
538
|
+
// the server too) and labels settle when meta lands.
|
|
539
|
+
if (isMetaLoading && !fields) {
|
|
540
|
+
return asPage(
|
|
428
541
|
<YStack
|
|
429
542
|
{...knobProps.panelPadding}
|
|
430
543
|
alignItems="center"
|
|
@@ -435,7 +548,7 @@ export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
|
435
548
|
<Text {...knobProps.body} color={knobProps.textAccentColor} marginTop="$2">
|
|
436
549
|
{t("Loading {{doctype}} schema...", { doctype })}
|
|
437
550
|
</Text>
|
|
438
|
-
</YStack
|
|
551
|
+
</YStack>,
|
|
439
552
|
);
|
|
440
553
|
}
|
|
441
554
|
|
|
@@ -456,6 +569,7 @@ export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
|
456
569
|
<XStack alignItems="center" {...knobProps.gap}>
|
|
457
570
|
<ViewSwitcher
|
|
458
571
|
views={[
|
|
572
|
+
...(renderCard ? [{ type: "grid", label: t("Cards") }] : []),
|
|
459
573
|
{ type: "list", label: t("List") },
|
|
460
574
|
{ type: "table", label: t("Table") },
|
|
461
575
|
]}
|
|
@@ -576,17 +690,23 @@ export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
|
576
690
|
);
|
|
577
691
|
|
|
578
692
|
const renderContent = () => {
|
|
579
|
-
if (viewMode === "list") {
|
|
693
|
+
if (viewMode === "list" || viewMode === "grid") {
|
|
694
|
+
const isGrid = viewMode === "grid";
|
|
580
695
|
return (
|
|
581
|
-
<YStack flex={1}>
|
|
582
|
-
{renderListSearch()}
|
|
696
|
+
<YStack flex={isGrid ? undefined : 1}>
|
|
697
|
+
{showSearch ? renderListSearch() : null}
|
|
583
698
|
<FrappeList
|
|
584
|
-
key={
|
|
699
|
+
key={`${viewMode}-${refreshKey}`}
|
|
700
|
+
layout={isGrid ? "grid" : "list"}
|
|
701
|
+
gridProps={gridProps}
|
|
702
|
+
emptyState={emptyState}
|
|
703
|
+
pageSize={pageSize}
|
|
704
|
+
onRetry={onRetry ?? handleRefresh}
|
|
585
705
|
doctype={doctype}
|
|
586
706
|
fields={effectiveFields as readonly ("name" | "doctype")[]}
|
|
587
707
|
filters={listFilters as Partial<{ name: string; doctype: string }>}
|
|
588
708
|
renderItem={
|
|
589
|
-
renderListItem as unknown as (
|
|
709
|
+
(isGrid && renderCard ? renderCard : renderListItem) as unknown as (
|
|
590
710
|
item: Partial<{ name: string; doctype: string }>,
|
|
591
711
|
index: number,
|
|
592
712
|
) => React.ReactNode
|
|
@@ -599,6 +719,11 @@ export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
|
599
719
|
baseURL={finalBaseURL}
|
|
600
720
|
auth={finalAuth}
|
|
601
721
|
syncOptions={finalSyncOptions}
|
|
722
|
+
orderBy={orderBy as FrappeListProps<{ name: string; doctype: string }>["orderBy"]}
|
|
723
|
+
limit={limit}
|
|
724
|
+
initialRows={
|
|
725
|
+
initialRows as FrappeListProps<{ name: string; doctype: string }>["initialRows"]
|
|
726
|
+
}
|
|
602
727
|
// Only override when narrowing is active: FrappeList's own
|
|
603
728
|
// "No {doctype} records found" stays the true-empty message.
|
|
604
729
|
{...(noResultsMessage ? { emptyMessage: noResultsMessage } : {})}
|
|
@@ -612,7 +737,7 @@ export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
|
612
737
|
key={`table-${refreshKey}`}
|
|
613
738
|
doctype={doctype}
|
|
614
739
|
fields={effectiveFields}
|
|
615
|
-
filters={
|
|
740
|
+
filters={resolvedFilters as Parameters<typeof FrappeTable<TDoc>>[0]["filters"]}
|
|
616
741
|
columns={effectiveColumns}
|
|
617
742
|
onRowClick={onItemClick}
|
|
618
743
|
baseURL={finalBaseURL}
|
|
@@ -622,24 +747,45 @@ export function FrappeListView<TDoc extends { name: string; doctype: string }>({
|
|
|
622
747
|
);
|
|
623
748
|
};
|
|
624
749
|
|
|
625
|
-
|
|
750
|
+
// A connection filter's matching records are known only once its linked
|
|
751
|
+
// rows are read; until then the view waits instead of listing everything.
|
|
752
|
+
const renderResolvedContent = () => {
|
|
753
|
+
if (linkFilters.error) {
|
|
754
|
+
return (
|
|
755
|
+
<AsyncBoundary
|
|
756
|
+
layout="list"
|
|
757
|
+
error={linkFilters.error}
|
|
758
|
+
errorTitle={
|
|
759
|
+
isPermissionError(linkFilters.error)
|
|
760
|
+
? t("You do not have permission to view {{doctype}}", { doctype })
|
|
761
|
+
: t("Error loading {{doctype}}", { doctype })
|
|
762
|
+
}
|
|
763
|
+
/>
|
|
764
|
+
);
|
|
765
|
+
}
|
|
766
|
+
if (linkFilters.pending) return <AsyncBoundary layout="list" loading />;
|
|
767
|
+
return renderContent();
|
|
768
|
+
};
|
|
769
|
+
|
|
770
|
+
return asPage(
|
|
626
771
|
<YStack
|
|
627
|
-
flex={1}
|
|
628
|
-
{...knobProps.surface}
|
|
629
|
-
{...knobProps.containerRadius}
|
|
630
|
-
overflow="hidden"
|
|
772
|
+
flex={viewMode === "grid" ? undefined : 1}
|
|
773
|
+
{...(surface ? knobProps.surface : {})}
|
|
774
|
+
{...(surface ? knobProps.containerRadius : {})}
|
|
775
|
+
overflow={surface ? "hidden" : undefined}
|
|
631
776
|
testID={`${doctype.toLowerCase()}-list`}
|
|
632
777
|
{...stackProps}
|
|
633
778
|
>
|
|
634
779
|
{renderToolbar()}
|
|
780
|
+
{linkFilters.readers}
|
|
635
781
|
{showFilterSidebar ? (
|
|
636
782
|
<XStack flex={1}>
|
|
637
783
|
{renderFilterSidebar()}
|
|
638
|
-
<YStack flex={1}>{
|
|
784
|
+
<YStack flex={1}>{renderResolvedContent()}</YStack>
|
|
639
785
|
</XStack>
|
|
640
786
|
) : (
|
|
641
|
-
|
|
787
|
+
renderResolvedContent()
|
|
642
788
|
)}
|
|
643
|
-
</YStack
|
|
789
|
+
</YStack>,
|
|
644
790
|
);
|
|
645
791
|
}
|
package/src/FrappeProvider.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { FixtureProvider, UseFrappeCollectionConfig } from "@multiplatform.one/frappe";
|
|
2
2
|
import React, { createContext, use, useContext } from "react";
|
|
3
|
+
import { FrappeNavigationProvider, type FrappeNavigation } from "./frappeNavigation";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Configuration for the Frappe connection.
|
|
@@ -101,6 +102,12 @@ export interface FrappeProviderProps {
|
|
|
101
102
|
* `baseURL` to run the whole app off fixtures with no server.
|
|
102
103
|
*/
|
|
103
104
|
fixtures?: FixtureProvider;
|
|
105
|
+
/**
|
|
106
|
+
* The host router. Given, a `FrappeListView` or `FrappeForm` with a
|
|
107
|
+
* `route` reads its record from the path and navigates between the
|
|
108
|
+
* doctype's list, record, edit and new pages on its own.
|
|
109
|
+
*/
|
|
110
|
+
navigation?: FrappeNavigation;
|
|
104
111
|
}
|
|
105
112
|
|
|
106
113
|
/**
|
|
@@ -137,6 +144,7 @@ export function FrappeProvider({
|
|
|
137
144
|
syncOptions,
|
|
138
145
|
socketOptions,
|
|
139
146
|
fixtures,
|
|
147
|
+
navigation,
|
|
140
148
|
}: FrappeProviderProps) {
|
|
141
149
|
const value = React.useMemo(
|
|
142
150
|
() => ({
|
|
@@ -163,7 +171,11 @@ export function FrappeProvider({
|
|
|
163
171
|
],
|
|
164
172
|
);
|
|
165
173
|
|
|
166
|
-
return
|
|
174
|
+
return (
|
|
175
|
+
<FrappeContext.Provider value={value}>
|
|
176
|
+
<FrappeNavigationProvider navigation={navigation}>{children}</FrappeNavigationProvider>
|
|
177
|
+
</FrappeContext.Provider>
|
|
178
|
+
);
|
|
167
179
|
}
|
|
168
180
|
|
|
169
181
|
/**
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useDocTypeMeta,
|
|
3
|
-
useFrappeCollection,
|
|
4
|
-
useFrappeDoctypeEvents,
|
|
5
|
-
useLiveQuery,
|
|
6
|
-
} from "@multiplatform.one/frappe";
|
|
1
|
+
import { useDocTypeMeta, useFrappeDoctypeEvents } from "@multiplatform.one/frappe";
|
|
7
2
|
import { downloadBlob } from "@multiplatform.one/platform";
|
|
8
3
|
import {
|
|
9
4
|
ReportBuilder,
|
|
@@ -20,6 +15,7 @@ import { Popover, Text, XStack, YStack, type YStackProps } from "tamagui";
|
|
|
20
15
|
import { FloppyDiskIcon, FolderOpenIcon, TrashIcon } from "@phosphor-icons/react";
|
|
21
16
|
import { useResolvedKnobs } from "@multiplatform.one/theme";
|
|
22
17
|
import { useFrappeConfig } from "./FrappeProvider";
|
|
18
|
+
import { useFrappeRows } from "./useFrappeRows";
|
|
23
19
|
|
|
24
20
|
// ============================================================================
|
|
25
21
|
// Saved Report Types (Frappe-specific persisted storage)
|
|
@@ -164,7 +160,7 @@ export function FrappeReportBuilder({
|
|
|
164
160
|
fieldname: f.fieldname,
|
|
165
161
|
label: f.label || f.fieldname,
|
|
166
162
|
fieldtype: f.fieldtype,
|
|
167
|
-
enabled: f.in_list_view
|
|
163
|
+
enabled: !!f.in_list_view,
|
|
168
164
|
}));
|
|
169
165
|
}, [initialColumns, meta]);
|
|
170
166
|
|
|
@@ -177,20 +173,16 @@ export function FrappeReportBuilder({
|
|
|
177
173
|
return fieldNames as readonly string[];
|
|
178
174
|
}, [allColumns]);
|
|
179
175
|
|
|
180
|
-
const collection = useFrappeCollection<{ name: string; doctype: string }>(
|
|
181
|
-
connectionConfig,
|
|
182
|
-
doctype,
|
|
183
|
-
{
|
|
184
|
-
fields: fetchFields as readonly ("name" | "doctype")[],
|
|
185
|
-
filters: filters as Partial<{ name: string; doctype: string }>,
|
|
186
|
-
},
|
|
187
|
-
);
|
|
188
176
|
const {
|
|
189
|
-
|
|
190
|
-
isLoading,
|
|
177
|
+
rows,
|
|
178
|
+
isQueryLoading: isLoading,
|
|
191
179
|
isError,
|
|
192
|
-
} =
|
|
193
|
-
|
|
180
|
+
} = useFrappeRows<{ name: string; doctype: string }>(connectionConfig, doctype, {
|
|
181
|
+
fields: fetchFields as readonly ("name" | "doctype")[],
|
|
182
|
+
filters: filters as Partial<{ name: string; doctype: string }>,
|
|
183
|
+
limit: null,
|
|
184
|
+
});
|
|
185
|
+
const data = rows as unknown as Record<string, unknown>[];
|
|
194
186
|
|
|
195
187
|
// Live staleness: a realtime change on the doctype marks the current
|
|
196
188
|
// report result stale until the collection reconciles (data identity
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import {
|
|
3
|
+
useFrappeRows,
|
|
4
|
+
type FrappeRowsConnection,
|
|
5
|
+
type UseFrappeRowsOptions,
|
|
6
|
+
} from "./useFrappeRows";
|
|
7
|
+
|
|
8
|
+
export interface FrappeRowsSnapshot<TDoc> {
|
|
9
|
+
rows: TDoc[];
|
|
10
|
+
isLoading: boolean;
|
|
11
|
+
error: Error | null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface FrappeRowsReaderProps<TDoc extends { name: string; doctype: string }> {
|
|
15
|
+
connection: FrappeRowsConnection | undefined;
|
|
16
|
+
doctype: string;
|
|
17
|
+
/** Memoize it: a new identity every render re-reports the same rows. */
|
|
18
|
+
options: UseFrappeRowsOptions<TDoc>;
|
|
19
|
+
onChange: (snapshot: FrappeRowsSnapshot<TDoc>) => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* One doctype read as a component. A parent that needs a varying number of
|
|
24
|
+
* reads (one per connection, one per junction filter) mounts one reader per
|
|
25
|
+
* read instead of calling hooks in a loop. Renders nothing.
|
|
26
|
+
*/
|
|
27
|
+
export function FrappeRowsReader<TDoc extends { name: string; doctype: string }>({
|
|
28
|
+
connection,
|
|
29
|
+
doctype,
|
|
30
|
+
options,
|
|
31
|
+
onChange,
|
|
32
|
+
}: FrappeRowsReaderProps<TDoc>) {
|
|
33
|
+
const { rows, isLoading, error } = useFrappeRows<TDoc>(connection, doctype, options);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
onChange({ rows, isLoading, error });
|
|
36
|
+
}, [rows, isLoading, error, onChange]);
|
|
37
|
+
return null;
|
|
38
|
+
}
|