@smartsoft001-mobilems/models 2.98.0 → 2.100.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
@@ -15,7 +15,7 @@ import { Config, Page, MsFile, ArticleWidgetType } from '@smartsoft001-mobilems/
15
15
  | `ConfigPageType` | Page-type enum used by the config menu |
16
16
  | `ConfigMenuItem` | Union of menu-item shapes |
17
17
  | `ITheme` | Theme block of `Config` (colours, fonts, per-area flags) |
18
- | `Page` | CMS page — `IEntity<number>`; optional `slug`, `seo: PageSeo \| null`, `sections: PageSection[] \| null` |
18
+ | `Page` | CMS page — `IEntity<number>`; optional `slug`, `seo: PageSeo \| null`, `sections: PageSectionRaw[] \| null` (raw API shape — normalize before use) |
19
19
  | `PageSlide` | Slide of a CMS page |
20
20
  | `MsFile` | Multimedia file — `IEntity<number>` |
21
21
  | `MsFileFromFeature` | Enum of file feature sources (image, audio, video, 3d, …) |
@@ -24,22 +24,41 @@ import { Config, Page, MsFile, ArticleWidgetType } from '@smartsoft001-mobilems/
24
24
 
25
25
  Dynamic CMS page sections — `Page.sections`, returned by `GET page/<id>` / `GET page/slug/<slug>` and
26
26
  rendered by `PageSectionsComponent` (`smart-mobilems-page-sections`) in
27
- [`@smartsoft001-mobilems/angular`](../angular/README.md). Fields the API may send as `null` are typed
28
- as such; `grid`, `margin` and `padding` are `unknown` (not interpreted yet).
27
+ [`@smartsoft001-mobilems/angular`](../angular/README.md). Shapes follow the real API response
28
+ (`GET page/slug/test-sekcje`, the `TEST_SECTIONS` fixture of the angular package). Fields the API may
29
+ send as `null` are typed as such. `PageSectionRaw` is what the API sends and what `Page.sections`
30
+ holds (positions and lists may be missing/`null`, lists may hold `null` items);
31
+ `normalizePageSections` turns it into `PageSection` — the shape variants receive (lists always
32
+ arrays without `null`s, everything sorted by `position`, `position` always a number). Every
33
+ `PageSection` is a valid `PageSectionRaw`.
29
34
 
30
35
  | Export | Shape |
31
36
  | ------------------------------- | --------------------------------------------------------------------------------------- |
32
- | `PageSection` | `type`, `theme` (component key `type/theme`), `position`, `appearance`, `content`, `blocks`, `cta`, `grid?` |
33
- | `PageSectionContent` | `title?`, `lead?` (HTML), `description?` (HTML) |
34
- | `PageSectionBlock` | `position`, `content`, `media: { background: PageSectionMedia \| null } \| null`, `target`, `grid?` |
37
+ | `PageSection` | `type`, `theme` (component key `type/theme`), `position`, `appearance`, `content`, `blocks`, `cta`, `grid?` (container children only), `widget?` (banner), `children?` (`grid_container`) |
38
+ | `PageSectionRaw` | `PageSection` as sent by the API: `position?`, `blocks?`, `cta?`, `children?`, `widget.search?`/`counter?` may be missing or `null`, list items may be `null` |
39
+ | `PageSectionBlockRaw` / `PageSectionCtaRaw` / `PageSectionSearchWidgetRaw` / `PageSectionCounterWidgetRaw` | API shapes of blocks, CTAs and widgets — `position?: number \| null` |
40
+ | `PageSectionWidgetRaw` | `search?`/`counter?`: lists of raw widgets (or `null` items), or `null` |
41
+ | `PageSectionContent` | `title?`, `lead?` (HTML), `description?` (HTML) — already in the requested language |
42
+ | `PageSectionBlock` | `position`, `content`, `media: PageSectionBlockMedia \| null`, `target`, `grid?: PageSectionGrid \| null` |
43
+ | `PageSectionBlockMedia` | `background: PageSectionMedia \| null`, `audiovisual?: PageSectionMedia \| null` |
44
+ | `PageSectionGrid` | `{ x, y, w, h }` on the CMS 12-column grid (0-based `x`/`y`) |
35
45
  | `PageSectionCta` | `position`, `target` |
