@jmruthers/pace-core 0.6.1 → 0.6.2
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/CHANGELOG.md +43 -10
- package/cursor-rules/00-pace-core-compliance.mdc +18 -91
- package/cursor-rules/01-standards-compliance.mdc +16 -47
- package/cursor-rules/02-project-structure.mdc +4 -4
- package/cursor-rules/03-solid-principles.mdc +45 -164
- package/cursor-rules/04-testing-standards.mdc +22 -69
- package/cursor-rules/05-bug-reports-and-features.mdc +2 -2
- package/cursor-rules/06-code-quality.mdc +42 -125
- package/cursor-rules/07-tech-stack-compliance.mdc +33 -128
- package/cursor-rules/08-markup-quality.mdc +452 -0
- package/cursor-rules/CHANGELOG.md +18 -0
- package/cursor-rules/README.md +2 -1
- package/dist/{AuthService-DjnJHDtC.d.ts → AuthService-BPvc3Ka0.d.ts} +54 -0
- package/dist/{DataTable-CH1U5Tpy.d.ts → DataTable-BMRU8a1j.d.ts} +33 -1
- package/dist/{DataTable-DQ7RSOHE.js → DataTable-TPTKCX4D.js} +10 -9
- package/dist/{PublicPageProvider-ce4xlHYA.d.ts → PublicPageProvider-DC6kCaqf.d.ts} +356 -111
- package/dist/{UnifiedAuthProvider-ATAP5UTR.js → UnifiedAuthProvider-CH6Z342H.js} +3 -3
- package/dist/{UnifiedAuthProvider-185Ih4dj.d.ts → UnifiedAuthProvider-CVcTjx-d.d.ts} +29 -0
- package/dist/{api-N774RPUA.js → api-MVVQZLJI.js} +2 -2
- package/dist/{chunk-KNC55RTG.js → chunk-24UVZUZG.js} +90 -54
- package/dist/chunk-24UVZUZG.js.map +1 -0
- package/dist/{chunk-4N5C5XZU.js → chunk-2UOI2FG5.js} +4 -4
- package/dist/chunk-2UOI2FG5.js.map +1 -0
- package/dist/{chunk-T33XF5ZC.js → chunk-3XC4CPTD.js} +4317 -3963
- package/dist/chunk-3XC4CPTD.js.map +1 -0
- package/dist/{chunk-4ZC4GX36.js → chunk-6J4GEEJR.js} +172 -45
- package/dist/chunk-6J4GEEJR.js.map +1 -0
- package/dist/{chunk-3QRJFVBR.js → chunk-6SOIHG6Z.js} +1 -1
- package/dist/chunk-6SOIHG6Z.js.map +1 -0
- package/dist/{chunk-BYFSK72L.js → chunk-EHMR7VYL.js} +4 -4
- package/dist/chunk-EHMR7VYL.js.map +1 -0
- package/dist/{chunk-I7PSE6JW.js → chunk-F2IMUDXZ.js} +2 -75
- package/dist/chunk-F2IMUDXZ.js.map +1 -0
- package/dist/{chunk-LXQLPRQ2.js → chunk-FFQEQTNW.js} +6 -8
- package/dist/chunk-FFQEQTNW.js.map +1 -0
- package/dist/chunk-FMUCXFII.js +76 -0
- package/dist/chunk-FMUCXFII.js.map +1 -0
- package/dist/{chunk-SQGMNID3.js → chunk-L4OXEN46.js} +4 -5
- package/dist/chunk-L4OXEN46.js.map +1 -0
- package/dist/{chunk-R77UEZ4E.js → chunk-M43Y4SSO.js} +1 -1
- package/dist/chunk-M43Y4SSO.js.map +1 -0
- package/dist/{chunk-3XTALGJF.js → chunk-MMZ7JXPU.js} +60 -223
- package/dist/chunk-MMZ7JXPU.js.map +1 -0
- package/dist/{chunk-GLK6VM3F.js → chunk-NECFR5MM.js} +254 -170
- package/dist/chunk-NECFR5MM.js.map +1 -0
- package/dist/{chunk-JBKQ3SAO.js → chunk-SFZUDBL5.js} +40 -4
- package/dist/chunk-SFZUDBL5.js.map +1 -0
- package/dist/{chunk-XM25TVIE.js → chunk-XWQCNGTQ.js} +724 -363
- package/dist/chunk-XWQCNGTQ.js.map +1 -0
- package/dist/components.d.ts +5 -5
- package/dist/components.js +14 -11
- package/dist/components.js.map +1 -1
- package/dist/{functions-D_kgHktt.d.ts → functions-DHebl8-F.d.ts} +1 -1
- package/dist/hooks.d.ts +55 -122
- package/dist/hooks.js +8 -12
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +60 -13
- package/dist/index.js +19 -19
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +21 -3
- package/dist/providers.js +2 -2
- package/dist/rbac/index.d.ts +145 -114
- package/dist/rbac/index.js +8 -11
- package/dist/theming/runtime.d.ts +1 -13
- package/dist/theming/runtime.js +1 -1
- package/dist/{timezone-_pgH8qrY.d.ts → timezone-CHhWg6b4.d.ts} +3 -10
- package/dist/{types-UU913iLA.d.ts → types-BeoeWV5I.d.ts} +8 -0
- package/dist/{types-CEpcvwwF.d.ts → types-CkbwOr4Y.d.ts} +6 -0
- package/dist/types.d.ts +2 -2
- package/dist/{usePublicRouteParams-BJAlWfuJ.d.ts → usePublicRouteParams-1oMokgLF.d.ts} +31 -1
- package/dist/utils.d.ts +4 -5
- package/dist/utils.js +14 -14
- package/dist/utils.js.map +1 -1
- package/docs/api/README.md +7 -1
- package/docs/api/classes/ColumnFactory.md +8 -8
- package/docs/api/classes/InvalidScopeError.md +4 -4
- package/docs/api/classes/Logger.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +4 -4
- package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
- package/docs/api/classes/PermissionDeniedError.md +4 -4
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +4 -4
- package/docs/api/classes/RBACNotInitializedError.md +4 -4
- package/docs/api/classes/SecureSupabaseClient.md +18 -15
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/enums/LogLevel.md +1 -1
- package/docs/api/enums/RBACErrorCode.md +1 -1
- package/docs/api/enums/RPCFunction.md +1 -1
- package/docs/api/interfaces/AddressFieldProps.md +1 -1
- package/docs/api/interfaces/AddressFieldRef.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +4 -4
- package/docs/api/interfaces/AutocompleteOptions.md +1 -1
- package/docs/api/interfaces/AvatarProps.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +9 -2
- package/docs/api/interfaces/ButtonProps.md +7 -4
- package/docs/api/interfaces/CalendarProps.md +8 -5
- package/docs/api/interfaces/CardProps.md +8 -5
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/ComplianceResult.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +9 -9
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +24 -21
- package/docs/api/interfaces/DataTableColumn.md +31 -31
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
- package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
- package/docs/api/interfaces/DatabaseIssue.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +5 -5
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/ErrorBoundaryProps.md +147 -0
- package/docs/api/interfaces/ErrorBoundaryProviderProps.md +36 -0
- package/docs/api/interfaces/ErrorBoundaryState.md +75 -0
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +8 -8
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- 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 +26 -23
- package/docs/api/interfaces/FooterProps.md +10 -8
- package/docs/api/interfaces/FormFieldProps.md +10 -10
- package/docs/api/interfaces/FormProps.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 +7 -4
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoggerConfig.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +14 -11
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +11 -11
- package/docs/api/interfaces/NavigationMenuProps.md +15 -15
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- 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 +30 -27
- package/docs/api/interfaces/PaceLoginPageProps.md +6 -4
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/ParsedAddress.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProgressProps.md +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.md +7 -26
- package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
- package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
- package/docs/api/interfaces/PublicPageLayoutProps.md +7 -20
- package/docs/api/interfaces/QuickFix.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
- package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
- package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContext.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
- package/docs/api/interfaces/RBACResult.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
- package/docs/api/interfaces/RBACRolesListParams.md +1 -1
- package/docs/api/interfaces/RBACRolesListResult.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +9 -9
- package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +3 -3
- package/docs/api/interfaces/SetupIssue.md +1 -1
- 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/TabsContentProps.md +1 -1
- package/docs/api/interfaces/TabsListProps.md +1 -1
- package/docs/api/interfaces/TabsProps.md +1 -1
- package/docs/api/interfaces/TabsTriggerProps.md +3 -3
- package/docs/api/interfaces/TextareaProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +4 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +58 -55
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +15 -13
- package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
- package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +11 -9
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +6 -6
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +9 -6
- package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
- package/docs/api/interfaces/UsePublicEventReturn.md +8 -5
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +12 -9
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +10 -7
- package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +14 -11
- package/docs/api/interfaces/UserMenuProps.md +8 -6
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +575 -634
- package/docs/architecture/database-schema-requirements.md +161 -0
- package/docs/core-concepts/rbac-system.md +3 -3
- package/docs/documentation-index.md +2 -4
- package/docs/getting-started/cursor-rules.md +2 -1
- package/docs/migration/DOCUMENTATION_STRUCTURE.md +441 -0
- package/docs/migration/MIGRATION_GUIDE.md +2 -24
- package/docs/migration/README.md +52 -6
- package/docs/migration/V0.5.190_TO_V0.6.1_MIGRATION.md +1153 -0
- package/docs/migration/database-changes-december-2025.md +3 -3
- package/docs/rbac/event-based-apps.md +1 -1
- package/docs/rbac/getting-started.md +1 -1
- package/docs/rbac/quick-start.md +1 -1
- package/docs/standards/README.md +1 -0
- package/package.json +2 -1
- package/scripts/audit/core/checks/accessibility.cjs +197 -0
- package/scripts/audit/core/checks/api-usage.cjs +191 -0
- package/scripts/audit/core/checks/bundle.cjs +142 -0
- package/scripts/{check-pace-core-compliance.cjs → audit/core/checks/compliance.cjs} +714 -687
- package/scripts/audit/core/checks/config.cjs +54 -0
- package/scripts/audit/core/checks/coverage.cjs +84 -0
- package/scripts/audit/core/checks/dependencies.cjs +454 -0
- package/scripts/audit/core/checks/documentation.cjs +203 -0
- package/scripts/audit/core/checks/environment.cjs +128 -0
- package/scripts/audit/core/checks/error-handling.cjs +299 -0
- package/scripts/audit/core/checks/forms.cjs +172 -0
- package/scripts/audit/core/checks/heuristics.cjs +68 -0
- package/scripts/audit/core/checks/hooks.cjs +334 -0
- package/scripts/audit/core/checks/imports.cjs +244 -0
- package/scripts/audit/core/checks/performance.cjs +325 -0
- package/scripts/audit/core/checks/routes.cjs +117 -0
- package/scripts/audit/core/checks/state.cjs +130 -0
- package/scripts/audit/core/checks/structure.cjs +65 -0
- package/scripts/audit/core/checks/style.cjs +584 -0
- package/scripts/audit/core/checks/testing.cjs +122 -0
- package/scripts/audit/core/checks/typescript.cjs +61 -0
- package/scripts/audit/core/scanner.cjs +199 -0
- package/scripts/audit/core/utils.cjs +137 -0
- package/scripts/audit/index.cjs +223 -0
- package/scripts/audit/reporters/console.cjs +151 -0
- package/scripts/audit/reporters/json.cjs +54 -0
- package/scripts/audit/reporters/markdown.cjs +124 -0
- package/scripts/audit-consuming-app.cjs +61 -936
- package/scripts/build-docs/build-decision.js +240 -0
- package/scripts/build-docs/cache-utils.js +105 -0
- package/scripts/build-docs/content-normalization.js +150 -0
- package/scripts/build-docs/file-utils.js +105 -0
- package/scripts/build-docs/git-utils.js +86 -0
- package/scripts/build-docs/hash-utils.js +116 -0
- package/scripts/build-docs/typedoc-runner.js +220 -0
- package/scripts/build-docs-incremental.js +77 -913
- package/scripts/utils/command-runner.js +16 -11
- package/scripts/validate-formats.js +61 -56
- package/scripts/validate-master.js +74 -69
- package/scripts/validate-pre-publish.js +70 -65
- package/src/__tests__/hooks/usePermissions.test.ts +2 -2
- package/src/components/Alert/Alert.test.tsx +12 -18
- package/src/components/Alert/Alert.tsx +5 -7
- package/src/components/Avatar/Avatar.test.tsx +4 -4
- package/src/components/Badge/Badge.tsx +14 -0
- package/src/components/Button/Button.tsx +22 -0
- package/src/components/Calendar/Calendar.tsx +8 -2
- package/src/components/Card/Card.tsx +4 -0
- package/src/components/Checkbox/Checkbox.test.tsx +12 -12
- package/src/components/Checkbox/Checkbox.tsx +2 -2
- package/src/components/DataTable/DataTable.tsx +38 -4
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +5 -6
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +18 -4
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +2 -3
- package/src/components/DataTable/components/AccessDeniedPage.tsx +16 -25
- package/src/components/DataTable/components/ActionButtons.tsx +10 -7
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +1 -1
- package/src/components/DataTable/components/ColumnFilter.tsx +10 -0
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +12 -0
- package/src/components/DataTable/components/DataTableBody.tsx +8 -0
- package/src/components/DataTable/components/DataTableCore.tsx +196 -554
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +11 -0
- package/src/components/DataTable/components/DataTableLayout.tsx +559 -0
- package/src/components/DataTable/components/DataTableModals.tsx +8 -0
- package/src/components/DataTable/components/DataTableToolbar.tsx +8 -0
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +12 -0
- package/src/components/DataTable/components/EditFields.tsx +307 -0
- package/src/components/DataTable/components/EditableRow.tsx +8 -0
- package/src/components/DataTable/components/EmptyState.tsx +10 -0
- package/src/components/DataTable/components/FilterRow.tsx +12 -0
- package/src/components/DataTable/components/GroupHeader.tsx +12 -0
- package/src/components/DataTable/components/GroupingDropdown.tsx +12 -0
- package/src/components/DataTable/components/ImportModal.tsx +7 -0
- package/src/components/DataTable/components/LoadingState.tsx +6 -0
- package/src/components/DataTable/components/PaginationControls.tsx +16 -1
- package/src/components/DataTable/components/RowComponent.tsx +391 -0
- package/src/components/DataTable/components/UnifiedTableBody.tsx +61 -849
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +16 -4
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +4 -2
- package/src/components/DataTable/components/cellValueUtils.ts +40 -0
- package/src/components/DataTable/components/hooks/useImportModalFocus.ts +53 -0
- package/src/components/DataTable/components/hooks/usePermissionTracking.ts +126 -0
- package/src/components/DataTable/context/DataTableContext.tsx +50 -0
- package/src/components/DataTable/core/ColumnFactory.ts +31 -0
- package/src/components/DataTable/core/DataTableContext.tsx +32 -1
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +10 -0
- package/src/components/DataTable/hooks/useColumnReordering.ts +12 -0
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +10 -0
- package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +16 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +124 -32
- package/src/components/DataTable/hooks/useDataTableState.ts +35 -1
- package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +12 -0
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +11 -0
- package/src/components/DataTable/hooks/useTableColumns.ts +8 -0
- package/src/components/DataTable/hooks/useTableHandlers.ts +14 -0
- package/src/components/DataTable/styles.ts +6 -6
- package/src/components/DataTable/types.ts +6 -10
- package/src/components/DataTable/utils/a11yUtils.ts +7 -0
- package/src/components/DataTable/utils/debugTools.ts +18 -113
- package/src/components/DataTable/utils/errorHandling.ts +12 -0
- package/src/components/DataTable/utils/exportUtils.ts +9 -0
- package/src/components/DataTable/utils/flexibleImport.ts +12 -48
- package/src/components/DataTable/utils/paginationUtils.ts +8 -0
- package/src/components/DataTable/utils/performanceUtils.ts +5 -1
- package/src/components/Dialog/Dialog.tsx +2 -2
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +180 -1
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +45 -5
- package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +129 -0
- package/src/components/ErrorBoundary/index.ts +27 -2
- package/src/components/EventSelector/EventSelector.tsx +3 -0
- package/src/components/FileDisplay/FileDisplay.tsx +32 -18
- package/src/components/FileUpload/FileUpload.tsx +22 -2
- package/src/components/Footer/Footer.test.tsx +16 -16
- package/src/components/Footer/Footer.tsx +14 -11
- package/src/components/Form/Form.tsx +1 -0
- package/src/components/Header/Header.tsx +21 -10
- package/src/components/Input/Input.test.tsx +2 -2
- package/src/components/Input/Input.tsx +8 -4
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +4 -4
- package/src/components/LoginForm/LoginForm.tsx +4 -0
- package/src/components/NavigationMenu/NavigationMenu.tsx +14 -513
- package/src/components/NavigationMenu/types.ts +56 -0
- package/src/components/NavigationMenu/useNavigationFiltering.ts +390 -0
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +3 -0
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +4 -2
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +32 -11
- package/src/components/PaceAppLayout/test-setup.tsx +1 -2
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +3 -0
- package/src/components/PasswordChange/PasswordChangeForm.tsx +9 -0
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -9
- package/src/components/PublicLayout/PublicPageLayout.tsx +2 -5
- package/src/components/PublicLayout/PublicPageProvider.tsx +4 -0
- package/src/components/Select/Select.tsx +80 -434
- package/src/components/Select/context.ts +23 -0
- package/src/components/Select/hooks/useSelectEvents.ts +87 -0
- package/src/components/Select/hooks/useSelectSearch.ts +91 -0
- package/src/components/Select/hooks/useSelectState.ts +104 -0
- package/src/components/Select/index.ts +9 -1
- package/src/components/Select/types.ts +123 -0
- package/src/components/Select/utils/text.ts +26 -0
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +4 -5
- package/src/components/Switch/Switch.tsx +4 -4
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Toast/Toast.tsx +4 -0
- package/src/components/Tooltip/Tooltip.tsx +2 -2
- package/src/components/UserMenu/UserMenu.test.tsx +24 -11
- package/src/components/UserMenu/UserMenu.tsx +21 -18
- package/src/components/index.ts +2 -2
- package/src/hooks/__tests__/index.unit.test.ts +2 -5
- package/src/hooks/index.ts +1 -2
- package/src/hooks/public/usePublicEvent.ts +4 -0
- package/src/hooks/public/usePublicEventLogo.ts +4 -0
- package/src/hooks/public/usePublicFileDisplay.ts +4 -0
- package/src/hooks/public/usePublicRouteParams.ts +4 -0
- package/src/hooks/services/useAuth.ts +32 -0
- package/src/hooks/services/useCurrentEvent.ts +6 -0
- package/src/hooks/services/useCurrentOrganisation.ts +6 -0
- package/src/hooks/useDebounce.ts +9 -0
- package/src/hooks/useEventTheme.ts +6 -0
- package/src/hooks/useFileDisplay.ts +4 -0
- package/src/hooks/useFileReference.ts +25 -7
- package/src/hooks/useFileUrl.ts +11 -1
- package/src/hooks/useFocusManagement.ts +14 -0
- package/src/hooks/useFocusTrap.ts +3 -0
- package/src/hooks/useInactivityTracker.ts +3 -0
- package/src/hooks/useKeyboardShortcuts.ts +4 -0
- package/src/hooks/useOrganisationPermissions.ts +4 -0
- package/src/hooks/useOrganisationSecurity.ts +4 -0
- package/src/hooks/usePerformanceMonitor.ts +4 -0
- package/src/hooks/usePermissionCache.ts +7 -0
- package/src/hooks/useQueryCache.ts +12 -1
- package/src/hooks/useSessionRestoration.ts +4 -0
- package/src/hooks/useStorage.ts +4 -0
- package/src/hooks/useToast.ts +1 -1
- package/src/index.ts +2 -1
- package/src/providers/__tests__/OrganisationProvider.test.tsx +92 -70
- package/src/providers/services/AuthServiceProvider.tsx +18 -0
- package/src/providers/services/EventServiceProvider.tsx +18 -0
- package/src/providers/services/InactivityServiceProvider.tsx +18 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +18 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +36 -0
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +29 -13
- package/src/rbac/README.md +1 -1
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +2 -2
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +4 -5
- package/src/rbac/adapters.tsx +14 -5
- package/src/rbac/api.ts +100 -67
- package/src/rbac/components/NavigationProvider.tsx +4 -1
- package/src/rbac/components/PagePermissionGuard.tsx +157 -17
- package/src/rbac/components/RoleBasedRouter.tsx +5 -1
- package/src/rbac/components/SecureDataProvider.test.tsx +84 -49
- package/src/rbac/components/SecureDataProvider.tsx +20 -5
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +24 -14
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +7 -0
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -6
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +15 -4
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +148 -24
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +81 -15
- package/src/rbac/engine.ts +38 -14
- package/src/rbac/hooks/permissions/index.ts +7 -0
- package/src/rbac/hooks/permissions/useAccessLevel.ts +105 -0
- package/src/rbac/hooks/permissions/useCachedPermissions.ts +79 -0
- package/src/rbac/hooks/permissions/useCan.ts +347 -0
- package/src/rbac/hooks/permissions/useHasAllPermissions.ts +90 -0
- package/src/rbac/hooks/permissions/useHasAnyPermission.ts +90 -0
- package/src/rbac/hooks/permissions/useMultiplePermissions.ts +93 -0
- package/src/rbac/hooks/permissions/usePermissions.ts +253 -0
- package/src/rbac/hooks/useCan.test.ts +71 -64
- package/src/rbac/hooks/usePermissions.ts +14 -995
- package/src/rbac/hooks/useResourcePermissions.test.ts +54 -18
- package/src/rbac/hooks/useResourcePermissions.ts +14 -4
- package/src/rbac/hooks/useSecureSupabase.ts +33 -13
- package/src/rbac/permissions.ts +0 -30
- package/src/rbac/secureClient.ts +200 -61
- package/src/rbac/types.ts +8 -0
- package/src/theming/__tests__/parseEventColours.test.ts +6 -9
- package/src/theming/parseEventColours.ts +5 -19
- package/src/types/vitest-globals.d.ts +51 -26
- package/src/utils/__mocks__/supabaseMock.ts +1 -3
- package/src/utils/__tests__/formatting.unit.test.ts +4 -4
- package/src/utils/__tests__/index.unit.test.ts +2 -2
- package/src/utils/audit/audit.ts +0 -3
- package/src/utils/core/cn.ts +1 -1
- package/src/utils/file-reference/index.ts +53 -1
- package/src/utils/formatting/formatting.ts +8 -18
- package/src/utils/index.ts +0 -1
- package/dist/chunk-3QRJFVBR.js.map +0 -1
- package/dist/chunk-3XTALGJF.js.map +0 -1
- package/dist/chunk-4N5C5XZU.js.map +0 -1
- package/dist/chunk-4ZC4GX36.js.map +0 -1
- package/dist/chunk-BYFSK72L.js.map +0 -1
- package/dist/chunk-EXUD6RNJ.js +0 -451
- package/dist/chunk-EXUD6RNJ.js.map +0 -1
- package/dist/chunk-GLK6VM3F.js.map +0 -1
- package/dist/chunk-I7PSE6JW.js.map +0 -1
- package/dist/chunk-JBKQ3SAO.js.map +0 -1
- package/dist/chunk-KNC55RTG.js.map +0 -1
- package/dist/chunk-LXQLPRQ2.js.map +0 -1
- package/dist/chunk-R77UEZ4E.js.map +0 -1
- package/dist/chunk-SQGMNID3.js.map +0 -1
- package/dist/chunk-T33XF5ZC.js.map +0 -1
- package/dist/chunk-XM25TVIE.js.map +0 -1
- package/docs/api/classes/ErrorBoundary.md +0 -144
- package/docs/migration/quick-migration-guide.md +0 -356
- package/docs/migration/service-architecture.md +0 -281
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -680
- package/src/hooks/useSecureDataAccess.test.ts +0 -559
- package/src/hooks/useSecureDataAccess.ts +0 -681
- /package/dist/{DataTable-DQ7RSOHE.js.map → DataTable-TPTKCX4D.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-ATAP5UTR.js.map → UnifiedAuthProvider-CH6Z342H.js.map} +0 -0
- /package/dist/{api-N774RPUA.js.map → api-MVVQZLJI.js.map} +0 -0
- /package/docs/migration/{organisation-context-timing-fix.md → V0.3.44_organisation-context-timing-fix.md} +0 -0
- /package/docs/migration/{rbac-migration.md → V0.4.0_rbac-migration.md} +0 -0
- /package/docs/migration/{person-scoped-profiles-migration-guide.md → V0.5.190_person-scoped-profiles-migration-guide.md} +0 -0
- /package/docs/migration/{REACT_19_MIGRATION.md → V0.6.0_REACT_19_MIGRATION.md} +0 -0
|
@@ -25,12 +25,13 @@ import {
|
|
|
25
25
|
SelectSeparator,
|
|
26
26
|
SelectTrigger,
|
|
27
27
|
SelectValue
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-3XC4CPTD.js";
|
|
29
29
|
import {
|
|
30
30
|
useCan,
|
|
31
31
|
usePermissions,
|
|
32
|
-
useRBAC
|
|
33
|
-
|
|
32
|
+
useRBAC,
|
|
33
|
+
useResolvedScope
|
|
34
|
+
} from "./chunk-XWQCNGTQ.js";
|
|
34
35
|
import {
|
|
35
36
|
createFileReferenceService,
|
|
36
37
|
generateFileUrlsBatch,
|
|
@@ -42,27 +43,26 @@ import {
|
|
|
42
43
|
useFileDisplay,
|
|
43
44
|
usePreventTabReload,
|
|
44
45
|
usePublicFileDisplay
|
|
45
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-SFZUDBL5.js";
|
|
46
47
|
import {
|
|
47
48
|
useToast
|
|
48
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-6SOIHG6Z.js";
|
|
49
50
|
import {
|
|
50
51
|
ErrorBoundary,
|
|
51
52
|
PublicPageContext,
|
|
52
53
|
useAppConfig,
|
|
53
54
|
useEvents,
|
|
54
|
-
useIsPublicPage
|
|
55
|
-
|
|
56
|
-
} from "./chunk-3XTALGJF.js";
|
|
55
|
+
useIsPublicPage
|
|
56
|
+
} from "./chunk-MMZ7JXPU.js";
|
|
57
57
|
import {
|
|
58
58
|
EventServiceContext,
|
|
59
59
|
useOrganisations,
|
|
60
60
|
useSessionRestoration,
|
|
61
61
|
useUnifiedAuth
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-EHMR7VYL.js";
|
|
63
63
|
import {
|
|
64
64
|
isSuperAdmin
|
|
65
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-24UVZUZG.js";
|
|
66
66
|
import {
|
|
67
67
|
assertAppId
|
|
68
68
|
} from "./chunk-QXHPKYJV.js";
|
|
@@ -72,13 +72,13 @@ import {
|
|
|
72
72
|
} from "./chunk-J36DSWQK.js";
|
|
73
73
|
import {
|
|
74
74
|
cn
|
|
75
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-M43Y4SSO.js";
|
|
76
76
|
import {
|
|
77
77
|
getCurrentAppName
|
|
78
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-F2IMUDXZ.js";
|
|
79
79
|
import {
|
|
80
80
|
clearPalette
|
|
81
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-L4OXEN46.js";
|
|
82
82
|
import {
|
|
83
83
|
createLogger,
|
|
84
84
|
logger
|
|
@@ -423,6 +423,12 @@ function useFileUrl(fileReference, options) {
|
|
|
423
423
|
setError(null);
|
|
424
424
|
return;
|
|
425
425
|
}
|
|
426
|
+
if (!supabase) {
|
|
427
|
+
setUrl(null);
|
|
428
|
+
setIsLoading(false);
|
|
429
|
+
setError(new Error("Supabase client is required for URL generation"));
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
426
432
|
if (isLoading || url && fileReferenceIdRef.current === fileReference.id) {
|
|
427
433
|
return;
|
|
428
434
|
}
|
|
@@ -554,10 +560,14 @@ function FileDisplayContent({
|
|
|
554
560
|
};
|
|
555
561
|
const handleDeleteConfirm = async () => {
|
|
556
562
|
setDeleteDialogOpen(false);
|
|
557
|
-
|
|
558
|
-
|
|
563
|
+
try {
|
|
564
|
+
if (onDelete) {
|
|
565
|
+
await onDelete();
|
|
566
|
+
}
|
|
567
|
+
setImageError(false);
|
|
568
|
+
} catch (error2) {
|
|
569
|
+
setImageError(false);
|
|
559
570
|
}
|
|
560
|
-
setImageError(false);
|
|
561
571
|
};
|
|
562
572
|
const handleImageError = () => {
|
|
563
573
|
setImageError(true);
|
|
@@ -971,9 +981,7 @@ function FileDisplayAuthenticated({
|
|
|
971
981
|
showMetadata
|
|
972
982
|
}) {
|
|
973
983
|
const { supabase } = useUnifiedAuth();
|
|
974
|
-
|
|
975
|
-
return /* @__PURE__ */ jsx4("figure", { className, title: "Error", children: /* @__PURE__ */ jsx4("p", { className: getFallbackClasses(fallbackSize || "md"), children: "Supabase client not available in authenticated context" }) });
|
|
976
|
-
}
|
|
984
|
+
const [displayOnlyFileReference, setDisplayOnlyFileReference] = useState3(null);
|
|
977
985
|
const {
|
|
978
986
|
fileUrl,
|
|
979
987
|
fileReference,
|
|
@@ -988,16 +996,15 @@ function FileDisplayAuthenticated({
|
|
|
988
996
|
record_id,
|
|
989
997
|
organisation_id,
|
|
990
998
|
category,
|
|
991
|
-
{ supabase }
|
|
999
|
+
{ supabase: supabase || null }
|
|
992
1000
|
);
|
|
993
|
-
const [displayOnlyFileReference, setDisplayOnlyFileReference] = useState3(null);
|
|
994
1001
|
const displayOnlyFileUrlFromMap = displayOnlyFileReference ? fileUrls.get(displayOnlyFileReference.id) : null;
|
|
995
1002
|
const displayOnlyFileUrlHook = useFileUrl(
|
|
996
1003
|
displayOnlyFileReference && !displayOnlyFileUrlFromMap ? displayOnlyFileReference : null,
|
|
997
1004
|
{
|
|
998
|
-
supabase,
|
|
1005
|
+
supabase: supabase || null,
|
|
999
1006
|
organisation_id,
|
|
1000
|
-
autoLoad: !displayOnlyFileUrlFromMap && !!displayOnlyFileReference
|
|
1007
|
+
autoLoad: !displayOnlyFileUrlFromMap && !!displayOnlyFileReference && !!supabase
|
|
1001
1008
|
}
|
|
1002
1009
|
);
|
|
1003
1010
|
const displayOnlyFileUrl = displayOnlyFileUrlFromMap || displayOnlyFileUrlHook.url;
|
|
@@ -1012,6 +1019,9 @@ function FileDisplayAuthenticated({
|
|
|
1012
1019
|
setDisplayOnlyFileReference(null);
|
|
1013
1020
|
}
|
|
1014
1021
|
}, [displayOnly, category, fileReferences, fileUrls]);
|
|
1022
|
+
if (!supabase) {
|
|
1023
|
+
return /* @__PURE__ */ jsx4("figure", { className, title: "Error", children: /* @__PURE__ */ jsx4("p", { className: getFallbackClasses(fallbackSize || "md"), children: "Supabase client not available in authenticated context" }) });
|
|
1024
|
+
}
|
|
1015
1025
|
const handleDelete = async () => {
|
|
1016
1026
|
};
|
|
1017
1027
|
let finalFileReference = fileReference;
|
|
@@ -1428,13 +1438,17 @@ function useFileReferenceById(supabase, fileReferenceId, organisationId) {
|
|
|
1428
1438
|
return;
|
|
1429
1439
|
}
|
|
1430
1440
|
const loadUrl = async () => {
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1441
|
+
try {
|
|
1442
|
+
const service = createFileReferenceService(supabase);
|
|
1443
|
+
const url = await service.getFileUrl(
|
|
1444
|
+
fileReference.table_name,
|
|
1445
|
+
fileReference.record_id,
|
|
1446
|
+
organisationId
|
|
1447
|
+
);
|
|
1448
|
+
setFileUrl(url);
|
|
1449
|
+
} catch (error2) {
|
|
1450
|
+
setFileUrl(null);
|
|
1451
|
+
}
|
|
1438
1452
|
};
|
|
1439
1453
|
loadUrl();
|
|
1440
1454
|
}, [fileReference, fileReferenceId, organisationId, supabase]);
|
|
@@ -1982,7 +1996,7 @@ var Calendar = React7.forwardRef(
|
|
|
1982
1996
|
] })
|
|
1983
1997
|
);
|
|
1984
1998
|
}
|
|
1985
|
-
return child;
|
|
1999
|
+
return React7.isValidElement(child) ? React7.cloneElement(child, { key: child.key ?? `calendar-child-${index}` }) : child;
|
|
1986
2000
|
}) });
|
|
1987
2001
|
});
|
|
1988
2002
|
CustomMonth.displayName = "CustomMonth";
|
|
@@ -2236,6 +2250,7 @@ function FormField({
|
|
|
2236
2250
|
type,
|
|
2237
2251
|
placeholder,
|
|
2238
2252
|
"data-testid": testId,
|
|
2253
|
+
"aria-label": label || placeholder || name,
|
|
2239
2254
|
className: cn(
|
|
2240
2255
|
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
2241
2256
|
fieldError && "border-destructive focus-visible:ring-destructive"
|
|
@@ -2864,9 +2879,10 @@ var UserMenu = React12.memo(function UserMenu2({
|
|
|
2864
2879
|
/* @__PURE__ */ jsx16(ChevronDown, { className: "size-4" })
|
|
2865
2880
|
] }) }),
|
|
2866
2881
|
/* @__PURE__ */ jsxs11(SelectContent, { children: [
|
|
2867
|
-
/* @__PURE__ */ jsx16(SelectLabel, { className: "font-normal", children: /* @__PURE__ */ jsxs11("
|
|
2868
|
-
|
|
2869
|
-
/* @__PURE__ */ jsx16("
|
|
2882
|
+
/* @__PURE__ */ jsx16(SelectLabel, { className: "font-normal", children: /* @__PURE__ */ jsxs11("li", { className: "pt-2", children: [
|
|
2883
|
+
userInfo.displayName,
|
|
2884
|
+
/* @__PURE__ */ jsx16("br", {}),
|
|
2885
|
+
/* @__PURE__ */ jsx16("span", { className: "text-muted-foreground", children: userInfo.email })
|
|
2870
2886
|
] }) }),
|
|
2871
2887
|
/* @__PURE__ */ jsx16(SelectSeparator, {}),
|
|
2872
2888
|
/* @__PURE__ */ jsx16(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs11(SelectItem, { value: "change-password", children: [
|
|
@@ -2901,60 +2917,54 @@ var UserMenu = React12.memo(function UserMenu2({
|
|
|
2901
2917
|
] });
|
|
2902
2918
|
});
|
|
2903
2919
|
var UserMenuLoading = React12.memo(function UserMenuLoading2() {
|
|
2904
|
-
return /* @__PURE__ */ jsxs11(
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
] });
|
|
2920
|
+
return /* @__PURE__ */ jsxs11(
|
|
2921
|
+
Button,
|
|
2922
|
+
{
|
|
2923
|
+
type: "button",
|
|
2924
|
+
disabled: true,
|
|
2925
|
+
variant: "outline",
|
|
2926
|
+
className: "flex items-center space-x-2",
|
|
2927
|
+
"aria-label": "Loading user menu",
|
|
2928
|
+
children: [
|
|
2929
|
+
/* @__PURE__ */ jsx16(LoadingSpinner, { size: "sm", className: "inline-block mr-2" }),
|
|
2930
|
+
/* @__PURE__ */ jsx16("span", { className: "truncate max-w-[150px]", children: "Loading..." }),
|
|
2931
|
+
/* @__PURE__ */ jsx16(ChevronDown, { className: "w-4 h-4 text-muted-foreground" })
|
|
2932
|
+
]
|
|
2933
|
+
}
|
|
2934
|
+
);
|
|
2920
2935
|
});
|
|
2921
2936
|
UserMenu.Loading = UserMenuLoading;
|
|
2922
2937
|
|
|
2923
2938
|
// src/components/NavigationMenu/NavigationMenu.tsx
|
|
2924
|
-
import * as
|
|
2939
|
+
import * as React14 from "react";
|
|
2925
2940
|
import { ChevronDown as ChevronDown2 } from "lucide-react";
|
|
2926
|
-
|
|
2927
|
-
|
|
2941
|
+
|
|
2942
|
+
// src/components/NavigationMenu/useNavigationFiltering.ts
|
|
2943
|
+
import * as React13 from "react";
|
|
2944
|
+
function useNavigationFiltering({
|
|
2928
2945
|
items,
|
|
2929
|
-
mode = "dropdown",
|
|
2930
|
-
currentPath,
|
|
2931
|
-
onNavigate,
|
|
2932
|
-
className,
|
|
2933
|
-
disabled = false,
|
|
2934
|
-
buttonText = "Menu",
|
|
2935
|
-
showIcons = true,
|
|
2936
|
-
navigationLabel = "Main navigation",
|
|
2937
|
-
// NEW: Phase 2 - Enhanced Security Features
|
|
2938
|
-
strictMode = true,
|
|
2939
|
-
auditLog = true,
|
|
2940
|
-
onNavigationAccessDenied,
|
|
2941
|
-
onStrictModeViolation,
|
|
2942
2946
|
itemsPreFiltered = false,
|
|
2943
|
-
|
|
2944
|
-
}
|
|
2945
|
-
const [
|
|
2946
|
-
const
|
|
2947
|
+
auditLog = true
|
|
2948
|
+
}) {
|
|
2949
|
+
const [resolvedAppId, setResolvedAppId] = React13.useState(void 0);
|
|
2950
|
+
const previousFilteredItemsRef = React13.useRef([]);
|
|
2947
2951
|
let authContext = null;
|
|
2948
2952
|
try {
|
|
2949
2953
|
authContext = useUnifiedAuth();
|
|
2950
2954
|
} catch (error) {
|
|
2951
|
-
logger.warn(
|
|
2955
|
+
logger.warn(
|
|
2956
|
+
"NavigationMenu",
|
|
2957
|
+
"useUnifiedAuth not available, running in unauthenticated mode"
|
|
2958
|
+
);
|
|
2952
2959
|
}
|
|
2953
2960
|
let rbacContext = null;
|
|
2954
2961
|
try {
|
|
2955
2962
|
rbacContext = useRBAC();
|
|
2956
2963
|
} catch (error) {
|
|
2957
|
-
logger.warn(
|
|
2964
|
+
logger.warn(
|
|
2965
|
+
"NavigationMenu",
|
|
2966
|
+
"useRBAC not available, permission filtering disabled"
|
|
2967
|
+
);
|
|
2958
2968
|
}
|
|
2959
2969
|
const eventLoadingRaw = authContext?.eventLoading;
|
|
2960
2970
|
const eventLoading = eventLoadingRaw ?? false;
|
|
@@ -2964,11 +2974,9 @@ var NavigationMenu = React13.forwardRef(({
|
|
|
2964
2974
|
const { selectedOrganisation } = authContext || {};
|
|
2965
2975
|
const { resolvedScope, isLoading: scopeLoading, error: scopeError } = useResolvedScope({
|
|
2966
2976
|
supabase: itemsPreFiltered ? null : supabase || null,
|
|
2967
|
-
// Skip expensive resolution if pre-filtered
|
|
2968
2977
|
selectedOrganisationId: itemsPreFiltered ? null : selectedOrganisation?.id || null,
|
|
2969
2978
|
selectedEventId: itemsPreFiltered ? null : selectedEvent?.event_id || null
|
|
2970
2979
|
});
|
|
2971
|
-
const [resolvedAppId, setResolvedAppId] = React13.useState(void 0);
|
|
2972
2980
|
React13.useEffect(() => {
|
|
2973
2981
|
if (!scopeLoading && !resolvedScope?.appId && selectedOrganisation?.id && authContext?.appName && authContext?.user?.id && !resolvedAppId) {
|
|
2974
2982
|
if (!authContext.user || !authContext.appName) {
|
|
@@ -2976,7 +2984,7 @@ var NavigationMenu = React13.forwardRef(({
|
|
|
2976
2984
|
}
|
|
2977
2985
|
const userId2 = authContext.user.id;
|
|
2978
2986
|
const appName = authContext.appName;
|
|
2979
|
-
import("./api-
|
|
2987
|
+
import("./api-MVVQZLJI.js").then(({ resolveAppContext }) => {
|
|
2980
2988
|
resolveAppContext({
|
|
2981
2989
|
userId: userId2,
|
|
2982
2990
|
appName
|
|
@@ -2984,11 +2992,19 @@ var NavigationMenu = React13.forwardRef(({
|
|
|
2984
2992
|
if (result?.appId) {
|
|
2985
2993
|
setResolvedAppId(result.appId);
|
|
2986
2994
|
}
|
|
2987
|
-
}).catch((
|
|
2995
|
+
}).catch(() => {
|
|
2988
2996
|
});
|
|
2997
|
+
}).catch(() => {
|
|
2989
2998
|
});
|
|
2990
2999
|
}
|
|
2991
|
-
}, [
|
|
3000
|
+
}, [
|
|
3001
|
+
scopeLoading,
|
|
3002
|
+
resolvedScope?.appId,
|
|
3003
|
+
selectedOrganisation?.id,
|
|
3004
|
+
authContext?.appName,
|
|
3005
|
+
authContext?.user?.id,
|
|
3006
|
+
resolvedAppId
|
|
3007
|
+
]);
|
|
2992
3008
|
const effectiveScope = React13.useMemo(() => {
|
|
2993
3009
|
if (resolvedScope?.organisationId) {
|
|
2994
3010
|
return resolvedScope;
|
|
@@ -3019,17 +3035,17 @@ var NavigationMenu = React13.forwardRef(({
|
|
|
3019
3035
|
};
|
|
3020
3036
|
}, [scopeKey, effectiveScope]);
|
|
3021
3037
|
const userId = authContext?.user?.id || "";
|
|
3022
|
-
const {
|
|
3038
|
+
const {
|
|
3039
|
+
permissions: permissionMap,
|
|
3040
|
+
hasAnyPermission,
|
|
3041
|
+
isLoading: permissionsLoading,
|
|
3042
|
+
error: permissionsError
|
|
3043
|
+
} = usePermissions(
|
|
3023
3044
|
itemsPreFiltered ? null : userId,
|
|
3024
|
-
// Pass null to trigger early return (empty string would wait 3s)
|
|
3025
3045
|
itemsPreFiltered ? void 0 : stableScope.organisationId,
|
|
3026
|
-
// Pass undefined to skip timeout
|
|
3027
3046
|
itemsPreFiltered ? void 0 : stableScope.eventId,
|
|
3028
|
-
// Skip if pre-filtered
|
|
3029
3047
|
itemsPreFiltered ? void 0 : stableScope.appId
|
|
3030
|
-
// Skip if pre-filtered
|
|
3031
3048
|
);
|
|
3032
|
-
const previousFilteredItemsRef = React13.useRef([]);
|
|
3033
3049
|
const filteredItems = React13.useMemo(() => {
|
|
3034
3050
|
if (itemsPreFiltered && items && items.length > 0) {
|
|
3035
3051
|
const visibleItems = (items || []).filter((item) => !item.meta?.hidden);
|
|
@@ -3059,9 +3075,13 @@ var NavigationMenu = React13.forwardRef(({
|
|
|
3059
3075
|
return [];
|
|
3060
3076
|
}
|
|
3061
3077
|
if (permissionsError) {
|
|
3062
|
-
logger.warn(
|
|
3063
|
-
|
|
3064
|
-
|
|
3078
|
+
logger.warn(
|
|
3079
|
+
"NavigationMenu",
|
|
3080
|
+
"Permission check error - showing no items for security",
|
|
3081
|
+
{
|
|
3082
|
+
permissionsError: permissionsError?.message
|
|
3083
|
+
}
|
|
3084
|
+
);
|
|
3065
3085
|
return [];
|
|
3066
3086
|
}
|
|
3067
3087
|
if (!permissionMap || Object.keys(permissionMap).length === 0) {
|
|
@@ -3087,7 +3107,7 @@ var NavigationMenu = React13.forwardRef(({
|
|
|
3087
3107
|
if (item.permissions && item.permissions.length > 0 && !item.href) {
|
|
3088
3108
|
const permissions = item.permissions.filter((p) => typeof p === "string").map((p) => p);
|
|
3089
3109
|
if (permissions.length > 0) {
|
|
3090
|
-
const hasPermission = hasAnyPermission(permissions);
|
|
3110
|
+
const hasPermission = hasAnyPermission?.(permissions);
|
|
3091
3111
|
if (!hasPermission) {
|
|
3092
3112
|
return false;
|
|
3093
3113
|
}
|
|
@@ -3119,13 +3139,12 @@ var NavigationMenu = React13.forwardRef(({
|
|
|
3119
3139
|
if (typeof item.accessLevel === "string") {
|
|
3120
3140
|
const accessLevel = item.accessLevel.toLowerCase();
|
|
3121
3141
|
const userEventRole = rbacContext.eventAppRole;
|
|
3122
|
-
if (rbacContext.isSuperAdmin) {
|
|
3123
|
-
} else {
|
|
3142
|
+
if (!rbacContext.isSuperAdmin) {
|
|
3124
3143
|
const roleToAccessLevel = {
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3144
|
+
viewer: "viewer",
|
|
3145
|
+
participant: "participant",
|
|
3146
|
+
planner: "planner",
|
|
3147
|
+
event_admin: "admin"
|
|
3129
3148
|
};
|
|
3130
3149
|
const userAccessLevel = userEventRole ? roleToAccessLevel[userEventRole] || "viewer" : null;
|
|
3131
3150
|
const levelHierarchy = {
|
|
@@ -3178,7 +3197,6 @@ var NavigationMenu = React13.forwardRef(({
|
|
|
3178
3197
|
}, [
|
|
3179
3198
|
items,
|
|
3180
3199
|
itemsPreFiltered,
|
|
3181
|
-
// Add itemsPreFiltered to dependencies
|
|
3182
3200
|
authContext,
|
|
3183
3201
|
rbacContext,
|
|
3184
3202
|
permissionMap,
|
|
@@ -3189,13 +3207,48 @@ var NavigationMenu = React13.forwardRef(({
|
|
|
3189
3207
|
resolvedScope,
|
|
3190
3208
|
effectiveScope,
|
|
3191
3209
|
auditLog,
|
|
3192
|
-
// Add event context state to dependencies so we re-check permissions when event context becomes available
|
|
3193
3210
|
eventLoadingRaw,
|
|
3194
3211
|
eventLoading,
|
|
3195
3212
|
selectedEvent,
|
|
3196
3213
|
orgContextReady,
|
|
3197
|
-
selectedOrganisation?.id
|
|
3214
|
+
selectedOrganisation?.id,
|
|
3215
|
+
permissionsError,
|
|
3216
|
+
stableScope.organisationId,
|
|
3217
|
+
stableScope.eventId,
|
|
3218
|
+
stableScope.appId
|
|
3198
3219
|
]);
|
|
3220
|
+
return {
|
|
3221
|
+
authContext,
|
|
3222
|
+
rbacContext,
|
|
3223
|
+
filteredItems,
|
|
3224
|
+
permissionMap,
|
|
3225
|
+
hasAnyPermission: hasAnyPermission || null
|
|
3226
|
+
};
|
|
3227
|
+
}
|
|
3228
|
+
|
|
3229
|
+
// src/components/NavigationMenu/NavigationMenu.tsx
|
|
3230
|
+
import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3231
|
+
var NavigationMenu = React14.forwardRef(({
|
|
3232
|
+
items,
|
|
3233
|
+
mode = "dropdown",
|
|
3234
|
+
currentPath,
|
|
3235
|
+
onNavigate,
|
|
3236
|
+
className,
|
|
3237
|
+
disabled = false,
|
|
3238
|
+
buttonText = "Menu",
|
|
3239
|
+
showIcons = true,
|
|
3240
|
+
navigationLabel = "Main navigation",
|
|
3241
|
+
// NEW: Phase 2 - Enhanced Security Features
|
|
3242
|
+
strictMode = true,
|
|
3243
|
+
auditLog = true,
|
|
3244
|
+
onNavigationAccessDenied,
|
|
3245
|
+
onStrictModeViolation,
|
|
3246
|
+
itemsPreFiltered = false,
|
|
3247
|
+
...props
|
|
3248
|
+
}, ref) => {
|
|
3249
|
+
const [expandedItems, setExpandedItems] = React14.useState(/* @__PURE__ */ new Set());
|
|
3250
|
+
const buttonRef = React14.useRef(null);
|
|
3251
|
+
const { authContext, rbacContext, filteredItems, permissionMap, hasAnyPermission } = useNavigationFiltering({ items, itemsPreFiltered, auditLog });
|
|
3199
3252
|
const handleHierarchicalKeyDown = (event, item) => {
|
|
3200
3253
|
switch (event.key) {
|
|
3201
3254
|
case "Enter":
|
|
@@ -3338,7 +3391,7 @@ var NavigationMenu = React13.forwardRef(({
|
|
|
3338
3391
|
id: `submenu-${item.id}`,
|
|
3339
3392
|
role: "menu",
|
|
3340
3393
|
"aria-label": `${item.label} submenu`,
|
|
3341
|
-
children: item.children.map((child) => /* @__PURE__ */ jsx17(
|
|
3394
|
+
children: item.children.map((child) => /* @__PURE__ */ jsx17(React14.Fragment, { children: renderHierarchicalItem(child, level + 1) }, child.id))
|
|
3342
3395
|
}
|
|
3343
3396
|
)
|
|
3344
3397
|
] }) : /* @__PURE__ */ jsx17(
|
|
@@ -3400,7 +3453,7 @@ var NavigationMenu = React13.forwardRef(({
|
|
|
3400
3453
|
className,
|
|
3401
3454
|
"aria-label": navigationLabel,
|
|
3402
3455
|
...props,
|
|
3403
|
-
children: /* @__PURE__ */ jsx17("ul", { role: "menubar", children: filteredItems.map((item) => /* @__PURE__ */ jsx17(
|
|
3456
|
+
children: /* @__PURE__ */ jsx17("ul", { role: "menubar", children: filteredItems.map((item) => /* @__PURE__ */ jsx17(React14.Fragment, { children: renderHierarchicalItem(item, 0) }, item.id)) })
|
|
3404
3457
|
}
|
|
3405
3458
|
);
|
|
3406
3459
|
});
|
|
@@ -3445,7 +3498,7 @@ function Header({
|
|
|
3445
3498
|
return /* @__PURE__ */ jsx18("header", { className: cn(
|
|
3446
3499
|
"w-full border-b border-main-200 h-16 shadow-sm bg-main-100 ",
|
|
3447
3500
|
className
|
|
3448
|
-
), role: "banner", children: /* @__PURE__ */ jsxs13("nav", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto
|
|
3501
|
+
), role: "banner", children: /* @__PURE__ */ jsxs13("nav", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto grid grid-cols-[auto_1fr_auto_auto_auto_auto] items-center gap-4 h-full", children: [
|
|
3449
3502
|
logo ? logoHref ? /* @__PURE__ */ jsx18(Link, { to: logoHref, className: "cursor-pointer hover:opacity-80 transition-opacity", children: logo }) : logo : logoUrl ? logoHref ? /* @__PURE__ */ jsx18(Link, { to: logoHref, className: "cursor-pointer hover:opacity-80 transition-opacity", children: /* @__PURE__ */ jsx18(
|
|
3450
3503
|
"img",
|
|
3451
3504
|
{
|
|
@@ -3486,32 +3539,36 @@ function Header({
|
|
|
3486
3539
|
itemsPreFiltered: true
|
|
3487
3540
|
}
|
|
3488
3541
|
),
|
|
3489
|
-
/* @__PURE__ */
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3542
|
+
showOrgSelector ? /* @__PURE__ */ jsx18(OrganisationSelectorConditional, {}) : null,
|
|
3543
|
+
showEventSelector ? /* @__PURE__ */ jsx18(
|
|
3544
|
+
EventSelector,
|
|
3545
|
+
{
|
|
3546
|
+
placeholder: "Select event",
|
|
3547
|
+
className: cn(
|
|
3548
|
+
"w-96",
|
|
3549
|
+
// If both org selector and actions exist, EventSelector uses 1 column
|
|
3550
|
+
// If only one exists, EventSelector spans 2 columns
|
|
3551
|
+
// If neither exists, EventSelector spans 3 columns
|
|
3552
|
+
showOrgSelector && actions ? "col-span-1" : showOrgSelector || actions ? "col-span-2" : "col-span-3"
|
|
3553
|
+
),
|
|
3554
|
+
"data-testid": "event-selector"
|
|
3555
|
+
}
|
|
3556
|
+
) : null,
|
|
3557
|
+
actions,
|
|
3558
|
+
showUserMenu && (userMenu ? userMenu : /* @__PURE__ */ jsx18(
|
|
3559
|
+
UserMenu,
|
|
3560
|
+
{
|
|
3561
|
+
user: user || null,
|
|
3562
|
+
onSignOut,
|
|
3563
|
+
onChangePassword,
|
|
3564
|
+
className: "w-70"
|
|
3565
|
+
}
|
|
3566
|
+
))
|
|
3510
3567
|
] }) });
|
|
3511
3568
|
}
|
|
3512
3569
|
|
|
3513
3570
|
// src/components/Footer/Footer.tsx
|
|
3514
|
-
import
|
|
3571
|
+
import React15 from "react";
|
|
3515
3572
|
import { Fragment as Fragment7, jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3516
3573
|
var FooterComponent = ({
|
|
3517
3574
|
companyName = "Solvera Solutions Pty Ltd",
|
|
@@ -3531,11 +3588,11 @@ var FooterComponent = ({
|
|
|
3531
3588
|
] }) });
|
|
3532
3589
|
};
|
|
3533
3590
|
FooterComponent.displayName = "Footer";
|
|
3534
|
-
var Footer =
|
|
3591
|
+
var Footer = React15.memo(FooterComponent);
|
|
3535
3592
|
Footer.displayName = "Footer";
|
|
3536
3593
|
|
|
3537
3594
|
// src/components/PaceAppLayout/PaceAppLayout.tsx
|
|
3538
|
-
import { useState as
|
|
3595
|
+
import { useState as useState13, useEffect as useEffect8, useMemo as useMemo9 } from "react";
|
|
3539
3596
|
import { Outlet, useNavigate, useLocation } from "react-router-dom";
|
|
3540
3597
|
import { Fragment as Fragment8, jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3541
3598
|
var EMPTY_PAGE_ID_MAPPING = {};
|
|
@@ -3579,8 +3636,8 @@ function PaceAppLayout({
|
|
|
3579
3636
|
isLoading: organisationLoading
|
|
3580
3637
|
} = useOrganisations();
|
|
3581
3638
|
const { isSuperAdmin: isSuperAdminFromRBAC, isLoading: rbacLoading } = useRBAC();
|
|
3582
|
-
const [isSuperAdminDirect, setIsSuperAdminDirect] =
|
|
3583
|
-
const [isCheckingSuperAdminDirect, setIsCheckingSuperAdminDirect] =
|
|
3639
|
+
const [isSuperAdminDirect, setIsSuperAdminDirect] = useState13(false);
|
|
3640
|
+
const [isCheckingSuperAdminDirect, setIsCheckingSuperAdminDirect] = useState13(false);
|
|
3584
3641
|
useEffect8(() => {
|
|
3585
3642
|
const checkSuperAdminDirect = async () => {
|
|
3586
3643
|
if (!user?.id) {
|
|
@@ -3594,8 +3651,8 @@ function PaceAppLayout({
|
|
|
3594
3651
|
}
|
|
3595
3652
|
setIsCheckingSuperAdminDirect(true);
|
|
3596
3653
|
try {
|
|
3597
|
-
const
|
|
3598
|
-
setIsSuperAdminDirect(
|
|
3654
|
+
const superAdminStatus2 = await isSuperAdmin(user.id);
|
|
3655
|
+
setIsSuperAdminDirect(superAdminStatus2);
|
|
3599
3656
|
} catch (error) {
|
|
3600
3657
|
logger.error("PaceAppLayout", "Error checking super admin status directly", { userId: user?.id, error });
|
|
3601
3658
|
setIsSuperAdminDirect(false);
|
|
@@ -3665,6 +3722,7 @@ function PaceAppLayout({
|
|
|
3665
3722
|
return permissionString;
|
|
3666
3723
|
}, [enforcePermissions, currentRoutePermission, currentPageId]);
|
|
3667
3724
|
const shouldCheckPermission = enforcePermissions && !!currentPermission && !!currentPageId;
|
|
3725
|
+
const superAdminStatus = isSuperAdminFromRBAC ? true : isCheckingSuperAdminDirect ? null : isSuperAdminDirect;
|
|
3668
3726
|
const { can: canFromHook, isLoading: isCheckingPermission, error: permissionError } = useCan(
|
|
3669
3727
|
user?.id || "",
|
|
3670
3728
|
scope,
|
|
@@ -3672,6 +3730,8 @@ function PaceAppLayout({
|
|
|
3672
3730
|
shouldCheckPermission ? currentPageId : "",
|
|
3673
3731
|
true,
|
|
3674
3732
|
// useCache
|
|
3733
|
+
superAdminStatus,
|
|
3734
|
+
// Pass super admin status to avoid duplicate check
|
|
3675
3735
|
appName
|
|
3676
3736
|
// Pass appName for PORTAL/ADMIN special case
|
|
3677
3737
|
);
|
|
@@ -3700,7 +3760,7 @@ function PaceAppLayout({
|
|
|
3700
3760
|
onPageAccessDenied(currentPageId, currentRoutePermission);
|
|
3701
3761
|
}
|
|
3702
3762
|
}, [enforcePermissions, can, isCheckingPermission, isSuperAdmin2, currentPageId, currentRoutePermission, user?.id, strictMode, auditLog, onPageAccessDenied, onStrictModeViolation]);
|
|
3703
|
-
const [filteredMenuItems, setFilteredMenuItems] =
|
|
3763
|
+
const [filteredMenuItems, setFilteredMenuItems] = useState13(baseMenuItems);
|
|
3704
3764
|
useEffect8(() => {
|
|
3705
3765
|
let isMounted = true;
|
|
3706
3766
|
const filterItems = async () => {
|
|
@@ -3727,7 +3787,7 @@ function PaceAppLayout({
|
|
|
3727
3787
|
return;
|
|
3728
3788
|
}
|
|
3729
3789
|
try {
|
|
3730
|
-
const { isSuperAdmin: checkSuperAdminDynamic } = await import("./api-
|
|
3790
|
+
const { isSuperAdmin: checkSuperAdminDynamic } = await import("./api-MVVQZLJI.js");
|
|
3731
3791
|
const isSuper = await checkSuperAdminDynamic(user.id);
|
|
3732
3792
|
if (isSuper) {
|
|
3733
3793
|
if (isMounted) {
|
|
@@ -3742,7 +3802,7 @@ function PaceAppLayout({
|
|
|
3742
3802
|
}
|
|
3743
3803
|
}
|
|
3744
3804
|
try {
|
|
3745
|
-
const { getPermissionMap } = await import("./api-
|
|
3805
|
+
const { getPermissionMap } = await import("./api-MVVQZLJI.js");
|
|
3746
3806
|
const permissionScope = {
|
|
3747
3807
|
organisationId: currentScope.organisationId,
|
|
3748
3808
|
eventId: currentScope.eventId,
|
|
@@ -3798,7 +3858,7 @@ function PaceAppLayout({
|
|
|
3798
3858
|
let hasAccess = true;
|
|
3799
3859
|
if (currentRoute.pageId && currentRoute.permissions && currentRoute.permissions.length > 0) {
|
|
3800
3860
|
try {
|
|
3801
|
-
const { isPermittedCached } = await import("./api-
|
|
3861
|
+
const { isPermittedCached } = await import("./api-MVVQZLJI.js");
|
|
3802
3862
|
const hasPagePermission = await isPermittedCached({
|
|
3803
3863
|
userId: user?.id || "",
|
|
3804
3864
|
scope,
|
|
@@ -3814,7 +3874,7 @@ function PaceAppLayout({
|
|
|
3814
3874
|
}
|
|
3815
3875
|
}
|
|
3816
3876
|
if (hasAccess && currentRoute.roles && currentRoute.roles.length > 0 && user?.id) {
|
|
3817
|
-
const { useUnifiedAuth: useUnifiedAuth2 } = await import("./UnifiedAuthProvider-
|
|
3877
|
+
const { useUnifiedAuth: useUnifiedAuth2 } = await import("./UnifiedAuthProvider-CH6Z342H.js");
|
|
3818
3878
|
hasAccess = true;
|
|
3819
3879
|
}
|
|
3820
3880
|
if (!isMounted) return;
|
|
@@ -3845,20 +3905,34 @@ function PaceAppLayout({
|
|
|
3845
3905
|
};
|
|
3846
3906
|
}, [roleBasedRouting, routeConfig, location.pathname, strictMode, user?.id, fallbackRoute, scope, navigate, auditLog, onRouteAccessDenied, onRouteStrictModeViolation]);
|
|
3847
3907
|
const handleSignOut = async () => {
|
|
3848
|
-
|
|
3908
|
+
try {
|
|
3909
|
+
await signOut();
|
|
3910
|
+
} catch (error) {
|
|
3911
|
+
logger.error("PaceAppLayout", "Failed to sign out", { error: error instanceof Error ? error.message : String(error) });
|
|
3912
|
+
}
|
|
3849
3913
|
};
|
|
3850
3914
|
const handleChangePassword = async (newPassword, confirmPassword) => {
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3915
|
+
try {
|
|
3916
|
+
const result = await updatePassword(newPassword);
|
|
3917
|
+
if (result?.error) {
|
|
3918
|
+
logger.error("PaceAppLayout", "Failed to change password", { error: result.error.message });
|
|
3919
|
+
return {
|
|
3920
|
+
error: {
|
|
3921
|
+
message: result.error.message,
|
|
3922
|
+
code: result.error.name || "PASSWORD_UPDATE_ERROR"
|
|
3923
|
+
}
|
|
3924
|
+
};
|
|
3925
|
+
}
|
|
3926
|
+
return {};
|
|
3927
|
+
} catch (error) {
|
|
3928
|
+
logger.error("PaceAppLayout", "Failed to change password", { error: error instanceof Error ? error.message : String(error) });
|
|
3854
3929
|
return {
|
|
3855
3930
|
error: {
|
|
3856
|
-
message:
|
|
3857
|
-
code:
|
|
3931
|
+
message: error instanceof Error ? error.message : "An unexpected error occurred",
|
|
3932
|
+
code: "PASSWORD_UPDATE_ERROR"
|
|
3858
3933
|
}
|
|
3859
3934
|
};
|
|
3860
3935
|
}
|
|
3861
|
-
return {};
|
|
3862
3936
|
};
|
|
3863
3937
|
if (user?.id && organisationLoading && !isSuperAdmin2 && !isCheckingSuperAdminDirect && !rbacLoading && !selectedOrganisationId) {
|
|
3864
3938
|
return /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs15("div", { className: "text-center", children: [
|
|
@@ -3937,7 +4011,7 @@ function PaceAppLayout({
|
|
|
3937
4011
|
}
|
|
3938
4012
|
|
|
3939
4013
|
// src/components/PaceLoginPage/PaceLoginPage.tsx
|
|
3940
|
-
import { useEffect as useEffect9, useState as
|
|
4014
|
+
import { useEffect as useEffect9, useState as useState14, useContext as useContext2 } from "react";
|
|
3941
4015
|
import { useNavigate as useNavigate2, useLocation as useLocation2 } from "react-router-dom";
|
|
3942
4016
|
import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
3943
4017
|
var PaceLoginPage = ({
|
|
@@ -3948,9 +4022,9 @@ var PaceLoginPage = ({
|
|
|
3948
4022
|
const { signIn, isAuthenticated, isLoading, authError, user, supabase } = useUnifiedAuth();
|
|
3949
4023
|
const navigate = useNavigate2();
|
|
3950
4024
|
const location = useLocation2();
|
|
3951
|
-
const [isSigningIn, setIsSigningIn] =
|
|
3952
|
-
const [accessError, setAccessError] =
|
|
3953
|
-
const [isCheckingAccess, setIsCheckingAccess] =
|
|
4025
|
+
const [isSigningIn, setIsSigningIn] = useState14(false);
|
|
4026
|
+
const [accessError, setAccessError] = useState14(null);
|
|
4027
|
+
const [isCheckingAccess, setIsCheckingAccess] = useState14(false);
|
|
3954
4028
|
const eventServiceContext = useContext2(EventServiceContext);
|
|
3955
4029
|
const eventService = eventServiceContext?.eventService || null;
|
|
3956
4030
|
useEffect9(() => {
|
|
@@ -4102,7 +4176,7 @@ var SessionRestorationLoader = ({
|
|
|
4102
4176
|
className
|
|
4103
4177
|
}) => {
|
|
4104
4178
|
return /* @__PURE__ */ jsxs17(
|
|
4105
|
-
|
|
4179
|
+
Alert,
|
|
4106
4180
|
{
|
|
4107
4181
|
className: cn(
|
|
4108
4182
|
"flex flex-col items-center justify-center h-screen w-full gap-4 text-center p-4 bg-background",
|
|
@@ -4113,19 +4187,18 @@ var SessionRestorationLoader = ({
|
|
|
4113
4187
|
"aria-label": message,
|
|
4114
4188
|
children: [
|
|
4115
4189
|
/* @__PURE__ */ jsx22(LoadingSpinner, { size: "lg" }),
|
|
4116
|
-
/* @__PURE__ */ jsx22("
|
|
4190
|
+
/* @__PURE__ */ jsx22("span", { className: "text-sm text-sec-600", children: message })
|
|
4117
4191
|
]
|
|
4118
4192
|
}
|
|
4119
4193
|
);
|
|
4120
4194
|
};
|
|
4121
4195
|
|
|
4122
4196
|
// src/components/ProtectedRoute/ProtectedRoute.tsx
|
|
4123
|
-
import { useMemo as useMemo10, useEffect as useEffect10, useRef as
|
|
4197
|
+
import { useMemo as useMemo10, useEffect as useEffect10, useRef as useRef9, useState as useState15 } from "react";
|
|
4124
4198
|
import { Navigate, Outlet as Outlet2 } from "react-router-dom";
|
|
4125
4199
|
import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
4126
4200
|
function ProtectedRoute({
|
|
4127
4201
|
requireEvent = false,
|
|
4128
|
-
allowSuperAdminBypass = false,
|
|
4129
4202
|
noEventsFallback,
|
|
4130
4203
|
loadingFallback,
|
|
4131
4204
|
loginPath = "/login"
|
|
@@ -4137,9 +4210,9 @@ function ProtectedRoute({
|
|
|
4137
4210
|
const eventLoading = requireEvent ? eventsContext.isLoading || false : false;
|
|
4138
4211
|
const sessionRestoration = useSessionRestoration();
|
|
4139
4212
|
usePreventTabReload({ enabled: true, gracePeriodMs: 2e3 });
|
|
4140
|
-
const wasAuthenticatedRef =
|
|
4141
|
-
const [shouldRedirect, setShouldRedirect] =
|
|
4142
|
-
const tabJustBecameVisibleRef =
|
|
4213
|
+
const wasAuthenticatedRef = useRef9(false);
|
|
4214
|
+
const [shouldRedirect, setShouldRedirect] = useState15(false);
|
|
4215
|
+
const tabJustBecameVisibleRef = useRef9(false);
|
|
4143
4216
|
useEffect10(() => {
|
|
4144
4217
|
if (isAuthenticated) {
|
|
4145
4218
|
wasAuthenticatedRef.current = true;
|
|
@@ -4253,7 +4326,7 @@ function ProtectedRoute({
|
|
|
4253
4326
|
}
|
|
4254
4327
|
|
|
4255
4328
|
// src/components/FileUpload/FileUpload.tsx
|
|
4256
|
-
import { useState as
|
|
4329
|
+
import { useState as useState16, useCallback as useCallback11, useRef as useRef10, useEffect as useEffect11, useMemo as useMemo11 } from "react";
|
|
4257
4330
|
import { Fragment as Fragment9, jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
4258
4331
|
function FileUpload({
|
|
4259
4332
|
supabase,
|
|
@@ -4280,12 +4353,19 @@ function FileUpload({
|
|
|
4280
4353
|
onProgress,
|
|
4281
4354
|
children
|
|
4282
4355
|
}) {
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4356
|
+
if (!pageContext) {
|
|
4357
|
+
const errorMsg = "pageContext is required for FileUpload component. This is used for permission checks.";
|
|
4358
|
+
if (import.meta.env.MODE === "development") {
|
|
4359
|
+
console.error("[FileUpload]", errorMsg);
|
|
4360
|
+
}
|
|
4361
|
+
throw new Error(errorMsg);
|
|
4362
|
+
}
|
|
4363
|
+
const [isDragging, setIsDragging] = useState16(false);
|
|
4364
|
+
const [uploadStates, setUploadStates] = useState16(/* @__PURE__ */ new Map());
|
|
4365
|
+
const [resolvedAppId, setResolvedAppId] = useState16(app_id || null);
|
|
4366
|
+
const [isResolvingAppId, setIsResolvingAppId] = useState16(!app_id);
|
|
4367
|
+
const [appIdError, setAppIdError] = useState16(null);
|
|
4368
|
+
const fileInputRef = useRef10(null);
|
|
4289
4369
|
const { uploadFile, isLoading, error } = useFileReference(supabase);
|
|
4290
4370
|
useEffect11(() => {
|
|
4291
4371
|
if (app_id) {
|
|
@@ -4447,6 +4527,10 @@ function FileUpload({
|
|
|
4447
4527
|
const errorMsg = appIdError || "App ID not available. Please provide app_id prop or set app name.";
|
|
4448
4528
|
throw new Error(errorMsg);
|
|
4449
4529
|
}
|
|
4530
|
+
if (!pageContext) {
|
|
4531
|
+
const errorMsg = "pageContext is required for file upload. This is used for permission checks.";
|
|
4532
|
+
throw new Error(errorMsg);
|
|
4533
|
+
}
|
|
4450
4534
|
const result = await uploadFile({
|
|
4451
4535
|
table_name,
|
|
4452
4536
|
record_id,
|
|
@@ -4544,7 +4628,7 @@ function FileUpload({
|
|
|
4544
4628
|
onUploadError?.(errorMessage, file);
|
|
4545
4629
|
}
|
|
4546
4630
|
}
|
|
4547
|
-
}, [uploadFile, table_name, record_id, organisation_id, resolvedAppId, category, folder, isPublic, maxSize, onUploadSuccess, onUploadError, onProgress, validateFile, generatePreview, showPreview, appIdError]);
|
|
4631
|
+
}, [uploadFile, table_name, record_id, organisation_id, resolvedAppId, category, folder, isPublic, maxSize, onUploadSuccess, onUploadError, onProgress, validateFile, generatePreview, showPreview, appIdError, pageContext]);
|
|
4548
4632
|
const handleDragOver = useCallback11((e) => {
|
|
4549
4633
|
e.preventDefault();
|
|
4550
4634
|
e.stopPropagation();
|
|
@@ -4616,7 +4700,8 @@ function FileUpload({
|
|
|
4616
4700
|
onChange: handleFileInputChange,
|
|
4617
4701
|
className: "hidden",
|
|
4618
4702
|
disabled: isDisabled,
|
|
4619
|
-
"data-testid": "file-input"
|
|
4703
|
+
"data-testid": "file-input",
|
|
4704
|
+
"aria-label": accept ? `Upload file${multiple ? "s" : ""} (${accept})` : `Upload file${multiple ? "s" : ""}`
|
|
4620
4705
|
}
|
|
4621
4706
|
),
|
|
4622
4707
|
/* @__PURE__ */ jsx24("div", { className: "text-sec-600", children: isResolvingAppId ? "Resolving app configuration..." : isDragging ? "Drop files here..." : /* @__PURE__ */ jsxs19(Fragment9, { children: [
|
|
@@ -4725,9 +4810,9 @@ function FileUpload({
|
|
|
4725
4810
|
}
|
|
4726
4811
|
|
|
4727
4812
|
// src/components/Table/Table.tsx
|
|
4728
|
-
import * as
|
|
4813
|
+
import * as React20 from "react";
|
|
4729
4814
|
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
4730
|
-
var Table =
|
|
4815
|
+
var Table = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx25(
|
|
4731
4816
|
"table",
|
|
4732
4817
|
{
|
|
4733
4818
|
ref,
|
|
@@ -4736,9 +4821,9 @@ var Table = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
4736
4821
|
}
|
|
4737
4822
|
));
|
|
4738
4823
|
Table.displayName = "Table";
|
|
4739
|
-
var TableHeader =
|
|
4824
|
+
var TableHeader = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx25("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
|
|
4740
4825
|
TableHeader.displayName = "TableHeader";
|
|
4741
|
-
var TableBody =
|
|
4826
|
+
var TableBody = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx25(
|
|
4742
4827
|
"tbody",
|
|
4743
4828
|
{
|
|
4744
4829
|
ref,
|
|
@@ -4747,7 +4832,7 @@ var TableBody = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE_
|
|
|
4747
4832
|
}
|
|
4748
4833
|
));
|
|
4749
4834
|
TableBody.displayName = "TableBody";
|
|
4750
|
-
var TableFooter =
|
|
4835
|
+
var TableFooter = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx25(
|
|
4751
4836
|
"tfoot",
|
|
4752
4837
|
{
|
|
4753
4838
|
ref,
|
|
@@ -4759,7 +4844,7 @@ var TableFooter = React19.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
4759
4844
|
}
|
|
4760
4845
|
));
|
|
4761
4846
|
TableFooter.displayName = "TableFooter";
|
|
4762
|
-
var TableRow =
|
|
4847
|
+
var TableRow = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx25(
|
|
4763
4848
|
"tr",
|
|
4764
4849
|
{
|
|
4765
4850
|
ref,
|
|
@@ -4771,7 +4856,7 @@ var TableRow = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__
|
|
|
4771
4856
|
}
|
|
4772
4857
|
));
|
|
4773
4858
|
TableRow.displayName = "TableRow";
|
|
4774
|
-
var TableHead =
|
|
4859
|
+
var TableHead = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx25(
|
|
4775
4860
|
"th",
|
|
4776
4861
|
{
|
|
4777
4862
|
ref,
|
|
@@ -4783,7 +4868,7 @@ var TableHead = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE_
|
|
|
4783
4868
|
}
|
|
4784
4869
|
));
|
|
4785
4870
|
TableHead.displayName = "TableHead";
|
|
4786
|
-
var TableCell =
|
|
4871
|
+
var TableCell = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx25(
|
|
4787
4872
|
"td",
|
|
4788
4873
|
{
|
|
4789
4874
|
ref,
|
|
@@ -4792,7 +4877,7 @@ var TableCell = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE_
|
|
|
4792
4877
|
}
|
|
4793
4878
|
));
|
|
4794
4879
|
TableCell.displayName = "TableCell";
|
|
4795
|
-
var TableCaption =
|
|
4880
|
+
var TableCaption = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx25(
|
|
4796
4881
|
"caption",
|
|
4797
4882
|
{
|
|
4798
4883
|
ref,
|
|
@@ -4882,7 +4967,6 @@ function PublicPageLayout({
|
|
|
4882
4967
|
error = null,
|
|
4883
4968
|
refetch,
|
|
4884
4969
|
showFooter = true,
|
|
4885
|
-
className = "",
|
|
4886
4970
|
errorFallback: ErrorFallback,
|
|
4887
4971
|
loadingFallback: LoadingFallback,
|
|
4888
4972
|
customHeader,
|
|
@@ -4988,4 +5072,4 @@ export {
|
|
|
4988
5072
|
PublicPageFooter,
|
|
4989
5073
|
PublicPageLayout
|
|
4990
5074
|
};
|
|
4991
|
-
//# sourceMappingURL=chunk-
|
|
5075
|
+
//# sourceMappingURL=chunk-NECFR5MM.js.map
|