@smartsoft001-mobilems/claude-plugins 2.86.0 → 2.87.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.
Files changed (46) hide show
  1. package/package.json +1 -1
  2. package/plugins/mobilems/.claude-plugin/plugin.json +1 -1
  3. package/plugins/mobilems/skills/mobilems-articles/SKILL.md +84 -0
  4. package/plugins/mobilems/skills/mobilems-articles/references/lib-contents.md +164 -0
  5. package/plugins/mobilems/skills/mobilems-articles/references/module-and-routes.md +146 -0
  6. package/plugins/mobilems/skills/mobilems-articles/references/shared-components.md +56 -0
  7. package/plugins/mobilems/skills/mobilems-articles/scripts/detect-init.sh +29 -0
  8. package/plugins/mobilems/skills/mobilems-articles/scripts/verify-module.sh +61 -0
  9. package/plugins/mobilems/skills/mobilems-events/SKILL.md +65 -0
  10. package/plugins/mobilems/skills/mobilems-events/references/lib-contents.md +212 -0
  11. package/plugins/mobilems/skills/mobilems-events/references/module-and-routes.md +113 -0
  12. package/plugins/mobilems/skills/mobilems-events/scripts/detect-init.sh +29 -0
  13. package/plugins/mobilems/skills/mobilems-events/scripts/verify-module.sh +59 -0
  14. package/plugins/mobilems/skills/mobilems-object-collections/SKILL.md +52 -0
  15. package/plugins/mobilems/skills/mobilems-object-collections/references/lib-contents.md +76 -0
  16. package/plugins/mobilems/skills/mobilems-object-collections/references/module-and-routes.md +116 -0
  17. package/plugins/mobilems/skills/mobilems-object-collections/references/shared-components.md +61 -0
  18. package/plugins/mobilems/skills/mobilems-object-collections/scripts/detect-init.sh +29 -0
  19. package/plugins/mobilems/skills/mobilems-object-collections/scripts/verify-module.sh +44 -0
  20. package/plugins/mobilems/skills/mobilems-objects/SKILL.md +52 -0
  21. package/plugins/mobilems/skills/mobilems-objects/references/lib-contents.md +68 -0
  22. package/plugins/mobilems/skills/mobilems-objects/references/module-and-routes.md +108 -0
  23. package/plugins/mobilems/skills/mobilems-objects/references/shared-components.md +69 -0
  24. package/plugins/mobilems/skills/mobilems-objects/scripts/detect-init.sh +29 -0
  25. package/plugins/mobilems/skills/mobilems-objects/scripts/verify-module.sh +51 -0
  26. package/plugins/mobilems/skills/mobilems-partners/SKILL.md +65 -0
  27. package/plugins/mobilems/skills/mobilems-partners/references/lib-contents.md +160 -0
  28. package/plugins/mobilems/skills/mobilems-partners/references/module-and-routes.md +125 -0
  29. package/plugins/mobilems/skills/mobilems-partners/scripts/detect-init.sh +29 -0
  30. package/plugins/mobilems/skills/mobilems-partners/scripts/verify-module.sh +59 -0
  31. package/plugins/mobilems/skills/mobilems-project-init/SKILL.md +134 -0
  32. package/plugins/mobilems/skills/mobilems-project-init/references/app-shell.md +107 -0
  33. package/plugins/mobilems/skills/mobilems-project-init/references/claude-config.md +44 -0
  34. package/plugins/mobilems/skills/mobilems-project-init/references/config-providers.md +203 -0
  35. package/plugins/mobilems/skills/mobilems-project-init/references/npm-deps.md +66 -0
  36. package/plugins/mobilems/skills/mobilems-project-init/references/server-env.md +89 -0
  37. package/plugins/mobilems/skills/mobilems-project-init/references/shared-lib.md +125 -0
  38. package/plugins/mobilems/skills/mobilems-project-init/references/tailwind-styles.md +106 -0
  39. package/plugins/mobilems/skills/mobilems-project-init/scripts/classify-shared-components.py +114 -0
  40. package/plugins/mobilems/skills/mobilems-project-init/scripts/detect-base.sh +49 -0
  41. package/plugins/mobilems/skills/mobilems-project-init/scripts/verify-init.sh +73 -0
  42. package/plugins/mobilems/skills/mobilems-thematic-publications/SKILL.md +60 -0
  43. package/plugins/mobilems/skills/mobilems-thematic-publications/references/lib-contents.md +134 -0
  44. package/plugins/mobilems/skills/mobilems-thematic-publications/references/module-and-routes.md +107 -0
  45. package/plugins/mobilems/skills/mobilems-thematic-publications/scripts/detect-init.sh +29 -0
  46. package/plugins/mobilems/skills/mobilems-thematic-publications/scripts/verify-module.sh +56 -0
