@smartsoft001-mobilems/models 2.98.0 → 2.99.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` (id) |
58
+ | `PageSectionDictionaryType` | `'creator' \| 'department' \| 'tag' \| 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.99.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,14 +21,25 @@ 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
+ /** Dictionary kinds the CMS offers; others may come later. */
37
+ export type PageSectionDictionaryType = 'creator' | 'department' | 'tag' | (string & {});
21
38
  export interface PageSectionDictionaryTarget {
22
39
  targetType: 'dictionary';
23
40
  targetLabel?: string | null;
24
41
  /** Dictionary kind, e.g. `creator`. */
25
- dictionaryType: string;
42
+ dictionaryType: PageSectionDictionaryType;
26
43
  /** Dictionary entry id. */
27
44
  dictionary: number;
28
45
  }
@@ -32,10 +49,29 @@ export interface PageSectionMuseumObjectTarget {
32
49
  /** Museum object id. */
33
50
  object: number;
34
51
  }
35
- export type PageSectionTarget = PageSectionLinkTarget | PageSectionDictionaryTarget | PageSectionMuseumObjectTarget;
52
+ export interface PageSectionCardTypeCodeTarget {
53
+ targetType: 'card_type_code';
54
+ targetLabel?: string | null;
55
+ /** Object card type codes — any of them matches. */
56
+ cardTypeCodes: number[];
57
+ }
58
+ /**
59
+ * `module` target — selectable in the CMS, but the API does not send its
60
+ * fields yet, so nothing beyond `targetType`/`targetLabel` is known. Never
61
+ * clickable until the backend defines it.
62
+ */
63
+ export interface PageSectionModuleTarget {
64
+ targetType: 'module';
65
+ targetLabel?: string | null;
66
+ [field: string]: unknown;
67
+ }
68
+ export type PageSectionTarget = PageSectionLinkTarget | PageSectionPageTarget | PageSectionDictionaryTarget | PageSectionMuseumObjectTarget | PageSectionCardTypeCodeTarget | PageSectionModuleTarget;
36
69
  export interface PageSectionFile {
37
70
  id?: number;
38
- /** Relative to the API host, e.g. `/uploads/media/…`. */
71
+ /**
72
+ * Usually relative to the multimedia host (`/uploads/media/…`); object
73
+ * images may come as an absolute CDN URL.
74
+ */
39
75
  filePath: string;
40
76
  extension?: string | null;
41
77
  altText?: string | null;
@@ -46,39 +82,124 @@ export interface PageSectionMedia {
46
82
  file: PageSectionFile | null;
47
83
  type: 'image' | 'video' | null;
48
84
  }
85
+ /** `media` of a block: the background and an optional audio/video file. */
86
+ export interface PageSectionBlockMedia {
87
+ background: PageSectionMedia | null;
88
+ audiovisual?: PageSectionMedia | null;
89
+ }
90
+ /** Placement on the CMS 12-column grid (0-based `x`/`y`, size `w`×`h`). */
91
+ export interface PageSectionGrid {
92
+ x: number;
93
+ y: number;
94
+ w: number;
95
+ h: number;
96
+ }
49
97
  export interface PageSectionBlock {
50
98
  position: number;
51
- grid?: unknown;
99
+ /** Mosaic placement; `null` outside mosaic themes. */
100
+ grid?: PageSectionGrid | null;
52
101
  content: PageSectionContent | null;
53
- media: {
54
- background: PageSectionMedia | null;
55
- } | null;
102
+ media: PageSectionBlockMedia | null;
56
103
  target: PageSectionTarget | null;
57
104
  }
58
105
  export interface PageSectionCta {
59
106
  position: number;
60
107
  target: PageSectionTarget | null;
61
108
  }
109
+ /**
110
+ * Margin/padding per side on the CMS 0–12 scale; `null`/missing = not set.
111
+ * Sides are optional so partial objects (typed `unknown` before 2.103) still
112
+ * compile.
113
+ */
114
+ export interface PageSectionSpacing {
115
+ top?: number | null;
116
+ right?: number | null;
117
+ bottom?: number | null;
118
+ left?: number | null;
119
+ }
120
+ export interface PageSectionBackground {
121
+ color: string | null;
122
+ file?: PageSectionFile | null;
123
+ /** `image`/`video`; any other string is accepted (and treated as image). */
124
+ type?: 'image' | 'video' | (string & {}) | null;
125
+ }
62
126
  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;
127
+ margin?: PageSectionSpacing | null;
128
+ padding?: PageSectionSpacing | null;
129
+ background: PageSectionBackground | null;
130
+ }
131
+ /** Search box of a `banner` — rendered by the museum variant. */
132
+ export interface PageSectionSearchWidget {
133
+ position: number;
134
+ placeholder: string | null;
135
+ }
136
+ /** Counter of a `banner`; `value` is computed by the API. */
137
+ export interface PageSectionCounterWidget {
138
+ position: number;
139
+ source: 'creators' | 'museum_objects' | (string & {});
140
+ value: number;
141
+ }
142
+ export interface PageSectionWidget {
143
+ search: PageSectionSearchWidget[];
144
+ counter: PageSectionCounterWidget[];
70
145
  }
