@jmruthers/pace-core 0.6.6 → 0.6.8
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/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +227 -22
- package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
- package/audit-tool/audits/02-project-structure.cjs +240 -0
- package/audit-tool/audits/03-architecture.cjs +224 -0
- package/audit-tool/audits/04-code-quality.cjs +149 -0
- package/audit-tool/audits/05-styling.cjs +224 -0
- package/audit-tool/audits/06-security-rbac.cjs +554 -0
- package/audit-tool/audits/07-api-tech-stack.cjs +355 -0
- package/audit-tool/audits/08-testing-documentation.cjs +202 -0
- package/audit-tool/audits/09-operations.cjs +208 -0
- package/audit-tool/index.cjs +295 -0
- package/audit-tool/utils/code-utils.cjs +218 -0
- package/audit-tool/utils/file-utils.cjs +230 -0
- package/audit-tool/utils/report-utils.cjs +380 -0
- package/cursor-rules/00-standards-overview.mdc +156 -0
- package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
- package/cursor-rules/02-project-structure.mdc +37 -5
- package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
- package/cursor-rules/04-code-quality.mdc +419 -0
- package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
- package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
- package/cursor-rules/07-api-tech-stack.mdc +377 -0
- package/cursor-rules/08-testing-documentation.mdc +324 -0
- package/cursor-rules/09-operations.mdc +365 -0
- package/dist/DataTable-6RMSCQJ6.js +15 -0
- package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
- package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-CIGSujI2.d.ts} +40 -24
- package/dist/{UnifiedAuthProvider-ZT6TIGM7.js → UnifiedAuthProvider-7SNDOWYD.js} +2 -2
- package/dist/{api-Y4MQWOFW.js → api-7P7DI652.js} +1 -1
- package/dist/{chunk-MAGBIDNS.js → chunk-4DDCYDQ3.js} +8 -7
- package/dist/{chunk-BVP2BCJF.js → chunk-5W2A3DRC.js} +10 -9
- package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
- package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
- package/dist/{chunk-3O3WHILE.js → chunk-EF2UGZWY.js} +239 -63
- package/dist/{chunk-LAZMKTTF.js → chunk-EURB7QFZ.js} +341 -337
- package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
- package/dist/{chunk-7TYHROIV.js → chunk-GS5672WG.js} +55 -13
- package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
- package/dist/{chunk-ZFYPMX46.js → chunk-LX6U42O3.js} +1 -1
- package/dist/{chunk-FENMYN2U.js → chunk-MPBLMWVR.js} +3 -3
- package/dist/{chunk-ZS5VO5JB.js → chunk-NKHKXPI4.js} +408 -453
- package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
- package/dist/{chunk-4T7OBVTU.js → chunk-S6ZQKDY6.js} +1 -1
- package/dist/{chunk-FTCRZOG2.js → chunk-T5CVK4R3.js} +5 -5
- package/dist/{chunk-OHIK3MIO.js → chunk-Z2FNRKF3.js} +13 -13
- package/dist/components.d.ts +5 -4
- package/dist/components.js +29 -34
- package/dist/eslint-rules/index.cjs +22 -9
- package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
- package/dist/eslint-rules/rules/04-code-quality.cjs +346 -0
- package/dist/eslint-rules/rules/05-styling.cjs +61 -0
- package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +34 -13
- package/dist/eslint-rules/rules/07-api-tech-stack.cjs +385 -0
- package/dist/eslint-rules/rules/08-testing.cjs +94 -0
- package/dist/{functions-DHebl8-F.d.ts → functions-lBy5L2ry.d.ts} +1 -1
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +8 -8
- package/dist/index.d.ts +7 -7
- package/dist/index.js +21 -20
- package/dist/providers.js +2 -2
- package/dist/rbac/index.d.ts +1 -1
- package/dist/rbac/index.js +8 -8
- package/dist/theming/runtime.d.ts +61 -1
- package/dist/theming/runtime.js +1 -1
- package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
- package/dist/types.d.ts +2 -2
- package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +8 -8
- package/docs/README.md +1 -1
- package/docs/api/modules.md +106 -41
- package/docs/api-reference/components.md +18 -20
- package/docs/api-reference/hooks.md +80 -80
- package/docs/api-reference/types.md +1 -1
- package/docs/api-reference/utilities.md +1 -1
- package/docs/architecture/README.md +1 -1
- package/docs/core-concepts/events.md +3 -3
- package/docs/core-concepts/organisations.md +6 -6
- package/docs/core-concepts/permissions.md +6 -6
- package/docs/documentation-index.md +12 -18
- package/docs/getting-started/dependencies.md +23 -0
- package/docs/getting-started/documentation-index.md +1 -1
- package/docs/getting-started/examples/README.md +4 -4
- package/docs/getting-started/examples/full-featured-app.md +1 -1
- package/docs/getting-started/faq.md +2 -2
- package/docs/getting-started/quick-reference.md +4 -4
- package/docs/implementation-guides/app-layout.md +1 -1
- package/docs/implementation-guides/authentication.md +15 -15
- package/docs/implementation-guides/component-styling.md +1 -1
- package/docs/implementation-guides/data-tables.md +127 -34
- package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
- package/docs/implementation-guides/dynamic-colors.md +3 -3
- package/docs/implementation-guides/file-upload-storage.md +2 -2
- package/docs/implementation-guides/hierarchical-datatable.md +40 -60
- package/docs/implementation-guides/inactivity-tracking.md +3 -3
- package/docs/implementation-guides/large-datasets.md +3 -2
- package/docs/implementation-guides/organisation-security.md +2 -2
- package/docs/implementation-guides/performance.md +2 -2
- package/docs/implementation-guides/permission-enforcement.md +1 -1
- package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
- package/docs/migration/V0.4.0_rbac-migration.md +6 -6
- package/docs/rbac/README.md +5 -5
- package/docs/rbac/advanced-patterns.md +6 -6
- package/docs/rbac/api-reference.md +20 -20
- package/docs/rbac/event-based-apps.md +3 -3
- package/docs/rbac/examples.md +41 -41
- package/docs/rbac/getting-started.md +37 -37
- package/docs/rbac/performance.md +1 -1
- package/docs/rbac/quick-start.md +52 -52
- package/docs/rbac/secure-client-protection.md +1 -1
- package/docs/rbac/troubleshooting.md +1 -1
- package/docs/security/README.md +5 -5
- package/docs/standards/0-standards-overview.md +220 -0
- package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +241 -185
- package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
- package/docs/standards/3-architecture-standards.md +606 -0
- package/docs/standards/4-code-quality-standards.md +728 -0
- package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
- package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
- package/docs/standards/7-api-tech-stack-standards.md +662 -0
- package/docs/standards/8-testing-documentation-standards.md +401 -0
- package/docs/standards/9-operations-standards.md +1102 -0
- package/docs/standards/README.md +203 -104
- package/docs/troubleshooting/README.md +4 -4
- package/docs/troubleshooting/common-issues.md +2 -2
- package/docs/troubleshooting/debugging.md +9 -9
- package/docs/troubleshooting/migration.md +4 -4
- package/eslint-config-pace-core.cjs +50 -20
- package/package.json +50 -19
- package/scripts/eslint-audit.cjs +123 -0
- package/scripts/install-cursor-rules.cjs +11 -243
- package/scripts/install-eslint-config.cjs +349 -0
- package/scripts/validate-dependencies.cjs +248 -0
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +30 -18
- package/src/__tests__/integration/UserProfile.test.tsx +14 -14
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
- package/src/__tests__/templates/accessibility.test.template.tsx +10 -9
- package/src/__tests__/templates/component.test.template.tsx +18 -15
- package/src/components/AddressField/AddressField.tsx +26 -1
- package/src/components/Alert/Alert.test.tsx +86 -22
- package/src/components/Alert/Alert.tsx +19 -11
- package/src/components/Badge/Badge.tsx +1 -1
- package/src/components/Calendar/Calendar.tsx +201 -47
- package/src/components/Checkbox/Checkbox.test.tsx +2 -1
- package/src/components/ContextSelector/ContextSelector.tsx +108 -126
- package/src/components/DataTable/AUDIT_REPORT.md +293 -0
- package/src/components/DataTable/DataTable.tsx +1 -19
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +6 -2
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +21 -6
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +3 -2
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
- package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
- package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
- package/src/components/DataTable/components/EditableRow.tsx +5 -7
- package/src/components/DataTable/components/EmptyState.tsx +11 -10
- package/src/components/DataTable/components/FilterRow.tsx +2 -4
- package/src/components/DataTable/components/ImportModal.tsx +124 -126
- package/src/components/DataTable/components/LoadingState.tsx +5 -6
- package/src/components/DataTable/components/SortIndicator.tsx +50 -0
- package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
- package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +45 -27
- package/src/components/DataTable/components/index.ts +2 -1
- package/src/components/DataTable/types.ts +0 -18
- package/src/components/DataTable/utils/a11yUtils.ts +17 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +1 -1
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
- package/src/components/DateTimeField/DateTimeField.tsx +7 -8
- package/src/components/Dialog/Dialog.test.tsx +1 -0
- package/src/components/Dialog/Dialog.tsx +25 -8
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
- package/src/components/FileUpload/FileUpload.test.tsx +45 -16
- package/src/components/FileUpload/FileUpload.tsx +141 -130
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +48 -12
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +9 -9
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +30 -30
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +4 -4
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +7 -1
- package/src/components/Progress/Progress.tsx +2 -4
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
- package/src/components/Select/Select.tsx +86 -77
- package/src/components/Select/types.ts +3 -0
- package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
- package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
- package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +8 -5
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +4 -0
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +99 -99
- package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +45 -8
- package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +22 -2
- package/src/hooks/public/usePublicEvent.ts +5 -5
- package/src/hooks/public/usePublicEventLogo.ts +5 -5
- package/src/hooks/public/usePublicFileDisplay.ts +2 -2
- package/src/hooks/public/usePublicRouteParams.ts +13 -9
- package/src/hooks/useAddressAutocomplete.test.ts +18 -18
- package/src/hooks/useAppConfig.ts +2 -2
- package/src/hooks/useEventTheme.test.ts +7 -7
- package/src/hooks/useEventTheme.ts +2 -1
- package/src/hooks/useFileDisplay.ts +2 -2
- package/src/hooks/useFileUrl.ts +52 -8
- package/src/hooks/useOrganisationSecurity.test.ts +2 -1
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
- package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
- package/src/providers/__tests__/EventProvider.test.tsx +61 -61
- package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
- package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +38 -38
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +15 -6
- package/src/rbac/__tests__/rbac-functions.test.ts +3 -3
- package/src/rbac/api.test.ts +104 -0
- package/src/rbac/engine.ts +1 -1
- package/src/rbac/hooks/useCan.test.ts +2 -2
- package/src/rbac/secureClient.ts +1 -1
- package/src/rbac/types/functions.ts +1 -1
- package/src/styles/core.css +7 -0
- package/src/theming/__tests__/parseEventColours.test.ts +118 -3
- package/src/theming/parseEventColours.ts +77 -11
- package/src/types/supabase.ts +2 -3
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +9 -9
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
- package/src/utils/file-reference/__tests__/file-reference.test.ts +4 -0
- package/src/utils/formatting/formatDate.test.ts +3 -2
- package/src/utils/formatting/formatDateTime.test.ts +2 -2
- package/src/utils/google-places/googlePlacesUtils.test.ts +36 -24
- package/src/utils/storage/README.md +1 -1
- package/src/utils/storage/__tests__/helpers.unit.test.ts +19 -12
- package/src/utils/storage/helpers.test.ts +69 -3
- package/cursor-rules/01-standards-compliance.mdc +0 -285
- package/cursor-rules/04-testing-standards.mdc +0 -270
- package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
- package/cursor-rules/06-code-quality.mdc +0 -311
- package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
- package/cursor-rules/10-error-handling-patterns.mdc +0 -179
- package/cursor-rules/11-performance-optimization.mdc +0 -169
- package/cursor-rules/12-ci-cd-integration.mdc +0 -150
- package/dist/DataTable-LRJL4IRV.js +0 -15
- package/dist/eslint-rules/rules/compliance.cjs +0 -348
- package/dist/eslint-rules/rules/components.cjs +0 -113
- package/dist/eslint-rules/rules/imports.cjs +0 -102
- package/docs/best-practices/README.md +0 -472
- package/docs/best-practices/accessibility.md +0 -604
- package/docs/best-practices/common-patterns.md +0 -516
- package/docs/best-practices/deployment.md +0 -1103
- package/docs/best-practices/performance.md +0 -1328
- package/docs/best-practices/security.md +0 -940
- package/docs/best-practices/testing.md +0 -1034
- package/docs/rbac/compliance/compliance-guide.md +0 -544
- package/docs/standards/01-standards-compliance.md +0 -188
- package/docs/standards/03-solid-principles.md +0 -39
- package/docs/standards/04-testing-standards.md +0 -36
- package/docs/standards/05-bug-reports-and-features.md +0 -27
- package/docs/standards/06-code-quality.md +0 -34
- package/docs/standards/07-tech-stack-compliance.md +0 -30
- package/docs/standards/10-error-handling-patterns.md +0 -401
- package/docs/standards/11-performance-optimization.md +0 -348
- package/docs/standards/12-ci-cd-integration.md +0 -370
- package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
- package/scripts/audit/audit-compliance.cjs +0 -1295
- package/scripts/audit/audit-components.cjs +0 -260
- package/scripts/audit/audit-rbac.cjs +0 -954
- package/scripts/audit/audit-standards.cjs +0 -1268
- package/scripts/audit/index.cjs +0 -1927
- package/src/components/DataTable/components/DataTableBody.tsx +0 -478
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
- package/src/components/DataTable/components/ExpandButton.tsx +0 -113
- package/src/components/DataTable/components/GroupHeader.tsx +0 -54
- package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
- package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
- package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
- package/src/components/DataTable/core/DataTableContext.tsx +0 -216
- package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
- package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
- package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
- package/src/components/DataTable/utils/debugTools.ts +0 -514
- package/src/eslint-rules/index.cjs +0 -22
- package/src/eslint-rules/rules/components.cjs +0 -113
- package/src/eslint-rules/rules/imports.cjs +0 -102
- package/src/eslint-rules/rules/rbac.cjs +0 -790
- package/src/eslint-rules/utils/helpers.cjs +0 -42
- package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
|
@@ -112,20 +112,20 @@ const columns: DataTableColumn<Dish>[] = [
|
|
|
112
112
|
header: 'Name',
|
|
113
113
|
// Different rendering for parent vs child rows
|
|
114
114
|
renderForParent: (row) => (
|
|
115
|
-
<
|
|
115
|
+
<section className="flex items-center gap-2">
|
|
116
116
|
<span className="font-semibold text-main-800">{row.name}</span>
|
|
117
117
|
<span className="text-xs bg-main-100 text-main-700 px-2 py-1 rounded">
|
|
118
118
|
{row.type}
|
|
119
119
|
</span>
|
|
120
|
-
</
|
|
120
|
+
</section>
|
|
121
121
|
),
|
|
122
122
|
renderForChild: (row) => (
|
|
123
|
-
<
|
|
123
|
+
<section className="flex items-center gap-2 ml-4">
|
|
124
124
|
<span className="text-sec-700">{row.name}</span>
|
|
125
125
|
<span className="text-xs bg-sec-100 text-sec-600 px-2 py-1 rounded">
|
|
126
126
|
{row.type}
|
|
127
127
|
</span>
|
|
128
|
-
</
|
|
128
|
+
</section>
|
|
129
129
|
),
|
|
130
130
|
},
|
|
131
131
|
{
|
|
@@ -133,14 +133,14 @@ const columns: DataTableColumn<Dish>[] = [
|
|
|
133
133
|
accessorKey: 'cost',
|
|
134
134
|
header: 'Cost',
|
|
135
135
|
renderForParent: (row) => (
|
|
136
|
-
<
|
|
136
|
+
<p className="text-right font-semibold text-main-800">
|
|
137
137
|
${row.cost?.toFixed(2)}
|
|
138
|
-
</
|
|
138
|
+
</p>
|
|
139
139
|
),
|
|
140
140
|
renderForChild: (row) => (
|
|
141
|
-
<
|
|
141
|
+
<p className="text-right text-sec-600 ml-4">
|
|
142
142
|
${row.cost?.toFixed(2)}
|
|
143
|
-
</
|
|
143
|
+
</p>
|
|
144
144
|
),
|
|
145
145
|
},
|
|
146
146
|
{
|
|
@@ -150,10 +150,10 @@ const columns: DataTableColumn<Dish>[] = [
|
|
|
150
150
|
// Only show for child rows
|
|
151
151
|
renderForParent: () => null,
|
|
152
152
|
renderForChild: (row) => (
|
|
153
|
-
<
|
|
153
|
+
<p className="text-sm ml-4">
|
|
154
154
|
<span className="font-medium">{row.quantity}</span>
|
|
155
155
|
{row.unit && <span className="text-sec-500 ml-1">{row.unit}</span>}
|
|
156
|
-
</
|
|
156
|
+
</p>
|
|
157
157
|
),
|
|
158
158
|
hideForParent: true, // Hide this column for parent rows
|
|
159
159
|
}
|
|
@@ -193,7 +193,7 @@ hierarchical={{
|
|
|
193
193
|
onExpandedChange: (expandedIds) => {
|
|
194
194
|
console.log('Expanded rows:', expandedIds);
|
|
195
195
|
},
|
|
196
|
-
|
|
196
|
+
// Note: Custom expand button functionality has been removed. Expand/collapse is handled inline by RowComponent.
|
|
197
197
|
indentSize: 24, // Indentation for child rows in pixels
|
|
198
198
|
parentRowClassName: 'bg-main-50 font-medium', // CSS classes for parent rows
|
|
199
199
|
childRowClassName: 'bg-sec-25', // CSS classes for child rows
|
|
@@ -207,7 +207,7 @@ hierarchical={{
|
|
|
207
207
|
| `enabled` | `boolean` | `false` | Enable/disable hierarchical functionality |
|
|
208
208
|
| `defaultExpanded` | `boolean \| string[]` | `false` | Initial expansion state |
|
|
209
209
|
| `onExpandedChange` | `(expandedIds: string[]) => void` | `undefined` | Callback when expansion changes |
|
|
210
|
-
| `expandButton` |
|
|
210
|
+
| `expandButton` | ~~`React.ComponentType`~~ | ~~`ExpandButton`~~ | ~~Custom expand/collapse button~~ **DEPRECATED - Removed** |
|
|
211
211
|
| `indentSize` | `number` | `24` | Indentation for child rows in pixels |
|
|
212
212
|
| `parentRowClassName` | `string` | `''` | CSS classes for parent rows |
|
|
213
213
|
| `childRowClassName` | `string` | `''` | CSS classes for child rows |
|
|
@@ -240,16 +240,16 @@ const column: DataTableColumn<YourType> = {
|
|
|
240
240
|
id: 'actions',
|
|
241
241
|
header: 'Actions',
|
|
242
242
|
renderForParent: (row) => (
|
|
243
|
-
<
|
|
243
|
+
<section className="flex gap-2">
|
|
244
244
|
<Button size="sm">Edit Recipe</Button>
|
|
245
245
|
<Button size="sm" variant="outline">Add Ingredient</Button>
|
|
246
|
-
</
|
|
246
|
+
</section>
|
|
247
247
|
),
|
|
248
248
|
renderForChild: (row) => (
|
|
249
|
-
<
|
|
249
|
+
<section className="flex gap-2">
|
|
250
250
|
<Button size="sm" variant="ghost">Edit</Button>
|
|
251
251
|
<Button size="sm" variant="destructive">Remove</Button>
|
|
252
|
-
</
|
|
252
|
+
</section>
|
|
253
253
|
),
|
|
254
254
|
}
|
|
255
255
|
```
|
|
@@ -277,29 +277,9 @@ The DataTable automatically adds an expand/collapse all button in the header whe
|
|
|
277
277
|
You can provide a custom expand button component:
|
|
278
278
|
|
|
279
279
|
```tsx
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
<button
|
|
284
|
-
onClick={onClick}
|
|
285
|
-
className="p-1 hover:bg-sec-100 rounded"
|
|
286
|
-
{...props}
|
|
287
|
-
>
|
|
288
|
-
{isExpanded ? (
|
|
289
|
-
<ChevronDown className="h-4 w-4" />
|
|
290
|
-
) : (
|
|
291
|
-
<ChevronRight className="h-4 w-4" />
|
|
292
|
-
)}
|
|
293
|
-
</button>
|
|
294
|
-
);
|
|
295
|
-
|
|
296
|
-
// Use in DataTable
|
|
297
|
-
<DataTable
|
|
298
|
-
hierarchical={{
|
|
299
|
-
enabled: true,
|
|
300
|
-
expandButton: CustomExpandButton,
|
|
301
|
-
}}
|
|
302
|
-
/>
|
|
280
|
+
// Note: Custom expand button functionality has been removed.
|
|
281
|
+
// Expand/collapse buttons are now handled inline by RowComponent.
|
|
282
|
+
// The expandButton prop is no longer available in HierarchicalConfig.
|
|
303
283
|
```
|
|
304
284
|
|
|
305
285
|
## Hierarchical Actions
|
|
@@ -510,20 +490,20 @@ function HierarchicalDishTable() {
|
|
|
510
490
|
enableSorting: true,
|
|
511
491
|
size: 200,
|
|
512
492
|
renderForParent: (row) => (
|
|
513
|
-
<
|
|
493
|
+
<section className="flex items-center gap-2">
|
|
514
494
|
<span className="font-semibold text-main-800">{row.name}</span>
|
|
515
495
|
<span className="text-xs bg-main-100 text-main-700 px-2 py-1 rounded">
|
|
516
496
|
{row.type}
|
|
517
497
|
</span>
|
|
518
|
-
</
|
|
498
|
+
</section>
|
|
519
499
|
),
|
|
520
500
|
renderForChild: (row) => (
|
|
521
|
-
<
|
|
501
|
+
<section className="flex items-center gap-2 ml-4">
|
|
522
502
|
<span className="text-sec-700">{row.name}</span>
|
|
523
503
|
<span className="text-xs bg-sec-100 text-sec-600 px-2 py-1 rounded">
|
|
524
504
|
{row.type}
|
|
525
505
|
</span>
|
|
526
|
-
</
|
|
506
|
+
</section>
|
|
527
507
|
),
|
|
528
508
|
},
|
|
529
509
|
{
|
|
@@ -533,14 +513,14 @@ function HierarchicalDishTable() {
|
|
|
533
513
|
enableSorting: true,
|
|
534
514
|
size: 250,
|
|
535
515
|
renderForParent: (row) => (
|
|
536
|
-
<
|
|
516
|
+
<p className="text-sm text-sec-600">
|
|
537
517
|
{row.description}
|
|
538
|
-
</
|
|
518
|
+
</p>
|
|
539
519
|
),
|
|
540
520
|
renderForChild: (row) => (
|
|
541
|
-
<
|
|
521
|
+
<p className="text-sm text-sec-500 ml-4">
|
|
542
522
|
{row.description}
|
|
543
|
-
</
|
|
523
|
+
</p>
|
|
544
524
|
),
|
|
545
525
|
},
|
|
546
526
|
{
|
|
@@ -551,10 +531,10 @@ function HierarchicalDishTable() {
|
|
|
551
531
|
size: 120,
|
|
552
532
|
renderForParent: () => null,
|
|
553
533
|
renderForChild: (row) => (
|
|
554
|
-
<
|
|
534
|
+
<p className="text-sm ml-4">
|
|
555
535
|
<span className="font-medium">{row.quantity}</span>
|
|
556
536
|
{row.unit && <span className="text-sec-500 ml-1">{row.unit}</span>}
|
|
557
|
-
</
|
|
537
|
+
</p>
|
|
558
538
|
),
|
|
559
539
|
hideForParent: true,
|
|
560
540
|
},
|
|
@@ -565,14 +545,14 @@ function HierarchicalDishTable() {
|
|
|
565
545
|
enableSorting: true,
|
|
566
546
|
size: 100,
|
|
567
547
|
renderForParent: (row) => (
|
|
568
|
-
<
|
|
548
|
+
<p className="text-right font-semibold text-main-800">
|
|
569
549
|
${row.cost?.toFixed(2)}
|
|
570
|
-
</
|
|
550
|
+
</p>
|
|
571
551
|
),
|
|
572
552
|
renderForChild: (row) => (
|
|
573
|
-
<
|
|
553
|
+
<p className="text-right text-sec-600 ml-4">
|
|
574
554
|
${row.cost?.toFixed(2)}
|
|
575
|
-
</
|
|
555
|
+
</p>
|
|
576
556
|
),
|
|
577
557
|
},
|
|
578
558
|
{
|
|
@@ -583,9 +563,9 @@ function HierarchicalDishTable() {
|
|
|
583
563
|
size: 150,
|
|
584
564
|
renderForParent: () => null,
|
|
585
565
|
renderForChild: (row) => (
|
|
586
|
-
<
|
|
566
|
+
<p className="text-sm text-sec-600 ml-4">
|
|
587
567
|
{row.supplier}
|
|
588
|
-
</
|
|
568
|
+
</p>
|
|
589
569
|
),
|
|
590
570
|
hideForParent: true,
|
|
591
571
|
},
|
|
@@ -596,11 +576,11 @@ function HierarchicalDishTable() {
|
|
|
596
576
|
enableSorting: true,
|
|
597
577
|
size: 100,
|
|
598
578
|
renderForParent: (row) => (
|
|
599
|
-
<
|
|
579
|
+
<section className="text-center">
|
|
600
580
|
<span className="inline-flex items-center px-2 py-1 rounded text-xs font-medium bg-sec-100 text-sec-800">
|
|
601
581
|
{row.prepTime} min
|
|
602
582
|
</span>
|
|
603
|
-
</
|
|
583
|
+
</section>
|
|
604
584
|
),
|
|
605
585
|
renderForChild: () => null,
|
|
606
586
|
hideForChild: true,
|
|
@@ -618,11 +598,11 @@ function HierarchicalDishTable() {
|
|
|
618
598
|
Hard: 'bg-acc-100 text-acc-800'
|
|
619
599
|
};
|
|
620
600
|
return (
|
|
621
|
-
<
|
|
601
|
+
<section className="text-center">
|
|
622
602
|
<span className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${colors[row.difficulty as keyof typeof colors] || 'bg-sec-100 text-sec-800'}`}>
|
|
623
603
|
{row.difficulty}
|
|
624
604
|
</span>
|
|
625
|
-
</
|
|
605
|
+
</section>
|
|
626
606
|
);
|
|
627
607
|
},
|
|
628
608
|
renderForChild: () => null,
|
|
@@ -812,7 +792,7 @@ interface HierarchicalConfig {
|
|
|
812
792
|
enabled: boolean;
|
|
813
793
|
defaultExpanded?: boolean | string[];
|
|
814
794
|
onExpandedChange?: (expandedIds: string[]) => void;
|
|
815
|
-
expandButton
|
|
795
|
+
// expandButton prop has been removed - expand/collapse is handled inline by RowComponent
|
|
816
796
|
indentSize?: number;
|
|
817
797
|
parentRowClassName?: string;
|
|
818
798
|
childRowClassName?: string;
|
|
@@ -449,7 +449,7 @@ function AuthenticatedApp() {
|
|
|
449
449
|
|
|
450
450
|
// Don't track inactivity if not authenticated
|
|
451
451
|
if (loading || !user) {
|
|
452
|
-
return <
|
|
452
|
+
return <p>Loading...</p>;
|
|
453
453
|
}
|
|
454
454
|
|
|
455
455
|
return (
|
|
@@ -831,5 +831,5 @@ When user extends session during warning:
|
|
|
831
831
|
|
|
832
832
|
- **[Authentication Integration](./permission-enforcement.md)** - Security patterns
|
|
833
833
|
- **[Performance Optimization](./performance.md)** - Large application considerations
|
|
834
|
-
- **[Accessibility
|
|
835
|
-
- **[Security
|
|
834
|
+
- **[Accessibility Requirements](../standards/4-code-quality-standards.md#accessibility-requirements)** - Accessibility requirements
|
|
835
|
+
- **[Security & RBAC Standards](../standards/6-security-rbac-standards.md)** - Security considerations
|
|
@@ -10,11 +10,12 @@ This guide addresses the common issues when working with large datasets (9,000+
|
|
|
10
10
|
|
|
11
11
|
**Problem**: Header and body columns were misaligned in virtualized mode due to separate table layouts.
|
|
12
12
|
|
|
13
|
-
**Solution**:
|
|
13
|
+
**Solution**: `UnifiedTableBody` component automatically handles virtualization with:
|
|
14
14
|
- Synchronized column sizing between header and body tables
|
|
15
15
|
- `table-fixed` layout for consistent column widths
|
|
16
16
|
- Dynamic column width calculation and synchronization
|
|
17
|
-
-
|
|
17
|
+
- Automatic virtualization when data exceeds 1000 records
|
|
18
|
+
- Proper virtualization handling for optimal performance
|
|
18
19
|
|
|
19
20
|
```tsx
|
|
20
21
|
// ✅ Now properly aligned
|
|
@@ -819,5 +819,5 @@ When invalid organisation IDs are provided:
|
|
|
819
819
|
|
|
820
820
|
- **[RBAC System](../rbac/README.md)** - Role-based access control
|
|
821
821
|
- **[Permission Enforcement](./permission-enforcement.md)** - UI permission patterns
|
|
822
|
-
- **[Security
|
|
823
|
-
- **[
|
|
822
|
+
- **[Security & RBAC Standards](../standards/6-security-rbac-standards.md)** - Security guidelines
|
|
823
|
+
- **[Operations Standards](../standards/9-operations-standards.md)** - Error handling and monitoring
|
|
@@ -299,9 +299,9 @@ EnhancedDataTable
|
|
|
299
299
|
│ ├── SearchIndex
|
|
300
300
|
│ ├── PerformanceMonitor
|
|
301
301
|
│ └── VisibilityTracker
|
|
302
|
-
├──
|
|
302
|
+
├── UnifiedTableBody (with automatic virtualization)
|
|
303
303
|
│ ├── MemoizedRow
|
|
304
|
-
│ └──
|
|
304
|
+
│ └── Virtualized rows (when data > 1000 records)
|
|
305
305
|
└── EnhancedPaginationControls
|
|
306
306
|
├── Performance metrics display
|
|
307
307
|
├── Jump to page functionality
|
|
@@ -701,7 +701,7 @@ useEffect(() => {
|
|
|
701
701
|
```tsx
|
|
702
702
|
const { selectedOrganisationId } = useUnifiedAuth();
|
|
703
703
|
if (!selectedOrganisationId) {
|
|
704
|
-
return <
|
|
704
|
+
return <p>Please select an organisation first</p>;
|
|
705
705
|
}
|
|
706
706
|
```
|
|
707
707
|
|
|
@@ -60,7 +60,7 @@ function OrganisationContextGuard({ children }) {
|
|
|
60
60
|
}, [selectedOrganisation, supabase]);
|
|
61
61
|
|
|
62
62
|
if (!contextReady) {
|
|
63
|
-
return <
|
|
63
|
+
return <p>Setting up organisation context...</p>;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
return <>{children}</>;
|
|
@@ -239,7 +239,7 @@ function UserActions() {
|
|
|
239
239
|
'delete:users'
|
|
240
240
|
);
|
|
241
241
|
|
|
242
|
-
if (isLoadingEdit || isLoadingDelete) return <
|
|
242
|
+
if (isLoadingEdit || isLoadingDelete) return <p>Loading permissions...</p>;
|
|
243
243
|
|
|
244
244
|
return (
|
|
245
245
|
<div>
|
|
@@ -375,7 +375,7 @@ const { can: canEdit, isLoading } = useCan(
|
|
|
375
375
|
'update:users'
|
|
376
376
|
);
|
|
377
377
|
|
|
378
|
-
if (isLoading) return <
|
|
378
|
+
if (isLoading) return <p>Loading...</p>;
|
|
379
379
|
return canEdit ? <EditButton /> : null;
|
|
380
380
|
```
|
|
381
381
|
|
|
@@ -406,7 +406,7 @@ const canCreate = hasPermission('create:users');
|
|
|
406
406
|
const canUpdate = hasPermission('update:users');
|
|
407
407
|
const canDelete = hasPermission('delete:users');
|
|
408
408
|
|
|
409
|
-
if (isLoading) return <
|
|
409
|
+
if (isLoading) return <p>Loading permissions...</p>;
|
|
410
410
|
```
|
|
411
411
|
|
|
412
412
|
### Pattern 3: Component Guards
|
|
@@ -504,8 +504,8 @@ function UserActions({ userId, scope }) {
|
|
|
504
504
|
checkPermission();
|
|
505
505
|
}, [hasPermission, isLoading, userId, scope]);
|
|
506
506
|
|
|
507
|
-
if (error) return <
|
|
508
|
-
if (isLoading) return <
|
|
507
|
+
if (error) return <p>Error checking permissions</p>;
|
|
508
|
+
if (isLoading) return <p>Loading...</p>;
|
|
509
509
|
|
|
510
510
|
return (
|
|
511
511
|
<div>
|
|
@@ -595,7 +595,7 @@ const canEdit = await hasPermission('update:users', { userId, scope });
|
|
|
595
595
|
```tsx
|
|
596
596
|
const { hasPermission, isLoading } = useCan();
|
|
597
597
|
|
|
598
|
-
if (isLoading) return <
|
|
598
|
+
if (isLoading) return <p>Loading permissions...</p>;
|
|
599
599
|
```
|
|
600
600
|
|
|
601
601
|
### Getting Help
|
package/docs/rbac/README.md
CHANGED
|
@@ -56,7 +56,7 @@ function MyComponent() {
|
|
|
56
56
|
<PagePermissionGuard
|
|
57
57
|
pageName="users"
|
|
58
58
|
operation="read"
|
|
59
|
-
fallback={<
|
|
59
|
+
fallback={<p>Access Denied</p>}
|
|
60
60
|
>
|
|
61
61
|
<UserList />
|
|
62
62
|
</PagePermissionGuard>
|
|
@@ -232,9 +232,9 @@ function UsersPage() {
|
|
|
232
232
|
<PagePermissionGuard
|
|
233
233
|
pageName="users"
|
|
234
234
|
operation="read"
|
|
235
|
-
fallback={<
|
|
235
|
+
fallback={<p>You don't have permission to view this page</p>}
|
|
236
236
|
>
|
|
237
|
-
<
|
|
237
|
+
<section>
|
|
238
238
|
<h1>User Management</h1>
|
|
239
239
|
|
|
240
240
|
{/* Multiple operations on same page */}
|
|
@@ -261,7 +261,7 @@ function UsersPage() {
|
|
|
261
261
|
>
|
|
262
262
|
<DeleteUserButtons />
|
|
263
263
|
</PagePermissionGuard>
|
|
264
|
-
</
|
|
264
|
+
</section>
|
|
265
265
|
</PagePermissionGuard>
|
|
266
266
|
);
|
|
267
267
|
}
|
|
@@ -282,7 +282,7 @@ function AdminPanel() {
|
|
|
282
282
|
<PagePermissionGuard
|
|
283
283
|
pageName="admin"
|
|
284
284
|
operation="read"
|
|
285
|
-
fallback={<
|
|
285
|
+
fallback={<p>Access denied</p>}
|
|
286
286
|
>
|
|
287
287
|
<UserManagement />
|
|
288
288
|
</PagePermissionGuard>
|
|
@@ -379,7 +379,7 @@ export function withPermission(permission: string, fallback?: React.ComponentTyp
|
|
|
379
379
|
|
|
380
380
|
// Usage
|
|
381
381
|
const ProtectedUserList = withPermission('read:users', () => (
|
|
382
|
-
<
|
|
382
|
+
<p>Access denied to user list</p>
|
|
383
383
|
))(UserList);
|
|
384
384
|
|
|
385
385
|
// In component
|
|
@@ -436,16 +436,16 @@ export const useOrganisationPermissions = createPermissionHook('organisations');
|
|
|
436
436
|
function UserManagement({ userId, scope }) {
|
|
437
437
|
const { permissions, isLoading } = useUserPermissions(userId, scope);
|
|
438
438
|
|
|
439
|
-
if (isLoading) return <
|
|
439
|
+
if (isLoading) return <p>Loading permissions...</p>;
|
|
440
440
|
|
|
441
441
|
return (
|
|
442
|
-
<
|
|
442
|
+
<section>
|
|
443
443
|
{permissions.read && <UserList />}
|
|
444
444
|
{permissions.create && <CreateUserButton />}
|
|
445
445
|
{permissions.update && <EditUserButton />}
|
|
446
446
|
{permissions.delete && <DeleteUserButton />}
|
|
447
447
|
{permissions.manage && <UserManagementPanel />}
|
|
448
|
-
</
|
|
448
|
+
</section>
|
|
449
449
|
);
|
|
450
450
|
}
|
|
451
451
|
```
|
|
@@ -647,7 +647,7 @@ import { withPermission } from './permission-decorators';
|
|
|
647
647
|
|
|
648
648
|
// Mock component
|
|
649
649
|
const TestComponent = ({ data }: { data: string }) => (
|
|
650
|
-
<
|
|
650
|
+
<p>Test Component: {data}</p>
|
|
651
651
|
);
|
|
652
652
|
|
|
653
653
|
describe('Permission Decorators', () => {
|
|
@@ -684,7 +684,7 @@ describe('Permission Decorators', () => {
|
|
|
684
684
|
})
|
|
685
685
|
}));
|
|
686
686
|
|
|
687
|
-
const FallbackComponent = () => <
|
|
687
|
+
const FallbackComponent = () => <p>Access Denied</p>;
|
|
688
688
|
const ProtectedComponent = withPermission('read:users', FallbackComponent)(TestComponent);
|
|
689
689
|
|
|
690
690
|
render(
|
|
@@ -44,13 +44,13 @@ function UserActions() {
|
|
|
44
44
|
undefined // No pageId for event-app permissions
|
|
45
45
|
);
|
|
46
46
|
|
|
47
|
-
if (error) return <
|
|
48
|
-
if (isLoading) return <
|
|
47
|
+
if (error) return <p>Error: {error.message}</p>;
|
|
48
|
+
if (isLoading) return <p>Checking permissions...</p>;
|
|
49
49
|
|
|
50
50
|
return (
|
|
51
|
-
<
|
|
51
|
+
<section>
|
|
52
52
|
{can && <EventActions />}
|
|
53
|
-
</
|
|
53
|
+
</section>
|
|
54
54
|
);
|
|
55
55
|
}
|
|
56
56
|
```
|
|
@@ -87,19 +87,19 @@ function PermissionDisplay() {
|
|
|
87
87
|
}
|
|
88
88
|
);
|
|
89
89
|
|
|
90
|
-
if (isLoading) return <
|
|
91
|
-
if (error) return <
|
|
90
|
+
if (isLoading) return <p>Loading permissions...</p>;
|
|
91
|
+
if (error) return <p>Error: {error.message}</p>;
|
|
92
92
|
|
|
93
93
|
return (
|
|
94
|
-
<
|
|
94
|
+
<section>
|
|
95
95
|
<h3>User Permissions</h3>
|
|
96
96
|
{Object.entries(permissions).map(([pageId, operations]) => (
|
|
97
|
-
<
|
|
97
|
+
<p key={pageId}>
|
|
98
98
|
<strong>{pageId}:</strong> {operations.join(', ')}
|
|
99
|
-
</
|
|
99
|
+
</p>
|
|
100
100
|
))}
|
|
101
101
|
<button onClick={refetch}>Refresh</button>
|
|
102
|
-
</
|
|
102
|
+
</section>
|
|
103
103
|
);
|
|
104
104
|
}
|
|
105
105
|
```
|
|
@@ -128,13 +128,13 @@ function AccessLevelDisplay({ userId, scope }) {
|
|
|
128
128
|
scope
|
|
129
129
|
});
|
|
130
130
|
|
|
131
|
-
if (isLoading) return <
|
|
132
|
-
if (error) return <
|
|
131
|
+
if (isLoading) return <p>Loading access level...</p>;
|
|
132
|
+
if (error) return <p>Error: {error.message}</p>;
|
|
133
133
|
|
|
134
134
|
return (
|
|
135
|
-
<
|
|
135
|
+
<section>
|
|
136
136
|
<p>Access Level: {accessLevel || 'None'}</p>
|
|
137
|
-
</
|
|
137
|
+
</section>
|
|
138
138
|
);
|
|
139
139
|
}
|
|
140
140
|
```
|
|
@@ -183,12 +183,12 @@ function UserManagement({ userId, scope }) {
|
|
|
183
183
|
}, [checkMultiple, isLoading, userId, scope]);
|
|
184
184
|
|
|
185
185
|
return (
|
|
186
|
-
<
|
|
186
|
+
<section>
|
|
187
187
|
{permissions['read:users'] && <UserList />}
|
|
188
188
|
{permissions['create:users'] && <CreateUserButton />}
|
|
189
189
|
{permissions['update:users'] && <EditUserButton />}
|
|
190
190
|
{permissions['delete:users'] && <DeleteUserButton />}
|
|
191
|
-
</
|
|
191
|
+
</section>
|
|
192
192
|
);
|
|
193
193
|
}
|
|
194
194
|
```
|
|
@@ -221,12 +221,12 @@ import { PermissionEnforcer } from '@jmruthers/pace-core/rbac';
|
|
|
221
221
|
|
|
222
222
|
function UserActions() {
|
|
223
223
|
return (
|
|
224
|
-
<
|
|
224
|
+
<section>
|
|
225
225
|
{/* Pattern 1: PermissionEnforcer - automatic scope resolution */}
|
|
226
226
|
<PermissionEnforcer
|
|
227
227
|
permissions={['read:users']}
|
|
228
228
|
operation="user-management"
|
|
229
|
-
fallback={<
|
|
229
|
+
fallback={<p>Access Denied</p>}
|
|
230
230
|
>
|
|
231
231
|
<UserList />
|
|
232
232
|
</PermissionEnforcer>
|
|
@@ -236,11 +236,11 @@ function UserActions() {
|
|
|
236
236
|
permissions={['create:users', 'update:users']}
|
|
237
237
|
operation="user-crud"
|
|
238
238
|
requireAll={true} // User needs ALL permissions
|
|
239
|
-
fallback={<
|
|
239
|
+
fallback={<p>You need create and update permissions</p>}
|
|
240
240
|
>
|
|
241
241
|
<UserManagementPanel />
|
|
242
242
|
</PermissionEnforcer>
|
|
243
|
-
</
|
|
243
|
+
</section>
|
|
244
244
|
);
|
|
245
245
|
}
|
|
246
246
|
```
|
|
@@ -491,7 +491,7 @@ export function Dashboard() {
|
|
|
491
491
|
const { user, selectedEventId, selectedOrganisationId } = useUnifiedAuth()
|
|
492
492
|
|
|
493
493
|
if (!user) {
|
|
494
|
-
return <
|
|
494
|
+
return <p>Please log in</p>
|
|
495
495
|
}
|
|
496
496
|
|
|
497
497
|
return (
|
|
@@ -580,7 +580,7 @@ export function Participants() {
|
|
|
580
580
|
const { user, selectedEventId, selectedOrganisationId } = useUnifiedAuth()
|
|
581
581
|
|
|
582
582
|
if (!user) {
|
|
583
|
-
return <
|
|
583
|
+
return <p>Please log in</p>
|
|
584
584
|
}
|
|
585
585
|
|
|
586
586
|
return (
|
|
@@ -748,7 +748,7 @@ setupRBAC(supabase) // Must be called BEFORE rendering app
|
|
|
748
748
|
setSelectedEventId('your-event-id');
|
|
749
749
|
}, []);
|
|
750
750
|
|
|
751
|
-
return <
|
|
751
|
+
return <p>...</p>;
|
|
752
752
|
}
|
|
753
753
|
```
|
|
754
754
|
|