@smartsoft001/crud-shell-angular 2.124.0 โ 2.126.0
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
CHANGED
|
@@ -1,7 +1,290 @@
|
|
|
1
|
-
# crud-shell-angular
|
|
1
|
+
# ๐ฆ @smartsoft001/crud-shell-angular
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
 
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## ๐งญ Overview
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
`@smartsoft001/crud-shell-angular` is the **config / metadata-driven container layer** for
|
|
8
|
+
CRUD screens โ **not** a primitive-component library. You do not place a table here, a form
|
|
9
|
+
there, and wire them by hand. Instead you describe **what** the entity is (model decorators)
|
|
10
|
+
and **how** its screens should behave (a config object), and the engine **generates** the UI.
|
|
11
|
+
|
|
12
|
+
Three inputs drive every screen:
|
|
13
|
+
|
|
14
|
+
1. **Model decorators** โ `@Model` / `@Field` from `@smartsoft001/models`, plus a `FieldType`
|
|
15
|
+
per field. These describe the entity's shape, labels, validation and which fields appear in
|
|
16
|
+
list / details / edit / filters.
|
|
17
|
+
2. **A `CrudFullConfig`** โ declares the API endpoint, the entity name, and the screen behavior
|
|
18
|
+
(title, pagination, search, export, sort, list mode, groups, buttons, styling, โฆ).
|
|
19
|
+
3. **The engine** โ `CreateDynamicComponent` and the page components read the config + model
|
|
20
|
+
metadata and instantiate the right children dynamically.
|
|
21
|
+
|
|
22
|
+
The **free** library renders with the free `@smartsoft001/angular` components (Tailwind +
|
|
23
|
+
signals, OnPush, HTML-template-first). The **pro** library
|
|
24
|
+
(`@smartsoft001/pro-crud-shell-angular`, FRA-294) does **not** fork these screens โ it
|
|
25
|
+
**extends the `@Directive()` base classes exported here** and registers richer `smartpro-*`
|
|
26
|
+
implementations via the base + token precedent established in `@smartsoft001/angular`.
|
|
27
|
+
|
|
28
|
+
## ๐ Usage
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm i @smartsoft001/crud-shell-angular
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 1. Describe the entity with model decorators
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { Model, Field, FieldType } from '@smartsoft001/models';
|
|
38
|
+
|
|
39
|
+
@Model({ name: 'user' })
|
|
40
|
+
export class User {
|
|
41
|
+
@Field({ list: true, details: true, create: true, update: true })
|
|
42
|
+
firstName!: string;
|
|
43
|
+
|
|
44
|
+
@Field({ list: true, details: true, create: true, update: true })
|
|
45
|
+
lastName!: string;
|
|
46
|
+
|
|
47
|
+
@Field({
|
|
48
|
+
list: true,
|
|
49
|
+
filter: true,
|
|
50
|
+
fieldType: FieldType.flag,
|
|
51
|
+
})
|
|
52
|
+
active!: boolean;
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 2. Declare a `CrudFullConfig`
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { CrudFullConfig } from '@smartsoft001/crud-shell-angular';
|
|
60
|
+
import { ListMode, PaginationMode } from '@smartsoft001/angular';
|
|
61
|
+
|
|
62
|
+
export const userConfig: CrudFullConfig<User> = {
|
|
63
|
+
// CrudConfig (base)
|
|
64
|
+
apiUrl: 'https://api.example.com',
|
|
65
|
+
entity: 'user',
|
|
66
|
+
type: User,
|
|
67
|
+
|
|
68
|
+
// CrudFullConfig
|
|
69
|
+
title: 'Users',
|
|
70
|
+
details: true,
|
|
71
|
+
edit: true,
|
|
72
|
+
add: true,
|
|
73
|
+
remove: true,
|
|
74
|
+
search: true,
|
|
75
|
+
export: true,
|
|
76
|
+
pagination: { limit: 25 },
|
|
77
|
+
sort: { default: 'lastName', defaultDesc: false },
|
|
78
|
+
list: {
|
|
79
|
+
mode: ListMode.desktop,
|
|
80
|
+
paginationMode: PaginationMode.singlePage,
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
// Declarative styling (tier 2)
|
|
84
|
+
cssClass: 'smart:bg-gray-50',
|
|
85
|
+
variant: 'standard',
|
|
86
|
+
};
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 3. Register the module
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { CrudModule } from '@smartsoft001/crud-shell-angular';
|
|
93
|
+
|
|
94
|
+
@NgModule({
|
|
95
|
+
imports: [
|
|
96
|
+
CrudModule.forFeature({
|
|
97
|
+
routing: true, // true -> CrudFullModule (with pages/routing); false -> CrudCoreModule
|
|
98
|
+
config: userConfig,
|
|
99
|
+
// socket: true, // opt-in realtime provider wiring (inert stub today)
|
|
100
|
+
}),
|
|
101
|
+
],
|
|
102
|
+
})
|
|
103
|
+
export class UserModule {}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 4. Place the pages
|
|
107
|
+
|
|
108
|
+
The engine-generated container pages are the **only** hand-placed entry points:
|
|
109
|
+
|
|
110
|
+
```html
|
|
111
|
+
<!-- List screen (page, search, end-buttons, generated list) -->
|
|
112
|
+
<smart-crud-list-page></smart-crud-list-page>
|
|
113
|
+
|
|
114
|
+
<!-- Item screen (create / update / details) -->
|
|
115
|
+
<smart-crud-item-page></smart-crud-item-page>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
When `routing: true`, `CrudFullModule` wires these pages into routes for you.
|
|
119
|
+
|
|
120
|
+
## โ๏ธ Configuration
|
|
121
|
+
|
|
122
|
+
### `CrudConfig<T>` (base)
|
|
123
|
+
|
|
124
|
+
| Property | Type | Description |
|
|
125
|
+
| ---------------- | ----------------------------- | --------------------------------------------------------------- |
|
|
126
|
+
| `apiUrl` | `string` | Backend base URL (also fed to `FILE_SERVICE_CONFIG`) |
|
|
127
|
+
| `entity` | `string` | Entity name โ keys the NgRx reducer registration |
|
|
128
|
+
| `type` | `any` | Model class decorated with `@Model` / `@Field` |
|
|
129
|
+
| `reducerFactory` | `() => any` | Optional custom reducer factory (defaults to `getReducer`) |
|
|
130
|
+
| `baseQuery` | `Array<ICrudFilterQueryItem>` | Optional always-applied query items |
|
|
131
|
+
|
|
132
|
+
### `CrudFullConfig<T>` (extends `CrudConfig<T>`)
|
|
133
|
+
|
|
134
|
+
| Property | Type | Description |
|
|
135
|
+
| ----------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------ |
|
|
136
|
+
| `title` | `string` | Page title (translated) |
|
|
137
|
+
| `details` | `boolean \| { cellPipe?; components?: { top?; bottom? } }` | Enable details view; optionally a `cellPipe` and top/bottom dynamic components |
|
|
138
|
+
| `edit` | `boolean \| { cellPipe?; components?: { top?; bottom? } }` | Enable edit; optional cell pipe and top/bottom components |
|
|
139
|
+
| `add` | `boolean \| { components?: { top?; bottom? } }` | Enable create; optional top/bottom components |
|
|
140
|
+
| `remove` | `boolean` | Enable row remove |
|
|
141
|
+
| `search` | `boolean` | Enable the page search bar |
|
|
142
|
+
| `export` | `boolean` | Enable the export control |
|
|
143
|
+
| `pagination` | `{ limit: number }` | Page size |
|
|
144
|
+
| `sort` | `boolean \| { default?: string; defaultDesc?: boolean }` | Enable sort; optional default column + direction |
|
|
145
|
+
| `list` | `{ cellPipe?; components?: { top?; multi? }; mode?; paginationMode?; resetQuery?; groups? }` | List behavior (see below) |
|
|
146
|
+
| `buttons` | `Array<IIconButtonOptions>` | Extra header/end buttons rendered through `<smart-page>` |
|
|
147
|
+
| `inputComponents` | `{ [key: string]: Type<InputBaseComponent<T>> }` | Per-field input component overrides (keyed by field name) |
|
|
148
|
+
| `cssClass` | `string` | **Tier-2 styling** โ forwarded to `<smart-page [class]>` on the list/item pages |
|
|
149
|
+
| `variant` | `SmartPageVariant` | **Tier-2 styling** โ threaded into `pageOptions().variant` to pick a `<smart-page>` variant |
|
|
150
|
+
|
|
151
|
+
`list` sub-fields:
|
|
152
|
+
|
|
153
|
+
| Field | Type | Description |
|
|
154
|
+
| ---------------- | ----------------------------------- | ------------------------------------------------------------ |
|
|
155
|
+
| `mode` | `ListMode` | `desktop` / `mobile` / `masonryGrid` list rendering |
|
|
156
|
+
| `paginationMode` | `PaginationMode` | `singlePage` / `infiniteScroll` |
|
|
157
|
+
| `groups` | `Array<ICrudListGroup>` | Grouped (accordion) list sections |
|
|
158
|
+
| `components` | `{ top?; multi? }` | Dynamic top component + multi-select action component |
|
|
159
|
+
| `cellPipe` | `ICellPipe<T>` | Per-cell value transform |
|
|
160
|
+
| `resetQuery` | `'beforeInit'` | Reset the active filter query before first read |
|
|
161
|
+
|
|
162
|
+
## ๐งฉ Components
|
|
163
|
+
|
|
164
|
+
The CRUD module exposes the following selectors. Only the **page** components and `smart-crud-export`
|
|
165
|
+
are normally hand-placed; the rest are mounted by the engine / containers.
|
|
166
|
+
|
|
167
|
+
| Selector | Purpose |
|
|
168
|
+
| --------------------------------------- | ---------------------------------------------------------------------------- |
|
|
169
|
+
| `smart-crud-list-page` | List container page (wraps `<smart-page>`; search, header buttons, list) |
|
|
170
|
+
| `smart-crud-item-page` | Item container page (create / update / details; mode action buttons) |
|
|
171
|
+
| `smart-crud-export` | Export control + post-export popover |
|
|
172
|
+
| `smart-crud-filters` | Filters panel (header, scrollable list of per-field filters) |
|
|
173
|
+
| `smart-crud-filters-config` | Active-filter chips (dismissible badges; remove active query) |
|
|
174
|
+
| `smart-crud-multiselect` | Multi-select header / action bar (`selected: N`, close) |
|
|
175
|
+
| `smart-crud-group` | Grouped list disclosure (accessible HTML accordion, two-way `show`) |
|
|
176
|
+
| `smart-crud-filter` | **Filter dispatcher** โ switches on `FieldType` to the right widget below |
|
|
177
|
+
| `smart-crud-filter-text` | Text filter |
|
|
178
|
+
| `smart-crud-filter-int` | Integer filter (value + advanced min/max range) |
|
|
179
|
+
| `smart-crud-filter-flag` | Boolean flag filter |
|
|
180
|
+
| `smart-crud-filter-radio` | Single-choice (radio) filter |
|
|
181
|
+
| `smart-crud-filter-check` | Multi-choice (checkbox list) filter |
|
|
182
|
+
| `smart-crud-filter-date` | Single-date filter |
|
|
183
|
+
| `smart-crud-filter-date-time` | Datetime "from"/"to" range filter |
|
|
184
|
+
| `smart-crud-filter-date-with-edit` | Editable-date filter (value + advanced min/max range) |
|
|
185
|
+
|
|
186
|
+
> The page component selectors have `*-standard` variant children
|
|
187
|
+
> (`smart-crud-list-standard-page`, `smart-crud-item-standard-page`) that hold the actual
|
|
188
|
+
> generated body; the public wrappers above are what you place.
|
|
189
|
+
|
|
190
|
+
## ๐ Filter widgets
|
|
191
|
+
|
|
192
|
+
`smart-crud-filter` is a dispatcher: it reads `item().fieldType` and renders the matching widget
|
|
193
|
+
(`@switch` on `FieldType`, `text` as default). Each widget reuses the **shared input components**
|
|
194
|
+
from `@smartsoft001/angular` wherever the shape fits, is authored **OnPush**, and binds through a
|
|
195
|
+
reactive `FormControl` bridged to the filter state by the base class.
|
|
196
|
+
|
|
197
|
+
| `FieldType` | Widget | Rendering |
|
|
198
|
+
| --------------- | ---------------------------------- | -------------------------------------------------------------------------- |
|
|
199
|
+
| `text` (default)| `smart-crud-filter-text` | `smart-input-text` (reactive `[formControl]`) |
|
|
200
|
+
| `flag` | `smart-crud-filter-flag` | `smart-input-flag` |
|
|
201
|
+
| `radio` | `smart-crud-filter-radio` | `smart-input-radio` (+ possibilities bridge) |
|
|
202
|
+
| `int` | `smart-crud-filter-int` | `smart-input-int` for the value; native Tailwind "from"/"to" range inputs |
|
|
203
|
+
| `check` | `smart-crud-filter-check` | Native Tailwind checkbox list (scalar-id + array value shape) |
|
|
204
|
+
| `date` | `smart-crud-filter-date` | `smart-date-edit` |
|
|
205
|
+
| `dateTime` | `smart-crud-filter-date-time` | Native `<input type="datetime-local">` "from"/"to" |
|
|
206
|
+
| `dateWithEdit` | `smart-crud-filter-date-with-edit` | `smart-date-edit` + native "from"/"to" range |
|
|
207
|
+
|
|
208
|
+
Notes:
|
|
209
|
+
|
|
210
|
+
- **Possibilities** (radio / check options) flow through `options.possibilities` on the shared
|
|
211
|
+
input. The base class maps `possibilities` into the `{ id, text, checked }` shape via
|
|
212
|
+
`buildInputOptions(control, withPossibilities)`. Possibilities resolve from
|
|
213
|
+
`item.possibilities`, and (when provided) the deprecated
|
|
214
|
+
`CRUD_MODEL_POSSIBILITIES_PROVIDER` keyed by `config.type` + field key.
|
|
215
|
+
- **Labels** resolve via the shared `ModelLabelPipe`. The CRUD module ships a default
|
|
216
|
+
`CrudModelLabelProvider` (registered for `IModelLabelProvider`) which delegates to an
|
|
217
|
+
app-level `IModelLabelProvider` higher in the injector tree if one exists, otherwise translates
|
|
218
|
+
`MODEL.<key>`. An app can override it.
|
|
219
|
+
- The base class exposes `bindControl(type)` / `bindValueControl()` (reactive bridge to the
|
|
220
|
+
`value` / `>=` / `<=` query slots), and OnPush-safe `hasValue` / `hasMinValue` / `hasMaxValue`
|
|
221
|
+
computed signals for clear-button visibility.
|
|
222
|
+
|
|
223
|
+
## ๐จ Styling (3-tier)
|
|
224
|
+
|
|
225
|
+
CRUD styling is layered so apps can reach for the lightest tool that does the job:
|
|
226
|
+
|
|
227
|
+
1. **Tailwind theme (`smart:` prefix).** All CRUD templates use the prefixed Tailwind utilities
|
|
228
|
+
shared with `@smartsoft001/angular`. Theme tokens flow from the host app's Tailwind config.
|
|
229
|
+
2. **Declarative `cssClass` / `variant` on `CrudFullConfig`.** These are threaded into the page:
|
|
230
|
+
`config.variant` drives `pageOptions().variant` (which `<smart-page>` variant renders) and
|
|
231
|
+
`config.cssClass` is bound as `[class]` on the `<smart-page>` of the list/item screens.
|
|
232
|
+
3. **`class` on the hand-placed entry points only** โ `smart-crud-list-page`,
|
|
233
|
+
`smart-crud-item-page`, `smart-crud-export`. Engine-generated leaf components are mounted
|
|
234
|
+
dynamically and do **not** expose a `class` input; style them through tiers 1โ2.
|
|
235
|
+
|
|
236
|
+
## ๐งฌ Extending (pro / custom)
|
|
237
|
+
|
|
238
|
+
Every container component is split into a thin `@Directive()` base class (logic only) and a
|
|
239
|
+
concrete implementation, so the **pro** library can extend the logic and supply its own template
|
|
240
|
+
via the base + token precedent from `@smartsoft001/angular`.
|
|
241
|
+
|
|
242
|
+
Exported base classes (from the package barrel):
|
|
243
|
+
|
|
244
|
+
| Base class | Concrete | Extend to customize |
|
|
245
|
+
| ------------------------- | ------------------------- | -------------------------------------------- |
|
|
246
|
+
| `ExportBaseComponent` | `smart-crud-export` | Export trigger + post-export popover logic |
|
|
247
|
+
| `MultiselectBaseComponent`| `smart-crud-multiselect` | Multi-select header / action bar |
|
|
248
|
+
| `FiltersBaseComponent` | `smart-crud-filters` | Filters panel container |
|
|
249
|
+
| `GroupBaseComponent` | `smart-crud-group` | Grouped-list disclosure |
|
|
250
|
+
| `BaseComponent` (filter) | `smart-crud-filter-*` | Per-`FieldType` filter widget logic |
|
|
251
|
+
|
|
252
|
+
The pro library (`@smartsoft001/pro-crud-shell-angular`, FRA-294) provides `smartpro-*` variants
|
|
253
|
+
that `extends` these bases โ for example a rich `smartpro-accordion`-backed group โ registered
|
|
254
|
+
through the same InjectionToken override pattern used across `@smartsoft001/angular` (the
|
|
255
|
+
`*_STANDARD_COMPONENT_TOKEN` precedent).
|
|
256
|
+
|
|
257
|
+
## ๐
ฐ๏ธ Angular 22 readiness
|
|
258
|
+
|
|
259
|
+
- Components are authored **OnPush**.
|
|
260
|
+
- The form model stays **reactive** (`FormFactory` / `UntypedFormGroup`); signal-forms are a
|
|
261
|
+
planned **additive** step, not a rewrite.
|
|
262
|
+
- `HttpClient` works under the Fetch backend; no XHR-specific assumptions.
|
|
263
|
+
|
|
264
|
+
## ๐ Storybook
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
nx storybook crud-shell-angular
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## ๐งช Unit tests
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
nx test crud-shell-angular
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## ๐ค Contributing
|
|
277
|
+
|
|
278
|
+
Contributions are welcome! ๐
|
|
279
|
+
|
|
280
|
+
1. Fork the repository.
|
|
281
|
+
2. Create a feature branch: git checkout -b feature/my-new-feature.
|
|
282
|
+
3. Commit your changes: git commit -m 'Add some feature'.
|
|
283
|
+
4. Push to the branch: git push origin feature/my-new-feature.
|
|
284
|
+
Submit a pull request.
|
|
285
|
+
|
|
286
|
+
For more details, see our [Contributing Guidelines](../../../../CONTRIBUTING.md).
|
|
287
|
+
|
|
288
|
+
## ๐ Changelog
|
|
289
|
+
|
|
290
|
+
All notable changes to this project will be documented in the [CHANGELOG](../../../../CHANGELOG.md).
|