bways-report 0.1.5 → 0.1.7

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.
Files changed (107) hide show
  1. package/README.md +291 -422
  2. package/esm2022/lib/core/config/bways-report-config.mjs +83 -0
  3. package/esm2022/lib/core/index.mjs +2 -1
  4. package/esm2022/lib/core/models/report-definition.model.mjs +1 -1
  5. package/esm2022/lib/core/services/index.mjs +2 -1
  6. package/esm2022/lib/core/services/report-data-discovery.service.mjs +138 -0
  7. package/esm2022/lib/core/services/report-session-context.service.mjs +11 -7
  8. package/esm2022/lib/core/tokens/reporting-config.token.mjs +1 -1
  9. package/esm2022/lib/core/utils/data-normalization.util.mjs +87 -1
  10. package/esm2022/lib/core/utils/identifier-humanizer.mjs +15 -4
  11. package/esm2022/lib/core/utils/report-parameter.util.mjs +119 -3
  12. package/esm2022/lib/data-access/adapters/endpoint-datasource.adapter.mjs +69 -0
  13. package/esm2022/lib/data-access/adapters/endpoint-lookup.adapter.mjs +98 -0
  14. package/esm2022/lib/data-access/adapters/endpoint-masterdata.adapter.mjs +57 -0
  15. package/esm2022/lib/data-access/adapters/endpoint-persistence.adapter.mjs +85 -0
  16. package/esm2022/lib/data-access/adapters/endpoint-schema-discovery.adapter.mjs +163 -0
  17. package/esm2022/lib/data-access/adapters/endpoint-tokens.mjs +12 -0
  18. package/esm2022/lib/data-access/adapters/http-lookup.adapter.mjs +20 -30
  19. package/esm2022/lib/data-access/adapters/index.mjs +8 -1
  20. package/esm2022/lib/data-access/contracts/lookup.contract.mjs +1 -1
  21. package/esm2022/lib/features/designer/components/component-palette/component-palette.component.mjs +12 -2
  22. package/esm2022/lib/features/designer/components/design-canvas/design-canvas.component.mjs +71 -13
  23. package/esm2022/lib/features/designer/components/dialogs/report-saved-dialog.component.mjs +407 -0
  24. package/esm2022/lib/features/designer/components/property-editor/parameter-binding-editor.component.mjs +403 -222
  25. package/esm2022/lib/features/designer/components/property-editor/property-editor-action.component.mjs +41 -34
  26. package/esm2022/lib/features/designer/components/property-editor/property-editor-datasource.component.mjs +142 -20
  27. package/esm2022/lib/features/designer/components/property-editor/property-editor-general.component.mjs +3 -3
  28. package/esm2022/lib/features/designer/components/property-editor/property-editor-grid.component.mjs +154 -5
  29. package/esm2022/lib/features/designer/components/property-editor/property-editor-layout.component.mjs +11 -5
  30. package/esm2022/lib/features/designer/components/property-editor/property-editor-report.component.mjs +3 -3
  31. package/esm2022/lib/features/designer/components/property-editor/property-editor-validation.component.mjs +15 -3
  32. package/esm2022/lib/features/designer/components/property-editor/property-editor.component.mjs +112 -39
  33. package/esm2022/lib/features/designer/components/toolbar/designer-toolbar.component.mjs +204 -10
  34. package/esm2022/lib/features/designer/designer.component.mjs +44 -3
  35. package/esm2022/lib/features/designer/services/designer-state.service.mjs +70 -3
  36. package/esm2022/lib/features/embed/bways-report-builder.component.mjs +207 -0
  37. package/esm2022/lib/features/embed/bways-report-menu.component.mjs +433 -0
  38. package/esm2022/lib/features/embed/bways-report-page.component.mjs +204 -0
  39. package/esm2022/lib/features/embed/index.mjs +5 -0
  40. package/esm2022/lib/features/embed/inject-report-menu.mjs +99 -0
  41. package/esm2022/lib/features/index.mjs +2 -1
  42. package/esm2022/lib/features/persistence/services/report-store.service.mjs +43 -5
  43. package/esm2022/lib/features/routing/components/routed-report-runtime.component.mjs +4 -4
  44. package/esm2022/lib/features/routing/index.mjs +2 -2
  45. package/esm2022/lib/features/routing/models/report-route.models.mjs +1 -1
  46. package/esm2022/lib/features/routing/report-routes.mjs +42 -1
  47. package/esm2022/lib/features/routing/resolvers/report.resolver.mjs +6 -8
  48. package/esm2022/lib/features/routing/services/report-menu.service.mjs +14 -4
  49. package/esm2022/lib/features/runtime/dynamic-renderer.component.mjs +22 -3
  50. package/esm2022/lib/features/runtime/report-grid-bridge.component.mjs +121 -15
  51. package/esm2022/lib/primitives/components/button/rpt-button.component.mjs +28 -5
  52. package/esm2022/lib/primitives/components/dropdown/rpt-dropdown.component.mjs +113 -20
  53. package/esm2022/lib/primitives/components/icon/rpt-icon.component.mjs +8 -1
  54. package/esm2022/lib/primitives/components/index.mjs +2 -1
  55. package/esm2022/lib/primitives/components/number/rpt-number.component.mjs +9 -3
  56. package/esm2022/lib/primitives/components/searchable-select/rpt-searchable-select.component.mjs +386 -0
  57. package/esm2022/lib/provide-reporting.mjs +156 -11
  58. package/fesm2022/bways-report.mjs +5703 -1766
  59. package/fesm2022/bways-report.mjs.map +1 -1
  60. package/lib/core/config/bways-report-config.d.ts +161 -0
  61. package/lib/core/index.d.ts +1 -0
  62. package/lib/core/models/report-definition.model.d.ts +16 -0
  63. package/lib/core/services/index.d.ts +1 -0
  64. package/lib/core/services/report-data-discovery.service.d.ts +38 -0
  65. package/lib/core/services/report-session-context.service.d.ts +1 -0
  66. package/lib/core/tokens/reporting-config.token.d.ts +18 -0
  67. package/lib/core/utils/data-normalization.util.d.ts +10 -0
  68. package/lib/core/utils/report-parameter.util.d.ts +18 -1
  69. package/lib/data-access/adapters/endpoint-datasource.adapter.d.ts +13 -0
  70. package/lib/data-access/adapters/endpoint-lookup.adapter.d.ts +14 -0
  71. package/lib/data-access/adapters/endpoint-masterdata.adapter.d.ts +11 -0
  72. package/lib/data-access/adapters/endpoint-persistence.adapter.d.ts +15 -0
  73. package/lib/data-access/adapters/endpoint-schema-discovery.adapter.d.ts +21 -0
  74. package/lib/data-access/adapters/endpoint-tokens.d.ts +21 -0
  75. package/lib/data-access/adapters/http-lookup.adapter.d.ts +2 -1
  76. package/lib/data-access/adapters/index.d.ts +7 -0
  77. package/lib/data-access/contracts/lookup.contract.d.ts +2 -2
  78. package/lib/features/designer/components/component-palette/component-palette.component.d.ts +1 -0
  79. package/lib/features/designer/components/design-canvas/design-canvas.component.d.ts +6 -2
  80. package/lib/features/designer/components/dialogs/report-saved-dialog.component.d.ts +34 -0
  81. package/lib/features/designer/components/property-editor/parameter-binding-editor.component.d.ts +6 -0
  82. package/lib/features/designer/components/property-editor/property-editor-action.component.d.ts +3 -0
  83. package/lib/features/designer/components/property-editor/property-editor-datasource.component.d.ts +12 -2
  84. package/lib/features/designer/components/property-editor/property-editor-grid.component.d.ts +41 -1
  85. package/lib/features/designer/components/property-editor/property-editor.component.d.ts +19 -0
  86. package/lib/features/designer/components/toolbar/designer-toolbar.component.d.ts +13 -1
  87. package/lib/features/designer/designer.component.d.ts +4 -0
  88. package/lib/features/designer/services/designer-state.service.d.ts +12 -1
  89. package/lib/features/embed/bways-report-builder.component.d.ts +48 -0
  90. package/lib/features/embed/bways-report-menu.component.d.ts +40 -0
  91. package/lib/features/embed/bways-report-page.component.d.ts +61 -0
  92. package/lib/features/embed/index.d.ts +4 -0
  93. package/lib/features/embed/inject-report-menu.d.ts +44 -0
  94. package/lib/features/index.d.ts +1 -0
  95. package/lib/features/persistence/services/report-store.service.d.ts +5 -0
  96. package/lib/features/routing/index.d.ts +1 -1
  97. package/lib/features/routing/models/report-route.models.d.ts +3 -0
  98. package/lib/features/routing/report-routes.d.ts +40 -0
  99. package/lib/features/routing/resolvers/report.resolver.d.ts +1 -1
  100. package/lib/features/runtime/dynamic-renderer.component.d.ts +1 -0
  101. package/lib/features/runtime/report-grid-bridge.component.d.ts +8 -59
  102. package/lib/primitives/components/button/rpt-button.component.d.ts +3 -0
  103. package/lib/primitives/components/dropdown/rpt-dropdown.component.d.ts +18 -2
  104. package/lib/primitives/components/index.d.ts +2 -0
  105. package/lib/primitives/components/searchable-select/rpt-searchable-select.component.d.ts +89 -0
  106. package/lib/provide-reporting.d.ts +28 -6
  107. package/package.json +1 -1