36
- | `PageSectionAppearance` | `background: { color, file?, type? } \| null`, `margin?`, `padding?` |
46
+ | `PageSectionAppearance` | `margin?`/`padding?: PageSectionSpacing \| null`, `background: PageSectionBackground \| null` |
47
+ | `PageSectionSpacing` | `top?`, `right?`, `bottom?`, `left?` — each `number` (CMS scale 0–12) or `null` |
48
+ | `PageSectionBackground` | `color: string \| null`, `file?: PageSectionFile \| null`, `type?: 'image' \| 'video' \| string \| null` |
37
49
  | `PageSectionMedia` | `position?`, `file: PageSectionFile \| null`, `type: 'image' \| 'video' \| null` |
38
- | `PageSectionFile` | `filePath` (relative to the API host), `id?`, `extension?`, `altText?`, `fileName?` |
39
- | `PageSectionTarget` | Union of the three targets below, discriminated by `targetType` |
40
- | `PageSectionLinkTarget` | `targetType: 'link'`, `url` (`http(s)://`, `#anchor` or internal path), `targetLabel?` |
41
- | `PageSectionDictionaryTarget` | `targetType: 'dictionary'`, `dictionaryType` (e.g. `creator`), `dictionary` (id), `targetLabel?` |
42
- | `PageSectionMuseumObjectTarget` | `targetType: 'museum_object'`, `object` (id), `targetLabel?` |
50
+ | `PageSectionFile` | `filePath` (relative to the multimedia host, or an absolute CDN URL), `id?`, `extension?`, `altText?`, `fileName?` |
51
+ | `PageSectionWidget` | banner widgets: `search: PageSectionSearchWidget[]`, `counter: PageSectionCounterWidget[]` |
52
+ | `PageSectionSearchWidget` | `position`, `placeholder: string \| null` |
53
+ | `PageSectionCounterWidget` | `position`, `source` (`'creators' \| 'museum_objects' \| string`), `value` (computed by the API) |
54
+ | `PageSectionTarget` | Union of the targets below, discriminated by `targetType`; every target has `targetLabel?` |
55
+ | `PageSectionLinkTarget` | `targetType: 'link'`, `url` (`http(s)://`, `mailto:`, `tel:`, `#anchor` or internal path) |
56
+ | `PageSectionPageTarget` | `targetType: 'page'`, `page` (CMS page id) |
57
+ | `PageSectionDictionaryTarget` | `targetType: 'dictionary'`, `dictionaryType: PageSectionDictionaryType`, `dictionary: number \| null` — an entry id (selected record) or `null`/missing = the whole dictionary (expanded by the angular `smart-mobilems-page-sections`) |
58
+ | `PageSectionDictionaryType` | `'creator' \| 'department' \| 'tag' \| 'cycle' \| string` |
59
+ | `PageSectionMuseumObjectTarget` | `targetType: 'museum_object'`, `object` (id) |
60
+ | `PageSectionCardTypeCodeTarget` | `targetType: 'card_type_code'`, `cardTypeCodes: number[]` (any matches) |
61
+ | `PageSectionModuleTarget` | `targetType: 'module'` — exists in the CMS, fields not sent by the API yet (never clickable) |
43
62
  | `PageSeo` | `title?`, `description?` — SEO fields of a `Page` |
44
63
 
45
64
  ## User
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartsoft001-mobilems/models",
3
- "version": "2.98.0",
3
+ "version": "2.100.0",
4
4
  "types": "./src/index.d.ts",
5
5
  "main": "./src/index.js",
6
6
  "type": "commonjs"
@@ -2,9 +2,15 @@
2
2
  * Dynamic CMS page sections — `sections` of a `Page` returned by
