robobyte-front-builder 1.0.24 → 1.0.26
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/INTEGRATION.md +94 -10
- package/README.md +92 -21
- package/package.json +1 -1
- package/src/lib/agGridTheme.js +58 -0
- package/src/lib/agGridThemeContext.jsx +42 -0
- package/src/lib/index.js +7 -0
- package/src/lib/providers/RoboByteFrontBuilderProvider.jsx +14 -0
- package/src/pages/reportModule/reportBuilder/reportViewer/index.js +134 -2
- package/src/views/builder/inspector/definitions/reportViewer/main.js +5 -0
- package/src/views/builder/viewer/renderers/DataGridRenderer.jsx +4 -4
- package/src/views/genericTable/SGrid.js +5 -5
- package/src/views/genericTable/TAGGrid.js +3 -5
- package/src/views/rolePermissions/UpdateReportPermissionDialog.js +4 -0
package/INTEGRATION.md
CHANGED
|
@@ -173,6 +173,9 @@ function RoboByteBridge({ children }) {
|
|
|
173
173
|
user={auth.user}
|
|
174
174
|
accessToken={auth.accessToken}
|
|
175
175
|
agGridLicenseKey={process.env.NEXT_PUBLIC_AG_GRID_LICENSE_KEY}
|
|
176
|
+
// Optional — Quartz theme overrides for every <AgGridReact> in the
|
|
177
|
+
// package. Merged on top of the package defaults.
|
|
178
|
+
// agGridTheme={{ accentColor: '#3b82f6', headerHeight: 32 }}
|
|
176
179
|
>
|
|
177
180
|
{children}
|
|
178
181
|
</RoboByteFrontBuilderProvider>
|
|
@@ -200,11 +203,15 @@ export default function App({ Component, pageProps }) {
|
|
|
200
203
|
| `user` | object | Current user object from your auth context |
|
|
201
204
|
| `accessToken` | string | Bearer token — attached to every robobyte service call |
|
|
202
205
|
| `agGridLicenseKey` | string | AG Grid Enterprise license key. The provider calls `LicenseManager.setLicenseKey()` and registers `AllEnterpriseModule` + `IntegratedChartsModule.with(AgChartsEnterpriseModule)` internally. |
|
|
206
|
+
| `agGridTheme` | object | Optional. Quartz theme overrides applied to every `<AgGridReact>` in the package. Merged on top of `DEFAULT_AG_THEME_PARAMS` (see [`src/lib/agGridTheme.js`](src/lib/agGridTheme.js)). Example: `{ accentColor: '#3b82f6', headerHeight: 32 }`. |
|
|
203
207
|
| `navExtensions` | array | Static nav items to inject into the sidebar (optional) |
|
|
204
208
|
| `endpoints` | object | Full-URL overrides per endpoint group + name (optional) |
|
|
205
209
|
|
|
206
210
|
> **AG Grid note:** Do not call `LicenseManager` or `ModuleRegistry` in the
|
|
207
|
-
> host app — the provider handles it entirely via `agGridLicenseKey`.
|
|
211
|
+
> host app — the provider handles it entirely via `agGridLicenseKey`. The
|
|
212
|
+
> theme is also handled internally — do not pass `theme={...}` to
|
|
213
|
+
> individual `<AgGridReact>` instances rendered by the package; the
|
|
214
|
+
> `agGridTheme` prop is the single source of truth.
|
|
208
215
|
|
|
209
216
|
---
|
|
210
217
|
|
|
@@ -308,17 +315,35 @@ Paths to stub out:
|
|
|
308
315
|
Fetches report data by `pageId` without any AG Grid dependency. The canonical
|
|
309
316
|
implementation lives in the package at `services/reportData/fetchReportData`.
|
|
310
317
|
|
|
311
|
-
|
|
318
|
+
For the full host-app reference (cancellation in `useEffect`, memoizing
|
|
319
|
+
filters, paginated cursor hook, exporting to XLSX, all recipes and pitfalls),
|
|
320
|
+
see **[`docs/fetchReportData.md`](docs/fetchReportData.md)**. The companion
|
|
321
|
+
in-builder Calculation manual is **[`training/48-fetchReportData.md`](training/48-fetchReportData.md)**
|
|
322
|
+
(the auto-injected `fetchReportData` symbol).
|
|
312
323
|
|
|
313
|
-
|
|
314
|
-
of `services/reportData/fetchReportData` — from any file, host or package — to
|
|
315
|
-
the package's copy via `NormalModuleReplacementPlugin`. The host app's local
|
|
316
|
-
copy (if any) should be emptied out and never executed.
|
|
324
|
+
### Sourcing — both import paths work
|
|
317
325
|
|
|
318
|
-
|
|
326
|
+
Since v1.0.23, the recommended import is the package surface:
|
|
327
|
+
|
|
328
|
+
```js
|
|
329
|
+
import { fetchReportDataByPageId } from 'robobyte-front-builder'
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
The legacy bare-alias path also still works and resolves to the same module
|
|
333
|
+
via the `NormalModuleReplacementPlugin` rule:
|
|
319
334
|
|
|
320
335
|
```js
|
|
321
336
|
import fetchReportDataByPageId from 'services/reportData/fetchReportData'
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Both paths point to the same file, so the in-memory `builderModelCache` is
|
|
340
|
+
shared. Pick the package import for new code — it doesn't depend on the
|
|
341
|
+
webpack rule.
|
|
342
|
+
|
|
343
|
+
### Usage
|
|
344
|
+
|
|
345
|
+
```js
|
|
346
|
+
import { fetchReportDataByPageId } from 'robobyte-front-builder'
|
|
322
347
|
|
|
323
348
|
const result = await fetchReportDataByPageId({
|
|
324
349
|
pageId, // string | number — required
|
|
@@ -374,9 +399,18 @@ import { ReportViewer } from 'robobyte-front-builder'
|
|
|
374
399
|
noHeader={true}
|
|
375
400
|
filter={{ Tfilter: [...] }}
|
|
376
401
|
height="400px"
|
|
402
|
+
title="Q1 Orders" // toolbar title (left side)
|
|
403
|
+
caption="2026-01-01 → 2026-03-31"
|
|
377
404
|
/>
|
|
378
405
|
```
|
|
379
406
|
|
|
407
|
+
For the complete host-app reference — every prop, the new `viewerActions` /
|
|
408
|
+
`title` / `caption` / `debug` props, `setOutGridApi` for raw AG Grid API
|
|
409
|
+
access, building filters from React state, master/detail patterns, dialog
|
|
410
|
+
embedding, all pitfalls — see **[`docs/ReportViewer.md`](docs/ReportViewer.md)**.
|
|
411
|
+
The schema-side AI manual for the same component is
|
|
412
|
+
**[`training/35-reportViewer.md`](training/35-reportViewer.md)**.
|
|
413
|
+
|
|
380
414
|
### Props
|
|
381
415
|
|
|
382
416
|
| Prop | Type | Description |
|
|
@@ -858,9 +892,9 @@ The print builder persists layouts via four REST endpoints. The host API must im
|
|
|
858
892
|
|
|
859
893
|
The `value` field is the schema serialised with `JSON.stringify`. The print builder deserialises it with `JSON.parse` after fetching.
|
|
860
894
|
|
|
861
|
-
### Step 3 — Trigger print from a view
|
|
895
|
+
### Step 3 — Trigger print from a view (inside the builder)
|
|
862
896
|
|
|
863
|
-
Inside any action code (button `onClick`, row action, etc.) in a UI Builder view:
|
|
897
|
+
Inside any action code (button `onClick`, row action, viewer action, form `onSubmit`, etc.) in a UI Builder view:
|
|
864
898
|
|
|
865
899
|
```js
|
|
866
900
|
openPrintLayout('your-layout-id', {
|
|
@@ -871,7 +905,57 @@ openPrintLayout('your-layout-id', {
|
|
|
871
905
|
})
|
|
872
906
|
```
|
|
873
907
|
|
|
874
|
-
`openPrintLayout` is injected into every action's execution scope automatically by `ProductionViewer`. No import is needed.
|
|
908
|
+
`openPrintLayout` is injected into every action's execution scope automatically by `ProductionViewer`. No import is needed. The companion helper `closePrintLayout()` dismisses the dialog programmatically.
|
|
909
|
+
|
|
910
|
+
For the full Calculation-scope reference (data shape, all trigger points, recipes for row actions / viewer actions / form submits, pitfalls), see **[`training/49-printLayout.md`](training/49-printLayout.md)**.
|
|
911
|
+
|
|
912
|
+
### Step 3b — Trigger print from host-app code (outside the builder)
|
|
913
|
+
|
|
914
|
+
When you need to print from regular host-app React code — a custom page, an action handler, a dialog, a hook, anywhere outside a builder Calculation — use the imperative `PrintDialog` API.
|
|
915
|
+
|
|
916
|
+
The pattern, condensed:
|
|
917
|
+
|
|
918
|
+
```jsx
|
|
919
|
+
// host-app/pages/invoices.jsx (or any host React file)
|
|
920
|
+
import { useRef } from 'react'
|
|
921
|
+
import PrintDialog from 'views/builder/viewer/PrintDialog' // bare-aliased import
|
|
922
|
+
|
|
923
|
+
export default function InvoicesPage() {
|
|
924
|
+
const printDialogRef = useRef(null)
|
|
925
|
+
|
|
926
|
+
const viewerContext = {
|
|
927
|
+
printDialogRef,
|
|
928
|
+
data: {}, setData: () => {}, form: {}, setForm: () => {},
|
|
929
|
+
mode: 'preview', isEditMode: false, isPreviewMode: true, isPrintContext: true,
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
return (
|
|
933
|
+
<>
|
|
934
|
+
<Button
|
|
935
|
+
onClick={() => printDialogRef.current?.open('invoice-layout-id', {
|
|
936
|
+
invoiceNumber: 'INV-1042',
|
|
937
|
+
customerName: 'Acme Corp',
|
|
938
|
+
lines: [{ sku: 'A', qty: 2 }],
|
|
939
|
+
})}
|
|
940
|
+
>
|
|
941
|
+
Print Invoice
|
|
942
|
+
</Button>
|
|
943
|
+
|
|
944
|
+
<PrintDialog viewerContext={viewerContext} />
|
|
945
|
+
</>
|
|
946
|
+
)
|
|
947
|
+
}
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
Three things to know:
|
|
951
|
+
|
|
952
|
+
1. **The `PrintDialog` import is bare-aliased.** Either add `views/builder/viewer/PrintDialog` to your `packageOwnedServices` array in `next.config.js` (next to the existing `services/reportData/fetchReportData` entry), or use the longer path `'robobyte-front-builder/src/views/builder/viewer/PrintDialog'`. Both resolve to the same file.
|
|
953
|
+
|
|
954
|
+
2. **The dialog is mounted-but-hidden.** It registers itself on `printDialogRef.current` after first render and exposes `{ open(layoutId, data), openWithSchema(schema, data), close() }`.
|
|
955
|
+
|
|
956
|
+
3. **For multi-page apps, prefer a `PrintProvider` pattern** — mount the dialog once at `_app.js` level and expose `usePrintLayout()` from a React context so every page gets `openPrintLayout(id, data)` without re-mounting. The full pattern is in **[`docs/printLayout.md`](docs/printLayout.md)**.
|
|
957
|
+
|
|
958
|
+
For the complete host-app reference (the three mounting patterns, listing layouts, recipes for printing from a `<ReportViewer>` viewer action, all pitfalls), see **[`docs/printLayout.md`](docs/printLayout.md)**.
|
|
875
959
|
|
|
876
960
|
### Step 4 — Build the layout
|
|
877
961
|
|
package/README.md
CHANGED
|
@@ -17,27 +17,28 @@ A low-code **UI Builder**, **Report Builder**, **Print Layout Designer**, and **
|
|
|
17
17
|
7. [Builder pages](#builder-pages)
|
|
18
18
|
8. [Navigation Extension API](#navigation-extension-api)
|
|
19
19
|
9. [Provider props reference](#provider-props-reference)
|
|
20
|
-
10. [
|
|
21
|
-
11. [
|
|
22
|
-
12. [
|
|
23
|
-
13. [
|
|
24
|
-
14. [
|
|
25
|
-
15. [
|
|
26
|
-
16. [
|
|
27
|
-
17. [
|
|
28
|
-
18. [
|
|
29
|
-
19. [
|
|
30
|
-
20. [
|
|
31
|
-
21. [
|
|
32
|
-
22. [
|
|
33
|
-
23. [
|
|
34
|
-
24. [
|
|
35
|
-
25. [
|
|
36
|
-
26. [
|
|
37
|
-
27. [
|
|
38
|
-
28. [
|
|
39
|
-
29. [
|
|
40
|
-
30. [
|
|
20
|
+
10. [AG Grid theme](#ag-grid-theme)
|
|
21
|
+
11. [fetchReportDataByPageId](#fetchreportdatabypageid)
|
|
22
|
+
12. [ReportViewer as a component](#reportviewer-as-a-component)
|
|
23
|
+
13. [Data Grid component](#data-grid-component)
|
|
24
|
+
14. [Dialog component](#dialog-component)
|
|
25
|
+
15. [Popover component](#popover-component)
|
|
26
|
+
16. [Excel Upload component](#excel-upload-component)
|
|
27
|
+
17. [Wizard component](#wizard-component)
|
|
28
|
+
18. [Repeater component](#repeater-component)
|
|
29
|
+
19. [Menu component](#menu-component)
|
|
30
|
+
20. [View Renderer component](#view-renderer-component)
|
|
31
|
+
21. [Layout Grid component](#layout-grid-component)
|
|
32
|
+
22. [Breadcrumb component](#breadcrumb-component)
|
|
33
|
+
23. [Print Layout Builder](#print-layout-builder)
|
|
34
|
+
24. [Calculation Scope Reference](#calculation-scope-reference)
|
|
35
|
+
25. [KPI Component Actions](#kpi-component-actions)
|
|
36
|
+
26. [Global Data Store](#global-data-store)
|
|
37
|
+
27. [Dark / Light theme](#dark--light-theme)
|
|
38
|
+
28. [Syncing local changes](#syncing-local-changes)
|
|
39
|
+
29. [Troubleshooting](#troubleshooting)
|
|
40
|
+
30. [Publishing](#publishing)
|
|
41
|
+
31. [Changelog](#changelog)
|
|
41
42
|
|
|
42
43
|
---
|
|
43
44
|
|
|
@@ -171,6 +172,11 @@ function RoboByteBridge({ children }) {
|
|
|
171
172
|
user={auth.user}
|
|
172
173
|
accessToken={auth.accessToken}
|
|
173
174
|
agGridLicenseKey={process.env.NEXT_PUBLIC_AG_GRID_LICENSE_KEY}
|
|
175
|
+
// Optional: Quartz theme overrides applied to every <AgGridReact>
|
|
176
|
+
// in the package. Merged on top of the package defaults — see the
|
|
177
|
+
// "AG Grid theme" section for the full list of params and the
|
|
178
|
+
// programmatic API. Omit to use the package defaults.
|
|
179
|
+
agGridTheme={{ accentColor: '#3b82f6' }}
|
|
174
180
|
>
|
|
175
181
|
{children}
|
|
176
182
|
</RoboByteFrontBuilderProvider>
|
|
@@ -316,6 +322,7 @@ function MyFeaturePlugin() {
|
|
|
316
322
|
| `user` | object | Current user object from your auth context |
|
|
317
323
|
| `accessToken` | string | Bearer token attached to every service call |
|
|
318
324
|
| `agGridLicenseKey` | string | AG Grid Enterprise license key — the provider calls `LicenseManager.setLicenseKey()` and registers all enterprise modules internally |
|
|
325
|
+
| `agGridTheme` | object | Quartz theme overrides applied to every `<AgGridReact>` in the package. Merged on top of `DEFAULT_AG_THEME_PARAMS`. Example: `{ accentColor: '#3b82f6', headerHeight: 32 }`. See [AG Grid theme](#ag-grid-theme). |
|
|
319
326
|
| `navExtensions` | array | Static nav items to inject into the sidebar |
|
|
320
327
|
| `endpoints` | object | Full-URL overrides per endpoint group + name |
|
|
321
328
|
|
|
@@ -323,6 +330,58 @@ function MyFeaturePlugin() {
|
|
|
323
330
|
|
|
324
331
|
---
|
|
325
332
|
|
|
333
|
+
## AG Grid theme
|
|
334
|
+
|
|
335
|
+
Every `<AgGridReact>` in the package — `reportViewer`, `dataGrid`, the role-permission editor, the navigator picker — reads its theme from a single context. The default lives in code at [`src/lib/agGridTheme.js`](src/lib/agGridTheme.js) and can be overridden in two places:
|
|
336
|
+
|
|
337
|
+
### 1. Host-app override via the provider
|
|
338
|
+
|
|
339
|
+
Pass an object of Quartz params to `agGridTheme`. The object is merged on top of the package defaults — keys you set win, everything else falls back.
|
|
340
|
+
|
|
341
|
+
```jsx
|
|
342
|
+
<RoboByteFrontBuilderProvider
|
|
343
|
+
agGridTheme={{
|
|
344
|
+
accentColor: '#3b82f6',
|
|
345
|
+
headerHeight: 32,
|
|
346
|
+
fontFamily: 'inherit',
|
|
347
|
+
}}
|
|
348
|
+
/* …other props… */
|
|
349
|
+
>
|
|
350
|
+
<App />
|
|
351
|
+
</RoboByteFrontBuilderProvider>
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
See the [AG Grid Quartz theming reference](https://www.ag-grid.com/react-data-grid/theming/) for the full list of params.
|
|
355
|
+
|
|
356
|
+
### 2. Package-wide default
|
|
357
|
+
|
|
358
|
+
Open [`src/lib/agGridTheme.js`](src/lib/agGridTheme.js) and edit `DEFAULT_AG_THEME_PARAMS`. Affects every consumer of `robobyte-front-builder` that doesn't supply its own `agGridTheme`.
|
|
359
|
+
|
|
360
|
+
### Programmatic use
|
|
361
|
+
|
|
362
|
+
```js
|
|
363
|
+
import {
|
|
364
|
+
DEFAULT_AG_THEME_PARAMS, // frozen params object
|
|
365
|
+
DEFAULT_AG_THEME, // pre-built Quartz theme
|
|
366
|
+
buildAgGridTheme, // (overrides) => Quartz theme
|
|
367
|
+
AgGridThemeProvider, // standalone provider (no other dependencies)
|
|
368
|
+
useAgGridTheme, // hook returning the resolved theme
|
|
369
|
+
} from 'robobyte-front-builder'
|
|
370
|
+
|
|
371
|
+
// In a host component that renders its own AG Grid:
|
|
372
|
+
import { AgGridReact } from 'ag-grid-react'
|
|
373
|
+
function MyGrid() {
|
|
374
|
+
const theme = useAgGridTheme()
|
|
375
|
+
return <AgGridReact theme={theme} columnDefs={[...]} />
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
The hook falls back to `DEFAULT_AG_THEME` when called outside `RoboByteFrontBuilderProvider`, so isolated grids still render correctly.
|
|
380
|
+
|
|
381
|
+
> **Future plan.** A "system settings" path will eventually layer between `DEFAULT_AG_THEME_PARAMS` and the host's `agGridTheme` prop, letting admins customize the theme without a code change. The provider API will stay the same.
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
326
385
|
## `fetchReportDataByPageId`
|
|
327
386
|
|
|
328
387
|
Fetches report data by `pageId` without any AG Grid dependency. Always imported from the package path — the `NormalModuleReplacementPlugin` in `next.config.js` routes it to the package's canonical implementation.
|
|
@@ -868,6 +927,9 @@ Hot-reload picks up all file changes automatically. Only `next.config.js` change
|
|
|
868
927
|
**AG Grid error #200 — IntegratedChartsModule not registered**
|
|
869
928
|
→ The provider registers `IntegratedChartsModule.with(AgChartsEnterpriseModule)` automatically. Ensure `ag-charts-enterprise` is installed in the package.
|
|
870
929
|
|
|
930
|
+
**AG Grid theme override not applying**
|
|
931
|
+
→ Pass it via `<RoboByteFrontBuilderProvider agGridTheme={{ … }}>`, not as a `theme={…}` prop on individual `<AgGridReact>` instances rendered by the package. Internal grids ignore per-instance themes; the provider's context is the single source of truth. See the *AG Grid theme* section.
|
|
932
|
+
|
|
871
933
|
**ReportViewer renders at half width**
|
|
872
934
|
→ The outer `Box` in `reportViewer/index.js` must use `display: 'block'`, not `display: 'flex'`.
|
|
873
935
|
|
|
@@ -903,6 +965,15 @@ npm publish --dry-run
|
|
|
903
965
|
|
|
904
966
|
## Changelog
|
|
905
967
|
|
|
968
|
+
### 1.0.25
|
|
969
|
+
- **Centralized AG Grid theme.** Every `<AgGridReact>` in the package (`reportViewer`, `dataGrid`, role-permission editor, navigator picker) now reads its Quartz theme from a single context. Host apps can override package-wide theme params (accent color, header height, fonts, border radius, etc.) via the new `agGridTheme` prop on `RoboByteFrontBuilderProvider`. Defaults live in [`src/lib/agGridTheme.js`](src/lib/agGridTheme.js). New exports: `DEFAULT_AG_THEME_PARAMS`, `DEFAULT_AG_THEME`, `buildAgGridTheme`, `AgGridThemeProvider`, `useAgGridTheme`.
|
|
970
|
+
- **`<ReportViewer>` redesigned toolbar.** Single-row toolbar: title + caption on the left; collapsible search, Filter (outlined button), Refresh (outlined button), and configurable viewer actions on the right. Auto-refresh interval, "Load all data" toggle, and Excel export moved into the side tool panel under *Display Settings*. Search popover navigable by keyboard (↑ ↓ Home End Enter Esc).
|
|
971
|
+
- **`<ReportViewer>` new inspector fields.** `title`, `caption`, `viewerActions` (array of page-level action buttons appended after Filter/Refresh), `debug` (renders a floating bug icon with a popover showing resolved `pageId`/`id`/builder model id/etc. — hidden in production by default).
|
|
972
|
+
- **Print Layout integration.** Host apps can now trigger print layouts directly via the imperative `PrintDialog` ref API — see [docs/printLayout.md](./docs/printLayout.md) for the recommended `PrintProvider` pattern with `usePrintLayout()`.
|
|
973
|
+
- **Public exports expanded.** `fetchReportDataByPageId` now exported from the package surface (`import { fetchReportDataByPageId } from 'robobyte-front-builder'`); the legacy bare-alias path still works.
|
|
974
|
+
- **Unsaved changes guard.** Builder pages now warn on tab close / refresh / in-app navigation when the schema has unsaved edits. `BuilderProvider` exposes `loadSchema(schema)` (clears history baseline), `markClean()` (post-save reset), and `isDirty`.
|
|
975
|
+
- **Session log + AI fine-tune pipeline.** Every successful save (UI Builder + Print Builder) is auto-logged to localStorage with the full schema. New *Session Logs* toolbar dialog lets developers add training prompts to entries and export a Together AI-ready JSONL. Together is now a first-class AI provider in `/api/ai`.
|
|
976
|
+
|
|
906
977
|
### 1.0.21
|
|
907
978
|
- Added Timer Engine — configurable auto-refresh timers per view
|
|
908
979
|
- Added full Undo / Redo history with keyboard shortcuts (Ctrl+Z / Ctrl+Y)
|
package/package.json
CHANGED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized AG Grid theme configuration.
|
|
3
|
+
*
|
|
4
|
+
* Every <AgGridReact> in the package reads its theme from a single source —
|
|
5
|
+
* the React context provided by `AgGridThemeProvider` (wrapped automatically
|
|
6
|
+
* inside RoboByteFrontBuilderProvider). The default lives here, in code.
|
|
7
|
+
*
|
|
8
|
+
* Host apps can override theme params by passing `agGridTheme` to
|
|
9
|
+
* RoboByteFrontBuilderProvider:
|
|
10
|
+
*
|
|
11
|
+
* <RoboByteFrontBuilderProvider
|
|
12
|
+
* agGridTheme={{ accentColor: '#3b82f6', headerHeight: 32 }}
|
|
13
|
+
* ...
|
|
14
|
+
* />
|
|
15
|
+
*
|
|
16
|
+
* The override object is merged on top of DEFAULT_AG_THEME_PARAMS — host
|
|
17
|
+
* params win for the keys they set, and fall back to defaults otherwise.
|
|
18
|
+
*
|
|
19
|
+
* Future: this default will be replaced with a system-settings fetch so
|
|
20
|
+
* theme params can be tweaked at runtime without a code change. Until then,
|
|
21
|
+
* editing this file is the way to change the package-wide default.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { themeQuartz } from 'ag-grid-community'
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Default Quartz theme parameters used across the package.
|
|
28
|
+
* See https://www.ag-grid.com/react-data-grid/theming/ for the full list.
|
|
29
|
+
*
|
|
30
|
+
* Add new keys here as the package grows. Host apps can override any of
|
|
31
|
+
* them by passing `agGridTheme={{ <key>: <value> }}` to the provider.
|
|
32
|
+
*/
|
|
33
|
+
export const DEFAULT_AG_THEME_PARAMS = Object.freeze({
|
|
34
|
+
accentColor: '#FF1185',
|
|
35
|
+
// headerHeight: 28,
|
|
36
|
+
// rowHeight: 34,
|
|
37
|
+
// fontFamily: 'inherit',
|
|
38
|
+
// fontSize: 13,
|
|
39
|
+
// borderRadius: 4,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Build a Quartz theme from optional overrides. Returns a fresh theme object
|
|
44
|
+
* (Quartz themes are immutable). Safe to call on every render — `withParams`
|
|
45
|
+
* caches by params identity.
|
|
46
|
+
*
|
|
47
|
+
* @param {Object} [overrides] - Quartz theme params to merge over the defaults.
|
|
48
|
+
* @returns {object} A ready-to-use AG Grid theme.
|
|
49
|
+
*/
|
|
50
|
+
export function buildAgGridTheme(overrides) {
|
|
51
|
+
return themeQuartz.withParams({
|
|
52
|
+
...DEFAULT_AG_THEME_PARAMS,
|
|
53
|
+
...(overrides ?? {}),
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Pre-built default theme — convenient when no override is in play. */
|
|
58
|
+
export const DEFAULT_AG_THEME = buildAgGridTheme()
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgGridThemeContext — single source of truth for the package-wide AG Grid
|
|
3
|
+
* theme. Wrapped automatically inside RoboByteFrontBuilderProvider.
|
|
4
|
+
*
|
|
5
|
+
* Consumers call `useAgGridTheme()` to get the resolved Quartz theme and pass
|
|
6
|
+
* it to <AgGridReact theme={agTheme} />.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createContext, useContext, useMemo } from 'react'
|
|
10
|
+
import { buildAgGridTheme, DEFAULT_AG_THEME } from './agGridTheme'
|
|
11
|
+
|
|
12
|
+
const AgGridThemeContext = createContext(DEFAULT_AG_THEME)
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Wraps children with the AG Grid theme context.
|
|
16
|
+
*
|
|
17
|
+
* @param {Object} [params] - Quartz theme overrides (merged over defaults).
|
|
18
|
+
* @param {ReactNode} children
|
|
19
|
+
*/
|
|
20
|
+
export function AgGridThemeProvider({ params, children }) {
|
|
21
|
+
// JSON.stringify on the params object is intentional — host apps that pass
|
|
22
|
+
// an inline object literal would otherwise rebuild the theme on every
|
|
23
|
+
// parent render. Stringify keys the memo by the actual params content.
|
|
24
|
+
const theme = useMemo(
|
|
25
|
+
() => buildAgGridTheme(params),
|
|
26
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
27
|
+
[JSON.stringify(params ?? null)]
|
|
28
|
+
)
|
|
29
|
+
return (
|
|
30
|
+
<AgGridThemeContext.Provider value={theme}>
|
|
31
|
+
{children}
|
|
32
|
+
</AgGridThemeContext.Provider>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Returns the live AG Grid theme. Falls back to the default theme when
|
|
38
|
+
* called outside RoboByteFrontBuilderProvider, so isolated grids still work.
|
|
39
|
+
*/
|
|
40
|
+
export function useAgGridTheme() {
|
|
41
|
+
return useContext(AgGridThemeContext)
|
|
42
|
+
}
|
package/src/lib/index.js
CHANGED
|
@@ -106,3 +106,10 @@ export { AuthContext } from '../context/AuthContext'
|
|
|
106
106
|
// — both resolve to the same module thanks to the NormalModuleReplacementPlugin
|
|
107
107
|
// in next.config.js, so the in-memory builderModelCache is shared.
|
|
108
108
|
export { default as fetchReportDataByPageId } from '../services/reportData/fetchReportData'
|
|
109
|
+
|
|
110
|
+
// ── AG Grid theme ────────────────────────────────────────────────────────────
|
|
111
|
+
// Default theme params (host can override via RoboByteFrontBuilderProvider's
|
|
112
|
+
// `agGridTheme` prop), a builder function for ad-hoc themes, and the hook
|
|
113
|
+
// every internal grid uses to read the live theme.
|
|
114
|
+
export { DEFAULT_AG_THEME_PARAMS, buildAgGridTheme, DEFAULT_AG_THEME } from './agGridTheme'
|
|
115
|
+
export { AgGridThemeProvider, useAgGridTheme } from './agGridThemeContext'
|
|
@@ -49,6 +49,7 @@ import { Toaster } from 'react-hot-toast'
|
|
|
49
49
|
import { ModuleRegistry } from 'ag-grid-community'
|
|
50
50
|
import { AllEnterpriseModule, LicenseManager } from 'ag-grid-enterprise'
|
|
51
51
|
import { NavigationExtensionProvider } from '../navigation/NavigationExtensionContext'
|
|
52
|
+
import { AgGridThemeProvider } from '../agGridThemeContext'
|
|
52
53
|
import { configureRoboByte } from '../../services/config'
|
|
53
54
|
import { AuthContext } from '../../context/AuthContext'
|
|
54
55
|
import { setRouter } from '../../services/routerRef'
|
|
@@ -95,6 +96,17 @@ const RoboByteFrontBuilderProvider = ({
|
|
|
95
96
|
navExtensions = [],
|
|
96
97
|
endpoints = null,
|
|
97
98
|
agGridLicenseKey = null,
|
|
99
|
+
/**
|
|
100
|
+
* Optional Quartz theme overrides applied to every <AgGridReact> in the
|
|
101
|
+
* package. Merged on top of DEFAULT_AG_THEME_PARAMS in `lib/agGridTheme.js`.
|
|
102
|
+
*
|
|
103
|
+
* Example:
|
|
104
|
+
* agGridTheme={{ accentColor: '#3b82f6', headerHeight: 32 }}
|
|
105
|
+
*
|
|
106
|
+
* Future: this will accept a "load from system settings" mode. For now
|
|
107
|
+
* pass a plain params object.
|
|
108
|
+
*/
|
|
109
|
+
agGridTheme = null,
|
|
98
110
|
toasterProps = {},
|
|
99
111
|
}) => {
|
|
100
112
|
// Apply URL + endpoint config synchronously before any child renders.
|
|
@@ -121,6 +133,7 @@ const RoboByteFrontBuilderProvider = ({
|
|
|
121
133
|
return (
|
|
122
134
|
<AuthContext.Provider value={authValue}>
|
|
123
135
|
<NavigationExtensionProvider items={navExtensions}>
|
|
136
|
+
<AgGridThemeProvider params={agGridTheme}>
|
|
124
137
|
<RouterSync />
|
|
125
138
|
{children}
|
|
126
139
|
{/* Package-owned Toaster — same react-hot-toast instance used by all
|
|
@@ -157,6 +170,7 @@ const RoboByteFrontBuilderProvider = ({
|
|
|
157
170
|
}}
|
|
158
171
|
{...toasterProps}
|
|
159
172
|
/>
|
|
173
|
+
</AgGridThemeProvider>
|
|
160
174
|
</NavigationExtensionProvider>
|
|
161
175
|
</AuthContext.Provider>
|
|
162
176
|
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, {useEffect, useState} from 'react'
|
|
2
|
-
import {Box, CircularProgress, Typography, Paper, IconButton, CardContent, Tooltip} from '@mui/material'
|
|
2
|
+
import {Box, CircularProgress, Typography, Paper, IconButton, CardContent, Tooltip, Popover, Chip} from '@mui/material'
|
|
3
3
|
import {useRouter} from 'next/router'
|
|
4
4
|
import SGrid from 'views/genericTable/SGrid'
|
|
5
5
|
import {Endpoints, Services} from 'services/Endpoints'
|
|
@@ -8,7 +8,7 @@ import CardHeader from "@mui/material/CardHeader";
|
|
|
8
8
|
import Grid from "@mui/material/Grid";
|
|
9
9
|
import {Plus} from "mdi-material-ui";
|
|
10
10
|
import TAGGrid from "views/genericTable/TAGGrid";
|
|
11
|
-
import {SettingsOutlined, AssessmentOutlined} from "@mui/icons-material";
|
|
11
|
+
import {SettingsOutlined, AssessmentOutlined, BugReportOutlined, ContentCopyOutlined} from "@mui/icons-material";
|
|
12
12
|
import UpdateReportPermissionDialog from "views/rolePermissions/UpdateReportPermissionDialog";
|
|
13
13
|
import {getReportSession} from 'src/services/helper/reportSessionHelper'
|
|
14
14
|
import BlankLayout from '../../../../lib/layouts/BlankLayout';
|
|
@@ -48,6 +48,12 @@ const ReportViewer = (params) => {
|
|
|
48
48
|
// Page-level toolbar buttons rendered after Filter / Refresh.
|
|
49
49
|
// Built by ReportViewerRenderer with bound onClick handlers.
|
|
50
50
|
viewerActions,
|
|
51
|
+
// Debug — when truthy, renders a small floating BugReport icon at the
|
|
52
|
+
// top-right corner of the report area. Clicking it opens a popover
|
|
53
|
+
// showing the resolved ids (pageId, id, builderMetadata.id) and other
|
|
54
|
+
// useful runtime info. Hidden entirely when `debug` is falsy, so
|
|
55
|
+
// production builds incur zero cost.
|
|
56
|
+
debug,
|
|
51
57
|
// nodeId / reportRefs are injected by the UI builder's ReportViewerRenderer.
|
|
52
58
|
// nodeId — the builder schema node ID for this ReportViewer instance
|
|
53
59
|
// reportRefs — the shared registry { [nodeId]: updateRef } for all reports on the page
|
|
@@ -64,6 +70,8 @@ const ReportViewer = (params) => {
|
|
|
64
70
|
const [builderMetadata, setBuilderMetadata] = useState(null)
|
|
65
71
|
const [sessionPayload, setSessionPayload] = useState(null)
|
|
66
72
|
const [payloadVersion, setPayloadVersion] = useState(0)
|
|
73
|
+
// Debug popover anchor — only used when `debug` prop is truthy.
|
|
74
|
+
const [debugAnchor, setDebugAnchor] = useState(null)
|
|
67
75
|
|
|
68
76
|
useEffect(() => {
|
|
69
77
|
// Prefer localStorage payload via sessionId (set by SGrid)
|
|
@@ -176,13 +184,137 @@ const ReportViewer = (params) => {
|
|
|
176
184
|
setPayloadVersion(v => v + 1);
|
|
177
185
|
}, [id, router.query?.id, pageId, router.query?.pageId, sessionPayload])
|
|
178
186
|
|
|
187
|
+
// ── Debug snapshot — gathered fresh on every render so the popover always
|
|
188
|
+
// reflects the current resolved state. Cheap to build (just reads
|
|
189
|
+
// existing state / props) so no memo needed.
|
|
190
|
+
const resolvedPageId = pageId ?? sessionPayload?.pageId ?? router.query?.pageId
|
|
191
|
+
const resolvedId = id ?? sessionPayload?.id ?? router.query?.id
|
|
192
|
+
const debugFields = debug ? [
|
|
193
|
+
{ label: 'pageId', value: resolvedPageId },
|
|
194
|
+
{ label: 'id (prop)', value: resolvedId },
|
|
195
|
+
{ label: 'builder model id', value: builderModel?.id },
|
|
196
|
+
{ label: 'report name', value: builderMetadata?.name },
|
|
197
|
+
{ label: 'nodeId', value: nodeId },
|
|
198
|
+
{ label: 'sessionId', value: sessionId },
|
|
199
|
+
{ label: 'payload version', value: payloadVersion },
|
|
200
|
+
{ label: 'session payload', value: sessionPayload ? '✓ loaded' : '—' },
|
|
201
|
+
{ label: 'isSingle', value: String(Boolean(isSingle)) },
|
|
202
|
+
{ label: 'dataAsObject', value: String(Boolean(dataAsObject)) },
|
|
203
|
+
{ label: 'isRerender', value: String(Boolean(isRerender)) },
|
|
204
|
+
{ label: 'externalTimer', value: externalTimer ?? '—' },
|
|
205
|
+
{ label: 'height', value: height ?? '85vh' },
|
|
206
|
+
{ label: 'globalParams', value: globalParams ? JSON.stringify(globalParams) : '—' },
|
|
207
|
+
] : []
|
|
208
|
+
|
|
209
|
+
const copyToClipboard = (value) => {
|
|
210
|
+
if (value == null) return
|
|
211
|
+
try { navigator.clipboard?.writeText(String(value)) } catch (_) {}
|
|
212
|
+
}
|
|
213
|
+
|
|
179
214
|
return (
|
|
180
215
|
<Box
|
|
181
216
|
sx={{
|
|
182
217
|
display: 'block',
|
|
183
218
|
width: '100%',
|
|
219
|
+
position: 'relative',
|
|
184
220
|
}}
|
|
185
221
|
>
|
|
222
|
+
{/* ── Debug floater ────────────────────────────────────────────────────
|
|
223
|
+
Renders only when the `debug` prop is truthy. A small icon button at
|
|
224
|
+
the top-right corner that opens a key/value popover. Useful when a
|
|
225
|
+
report appears broken — confirm pageId/id resolved correctly, the
|
|
226
|
+
builder model loaded, the right sessionPayload was picked, etc. */}
|
|
227
|
+
{debug && (
|
|
228
|
+
<>
|
|
229
|
+
<Tooltip title='Report debug info' placement='left'>
|
|
230
|
+
<IconButton
|
|
231
|
+
size='small'
|
|
232
|
+
onClick={(e) => setDebugAnchor(e.currentTarget)}
|
|
233
|
+
sx={{
|
|
234
|
+
position: 'absolute',
|
|
235
|
+
top: 4,
|
|
236
|
+
insetInlineEnd: 4,
|
|
237
|
+
zIndex: 10,
|
|
238
|
+
bgcolor: 'warning.light',
|
|
239
|
+
color: 'warning.contrastText',
|
|
240
|
+
opacity: 0.9,
|
|
241
|
+
'&:hover': { bgcolor: 'warning.main', opacity: 1 },
|
|
242
|
+
boxShadow: 1,
|
|
243
|
+
}}
|
|
244
|
+
>
|
|
245
|
+
<BugReportOutlined fontSize='small' />
|
|
246
|
+
</IconButton>
|
|
247
|
+
</Tooltip>
|
|
248
|
+
|
|
249
|
+
<Popover
|
|
250
|
+
open={Boolean(debugAnchor)}
|
|
251
|
+
anchorEl={debugAnchor}
|
|
252
|
+
onClose={() => setDebugAnchor(null)}
|
|
253
|
+
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
|
254
|
+
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
|
|
255
|
+
PaperProps={{ sx: { p: 0, minWidth: 320, maxWidth: 480 } }}
|
|
256
|
+
>
|
|
257
|
+
<Box sx={{ px: 2, py: 1, bgcolor: 'warning.light', display: 'flex', alignItems: 'center', gap: 1 }}>
|
|
258
|
+
<BugReportOutlined fontSize='small' sx={{ color: 'warning.contrastText' }} />
|
|
259
|
+
<Typography variant='subtitle2' sx={{ color: 'warning.contrastText', fontWeight: 700, flex: 1 }}>
|
|
260
|
+
Report Debug
|
|
261
|
+
</Typography>
|
|
262
|
+
<Chip
|
|
263
|
+
size='small'
|
|
264
|
+
label={isLoading ? 'loading' : builderModel ? 'ready' : 'idle'}
|
|
265
|
+
color={isLoading ? 'info' : builderModel ? 'success' : 'default'}
|
|
266
|
+
sx={{ height: 18, fontSize: 10 }}
|
|
267
|
+
/>
|
|
268
|
+
</Box>
|
|
269
|
+
<Box sx={{ p: 1.5, display: 'flex', flexDirection: 'column', gap: 0.5 }}>
|
|
270
|
+
{debugFields.map(({ label, value }) => (
|
|
271
|
+
<Box
|
|
272
|
+
key={label}
|
|
273
|
+
sx={{
|
|
274
|
+
display: 'grid',
|
|
275
|
+
gridTemplateColumns: '130px 1fr auto',
|
|
276
|
+
alignItems: 'center',
|
|
277
|
+
gap: 1,
|
|
278
|
+
px: 1,
|
|
279
|
+
py: 0.5,
|
|
280
|
+
borderRadius: 0.5,
|
|
281
|
+
'&:hover': { bgcolor: 'action.hover' },
|
|
282
|
+
}}
|
|
283
|
+
>
|
|
284
|
+
<Typography variant='caption' sx={{ color: 'text.secondary', fontFamily: 'monospace' }}>
|
|
285
|
+
{label}
|
|
286
|
+
</Typography>
|
|
287
|
+
<Typography
|
|
288
|
+
variant='body2'
|
|
289
|
+
sx={{
|
|
290
|
+
fontFamily: 'monospace',
|
|
291
|
+
fontSize: 12,
|
|
292
|
+
color: value == null || value === '—' ? 'text.disabled' : 'text.primary',
|
|
293
|
+
overflow: 'hidden',
|
|
294
|
+
textOverflow: 'ellipsis',
|
|
295
|
+
whiteSpace: 'nowrap',
|
|
296
|
+
}}
|
|
297
|
+
title={String(value ?? '')}
|
|
298
|
+
>
|
|
299
|
+
{value ?? '—'}
|
|
300
|
+
</Typography>
|
|
301
|
+
<Tooltip title='Copy' placement='left'>
|
|
302
|
+
<IconButton
|
|
303
|
+
size='small'
|
|
304
|
+
onClick={() => copyToClipboard(value)}
|
|
305
|
+
disabled={value == null || value === '—'}
|
|
306
|
+
sx={{ p: 0.25 }}
|
|
307
|
+
>
|
|
308
|
+
<ContentCopyOutlined sx={{ fontSize: 13 }} />
|
|
309
|
+
</IconButton>
|
|
310
|
+
</Tooltip>
|
|
311
|
+
</Box>
|
|
312
|
+
))}
|
|
313
|
+
</Box>
|
|
314
|
+
</Popover>
|
|
315
|
+
</>
|
|
316
|
+
)}
|
|
317
|
+
|
|
186
318
|
{isLoading ? (
|
|
187
319
|
<Box
|
|
188
320
|
sx={{
|
|
@@ -9,6 +9,11 @@ export const REPORT_VIEWER_MAIN_FIELDS = [
|
|
|
9
9
|
{ name: 'title', label: 'Title', type: 'expression' },
|
|
10
10
|
{ name: 'caption', label: 'Caption', type: 'expression' },
|
|
11
11
|
|
|
12
|
+
// Debug — when true, a small BugReport icon appears at the report's
|
|
13
|
+
// top-right corner; clicking it opens a popover listing the resolved
|
|
14
|
+
// pageId / id / builder model id / sessionId / and other runtime info.
|
|
15
|
+
// Hidden entirely when false / unset — zero cost in production schemas.
|
|
16
|
+
{ name: 'debug', label: 'Debug', type: 'boolean' },
|
|
12
17
|
{ name: 'minimized', label: 'Minimized', type: 'boolean' },
|
|
13
18
|
{ name: 'isRerender', label: 'Is Rerender', type: 'boolean' },
|
|
14
19
|
{ name: 'height', label: 'Height', type: 'expression' },
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Box, Button, IconButton, Tooltip, Typography } from '@mui/material'
|
|
2
2
|
import { useRef, useMemo, useCallback, useEffect } from 'react'
|
|
3
3
|
import { AgGridReact } from 'ag-grid-react'
|
|
4
|
-
import { themeQuartz } from 'ag-grid-community'
|
|
5
4
|
import { AddOutlined, DeleteOutlined, TableChartOutlined } from '@mui/icons-material'
|
|
6
5
|
import ViewerComponentWrapper from '../ViewerComponentWrapper'
|
|
7
6
|
import RowActionsCell from './RowActionsCell'
|
|
@@ -9,9 +8,7 @@ import { resolveProps } from 'services/builderHelper/resolveProps'
|
|
|
9
8
|
import { executeJSCode } from 'services/builderHelper/jsExecutor'
|
|
10
9
|
import { processColumnDefinitions, processColumnsConfig } from 'views/genericTable/convertStringFunctions'
|
|
11
10
|
import { AG_COMPONENTS } from './dataGridComponents'
|
|
12
|
-
|
|
13
|
-
// ── Shared AG Grid theme (same as SGrid) ──────────────────────────────────────
|
|
14
|
-
const agTheme = themeQuartz.withParams({ accentColor: '#FF1185' })
|
|
11
|
+
import { useAgGridTheme } from 'src/lib/agGridThemeContext'
|
|
15
12
|
|
|
16
13
|
// ── Delete-column cell renderer ───────────────────────────────────────────────
|
|
17
14
|
// Defined at module level so AG Grid never receives a new component reference.
|
|
@@ -49,6 +46,9 @@ export default function DataGridRenderer({ node, viewerContext }) {
|
|
|
49
46
|
form, data, setData, dataRef, reportRefs, openDialog, closeDialog, isEditMode,
|
|
50
47
|
} = viewerContext
|
|
51
48
|
|
|
49
|
+
// Centralized AG Grid theme — see lib/agGridTheme.js / RoboByteFrontBuilderProvider.
|
|
50
|
+
const agTheme = useAgGridTheme()
|
|
51
|
+
|
|
52
52
|
const main = resolveProps(node, 'main', viewerContext)
|
|
53
53
|
|
|
54
54
|
const {
|
|
@@ -115,7 +115,7 @@ import numeral from 'numeral'
|
|
|
115
115
|
import CustomFilterDialog from "views/customFilter/CustomFilterDialog";
|
|
116
116
|
import CustomStatusBar from "views/genericTable/statusBar/rowCountStatusBar";
|
|
117
117
|
import StreamService from "services/StreamService";
|
|
118
|
-
import {
|
|
118
|
+
import { useAgGridTheme } from 'src/lib/agGridThemeContext'
|
|
119
119
|
import {ReportBuilderEndpoints} from "services/Endpoints/ReportBuilderEndpoints";
|
|
120
120
|
import {debounce} from "lodash";
|
|
121
121
|
import jsPDF from "jspdf";
|
|
@@ -330,10 +330,10 @@ const SGrid = props => {
|
|
|
330
330
|
// ** State
|
|
331
331
|
const appContext = useContext(SystemContext);
|
|
332
332
|
const imageBaseUrl = appContext?.settings?.imagesStorageServer;
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
333
|
+
// Theme comes from RoboByteFrontBuilderProvider's agGridTheme prop, merged
|
|
334
|
+
// with DEFAULT_AG_THEME_PARAMS in lib/agGridTheme.js. Falls back to the
|
|
335
|
+
// bare default when used outside the provider.
|
|
336
|
+
const agTheme = useAgGridTheme()
|
|
337
337
|
|
|
338
338
|
const {
|
|
339
339
|
externalTimer,
|
|
@@ -37,7 +37,7 @@ import numeral from 'numeral'
|
|
|
37
37
|
import CustomFilterDialog from "views/customFilter/CustomFilterDialog";
|
|
38
38
|
import CustomStatusBar from "views/genericTable/statusBar/rowCountStatusBar";
|
|
39
39
|
import StreamService from "services/StreamService";
|
|
40
|
-
import {
|
|
40
|
+
import { useAgGridTheme } from 'src/lib/agGridThemeContext'
|
|
41
41
|
|
|
42
42
|
// ** Utils Import
|
|
43
43
|
|
|
@@ -52,10 +52,8 @@ const defaultFinalRequest = {
|
|
|
52
52
|
}
|
|
53
53
|
const TAGGrid = props => {
|
|
54
54
|
// ** State
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
accentColor: "#FF1185"
|
|
58
|
-
});
|
|
55
|
+
// Theme comes from RoboByteFrontBuilderProvider's agGridTheme prop.
|
|
56
|
+
const agTheme = useAgGridTheme()
|
|
59
57
|
const {
|
|
60
58
|
groupEndPoint,
|
|
61
59
|
streamEndPoint,
|
|
@@ -21,8 +21,11 @@ import {Endpoints, Services} from 'src/services/Endpoints'
|
|
|
21
21
|
import {toast} from 'react-hot-toast'
|
|
22
22
|
import {AgGridReact} from "ag-grid-react";
|
|
23
23
|
import {AutocompleteEditorWrapper} from "views/genericTable/cellEditors/autocompleteEditor";
|
|
24
|
+
import { useAgGridTheme } from 'src/lib/agGridThemeContext'
|
|
24
25
|
|
|
25
26
|
const UpdateReportPermissionsDialog = props => {
|
|
27
|
+
// Centralized AG Grid theme.
|
|
28
|
+
const agTheme = useAgGridTheme()
|
|
26
29
|
// ** Props
|
|
27
30
|
const {handleToggleDialogs, report, dialog, setRefresh} = props
|
|
28
31
|
const [IsSubmitting, setIsSubmitting] = useState(false)
|
|
@@ -266,6 +269,7 @@ const UpdateReportPermissionsDialog = props => {
|
|
|
266
269
|
<Grid container size={{ xs: 12 }}>
|
|
267
270
|
<div style={{width: "100%", height: "40vh", direction: 'ltr'}}>
|
|
268
271
|
<AgGridReact
|
|
272
|
+
theme={agTheme}
|
|
269
273
|
enableRtl={true}
|
|
270
274
|
columnDefs={colDefs}
|
|
271
275
|
rowData={ReportPermissions}
|