package/README.md CHANGED
@@ -1,572 +1,441 @@
1
1
  # BWays-Report — Integration & Developer Guide
2
2
 
3
- `bways-report` is an enterprise-grade, metadata-driven reporting platform and visual dynamic page builder for Angular 18+ business & ERP applications.
3
+ `bways-report` is an enterprise reporting platform and visual drag-and-drop page builder for Angular 18+ business & ERP applications with NestJS / SQL Server.
4
4
 
5
- It allows non-developers to visually design reporting pages with filters, KPI metric cards, charts, and grids. The report configuration is saved purely as JSON metadata (`ReportDefinition`), and the runtime engine dynamically instantiates the reactive forms, controls, data queries, and results grid on the fly.
5
+ It empowers developers and business users to visually design reporting pages with filters, lookup dropdowns, metric cards, charts, and data grids. Report configurations are saved as clean JSON metadata (`ReportDefinition`), and the runtime engine dynamically generates reactive forms, controls, queries, and live grid views on the fly.
6
6
 
7
7
  ---
8
8
  [![npm version](https://img.shields.io/npm/v/bways-report.svg)](https://www.npmjs.com/package/bways-report)
9
- [![license](https://img.shields.io/npm/l/bways-report.svg)](https://github.com/ccplProject/BWays-CustomeReport)
9
+ [![license](https://img.shields.io/badge/License-Proprietary-blue.svg)](LICENSE)
10
+ [![Changelog](https://img.shields.io/badge/Changelog-v0.2.0-blue.svg)](CHANGELOG.md)
11
+ ---
12
+
13
+ ## What's New in v0.2.0
14
+
15
+ - **1 Config Object + 3 Drop-in Components**: Eliminate boilerplate adapters with `BwaysReportConfig` and drop-in tags.
16
+ - **`<bways-report-builder>`**: Drop-in visual designer shell with width/height controls, starter blueprints, and save flow.
17
+ - **`<bways-report-page>`**: Live runtime form & dynamic grid page rendered automatically from a report slug.
18
+ - **`<bways-report-menu>` & `injectReportMenu()`**: Responsive navigation menu (sidebar, navbar, dropdown) with search and category folding.
19
+ - **`bwaysReportRoutes()`**: Declarative Angular routing for live report pages (`/reports/:slug`).
20
+ - **Post-Save Interactive Modal**: Immediate live form preview with page routing settings (slug, menu group, publish toggle).
21
+ - **CDK Overlay Viewport Flipping**: Zero clipping for searchable dropdowns inside cards and scroll containers.
22
+ - **Quick Action ("+") & Inline Renaming**: Double-click report title to rename in place; `+` button to start fresh pages.
23
+
10
24
  ---
11
25
 
12
26
  ## Table of Contents
13
27
 
14
- 1. [Automated Setup (ng add)](#1-automated-setup-ng-add)
15
- 2. [Quick Start (Rule of 1)](#2-quick-start-rule-of-1)
16
- - [A. 1-Line App Setup](#a-1-line-app-setup)
17
- - [B. 1-Tag Runtime Page](#b-1-tag-runtime-page)
18
- - [C. 1-Tag Visual Report Designer](#c-1-tag-visual-report-designer)
19
- - [D. Saved Views & Presets in JSON](#d-saved-views--presets-in-json)
20
- 3. [Configuration Options & Zero-Backend Dev](#3-configuration-options--zero-backend-dev)
21
- 4. [Implementing Host Adapters (Advanced)](#4-implementing-host-adapters)
22
- - [A. Data Source Adapter (Query Execution)](#a-data-source-adapter)
23
- - [B. Persistence Adapter (Saving & Loading Reports)](#b-persistence-adapter)
24
- - [C. Master Data Provider (Dropdown Lookups)](#c-master-data-provider)
25
- 5. [Routing & ERP Navigation Integration](#5-routing--erp-navigation-integration)
26
- 6. [Drill-Down Drill-Through & Slide-Over Drawers](#6-drill-down--slide-over-drawers)
27
- 7. [Starter Blueprints Gallery & Branded Exports](#7-starter-blueprints--branded-exports)
28
+ 1. [Quick Start (5 Steps)](#1-quick-start-5-steps)
29
+ - [Step 1: Install](#step-1-install)
30
+ - [Step 2: Configure Once (`app.config.ts`)](#step-2-configure-once-appconfigts)
31
+ - [Step 3: Drop-in Builder Component](#step-3-drop-in-builder-component)
32
+ - [Step 4: Host Navigation Menu](#step-4-host-navigation-menu)
33
+ - [Step 5: Declarative Routes (`app.routes.ts`)](#step-5-declarative-routes-approutests)
34
+ 2. [Visual Designer Features](#2-visual-designer-features)
35
+ - [Single-Mode Technical Property Editor](#single-mode-technical-property-editor)
36
+ - [CDK Overlay Viewport Flip](#cdk-overlay-viewport-flip)
37
+ - [Post-Save Live Preview & Settings Dialog](#post-save-live-preview--settings-dialog)
38
+ - [Inline Double-Click Renaming](#inline-double-click-renaming)
39
+ - [Report Switcher & Quick New Page ("+")](#report-switcher--quick-new-page-)
40
+ 3. [Backend Contract Reference](#3-backend-contract-reference)
41
+ 4. [Dynamic Session Context & Auto-Parameter Binding](#4-dynamic-session-context--auto-parameter-binding)
42
+ 5. [Plugging in BWays-Grid (`UltraGridComponent`)](#5-plugging-in-bways-grid-ultragridcomponent)
43
+ 6. [Advanced Custom Adapters](#6-advanced-custom-adapters)
44
+ 7. [Theming & CSS Custom Properties](#7-theming--css-custom-properties)
45
+ 8. [Exporting Data (CSV & JSON)](#8-exporting-data-csv--json)
28
46
 
29
47
  ---
30
48
 
31
- ## 1. Automated Setup (ng add)
49
+ ## 1. Quick Start (5 Steps)
32
50
 
33
- Run the Angular CLI schematic to configure your application in seconds:
51
+ ### Step 1: Install
34
52
 
35
53
  ```bash
36
- ng add bways-report
54
+ npm install bways-report bways-grid @angular/cdk
37
55
  ```
38
56
 
39
- This automatically installs required dependencies and adds `provideReporting()` to your `src/app/app.config.ts`.
57
+ > **Compatibility**: Angular 18+ or 19+ standalone architecture with Zone.js or Zoneless change detection.
40
58
 
41
59
  ---
42
60
 
43
- ## 2. Quick Start (Rule of 1)
44
-
45
- ### A. 1-Line App Setup
61
+ ### Step 2: Configure Once (`app.config.ts`)
46
62
 
47
- In your Angular 18+ application:
63
+ Configure `provideBwaysReport()` with a single `BwaysReportConfig` object:
48
64
 
49
65
  ```typescript
50
66
  // src/app/app.config.ts
51
- import { ApplicationConfig } from '@angular/core';
52
- import { provideReporting } from 'bways-report';
67
+ import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
68
+ import { provideHttpClient } from '@angular/common/http';
69
+ import { provideRouter } from '@angular/router';
70
+ import { provideBwaysReport, BwaysReportConfig } from 'bways-report';
71
+ import { UltraGridComponent } from 'bways-grid';
72
+ import { routes } from './app.routes';
73
+ import { AuthService } from './services/auth.service';
74
+
75
+ const reportConfig: BwaysReportConfig = {
76
+ // Backend Endpoints (only these 3-4 URLs needed)
77
+ spEndpoint: 'http://localhost:3000/api/reporting/procedures', // GET -> SPs + parameters
78
+ tablesEndpoint: 'http://localhost:3000/api/reporting/tables', // GET -> Tables + columns
79
+ executeEndpoint: 'http://localhost:3000/api/reporting/execute', // POST -> Query / SP execution
80
+ lookupEndpoint: 'http://localhost:3000/api/reporting/lookup', // POST -> Dropdown master data / lookup (optional)
81
+ reportsEndpoint: 'http://localhost:3000/api/reporting/reports', // Optional CRUD (defaults to localStorage)
82
+
83
+ // Visual Designer Configuration
84
+ components: ['formInputs', 'actionButtons', 'displayLabels'], // Palette categories to show (default: all)
85
+ autoParameter: true, // Auto-bind @BranchId, @CompanyId from session
86
+ session: () => inject(AuthService).currentSession(), // Session source for autoParameter
87
+
88
+ // Live Pages & Data Grid
89
+ routeBase: 'reports', // Live pages mount at /reports/:slug
90
+ grid: UltraGridComponent, // UltraGrid from bways-grid (or built-in table)
91
+ defaultPageSize: 25,
92
+ };
53
93
 
54
94
  export const appConfig: ApplicationConfig = {
55
95
  providers: [
56
- // 1-line setup: automatically hooks up HTTP adapters, UltraGridComponent, and session headers
57
- provideReporting({ apiBaseUrl: '/api/reporting' }),
96
+ provideZoneChangeDetection({ eventCoalescing: true }),
97
+ provideHttpClient(),
98
+ provideRouter(routes),
99
+ provideBwaysReport(reportConfig),
58
100
  ],
59
101
  };
60
102
  ```
61
103
 
62
- > **Zero-Backend / Local Storage Mode:**
63
- > For local prototyping, offline demos, or frontend-only dev, use:
64
- > ```typescript
65
- > provideReporting(withLocalStorage()); // seeds built-in blueprints and saves to browser localStorage
66
- > ```
67
-
68
104
  ---
69
105
 
70
- ### B. 1-Tag Runtime Page
106
+ ### Step 3: Drop-in Builder Component
107
+
108
+ Embed the full visual drag-and-drop report designer with one HTML tag:
71
109
 
72
- Render any saved report with its dynamic filter form, auto-bound stored procedure results, top toolbar, export actions, and saved view presets:
110
+ ```html
111
+ <!-- src/app/pages/admin-reports/admin-reports.component.html -->
112
+ <bways-report-builder
113
+ width="100%"
114
+ height="calc(100vh - 64px)"
115
+ (saved)="onReportSaved($event)"
116
+ />
117
+ ```
73
118
 
74
119
  ```typescript
120
+ // src/app/pages/admin-reports/admin-reports.component.ts
75
121
  import { Component } from '@angular/core';
76
- import { RptReportComponent } from 'bways-report';
122
+ import { BwaysReportBuilderComponent, ReportDefinition } from 'bways-report';
77
123
 
78
124
  @Component({
79
125
  standalone: true,
80
- imports: [RptReportComponent],
81
- template: `
82
- <!-- 1 tag to run and render the full report page -->
83
- <rpt-report [id]="'sales-ledger'" />
84
- `,
126
+ imports: [BwaysReportBuilderComponent],
127
+ templateUrl: './admin-reports.component.html',
85
128
  })
86
- export class SalesReportPage {}
129
+ export class AdminReportsComponent {
130
+ onReportSaved(report: ReportDefinition): void {
131
+ console.log('Report saved and published:', report.name, report.slug);
132
+ }
133
+ }
87
134
  ```
88
135
 
89
136
  ---
90
137
 
91
- ### C. 1-Tag Visual Report Designer
138
+ ### Step 4: Host Navigation Menu
92
139
 
93
- Embed the full drag-and-drop report builder into your ERP settings or admin portal:
140
+ Display published reports in your host ERP navigation bar or sidebar:
94
141
 
142
+ #### Option A: Drop-in Component
143
+ ```html
144
+ <!-- Sidebar variant with search filter and category folding -->
145
+ <bways-report-menu variant="sidebar" />
146
+
147
+ <!-- Or dropdown variant for top navigation bars -->
148
+ <bways-report-menu variant="dropdown" />
149
+ ```
150
+
151
+ #### Option B: Reactive Signal (`injectReportMenu`)
95
152
  ```typescript
96
153
  import { Component } from '@angular/core';
97
- import { RptReportDesignerComponent } from 'bways-report';
154
+ import { RouterLink, RouterLinkActive } from '@angular/router';
155
+ import { injectReportMenu } from 'bways-report';
98
156
 
99
157
  @Component({
100
158
  standalone: true,
101
- imports: [RptReportDesignerComponent],
159
+ imports: [RouterLink, RouterLinkActive],
102
160
  template: `
103
- <!-- 1 tag to build, preview, or modify any report -->
104
- <rpt-report-designer
105
- [id]="'sales-ledger'"
106
- (saved)="onReportSaved($event)"
107
- />
161
+ <nav class="erp-menu">
162
+ @for (group of menu(); track group.groupName) {
163
+ <div class="menu-group">
164
+ <h3>{{ group.groupName }}</h3>
165
+ @for (item of group.items; track item.id) {
166
+ <a [routerLink]="item.route" routerLinkActive="active">
167
+ {{ item.name }}
168
+ </a>
169
+ }
170
+ </div>
171
+ }
172
+ </nav>
108
173
  `,
109
174
  })
110
- export class ReportBuilderPage {
111
- onReportSaved(definition: any) {
112
- console.log('Report saved successfully:', definition);
113
- }
175
+ export class NavigationSidebarComponent {
176
+ readonly menu = injectReportMenu();
114
177
  }
115
178
  ```
116
179
 
117
180
  ---
118
181
 
119
- ### D. Saved Views & Presets in JSON
182
+ ### Step 5: Declarative Routes (`app.routes.ts`)
120
183
 
121
- When users filter, reorder, group, or format columns in the grid, they can click **"+ Save View"** to persist their customized view preset. Presets are saved directly into the report's JSON:
122
-
123
- ```json
124
- {
125
- "grid": {
126
- "dataSourceId": "ds-sales",
127
- "columns": [...],
128
- "options": {
129
- "presets": [
130
- {
131
- "id": "preset_1728200000",
132
- "name": "Q3 High Value Clients",
133
- "gridState": {
134
- "filters": { "amount": { "operator": "gte", "value": 50000 } },
135
- "columnOrder": ["invoiceId", "amount", "customerName"]
136
- }
137
- }
138
- ]
139
- }
140
- }
141
- }
142
- ```
143
- Users can switch between views seamlessly from the top dropdown, keeping all formatting and custom filters intact.
144
-
145
- ---
146
-
147
- ### Backend Integration: Mounting `BwaysReportingModule` in NestJS
148
-
149
- To power the built-in HTTP adapters, mount `BwaysReportingModule` directly inside your existing NestJS host application:
184
+ Add one line to your route definitions to enable dynamic live report pages:
150
185
 
151
186
  ```typescript
152
- // app.module.ts (in your NestJS backend)
153
- import { Module } from '@nestjs/common';
154
- import { BwaysReportingModule } from '@bways/reporting-backend';
155
-
156
- @Module({
157
- imports: [
158
- BwaysReportingModule.forRoot({
159
- security: {
160
- allowedSchemas: ['dbo', 'reporting'],
161
- disallowRawSql: true, // SQL injection prevention
162
- validateEntitiesAgainstCatalog: true, // Checks sys.procedures catalog
163
- },
164
- }),
165
- ],
166
- })
167
- export class AppModule {}
168
- ```
169
-
170
- ---
171
-
172
- ### Option B: Custom Adapters (Full Manual Control)
187
+ // src/app/app.routes.ts
188
+ import { Routes } from '@angular/router';
189
+ import { bwaysReportRoutes } from 'bways-report';
190
+ import { AdminReportsComponent } from './pages/admin-reports/admin-reports.component';
173
191
 
174
- If you don't use the standard backend endpoints, you can implement your own adapters:
192
+ export const routes: Routes = [
193
+ // Admin visual designer route
194
+ { path: 'admin/reports', component: AdminReportsComponent },
175
195
 
176
- ```typescript
177
- export const appConfig: ApplicationConfig = {
178
- providers: [
179
- provideZoneChangeDetection({ eventCoalescing: true }),
180
- provideRouter(routes),
181
- provideBwaysReport({
182
- gridComponent: BWaysGridComponent,
183
- dataSourceAdapter: MyCustomDataSourceAdapter,
184
- persistenceAdapter: MyCustomPersistenceAdapter,
185
- masterDataProvider: MyCustomMasterDataProvider,
186
- defaultPageSize: 25,
187
- enableDesigner: true,
196
+ // Live user reporting pages: /reports/:slug (e.g. /reports/sale-report)
197
+ {
198
+ path: 'reports',
199
+ children: bwaysReportRoutes({
200
+ // includeBuilderRoute: false, // Set true to include /reports/new and /reports/:slug/edit
188
201
  }),
189
- ],
190
- };
202
+ },
203
+ ];
191
204
  ```
192
205
 
206
+ When users click "Sale Report" in the menu, `/reports/sale-report` opens the **live interactive form** with reactive inputs and data grid without needing custom page components!
207
+
193
208
  ---
194
209
 
195
- ## 3. Implementing Host Adapters
210
+ ## 2. Visual Designer Features
196
211
 
197
- The library is decoupled from your backend. You provide your business application's API handlers by extending three abstract contracts:
212
+ ### Single-Mode Technical Property Editor
213
+ Eliminates confusing simplified/advanced toggles. Standardized on technical database terminology:
214
+ - `Database Table / View`
215
+ - `Stored Proc`
216
+ - `Display Field (Visible Text)`
217
+ - `Value Field (Stored Key)`
218
+ - `Dependent On (Cascading Parent Field)`
198
219
 
199
- ### A. Data Source Adapter
220
+ ### CDK Overlay Viewport Flip
221
+ Searchable selects (`<rpt-searchable-select>`) and comboboxes (`<rpt-dropdown>`) render inside Angular CDK Overlays attached to the document body. They automatically evaluate available viewport space and flip between `below-start`, `above-start`, `below-end`, and `above-end` to eliminate clipping inside cards and scrollable drawers.
200
222
 
201
- Responsible for executing report queries and returning tabular result rows:
223
+ ### Post-Save Live Preview & Settings Dialog
224
+ Saving a report in the builder automatically opens a two-column modal:
225
+ - **Left Column**: Page settings (Display Name, URL Slug `/reports/:slug`, Menu Group, Publish to Menu toggle, and a Copy Route button).
226
+ - **Right Column**: Live interactive form preview rendered via `<rpt-runtime>` allowing instant testing of validation and execution before publishing.
202
227
 
203
- ```typescript
204
- // src/app/services/erp-datasource.adapter.ts
205
- import { Injectable, inject } from '@angular/core';
206
- import { HttpClient } from '@angular/common/http';
207
- import { Observable } from 'rxjs';
208
- import { ReportDataSourceAdapter, ReportDataSourceDefinition } from 'bways-report';
209
-
210
- @Injectable({ providedIn: 'root' })
211
- export class ErpDataSourceAdapter extends ReportDataSourceAdapter {
212
- private readonly http = inject(HttpClient);
213
-
214
- execute(
215
- dataSource: ReportDataSourceDefinition,
216
- parameters: Record<string, unknown>
217
- ): Observable<unknown[]> {
218
- // Send report filter parameters to your backend API endpoint
219
- return this.http.post<unknown[]>(dataSource.endpoint, parameters);
220
- }
221
- }
222
- ```
223
-
224
- ### B. Persistence Adapter
228
+ ### Inline Double-Click Renaming
229
+ Double-click the report title in the toolbar to edit it inline:
230
+ - `Enter` saves the new name and suggests a URL slug.
231
+ - `Escape` cancels edits.
232
+ - `blur` persists the change.
233
+ - Changes are pushed to the undo/redo history stack.
225
234
 
226
- Responsible for saving, loading, listing, and publishing report metadata definitions (`ReportDefinition`):
235
+ ### Report Switcher & Quick New Page ("+")
236
+ - **"+" Button**: Immediately instantiates a fresh blank canvas (with confirmation if unsaved changes exist).
237
+ - **Report Switcher**: Dropdown populated from saved reports allowing rapid switching between report definitions.
227
238
 
228
- ```typescript
229
- // src/app/services/erp-persistence.adapter.ts
230
- import { Injectable, inject } from '@angular/core';
231
- import { HttpClient } from '@angular/common/http';
232
- import { Observable } from 'rxjs';
233
- import {
234
- ReportPersistenceAdapter,
235
- ReportDefinition,
236
- ReportSummary,
237
- } from 'bways-report';
238
-
239
- @Injectable({ providedIn: 'root' })
240
- export class ErpPersistenceAdapter extends ReportPersistenceAdapter {
241
- private readonly http = inject(HttpClient);
242
- private readonly baseUrl = '/api/reports';
243
-
244
- load(reportId: string): Observable<ReportDefinition> {
245
- return this.http.get<ReportDefinition>(`${this.baseUrl}/${reportId}`);
246
- }
239
+ ---
247
240
 
248
- save(report: ReportDefinition): Observable<ReportDefinition> {
249
- return this.http.post<ReportDefinition>(this.baseUrl, report);
250
- }
241
+ ## 3. Backend Contract Reference
251
242
 
252
- list(): Observable<ReportSummary[]> {
253
- return this.http.get<ReportSummary[]>(this.baseUrl);
254
- }
243
+ | Endpoint | Method | Path | Request Format | Response Format |
244
+ | :--- | :--- | :--- | :--- | :--- |
245
+ | `spEndpoint` | `GET` | `/api/reporting/procedures` | None | `StoredProcedureSummary[]` |
246
+ | `tablesEndpoint` | `GET` | `/api/reporting/tables` | None | `TableSummary[]` |
247
+ | `executeEndpoint` | `POST` | `/api/reporting/execute` | `{ kind, name, schema, parameters, columns?, top? }` | `Record<string, unknown>[]` |
248
+ | `reportsEndpoint` *(opt)* | `GET/POST/PUT/DELETE` | `/api/reporting/reports` | JSON `ReportDefinition` | `ReportSummary[]` / `ReportDefinition` |
255
249
 
256
- delete(reportId: string): Observable<void> {
257
- return this.http.delete<void>(`${this.baseUrl}/${reportId}`);
250
+ ### Stored Procedure Discovery Format
251
+ ```json
252
+ [
253
+ {
254
+ "name": "usp_GetCustomerList",
255
+ "schema": "dbo",
256
+ "parameters": [
257
+ { "name": "@BranchId", "sqlType": "int", "required": true },
258
+ { "name": "@SearchTerm", "sqlType": "varchar", "required": false, "defaultValue": "" }
259
+ ]
258
260
  }
261
+ ]
262
+ ```
259
263
 
260
- publish(reportId: string, version: number): Observable<void> {
261
- return this.http.post<void>(`${this.baseUrl}/${reportId}/publish`, { version });
264
+ ### Table Discovery Format
265
+ ```json
266
+ [
267
+ {
268
+ "name": "Customers",
269
+ "schema": "dbo",
270
+ "type": "table",
271
+ "columns": [
272
+ { "name": "CustomerId", "sqlType": "int" },
273
+ { "name": "CustomerName", "sqlType": "nvarchar" }
274
+ ]
262
275
  }
263
- }
276
+ ]
264
277
  ```
265
278
 
266
- ### C. Master Data Provider
279
+ ### Execution Request Format
280
+ Supports both simplified and enterprise DTO contracts out-of-the-box:
267
281
 
268
- Supplies option lists for dropdowns and lookups (e.g., Customers, Warehouses, Statuses):
269
-
270
- ```typescript
271
- // src/app/services/erp-masterdata.provider.ts
272
- import { Injectable, inject } from '@angular/core';
273
- import { HttpClient } from '@angular/common/http';
274
- import { Observable } from 'rxjs';
275
- import { MasterDataProvider, DropdownOption } from 'bways-report';
276
-
277
- @Injectable({ providedIn: 'root' })
278
- export class ErpMasterDataProvider extends MasterDataProvider {
279
- private readonly http = inject(HttpClient);
280
-
281
- getOptions(
282
- masterName: string,
283
- filter?: Record<string, unknown>
284
- ): Observable<DropdownOption[]> {
285
- return this.http.get<DropdownOption[]>(`/api/master-data/${masterName}`, {
286
- params: filter as any,
287
- });
282
+ **Option A (Simplified contract):**
283
+ ```json
284
+ {
285
+ "kind": "procedure",
286
+ "name": "usp_GetCustomerList",
287
+ "schema": "dbo",
288
+ "parameters": {
289
+ "BranchId": 1,
290
+ "SearchTerm": "Acme"
288
291
  }
289
292
  }
290
293
  ```
291
294
 
292
- ---
293
-
294
- ## 4. Routing & ERP Navigation Integration
295
-
296
- ### Dynamic Route Generation
297
-
298
- Mount all report runtime and designer routes with a single call in your `app.routes.ts`:
299
-
300
- ```typescript
301
- // src/app/app.routes.ts
302
- import { Routes } from '@angular/router';
303
- import { createReportRoutes } from 'bways-report';
304
-
305
- export const routes: Routes = [
306
- {
307
- path: 'reports',
308
- children: createReportRoutes({
309
- // Optional: enforce auth or role guards
310
- runtimeGuards: [],
311
- designerGuards: [], // e.g. [AdminGuard]
312
- enableDesignerRoutes: true, // creates 'new' and ':reportId/edit' routes
313
- }),
295
+ **Option B (Enterprise DTO contract):**
296
+ ```json
297
+ {
298
+ "dataSource": {
299
+ "id": "usp_GetCustomerList",
300
+ "type": "stored_procedure",
301
+ "name": "usp_GetCustomerList",
302
+ "schema": "dbo"
314
303
  },
315
- ];
304
+ "parameters": {
305
+ "BranchId": 1
306
+ },
307
+ "sessionContext": {
308
+ "companyId": 101,
309
+ "branchId": 1
310
+ }
311
+ }
316
312
  ```
317
313
 
318
- This instantly creates:
319
- - `/reports/:reportId` — Renders `RoutedReportRuntimeComponent` (resolves report via `reportResolver`, presents interactive filters, KPI metrics, chart, and result grid).
320
- - `/reports/:reportId/edit` — Renders `RoutedReportDesignerComponent` (visual drag-and-drop builder loaded with current definition).
321
- - `/reports/new` — Renders `RoutedReportDesignerComponent` initialized with a blank template.
322
-
323
- ### Categorized ERP Sidebar / Header Navigation
324
-
325
- Use `ReportMenuService` to generate hierarchical sidebar menus grouped by category (e.g. Finance, Sales, Inventory):
326
-
327
- ```typescript
328
- // src/app/components/sidebar/erp-sidebar.component.ts
329
- import { Component, inject } from '@angular/core';
330
- import { CommonModule } from '@angular/common';
331
- import { RouterModule } from '@angular/router';
332
- import { ReportMenuService } from 'bways-report';
333
-
334
- @Component({
335
- selector: 'erp-sidebar',
336
- standalone: true,
337
- imports: [CommonModule, RouterModule],
338
- template: `
339
- <aside class="sidebar">
340
- <input
341
- type="search"
342
- placeholder="Search reports..."
343
- (input)="onSearch($event)"
344
- />
345
-
346
- @for (group of menuService.menuGroups(); track group.category) {
347
- <div class="menu-group">
348
- <h4>{{ group.displayName }}</h4>
349
- <ul>
350
- @for (item of group.items; track item.id) {
351
- <li>
352
- <a [routerLink]="item.route" routerLinkActive="active">
353
- {{ item.name }}
354
- @if (item.isDraft) {
355
- <span class="badge">Draft</span>
356
- }
357
- </a>
358
- </li>
359
- }
360
- </ul>
361
- </div>
362
- }
363
- </aside>
364
- `,
365
- })
366
- export class ErpSidebarComponent {
367
- readonly menuService = inject(ReportMenuService);
368
-
369
- onSearch(event: Event): void {
370
- const query = (event.target as HTMLInputElement).value;
371
- this.menuService.setSearchQuery(query);
372
- }
314
+ ### Dropdown Lookup Request Format (`lookupEndpoint`)
315
+ Dropdowns with database data sources query `/api/reporting/lookup` (or fallback to `executeEndpoint`):
316
+ ```json
317
+ {
318
+ "entityName": "Sel_UserWiseCompUnit",
319
+ "sourceType": "stored_procedure",
320
+ "schema": "dbo",
321
+ "valueField": "COMPUNIT_ID",
322
+ "displayField": "COMPUNIT_NAME",
323
+ "parameters": {}
373
324
  }
374
325
  ```
375
326
 
376
327
  ---
377
328
 
378
- ## 5. Embedding Components Directly
379
-
380
- If you prefer embedding components inside existing pages instead of routing:
381
-
382
- ### Report Runtime (Interactive Report Page)
383
-
384
- ```typescript
385
- import { Component } from '@angular/core';
386
- import { ReportRuntimeComponent, ReportDefinition } from 'bways-report';
387
-
388
- @Component({
389
- selector: 'my-report-page',
390
- standalone: true,
391
- imports: [ReportRuntimeComponent],
392
- template: `
393
- <!-- Option A: Load by ID via persistence adapter -->
394
- <rpt-runtime [reportId]="'sales-register-2024'" />
329
+ ## 4. Dynamic Session Context & Auto-Parameter Binding
395
330
 
396
- <!-- Option B: Pass ReportDefinition directly -->
397
- <!-- <rpt-runtime [report]="customDefinition" /> -->
398
- `,
399
- })
400
- export class MyReportPageComponent {}
401
- ```
331
+ When `autoParameter: true` is configured, parameters matching active ERP session keys are automatically populated and hidden from non-technical users:
402
332
 
403
- ### Visual Drag-and-Drop Designer
333
+ | Stored Procedure Parameter | Matching Session Keys |
334
+ | :--- | :--- |
335
+ | `@BranchId`, `@branch_id`, `@bid`, `@branchcode`, `@locationid` | `branchId`, `branch`, `locationId` |
336
+ | `@CompanyId`, `@company_id`, `@cid`, `@companycode`, `@tenantid` | `companyId`, `company`, `tenantId` |
337
+ | `@UserId`, `@user_id`, `@uid`, `@usercode`, `@operatorid` | `userId`, `user`, `loginUser` |
338
+ | `@FinancialYearId`, `@fyear`, `@fiscalyear`, `@yearid` | `financialYearId`, `fYear` |
404
339
 
340
+ Session values can be updated at runtime:
405
341
  ```typescript
406
- import { Component } from '@angular/core';
407
- import { DesignerComponent, ReportDefinition } from 'bways-report';
342
+ import { inject } from '@angular/core';
343
+ import { ReportSessionContextService } from 'bways-report';
408
344
 
409
- @Component({
410
- selector: 'my-designer-page',
411
- standalone: true,
412
- imports: [DesignerComponent],
413
- template: `
414
- <rpt-designer
415
- [initialReport]="reportDefinition"
416
- (save)="onSaveReport($event)"
417
- />
418
- `,
419
- })
420
- export class MyDesignerPageComponent {
421
- reportDefinition: ReportDefinition = /* ... */;
345
+ export class SessionWidget {
346
+ private readonly session = inject(ReportSessionContextService);
422
347
 
423
- onSaveReport(updatedReport: ReportDefinition): void {
424
- console.log('Saved report schema:', updatedReport);
348
+ onBranchSwitch(branchId: number): void {
349
+ this.session.setSessionParameter('branchId', branchId);
425
350
  }
426
351
  }
427
352
  ```
428
353
 
429
354
  ---
430
355
 
431
- ## 6. Grid & Chart Bridge Integration (BWays-Grid)
356
+ ## 5. Plugging in BWays-Grid (`UltraGridComponent`)
432
357
 
433
- ### Using BWays-Grid or Custom Grid
358
+ `BWays-Report` provides first-class support for `bways-grid` (`v0.1.18+` / `v0.1.19+`). Pass `grid: UltraGridComponent` to `provideBwaysReport()`:
434
359
 
435
- Provide your grid component via the `GRID_COMPONENT` token in `provideBwaysReport()`:
436
-
437
- ```typescript
438
- provideBwaysReport({
439
- gridComponent: BWaysGridComponent, // or AgGridWrapperComponent
440
- })
441
- ```
360
+ - **Runtime `@Input()` Safety**: Dynamic grid bridging inspects component metadata (`ɵcmp.inputs`) before calling `ComponentRef.setInput()`, preventing Angular `NG0303` runtime template binding errors.
361
+ - **Row Selection Alignment**: Row selection mode (`single` vs `multiple`) is passed cleanly through `config.rowSelection` and `config.selectionMode`, preserving full compatibility with `UltraGridComponent`.
362
+ - **Circular Echo Suppression**: Grid state changes originating from user interaction are tracked to avoid re-triggering parent input cycles. Column menus, search inputs, and drag-handles stay open and focused without flicker.
363
+ - **Filter State Preservation**: Preserves both `activeFilters` (checkboxes) and `conditionFilters` (expressions) across runtime updates and JSON serialization.
364
+ - **Selective Layout Auto-Persistence**: Structural layout changes (column widths, pinning, grouping) persist immediately, while interactive data filtering is debounced to avoid undo stack pollution.
442
365
 
443
- `ReportGridBridgeComponent` dynamically passes the data rows, columns configuration, sorting, and aggregate settings directly to your grid component. If no grid is provided, `bways-report` renders its high-performance built-in tabular grid with pagination and column sorting.
366
+ ---
444
367
 
445
- ### Using Chart Components
368
+ ## 6. Advanced Custom Adapters
446
369
 
447
- Provide a chart component wrapper (Chart.js, ApexCharts, Highcharts) via `chartComponent`:
370
+ For applications with custom HTTP pipelines, gRPC, or microservice gateways, extend the library's abstract contracts:
448
371
 
449
372
  ```typescript
450
373
  provideBwaysReport({
451
- chartComponent: MyHostChartComponent,
452
- })
374
+ gridComponent: UltraGridComponent,
375
+ dataSourceAdapter: MyCustomDataSourceAdapter,
376
+ persistenceAdapter: MyCustomPersistenceAdapter,
377
+ schemaDiscoveryAdapter: MyCustomSchemaDiscoveryAdapter,
378
+ lookupAdapter: MyCustomLookupAdapter,
379
+ });
453
380
  ```
454
381
 
455
- If not provided, the built-in SVG visual chart renderer outputs crisp, responsive Bar charts, Donut charts, and Line/Area charts with zero external dependencies.
382
+ Abstract base classes:
383
+ - `ReportDataSourceAdapter`
384
+ - `ReportPersistenceAdapter`
385
+ - `ReportSchemaDiscoveryAdapter`
386
+ - `ReportLookupAdapter`
456
387
 
457
388
  ---
458
389
 
459
390
  ## 7. Theming & CSS Custom Properties
460
391
 
461
- `bways-report` uses CSS custom properties (`--rpt-*`) throughout all components, ensuring seamless alignment with your ERP application's design system:
392
+ `bways-report` uses Vanilla CSS custom properties. Customize the tokens in your application's `styles.css`:
462
393
 
463
394
  ```css
464
- /* In your host application's styles.scss or theme file */
465
395
  :root {
466
- /* Brand Colors */
467
- --rpt-primary: #2563eb;
468
- --rpt-primary-hover: #1d4ed8;
469
- --rpt-primary-focus: rgba(37, 99, 235, 0.25);
470
-
471
- /* Surface & Text */
472
- --rpt-surface-bg: #ffffff;
473
- --rpt-bg-subtle: #f8fafc;
474
- --rpt-text-color: #0f172a;
475
- --rpt-text-muted: #64748b;
476
- --rpt-border-color: #e2e8f0;
477
-
478
- /* Geometry & Typography */
479
- --rpt-radius-md: 6px;
480
- --rpt-radius-lg: 12px;
396
+ --rpt-color-primary: #2563eb;
397
+ --rpt-color-primary-hover: #1d4ed8;
398
+ --rpt-color-bg: #ffffff;
399
+ --rpt-color-surface: #f8fafc;
400
+ --rpt-color-text: #0f172a;
401
+ --rpt-color-text-muted: #64748b;
402
+ --rpt-color-border: #cbd5e1;
481
403
  --rpt-font-family: 'Inter', system-ui, sans-serif;
482
- --rpt-font-size-base: 0.875rem;
483
-
484
- /* Status Colors */
485
- --rpt-success-color: #10b981;
486
- --rpt-warning-color: #f59e0b;
487
- --rpt-error-color: #ef4444;
404
+ --rpt-border-radius: 6px;
405
+ --rpt-border-radius-lg: 8px;
488
406
  }
489
- ```
490
-
491
- ---
492
-
493
- ## 8. Registering Custom Host Controls
494
-
495
- You can register custom Angular components (e.g., custom slider, multi-select, rich customer picker) into the `ComponentRegistry` so they appear in the Visual Designer palette and render dynamically at runtime:
496
407
 
497
- ```typescript
498
- import { ComponentRegistry, ComponentMetadata } from 'bways-report';
499
- import { MyCustomPickerComponent } from './my-custom-picker.component';
500
-
501
- export function configureCustomControls(registry: ComponentRegistry): void {
502
- registry.register({
503
- type: 'customer-picker',
504
- displayName: 'Customer Picker',
505
- category: 'input',
506
- icon: 'person_search',
507
- component: MyCustomPickerComponent,
508
- createDefaultConfig: () => ({
509
- id: 'cust-picker',
510
- type: 'customer-picker',
511
- label: 'Select Customer',
512
- properties: { placeholder: 'Search customer...' },
513
- layout: { columnSpan: 4 },
514
- }),
515
- propertySchema: [
516
- { key: 'label', label: 'Label', type: 'string', required: true, group: 'General' },
517
- { key: 'key', label: 'Field Name (Key)', type: 'string', required: true, group: 'General' },
518
- { key: 'required', label: 'Required', type: 'boolean', group: 'Validation' },
519
- ],
520
- });
408
+ [data-theme='dark'] {
409
+ --rpt-color-bg: #0f172a;
410
+ --rpt-color-surface: #1e293b;
411
+ --rpt-color-text: #f8fafc;
412
+ --rpt-color-text-muted: #94a3b8;
413
+ --rpt-color-border: #334155;
521
414
  }
522
415
  ```
523
416
 
524
417
  ---
525
418
 
526
- ## 9. Exporting Data (CSV & JSON)
419
+ ## 8. Exporting Data (CSV & JSON)
527
420
 
528
- Use `ReportExportService` for one-click file generation:
421
+ Inject `ReportExportService` in any host component:
529
422
 
530
423
  ```typescript
531
424
  import { Component, inject } from '@angular/core';
532
425
  import { ReportExportService } from 'bways-report';
533
426
 
534
- @Component({
535
- selector: 'export-actions',
536
- standalone: true,
537
- template: `
538
- <button (click)="downloadCsv()">Download CSV</button>
539
- <button (click)="downloadJson()">Download Metadata</button>
540
- `,
541
- })
542
- export class ExportActionsComponent {
427
+ @Component({ ... })
428
+ export class ExportComponent {
543
429
  private readonly exportService = inject(ReportExportService);
544
430
 
545
- downloadCsv(): void {
546
- const data = [
547
- { invoiceNo: 'INV-001', customer: 'Acme Corp', total: 4950 },
548
- { invoiceNo: 'INV-002', customer: 'Globex Inc', total: 14080 },
549
- ];
550
-
431
+ onExportCsv(data: unknown[]): void {
551
432
  this.exportService.exportCsv(data, {
552
- fileName: 'invoices-export.csv',
433
+ fileName: 'sales-register.csv',
553
434
  columns: [
554
435
  { field: 'invoiceNo', header: 'Invoice #' },
555
- { field: 'customer', header: 'Customer' },
556
- {
557
- field: 'total',
558
- header: 'Total ($)',
559
- formatter: (val: number) => `$${val.toLocaleString()}`
560
- },
436
+ { field: 'amount', header: 'Amount' },
561
437
  ],
562
- addBom: true, // Includes UTF-8 BOM so Microsoft Excel renders international characters properly
563
- });
564
- }
565
-
566
- downloadJson(): void {
567
- this.exportService.exportJson(myReportDefinition, {
568
- fileName: 'report-schema.json',
569
- pretty: true,
438
+ addBom: true, // UTF-8 Excel compatibility
570
439
  });
571
440
  }
572
441
  }
@@ -576,4 +445,4 @@ export class ExportActionsComponent {
576
445
 
577
446
  ## License
578
447
 
579
- MIT © BWays Technologies
448
+ Proprietary License. Copyright (c) 2026 CCPL / BWays Team. All rights reserved.