@jmruthers/pace-core 0.5.135 → 0.5.137
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/{DataTable-A36PJG6N.js → DataTable-6M4L6BI2.js} +26 -13
- package/dist/{DataTable-C7GaRZye.d.ts → DataTable-CWAZZcXC.d.ts} +1 -1
- package/dist/{PublicLoadingSpinner-CUAnTvcg.d.ts → EventLogo-rFL_kRjk.d.ts} +123 -135
- package/dist/{UnifiedAuthProvider-BVKmQd9u.d.ts → UnifiedAuthProvider-DJxGTftH.d.ts} +1 -1
- package/dist/{UnifiedAuthProvider-CQDZRJIS.js → UnifiedAuthProvider-XIQQ7LVU.js} +5 -5
- package/dist/{api-TNIBJWLM.js → api-45XYYO2A.js} +4 -3
- package/dist/{audit-T36HM7IM.js → audit-64X3VJXB.js} +3 -2
- package/dist/{chunk-F64FFPOZ.js → chunk-22WKWKRX.js} +26 -20
- package/dist/chunk-22WKWKRX.js.map +1 -0
- package/dist/{chunk-VZ5OR6HD.js → chunk-4C7EXCAR.js} +62 -150
- package/dist/chunk-4C7EXCAR.js.map +1 -0
- package/dist/{chunk-PYUXFQJ3.js → chunk-56XJ3TU6.js} +2 -2
- package/dist/chunk-56XJ3TU6.js.map +1 -0
- package/dist/{chunk-CTJRBUX2.js → chunk-6LAAY47Q.js} +2 -2
- package/dist/{chunk-UJI6WSMD.js → chunk-7QCC6MCP.js} +90 -3
- package/dist/chunk-7QCC6MCP.js.map +1 -0
- package/dist/{chunk-66C4BSAY.js → chunk-ANBQRTPX.js} +9 -2
- package/dist/chunk-ANBQRTPX.js.map +1 -0
- package/dist/{chunk-CQZU6TFE.js → chunk-BCIBECNB.js} +100 -62
- package/dist/chunk-BCIBECNB.js.map +1 -0
- package/dist/{chunk-GKHF54DI.js → chunk-BESYRHQM.js} +10 -4
- package/dist/chunk-BESYRHQM.js.map +1 -0
- package/dist/chunk-BJPBT3CU.js +21 -0
- package/dist/chunk-BJPBT3CU.js.map +1 -0
- package/dist/{chunk-BYXRHAIF.js → chunk-BLCXZEYF.js} +23 -14
- package/dist/chunk-BLCXZEYF.js.map +1 -0
- package/dist/{chunk-WP5I5GLN.js → chunk-BVYWGZVV.js} +112 -97
- package/dist/chunk-BVYWGZVV.js.map +1 -0
- package/dist/{chunk-GEVIB2UB.js → chunk-ERISIBYU.js} +14 -5
- package/dist/chunk-ERISIBYU.js.map +1 -0
- package/dist/{chunk-O3NWNXDY.js → chunk-FMUCXFII.js} +2 -2
- package/dist/chunk-FMUCXFII.js.map +1 -0
- package/dist/{chunk-GVDR7WNV.js → chunk-HAWZXGR2.js} +334 -614
- package/dist/chunk-HAWZXGR2.js.map +1 -0
- package/dist/{chunk-ZV77RZMU.js → chunk-INQLMHPF.js} +2 -2
- package/dist/chunk-JISYG63F.js +70 -0
- package/dist/chunk-JISYG63F.js.map +1 -0
- package/dist/{chunk-HMNOSGVA.js → chunk-KYRHUBIU.js} +576 -767
- package/dist/chunk-KYRHUBIU.js.map +1 -0
- package/dist/{chunk-M6DDYFUD.js → chunk-LS353YLY.js} +19 -16
- package/dist/chunk-LS353YLY.js.map +1 -0
- package/dist/{chunk-TGIY2AR2.js → chunk-MA6EPSGZ.js} +4 -3
- package/dist/{chunk-TGIY2AR2.js.map → chunk-MA6EPSGZ.js.map} +1 -1
- package/dist/chunk-OWAG3GSU.js +58 -0
- package/dist/chunk-OWAG3GSU.js.map +1 -0
- package/dist/{chunk-JCQZ6LA7.js → chunk-Q5QRDWKI.js} +9 -3
- package/dist/chunk-Q5QRDWKI.js.map +1 -0
- package/dist/chunk-S5OFRT4M.js +94 -0
- package/dist/chunk-S5OFRT4M.js.map +1 -0
- package/dist/{chunk-3DBFLLLU.js → chunk-SBVILCCA.js} +14 -9
- package/dist/chunk-SBVILCCA.js.map +1 -0
- package/dist/{chunk-ZYZCRSBD.js → chunk-T6JN6LH6.js} +16 -11
- package/dist/chunk-T6JN6LH6.js.map +1 -0
- package/dist/chunk-XDNLUEXI.js +138 -0
- package/dist/chunk-XDNLUEXI.js.map +1 -0
- package/dist/{chunk-3CG5L6RN.js → chunk-YCWDTTUK.js} +90 -75
- package/dist/chunk-YCWDTTUK.js.map +1 -0
- package/dist/{chunk-5F3NDPJV.js → chunk-ZZ2SS7NI.js} +10 -5
- package/dist/chunk-ZZ2SS7NI.js.map +1 -0
- package/dist/components.d.ts +7 -287
- package/dist/components.js +27 -157
- package/dist/components.js.map +1 -1
- package/dist/{file-reference-C9isKNPn.d.ts → file-reference-C6Gkn77H.d.ts} +1 -1
- package/dist/{formatting-DFcCxUEk.d.ts → formatting-CvUXy2mF.d.ts} +1 -1
- package/dist/hooks.d.ts +3 -3
- package/dist/hooks.js +21 -16
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +101 -9
- package/dist/index.js +44 -31
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +4 -4
- package/dist/rbac/index.js +12 -12
- package/dist/schema-DTDZQe2u.d.ts +28 -0
- package/dist/styles/index.js +2 -1
- package/dist/theming/runtime.d.ts +2 -19
- package/dist/theming/runtime.js +2 -1
- package/dist/{types-D5rqZQXk.d.ts → types-Dfz9dmVH.d.ts} +12 -1
- package/dist/types.d.ts +153 -4
- package/dist/types.js +51 -16
- package/dist/types.js.map +1 -1
- package/dist/{useInactivityTracker-MRUU55XI.js → useInactivityTracker-TO6ZOF35.js} +3 -2
- package/dist/{usePublicRouteParams-Dyt1tzI9.d.ts → usePublicRouteParams-B7PabvuH.d.ts} +1 -1
- package/dist/utils.d.ts +221 -173
- package/dist/utils.js +185 -225
- package/dist/utils.js.map +1 -1
- package/dist/validation.d.ts +24 -115
- package/dist/validation.js +19 -474
- package/dist/validation.js.map +1 -1
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +6 -6
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +6 -6
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +7 -7
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +4 -4
- package/docs/api/interfaces/BadgeProps.md +27 -0
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +29 -4
- package/docs/api/interfaces/DataAccessRecord.md +9 -9
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +18 -18
- package/docs/api/interfaces/DataTableColumn.md +61 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
- package/docs/api/interfaces/EmptyStateConfig.md +5 -5
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +14 -14
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +152 -0
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +8 -8
- package/docs/api/interfaces/FileDisplayProps.md +15 -15
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
- package/docs/api/interfaces/NavigationContextType.md +9 -9
- package/docs/api/interfaces/NavigationGuardProps.md +10 -10
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +7 -7
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +27 -27
- package/docs/api/interfaces/PaceLoginPageProps.md +4 -4
- package/docs/api/interfaces/PageAccessRecord.md +8 -8
- package/docs/api/interfaces/PagePermissionContextType.md +8 -8
- package/docs/api/interfaces/PagePermissionGuardProps.md +11 -11
- package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
- package/docs/api/interfaces/PaletteData.md +4 -4
- package/docs/api/interfaces/PermissionEnforcerProps.md +11 -11
- package/docs/api/interfaces/ProtectedRouteProps.md +6 -6
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
- package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +10 -10
- package/docs/api/interfaces/RouteConfig.md +10 -10
- package/docs/api/interfaces/SecureDataContextType.md +9 -9
- package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +21 -0
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +9 -9
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
- package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
- package/docs/api/interfaces/UsePublicEventReturn.md +5 -5
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +9 -9
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +4 -4
- package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
- package/docs/api/interfaces/UserEventAccess.md +11 -11
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +591 -220
- package/docs/api-reference/components.md +106 -26
- package/docs/architecture/README.md +0 -3
- package/docs/implementation-guides/data-tables.md +277 -13
- package/docs/implementation-guides/forms.md +1 -16
- package/docs/implementation-guides/permission-enforcement.md +8 -2
- package/docs/styles/README.md +0 -2
- package/examples/README.md +30 -14
- package/examples/STRUCTURE.md +125 -0
- package/examples/components 2/DataTable/HierarchicalActionsExample.tsx +421 -0
- package/examples/components 2/DataTable/HierarchicalExample.tsx +475 -0
- package/examples/components 2/DataTable/InitialPageSizeExample.tsx +177 -0
- package/examples/components 2/DataTable/PerformanceExample.tsx +506 -0
- package/examples/components 2/DataTable/index.ts +13 -0
- package/examples/components 2/Dialog/BasicHtmlTest.tsx +55 -0
- package/examples/components 2/Dialog/DebugHtmlExample.tsx +68 -0
- package/examples/components 2/Dialog/HtmlDialogExample.tsx +202 -0
- package/examples/components 2/Dialog/ScrollableDialogExample.tsx +290 -0
- package/examples/components 2/Dialog/SimpleHtmlTest.tsx +61 -0
- package/examples/components 2/Dialog/SmartDialogExample.tsx +322 -0
- package/examples/components 2/Dialog/index.ts +15 -0
- package/examples/components 2/index.ts +11 -0
- package/examples/features/index.ts +12 -0
- package/{src/examples → examples/features/public-pages}/CorrectPublicPageImplementation.tsx +14 -17
- package/{src/examples → examples/features/public-pages}/PublicEventPage.tsx +14 -27
- package/{src/examples → examples/features/public-pages}/PublicPageApp.tsx +15 -28
- package/{src/examples → examples/features/public-pages}/PublicPageUsageExample.tsx +8 -10
- package/examples/features/public-pages/index.ts +14 -0
- package/examples/features/rbac/CompleteRBACExample.tsx +324 -0
- package/examples/features/rbac/EventBasedApp.tsx +239 -0
- package/examples/features/rbac/PermissionExample.tsx +151 -0
- package/examples/features/rbac/index.ts +13 -0
- package/examples/index.ts +11 -3
- package/package.json +30 -19
- package/src/__tests__/TEST_STANDARD.md +92 -0
- package/src/components/Alert/Alert.tsx +1 -1
- package/src/components/Avatar/Avatar.tsx +1 -1
- package/src/components/Badge/Badge.test.tsx +314 -0
- package/src/components/Badge/Badge.tsx +304 -0
- package/src/components/Badge/index.ts +3 -0
- package/src/components/Button/Button.tsx +1 -1
- package/src/components/Card/Card.tsx +1 -1
- package/src/components/Checkbox/Checkbox.tsx +1 -1
- package/src/components/DataTable/DataTable.test.tsx +1 -1
- package/src/components/DataTable/DataTable.tsx +1 -30
- package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +562 -0
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +217 -0
- package/src/components/DataTable/__tests__/styles.test.ts +3 -3
- package/src/components/DataTable/components/ActionButtons.tsx +0 -15
- package/src/components/DataTable/components/ColumnFilter.tsx +8 -4
- package/src/components/DataTable/components/DataTableBody.tsx +461 -0
- package/src/components/DataTable/components/DataTableCore.tsx +4 -185
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +1 -1
- package/src/components/DataTable/components/DataTableModals.tsx +1 -27
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +144 -0
- package/src/components/DataTable/components/EditableRow.tsx +1 -1
- package/src/components/DataTable/components/FilterRow.tsx +9 -3
- package/src/components/DataTable/components/ImportModal.tsx +2 -14
- package/src/components/DataTable/components/PaginationControls.tsx +2 -1
- package/src/components/DataTable/components/UnifiedTableBody.tsx +109 -82
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +513 -0
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +14 -68
- package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +1 -1
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +62 -0
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +1 -1
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +1 -1
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +43 -0
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +1 -1
- package/src/components/DataTable/core/ActionManager.ts +235 -0
- package/src/components/DataTable/core/ColumnManager.ts +205 -0
- package/src/components/DataTable/core/DataManager.ts +188 -0
- package/src/components/DataTable/core/DataTableContext.tsx +181 -0
- package/src/components/DataTable/core/LocalDataAdapter.ts +273 -0
- package/src/components/DataTable/core/PluginRegistry.ts +229 -0
- package/src/components/DataTable/core/StateManager.ts +311 -0
- package/src/components/DataTable/core/interfaces.ts +338 -0
- package/src/components/DataTable/examples/GroupingAggregationExample.tsx +273 -0
- package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +1 -1
- package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +1 -1
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +1 -1
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +1 -1
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +2 -23
- package/src/components/DataTable/index.ts +4 -0
- package/src/components/DataTable/styles.ts +28 -7
- package/src/components/DataTable/types.ts +13 -0
- package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +94 -0
- package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +1 -1
- package/src/components/DataTable/utils/aggregationUtils.ts +161 -0
- package/src/components/DataTable/utils/columnUtils.ts +40 -0
- package/src/components/DataTable/utils/debugTools.ts +609 -0
- package/src/components/DataTable/utils/exportUtils.ts +1 -1
- package/src/components/DataTable/utils/flexibleImport.ts +1 -11
- package/src/components/DataTable/utils/index.ts +2 -0
- package/src/components/DataTable/utils/paginationUtils.ts +1 -1
- package/src/components/Dialog/Dialog.tsx +2 -2
- package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +8 -1
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +35 -7
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +5 -4
- package/src/components/EventSelector/EventSelector.tsx +3 -2
- package/src/components/FileDisplay/FileDisplay.tsx +2 -36
- package/src/components/FileUpload/FileUpload.test.tsx +2 -2
- package/src/components/FileUpload/FileUpload.tsx +2 -2
- package/src/components/Footer/Footer.test.tsx +1 -1
- package/src/components/Footer/Footer.tsx +1 -1
- package/src/components/Form/Form.test.tsx +5 -510
- package/src/components/Form/Form.tsx +1 -1
- package/src/components/Form/FormField.tsx +1 -1
- package/src/components/Form/index.ts +0 -12
- package/src/components/Header/Header.tsx +1 -1
- package/src/components/Input/Input.tsx +1 -1
- package/src/components/Label/Label.tsx +1 -1
- package/src/components/LoginForm/LoginForm.test.tsx +1 -1
- package/src/components/LoginForm/LoginForm.tsx +1 -1
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -3
- package/src/components/NavigationMenu/NavigationMenu.tsx +9 -8
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +4 -3
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -12
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +0 -16
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +76 -10
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +0 -1
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -9
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +35 -3
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +14 -13
- package/src/components/PasswordReset/PasswordChangeForm.tsx +1 -1
- package/src/components/PasswordReset/index.ts +0 -2
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +35 -8
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -2
- package/src/components/PublicLayout/PublicErrorBoundary.tsx +1 -1
- package/src/components/PublicLayout/PublicLoadingSpinner.tsx +1 -1
- package/src/components/PublicLayout/PublicPageContextChecker.tsx +44 -43
- package/src/components/PublicLayout/PublicPageFooter.tsx +1 -1
- package/src/components/PublicLayout/PublicPageHeader.tsx +1 -15
- package/src/components/PublicLayout/PublicPageProvider.tsx +3 -2
- package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +2 -0
- package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +1 -1
- package/src/components/PublicLayout/index.ts +4 -2
- package/src/components/Select/Select.test.tsx +1 -1
- package/src/components/Select/Select.tsx +21 -9
- package/src/components/{SessionRestorationLoader.tsx → SessionRestorationLoader/SessionRestorationLoader.tsx} +3 -2
- package/src/components/SessionRestorationLoader/index.ts +3 -0
- package/src/components/Switch/Switch.tsx +1 -1
- package/src/components/Table/Table.tsx +1 -1
- package/src/components/Table/__tests__/Table.test.tsx +1 -1
- package/src/components/Toast/Toast.tsx +1 -1
- package/src/components/Tooltip/Tooltip.tsx +1 -1
- package/src/components/index.ts +7 -10
- package/src/hooks/__tests__/hooks.integration.test.tsx +37 -22
- package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +33 -17
- package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +28 -3
- package/src/hooks/__tests__/useFileDisplay.unit.test.ts +36 -9
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +83 -85
- package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +26 -2
- package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +19 -6
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -4
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +17 -4
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +26 -6
- package/src/hooks/__tests__/usePublicFileDisplay.test.ts +16 -6
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +3 -3
- package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +17 -3
- package/src/hooks/public/usePublicEvent.ts +7 -6
- package/src/hooks/public/usePublicEventLogo.ts +7 -4
- package/src/hooks/public/usePublicFileDisplay.ts +6 -150
- package/src/hooks/useComponentPerformance.ts +4 -1
- package/src/hooks/useDataTablePerformance.ts +4 -3
- package/src/hooks/useEventTheme.test.ts +18 -5
- package/src/hooks/useEventTheme.ts +4 -1
- package/src/hooks/useEvents.ts +2 -0
- package/src/hooks/useFileDisplay.ts +9 -8
- package/src/hooks/useFileReference.ts +4 -1
- package/src/hooks/useFileUrl.ts +4 -1
- package/src/hooks/useInactivityTracker.ts +5 -4
- package/src/hooks/useOrganisationSecurity.test.ts +33 -12
- package/src/hooks/useOrganisationSecurity.ts +8 -7
- package/src/hooks/usePerformanceMonitor.ts +6 -3
- package/src/hooks/usePermissionCache.ts +13 -6
- package/src/hooks/useSecureDataAccess.test.ts +2 -2
- package/src/hooks/useSecureDataAccess.ts +9 -8
- package/src/hooks/useSessionRestoration.ts +4 -1
- package/src/hooks/useStorage.ts +4 -1
- package/src/index.ts +20 -7
- package/src/providers/services/AuthServiceProvider.tsx +3 -2
- package/src/providers/services/EventServiceProvider.tsx +2 -1
- package/src/providers/services/InactivityServiceProvider.tsx +2 -1
- package/src/providers/services/OrganisationServiceProvider.tsx +2 -1
- package/src/providers/services/UnifiedAuthProvider.tsx +4 -3
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +22 -2
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +24 -2
- package/src/rbac/__tests__/cache-invalidation.test.ts +20 -6
- package/src/rbac/api.ts +5 -2
- package/src/rbac/audit-enhanced.ts +6 -6
- package/src/rbac/audit.test.ts +60 -38
- package/src/rbac/audit.ts +8 -8
- package/src/rbac/cache-invalidation.ts +7 -4
- package/src/rbac/components/EnhancedNavigationMenu.tsx +11 -5
- package/src/rbac/components/NavigationGuard.tsx +7 -3
- package/src/rbac/components/NavigationProvider.tsx +6 -3
- package/src/rbac/components/PagePermissionGuard.tsx +28 -16
- package/src/rbac/components/PagePermissionProvider.tsx +4 -1
- package/src/rbac/components/PermissionEnforcer.tsx +9 -3
- package/src/rbac/components/RoleBasedRouter.tsx +3 -1
- package/src/rbac/components/SecureDataProvider.tsx +7 -3
- package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +87 -61
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +83 -33
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +36 -13
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +2 -2
- package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +22 -8
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +19 -6
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +43 -17
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +42 -17
- package/src/rbac/engine.ts +15 -7
- package/src/rbac/hooks/usePermissions.ts +7 -3
- package/src/rbac/hooks/useResolvedScope.test.ts +2 -2
- package/src/rbac/hooks/useResolvedScope.ts +10 -7
- package/src/rbac/permissions.ts +5 -2
- package/src/rbac/security.test.ts +27 -16
- package/src/rbac/security.ts +5 -4
- package/src/services/AuthService.ts +22 -21
- package/src/services/EventService.ts +12 -12
- package/src/services/InactivityService.ts +5 -4
- package/src/services/OrganisationService.ts +26 -25
- package/src/services/__tests__/AuthService.test.ts +51 -19
- package/src/services/__tests__/EventService.test.ts +37 -5
- package/src/services/__tests__/InactivityService.test.ts +38 -4
- package/src/services/__tests__/OrganisationService.test.ts +3 -8
- package/src/services/base/BaseService.ts +3 -1
- package/src/styles/core.css +3 -0
- package/src/theming/__tests__/runtime.test.ts +21 -12
- package/src/theming/parseEventColours.ts +5 -19
- package/src/theming/runtime.ts +8 -4
- package/src/types/validation.ts +2 -29
- package/src/utils/__tests__/appConfig.unit.test.ts +1 -1
- package/src/utils/__tests__/audit.unit.test.ts +1 -1
- package/src/utils/__tests__/auth-utils.unit.test.ts +1 -1
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +19 -19
- package/src/utils/__tests__/cn.unit.test.ts +1 -1
- package/src/utils/__tests__/debugLogger.test.ts +1 -1
- package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -1
- package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -1
- package/src/utils/__tests__/formatting.unit.test.ts +1 -1
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +1 -1
- package/src/utils/__tests__/logger.unit.test.ts +1 -1
- package/src/utils/__tests__/organisationContext.unit.test.ts +1 -1
- package/src/utils/__tests__/performanceBenchmark.test.ts +1 -1
- package/src/utils/__tests__/performanceBudgets.unit.test.ts +1 -1
- package/src/utils/__tests__/permissionTypes.unit.test.ts +1 -1
- package/src/utils/__tests__/permissionUtils.unit.test.ts +1 -1
- package/src/utils/__tests__/sanitization.unit.test.ts +1 -1
- package/src/utils/__tests__/schemaUtils.unit.test.ts +1 -1
- package/src/utils/__tests__/secureDataAccess.unit.test.ts +1 -1
- package/src/utils/__tests__/secureErrors.unit.test.ts +33 -15
- package/src/utils/__tests__/secureStorage.unit.test.ts +1 -1
- package/src/utils/__tests__/security.unit.test.ts +40 -18
- package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -1
- package/src/utils/__tests__/sessionTracking.unit.test.ts +40 -29
- package/src/utils/__tests__/validationUtils.unit.test.ts +19 -6
- package/src/utils/app/appConfig.ts +47 -0
- package/src/utils/app/appIdResolver.test.ts +497 -0
- package/src/utils/app/appIdResolver.ts +133 -0
- package/src/utils/app/appNameResolver.simple.test.ts +212 -0
- package/src/utils/app/appNameResolver.test.ts +121 -0
- package/src/utils/app/appNameResolver.ts +195 -0
- package/src/utils/audit/audit.ts +127 -0
- package/src/utils/context/organisationContext.test.ts +322 -0
- package/src/utils/context/organisationContext.ts +156 -0
- package/src/utils/context/sessionTracking.ts +125 -0
- package/src/utils/core/cn.ts +7 -0
- package/src/utils/core/debugLogger.ts +67 -0
- package/src/utils/core/logger.ts +181 -0
- package/src/utils/device/deviceFingerprint.ts +215 -0
- package/src/utils/dynamic/dynamicUtils.ts +105 -0
- package/src/utils/dynamic/lazyLoad.tsx +44 -0
- package/src/utils/file-reference/__tests__/file-reference.test.ts +788 -0
- package/src/utils/file-reference/index.ts +501 -0
- package/src/utils/formatting/formatDate.test.ts +237 -0
- package/src/utils/formatting/formatting.ts +133 -0
- package/src/utils/index.ts +39 -54
- package/src/utils/performance/bundleAnalysis.ts +129 -0
- package/src/utils/performance/performanceBenchmark.ts +64 -0
- package/src/utils/performance/performanceBudgets.ts +110 -0
- package/src/utils/permissions/permissionTypes.ts +37 -0
- package/src/utils/permissions/permissionUtils.test.ts +393 -0
- package/src/utils/permissions/permissionUtils.ts +34 -0
- package/src/utils/security/auth-utils.ts +96 -0
- package/src/utils/security/secureDataAccess.test.ts +711 -0
- package/src/utils/security/secureDataAccess.ts +377 -0
- package/src/utils/security/secureErrors.ts +82 -0
- package/src/utils/security/secureStorage.ts +244 -0
- package/src/utils/security/security.ts +159 -0
- package/src/utils/security/securityMonitor.ts +45 -0
- package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -4
- package/src/utils/storage/helpers.ts +15 -8
- package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +598 -0
- package/src/{validation → utils/validation}/csrf.ts +1 -1
- package/src/utils/validation/htmlSanitization.ts +184 -0
- package/src/utils/validation/index.ts +79 -0
- package/src/utils/validation/sanitization.ts +333 -0
- package/src/{validation/schemaUtils.ts → utils/validation/schema.ts} +11 -6
- package/src/{validation → utils/validation}/sqlInjectionProtection.ts +2 -0
- package/src/utils/validation/validation.ts +111 -0
- package/src/utils/validation/validationUtils.ts +123 -0
- package/src/validation/index.ts +3 -34
- package/dist/chunk-24MKLB7U.js +0 -81
- package/dist/chunk-24MKLB7U.js.map +0 -1
- package/dist/chunk-3CG5L6RN.js.map +0 -1
- package/dist/chunk-3DBFLLLU.js.map +0 -1
- package/dist/chunk-5F3NDPJV.js.map +0 -1
- package/dist/chunk-66C4BSAY.js.map +0 -1
- package/dist/chunk-BDZUMRBD.js +0 -87
- package/dist/chunk-BDZUMRBD.js.map +0 -1
- package/dist/chunk-BYXRHAIF.js.map +0 -1
- package/dist/chunk-CDQ3PX7L.js +0 -18
- package/dist/chunk-CDQ3PX7L.js.map +0 -1
- package/dist/chunk-CQZU6TFE.js.map +0 -1
- package/dist/chunk-F64FFPOZ.js.map +0 -1
- package/dist/chunk-GEVIB2UB.js.map +0 -1
- package/dist/chunk-GKHF54DI.js.map +0 -1
- package/dist/chunk-GVDR7WNV.js.map +0 -1
- package/dist/chunk-HMNOSGVA.js.map +0 -1
- package/dist/chunk-JCQZ6LA7.js.map +0 -1
- package/dist/chunk-M6DDYFUD.js.map +0 -1
- package/dist/chunk-O3NWNXDY.js.map +0 -1
- package/dist/chunk-PYUXFQJ3.js.map +0 -1
- package/dist/chunk-UJI6WSMD.js.map +0 -1
- package/dist/chunk-VZ5OR6HD.js.map +0 -1
- package/dist/chunk-WP5I5GLN.js.map +0 -1
- package/dist/chunk-ZYZCRSBD.js.map +0 -1
- package/dist/validation-DnhrNMju.d.ts +0 -159
- package/src/components/PublicLayout/__tests__/PublicPageDebugger.test.tsx +0 -185
- package/src/validation/__tests__/common.unit.test.ts +0 -101
- package/src/validation/__tests__/csrf.unit.test.ts +0 -365
- package/src/validation/__tests__/passwordSchema.unit.test.ts +0 -203
- package/src/validation/__tests__/sanitization.unit.test.ts +0 -250
- package/src/validation/__tests__/schemaUtils.unit.test.ts +0 -451
- package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +0 -462
- package/src/validation/__tests__/user.unit.test.ts +0 -440
- package/src/validation/sanitization.ts +0 -96
- /package/dist/{DataTable-A36PJG6N.js.map → DataTable-6M4L6BI2.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-CQDZRJIS.js.map → UnifiedAuthProvider-XIQQ7LVU.js.map} +0 -0
- /package/dist/{api-TNIBJWLM.js.map → api-45XYYO2A.js.map} +0 -0
- /package/dist/{audit-T36HM7IM.js.map → audit-64X3VJXB.js.map} +0 -0
- /package/dist/{chunk-CTJRBUX2.js.map → chunk-6LAAY47Q.js.map} +0 -0
- /package/dist/{chunk-ZV77RZMU.js.map → chunk-INQLMHPF.js.map} +0 -0
- /package/dist/{useInactivityTracker-MRUU55XI.js.map → useInactivityTracker-TO6ZOF35.js.map} +0 -0
- /package/src/{validation → utils/validation}/common.ts +0 -0
- /package/src/{validation → utils/validation}/passwordSchema.ts +0 -0
- /package/src/{validation → utils/validation}/user.ts +0 -0
|
@@ -19,7 +19,7 @@ import type {
|
|
|
19
19
|
PaginationState,
|
|
20
20
|
} from '@tanstack/react-table';
|
|
21
21
|
import { Edit, Trash, ChevronUp, ChevronDown, ChevronsUpDown } from 'lucide-react';
|
|
22
|
-
import { cn } from '../../../utils/cn';
|
|
22
|
+
import { cn } from '../../../utils/core/cn';
|
|
23
23
|
import { Checkbox } from '../../Checkbox/Checkbox';
|
|
24
24
|
import { Button } from '../../Button/Button';
|
|
25
25
|
import { getTableClasses, getMainContainerClasses } from '../styles';
|
|
@@ -54,7 +54,7 @@ import { useTableColumns } from '../hooks/useTableColumns';
|
|
|
54
54
|
import { initializeLiveRegion, announceSortChange } from '../utils/a11yUtils';
|
|
55
55
|
import { useKeyboardNavigation } from '../hooks/useKeyboardNavigation';
|
|
56
56
|
import { getRowIdSafe } from '../utils/rowUtils';
|
|
57
|
-
import { createLogger } from '../../../utils/logger';
|
|
57
|
+
import { createLogger } from '../../../utils/core/logger';
|
|
58
58
|
|
|
59
59
|
import { normalizeDataTableFeatures } from '../types';
|
|
60
60
|
import type {
|
|
@@ -220,13 +220,6 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
220
220
|
onLayoutChange,
|
|
221
221
|
} = props;
|
|
222
222
|
|
|
223
|
-
// Debug logging to verify onExport prop is received
|
|
224
|
-
console.log('[DataTableInternal] Props received:', {
|
|
225
|
-
'onExport in props': !!props.onExport,
|
|
226
|
-
'onExport after destructuring': !!onExport,
|
|
227
|
-
'onExport type': typeof onExport,
|
|
228
|
-
'props keys with Export': Object.keys(props).filter(k => k.toLowerCase().includes('export')),
|
|
229
|
-
});
|
|
230
223
|
const logger = React.useMemo(() => createLogger('DataTableCore'), []);
|
|
231
224
|
|
|
232
225
|
// ============================================================================
|
|
@@ -244,16 +237,6 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
244
237
|
// MANDATORY: Get permissions and secure features
|
|
245
238
|
const { permissions, secureFeatures, effectivePageId } = useDataTablePermissions(rbac, requestedFeatures);
|
|
246
239
|
|
|
247
|
-
// Debug logging for creation feature
|
|
248
|
-
if (import.meta.env.MODE === 'development') {
|
|
249
|
-
logger.debug('[DataTableCore] Creation feature check:', {
|
|
250
|
-
'incomingFeatures.creation': incomingFeatures.creation,
|
|
251
|
-
'requestedFeatures.creation': requestedFeatures.creation,
|
|
252
|
-
'secureFeatures.creation': secureFeatures.creation,
|
|
253
|
-
'permissions.canCreate.can': permissions.canCreate.can,
|
|
254
|
-
'onCreateRow prop provided': !!onCreateRow
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
240
|
|
|
258
241
|
// ============================================================================
|
|
259
242
|
// UNIFIED STATE MANAGEMENT - Use ONLY useDataTableState for all state
|
|
@@ -441,22 +424,6 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
441
424
|
}
|
|
442
425
|
}, [hierarchicalValidation, logger]);
|
|
443
426
|
|
|
444
|
-
// Diagnostic logging when finalTableData is empty but input data exists
|
|
445
|
-
useEffect(() => {
|
|
446
|
-
if (finalTableData.length === 0 && data.length > 0) {
|
|
447
|
-
logger.warn('Diagnostic: finalTableData empty but input data exists', {
|
|
448
|
-
inputDataLength: data.length,
|
|
449
|
-
finalTableDataLength: finalTableData.length,
|
|
450
|
-
dataCount: finalDataCount,
|
|
451
|
-
finalPaginationMode,
|
|
452
|
-
hasServerData: !!serverData,
|
|
453
|
-
serverDataLength: serverData?.data?.length || 0,
|
|
454
|
-
hierarchicalEnabled: Boolean(secureFeatures.hierarchical && hierarchical?.enabled),
|
|
455
|
-
hierarchicalValid: hierarchicalValidation.isValid,
|
|
456
|
-
});
|
|
457
|
-
}
|
|
458
|
-
}, [finalTableData.length, data.length, finalDataCount, finalPaginationMode, serverData, secureFeatures.hierarchical, hierarchical, hierarchicalValidation.isValid, logger]);
|
|
459
|
-
|
|
460
427
|
const {
|
|
461
428
|
columnOrder: savedColumnOrder,
|
|
462
429
|
isLoaded: isColumnOrderLoaded,
|
|
@@ -488,17 +455,13 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
488
455
|
useEffect(() => {
|
|
489
456
|
if (secureFeatures.selection && state.columnOrder.includes('select') && state.columnOrder[0] !== 'select') {
|
|
490
457
|
const normalizedOrder = ['select', ...state.columnOrder.filter(id => id !== 'select')];
|
|
491
|
-
logger.warn('Correcting column order state - moving select to first position:', {
|
|
492
|
-
before: state.columnOrder,
|
|
493
|
-
after: normalizedOrder
|
|
494
|
-
});
|
|
495
458
|
stateActions.setColumnOrder(normalizedOrder);
|
|
496
459
|
// Also update persisted order if persistence is enabled
|
|
497
460
|
if (secureFeatures.columnReordering) {
|
|
498
461
|
updateColumnOrder(normalizedOrder);
|
|
499
462
|
}
|
|
500
463
|
}
|
|
501
|
-
}, [secureFeatures.selection, secureFeatures.columnReordering, state.columnOrder, stateActions, updateColumnOrder
|
|
464
|
+
}, [secureFeatures.selection, secureFeatures.columnReordering, state.columnOrder, stateActions, updateColumnOrder]);
|
|
502
465
|
|
|
503
466
|
// ============================================================================
|
|
504
467
|
// CONFIGURATION RESOLUTION - ALWAYS call these hooks
|
|
@@ -671,77 +634,14 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
671
634
|
onDeleteSelected: permissions.canDelete.can ? onDeleteSelected : undefined,
|
|
672
635
|
};
|
|
673
636
|
|
|
674
|
-
// Debug logging for handlers
|
|
675
|
-
console.log('[DataTableCore] Secure handlers setup:', {
|
|
676
|
-
'permissions.canExport.can': permissions.canExport.can,
|
|
677
|
-
'onExport prop provided': !!onExport,
|
|
678
|
-
'onExport type': typeof onExport,
|
|
679
|
-
'secureHandlers.onExport': !!handlers.onExport,
|
|
680
|
-
});
|
|
681
|
-
|
|
682
|
-
if (import.meta.env.MODE === 'development') {
|
|
683
|
-
logger.debug('[DataTableCore] Handler check:', {
|
|
684
|
-
'permissions.canCreate.can': permissions.canCreate.can,
|
|
685
|
-
'onCreateRow prop provided': !!onCreateRow,
|
|
686
|
-
'secureHandlers.onCreateRow': !!handlers.onCreateRow,
|
|
687
|
-
'secureFeatures.creation': secureFeatures.creation,
|
|
688
|
-
'will pass onCreateRow to toolbar': secureFeatures.creation && !!handlers.onCreateRow,
|
|
689
|
-
'permissions.canExport.can': permissions.canExport.can,
|
|
690
|
-
'onExport prop provided': !!onExport,
|
|
691
|
-
'secureHandlers.onExport': !!handlers.onExport,
|
|
692
|
-
});
|
|
693
|
-
}
|
|
694
|
-
|
|
695
637
|
return handlers;
|
|
696
|
-
}, [permissions.canUpdate.can, permissions.canDelete.can, permissions.canCreate.can, permissions.canImport.can, permissions.canExport.can, onEditRow, onDeleteRow, onCreateRow, onImport, onExport, onDeleteSelected, secureFeatures.creation
|
|
697
|
-
|
|
698
|
-
// Explicit debug log for creation button visibility (easier to spot)
|
|
699
|
-
if (import.meta.env.MODE === 'development') {
|
|
700
|
-
logger.debug('[DataTableCore] ⚠️ CREATION BUTTON DIAGNOSIS:', {
|
|
701
|
-
'✅ permissions.canCreate.can': permissions.canCreate.can,
|
|
702
|
-
'❓ features.creation enabled': secureFeatures.creation,
|
|
703
|
-
'❓ onCreateRow handler provided': !!onCreateRow,
|
|
704
|
-
'❓ secureHandlers.onCreateRow': !!secureHandlers.onCreateRow,
|
|
705
|
-
'🔍 WILL SHOW BUTTON': secureFeatures.creation && permissions.canCreate.can && !!onCreateRow,
|
|
706
|
-
'💡 SOLUTION': !secureFeatures.creation
|
|
707
|
-
? 'Enable features={{ creation: true }} in DataTable props'
|
|
708
|
-
: !onCreateRow
|
|
709
|
-
? 'Provide onCreateRow handler in DataTable props'
|
|
710
|
-
: 'All conditions met - button should be visible'
|
|
711
|
-
});
|
|
712
|
-
}
|
|
638
|
+
}, [permissions.canUpdate.can, permissions.canDelete.can, permissions.canCreate.can, permissions.canImport.can, permissions.canExport.can, onEditRow, onDeleteRow, onCreateRow, onImport, onExport, onDeleteSelected, secureFeatures.creation]);
|
|
713
639
|
|
|
714
640
|
// MANDATORY: Process actions with RBAC checks
|
|
715
641
|
const effectiveActions = useMemo(() => {
|
|
716
642
|
// Create a new array to avoid mutating the original
|
|
717
643
|
const result = [...actions];
|
|
718
644
|
|
|
719
|
-
// Log action configuration in development
|
|
720
|
-
logger.debug('Action Configuration Debug:', {
|
|
721
|
-
originalActions: actions.length,
|
|
722
|
-
secureFeatures: {
|
|
723
|
-
editing: secureFeatures.editing,
|
|
724
|
-
deletion: secureFeatures.deletion,
|
|
725
|
-
creation: secureFeatures.creation,
|
|
726
|
-
import: secureFeatures.import,
|
|
727
|
-
export: secureFeatures.export
|
|
728
|
-
},
|
|
729
|
-
secureHandlers: {
|
|
730
|
-
onEditRow: !!secureHandlers.onEditRow,
|
|
731
|
-
onDeleteRow: !!secureHandlers.onDeleteRow,
|
|
732
|
-
onCreateRow: !!secureHandlers.onCreateRow,
|
|
733
|
-
onImport: !!secureHandlers.onImport,
|
|
734
|
-
onExport: !!secureHandlers.onExport
|
|
735
|
-
},
|
|
736
|
-
permissions: {
|
|
737
|
-
canUpdate: permissions.canUpdate.can,
|
|
738
|
-
canDelete: permissions.canDelete.can,
|
|
739
|
-
canCreate: permissions.canCreate.can,
|
|
740
|
-
canImport: permissions.canImport.can,
|
|
741
|
-
canExport: permissions.canExport.can
|
|
742
|
-
}
|
|
743
|
-
});
|
|
744
|
-
|
|
745
645
|
// Add Edit action with RBAC check
|
|
746
646
|
if (secureFeatures.editing && secureHandlers.onEditRow && !result.some(a => a.label === 'Edit')) {
|
|
747
647
|
result.push({
|
|
@@ -804,13 +704,6 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
804
704
|
});
|
|
805
705
|
}
|
|
806
706
|
|
|
807
|
-
// Log final actions in development
|
|
808
|
-
logger.debug('Final Actions:', {
|
|
809
|
-
totalActions: result.length,
|
|
810
|
-
actionLabels: result.map(a => a.label),
|
|
811
|
-
hiddenActions: result.filter(a => a.hidden).map(a => a.label)
|
|
812
|
-
});
|
|
813
|
-
|
|
814
707
|
return result;
|
|
815
708
|
}, [actions, secureFeatures, permissions, secureHandlers, resolvedGetRowId, stateActions, data]);
|
|
816
709
|
|
|
@@ -842,16 +735,6 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
842
735
|
? ['select', ...state.columnOrder.filter(id => id !== 'select')]
|
|
843
736
|
: state.columnOrder;
|
|
844
737
|
|
|
845
|
-
// Log column order normalization in development
|
|
846
|
-
if (secureFeatures.selection && state.columnOrder[0] !== 'select') {
|
|
847
|
-
logger.warn('Column order normalized:', {
|
|
848
|
-
original: state.columnOrder,
|
|
849
|
-
normalized: normalizedColumnOrder,
|
|
850
|
-
firstColumnOriginal: state.columnOrder[0],
|
|
851
|
-
firstColumnNormalized: normalizedColumnOrder[0]
|
|
852
|
-
});
|
|
853
|
-
}
|
|
854
|
-
|
|
855
738
|
return {
|
|
856
739
|
sorting: state.sorting,
|
|
857
740
|
columnFilters: state.columnFilters,
|
|
@@ -905,44 +788,6 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
905
788
|
|
|
906
789
|
|
|
907
790
|
const table = useReactTable(tableConfig);
|
|
908
|
-
|
|
909
|
-
// Diagnostic logging when table is created but rows are empty
|
|
910
|
-
useEffect(() => {
|
|
911
|
-
const rows = table.getRowModel().rows;
|
|
912
|
-
|
|
913
|
-
if (rows.length === 0 && finalTableData.length > 0) {
|
|
914
|
-
const coreRows = table.getCoreRowModel().rows;
|
|
915
|
-
const prePaginationRows = table.getPrePaginationRowModel?.()?.rows || [];
|
|
916
|
-
const filteredRows = table.getFilteredRowModel?.()?.rows || [];
|
|
917
|
-
const sortedRows = table.getSortedRowModel?.()?.rows || [];
|
|
918
|
-
const tableState = table.getState();
|
|
919
|
-
|
|
920
|
-
logger.warn('Table created but rows are empty!', {
|
|
921
|
-
finalTableDataLength: finalTableData.length,
|
|
922
|
-
tableConfigDataLength: tableConfig.data?.length || 0,
|
|
923
|
-
coreRowsLength: coreRows.length,
|
|
924
|
-
prePaginationRowsLength: prePaginationRows.length,
|
|
925
|
-
filteredRowsLength: filteredRows.length,
|
|
926
|
-
sortedRowsLength: sortedRows.length,
|
|
927
|
-
finalRowsLength: rows.length,
|
|
928
|
-
pagination: tableState.pagination,
|
|
929
|
-
finalPaginationMode,
|
|
930
|
-
hasServerSideConfig: !!serverSide,
|
|
931
|
-
tableOptions: {
|
|
932
|
-
getCoreRowModel: !!tableConfig.getCoreRowModel,
|
|
933
|
-
getFilteredRowModel: !!tableConfig.getFilteredRowModel,
|
|
934
|
-
getSortedRowModel: !!tableConfig.getSortedRowModel,
|
|
935
|
-
getPaginationRowModel: !!tableConfig.getPaginationRowModel,
|
|
936
|
-
manualPagination: tableConfig.manualPagination,
|
|
937
|
-
manualFiltering: tableConfig.manualFiltering,
|
|
938
|
-
manualSorting: tableConfig.manualSorting,
|
|
939
|
-
pageCount: tableConfig.pageCount,
|
|
940
|
-
},
|
|
941
|
-
hasRowId: !!resolvedGetRowId,
|
|
942
|
-
effectivePageSize,
|
|
943
|
-
});
|
|
944
|
-
}
|
|
945
|
-
}, [table, finalTableData.length, tableConfig, resolvedGetRowId, finalPaginationMode, serverSide, effectivePageSize, logger]);
|
|
946
791
|
|
|
947
792
|
// ============================================================================
|
|
948
793
|
// RBAC VALIDATION AND EARLY RETURNS - AFTER ALL HOOKS
|
|
@@ -1084,31 +929,9 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
1084
929
|
};
|
|
1085
930
|
|
|
1086
931
|
// If custom handler provided, call it with options
|
|
1087
|
-
console.log('[DataTableCore] Export handler check:', {
|
|
1088
|
-
'secureHandlers.onExport exists': !!secureHandlers.onExport,
|
|
1089
|
-
'permissions.canExport.can': permissions.canExport.can,
|
|
1090
|
-
'onExport prop provided': !!onExport,
|
|
1091
|
-
'onExport type': typeof onExport,
|
|
1092
|
-
});
|
|
1093
|
-
|
|
1094
932
|
if (secureHandlers.onExport) {
|
|
1095
|
-
console.log('[DataTableCore] ✅ Calling custom onExport handler');
|
|
1096
|
-
logger.debug('[DataTableCore] Calling custom onExport handler');
|
|
1097
933
|
await secureHandlers.onExport(exportOptions);
|
|
1098
|
-
console.log('[DataTableCore] ✅ Custom onExport handler completed');
|
|
1099
|
-
logger.debug('[DataTableCore] Custom onExport handler completed');
|
|
1100
934
|
return;
|
|
1101
|
-
} else {
|
|
1102
|
-
console.warn('[DataTableCore] ⚠️ No custom onExport handler, using default export', {
|
|
1103
|
-
'secureHandlers.onExport': !!secureHandlers.onExport,
|
|
1104
|
-
'permissions.canExport.can': permissions.canExport.can,
|
|
1105
|
-
'onExport prop provided': !!onExport,
|
|
1106
|
-
});
|
|
1107
|
-
logger.debug('[DataTableCore] No custom onExport handler, using default export', {
|
|
1108
|
-
'secureHandlers.onExport': !!secureHandlers.onExport,
|
|
1109
|
-
'permissions.canExport.can': permissions.canExport.can,
|
|
1110
|
-
'onExport prop provided': !!onExport,
|
|
1111
|
-
});
|
|
1112
935
|
}
|
|
1113
936
|
|
|
1114
937
|
// Default export: exports exactly what's shown in the table
|
|
@@ -1150,8 +973,6 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
1150
973
|
description: `Data exported to ${exportOptions.filename}`,
|
|
1151
974
|
variant: "default"
|
|
1152
975
|
});
|
|
1153
|
-
|
|
1154
|
-
logger.debug('Export completed successfully');
|
|
1155
976
|
} catch (error) {
|
|
1156
977
|
logger.error('Failed to export data:', error);
|
|
1157
978
|
|
|
@@ -1421,12 +1242,10 @@ function DataTableInternal<TData extends DataRecord>(props: DataTableCoreProps<T
|
|
|
1421
1242
|
onImport={async (data: TData[]) => {
|
|
1422
1243
|
if (onImport) {
|
|
1423
1244
|
try {
|
|
1424
|
-
logger.debug('onImport called with', data.length, 'rows');
|
|
1425
1245
|
const result = onImport(data);
|
|
1426
1246
|
if (result && typeof result.then === 'function') {
|
|
1427
1247
|
await result;
|
|
1428
1248
|
}
|
|
1429
|
-
logger.debug('onImport completed successfully');
|
|
1430
1249
|
|
|
1431
1250
|
// Show success toast
|
|
1432
1251
|
// NOTE: Toast notifications use default timeout (5 seconds) - do not set duration property
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
|
11
11
|
import { Alert, AlertDescription, AlertTitle } from '../../Alert/Alert';
|
|
12
12
|
import { Button } from '../../Button/Button';
|
|
13
|
-
import { createLogger } from '../../../utils/logger';
|
|
13
|
+
import { createLogger } from '../../../utils/core/logger';
|
|
14
14
|
// Icons removed to avoid test mocking issues
|
|
15
15
|
|
|
16
16
|
// ============================================================================
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
import React, { useEffect } from 'react';
|
|
25
25
|
import { ImportModal, type ImportModalConfig } from './ImportModal';
|
|
26
|
-
import { createLogger } from '../../../utils/logger';
|
|
26
|
+
import { createLogger } from '../../../utils/core/logger';
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Maps CSV column data to table column structure
|
|
@@ -43,8 +43,6 @@ function mapCSVToTableColumns<TData extends Record<string, unknown> = Record<str
|
|
|
43
43
|
// Priority: editAccessorKey > accessorKey > id
|
|
44
44
|
const columnMap = new Map<string, string>();
|
|
45
45
|
|
|
46
|
-
logger.debug('Building column map from', columns.length, 'column definitions');
|
|
47
|
-
|
|
48
46
|
columns.forEach(col => {
|
|
49
47
|
const fieldName = col.editAccessorKey || col.accessorKey || col.id;
|
|
50
48
|
const header = typeof col.header === 'string' ? col.header : '';
|
|
@@ -53,13 +51,11 @@ function mapCSVToTableColumns<TData extends Record<string, unknown> = Record<str
|
|
|
53
51
|
const headerLower = header.toLowerCase();
|
|
54
52
|
// Map header to field name (case-insensitive)
|
|
55
53
|
columnMap.set(headerLower, fieldName);
|
|
56
|
-
logger.debug(`Mapped "${header}" -> "${fieldName}"`);
|
|
57
54
|
|
|
58
55
|
// Also map id/accessorKey if different from header
|
|
59
56
|
const colId = col.id || col.accessorKey;
|
|
60
57
|
if (colId && colId !== header && colId !== fieldName) {
|
|
61
58
|
columnMap.set(colId.toLowerCase(), fieldName);
|
|
62
|
-
logger.debug(`Also mapped "${colId}" -> "${fieldName}"`);
|
|
63
59
|
}
|
|
64
60
|
|
|
65
61
|
// For reference fields with editAccessorKey, also map the ID column header
|
|
@@ -68,10 +64,8 @@ function mapCSVToTableColumns<TData extends Record<string, unknown> = Record<str
|
|
|
68
64
|
const editAccessorKey = col.editAccessorKey; // Store in const for proper type narrowing
|
|
69
65
|
const idColumnHeader = `${header} (ID)`;
|
|
70
66
|
columnMap.set(idColumnHeader.toLowerCase(), editAccessorKey);
|
|
71
|
-
logger.debug(`Mapped ID column "${idColumnHeader}" -> "${editAccessorKey}"`);
|
|
72
67
|
// Also map the editAccessorKey directly (in case CSV uses the field name)
|
|
73
68
|
columnMap.set(editAccessorKey.toLowerCase(), editAccessorKey);
|
|
74
|
-
logger.debug(`Also mapped "${editAccessorKey}" -> "${editAccessorKey}"`);
|
|
75
69
|
}
|
|
76
70
|
} else {
|
|
77
71
|
logger.warn('Skipping column with missing fieldName or header:', col);
|
|
@@ -83,10 +77,6 @@ function mapCSVToTableColumns<TData extends Record<string, unknown> = Record<str
|
|
|
83
77
|
return [];
|
|
84
78
|
}
|
|
85
79
|
|
|
86
|
-
const csvHeaders = Object.keys(csvData[0]);
|
|
87
|
-
logger.debug('CSV headers found:', csvHeaders);
|
|
88
|
-
logger.debug('Column map size:', columnMap.size);
|
|
89
|
-
|
|
90
80
|
// Transform CSV data using the mapping
|
|
91
81
|
const mappedData = csvData.map((row, index) => {
|
|
92
82
|
const mappedRow: Record<string, unknown> = {};
|
|
@@ -108,9 +98,6 @@ function mapCSVToTableColumns<TData extends Record<string, unknown> = Record<str
|
|
|
108
98
|
const keyWithSpace = ` ${mapKey}`;
|
|
109
99
|
if (csvHeaderLower === mapKey || csvHeaderLower.endsWith(keyWithSpace)) {
|
|
110
100
|
fieldName = mapValue;
|
|
111
|
-
if (index === 0) {
|
|
112
|
-
logger.debug(`Flexible match: "${csvHeader}" -> "${mapValue}" (matched "${mapKey}")`);
|
|
113
|
-
}
|
|
114
101
|
break; // Found a match, stop searching
|
|
115
102
|
}
|
|
116
103
|
}
|
|
@@ -118,9 +105,6 @@ function mapCSVToTableColumns<TData extends Record<string, unknown> = Record<str
|
|
|
118
105
|
|
|
119
106
|
if (fieldName) {
|
|
120
107
|
mappedRow[fieldName] = row[csvHeader];
|
|
121
|
-
if (index === 0) {
|
|
122
|
-
logger.debug(`Row 0: "${csvHeader}" -> "${fieldName}"`);
|
|
123
|
-
}
|
|
124
108
|
} else {
|
|
125
109
|
// If no mapping found, use the CSV header as-is (lowercase)
|
|
126
110
|
mappedRow[csvHeaderLower] = row[csvHeader];
|
|
@@ -133,11 +117,6 @@ function mapCSVToTableColumns<TData extends Record<string, unknown> = Record<str
|
|
|
133
117
|
return mappedRow as TData;
|
|
134
118
|
});
|
|
135
119
|
|
|
136
|
-
logger.debug('Mapped', mappedData.length, 'rows');
|
|
137
|
-
if (mappedData.length > 0) {
|
|
138
|
-
logger.debug('First mapped row keys:', Object.keys(mappedData[0]));
|
|
139
|
-
}
|
|
140
|
-
|
|
141
120
|
return mappedData;
|
|
142
121
|
}
|
|
143
122
|
|
|
@@ -230,10 +209,7 @@ export function DataTableModals<TData extends Record<string, unknown> = Record<s
|
|
|
230
209
|
// Automatically map CSV columns to table columns based on column definitions
|
|
231
210
|
let mappedData: TData[];
|
|
232
211
|
if (columns && columns.length > 0) {
|
|
233
|
-
logger.debug('Mapping CSV data with', columns.length, 'column definitions');
|
|
234
|
-
logger.debug('Raw CSV headers:', rawData.length > 0 ? Object.keys(rawData[0]) : []);
|
|
235
212
|
mappedData = mapCSVToTableColumns<TData>(rawData, columns);
|
|
236
|
-
logger.debug('Mapped data sample:', mappedData.length > 0 ? mappedData[0] : null);
|
|
237
213
|
} else {
|
|
238
214
|
logger.warn('No columns provided for mapping, using raw data');
|
|
239
215
|
mappedData = rawData as TData[];
|
|
@@ -244,12 +220,10 @@ export function DataTableModals<TData extends Record<string, unknown> = Record<s
|
|
|
244
220
|
throw new Error('Import handler is not configured. Please provide an onImport callback.');
|
|
245
221
|
}
|
|
246
222
|
|
|
247
|
-
logger.debug('Calling onImport with', mappedData.length, 'rows');
|
|
248
223
|
const result = onImport(mappedData);
|
|
249
224
|
if (result && typeof result.then === 'function') {
|
|
250
225
|
await result;
|
|
251
226
|
}
|
|
252
|
-
logger.debug('Import completed successfully');
|
|
253
227
|
} catch (error) {
|
|
254
228
|
logger.error('Import error:', error);
|
|
255
229
|
throw error; // Re-throw to let ImportModal handle it
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Button } from '../../Button/Button';
|
|
3
|
+
import { ChevronUp, ChevronDown,ChevronsUpDown } from 'lucide-react';
|
|
4
|
+
import { cn } from '../../../utils/cn';
|
|
5
|
+
import type { Header } from '@tanstack/react-table';
|
|
6
|
+
|
|
7
|
+
interface DraggableColumnHeaderProps<TData> {
|
|
8
|
+
header: Header<TData, unknown>;
|
|
9
|
+
onMoveLeft?: () => void;
|
|
10
|
+
onMoveRight?: () => void;
|
|
11
|
+
canMoveLeft?: boolean;
|
|
12
|
+
canMoveRight?: boolean;
|
|
13
|
+
enableReordering?: boolean;
|
|
14
|
+
onColumnDrop?: (draggedColumnId: string, targetColumnId: string) => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function DraggableColumnHeader<TData>({
|
|
18
|
+
header,
|
|
19
|
+
onMoveLeft,
|
|
20
|
+
onMoveRight,
|
|
21
|
+
canMoveLeft = false,
|
|
22
|
+
canMoveRight = false,
|
|
23
|
+
enableReordering = false,
|
|
24
|
+
onColumnDrop,
|
|
25
|
+
}: DraggableColumnHeaderProps<TData>) {
|
|
26
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
27
|
+
const [dragOver, setDragOver] = useState(false);
|
|
28
|
+
|
|
29
|
+
const isSortable = header.column.getCanSort ? header.column.getCanSort() : false;
|
|
30
|
+
const ariaSort = isSortable
|
|
31
|
+
? (header.column.getIsSorted ? (header.column.getIsSorted() === 'asc'
|
|
32
|
+
? 'ascending'
|
|
33
|
+
: header.column.getIsSorted() === 'desc'
|
|
34
|
+
? 'descending'
|
|
35
|
+
: 'none') : 'none')
|
|
36
|
+
: undefined;
|
|
37
|
+
|
|
38
|
+
const handleDragStart = (e: React.DragEvent) => {
|
|
39
|
+
if (!enableReordering) return;
|
|
40
|
+
|
|
41
|
+
setIsDragging(true);
|
|
42
|
+
e.dataTransfer.setData('text/plain', header.id);
|
|
43
|
+
e.dataTransfer.effectAllowed = 'move';
|
|
44
|
+
|
|
45
|
+
// Add visual feedback
|
|
46
|
+
if (e.currentTarget instanceof HTMLElement) {
|
|
47
|
+
e.currentTarget.style.opacity = '0.5';
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const handleDragEnd = (e: React.DragEvent) => {
|
|
52
|
+
setIsDragging(false);
|
|
53
|
+
setDragOver(false);
|
|
54
|
+
|
|
55
|
+
// Reset visual feedback
|
|
56
|
+
if (e.currentTarget instanceof HTMLElement) {
|
|
57
|
+
e.currentTarget.style.opacity = '1';
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const handleDragOver = (e: React.DragEvent) => {
|
|
62
|
+
if (!enableReordering) return;
|
|
63
|
+
|
|
64
|
+
e.preventDefault();
|
|
65
|
+
e.dataTransfer.dropEffect = 'move';
|
|
66
|
+
setDragOver(true);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const handleDragLeave = (e: React.DragEvent) => {
|
|
70
|
+
if (!enableReordering) return;
|
|
71
|
+
|
|
72
|
+
// Only set dragOver to false if we're leaving the element entirely
|
|
73
|
+
if (!e.currentTarget.contains(e.relatedTarget as Node)) {
|
|
74
|
+
setDragOver(false);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const handleDrop = (e: React.DragEvent) => {
|
|
79
|
+
if (!enableReordering) return;
|
|
80
|
+
|
|
81
|
+
e.preventDefault();
|
|
82
|
+
setDragOver(false);
|
|
83
|
+
|
|
84
|
+
const draggedHeaderId = e.dataTransfer.getData('text/plain');
|
|
85
|
+
if (draggedHeaderId && draggedHeaderId !== header.id && onColumnDrop) {
|
|
86
|
+
onColumnDrop(draggedHeaderId, header.id);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<th
|
|
92
|
+
className={cn(
|
|
93
|
+
'px-3 py-2 text-sm font-medium text-left relative group',
|
|
94
|
+
isSortable && 'cursor-pointer hover:bg-sec-50',
|
|
95
|
+
isDragging && 'opacity-50',
|
|
96
|
+
dragOver && 'bg-main-50 border-main-200',
|
|
97
|
+
enableReordering && 'cursor-move'
|
|
98
|
+
)}
|
|
99
|
+
style={{}}
|
|
100
|
+
draggable={enableReordering}
|
|
101
|
+
onDragStart={handleDragStart}
|
|
102
|
+
onDragEnd={handleDragEnd}
|
|
103
|
+
onDragOver={handleDragOver}
|
|
104
|
+
onDragLeave={handleDragLeave}
|
|
105
|
+
onDrop={handleDrop}
|
|
106
|
+
{...(isSortable ? { 'aria-sort': ariaSort } : {})}
|
|
107
|
+
>
|
|
108
|
+
<div className="flex items-center justify-between">
|
|
109
|
+
<div className="flex items-center gap-1 flex-1">
|
|
110
|
+
{header.isPlaceholder ? null : (
|
|
111
|
+
isSortable ? (
|
|
112
|
+
<Button
|
|
113
|
+
variant="ghost"
|
|
114
|
+
className="h-auto p-0 font-medium hover:bg-transparent flex-1 justify-start"
|
|
115
|
+
onClick={header.column.getToggleSortingHandler()}
|
|
116
|
+
aria-label={`Sort by ${typeof header.column.columnDef.header === 'string' ? header.column.columnDef.header : 'column'}`}
|
|
117
|
+
tabIndex={0}
|
|
118
|
+
>
|
|
119
|
+
<div className="flex items-center gap-1">
|
|
120
|
+
{typeof header.column.columnDef.header === 'function'
|
|
121
|
+
? header.column.columnDef.header(header.getContext())
|
|
122
|
+
: header.column.columnDef.header}
|
|
123
|
+
{header.column.getIsSorted() === 'asc' ? (
|
|
124
|
+
<ChevronUp className="h-4 w-4" />
|
|
125
|
+
) : header.column.getIsSorted() === 'desc' ? (
|
|
126
|
+
<ChevronDown className="h-4 w-4" />
|
|
127
|
+
) : (
|
|
128
|
+
<ChevronsUpDown className="h-4 w-4" />
|
|
129
|
+
)}
|
|
130
|
+
</div>
|
|
131
|
+
</Button>
|
|
132
|
+
) : (
|
|
133
|
+
<div className="flex-1">
|
|
134
|
+
{typeof header.column.columnDef.header === 'function'
|
|
135
|
+
? header.column.columnDef.header(header.getContext())
|
|
136
|
+
: header.column.columnDef.header}
|
|
137
|
+
</div>
|
|
138
|
+
)
|
|
139
|
+
)}
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
</th>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
SelectLabel,
|
|
15
15
|
SelectSeparator,
|
|
16
16
|
} from '../../Select/Select';
|
|
17
|
-
import { createLogger } from '../../../utils/logger';
|
|
17
|
+
import { createLogger } from '../../../utils/core/logger';
|
|
18
18
|
import type { CellValue, DataRecord, DataTableAction, EditableColumnDef } from '../types';
|
|
19
19
|
|
|
20
20
|
interface EditableRowProps<TData extends DataRecord> {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ColumnFilter } from './ColumnFilter';
|
|
3
3
|
import type { Header, Table } from '@tanstack/react-table';
|
|
4
|
+
import { getColumnHeaderText } from '../utils/columnUtils';
|
|
4
5
|
|
|
5
6
|
interface FilterRowProps<TData> {
|
|
6
7
|
table: Table<TData>;
|
|
@@ -52,10 +53,15 @@ export function FilterRow<TData>({ table, visibleColumns }: FilterRowProps<TData
|
|
|
52
53
|
|
|
53
54
|
// PRIORITY 1: Check if column has explicit filter type configuration
|
|
54
55
|
// This MUST be checked first and must respect any explicit value, including 'text'
|
|
55
|
-
//
|
|
56
|
+
// Check for valid filter type strings explicitly to prevent any edge cases
|
|
56
57
|
// This prevents auto-detection from overriding explicit filterType settings
|
|
57
58
|
const explicitFilterType = columnDef.filterType;
|
|
58
|
-
if (
|
|
59
|
+
if (
|
|
60
|
+
explicitFilterType === 'text' ||
|
|
61
|
+
explicitFilterType === 'select' ||
|
|
62
|
+
explicitFilterType === 'number' ||
|
|
63
|
+
explicitFilterType === 'date'
|
|
64
|
+
) {
|
|
59
65
|
// Explicit filterType set - return it immediately (no auto-detection)
|
|
60
66
|
// This ensures filterType: 'text' is always respected, even for columns with ≤10 unique values
|
|
61
67
|
return explicitFilterType as 'text' | 'select' | 'number' | 'date';
|
|
@@ -108,7 +114,7 @@ export function FilterRow<TData>({ table, visibleColumns }: FilterRowProps<TData
|
|
|
108
114
|
column={column}
|
|
109
115
|
filterType={filterType}
|
|
110
116
|
options={options}
|
|
111
|
-
placeholder={`Filter ${column
|
|
117
|
+
placeholder={`Filter ${getColumnHeaderText(column)}...`}
|
|
112
118
|
/>
|
|
113
119
|
) : (
|
|
114
120
|
<div className="h-8 flex items-center text-sec-400 text-sm">
|
|
@@ -41,7 +41,7 @@ import { Button } from '../../Button/Button';
|
|
|
41
41
|
import { Input } from '../../Input/Input';
|
|
42
42
|
import { Progress } from '../../Progress/Progress';
|
|
43
43
|
import { Upload, FileText, AlertCircle } from 'lucide-react';
|
|
44
|
-
import { createLogger } from '../../../utils/logger';
|
|
44
|
+
import { createLogger } from '../../../utils/core/logger';
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
47
|
* Configuration interface for customizing ImportModal text content
|
|
@@ -160,11 +160,7 @@ export function ImportModal({ isOpen, onClose, onImport, config = {} }: ImportMo
|
|
|
160
160
|
|
|
161
161
|
|
|
162
162
|
const processCSV = (csvText: string): Array<Record<string, unknown>> => {
|
|
163
|
-
logger.debug('Raw CSV text:', csvText.substring(0, 200) + '...');
|
|
164
|
-
|
|
165
163
|
const lines = csvText.split('\n').filter(line => line.trim());
|
|
166
|
-
logger.debug('CSV lines count:', lines.length);
|
|
167
|
-
logger.debug('First few lines:', lines.slice(0, 3));
|
|
168
164
|
|
|
169
165
|
if (lines.length < 2) {
|
|
170
166
|
throw new Error('CSV must have at least a header row and one data row');
|
|
@@ -193,19 +189,16 @@ export function ImportModal({ isOpen, onClose, onImport, config = {} }: ImportMo
|
|
|
193
189
|
};
|
|
194
190
|
|
|
195
191
|
const headers = parseCSVLine(lines[0]).map(h => h.replace(/"/g, '').trim());
|
|
196
|
-
logger.debug('Parsed headers:', headers);
|
|
197
192
|
|
|
198
|
-
const data = lines.slice(1).map((line
|
|
193
|
+
const data = lines.slice(1).map((line) => {
|
|
199
194
|
const values = parseCSVLine(line).map(v => v.replace(/"/g, '').trim());
|
|
200
195
|
const row: Record<string, unknown> = {};
|
|
201
196
|
headers.forEach((header, colIndex) => {
|
|
202
197
|
row[header] = values[colIndex] || '';
|
|
203
198
|
});
|
|
204
|
-
logger.debug(`Row ${index + 1}:`, row);
|
|
205
199
|
return row;
|
|
206
200
|
});
|
|
207
201
|
|
|
208
|
-
logger.debug('Final parsed data:', data);
|
|
209
202
|
return data;
|
|
210
203
|
};
|
|
211
204
|
|
|
@@ -350,7 +343,6 @@ export function ImportModal({ isOpen, onClose, onImport, config = {} }: ImportMo
|
|
|
350
343
|
|
|
351
344
|
const handleFileSelect = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
352
345
|
const selectedFile = event.target.files?.[0];
|
|
353
|
-
logger.debug('File selected:', selectedFile?.name);
|
|
354
346
|
if (selectedFile) {
|
|
355
347
|
setFile(selectedFile);
|
|
356
348
|
setError(null);
|
|
@@ -359,13 +351,9 @@ export function ImportModal({ isOpen, onClose, onImport, config = {} }: ImportMo
|
|
|
359
351
|
// Generate preview
|
|
360
352
|
try {
|
|
361
353
|
const text = await selectedFile.text();
|
|
362
|
-
logger.debug('File content length:', text.length);
|
|
363
354
|
const data = processCSV(text);
|
|
364
|
-
logger.debug('Parsed CSV data:', data.length, 'rows');
|
|
365
|
-
logger.debug('Setting preview data:', data.slice(0, 5));
|
|
366
355
|
setPreviewData(data.slice(0, 5)); // Show first 5 rows as preview
|
|
367
356
|
setTotalCount(data.length); // Store total count
|
|
368
|
-
logger.debug('Preview data state should be updated');
|
|
369
357
|
} catch (err) {
|
|
370
358
|
logger.error('CSV parsing error:', err);
|
|
371
359
|
setError(err instanceof Error ? err.message : 'Failed to preview file');
|