3
3
  * `GET page/<id>` / `GET page/slug/<slug>`.
4
4
  *
5
- * Every field the API may send as `null` is typed as such. `grid`, `margin`
6
- * and `padding` are not interpreted by the framework yet, hence `unknown`.
5
+ * Every field the API may send as `null` is typed as such. Shapes follow the
6
+ * real API response (`GET page/slug/test-sekcje`, every CMS setting in use).
7
+ * `PageSection` is the normalized shape section components receive;
8
+ * `PageSectionRaw` is what the API sends (`Page.sections`) —
9
+ * `normalizePageSections` (`@smartsoft001-mobilems/angular`) turns missing
10
+ * lists into `[]`, drops `null` items and sorts everything by `position`
11
+ * before rendering.
7
12
  */
13
+ /** Section/block texts, already in the requested language. */
8
14
  export interface PageSectionContent {
9
15
  title?: string | null;
10
16
  /** HTML. */
@@ -15,16 +21,34 @@ export interface PageSectionContent {
15
21
  export interface PageSectionLinkTarget {
16
22
  targetType: 'link';
17
23
  targetLabel?: string | null;
18
- /** `http(s)://…` (external), `#anchor` or an internal path. */
24
+ /**
25
+ * `http(s)://…` (external), `mailto:`/`tel:`, `#anchor` or an internal
26
+ * path.
27
+ */
19
28
  url: string | null;
20
29
  }
30
+ export interface PageSectionPageTarget {
31
+ targetType: 'page';
32
+ targetLabel?: string | null;
33
+ /** CMS page id. */
34
+ page: number;
35
+ }
36
+ /**
37
+ * Dictionary kinds the CMS offers (`cycle` announced, not in the CMS yet);
38
+ * others may come later.
39
+ */
40
+ export type PageSectionDictionaryType = 'creator' | 'department' | 'tag' | 'cycle' | (string & {});
21
41
  export interface PageSectionDictionaryTarget {
22
42
  targetType: 'dictionary';
23
43
  targetLabel?: string | null;
24
44
  /** Dictionary kind, e.g. `creator`. */
25
- dictionaryType: string;
26
- /** Dictionary entry id. */
27
- dictionary: number;
45
+ dictionaryType: PageSectionDictionaryType;
46
+ /**
47
+ * Dictionary entry id (a selected record). `null` — or a missing field —
48
+ * means the whole dictionary: `smart-mobilems-page-sections` expands such a
49
+ * block into one block per entry (`expandDictionaryBlocks`).
50
+ */
51
+ dictionary: number | null;
28
52
  }
29
53
  export interface PageSectionMuseumObjectTarget {
30
54
  targetType: 'museum_object';
@@ -32,10 +56,29 @@ export interface PageSectionMuseumObjectTarget {
32
56
  /** Museum object id. */
33
57
  object: number;
34
58
  }
35
- export type PageSectionTarget = PageSectionLinkTarget | PageSectionDictionaryTarget | PageSectionMuseumObjectTarget;
59
+ export interface PageSectionCardTypeCodeTarget {
60
+ targetType: 'card_type_code';
61
+ targetLabel?: string | null;
62
+ /** Object card type codes — any of them matches. */
63
+ cardTypeCodes: number[];
64
+ }
65
+ /**
66
+ * `module` target — selectable in the CMS, but the API does not send its
67
+ * fields yet, so nothing beyond `targetType`/`targetLabel` is known. Never
68
+ * clickable until the backend defines it.
69
+ */
70
+ export interface PageSectionModuleTarget {
71
+ targetType: 'module';
72
+ targetLabel?: string | null;
73
+ [field: string]: unknown;
74
+ }
75
+ export type PageSectionTarget = PageSectionLinkTarget | PageSectionPageTarget | PageSectionDictionaryTarget | PageSectionMuseumObjectTarget | PageSectionCardTypeCodeTarget | PageSectionModuleTarget;
36
76
  export interface PageSectionFile {
37
77
  id?: number;
38
- /** Relative to the API host, e.g. `/uploads/media/…`. */
78
+ /**
79
+ * Usually relative to the multimedia host (`/uploads/media/…`); object
80
+ * images may come as an absolute CDN URL.
81
+ */
39
82
  filePath: string;
40
83
  extension?: string | null;
41
84
  altText?: string | null;
@@ -46,39 +89,124 @@ export interface PageSectionMedia {
46
89
  file: PageSectionFile | null;
47
90
  type: 'image' | 'video' | null;
48
91
  }
92
+ /** `media` of a block: the background and an optional audio/video file. */
93
+ export interface PageSectionBlockMedia {
94
+ background: PageSectionMedia | null;
95
+ audiovisual?: PageSectionMedia | null;
96
+ }
97
+ /** Placement on the CMS 12-column grid (0-based `x`/`y`, size `w`×`h`). */
98
+ export interface PageSectionGrid {
99
+ x: number;
100
+ y: number;
101
+ w: number;
102
+ h: number;
103
+ }
49
104
  export interface PageSectionBlock {
50
105
  position: number;
51
- grid?: unknown;
106
+ /** Mosaic placement; `null` outside mosaic themes. */
107
+ grid?: PageSectionGrid | null;
52
108
  content: PageSectionContent | null;
53
- media: {
54
- background: PageSectionMedia | null;
55
- } | null;
109
+ media: PageSectionBlockMedia | null;
56
110
  target: PageSectionTarget | null;
57
111
  }
58
112
  export interface PageSectionCta {
59
113
  position: number;
60
114
  target: PageSectionTarget | null;
61
115
  }
116
+ /**
117
+ * Margin/padding per side on the CMS 0–12 scale; `null`/missing = not set.
118
+ * Sides are optional so partial objects (typed `unknown` before 2.103) still
119
+ * compile.
120
+ */
121
+ export interface PageSectionSpacing {
122
+ top?: number | null;
123
+ right?: number | null;
124
+ bottom?: number | null;
125
+ left?: number | null;
126
+ }
127
+ export interface PageSectionBackground {
128
+ color: string | null;
129
+ file?: PageSectionFile | null;
130
+ /** `image`/`video`; any other string is accepted (and treated as image). */
131
+ type?: 'image' | 'video' | (string & {}) | null;
132
+ }
62
133
  export interface PageSectionAppearance {
63
- margin?: unknown;
64
- padding?: unknown;
65
- background: {
66
- color: string | null;
67
- file?: PageSectionFile | null;
68
- type?: string | null;
69
- } | null;
134
+ margin?: PageSectionSpacing | null;
135
+ padding?: PageSectionSpacing | null;
136
+ background: PageSectionBackground | null;
137
+ }
138
+ /** Search box of a `banner` — rendered by the museum variant. */
139
+ export interface PageSectionSearchWidget {
140
+ position: number;
141
+ placeholder: string | null;
142
+ }
143
+ /** Counter of a `banner`; `value` is computed by the API. */
144
+ export interface PageSectionCounterWidget {
145
+ position: number;
146
+ source: 'creators' | 'museum_objects' | (string & {});
147
+ value: number;
148
+ }
149
+ export interface PageSectionWidget {
150
+ search: PageSectionSearchWidget[];
151
+ counter: PageSectionCounterWidget[];
70
152
  }
71
153
  export interface PageSection {
72
- /** Section kind, e.g. `slider`, `tile_collection`, `banner`. */
154
+ /**
155
+ * Section kind, e.g. `slider`, `tile_collection`, `banner`,
156
+ * `grid_container`, `portal_slot`.
157
+ */
73
158
  type: string;
74
159
  /** Visual variant of the `type`, e.g. `carousel`, `cards`. */
75
160
  theme: string;
76
161
  appearance: PageSectionAppearance | null;
77
162
  position: number;
78
- grid?: unknown;
163
+ /**
164
+ * Placement of a `grid_container` child on the 12-column grid; always
165
+ * `null` for top-level sections.
166
+ */
167
+ grid?: PageSectionGrid | null;
79
168
  content: PageSectionContent | null;
80
169
  blocks: PageSectionBlock[];
81
170
  cta: PageSectionCta[];
171
+ /** `banner` widgets. */
172
+ widget?: PageSectionWidget | null;
173
+ /** Sections of a `grid_container` (one level — no nested containers). */
174
+ children?: PageSection[] | null;
175
+ }
176
+ /** A block as the API sends it — `position` may be missing or `null`. */
177
+ export interface PageSectionBlockRaw extends Omit<PageSectionBlock, 'position'> {
178
+ position?: number | null;
179
+ }
180
+ /** A CTA as the API sends it — `position` may be missing or `null`. */
181
+ export interface PageSectionCtaRaw extends Omit<PageSectionCta, 'position'> {
182
+ position?: number | null;
183
+ }
184
+ /** A search widget as the API sends it. */
185
+ export interface PageSectionSearchWidgetRaw extends Omit<PageSectionSearchWidget, 'position'> {
186
+ position?: number | null;
187
+ }
188
+ /** A counter widget as the API sends it. */
189
+ export interface PageSectionCounterWidgetRaw extends Omit<PageSectionCounterWidget, 'position'> {
190
+ position?: number | null;
191
+ }
192
+ /** `widget` as the API sends it — lists and their items may be `null`. */
193
+ export interface PageSectionWidgetRaw {
194
+ search?: (PageSectionSearchWidgetRaw | null)[] | null;
195
+ counter?: (PageSectionCounterWidgetRaw | null)[] | null;
196
+ }
197
+ /**
198
+ * A section exactly as the API sends it (`Page.sections`): `position` may be
199
+ * missing or `null`, lists may be missing or `null` (e.g. `grid_container`
200
+ * and `portal_slot` come without `blocks`/`cta`) and may hold `null` items.
201
+ * `normalizePageSections` (`@smartsoft001-mobilems/angular`) turns it into a
202
+ * `PageSection`. Every `PageSection` is a valid `PageSectionRaw`.
203
+ */
204
+ export interface PageSectionRaw extends Omit<PageSection, 'position' | 'blocks' | 'cta' | 'widget' | 'children'> {
205
+ position?: number | null;
206
+ blocks?: (PageSectionBlockRaw | null)[] | null;
207
+ cta?: (PageSectionCtaRaw | null)[] | null;
208
+ widget?: PageSectionWidgetRaw | null;
209
+ children?: (PageSectionRaw | null)[] | null;
82
210
  }
83
211
  /** SEO fields of a CMS page; every field may be `null`. */
84
212
  export interface PageSeo {
@@ -3,8 +3,13 @@
3
3
  * Dynamic CMS page sections — `sections` of a `Page` returned by
4
4
  * `GET page/<id>` / `GET page/slug/<slug>`.
5
5
  *
6
- * Every field the API may send as `null` is typed as such. `grid`, `margin`
7
- * and `padding` are not interpreted by the framework yet, hence `unknown`.
6
+ * Every field the API may send as `null` is typed as such. Shapes follow the
7
+ * real API response (`GET page/slug/test-sekcje`, every CMS setting in use).
8
+ * `PageSection` is the normalized shape section components receive;
9
+ * `PageSectionRaw` is what the API sends (`Page.sections`) —
10
+ * `normalizePageSections` (`@smartsoft001-mobilems/angular`) turns missing
11
+ * lists into `[]`, drops `null` items and sorts everything by `position`
12
+ * before rendering.
8
13
  */
9
14
  Object.defineProperty(exports, "__esModule", { value: true });
10
15
  //# sourceMappingURL=page-section.entity.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"page-section.entity.js","sourceRoot":"","sources":["../../../../../../../packages/shared/models/src/lib/entities/page-section.entity.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG"}
1
+ {"version":3,"file":"page-section.entity.js","sourceRoot":"","sources":["../../../../../../../packages/shared/models/src/lib/entities/page-section.entity.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG"}
@@ -1,5 +1,5 @@
1
1
  import { IEntity } from '@smartsoft001/domain-core';
2
- import { PageSection, PageSeo } from './page-section.entity';
2
+ import { PageSectionRaw, PageSeo } from './page-section.entity';
3
3
  export declare class Page implements IEntity<number> {
4
4
  id: number;
5
5
  title: string;
@@ -7,8 +7,12 @@ export declare class Page implements IEntity<number> {
7
7
  slides: Array<PageSlide>;
8
8
  slug?: string;
9
9
  seo?: PageSeo | null;
10
- /** Dynamic sections, rendered by `smart-mobilems-page-sections`. */
11
- sections?: PageSection[] | null;
10
+ /**
11
+ * Dynamic sections exactly as the API sends them — normalize them
12
+ * (`normalizePageSections`) before reading lists or positions;
13
+ * `smart-mobilems-page-sections` does it itself.
14
+ */
15
+ sections?: PageSectionRaw[] | null;
12
16
  }
13
17
  export declare class PageSlide {
14
18
  id: number;
@@ -1 +1 @@
1
- {"version":3,"file":"page.entity.js","sourceRoot":"","sources":["../../../../../../../packages/shared/models/src/lib/entities/page.entity.ts"],"names":[],"mappings":";;;;AACA,iDAAoD;AAK7C,IAAM,IAAI,GAAV,MAAM,IAAI;CAsBhB,CAAA;AAtBY,oBAAI;AAIf;IADC,IAAA,cAAK,GAAE;;mCACO;AAGf;IADC,IAAA,cAAK,GAAE;;qCACK;AAGb;IADC,IAAA,cAAK,GAAE;sCACC,KAAK;oCAAY;eAVf,IAAI;IADhB,IAAA,cAAK,GAAE;GACK,IAAI,CAsBhB;AAGM,IAAM,SAAS,GAAf,MAAM,SAAS;CAkBrB,CAAA;AAlBY,8BAAS;AAEpB;IADC,IAAA,cAAK,GAAE;;qCACI;AAGZ;IADC,IAAA,cAAK,GAAE;;wCACO;AAGf;IADC,IAAA,cAAK,GAAE;;+CACwB;AAGhC;IADC,IAAA,cAAK,GAAE;;+CACc;AAGtB;IADC,IAAA,cAAK,GAAE;;8CACa;AAGrB;IADC,IAAA,cAAK,GAAE;;8CACa;oBAjBV,SAAS;IADrB,IAAA,cAAK,GAAE;GACK,SAAS,CAkBrB"}
1
+ {"version":3,"file":"page.entity.js","sourceRoot":"","sources":["../../../../../../../packages/shared/models/src/lib/entities/page.entity.ts"],"names":[],"mappings":";;;;AACA,iDAAoD;AAK7C,IAAM,IAAI,GAAV,MAAM,IAAI;CA0BhB,CAAA;AA1BY,oBAAI;AAIf;IADC,IAAA,cAAK,GAAE;;mCACO;AAGf;IADC,IAAA,cAAK,GAAE;;qCACK;AAGb;IADC,IAAA,cAAK,GAAE;sCACC,KAAK;oCAAY;eAVf,IAAI;IADhB,IAAA,cAAK,GAAE;GACK,IAAI,CA0BhB;AAGM,IAAM,SAAS,GAAf,MAAM,SAAS;CAkBrB,CAAA;AAlBY,8BAAS;AAEpB;IADC,IAAA,cAAK,GAAE;;qCACI;AAGZ;IADC,IAAA,cAAK,GAAE;;wCACO;AAGf;IADC,IAAA,cAAK,GAAE;;+CACwB;AAGhC;IADC,IAAA,cAAK,GAAE;;+CACc;AAGtB;IADC,IAAA,cAAK,GAAE;;8CACa;AAGrB;IADC,IAAA,cAAK,GAAE;;8CACa;oBAjBV,SAAS;IADrB,IAAA,cAAK,GAAE;GACK,SAAS,CAkBrB"}