dts-universal-report-module 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +652 -11
- package/dist/index.esm.js +10137 -7926
- package/dist/index.js +32 -52
- package/package.json +78 -48
package/README.md
CHANGED
|
@@ -1,11 +1,652 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
# Universal Report Module (URM)
|
|
2
|
+
|
|
3
|
+
> A fully featured, embeddable React reporting component for Digital Twin Solutions applications.
|
|
4
|
+
> Drop it into any MERN-stack host app and get a complete data table with filtering, sorting,
|
|
5
|
+
> grouping, views, presets, export, audit history, and scheduled reports — out of the box.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Overview](#overview)
|
|
12
|
+
- [Features](#features)
|
|
13
|
+
- [Tech Stack](#tech-stack)
|
|
14
|
+
- [Architecture](#architecture)
|
|
15
|
+
- [Folder Structure](#folder-structure)
|
|
16
|
+
- [Prerequisites](#prerequisites)
|
|
17
|
+
- [Installation & Setup](#installation--setup)
|
|
18
|
+
- [Running the Development Server](#running-the-development-server)
|
|
19
|
+
- [Building the Library](#building-the-library)
|
|
20
|
+
- [Environment Configuration](#environment-configuration)
|
|
21
|
+
- [Usage — Integrating URM into a Host App](#usage--integrating-urm-into-a-host-app)
|
|
22
|
+
- [Data Source Options](#data-source-options)
|
|
23
|
+
- [Public API Reference](#public-api-reference)
|
|
24
|
+
- [Branching Strategy](#branching-strategy)
|
|
25
|
+
- [Commit Message Format](#commit-message-format)
|
|
26
|
+
- [Code Standards](#code-standards)
|
|
27
|
+
- [Developer Notes](#developer-notes)
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Overview
|
|
32
|
+
|
|
33
|
+
The **Universal Report Module (URM)** is a reusable React + TypeScript npm package built for
|
|
34
|
+
Digital Twin Solutions. It provides two primary surfaces:
|
|
35
|
+
|
|
36
|
+
- **`URMBuilder`** — A full report creation and management interface. Users can upload JSON data,
|
|
37
|
+
define column schemas, apply filters, sort, group, manage saved views, create presets, export
|
|
38
|
+
data, and review a complete audit history.
|
|
39
|
+
|
|
40
|
+
- **`URMViewer`** — A read-optimised embedded viewer for host applications that already have data.
|
|
41
|
+
It accepts data directly via props or an API source and renders the full table experience
|
|
42
|
+
without the upload or report-creation workflow.
|
|
43
|
+
|
|
44
|
+
Both surfaces are backed by the same core engine (`UseReportEngine`) and can be configured,
|
|
45
|
+
themed, and extended by the host application.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Features
|
|
50
|
+
|
|
51
|
+
### Data Ingestion
|
|
52
|
+
- JSON file upload with automatic schema detection
|
|
53
|
+
- Inline data via props (`data={myArray}`)
|
|
54
|
+
- API source with optional auto-refresh (`dataSource={{ type: 'api', url: '...' }}`)
|
|
55
|
+
- Async callback source (`dataSource={{ type: 'callback', fetch: async () => data }}`)
|
|
56
|
+
- Schema conflict detection and resolution UI
|
|
57
|
+
|
|
58
|
+
### Table & Display
|
|
59
|
+
- Resizable, reorderable columns via drag-and-drop
|
|
60
|
+
- Card grid view toggle (alternative to table rows)
|
|
61
|
+
- Sticky header and frozen column support
|
|
62
|
+
- Row selection (single, range, select-all)
|
|
63
|
+
- Inline row detail, edit, and delete modals
|
|
64
|
+
- Favourited rows and favourites-only filter toggle
|
|
65
|
+
- Empty state and error state components
|
|
66
|
+
|
|
67
|
+
### Filtering
|
|
68
|
+
- Multi-column filter panel
|
|
69
|
+
- Operators: equals, contains, startsWith, endsWith, gt, lt, gte, lte, isTrue, isFalse, NULL, NOT_NULL
|
|
70
|
+
- Per-column filter clear
|
|
71
|
+
- Filter conflict detection with user warnings
|
|
72
|
+
|
|
73
|
+
### Sorting
|
|
74
|
+
- Multi-level sort stack (unlimited sort rules)
|
|
75
|
+
- Drag-to-reorder sort priority
|
|
76
|
+
- Column header click cycling (asc → desc → clear)
|
|
77
|
+
- Sort panel with full rule management
|
|
78
|
+
|
|
79
|
+
### Grouping
|
|
80
|
+
- Multi-level row grouping (up to N levels)
|
|
81
|
+
- Collapsible group rows
|
|
82
|
+
- Group aggregate display (count, sum, min, max)
|
|
83
|
+
- Drag-to-reorder group levels
|
|
84
|
+
|
|
85
|
+
### Views
|
|
86
|
+
- Named, saved view snapshots (filters + sort + columns + grouping)
|
|
87
|
+
- Default view designation
|
|
88
|
+
- Favourite views
|
|
89
|
+
- Dirty-state detection with diff summary modal
|
|
90
|
+
- View restore and permanent delete
|
|
91
|
+
|
|
92
|
+
### Presets & Sharing
|
|
93
|
+
- Named saved presets (configuration snapshots)
|
|
94
|
+
- Shareable preset links via URL encoding
|
|
95
|
+
- Preset management panel (apply, delete, copy link)
|
|
96
|
+
- Active preset badge
|
|
97
|
+
|
|
98
|
+
### Export
|
|
99
|
+
- Export to CSV, Excel (`.xlsx`), and JSON
|
|
100
|
+
- Configurable export options (selected rows, full data, current view)
|
|
101
|
+
- Dirty-view export warning
|
|
102
|
+
- Bulk export for selected rows
|
|
103
|
+
|
|
104
|
+
### Scheduled Reports
|
|
105
|
+
- Schedule-based auto-export (daily, weekly, monthly)
|
|
106
|
+
- Email notification integration
|
|
107
|
+
- Scheduler management modal
|
|
108
|
+
|
|
109
|
+
### Audit & History
|
|
110
|
+
- Full audit trail of all user actions (filters, sorts, views, presets, exports)
|
|
111
|
+
- Audit history panel with collapsible timeline
|
|
112
|
+
- Audit events written to report state
|
|
113
|
+
|
|
114
|
+
### Search
|
|
115
|
+
- Global search across all visible columns
|
|
116
|
+
- Search history with favourites
|
|
117
|
+
- Persistent search history per report
|
|
118
|
+
|
|
119
|
+
### Pagination
|
|
120
|
+
- Configurable page size (10, 25, 50, 100, all)
|
|
121
|
+
- Page navigation controls
|
|
122
|
+
- Total row count display
|
|
123
|
+
|
|
124
|
+
### Permissions
|
|
125
|
+
- Role-based access: `owner`, `editor`, `viewer`
|
|
126
|
+
- Configurable permission gates per action
|
|
127
|
+
- View-only mode badge
|
|
128
|
+
|
|
129
|
+
### Developer Tools
|
|
130
|
+
- Hidden dev config panel (Ctrl+Shift+D or `?devpanel=true`)
|
|
131
|
+
- Feature flags: audit, presets, export, permissions
|
|
132
|
+
- Default filter/sort/column overrides for testing
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Tech Stack
|
|
137
|
+
|
|
138
|
+
| Layer | Technology | Version |
|
|
139
|
+
|---|---|---|
|
|
140
|
+
| UI Framework | React | `^18.3.1` |
|
|
141
|
+
| Language | TypeScript | via `@types/react ^18.3.18` |
|
|
142
|
+
| Component Library | Material UI (MUI) | `>=5` |
|
|
143
|
+
| Styling | MUI `sx` prop + Emotion | `>=11` |
|
|
144
|
+
| Drag & Drop | react-dnd + HTML5Backend | `16.0.1` |
|
|
145
|
+
| Export | xlsx (SheetJS) | `^0.18.5` |
|
|
146
|
+
| Build Tool | Vite | `^6.4.2` |
|
|
147
|
+
| Linting | ESLint + TypeScript plugin | — |
|
|
148
|
+
| Formatting | Prettier | — |
|
|
149
|
+
| Git Hooks | Husky + lint-staged | — |
|
|
150
|
+
|
|
151
|
+
**Peer dependencies required in the host app:**
|
|
152
|
+
- `react >= 18`
|
|
153
|
+
- `react-dom >= 18`
|
|
154
|
+
- `@mui/material >= 5`
|
|
155
|
+
- `@emotion/react >= 11`
|
|
156
|
+
- `@emotion/styled >= 11`
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Architecture
|
|
161
|
+
|
|
162
|
+
URM follows a **layered core engine** architecture. All business logic lives in the `core/`
|
|
163
|
+
directory as custom hooks. Components in `app/components/` are purely presentational — they
|
|
164
|
+
receive state and handlers from the engine via React Context, and never manage business logic
|
|
165
|
+
directly.
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
169
|
+
│ Host Application │
|
|
170
|
+
│ │
|
|
171
|
+
│ <URMBuilder /> or <URMViewer /> or <URMProvider /> │
|
|
172
|
+
└───────────────────────┬─────────────────────────────────────┘
|
|
173
|
+
│
|
|
174
|
+
┌───────────────────────▼─────────────────────────────────────┐
|
|
175
|
+
│ ReportProvider (Context) │
|
|
176
|
+
│ Owns all state. Exposes engine via useReportContext(). │
|
|
177
|
+
└───────────────────────┬─────────────────────────────────────┘
|
|
178
|
+
│
|
|
179
|
+
┌───────────────────────▼─────────────────────────────────────┐
|
|
180
|
+
│ UseReportEngine │
|
|
181
|
+
│ Master hook — orchestrates all sub-engines below. │
|
|
182
|
+
│ │
|
|
183
|
+
│ ┌──────────────┐ ┌─────────────┐ ┌───────────────────────┐ │
|
|
184
|
+
│ │UseFilterEngine│ │UseSortEngine│ │ UseGroupingEngine │ │
|
|
185
|
+
│ └──────────────┘ └─────────────┘ └───────────────────────┘ │
|
|
186
|
+
│ ┌──────────────┐ ┌─────────────┐ ┌───────────────────────┐ │
|
|
187
|
+
│ │UseColumnEngine│ │UseViewEngine│ │ UseSearchEngine │ │
|
|
188
|
+
│ └──────────────┘ └─────────────┘ └───────────────────────┘ │
|
|
189
|
+
│ ┌──────────────┐ ┌─────────────┐ │
|
|
190
|
+
│ │UseTableEngine│ │UsePagination│ │
|
|
191
|
+
│ └──────────────┘ └─────────────┘ │
|
|
192
|
+
└───────────────────────┬─────────────────────────────────────┘
|
|
193
|
+
│
|
|
194
|
+
┌───────────────────────▼─────────────────────────────────────┐
|
|
195
|
+
│ UI Components (src/app/components/) │
|
|
196
|
+
│ Pure presentation. No local business logic. │
|
|
197
|
+
│ Read state from context. Call handlers from engine. │
|
|
198
|
+
└─────────────────────────────────────────────────────────────┘
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Data flow:**
|
|
202
|
+
```
|
|
203
|
+
Host provides data → ReportProvider → UseReportEngine processes →
|
|
204
|
+
Context updated → Components re-render with new state
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Folder Structure
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
universal-report-module/
|
|
213
|
+
├── src/
|
|
214
|
+
│ ├── index.ts # Public package API — only export from here
|
|
215
|
+
│ ├── main.tsx # Dev-only entry point (not included in build)
|
|
216
|
+
│ │
|
|
217
|
+
│ ├── app/
|
|
218
|
+
│ │ ├── app.tsx # Dev-only root with URL-based mode routing
|
|
219
|
+
│ │ │
|
|
220
|
+
│ │ ├── components/ # All UI components (44 files)
|
|
221
|
+
│ │ │ ├── data-table.tsx # Core table with all interaction features
|
|
222
|
+
│ │ │ ├── report-viewer.tsx # Orchestrator — renders panels and modals
|
|
223
|
+
│ │ │ ├── filter-panel.tsx # Filter rule management
|
|
224
|
+
│ │ │ ├── sort-panel.tsx # Sort stack management
|
|
225
|
+
│ │ │ ├── group-panel.tsx # Grouping level management
|
|
226
|
+
│ │ │ ├── manage-columns-panel.tsx
|
|
227
|
+
│ │ │ ├── manage-views-panel.tsx
|
|
228
|
+
│ │ │ ├── manage-presets-panel.tsx
|
|
229
|
+
│ │ │ ├── export-config-modal.tsx
|
|
230
|
+
│ │ │ ├── scheduled-reports-modal.tsx
|
|
231
|
+
│ │ │ ├── audit-history-panel.tsx
|
|
232
|
+
│ │ │ ├── error-boundary.tsx
|
|
233
|
+
│ │ │ └── ... # 32 additional focused components
|
|
234
|
+
│ │ │
|
|
235
|
+
│ │ ├── devconfig/ # Developer configuration panel (hidden)
|
|
236
|
+
│ │ │ ├── dev-config-context.ts
|
|
237
|
+
│ │ │ ├── dev-config-modal.tsx
|
|
238
|
+
│ │ │ └── urm-dev-config.ts
|
|
239
|
+
│ │ │
|
|
240
|
+
│ │ ├── modules/ # Public-facing entry surfaces
|
|
241
|
+
│ │ │ ├── builder/
|
|
242
|
+
│ │ │ │ ├── index.tsx # URMBuilder — default export with provider wrap
|
|
243
|
+
│ │ │ │ └── builder.tsx # Builder UI (requires context to be provided)
|
|
244
|
+
│ │ │ └── viewer/
|
|
245
|
+
│ │ │ ├── index.tsx # URMViewer — default export with provider wrap
|
|
246
|
+
│ │ │ ├── viewer.tsx # Viewer UI (requires context to be provided)
|
|
247
|
+
│ │ │ └── urm-viewer.tsx # Alternative viewer export
|
|
248
|
+
│ │ │
|
|
249
|
+
│ │ ├── types/ # TypeScript interfaces and types
|
|
250
|
+
│ │ │ ├── report.ts # Report, View, Filter, SortRule, ColumnSchema, etc.
|
|
251
|
+
│ │ │ ├── data-source.ts # DataSourceConfig, DataLoadState
|
|
252
|
+
│ │ │ ├── grouping.ts # GroupNode (for group tree traversal)
|
|
253
|
+
│ │ │ └── scheduler.ts # ScheduledReport, ScheduleFrequency
|
|
254
|
+
│ │ │
|
|
255
|
+
│ │ └── utils/ # Pure utility functions (no React)
|
|
256
|
+
│ │ ├── logger.ts # Centralised logging (replaces console.*)
|
|
257
|
+
│ │ ├── error-handling.ts # Error classification and recovery logic
|
|
258
|
+
│ │ ├── export.ts # CSV, Excel, JSON export helpers
|
|
259
|
+
│ │ ├── filtering.ts # Filter application logic
|
|
260
|
+
│ │ ├── sorting.ts # Multi-level sort comparators
|
|
261
|
+
│ │ ├── grouping.ts # Data grouping and aggregate calculation
|
|
262
|
+
│ │ ├── schema-detector.ts # JSON schema inference
|
|
263
|
+
│ │ ├── view-helpers.ts # View state diff and snapshot helpers
|
|
264
|
+
│ │ ├── presets.ts # Preset capture, apply, share-link encoding
|
|
265
|
+
│ │ ├── persistence.ts # localStorage read/write for report state
|
|
266
|
+
│ │ ├── audit.ts # Audit event creation and appending
|
|
267
|
+
│ │ ├── use-scheduler-engine.ts # Scheduled report execution hook
|
|
268
|
+
│ │ └── ... # 9 additional utility modules
|
|
269
|
+
│ │
|
|
270
|
+
│ ├── core/ # Engine layer — all business logic hooks
|
|
271
|
+
│ │ ├── index.ts # Core exports
|
|
272
|
+
│ │ ├── report-context.tsx # React Context + Provider
|
|
273
|
+
│ │ ├── use-report-engine.ts # Master orchestration hook (~2000 lines)
|
|
274
|
+
│ │ ├── use-filter-engine.ts
|
|
275
|
+
│ │ ├── use-sort-engine.ts
|
|
276
|
+
│ │ ├── use-grouping-engine.ts
|
|
277
|
+
│ │ ├── use-column-engine.ts
|
|
278
|
+
│ │ ├── use-view-engine.ts
|
|
279
|
+
│ │ ├── use-search-engine.ts
|
|
280
|
+
│ │ ├── use-table-engine.ts
|
|
281
|
+
│ │ └── use-pagination-engine.ts
|
|
282
|
+
│ │
|
|
283
|
+
│ └── styles/
|
|
284
|
+
│ ├── globals.css # Base CSS resets
|
|
285
|
+
│ └── index.css # Entry CSS
|
|
286
|
+
│
|
|
287
|
+
├── eslint.config.js # ESLint rules (TypeScript + React)
|
|
288
|
+
├── .prettierrc # Prettier formatting config
|
|
289
|
+
├── tsconfig.json # TypeScript compiler config (strict mode)
|
|
290
|
+
├── vite.config.ts # Vite build config (lib mode + dev mode)
|
|
291
|
+
├── package.json # Package metadata, scripts, lint-staged
|
|
292
|
+
├── global.d.ts # Global type declarations
|
|
293
|
+
├── index.html # Dev-only HTML entry
|
|
294
|
+
└── .gitignore
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Prerequisites
|
|
300
|
+
|
|
301
|
+
| Requirement | Minimum Version |
|
|
302
|
+
|---|---|
|
|
303
|
+
| Node.js | `>= 18.x` |
|
|
304
|
+
| npm | `>= 9.x` |
|
|
305
|
+
| Git | any recent version |
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## Installation & Setup
|
|
310
|
+
|
|
311
|
+
### 1. Clone the repository
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
git clone https://github.com/Digital-Twin-Operations/universal-report-module.git
|
|
315
|
+
cd universal-report-module
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### 2. Switch to the develop branch
|
|
319
|
+
|
|
320
|
+
All active development happens on `develop`. Never work directly on `main`.
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
git checkout develop
|
|
324
|
+
git pull origin develop
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### 3. Install dependencies
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
npm install
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### 4. Set up environment (if needed)
|
|
334
|
+
|
|
335
|
+
There are no required environment variables for local development of this library.
|
|
336
|
+
If you add one in future, copy `.env.example` and fill values locally:
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
cp .env.example .env
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Never commit `.env` — it is in `.gitignore`.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Running the Development Server
|
|
347
|
+
|
|
348
|
+
The project includes a `main.tsx` and `app.tsx` for local development and testing of
|
|
349
|
+
components without needing a host application.
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
npm run dev
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Open [http://localhost:5173](http://localhost:5173) in your browser.
|
|
356
|
+
|
|
357
|
+
**URL parameters for switching modes:**
|
|
358
|
+
|
|
359
|
+
| URL | What it shows |
|
|
360
|
+
|---|---|
|
|
361
|
+
| `http://localhost:5173` | Builder surface (default) |
|
|
362
|
+
| `http://localhost:5173?mode=viewer` | Viewer surface |
|
|
363
|
+
| `http://localhost:5173?devpanel=true` | Builder + dev config gear icon visible |
|
|
364
|
+
|
|
365
|
+
**Hidden developer panel keyboard shortcut:**
|
|
366
|
+
`Ctrl + Shift + D` — opens the dev config panel in any mode.
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## Building the Library
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
npm run build
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
This produces the distributable package in `dist/`:
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
dist/
|
|
380
|
+
├── index.js # CommonJS build
|
|
381
|
+
├── index.esm.js # ES module build
|
|
382
|
+
└── index.d.ts # TypeScript declarations
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
The build is configured in `vite.config.ts` in library mode. All peer dependencies
|
|
386
|
+
(`react`, `@mui/material`, `@emotion/*`) are externalized and not bundled.
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Environment Configuration
|
|
391
|
+
|
|
392
|
+
| Variable | Description | Example |
|
|
393
|
+
|---|---|---|
|
|
394
|
+
| _(none required)_ | This library has no required env vars | — |
|
|
395
|
+
|
|
396
|
+
If you add environment variables in future:
|
|
397
|
+
- Prefix with `VITE_` for client-side access
|
|
398
|
+
- Document them here and in `.env.example`
|
|
399
|
+
- Never hardcode values in source files
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## Usage — Integrating URM into a Host App
|
|
404
|
+
|
|
405
|
+
### Install the package
|
|
406
|
+
|
|
407
|
+
```bash
|
|
408
|
+
npm install dts-universal-report-module
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Option 1 — Builder (full report creation UI)
|
|
412
|
+
|
|
413
|
+
```tsx
|
|
414
|
+
import { URMBuilder } from 'dts-universal-report-module';
|
|
415
|
+
|
|
416
|
+
function MyPage() {
|
|
417
|
+
return <URMBuilder />;
|
|
418
|
+
}
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### Option 2 — Builder with inline data (skip upload)
|
|
422
|
+
|
|
423
|
+
```tsx
|
|
424
|
+
import { URMBuilder } from 'dts-universal-report-module';
|
|
425
|
+
|
|
426
|
+
function MyPage() {
|
|
427
|
+
const data = [
|
|
428
|
+
{ id: 1, name: 'Device A', status: 'online', temperature: 72.4 },
|
|
429
|
+
{ id: 2, name: 'Device B', status: 'offline', temperature: 68.1 },
|
|
430
|
+
];
|
|
431
|
+
|
|
432
|
+
return <URMBuilder data={data} reportName="Device Status" />;
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Option 3 — Builder with API data source
|
|
437
|
+
|
|
438
|
+
```tsx
|
|
439
|
+
import { URMBuilder } from 'dts-universal-report-module';
|
|
440
|
+
|
|
441
|
+
function MyPage() {
|
|
442
|
+
return (
|
|
443
|
+
<URMBuilder
|
|
444
|
+
dataSource={{
|
|
445
|
+
type: 'api',
|
|
446
|
+
url: '/api/v1/devices/readings',
|
|
447
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
448
|
+
refreshInterval: 30000, // auto-refresh every 30 seconds
|
|
449
|
+
}}
|
|
450
|
+
reportName="Live Device Readings"
|
|
451
|
+
/>
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Option 4 — Viewer (read-only, data from host)
|
|
457
|
+
|
|
458
|
+
```tsx
|
|
459
|
+
import { URMViewer } from 'dts-universal-report-module';
|
|
460
|
+
|
|
461
|
+
function Dashboard() {
|
|
462
|
+
const data = useSelector(selectDeviceData);
|
|
463
|
+
|
|
464
|
+
return <URMViewer data={data} />;
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Option 5 — Custom layout with URMProvider
|
|
469
|
+
|
|
470
|
+
For full control over the layout, use the provider directly:
|
|
471
|
+
|
|
472
|
+
```tsx
|
|
473
|
+
import { URMProvider, useURMContext } from 'dts-universal-report-module';
|
|
474
|
+
|
|
475
|
+
function CustomReport() {
|
|
476
|
+
const engine = useURMContext();
|
|
477
|
+
return (
|
|
478
|
+
<div>
|
|
479
|
+
<MyCustomHeader reportCount={engine.reports.length} />
|
|
480
|
+
{/* render your own layout using engine state */}
|
|
481
|
+
</div>
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function App() {
|
|
486
|
+
return (
|
|
487
|
+
<URMProvider mode="builder" data={myData}>
|
|
488
|
+
<CustomReport />
|
|
489
|
+
</URMProvider>
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
## Data Source Options
|
|
497
|
+
|
|
498
|
+
| Type | Props | Auto-refresh |
|
|
499
|
+
|---|---|---|
|
|
500
|
+
| JSON file upload | _(no props needed)_ | No |
|
|
501
|
+
| Inline array | `data={myArray}` | No |
|
|
502
|
+
| API endpoint | `dataSource={{ type: 'api', url: '...' }}` | Yes (optional) |
|
|
503
|
+
| Async callback | `dataSource={{ type: 'callback', fetch: async () => data }}` | Yes (optional) |
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
## Public API Reference
|
|
508
|
+
|
|
509
|
+
All public exports are defined in `src/index.ts`.
|
|
510
|
+
|
|
511
|
+
### Components
|
|
512
|
+
|
|
513
|
+
| Export | Description |
|
|
514
|
+
|---|---|
|
|
515
|
+
| `URMBuilder` | Full report creation + management surface |
|
|
516
|
+
| `URMViewer` | Embedded read-only viewer |
|
|
517
|
+
| `URMBuilderRaw` | Builder without provider wrap — bring your own `URMProvider` |
|
|
518
|
+
| `URMViewerRaw` | Viewer without provider wrap — bring your own `URMProvider` |
|
|
519
|
+
| `URMProvider` | React context provider — use for custom layouts |
|
|
520
|
+
|
|
521
|
+
### Hooks
|
|
522
|
+
|
|
523
|
+
| Export | Description |
|
|
524
|
+
|---|---|
|
|
525
|
+
| `useURMContext` | Access full engine state and handlers inside `URMProvider` |
|
|
526
|
+
|
|
527
|
+
### Types
|
|
528
|
+
|
|
529
|
+
| Export | Description |
|
|
530
|
+
|---|---|
|
|
531
|
+
| `Report` | Full report object shape |
|
|
532
|
+
| `DataSourceConfig` | Union type for API and callback data sources |
|
|
533
|
+
| `DataLoadState` | `'idle' \| 'loading' \| 'ready' \| 'error' \| 'refreshing'` |
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
537
|
+
## Branching Strategy
|
|
538
|
+
|
|
539
|
+
| Branch | Purpose | Rules |
|
|
540
|
+
|---|---|---|
|
|
541
|
+
| `main` | Production-ready builds | Never commit directly. Merge from `develop` only when releasing. |
|
|
542
|
+
| `develop` | Active development | All feature work merges here. Always deployable. |
|
|
543
|
+
| `feature/*` | New features | Branch from `develop`. Merge back to `develop` via PR. |
|
|
544
|
+
| `bugfix/*` | Non-critical bug fixes | Branch from `develop`. Merge back to `develop`. |
|
|
545
|
+
| `hotfix/*` | Urgent production fixes | Branch from `main`. Merge to both `main` and `develop`. |
|
|
546
|
+
|
|
547
|
+
**Creating a feature branch:**
|
|
548
|
+
```bash
|
|
549
|
+
git checkout develop
|
|
550
|
+
git pull origin develop
|
|
551
|
+
git checkout -b feature/urm-123-short-description
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
**Merging back to develop:**
|
|
555
|
+
```bash
|
|
556
|
+
git checkout develop
|
|
557
|
+
git merge feature/urm-123-short-description
|
|
558
|
+
git push origin develop
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## Commit Message Format
|
|
564
|
+
|
|
565
|
+
All commits must follow **Conventional Commits** format:
|
|
566
|
+
|
|
567
|
+
```
|
|
568
|
+
type(scope): short description in imperative mood
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
| Type | When to use |
|
|
572
|
+
|---|---|
|
|
573
|
+
| `feat` | New feature or capability |
|
|
574
|
+
| `fix` | Bug fix |
|
|
575
|
+
| `refactor` | Code restructure with no behaviour change |
|
|
576
|
+
| `docs` | Documentation only |
|
|
577
|
+
| `chore` | Tooling, dependencies, config |
|
|
578
|
+
| `test` | Tests added or updated |
|
|
579
|
+
| `perf` | Performance improvement |
|
|
580
|
+
|
|
581
|
+
**Examples:**
|
|
582
|
+
|
|
583
|
+
```bash
|
|
584
|
+
git commit -m "feat(export): add JSON export option to export config modal"
|
|
585
|
+
git commit -m "fix(filter): resolve null crash when filter value is empty string"
|
|
586
|
+
git commit -m "refactor(structure): rename all files to kebab-case convention"
|
|
587
|
+
git commit -m "docs(readme): add complete project overview and developer guide"
|
|
588
|
+
git commit -m "chore(toolchain): add eslint, prettier, and husky configuration"
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
**Rules:**
|
|
592
|
+
- Subject line max 72 characters
|
|
593
|
+
- Use imperative mood: "add", "fix", "update" — not "added", "fixes"
|
|
594
|
+
- Scope = the module or area affected
|
|
595
|
+
|
|
596
|
+
---
|
|
597
|
+
|
|
598
|
+
## Code Standards
|
|
599
|
+
|
|
600
|
+
This project follows the **MERN Engineering Standards v1.0** document.
|
|
601
|
+
Key rules enforced by ESLint and Prettier:
|
|
602
|
+
|
|
603
|
+
- All file names: `kebab-case` (e.g. `data-table.tsx`)
|
|
604
|
+
- All folder names: `kebab-case` (e.g. `modules/builder/`)
|
|
605
|
+
- React component names: `PascalCase` (export name inside the file)
|
|
606
|
+
- Hook names: `camelCase` with `use` prefix
|
|
607
|
+
- No `console.log` — use `logger` from `src/app/utils/logger.ts`
|
|
608
|
+
- No `console.error` or `console.warn` directly — use `logger`
|
|
609
|
+
- No inline `style={{}}` — use MUI `sx` prop
|
|
610
|
+
- No hardcoded colour values — use MUI theme tokens
|
|
611
|
+
- No function longer than 80 lines
|
|
612
|
+
- No commented-out dead code
|
|
613
|
+
- All code through `develop` branch — never commit to `main`
|
|
614
|
+
|
|
615
|
+
---
|
|
616
|
+
|
|
617
|
+
## Developer Notes
|
|
618
|
+
|
|
619
|
+
### Why is UseReportEngine.ts so large?
|
|
620
|
+
|
|
621
|
+
`use-report-engine.ts` (~2,000 lines) is the master orchestration hook. It intentionally
|
|
622
|
+
centralises all state management and handler definitions in one place so that the
|
|
623
|
+
`ReportContext` can expose a single, stable API to all components. This is a known area
|
|
624
|
+
for future decomposition — the sub-engines (`use-filter-engine`, `use-sort-engine`, etc.)
|
|
625
|
+
are already extracted; the remaining work is to move more handler logic into them.
|
|
626
|
+
|
|
627
|
+
### Why does the build externalise so many dependencies?
|
|
628
|
+
|
|
629
|
+
URM is designed to be embedded in host applications that already have React and MUI installed.
|
|
630
|
+
Bundling them again would cause version conflicts and bloat the package. All peer dependencies
|
|
631
|
+
are listed in `package.json > peerDependencies` and must be present in the host app.
|
|
632
|
+
|
|
633
|
+
### Dev panel
|
|
634
|
+
|
|
635
|
+
The developer configuration panel is deliberately hidden from production UI. It can be
|
|
636
|
+
accessed via `Ctrl+Shift+D` or the `?devpanel=true` URL parameter. It allows toggling
|
|
637
|
+
feature flags, setting default filter/sort/column configs, and simulating different user roles.
|
|
638
|
+
It is excluded from the published package build.
|
|
639
|
+
|
|
640
|
+
### Adding a new utility
|
|
641
|
+
|
|
642
|
+
1. Create the file in `src/app/utils/` with a `kebab-case` name
|
|
643
|
+
2. Export only what other files need
|
|
644
|
+
3. Import using relative paths, e.g. `import { myUtil } from '../utils/my-util'`
|
|
645
|
+
4. If it needs logging, import from `./logger`
|
|
646
|
+
|
|
647
|
+
### Adding a new component
|
|
648
|
+
|
|
649
|
+
1. Create the file in `src/app/components/` with a `kebab-case` name
|
|
650
|
+
2. Export the component as a named export using `PascalCase`
|
|
651
|
+
3. Do not manage business logic inside components — use `useReportContext()`
|
|
652
|
+
4. Do not use `style={{}}` — use MUI `sx` prop only
|