@smartsoft001/pro-claude-plugins 0.3.0 → 0.3.1
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/package.json +1 -1
- package/plugins/flow/skills/impl/SKILL.md +4 -3
- package/plugins/flow/skills/plan/SKILL.md +18 -13
- package/plugins/flow-external/skills/impl/SKILL.md +3 -3
- package/plugins/flow-external/skills/plan/SKILL.md +17 -12
- package/plugins/flow-legacy/skills/impl/SKILL.md +3 -3
- package/plugins/flow-legacy/skills/plan/SKILL.md +18 -13
- package/plugins/smart-pro/skills/angular-components-crud/SKILL.md +236 -0
package/package.json
CHANGED
|
@@ -383,8 +383,8 @@ The agent will:
|
|
|
383
383
|
|
|
384
384
|
1. **Check for existing `orchestration.md` attachment** on the task via `mcp__linear__get_issue` (the response includes an `attachments` array).
|
|
385
385
|
- If one exists, delete it via `mcp__linear__delete_attachment({ id: oldAttachmentId })`. Linear hosts the file natively, so nothing else needs cleanup.
|
|
386
|
-
2. **Write locally**: use `Write` to save the orchestration markdown to
|
|
387
|
-
3. **Base64-encode**: `b64=$(base64 -i /
|
|
386
|
+
2. **Write locally**: ensure `.ai/tasks/` is gitignored (idempotent — `.ai/tasks` must NOT be synced to git): `grep -qxF '.ai/tasks/' .gitignore 2>/dev/null || echo '.ai/tasks/' >> .gitignore`. Then `mkdir -p .ai/tasks/<taskId>` and use `Write` to save the orchestration markdown to `.ai/tasks/<taskId>/orchestration.md` (sibling of `plan.md`).
|
|
387
|
+
3. **Base64-encode**: `b64=$(base64 -i .ai/tasks/<taskId>/orchestration.md)`.
|
|
388
388
|
4. **Create Linear attachment** via `mcp__linear__create_attachment`:
|
|
389
389
|
- `issue`: the task/subtask ID
|
|
390
390
|
- `filename`: `orchestration.md`
|
|
@@ -392,7 +392,7 @@ The agent will:
|
|
|
392
392
|
- `title`: `orchestration.md` (exact — used for detection/replacement on the next `/impl` run)
|
|
393
393
|
- `subtitle`: `Plan orkiestracji wygenerowany przez Claude Code`
|
|
394
394
|
- `base64Content`: the base64 string from step 3
|
|
395
|
-
5. **
|
|
395
|
+
5. **Keep the local file**: do NOT delete `.ai/tasks/<taskId>/orchestration.md` — it persists as a gitignored local artifact.
|
|
396
396
|
6. **Follow the plan** — execute agents in the defined order.
|
|
397
397
|
7. **Use TDD strictly** — `shared-tdd-developer` is MANDATORY for ALL code implementation.
|
|
398
398
|
|
|
@@ -915,6 +915,7 @@ When verification fails, delegate to appropriate fix agent:
|
|
|
915
915
|
19. **Capture before screenshots in background**: Launch `screenshot-reporter` agent with `run_in_background: true` BEFORE implementing UI changes to capture "before" state while implementation proceeds
|
|
916
916
|
20. **Capture after screenshots + post to Linear**: After implementation, launch `screenshot-reporter` agent to capture "after" screenshots, generate comparison report, post to Linear, and cleanup
|
|
917
917
|
21. **Document translations changes**: If `apps/web/public/translations.json` was modified, include a table with added/changed translation keys and their PL/EN values in the Implementation Report
|
|
918
|
+
21a. **⚠️ MANDATORY: Translation completeness before completion**: No hardcoded UI strings — every static label, heading, button, aria-label, meta/SEO text goes through a translation key. Before marking a subtask complete, verify that EVERY key referenced in the changed templates/TS exists in `apps/web/public/translations.json` in BOTH `pl` and `en` (a raw `GROUP.key` rendered in the UI is a defect), and that the touched groups are complete against the design/mockup — every visible text on the mockup has its key. When a reference project is available, diff the touched groups against it and fill the gaps
|
|
918
919
|
22. **Capture screenshots in both modes**: Agent captures screenshots in BOTH normal mode and dark mode (high contrast) for complete visual documentation
|
|
919
920
|
23. **Ask before collecting feedback for agent evolution**: When user provides corrections or suggestions during implementation, **explicitly ask** if they want to create a Linear issue for the improvement. Only user-confirmed feedback (answered "Yes") should be processed at evolution checkpoints (Step 3g-evolve, Step 4a) via `shared-agent-evolver` agent.
|
|
920
921
|
24. **Never modify agent files directly during implementation**: The `shared-agent-evolver` agent files all proposals as Linear issues for manual review — it does NOT modify agent, command, or skill files directly.
|
|
@@ -679,7 +679,18 @@ When using `--deep` flag and the Planning Team has completed its analysis, appen
|
|
|
679
679
|
|
|
680
680
|
**MANDATORY.** Before any Linear write (deletion of old `plan.md`, creation of new `plan.md`, label apply), the user MUST approve the generated plan content. This is the gate FRA-126 added.
|
|
681
681
|
|
|
682
|
-
|
|
682
|
+
**Persist the plan locally first (both modes).** For each task/subtask that needs planning:
|
|
683
|
+
|
|
684
|
+
- Ensure `.ai/tasks/` is gitignored (idempotent — `.ai/tasks` must NOT be synced to git):
|
|
685
|
+
```bash
|
|
686
|
+
grep -qxF '.ai/tasks/' .gitignore 2>/dev/null || echo '.ai/tasks/' >> .gitignore
|
|
687
|
+
```
|
|
688
|
+
- `mkdir -p .ai/tasks/<taskId>`
|
|
689
|
+
- Use the `Write` tool to save the Step 8 plan markdown to `.ai/tasks/<taskId>/plan.md`.
|
|
690
|
+
|
|
691
|
+
This file is the source for the Linear attachment in Step 9a and is NOT deleted — it persists as a gitignored local artifact. On regeneration (below) the `Write` overwrites it with the new plan.
|
|
692
|
+
|
|
693
|
+
**`--auto` mode**: Skip the approval prompt below — the plan is auto-approved and already persisted above. Record the auto-approval in the final Linear audit comment (e.g. `Plan zaakceptowany automatycznie (--auto)`). Proceed to Step 9.
|
|
683
694
|
|
|
684
695
|
**Default mode** (interactive):
|
|
685
696
|
|
|
@@ -749,20 +760,14 @@ Use `AskUserQuestion` tool with options:
|
|
|
749
760
|
|
|
750
761
|
For each task that needs planning, upload the plan content directly to Linear via `mcp__linear__create_attachment` — Linear hosts the file itself, no intermediate storage.
|
|
751
762
|
|
|
752
|
-
#### 9a.1 —
|
|
753
|
-
|
|
754
|
-
The plan content is exactly the markdown produced in Step 8 (the same block that would previously have been posted as a comment). Write it to the temp file:
|
|
755
|
-
|
|
756
|
-
```bash
|
|
757
|
-
mkdir -p /tmp/claude-plans
|
|
758
|
-
```
|
|
763
|
+
#### 9a.1 — Locate plan content
|
|
759
764
|
|
|
760
|
-
|
|
765
|
+
The plan content was already written to `.ai/tasks/<taskId>/plan.md` in Step 8a (before acceptance). No temp file is needed — that persistent, gitignored file is the source for the attachment below.
|
|
761
766
|
|
|
762
767
|
#### 9a.2 — Base64-encode the content
|
|
763
768
|
|
|
764
769
|
```bash
|
|
765
|
-
b64=$(base64 -i /
|
|
770
|
+
b64=$(base64 -i .ai/tasks/<taskId>/plan.md)
|
|
766
771
|
```
|
|
767
772
|
|
|
768
773
|
On macOS `base64 -i <file>` outputs without line-wrapping (which is what the Linear MCP expects). If you ever switch to GNU coreutils, pipe through `tr -d '\n'` to strip wraps.
|
|
@@ -780,9 +785,9 @@ Call `mcp__linear__create_attachment` with:
|
|
|
780
785
|
|
|
781
786
|
Linear stores the file on its own infrastructure and surfaces it in the issue's Attachments pane.
|
|
782
787
|
|
|
783
|
-
#### 9a.4 —
|
|
788
|
+
#### 9a.4 — Keep the local file
|
|
784
789
|
|
|
785
|
-
|
|
790
|
+
Do NOT delete `.ai/tasks/<taskId>/plan.md` — it is intentionally kept as a gitignored local artifact. `/push` leaves Linear attachments in place — they stay on the issue as permanent artifacts.
|
|
786
791
|
|
|
787
792
|
#### Scope rule
|
|
788
793
|
|
|
@@ -1030,4 +1035,4 @@ _Plan generated by Claude Code_
|
|
|
1030
1035
|
- **Default mode**: Before saving the plans as attachments, show them to the user for review and approval.
|
|
1031
1036
|
- **`--auto` mode**: Skip the review step; proceed directly to saving the attachments.
|
|
1032
1037
|
|
|
1033
|
-
The plan content is written to
|
|
1038
|
+
The plan content is written to `.ai/tasks/<taskId>/plan.md` (before acceptance, gitignored), base64-encoded, and uploaded as a native Linear attachment via `mcp__linear__create_attachment`. After that, the `AI Plan` label is applied to the invoked issue.
|
|
@@ -133,8 +133,8 @@ Use `shared-impl-orchestrator` agent to generate a `🎭 Agent Orchestration Pla
|
|
|
133
133
|
Then save it as an `orchestration.md` attachment on the task (not as a comment):
|
|
134
134
|
|
|
135
135
|
1. **Replace existing orchestration**: use `mcp__linear__get_issue` to list attachments; if one titled `orchestration.md` exists, delete it via `mcp__linear__delete_attachment({ id: oldAttachmentId })`. Linear hosts the file natively, so nothing else needs cleanup.
|
|
136
|
-
2. **Write locally**: `Write` the orchestration markdown to
|
|
137
|
-
3. **Base64-encode**: `b64=$(base64 -i /
|
|
136
|
+
2. **Write locally**: ensure `.ai/tasks/` is gitignored (idempotent — `.ai/tasks` must NOT be synced to git): `grep -qxF '.ai/tasks/' .gitignore 2>/dev/null || echo '.ai/tasks/' >> .gitignore`. Then `mkdir -p .ai/tasks/<taskId>` and `Write` the orchestration markdown to `.ai/tasks/<taskId>/orchestration.md` (sibling of `plan.md`).
|
|
137
|
+
3. **Base64-encode**: `b64=$(base64 -i .ai/tasks/<taskId>/orchestration.md)`.
|
|
138
138
|
4. **Create Linear attachment** via `mcp__linear__create_attachment`:
|
|
139
139
|
- `issue`: the task ID
|
|
140
140
|
- `filename`: `orchestration.md`
|
|
@@ -142,7 +142,7 @@ Then save it as an `orchestration.md` attachment on the task (not as a comment):
|
|
|
142
142
|
- `title`: `orchestration.md` (exact)
|
|
143
143
|
- `subtitle`: `Plan orkiestracji wygenerowany przez Claude Code (external)`
|
|
144
144
|
- `base64Content`: the base64 string from step 3
|
|
145
|
-
5. **
|
|
145
|
+
5. **Keep the local file**: do NOT delete `.ai/tasks/<taskId>/orchestration.md` — it persists as a gitignored local artifact.
|
|
146
146
|
|
|
147
147
|
### Step 4: Implement Each Step
|
|
148
148
|
|
|
@@ -177,7 +177,18 @@ Structure the plan as follows:
|
|
|
177
177
|
|
|
178
178
|
**MANDATORY.** Before any Linear write (subtask creation, attachment delete, attachment create, label apply), the user MUST approve the generated plan content. This is the gate FRA-126 added.
|
|
179
179
|
|
|
180
|
-
|
|
180
|
+
**Persist the plan locally first (both modes — this is the "przed akceptacją" save).**
|
|
181
|
+
|
|
182
|
+
- Ensure `.ai/tasks/` is gitignored (idempotent — `.ai/tasks` must NOT be synced to git):
|
|
183
|
+
```bash
|
|
184
|
+
grep -qxF '.ai/tasks/' .gitignore 2>/dev/null || echo '.ai/tasks/' >> .gitignore
|
|
185
|
+
```
|
|
186
|
+
- `mkdir -p .ai/tasks/<taskId>`
|
|
187
|
+
- Use the `Write` tool to save the Step 4 plan markdown to `.ai/tasks/<taskId>/plan.md`.
|
|
188
|
+
|
|
189
|
+
This file is the source for the Linear attachment in Step 6 and is NOT deleted — it persists as a gitignored local artifact. On regeneration (below) the `Write` overwrites it with the new plan.
|
|
190
|
+
|
|
191
|
+
**`--auto` mode**: Skip the approval prompt below — the plan is auto-approved and already persisted above. Record the auto-approval in the final Linear audit comment (e.g. `Plan zaakceptowany automatycznie (--auto)`). Proceed to Step 5.
|
|
181
192
|
|
|
182
193
|
**Default mode** (interactive):
|
|
183
194
|
|
|
@@ -233,20 +244,14 @@ If a `plan.md` attachment is being replaced:
|
|
|
233
244
|
|
|
234
245
|
- **`--auto` mode**: skip the prompt; delete the old Linear attachment via `mcp__linear__delete_attachment({ id: oldAttachmentId })` automatically and proceed.
|
|
235
246
|
|
|
236
|
-
#### 6.2 —
|
|
237
|
-
|
|
238
|
-
The plan content is exactly the markdown produced in Step 4. Write it to the temp file:
|
|
239
|
-
|
|
240
|
-
```bash
|
|
241
|
-
mkdir -p /tmp/claude-plans
|
|
242
|
-
```
|
|
247
|
+
#### 6.2 — Locate plan content
|
|
243
248
|
|
|
244
|
-
|
|
249
|
+
The plan content was already written to `.ai/tasks/<taskId>/plan.md` in Step 4a (before acceptance). No temp file is needed — that persistent, gitignored file is the source for the attachment below.
|
|
245
250
|
|
|
246
251
|
#### 6.3 — Base64-encode
|
|
247
252
|
|
|
248
253
|
```bash
|
|
249
|
-
b64=$(base64 -i /
|
|
254
|
+
b64=$(base64 -i .ai/tasks/<taskId>/plan.md)
|
|
250
255
|
```
|
|
251
256
|
|
|
252
257
|
#### 6.4 — Create Linear attachment
|
|
@@ -260,9 +265,9 @@ Call `mcp__linear__create_attachment` with:
|
|
|
260
265
|
- `subtitle`: `Plan wygenerowany przez Claude Code (external)`
|
|
261
266
|
- `base64Content`: the base64 string from 6.3
|
|
262
267
|
|
|
263
|
-
#### 6.5 —
|
|
268
|
+
#### 6.5 — Keep the local file
|
|
264
269
|
|
|
265
|
-
|
|
270
|
+
Do NOT delete `.ai/tasks/<taskId>/plan.md` — it is intentionally kept as a gitignored local artifact. `/push` leaves the Linear attachment in place.
|
|
266
271
|
|
|
267
272
|
### Step 7: Add "AI Plan" Label
|
|
268
273
|
|
|
@@ -352,8 +352,8 @@ The agent will:
|
|
|
352
352
|
|
|
353
353
|
1. **Check for existing `orchestration.md` attachment** on the task via `mcp__linear__get_issue` (response includes `attachments`).
|
|
354
354
|
- If one exists, delete it via `mcp__linear__delete_attachment({ id: oldAttachmentId })`. Linear hosts the file natively, so nothing else needs cleanup.
|
|
355
|
-
2. **Write locally**: `Write` the orchestration markdown to
|
|
356
|
-
3. **Base64-encode**: `b64=$(base64 -i /
|
|
355
|
+
2. **Write locally**: ensure `.ai/tasks/` is gitignored (idempotent — `.ai/tasks` must NOT be synced to git): `grep -qxF '.ai/tasks/' .gitignore 2>/dev/null || echo '.ai/tasks/' >> .gitignore`. Then `mkdir -p .ai/tasks/<taskId>` and `Write` the orchestration markdown to `.ai/tasks/<taskId>/orchestration.md` (sibling of `plan.md`).
|
|
356
|
+
3. **Base64-encode**: `b64=$(base64 -i .ai/tasks/<taskId>/orchestration.md)`.
|
|
357
357
|
4. **Create Linear attachment** via `mcp__linear__create_attachment`:
|
|
358
358
|
- `issue`: the task/subtask ID
|
|
359
359
|
- `filename`: `orchestration.md`
|
|
@@ -361,7 +361,7 @@ The agent will:
|
|
|
361
361
|
- `title`: `orchestration.md` (exact — used for detection/replacement on the next `/impl` run)
|
|
362
362
|
- `subtitle`: `Plan orkiestracji wygenerowany przez Claude Code (legacy)`
|
|
363
363
|
- `base64Content`: the base64 string from step 3
|
|
364
|
-
5. **
|
|
364
|
+
5. **Keep the local file**: do NOT delete `.ai/tasks/<taskId>/orchestration.md` — it persists as a gitignored local artifact.
|
|
365
365
|
6. **Follow the plan** — execute agents in the defined order.
|
|
366
366
|
7. **Use TDD strictly** — `shared-tdd-developer` is MANDATORY for ALL code implementation.
|
|
367
367
|
|
|
@@ -550,7 +550,18 @@ _Plan generated by Claude Code (flow-legacy)_
|
|
|
550
550
|
|
|
551
551
|
**MANDATORY.** Before any Linear write (deletion of old `plan.md`, creation of new `plan.md`, label apply), the user MUST approve the generated plan content. This is the gate FRA-126 added.
|
|
552
552
|
|
|
553
|
-
|
|
553
|
+
**Persist the plan locally first (both modes — this is the "przed akceptacją" save).** For each task/subtask that needs planning:
|
|
554
|
+
|
|
555
|
+
- Ensure `.ai/tasks/` is gitignored (idempotent — `.ai/tasks` must NOT be synced to git):
|
|
556
|
+
```bash
|
|
557
|
+
grep -qxF '.ai/tasks/' .gitignore 2>/dev/null || echo '.ai/tasks/' >> .gitignore
|
|
558
|
+
```
|
|
559
|
+
- `mkdir -p .ai/tasks/<taskId>`
|
|
560
|
+
- Use the `Write` tool to save the Step 8 plan markdown to `.ai/tasks/<taskId>/plan.md`.
|
|
561
|
+
|
|
562
|
+
This file is the source for the Linear attachment in Step 9a and is NOT deleted — it persists as a gitignored local artifact. On regeneration (below) the `Write` overwrites it with the new plan.
|
|
563
|
+
|
|
564
|
+
**`--auto` mode**: Skip the approval prompt below — the plan is auto-approved and already persisted above. Record the auto-approval in the final Linear audit comment (e.g. `Plan zaakceptowany automatycznie (--auto)`). Proceed to Step 9.
|
|
554
565
|
|
|
555
566
|
**Default mode** (interactive):
|
|
556
567
|
|
|
@@ -618,20 +629,14 @@ Use `AskUserQuestion` with options:
|
|
|
618
629
|
|
|
619
630
|
For each task that needs planning, upload the plan content directly to Linear (no external storage).
|
|
620
631
|
|
|
621
|
-
#### 9a.1 —
|
|
622
|
-
|
|
623
|
-
The plan content is exactly the markdown produced in Step 8. Write it to the temp file:
|
|
624
|
-
|
|
625
|
-
```bash
|
|
626
|
-
mkdir -p /tmp/claude-plans
|
|
627
|
-
```
|
|
632
|
+
#### 9a.1 — Locate plan content
|
|
628
633
|
|
|
629
|
-
|
|
634
|
+
The plan content was already written to `.ai/tasks/<taskId>/plan.md` in Step 8a (before acceptance). No temp file is needed — that persistent, gitignored file is the source for the attachment below.
|
|
630
635
|
|
|
631
636
|
#### 9a.2 — Base64-encode
|
|
632
637
|
|
|
633
638
|
```bash
|
|
634
|
-
b64=$(base64 -i /
|
|
639
|
+
b64=$(base64 -i .ai/tasks/<taskId>/plan.md)
|
|
635
640
|
```
|
|
636
641
|
|
|
637
642
|
On macOS `base64 -i <file>` outputs without line-wrapping. On Linux, pipe through `tr -d '\n'` if needed.
|
|
@@ -649,9 +654,9 @@ Call `mcp__linear__create_attachment` with:
|
|
|
649
654
|
|
|
650
655
|
Linear hosts the file on its own infrastructure.
|
|
651
656
|
|
|
652
|
-
#### 9a.4 —
|
|
657
|
+
#### 9a.4 — Keep the local file
|
|
653
658
|
|
|
654
|
-
|
|
659
|
+
Do NOT delete `.ai/tasks/<taskId>/plan.md` — it is intentionally kept as a gitignored local artifact. `/push` does NOT delete Linear attachments — they stay on the issue.
|
|
655
660
|
|
|
656
661
|
#### Scope rule
|
|
657
662
|
|
|
@@ -739,4 +744,4 @@ After saving:
|
|
|
739
744
|
- **Default mode**: Before saving the plans as attachments, show them to the user for review and approval.
|
|
740
745
|
- **`--auto` mode**: Skip the review step; proceed directly to saving the attachments.
|
|
741
746
|
|
|
742
|
-
The plan content is written to
|
|
747
|
+
The plan content is written to `.ai/tasks/<taskId>/plan.md` (before acceptance, gitignored), base64-encoded, and uploaded as a native Linear attachment via `mcp__linear__create_attachment`. After that, the `AI Plan` label is applied to the invoked issue.
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: angular-components-crud
|
|
3
|
+
description: Pro CRUD shell for @smartsoft001/pro-crud-shell-angular — ProCrudModule.forFeature wiring, 6 smartpro-* components with inputs/selectors, DYNAMIC_COMPONENTS_STORE override mechanism, cssClass/variant styling surface, known routed-wrapper projection limitation, and [class]-not-[class.smart:X] Tailwind rule.
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Pro CRUD Shell (`@smartsoft001/pro-crud-shell-angular`)
|
|
8
|
+
|
|
9
|
+
This package is the pro UI tier of the CRUD engine. It inherits all logic from
|
|
10
|
+
`@smartsoft001/crud-shell-angular` (config-driven routing, NgRx facades,
|
|
11
|
+
filter/sort/export/multiselect) and replaces the rendering layer with
|
|
12
|
+
`smartpro-*` components styled with the `smart:` Tailwind prefix.
|
|
13
|
+
|
|
14
|
+
## When to Use This Skill
|
|
15
|
+
|
|
16
|
+
- Developer wants to wire a CRUD feature with pro Tailwind UI → show `ProCrudModule.forFeature` setup
|
|
17
|
+
- Developer asks which pro CRUD components exist → show the component table below
|
|
18
|
+
- Developer asks how the engine selects the pro page over the free one → explain `DYNAMIC_COMPONENTS_STORE`
|
|
19
|
+
- Developer asks how to style the CRUD pages → show `cssClass` / `variant` on `CrudFullConfig`
|
|
20
|
+
- Developer gets a blank page despite the override being registered → point to the known routed-wrapper limitation
|
|
21
|
+
- Developer tries to use `[class.smart:X]` → apply the Tailwind rule
|
|
22
|
+
|
|
23
|
+
## Module Setup
|
|
24
|
+
|
|
25
|
+
### `ProCrudModule.forFeature`
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { NgModule } from '@angular/core';
|
|
29
|
+
import { ProCrudModule } from '@smartsoft001/pro-crud-shell-angular';
|
|
30
|
+
|
|
31
|
+
@NgModule({
|
|
32
|
+
imports: [
|
|
33
|
+
ProCrudModule.forFeature({
|
|
34
|
+
routing: true, // true -> ProCrudModule (routed pages); false -> ProCrudCoreModule (no routes)
|
|
35
|
+
config: userConfig, // CrudFullConfig<T>
|
|
36
|
+
// socket: true, // opt-in realtime provider (inert stub today)
|
|
37
|
+
}),
|
|
38
|
+
],
|
|
39
|
+
})
|
|
40
|
+
export class UserModule {}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`forFeature` delegates to the engine's `CrudModule.forFeature` for all engine
|
|
44
|
+
providers, then additionally provides `ProCrudListPageComponent` and
|
|
45
|
+
`ProCrudItemPageComponent` into `DYNAMIC_COMPONENTS_STORE`.
|
|
46
|
+
|
|
47
|
+
### `ProCrudCoreModule`
|
|
48
|
+
|
|
49
|
+
When `routing: false`, `forFeature` returns `ProCrudCoreModule`, which wraps
|
|
50
|
+
the engine's `CrudCoreModule` (logic without routed pages). Use this when you
|
|
51
|
+
manage routing yourself or compose the pro components manually.
|
|
52
|
+
|
|
53
|
+
## CrudFullConfig — Relevant Fields
|
|
54
|
+
|
|
55
|
+
Declare `CrudFullConfig<T>` from `@smartsoft001/crud-shell-angular`. The fields
|
|
56
|
+
below are the ones the pro layer reads directly; the full reference is in the
|
|
57
|
+
engine's README.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { CrudFullConfig } from '@smartsoft001/crud-shell-angular';
|
|
61
|
+
import { ListMode, PaginationMode } from '@smartsoft001/angular';
|
|
62
|
+
|
|
63
|
+
export const userConfig: CrudFullConfig<User> = {
|
|
64
|
+
apiUrl: 'https://api.example.com',
|
|
65
|
+
entity: 'user',
|
|
66
|
+
type: User,
|
|
67
|
+
|
|
68
|
+
title: 'Users',
|
|
69
|
+
details: true,
|
|
70
|
+
edit: true,
|
|
71
|
+
add: true,
|
|
72
|
+
remove: true,
|
|
73
|
+
search: true,
|
|
74
|
+
export: true,
|
|
75
|
+
pagination: { limit: 25 },
|
|
76
|
+
sort: { default: 'lastName', defaultDesc: false },
|
|
77
|
+
list: {
|
|
78
|
+
mode: ListMode.desktop,
|
|
79
|
+
paginationMode: PaginationMode.singlePage,
|
|
80
|
+
groups: [], // optional — activates the group accordion
|
|
81
|
+
},
|
|
82
|
+
inputComponents: {}, // per-field input overrides keyed by field name
|
|
83
|
+
|
|
84
|
+
// Pro styling surface (tier 2)
|
|
85
|
+
cssClass: 'smart:bg-gray-50', // forwarded as [class] to page host
|
|
86
|
+
variant: 'with-actions', // picks the smartpro-page-* variant
|
|
87
|
+
};
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## DYNAMIC_COMPONENTS_STORE Override Mechanism
|
|
91
|
+
|
|
92
|
+
The engine resolves `'crud-list-page'` and `'crud-item-page'` dynamic slots
|
|
93
|
+
against `DYNAMIC_COMPONENTS_STORE`. Each pro page component carries a static
|
|
94
|
+
`smartType` field that matches those keys:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// Pro list page
|
|
98
|
+
ProCrudListPageComponent.smartType = 'crud-list-page';
|
|
99
|
+
|
|
100
|
+
// Pro item page
|
|
101
|
+
ProCrudItemPageComponent.smartType = 'crud-item-page';
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`ProCrudModule.forFeature` registers both into the token:
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
{
|
|
108
|
+
provide: DYNAMIC_COMPONENTS_STORE,
|
|
109
|
+
useValue: [ProCrudListPageComponent, ProCrudItemPageComponent],
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The engine's dynamic-component resolver checks `DYNAMIC_COMPONENTS_STORE` first
|
|
114
|
+
and selects the pro variant over the free standard variant for those two slots.
|
|
115
|
+
|
|
116
|
+
## Component Reference
|
|
117
|
+
|
|
118
|
+
All six components are `ChangeDetectionStrategy.OnPush` and extend an engine
|
|
119
|
+
base class that provides all facade wiring.
|
|
120
|
+
|
|
121
|
+
| Selector | Class | Extends | Purpose |
|
|
122
|
+
| --------------------------- | ----------------------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
123
|
+
| `smartpro-crud-list-page` | `ProCrudListPageComponent` | `CrudListPageBaseComponent` | List page: `smart-crud-filters-config` + `smartpro-list`; shows group accordion when `config.list.groups` is set; hides flat list during search |
|
|
124
|
+
| `smartpro-crud-item-page` | `ProCrudItemPageComponent` | `CrudItemPageBaseComponent` | Item page: `smartpro-details` in details mode; `smart-form` with `config.inputComponents` in add/update mode |
|
|
125
|
+
| `smartpro-crud-filters` | `ProCrudFiltersComponent` | `FiltersBaseComponent` | Filters panel: Tailwind header with close button; individual filter controls via engine `smart-crud-filter` |
|
|
126
|
+
| `smartpro-crud-group` | `ProCrudGroupComponent` | `GroupBaseComponent` | Group accordion: accessible `button`/region with `aria-expanded`, rotating chevron; recursive child group support; embeds `smartpro-list` for leaf groups |
|
|
127
|
+
| `smartpro-crud-multiselect` | `ProCrudMultiselectComponent` | `MultiselectBaseComponent` | Multiselect panel: count header with close; optional `config.list.components.multi` outlet; multi-update `smart-form` + `smartpro-button` submit |
|
|
128
|
+
| `smartpro-crud-export` | `ProCrudExportComponent` | `ExportBaseComponent` | Export popover: CSV and XLSX triggers via `smartpro-button`; `config.cssClass` forwarded to wrapper |
|
|
129
|
+
|
|
130
|
+
### Key inputs (inherited from engine base classes)
|
|
131
|
+
|
|
132
|
+
| Component | Signal/Input | Source | Description |
|
|
133
|
+
| --------------------------- | ---------------------------------------------------- | --------------------------- | -------------------------------------------------------------------- |
|
|
134
|
+
| `smartpro-crud-list-page` | `listOptions()` | `CrudListPageBaseComponent` | `IListOptionsPro<T>` fed to `smartpro-list` |
|
|
135
|
+
| `smartpro-crud-list-page` | `config` | `inject(CrudFullConfig)` | Full config (groups, cssClass, variant) |
|
|
136
|
+
| `smartpro-crud-item-page` | `mode()` | `CrudItemPageBaseComponent` | `'details' \| 'add' \| 'update'` |
|
|
137
|
+
| `smartpro-crud-item-page` | `detailsOptions()` | `CrudItemPageBaseComponent` | Options fed to `smartpro-details` |
|
|
138
|
+
| `smartpro-crud-item-page` | `selected()` | `CrudItemPageBaseComponent` | Current entity fed to `smart-form` |
|
|
139
|
+
| `smartpro-crud-filters` | `list()` | `FiltersBaseComponent` | Array of filter items; each rendered by `smart-crud-filter` |
|
|
140
|
+
| `smartpro-crud-filters` | `hideMenu()` | `FiltersBaseComponent` | Hides the header row when `true` |
|
|
141
|
+
| `smartpro-crud-group` | `groups()` | `GroupBaseComponent` | Array of group nodes with `key`, `text`, `show`, optional `children` |
|
|
142
|
+
| `smartpro-crud-group` | `listOptions()` | `GroupBaseComponent` | `IListOptionsPro<T>` for leaf group `smartpro-list` |
|
|
143
|
+
| `smartpro-crud-multiselect` | `list()` | `MultiselectBaseComponent` | Array of selected entities |
|
|
144
|
+
| `smartpro-crud-export` | `buttonExportCsvOptions` / `buttonExportXlsxOptions` | `ExportBaseComponent` | `IButtonOptions` for each trigger |
|
|
145
|
+
|
|
146
|
+
## Styling Rules
|
|
147
|
+
|
|
148
|
+
### Tier-2 surface: `cssClass` and `variant`
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// In CrudFullConfig
|
|
152
|
+
cssClass: 'smart:bg-gray-50 smart:rounded-xl',
|
|
153
|
+
variant: 'with-actions', // any SmartPageVariant from @smartsoft001/pro-angular
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
- `cssClass` is bound as `[class]` on the page host element of the list and item pages, and on the export wrapper.
|
|
157
|
+
- `variant` is threaded into `pageOptions().variant`, which `SmartProComponentsModule` resolves to the matching `smartpro-page-*` component via `PAGE_VARIANT_COMPONENTS_TOKEN`.
|
|
158
|
+
|
|
159
|
+
### Tailwind `smart:` prefix — no `[class.smart:X]` shorthand
|
|
160
|
+
|
|
161
|
+
Angular's `[class.X]` shorthand treats the full string `smart:X` as the class
|
|
162
|
+
name, which breaks the Tailwind `smart:` prefix during JIT purging.
|
|
163
|
+
|
|
164
|
+
```html
|
|
165
|
+
<!-- WRONG -->
|
|
166
|
+
<div [class.smart:font-semibold]="isActive"></div>
|
|
167
|
+
|
|
168
|
+
<!-- CORRECT -->
|
|
169
|
+
<div [class]="isActive ? 'smart:font-semibold' : ''"></div>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
All pro CRUD components follow this rule. Enforce it in any customization.
|
|
173
|
+
|
|
174
|
+
## Known Limitation — Routed Wrappers Do Not Project the Pro Page
|
|
175
|
+
|
|
176
|
+
The engine's free routed wrappers (`smart-crud-list-page` /
|
|
177
|
+
`smart-crud-item-page`) use `CreateDynamicComponent` to mount the override
|
|
178
|
+
found in `DYNAMIC_COMPONENTS_STORE`. The wrapper templates currently do not
|
|
179
|
+
include `DynamicContentDirective` in their `imports` array, so the pro component
|
|
180
|
+
is instantiated but not inserted into the DOM — the page renders blank.
|
|
181
|
+
|
|
182
|
+
**This is an engine-side fix pending in `@smartsoft001/crud-shell-angular`.**
|
|
183
|
+
|
|
184
|
+
Until the fix lands, mount the pro pages directly instead of relying on the
|
|
185
|
+
routed wrappers:
|
|
186
|
+
|
|
187
|
+
```html
|
|
188
|
+
<smartpro-crud-list-page></smartpro-crud-list-page>
|
|
189
|
+
<smartpro-crud-item-page></smartpro-crud-item-page>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Or compose the components manually inside your own page shell.
|
|
193
|
+
|
|
194
|
+
## Usage Example
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
// user.module.ts
|
|
198
|
+
import { NgModule } from '@angular/core';
|
|
199
|
+
import { ProCrudModule } from '@smartsoft001/pro-crud-shell-angular';
|
|
200
|
+
import { userConfig } from './user.config';
|
|
201
|
+
|
|
202
|
+
@NgModule({
|
|
203
|
+
imports: [ProCrudModule.forFeature({ routing: true, config: userConfig })],
|
|
204
|
+
})
|
|
205
|
+
export class UserModule {}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
```html
|
|
209
|
+
<!-- user-list.page.html — direct mount (recommended until engine fix) -->
|
|
210
|
+
<smartpro-crud-list-page></smartpro-crud-list-page>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
```html
|
|
214
|
+
<!-- user-item.page.html -->
|
|
215
|
+
<smartpro-crud-item-page></smartpro-crud-item-page>
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Compositional use — embed only the filters panel in a custom page shell:
|
|
219
|
+
|
|
220
|
+
```html
|
|
221
|
+
<aside class="smart:w-72">
|
|
222
|
+
<smartpro-crud-filters></smartpro-crud-filters>
|
|
223
|
+
</aside>
|
|
224
|
+
<main>
|
|
225
|
+
<!-- your own content -->
|
|
226
|
+
</main>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## File Locations
|
|
230
|
+
|
|
231
|
+
- Package: `packages/crud/shell/pro-angular/`
|
|
232
|
+
- Module: `packages/crud/shell/pro-angular/src/lib/pro-crud.module.ts`
|
|
233
|
+
- Pages: `packages/crud/shell/pro-angular/src/lib/pages/{list,item}/`
|
|
234
|
+
- Components: `packages/crud/shell/pro-angular/src/lib/components/{filters,group,multiselect,export}/`
|
|
235
|
+
- Barrel: `packages/crud/shell/pro-angular/src/index.ts`
|
|
236
|
+
- README: `packages/crud/shell/pro-angular/README.md`
|