71
146
  export interface PageSection {
72
- /** Section kind, e.g. `slider`, `tile_collection`, `banner`. */
147
+ /**
148
+ * Section kind, e.g. `slider`, `tile_collection`, `banner`,
149
+ * `grid_container`, `portal_slot`.
150
+ */
73
151
  type: string;
74
152
  /** Visual variant of the `type`, e.g. `carousel`, `cards`. */
75
153
  theme: string;
76
154
  appearance: PageSectionAppearance | null;
77
155
  position: number;
78
- grid?: unknown;
156
+ /**
157
+ * Placement of a `grid_container` child on the 12-column grid; always
158
+ * `null` for top-level sections.
159
+ */
160
+ grid?: PageSectionGrid | null;
79
161
  content: PageSectionContent | null;
80
162
  blocks: PageSectionBlock[];
81
163
  cta: PageSectionCta[];
164
+ /** `banner` widgets. */
165
+ widget?: PageSectionWidget | null;
166
+ /** Sections of a `grid_container` (one level — no nested containers). */
167
+ children?: PageSection[] | null;
168
+ }
169
+ /** A block as the API sends it — `position` may be missing or `null`. */
170
+ export interface PageSectionBlockRaw extends Omit<PageSectionBlock, 'position'> {
171
+ position?: number | null;
172
+ }
173
+ /** A CTA as the API sends it — `position` may be missing or `null`. */
174
+ export interface PageSectionCtaRaw extends Omit<PageSectionCta, 'position'> {
175
+ position?: number | null;
176
+ }
177
+ /** A search widget as the API sends it. */
178
+ export interface PageSectionSearchWidgetRaw extends Omit<PageSectionSearchWidget, 'position'> {
179
+ position?: number | null;
180
+ }
181
+ /** A counter widget as the API sends it. */
182
+ export interface PageSectionCounterWidgetRaw extends Omit<PageSectionCounterWidget, 'position'> {
183
+ position?: number | null;
184
+ }
185
+ /** `widget` as the API sends it — lists and their items may be `null`. */
186
+ export interface PageSectionWidgetRaw {
187
+ search?: (PageSectionSearchWidgetRaw | null)[] | null;
188
+ counter?: (PageSectionCounterWidgetRaw | null)[] | null;
189
+ }
190
+ /**
191
+ * A section exactly as the API sends it (`Page.sections`): `position` may be
192
+ * missing or `null`, lists may be missing or `null` (e.g. `grid_container`
193
+ * and `portal_slot` come without `blocks`/`cta`) and may hold `null` items.
194
+ * `normalizePageSections` (`@smartsoft001-mobilems/angular`) turns it into a
195
+ * `PageSection`. Every `PageSection` is a valid `PageSectionRaw`.
196
+ */
197
+ export interface PageSectionRaw extends Omit<PageSection, 'position' | 'blocks' | 'cta' | 'widget' | 'children'> {
198
+ position?: number | null;
199
+ blocks?: (PageSectionBlockRaw | null)[] | null;
200
+ cta?: (PageSectionCtaRaw | null)[] | null;
201
+ widget?: PageSectionWidgetRaw | null;
202
+ children?: (PageSectionRaw | null)[] | null;
82
203
  }
83
204
  /** SEO fields of a CMS page; every field may be `null`. */
84
205
  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"}