@@ -0,0 +1,61 @@
1
+ # Collections shared components
2
+
3
+ The collections module contributes one shared component to `libs/shared/angular` — the part of the
4
+ shared UI that renders a museum collection and therefore depends on
5
+ `@smartsoft001-mobilems/public-collections-domain`. Build it by copying from the reference repo's
6
+ `libs/shared/angular/src/lib` and threading `<PREFIX>`. Every step is idempotent — if the target
7
+ already exists, leave it.
8
+
9
+ All paths below are under `libs/shared/angular/src/lib`.
10
+
11
+ ## 1. Collection card component
12
+
13
+ Build this component directory and export it from `components/index.ts`:
14
+
15
+ | Component | Renders |
16
+ | ---------------------------------- | ---------------------------------- |
17
+ | `components/collections-grid-item` | a collection card in the grid view |
18
+
19
+ ```ts
20
+ // components/index.ts — this export belongs to the collections module:
21
+ export * from './collections-grid-item';
22
+ ```
23
+
24
+ `collections-grid-item` carries its own `index.ts`
25
+ (`export * from './collections-grid-item.component';`) plus the `.component.ts` + `.component.html`.
26
+ Build the whole dir from the reference and thread `<PREFIX>`.
27
+
28
+ The build-safety grep over the reference shared lib confirms which components depend on the
29
+ public-collections feature package — it should list only `collections-grid-item`:
30
+
31
+ ```bash
32
+ grep -rlnE "from '@[^']*/(public-collections)-(domain|shell-angular|shell-dtos)'" \
33
+ <reference-repo>/libs/shared/angular/src
34
+ ```
35
+
36
+ ## 2. No widget, no model type
37
+
38
+ Unlike `mobilems-objects`, collections contributes **nothing** to the widget container
39
+ (`components/widget/widget.component.ts`) and **no** model type to `models/`. There is no
40
+ `GALLERY_COLLECTION` widget type. Do not touch the widget container or the models dir.
41
+
42
+ ## 3. Cross-module dependency — the collection detail page renders related objects + articles
43
+
44
+ The collection **item/detail page** (`libs/museum-collections/shell/angular/.../pages/item`) shows
45
+ related objects and articles, so it imports the object and article card shared components
46
+ (`ObjectsGridItemComponent`/`ObjectsListItemComponent` and `ArticlesGridItemComponent`/
47
+ `ArticlesListItemComponent`) from `@<PREFIX>/angular`, and uses `MsObject` (objects-domain) /
48
+ `Article` (articles-domain). Those cards are built by `mobilems-objects` / `mobilems-articles`, so the
49
+ collections module is **not** fully standalone — its detail page assumes those modules' card
50
+ components exist.
51
+
52
+ When you add collections, check which of those cards the copied item page imports and confirm they're
53
+ exported from `components/index.ts`. If a needed card isn't there yet (its module hasn't been added),
54
+ either add that module first, build the missing card component here (it's just an Article/MsObject
55
+ card — copy it from the reference like `collections-grid-item`), or remove the related-content section
56
+ from the item page. Don't leave a dangling import — it will not compile.
57
+
58
+ ## Verify
59
+
60
+ `scripts/verify-module.sh` checks that the `collections-grid-item` component exists and is exported
61
+ from `components/index.ts`.
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # detect-init.sh <workspace-root>
4
+ #
5
+ # Precondition gate for mobilems-objects (and the other module skills follow the same shape):
6
+ # confirm the MobilEMS foundation from mobilems-project-init is present. Portable to macOS bash 3.2.
7
+ #
8
+ # Exit 0 → foundation present, OK to add the module.
9
+ # Exit 3 → foundation missing (tell the user to run /mobilems:project-init first).
10
+ set -eu
11
+
12
+ ROOT="${1:?usage: detect-init.sh <workspace-root>}"
13
+ cd "$ROOT" 2>/dev/null || { echo "ERROR: no such dir: $ROOT" >&2; exit 2; }
14
+
15
+ miss() {
16
+ echo "FOUNDATION MISSING: $1" >&2
17
+ echo "Run /mobilems:project-init first to lay down the MobilEMS foundation." >&2
18
+ exit 3
19
+ }
20
+
21
+ [ -f apps/web/src/app/app.config.ts ] || miss "app.config.ts missing"
22
+ grep -q "SharedModule.forRoot" apps/web/src/app/app.config.ts || miss "SharedModule.forRoot not in app.config.ts (foundation not applied)"
23
+ grep -q "./lib/components" libs/shared/angular/src/index.ts 2>/dev/null || miss "shared-lib components barrel not populated"
24
+ [ -f apps/web/src/app/app.routes.ts ] || miss "app.routes.ts missing"
25
+
26
+ PREFIX="$(grep -oE '@[a-z0-9-]+/angular' tsconfig.base.json | head -1 | sed -E 's#@([a-z0-9-]+)/angular#\1#')"
27
+ echo "FOUNDATION OK. Detected prefix: ${PREFIX:-<unknown>}"
28
+ [ -d libs/museum-objects ] && echo "NOTE: libs/museum-objects already exists — build steps must be idempotent." >&2
29
+ exit 0
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # verify-module.sh <workspace-root> <PREFIX>
4
+ #
5
+ # Post-condition check for mobilems-object-collections: library created, route registered (top-level
6
+ # + search child), the collections shared component built + exported, public-collections deps present.
7
+ # macOS bash 3.2 safe.
8
+ set -eu
9
+
10
+ ROOT="${1:?usage: verify-module.sh <workspace-root> <PREFIX>}"
11
+ PREFIX="${2:?usage: verify-module.sh <workspace-root> <PREFIX>}"
12
+ cd "$ROOT" 2>/dev/null || { echo "ERROR: no such dir: $ROOT" >&2; exit 2; }
13
+
14
+ fail=0
15
+ pass() { echo " PASS: $1"; }
16
+ bad() { echo " FAIL: $1" >&2; fail=1; }
17
+
18
+ echo "== Library =="
19
+ [ -f libs/museum-collections/shell/angular/src/lib/collections.module.ts ] && pass "MuseumCollectionsModule present" || bad "collections.module.ts missing"
20
+ [ -f libs/museum-collections/domain/src/lib/entities/museum-collection.entity.ts ] && pass "MuseumCollection entity present" || bad "domain entity missing"
21
+ grep -q "MuseumCollection" libs/museum-collections/domain/src/lib/entities/museum-collection.entity.ts 2>/dev/null && pass "MuseumCollection class declared" || bad "MuseumCollection class missing"
22
+ grep -q "museum-collections/shell/angular" tsconfig.base.json && pass "tsconfig path added" || bad "tsconfig.base.json path missing"
23
+ grep -q "PublicCollectionsSharedModule.forFeature" libs/museum-collections/shell/angular/src/lib/collections.module.ts 2>/dev/null && pass "forFeature wired" || bad "PublicCollectionsSharedModule.forFeature missing"
24
+
25
+ echo "== Route registration =="
26
+ ROUTES=apps/web/src/app/app.routes.ts
27
+ grep -q "museum-collections/shell/angular" "$ROUTES" && pass "collections route registered" || bad "collections route not in app.routes.ts"
28
+ # top-level + search child — expect at least 2 occurrences
29
+ n=$(grep -c "museum-collections/shell/angular" "$ROUTES" || true)
30
+ [ "${n:-0}" -ge 2 ] && pass "registered top-level + search child ($n)" || bad "expected route top-level + search child, found $n"
31
+
32
+ echo "== Collections shared components =="
33
+ COMP=libs/shared/angular/src/lib/components
34
+ [ -d "$COMP/collections-grid-item" ] && pass "built collections-grid-item" || bad "missing $COMP/collections-grid-item"
35
+ grep -q "collections-grid-item" "$COMP/index.ts" && pass "collections-grid-item exported" || bad "collections-grid-item export missing"
36
+
37
+ echo "== Deps =="
38
+ grep -q "@smartsoft001-mobilems/public-collections-domain" package.json && pass "public-collections-domain dep" || bad "public-collections-domain dep missing"
39
+ grep -q "@smartsoft001-mobilems/public-collections-shell-angular" package.json && pass "public-collections-shell-angular dep" || bad "public-collections-shell-angular dep missing"
40
+ grep -q "@smartsoft001-mobilems/public-collections-shell-dtos" package.json && pass "public-collections-shell-dtos dep" || bad "public-collections-shell-dtos dep missing"
41
+
42
+ echo
43
+ if [ "$fail" = 0 ]; then echo "VERIFY: all checks passed."; else echo "VERIFY: FAILED — fix the items above and re-run." >&2; fi
44
+ exit "$fail"
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: mobilems-objects
3
+ description: Add the museum OBJECTS feature module to a MobilEMS app initialized with mobilems-project-init. Use whenever the user wants to add / scaffold / wire the objects (obiekty) module, museum object list + detail pages, object tabs (images, map, audio, 3D, animation, virtual walk), or asks to "dodaj moduł obiektów / eksponatów". Creates libs/museum-objects (domain + shell/angular), registers the /obiekty route, builds the objects shared components, and adds the objects npm packages. Requires the MobilEMS foundation to exist first.
4
+ user-invocable: true
5
+ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion
6
+ ---
7
+
8
+ # MobilEMS objects module
9
+
10
+ Add the **objects** (obiekty) feature module to a MobilEMS app whose foundation was built by
11
+ `mobilems-project-init`. This skill builds the `libs/museum-objects` library, the objects shared
12
+ components, the objects route, and adds the objects npm packages.
13
+
14
+ Objects is the richest module — a list/detail view with a tabbed detail (images deep-zoom, Leaflet
15
+ map, audio, 3D model, animation, virtual walk) backed by `ObjectsSharedModule.forFeature` over the
16
+ `MsObject` entity.
17
+
18
+ ## Precondition
19
+
20
+ Run `scripts/detect-init.sh <workspace-root>`. It confirms the MobilEMS foundation is present
21
+ (`SharedModule.forRoot` in `app.config.ts`, a populated shared-lib barrel). If not, tell the user to
22
+ run `/mobilems:project-init` first. Hold `<PREFIX>` (from `tsconfig.base.json`; reference uses
23
+ `@msr`) and the reference repo path (same one init used).
24
+
25
+ ## Steps
26
+
27
+ 1. **npm deps** — add `@smartsoft001-mobilems/objects-domain`, `@smartsoft001-mobilems/objects-shell-angular`,
28
+ `@smartsoft001-mobilems/objects-shell-dtos` (match the installed mobilems line) and
29
+ `online-3d-viewer` (the 3D tab; `leaflet`/`openseadragon`/`swiper` are already foundation deps).
30
+ Resolve versions at run time; do not `npm install` unless asked.
31
+ 2. **Library** — create `libs/museum-objects/{domain,shell/angular}` per `references/lib-contents.md`:
32
+ copy the domain entity/enums and the shell (`MuseumObjectsModule`, routes, `components/*`,
33
+ `pages/{list,item}`, `services`), thread `<PREFIX>`. Add the two `tsconfig.base.json` paths and the
34
+ `museum-objects` commit scope.
35
+ 3. **Module + routes** — see `references/module-and-routes.md`: `MuseumObjectsModule` wraps
36
+ `ObjectsSharedModule.forFeature({ routing: false, config: { type: MsObject, apiUrl, entity: 'objects' } })`
37
+ with the `Masonry` SSR factory. Add the lazy `obiekty` route to `appRoutes` in
38
+ `apps/web/src/app/app.routes.ts` and a matching child under the `wyszukaj/:text` search route.
39
+ 4. **Objects shared components** — see `references/shared-components.md`: build `objects-grid-item`,
40
+ `objects-list-item`, and the object gallery widget (`widget/gallery-object`) in the shared lib +
41
+ export them; register the object gallery widget in the widget content-type map (`GALLERY_OBJECT`);
42
+ and add `ISpecificObject` (extends `MsObject`) to `models/objects.model.ts`.
43
+ 5. **Verify** — run `scripts/verify-module.sh <workspace-root> <PREFIX>`: asserts the lib exists, the
44
+ `obiekty` route is registered (top-level + search child), the objects shared components are built
45
+ and exported, the widget map registers the object gallery widget, and `ISpecificObject` is present.
46
+ Fix and re-run.
47
+
48
+ ## Notes
49
+
50
+ - This skill builds only the objects module + its shared components + its route. It never adds other
51
+ feature modules and never re-runs the foundation.
52
+ - Bundled `references/` + `scripts/` ship automatically. Do not hand-edit `plugin.json`.
@@ -0,0 +1,68 @@
1
+ # libs/museum-objects — structure to create
2
+
3
+ Copy from the reference repo's `libs/museum-objects` and thread `<PREFIX>`. The lib has two
4
+ projects: a `domain` (entities/enums) and a `shell/angular` (the Angular module + UI).
5
+
6
+ ```
7
+ libs/museum-objects/
8
+ ├── domain/ # project: museum-objects-domain
9
+ │ └── src/
10
+ │ ├── index.ts # export * from './lib/entities'; export * from './lib/enums';
11
+ │ └── lib/
12
+ │ ├── entities/ # MuseumObject extends MsObject (+ index)
13
+ │ ├── enums/ # connection-type.enum (+ index)
14
+ │ ├── specifications/
15
+ │ └── value-objects/
16
+ └── shell/angular/ # project: museum-objects-shell-angular
17
+ └── src/
18
+ ├── index.ts # export * from './pages'; export * from './objects.module';
19
+ ├── __mocks__/ # jest mocks for the @smartsoft001-mobilems/* feature pkgs
20
+ └── lib/
21
+ ├── objects.module.ts # MuseumObjectsModule (references/module-and-routes.md)
22
+ ├── objects.routes.ts
23
+ ├── components/ # description, filter-input, high-def-request-modal,
24
+ │ # menu, objects-searchbar, tabs/*
25
+ ├── pages/ # list (ListComponent), item (ItemComponent) + index
26
+ └── services/ # objects.service.ts + index
27
+ ```
28
+
29
+ ## Domain entity (verbatim, thread nothing — pure types)
30
+
31
+ ```ts
32
+ import { Field, Model } from '@smartsoft001/models';
33
+ import { MsObject } from '@smartsoft001-mobilems/objects-domain';
34
+
35
+ @Model({})
36
+ export class MuseumObject extends MsObject {
37
+ historicalProvenance?: any;
38
+ seriesTitles?: any;
39
+ imageDesktop?: any;
40
+ virtualExhibitionSlides?: any;
41
+ shareMuseumObjectMultimediaEnabled!: boolean;
42
+ }
43
+ ```
44
+
45
+ ## Wiring
46
+
47
+ - **tsconfig.base.json paths** (add both):
48
+ ```json
49
+ "@<PREFIX>/museum-objects/domain": ["libs/museum-objects/domain/src/index.ts"],
50
+ "@<PREFIX>/museum-objects/shell/angular": ["libs/museum-objects/shell/angular/src/index.ts"]
51
+ ```
52
+ - **project.json / build config** — copy each project's build config and normalize every path field
53
+ that the reference baked to its origin location — `sourceRoot`, `dest`, `outputPath`,
54
+ `coverageDirectory`, `jestConfig`, `lintFilePatterns`, and the jest `displayName` — to `libs/museum-objects/...`. Some
55
+ reference modules carry stale values here (e.g. a shell `sourceRoot` missing the `shell/angular`
56
+ segment, or a `coverageDirectory` under `packages/...`) while others are already correct — verify
57
+ each field against a known-good sibling lib and fix only the ones that are actually wrong. The
58
+ `domain` project may ship no `project.json` at all (Nx infers its targets from `package.json` +
59
+ `jest.config`) — that's fine, leave it inferred; just set its `package.json` `name` to
60
+ `museum-objects-domain`.
61
+ - **commit scope** — `commitlint.config.js` reads `libs/` dir names, so `museum-objects` becomes a
62
+ valid scope automatically; no edit needed.
63
+ - **jest `__mocks__`** — keep the `src/__mocks__/@smartsoft001-mobilems/*` stubs from the reference;
64
+ they let the shell unit-test without the real feature packages.
65
+
66
+ The tabs (`tabs/*`) include the 3D model tab, which uses `online-3d-viewer` — that's why this skill
67
+ adds that dep. The map tab uses `leaflet`, images use `openseadragon`/`swiper` — already foundation
68
+ deps.
@@ -0,0 +1,108 @@
1
+ # MuseumObjectsModule + route registration
2
+
3
+ ## `libs/museum-objects/shell/angular/src/lib/objects.module.ts`
4
+
5
+ Thread `<PREFIX>` (the `environment` import). `ObjectsSharedModule.forFeature` provides the list/detail
6
+ behaviour over `MsObject`; the `Masonry` factory returns the real library in the browser and a no-op
7
+ mock during SSR.
8
+
9
+ ```ts
10
+ import { NgModule } from '@angular/core';
11
+ import { FormsModule } from '@angular/forms';
12
+ import { RouterModule } from '@angular/router';
13
+ import { SharedModule as SmartSharedModule } from '@smartsoft001/angular';
14
+ import { MsObject } from '@smartsoft001-mobilems/objects-domain';
15
+ import { ObjectsSharedModule } from '@smartsoft001-mobilems/objects-shell-angular';
16
+ import { Masonry } from '@thisissoon/angular-masonry';
17
+
18
+ import { environment } from '@<PREFIX>/angular';
19
+
20
+ import { routes } from './objects.routes';
21
+
22
+ @NgModule({
23
+ providers: [
24
+ {
25
+ provide: Masonry,
26
+ useFactory: () => {
27
+ if (typeof window !== 'undefined' && (window as any)['Masonry']) {
28
+ return (window as any)['Masonry'];
29
+ }
30
+ // Return a mock for SSR
31
+ return class {
32
+ constructor() {
33
+ // no-op
34
+ }
35
+ layout() {
36
+ return;
37
+ }
38
+ reloadItems() {
39
+ return;
40
+ }
41
+ destroy() {
42
+ return;
43
+ }
44
+ };
45
+ },
46
+ },
47
+ ],
48
+ imports: [
49
+ FormsModule,
50
+ SmartSharedModule,
51
+ ObjectsSharedModule.forFeature({
52
+ routing: false,
53
+ config: {
54
+ type: MsObject,
55
+ apiUrl: environment.apiUrl,
56
+ entity: 'objects',
57
+ },
58
+ }),
59
+ RouterModule.forChild(routes),
60
+ ],
61
+ })
62
+ export class MuseumObjectsModule {}
63
+ ```
64
+
65
+ ## `objects.routes.ts`
66
+
67
+ ```ts
68
+ import { Route } from '@angular/router';
69
+
70
+ import { ItemComponent, ListComponent } from './pages';
71
+
72
+ export const routes: Route[] = [
73
+ { path: ':id/:slug', component: ItemComponent },
74
+ { path: ':id', component: ItemComponent },
75
+ { path: '', component: ListComponent },
76
+ ];
77
+ ```
78
+
79
+ ## Register in `apps/web/src/app/app.routes.ts`
80
+
81
+ Add the objects route to the `appRoutes` array (idempotently — if an `obiekty` route already exists,
82
+ skip). Add it as a top-level route, and as a child of the `wyszukaj/:text` search route so
83
+ `/wyszukaj/:text/obiekty` works and the search view's `redirectTo: 'obiekty'` default resolves.
84
+
85
+ Top-level — add to `appRoutes`:
86
+
87
+ ```ts
88
+ {
89
+ path: 'obiekty',
90
+ loadChildren: () =>
91
+ import('@<PREFIX>/museum-objects/shell/angular').then(
92
+ (m) => m.MuseumObjectsModule,
93
+ ),
94
+ },
95
+ ```
96
+
97
+ Search child — add to the `children` of the `wyszukaj/:text` route, before the
98
+ `{ path: '', redirectTo: 'obiekty' }` default:
99
+
100
+ ```ts
101
+ {
102
+ path: 'obiekty',
103
+ loadChildren: () =>
104
+ import('@<PREFIX>/museum-objects/shell/angular').then(
105
+ (m) => m.MuseumObjectsModule,
106
+ ),
107
+ },
108
+ ```
@@ -0,0 +1,69 @@
1
+ # Objects shared components
2
+
3
+ The objects module contributes a few shared components to `libs/shared/angular` — the parts of the
4
+ shared UI that render a museum object and therefore depend on `@smartsoft001-mobilems/objects-domain`.
5
+ Build them by copying from the reference repo's `libs/shared/angular/src/lib` and threading
6
+ `<PREFIX>`. Every step is idempotent — if the target already exists, leave it.
7
+
8
+ All paths below are under `libs/shared/angular/src/lib`.
9
+
10
+ ## 1. Object card components
11
+
12
+ Build these component directories and export them from `components/index.ts`:
13
+
14
+ | Component | Renders |
15
+ | ------------------------------ | ------------------------------- |
16
+ | `components/objects-grid-item` | an object card in the grid view |
17
+ | `components/objects-list-item` | an object row in the list view |
18
+
19
+ ```ts
20
+ // components/index.ts — these exports belong to the objects module:
21
+ export * from './objects-grid-item';
22
+ export * from './objects-list-item';
23
+ ```
24
+
25
+ ## 2. Object gallery widget
26
+
27
+ Build `components/widget/gallery-object` and export it from the widget barrel:
28
+
29
+ ```ts
30
+ // components/widget/index.ts:
31
+ export * from './gallery-object/widget-gallery-object.component';
32
+ ```
33
+
34
+ Register it in the widget content-type map in `components/widget/widget.component.ts` so the page
35
+ renderer can render `GALLERY_OBJECT` content blocks:
36
+
37
+ ```ts
38
+ import { WidgetGalleryObjectComponent } from './gallery-object/widget-gallery-object.component';
39
+ // …in the ArticleWidgetType → component map:
40
+ [ArticleWidgetType.GALLERY_OBJECT]: WidgetGalleryObjectComponent,
41
+ ```
42
+
43
+ The widget container renders sub-widgets via `NgComponentOutlet`, so the gallery widget goes in the
44
+ type-map only — it does **not** go in the container's `imports` array.
45
+
46
+ ## 3. Object model type
47
+
48
+ `models/objects.model.ts` holds the foundation model types plus the object-specific `ISpecificObject`,
49
+ which extends `MsObject`. Add the import and the **full** interface — copy `ISpecificObject` verbatim
50
+ from the reference's `models/objects.model.ts` (it has a real field set; do not leave it as an empty
51
+ stub, or the objects `description-container` component won't compile):
52
+
53
+ ```ts
54
+ import { MsObject } from '@smartsoft001-mobilems/objects-domain';
55
+ // …
56
+ export interface ISpecificObject extends MsObject {
57
+ // …copy the full field set from the reference objects.model.ts…
58
+ }
59
+ ```
60
+
61
+ `ISpecificObject` is consumed by the objects `description-container` component, so it must be present
62
+ (with its real fields) before that compiles. Note `verify-module.sh` only checks the interface
63
+ exists — it can't tell a stub from the real thing, so copy the fields.
64
+
65
+ ## Verify
66
+
67
+ `scripts/verify-module.sh` checks the two card components + the gallery widget exist and are exported,
68
+ the widget map registers `WidgetGalleryObjectComponent`, and `ISpecificObject` is present in
69
+ `objects.model.ts`.
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # detect-init.sh <workspace-root>
4
+ #
5
+ # Precondition gate for mobilems-objects (and the other module skills follow the same shape):
6
+ # confirm the MobilEMS foundation from mobilems-project-init is present. Portable to macOS bash 3.2.
7
+ #
8
+ # Exit 0 → foundation present, OK to add the module.
9
+ # Exit 3 → foundation missing (tell the user to run /mobilems:project-init first).
10
+ set -eu
11
+
12
+ ROOT="${1:?usage: detect-init.sh <workspace-root>}"
13
+ cd "$ROOT" 2>/dev/null || { echo "ERROR: no such dir: $ROOT" >&2; exit 2; }
14
+
15
+ miss() {
16
+ echo "FOUNDATION MISSING: $1" >&2
17
+ echo "Run /mobilems:project-init first to lay down the MobilEMS foundation." >&2
18
+ exit 3
19
+ }
20
+
21
+ [ -f apps/web/src/app/app.config.ts ] || miss "app.config.ts missing"
22
+ grep -q "SharedModule.forRoot" apps/web/src/app/app.config.ts || miss "SharedModule.forRoot not in app.config.ts (foundation not applied)"
23
+ grep -q "./lib/components" libs/shared/angular/src/index.ts 2>/dev/null || miss "shared-lib components barrel not populated"
24
+ [ -f apps/web/src/app/app.routes.ts ] || miss "app.routes.ts missing"
25
+
26
+ PREFIX="$(grep -oE '@[a-z0-9-]+/angular' tsconfig.base.json | head -1 | sed -E 's#@([a-z0-9-]+)/angular#\1#')"
27
+ echo "FOUNDATION OK. Detected prefix: ${PREFIX:-<unknown>}"
28
+ [ -d libs/museum-objects ] && echo "NOTE: libs/museum-objects already exists — build steps must be idempotent." >&2
29
+ exit 0
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # verify-module.sh <workspace-root> <PREFIX>
4
+ #
5
+ # Post-condition check for mobilems-objects: library created, route registered (top-level + search
6
+ # child), objects shared components built + wired into the widget map + objects.model. bash 3.2 safe.
7
+ set -eu
8
+
9
+ ROOT="${1:?usage: verify-module.sh <workspace-root> <PREFIX>}"
10
+ PREFIX="${2:?usage: verify-module.sh <workspace-root> <PREFIX>}"
11
+ cd "$ROOT" 2>/dev/null || { echo "ERROR: no such dir: $ROOT" >&2; exit 2; }
12
+
13
+ fail=0
14
+ pass() { echo " PASS: $1"; }
15
+ bad() { echo " FAIL: $1" >&2; fail=1; }
16
+
17
+ echo "== Library =="
18
+ [ -f libs/museum-objects/shell/angular/src/lib/objects.module.ts ] && pass "MuseumObjectsModule present" || bad "objects.module.ts missing"
19
+ [ -f libs/museum-objects/domain/src/lib/entities/museum-object.entity.ts ] && pass "MuseumObject entity present" || bad "domain entity missing"
20
+ grep -q "museum-objects/shell/angular" tsconfig.base.json && pass "tsconfig path added" || bad "tsconfig.base.json path missing"
21
+ grep -q "ObjectsSharedModule.forFeature" libs/museum-objects/shell/angular/src/lib/objects.module.ts 2>/dev/null && pass "forFeature wired" || bad "ObjectsSharedModule.forFeature missing"
22
+
23
+ echo "== Route registration =="
24
+ ROUTES=apps/web/src/app/app.routes.ts
25
+ grep -q "museum-objects/shell/angular" "$ROUTES" && pass "objects route registered" || bad "objects route not in app.routes.ts"
26
+ # top-level + search child — expect at least 2 occurrences
27
+ n=$(grep -c "museum-objects/shell/angular" "$ROUTES" || true)
28
+ [ "${n:-0}" -ge 2 ] && pass "registered top-level + search child ($n)" || bad "expected route top-level + search child, found $n"
29
+
30
+ echo "== Objects shared components =="
31
+ COMP=libs/shared/angular/src/lib/components
32
+ for d in objects-grid-item objects-list-item widget/gallery-object; do
33
+ [ -d "$COMP/$d" ] && pass "built $d" || bad "missing $COMP/$d"
34
+ done
35
+ grep -q "objects-grid-item" "$COMP/index.ts" && pass "objects-grid-item exported" || bad "objects-grid-item export missing"
36
+ grep -q "gallery-object" "$COMP/widget/index.ts" && pass "gallery-object exported" || bad "gallery-object export missing"
37
+
38
+ echo "== Widget map + object model =="
39
+ WID="$COMP/widget/widget.component.ts"
40
+ grep -q "WidgetGalleryObjectComponent" "$WID" && pass "object gallery widget registered in widget map" || bad "object gallery widget not in widget map"
41
+ OBJM=libs/shared/angular/src/lib/models/objects.model.ts
42
+ grep -q "objects-domain" "$OBJM" && pass "objects.model imports MsObject" || bad "objects.model MsObject import missing"
43
+ grep -qE "interface ISpecificObject" "$OBJM" && pass "ISpecificObject present" || bad "ISpecificObject missing"
44
+
45
+ echo "== Deps =="
46
+ grep -q "@smartsoft001-mobilems/objects-domain" package.json && pass "objects-domain dep" || bad "objects-domain dep missing"
47
+ grep -q "online-3d-viewer" package.json && pass "online-3d-viewer dep" || bad "online-3d-viewer dep missing"
48
+
49
+ echo
50
+ if [ "$fail" = 0 ]; then echo "VERIFY: all checks passed."; else echo "VERIFY: FAILED — fix the items above and re-run." >&2; fi
51
+ exit "$fail"
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: mobilems-partners
3
+ description: Add the museum PARTNERS feature module (partnerzy) to a MobilEMS app initialized with mobilems-project-init. Use whenever the user wants to add / scaffold / wire the partners (partnerzy) module, the museum partners list + detail pages (partner cards, map, connected objects), or asks to "dodaj moduł partnerów / partnerzy". Creates libs/museum-partners (domain + shell/angular), registers the /partnerzy route (top-level + search child), and adds the Articles + objects-domain npm packages it reuses. Requires the MobilEMS foundation to exist first.
4
+ user-invocable: true
5
+ allowed-tools: Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion
6
+ ---
7
+
8
+ # MobilEMS partners module
9
+
10
+ Add the **partners** (partnerzy) feature module on top of a MobilEMS foundation produced by
11
+ `mobilems-project-init`. This module's entire UI lives inside its own `libs/museum-partners`
12
+ library, so this skill builds that library and registers the `partnerzy` route.
13
+
14
+ Partners is a list/detail feature where each entry is a partnering institution: a `ListComponent`
15
+ with grid/list partner cards (sortable, paged, masonry layout) plus an `ItemComponent` that renders
16
+ the partner detail (logo, description, map location, and the museum objects connected to that
17
+ partner). It is backed by `ArticlesSharedModule.forFeature` over the Articles `Article` type — it
18
+ REUSES the Articles shared module (like the thematic-paths module) but with its OWN domain entity
19
+ (`MuseumPartner`), its OWN reducer (`getReducer`), and **no `baseQuery`**.
20
+
21
+ ## Precondition
22
+
23
+ Run `scripts/detect-init.sh <workspace-root>`. It confirms the MobilEMS foundation is present
24
+ (`SharedModule.forRoot` in `app.config.ts`, a populated shared-lib barrel). If not, tell the user to
25
+ run `/mobilems:project-init` first. Hold `<PREFIX>` (from `tsconfig.base.json`; reference uses
26
+ `@msr`) and the reference repo path (same one init used).
27
+
28
+ ## Steps
29
+
30
+ 1. **npm deps** — add `@smartsoft001-mobilems/articles-domain`,
31
+ `@smartsoft001-mobilems/articles-shell-angular`, `@smartsoft001-mobilems/articles-shell-dtos`
32
+ (this module reuses the Articles shared module — `ArticlesSharedModule` + `ArticlesService`) and
33
+ `@smartsoft001-mobilems/objects-domain` (the `MuseumPartner` entity types its `connections` with
34
+ `IMsObjectConnection` from objects-domain). Also add `lodash-decorators` (the list page uses
35
+ `@debounce` for its date filter). Grep the copied pages/components for any other third-party
36
+ imports and add those too. Match the installed mobilems line; resolve versions at run time; do
37
+ not `npm install` unless asked. Adding is idempotent — if a sibling module already installed
38
+ these, nothing changes. (`@smartsoft001-mobilems/{angular,models}` and
39
+ `@thisissoon/angular-masonry` are already foundation deps.)
40
+ 2. **Library** — create `libs/museum-partners/{domain,shell/angular}` per
41
+ `references/lib-contents.md`: copy the domain entity (`MuseumPartner`) and the shell
42
+ (`MuseumPartnersModule`, routes, `+state/partners.reducer.ts`, `components/{grid-item,list-item}`,
43
+ `pages/{list,item}`, `services/partners`), thread `<PREFIX>`. Add the two `tsconfig.base.json`
44
+ paths and the `museum-partners` commit scope.
45
+ 3. **Module + routes** — see `references/module-and-routes.md`: `MuseumPartnersModule` wraps
46
+ `ArticlesSharedModule.forFeature({ routing: false, config: { reducerFactory: getReducer, type: Article, apiUrl, entity: 'partners' } })`
47
+ (note: **no baseQuery**) with the `Masonry` SSR factory and provides `SERVICES`. Add the lazy
48
+ `partnerzy` route to the `appRoutes` array in `apps/web/src/app/app.routes.ts` as a top-level
49
+ route, and a matching child under the `wyszukaj/:text` search route (partners appears in site
50
+ search).
51
+ 4. **Verify** — run `scripts/verify-module.sh <workspace-root> <PREFIX>`: asserts the lib + entity
52
+ exist, both tsconfig paths are added, `ArticlesSharedModule.forFeature` is wired with
53
+ `entity: 'partners'` + `reducerFactory: getReducer`, the `+state/partners.reducer.ts` exports
54
+ `getReducer`, the `components/{grid-item,list-item}` cards are present in the partners lib, the
55
+ `partnerzy` route is registered (top-level + search child), and the Articles + objects-domain deps
56
+ are in `package.json`. Fix and re-run.
57
+
58
+ ## Notes
59
+
60
+ - Partners contributes nothing to `libs/shared/angular`: its grid/list cards live in its own lib, and
61
+ the `partners-carousel` foundation component is already built by `mobilems-project-init`. So this
62
+ skill builds only the partners module + its route — there is no shared-components reference.
63
+ - This skill ONLY touches the partners module + its route. It never adds other feature modules,
64
+ never re-runs the foundation, and never edits `libs/shared/angular`.
65
+ - Bundled `references/` + `scripts/` ship automatically. Do not hand-edit `plugin.json`.