@startinblox/components-ds4go 3.0.3 → 3.1.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 (33) hide show
  1. package/.storybook/preview.ts +1 -0
  2. package/biome.json +1 -1
  3. package/dist/custom-getter-ZPFnoSjt-BCNOlbJZ-B4tuxA42.js +338 -0
  4. package/dist/en-BySYJZMr-CWZl5AwU-CWZl5AwU.js +14 -0
  5. package/dist/fr-BZZDTsmw-CNDWt66j-CNDWt66j.js +14 -0
  6. package/dist/index-BSwVRtNS.js +104980 -0
  7. package/dist/index.js +1 -3032
  8. package/dist/quill.snow-C_A_QkE8-D-uedtvC-D-uedtvC.js +13 -0
  9. package/dist/slimselect-NFLzJMfV-DZ7j6Vsj-DZ7j6Vsj.js +5 -0
  10. package/package.json +9 -8
  11. package/src/components/cards/ds4go-card-catalog.ts +132 -0
  12. package/src/components/catalog/ds4go-catalog-filter-holder.ts +459 -0
  13. package/src/components/catalog/ds4go-customer-holder.ts +162 -0
  14. package/src/components/catalog/ds4go-fact-bundle-holder.ts +7 -7
  15. package/src/components/modal/ds4go-customer-modal.ts +134 -0
  16. package/src/components/modal/ds4go-fact-bundle-modal.ts +2 -2
  17. package/src/components/solid-customer-list.ts +195 -0
  18. package/src/components/solid-dsif-explorer-poc.ts +8 -8
  19. package/src/components/solid-dsp-connector.ts +12 -4
  20. package/src/components/solid-fact-bundle-creation.ts +244 -151
  21. package/src/components/solid-fact-bundle.ts +9 -4
  22. package/src/helpers/components/orbitComponent.ts +12 -13
  23. package/src/helpers/i18n/configureLocalization.ts +12 -5
  24. package/src/helpers/index.ts +0 -2
  25. package/src/styles/cards/ds4go-card-catalog.scss +149 -0
  26. package/src/styles/fact-bundle-creation.scss +6 -2
  27. package/src/styles/modal/ds4go-customer-modal.scss +91 -0
  28. package/src/styles/modal/ds4go-fact-bundle-modal.scss +1 -1
  29. package/vite.config.ts +7 -7
  30. package/src/components/solid-boilerplate.ts +0 -76
  31. package/src/helpers/components/ResourceMapper.ts +0 -469
  32. package/src/helpers/components/orbitDspComponent.ts +0 -250
  33. package/src/helpers/mappings/dsp-mapping-config.ts +0 -545
@@ -0,0 +1,459 @@
1
+ import { sort } from "@helpers";
2
+ import { msg } from "@lit/localize";
3
+ import type { Resource } from "@src/component";
4
+ import {
5
+ TemsObjectsHandler,
6
+ type TemsSearchObject,
7
+ } from "@startinblox/solid-tems-shared";
8
+ import {
9
+ css,
10
+ html,
11
+ nothing,
12
+ type PropertyValues,
13
+ type TemplateResult,
14
+ } from "lit";
15
+ import { customElement, property, state } from "lit/decorators.js";
16
+
17
+ @customElement("ds4go-catalog-filter-holder")
18
+ export class DS4GOCatalogFilterHolder extends TemsObjectsHandler {
19
+ static styles = css`
20
+ .filter-bar {
21
+ position: fixed;
22
+ top: 0;
23
+ left: 0;
24
+ right: 0;
25
+ bottom: 0;
26
+ background-color: rgba(0, 2, 49, 0.2);
27
+ z-index: 9999;
28
+ display: flex;
29
+ justify-content: flex-end;
30
+ }
31
+ `;
32
+
33
+ @property({ attribute: false })
34
+ displayFiltering = false;
35
+
36
+ search: TemsSearchObject[] = [];
37
+
38
+ @state()
39
+ protected _internalFilters: TemsSearchObject[] = [];
40
+
41
+ @state()
42
+ displayFilters = false;
43
+
44
+ @state()
45
+ resultCount = 0;
46
+
47
+ @state()
48
+ filterCount = 0;
49
+
50
+ @state()
51
+ view: "card" | "list" | "table" | "map" = "card";
52
+
53
+ @state()
54
+ protected _accordionStates: { [key: string]: boolean } = {};
55
+
56
+ protected willUpdate(changedProperties: PropertyValues) {
57
+ if (changedProperties.has("search")) {
58
+ this._internalFilters = [...this.search];
59
+ }
60
+ }
61
+
62
+ protected shouldUpdate(changedProperties: PropertyValues): boolean {
63
+ if (changedProperties.has("_accordionStates")) {
64
+ return true;
65
+ }
66
+ if (
67
+ changedProperties.has("search") ||
68
+ changedProperties.has("_internalFilters")
69
+ ) {
70
+ return false;
71
+ }
72
+ return super.shouldUpdate(changedProperties);
73
+ }
74
+
75
+ updated(changedProperties: PropertyValues) {
76
+ if (changedProperties.has("displayFilters") && this.displayFilters) {
77
+ const needsInitialization =
78
+ !changedProperties.get("displayFilters") ||
79
+ Object.keys(this._accordionStates).length === 0;
80
+
81
+ if (needsInitialization) {
82
+ const initialStates: { [key: string]: boolean } = {};
83
+ const filters = this._getFiltersDefinition();
84
+ for (const filter of filters) {
85
+ let condition = true;
86
+ if (filter.type && typeof filter.type === "string") {
87
+ condition = this.hasType(filter.type, this.objects);
88
+ } else if (filter.type && Array.isArray(filter.type)) {
89
+ condition = filter.type
90
+ .flat()
91
+ .some((typeString) => this.hasType(typeString, this.objects));
92
+ }
93
+
94
+ if (condition && filter.condition()) {
95
+ initialStates[filter.name] = !!this._internalFilters.find(
96
+ (f: TemsSearchObject) => f.name === filter.name,
97
+ );
98
+ } else {
99
+ initialStates[filter.name] = false;
100
+ }
101
+ }
102
+ if (
103
+ JSON.stringify(this._accordionStates) !==
104
+ JSON.stringify(initialStates)
105
+ ) {
106
+ this._accordionStates = initialStates;
107
+ }
108
+ }
109
+ }
110
+ }
111
+
112
+ protected shouldUpdateSearch() {
113
+ this.dispatchEvent(
114
+ new CustomEvent("search", { detail: this._internalFilters }),
115
+ );
116
+ }
117
+
118
+ protected _toggleChangeView(e: Event) {
119
+ e.preventDefault();
120
+ this.dispatchEvent(
121
+ new CustomEvent("change-view", {
122
+ detail: e.detail,
123
+ }),
124
+ );
125
+ }
126
+
127
+ protected _displayFilters() {
128
+ this.displayFilters = !this.displayFilters;
129
+ }
130
+
131
+ protected _hideFiltersFromBackground(e: Event) {
132
+ e.preventDefault();
133
+ if (e.target?.classList.contains("filter-bar")) this.displayFilters = false;
134
+ }
135
+
136
+ protected _searchByText(e: Event) {
137
+ e.preventDefault();
138
+ this._internalFilters = this._internalFilters.filter(
139
+ (s) => s.name !== "search",
140
+ );
141
+ if (e.detail) {
142
+ this._internalFilters.push({
143
+ name: "search",
144
+ value: e.detail,
145
+ });
146
+ this._internalFilters = [...this._internalFilters];
147
+ }
148
+ this.shouldUpdateSearch();
149
+ }
150
+
151
+ protected _resetFilters() {
152
+ this._internalFilters = [
153
+ this._internalFilters.find((s) => s.name === "search") || {
154
+ name: "search",
155
+ value: "",
156
+ },
157
+ ];
158
+ this.shouldUpdateSearch();
159
+ }
160
+
161
+ // matchId
162
+ protected renderFilterItemsById(objects: any[], propertyName: string) {
163
+ if (!objects) {
164
+ return nothing;
165
+ }
166
+
167
+ return html`${sort(
168
+ objects
169
+ .flatMap((item: Resource) => {
170
+ let obj = item;
171
+ if (propertyName) {
172
+ obj = obj[propertyName];
173
+ if (!obj) {
174
+ return [];
175
+ }
176
+ }
177
+ return obj;
178
+ })
179
+ .filter((o: Resource) => o)
180
+ .reduce((acc: Resource[], current: Resource) => {
181
+ if (!acc.find((res: Resource) => res["@id"] === current["@id"])) {
182
+ acc.push(current);
183
+ }
184
+ return acc;
185
+ }, []),
186
+ "name",
187
+ ).map((obj: Resource) => {
188
+ const filterValue = !!this._internalFilters.find(
189
+ (s) =>
190
+ s.type === "matchId" &&
191
+ s.name === propertyName &&
192
+ s.value === obj["@id"],
193
+ );
194
+ return html`<tems-filter-item
195
+ label=${obj.name}
196
+ type="checkbox"
197
+ count=${
198
+ this.objects?.filter((o: Resource) => {
199
+ let to = o;
200
+ if (propertyName) {
201
+ to = to[propertyName];
202
+ if (!to) {
203
+ return false;
204
+ }
205
+ }
206
+ if (Array.isArray(to)) {
207
+ return to.some((i) => i["@id"] === obj["@id"]);
208
+ }
209
+ return to["@id"] === obj["@id"];
210
+ }).length
211
+ }
212
+ value=${filterValue || nothing}
213
+ checked=${filterValue || nothing}
214
+ @change=${(e: Event) => {
215
+ e.preventDefault();
216
+ if (e.detail.value) {
217
+ this._internalFilters.push({
218
+ type: "matchId",
219
+ name: propertyName,
220
+ value: obj["@id"],
221
+ });
222
+ this._internalFilters = [...this._internalFilters];
223
+ } else {
224
+ this._internalFilters = this._internalFilters.filter(
225
+ (s) =>
226
+ !(
227
+ s.type === "matchId" &&
228
+ s.name === propertyName &&
229
+ s.value === obj["@id"]
230
+ ),
231
+ );
232
+ }
233
+ this.shouldUpdateSearch();
234
+ }}
235
+ >
236
+ </tems-filter-item>`;
237
+ })}`;
238
+ }
239
+
240
+ // matchValue
241
+ protected renderFilterItemsByValue(objects: any[], propertyName: string) {
242
+ if (!objects) {
243
+ return nothing;
244
+ }
245
+
246
+ const filterValue = this._internalFilters.find(
247
+ (s) => s.type === "matchValue" && s.name === propertyName,
248
+ );
249
+
250
+ return html`
251
+ <tems-input-field
252
+ label=${msg("Search for...")}
253
+ type="text"
254
+ value=${filterValue?.value ?? ""}
255
+ @change=${(e: Event) => {
256
+ e.preventDefault();
257
+ this._internalFilters = this._internalFilters.filter(
258
+ (s) => !(s.type === "matchValue" && s.name === propertyName),
259
+ );
260
+ if (e.detail.value) {
261
+ this._internalFilters.push({
262
+ type: "matchValue",
263
+ name: propertyName,
264
+ value: e.detail.value,
265
+ });
266
+ this._internalFilters = [...this._internalFilters];
267
+ }
268
+ this.shouldUpdateSearch();
269
+ }}
270
+ ></tems-input-field>
271
+ `;
272
+ }
273
+
274
+ // dateAfter
275
+ protected renderFilterItemsFromDate(objects: any[], propertyName: string) {
276
+ if (!objects) {
277
+ return nothing;
278
+ }
279
+
280
+ const filterValue = this._internalFilters.find(
281
+ (s) => s.type === "dateAfter" && s.name === propertyName,
282
+ );
283
+
284
+ return html`
285
+ <tems-input-field
286
+ label=${msg("Date after")}
287
+ type="date"
288
+ value=${filterValue?.value ?? ""}
289
+ @change=${(e: Event) => {
290
+ e.preventDefault();
291
+ this._internalFilters = this._internalFilters.filter(
292
+ (s) => !(s.type === "dateAfter" && s.name === propertyName),
293
+ );
294
+ if (e.detail.value) {
295
+ this._internalFilters.push({
296
+ type: "dateAfter",
297
+ name: propertyName,
298
+ value: e.detail.value,
299
+ });
300
+ this._internalFilters = [...this._internalFilters];
301
+ }
302
+ this.shouldUpdateSearch();
303
+ }}
304
+ ></tems-input-field>
305
+ `;
306
+ }
307
+
308
+ protected renderFilterItemsByNumberRange(
309
+ objects: any[],
310
+ propertyName: string,
311
+ ) {
312
+ if (!objects) {
313
+ return nothing;
314
+ }
315
+
316
+ const numbers = objects
317
+ .map((o: any) => Number(o[propertyName]) || 0)
318
+ .filter(Number.isFinite);
319
+
320
+ const min = numbers.length > 0 ? Math.min(...numbers) : 0;
321
+ const max = numbers.length > 0 ? Math.max(...numbers) : 0;
322
+
323
+ if (min === max) {
324
+ return nothing;
325
+ }
326
+
327
+ const filterValue = this._internalFilters.find(
328
+ (s) => s.type === "interval" && s.name === propertyName,
329
+ );
330
+
331
+ const valueMin = filterValue?.value?.split("/")[0] || min;
332
+ const valueMax = filterValue?.value?.split("/")[1] || max;
333
+
334
+ return html`
335
+ <tems-slider
336
+ type="multiple"
337
+ min=${min}
338
+ max=${max}
339
+ value=${valueMin}
340
+ value-max=${valueMax}
341
+ @change=${(e: Event) => {
342
+ e.preventDefault();
343
+ this._internalFilters = this._internalFilters.filter(
344
+ (s) => !(s.type === "interval" && s.name === propertyName),
345
+ );
346
+ const min = e.detail.min ?? 0;
347
+ const max = e.detail.max ?? 0;
348
+ this._internalFilters.push({
349
+ type: "interval",
350
+ name: propertyName,
351
+ value: `${min}/${max}`,
352
+ });
353
+ this._internalFilters = [...this._internalFilters];
354
+ this.shouldUpdateSearch();
355
+ }}
356
+ ></tems-slider>
357
+ `;
358
+ }
359
+
360
+ protected _handleAccordionOpened(filterName: string) {
361
+ if (this._accordionStates[filterName] !== true) {
362
+ this._accordionStates = {
363
+ ...this._accordionStates,
364
+ [filterName]: true,
365
+ };
366
+ }
367
+ }
368
+
369
+ protected _handleAccordionClosed(filterName: string) {
370
+ if (this._accordionStates[filterName] !== false) {
371
+ this._accordionStates = {
372
+ ...this._accordionStates,
373
+ [filterName]: false,
374
+ };
375
+ }
376
+ }
377
+
378
+ protected _getFiltersDefinition(): {
379
+ name: string;
380
+ type: string;
381
+ condition: () => boolean;
382
+ label: string;
383
+ icon: TemplateResult;
384
+ render: () => TemplateResult;
385
+ }[] {
386
+ return [];
387
+ }
388
+
389
+ render() {
390
+ const filters = this._getFiltersDefinition();
391
+
392
+ return html`
393
+ <div>
394
+ <tems-search-bar
395
+ .displayFilters=${this.displayFiltering}
396
+ .displaySavedSearch=${this.displayFiltering}
397
+ .displayViews=${this.displayFiltering}
398
+ .dropdownCardElement=${true}
399
+ .dropdownListElement=${true}
400
+ .dropdownTableElement=${false}
401
+ .dropdownMapElement=${false}
402
+ .displayActiveTags=${false}
403
+ .view=${this.view}
404
+ .value=${
405
+ this._internalFilters.find((s) => s.name === "search")?.value
406
+ }
407
+ @search=${this._searchByText}
408
+ @change-view=${this._toggleChangeView}
409
+ @toggle-filters=${this._displayFilters}
410
+ ></tems-search-bar>
411
+ ${
412
+ this.displayFilters
413
+ ? html`<div
414
+ class="filter-bar"
415
+ @click=${this._hideFiltersFromBackground}
416
+ >
417
+ <tems-filter-sidebar
418
+ counter=${this.filterCount || nothing}
419
+ result-counter=${this.resultCount}
420
+ @close=${this._displayFilters}
421
+ @show-results=${this._displayFilters}
422
+ @clear-filters=${this._resetFilters}
423
+ >
424
+ ${filters.map((filter) => {
425
+ let condition = true;
426
+ if (filter.type && typeof filter.type === "string") {
427
+ condition = this.hasType(filter.type, this.objects);
428
+ } else if (filter.type && Array.isArray(filter.type)) {
429
+ condition = filter.type
430
+ .flat()
431
+ .some((typeString) =>
432
+ this.hasType(typeString, this.objects),
433
+ );
434
+ }
435
+
436
+ const shouldRender = condition && filter.condition();
437
+
438
+ return shouldRender
439
+ ? html`<tems-vertical-accordion
440
+ label=${filter.label}
441
+ .icon=${filter.icon}
442
+ .open=${this._accordionStates[filter.name] ?? false}
443
+ @opened=${() =>
444
+ this._handleAccordionOpened(filter.name)}
445
+ @closed=${() =>
446
+ this._handleAccordionClosed(filter.name)}
447
+ >
448
+ ${filter.render()}
449
+ </tems-vertical-accordion>`
450
+ : nothing;
451
+ })}
452
+ </tems-filter-sidebar>
453
+ </div>`
454
+ : nothing
455
+ }
456
+ </div>
457
+ `;
458
+ }
459
+ }
@@ -0,0 +1,162 @@
1
+ import {
2
+ ComponentObjectsHandler,
3
+ filterObjectByDateAfter,
4
+ filterObjectById,
5
+ filterObjectByInterval,
6
+ filterObjectByNamedValue,
7
+ filterObjectByType,
8
+ filterObjectByValue,
9
+ } from "@helpers";
10
+ import { msg, str } from "@lit/localize";
11
+ import type { Resource, SearchObject, UnknownResource } from "@src/component";
12
+ import { css, html, nothing, type PropertyValues } from "lit";
13
+ import { customElement, state } from "lit/decorators.js";
14
+
15
+ @customElement("ds4go-customer-holder")
16
+ export class Ds4goCustomerHolder extends ComponentObjectsHandler {
17
+ static styles = css`
18
+ .card-grid {
19
+ display: flex;
20
+ flex-direction: row;
21
+ flex-wrap: wrap;
22
+ gap: 20px;
23
+ }
24
+ .card-grid-vertical {
25
+ justify-content: stretch;
26
+ }
27
+ .card-grid-vertical ds4go-card-catalog {
28
+ width: 354px;
29
+ height: auto;
30
+ }
31
+ ds4go-card-catalog {
32
+ cursor: pointer;
33
+ }
34
+ `;
35
+
36
+ @state()
37
+ search: SearchObject[] = [];
38
+
39
+ @state()
40
+ protected _displayObjects: Resource[] = [];
41
+
42
+ protected filter(objects: Resource[], filters: SearchObject[] = []) {
43
+ if (!filters || filters.length === 0 || !objects || objects.length === 0) {
44
+ return objects;
45
+ }
46
+
47
+ const groupedFilters = new Map<string, SearchObject[]>();
48
+ for (const filter of filters) {
49
+ const groupKey = filter.name;
50
+ const group = groupedFilters.get(groupKey) || [];
51
+ group.push(filter);
52
+ groupedFilters.set(groupKey, group);
53
+ }
54
+
55
+ let currentFilteredObjects = [...objects];
56
+
57
+ for (const filterGroup of groupedFilters.values()) {
58
+ if (currentFilteredObjects.length === 0) {
59
+ break;
60
+ }
61
+
62
+ const tempResults: UnknownResource[] = [];
63
+ for (const filter of filterGroup) {
64
+ switch (filter.type) {
65
+ case "interval":
66
+ tempResults.push(
67
+ filterObjectByInterval(
68
+ currentFilteredObjects,
69
+ filter.name,
70
+ filter.value,
71
+ ),
72
+ );
73
+ break;
74
+ case "dateAfter":
75
+ tempResults.push(
76
+ filterObjectByDateAfter(
77
+ currentFilteredObjects,
78
+ filter.name,
79
+ filter.value,
80
+ ),
81
+ );
82
+ break;
83
+ case "matchId":
84
+ tempResults.push(
85
+ filterObjectById(
86
+ currentFilteredObjects,
87
+ filter.name,
88
+ filter.value,
89
+ ),
90
+ );
91
+ break;
92
+ case "matchType":
93
+ tempResults.push(
94
+ filterObjectByType(currentFilteredObjects, filter.value),
95
+ );
96
+ break;
97
+ case "exact":
98
+ tempResults.push(
99
+ filterObjectByNamedValue(
100
+ currentFilteredObjects,
101
+ filter.name,
102
+ filter.value,
103
+ ),
104
+ );
105
+ break;
106
+ default:
107
+ tempResults.push(
108
+ filterObjectByValue(currentFilteredObjects, filter.value),
109
+ );
110
+ }
111
+ }
112
+ currentFilteredObjects = [...tempResults.flat()] as Resource[];
113
+ }
114
+
115
+ return currentFilteredObjects;
116
+ }
117
+
118
+ protected _handleClickEvent(originalObj: Resource) {
119
+ this.dispatchEvent(new CustomEvent("clicked", { detail: originalObj }));
120
+ }
121
+
122
+ willUpdate(changedProperties: PropertyValues) {
123
+ if (changedProperties.has("objects") || changedProperties.has("search")) {
124
+ if (this.objects) {
125
+ this._displayObjects = this.filter(this.objects, this.search);
126
+ } else {
127
+ this._displayObjects = [];
128
+ }
129
+ this.dispatchEvent(
130
+ new CustomEvent("result-count", {
131
+ detail: this._displayObjects.length,
132
+ }),
133
+ );
134
+ }
135
+ }
136
+
137
+ render() {
138
+ if (!this._displayObjects || this._displayObjects.length === 0) {
139
+ return nothing;
140
+ }
141
+
142
+ return html`<div class="card-grid card-grid-vertical">
143
+ ${this._displayObjects.map((displayObj) => {
144
+ const tags = [
145
+ {
146
+ name: `${msg(str`Balance: ${displayObj.balance}€`)}`,
147
+ type: "information",
148
+ },
149
+ ];
150
+ return html`<ds4go-card-catalog
151
+ .object=${import.meta.env.DEV ? displayObj : nothing}
152
+ type=${"vertical"}
153
+ .tags=${tags}
154
+ .header=${displayObj.name || nothing}
155
+ .content=${displayObj.participant_id ? msg(str`Participant ID: ${displayObj.participant_id}`) : nothing}
156
+ date=${displayObj.updated_at || nothing}
157
+ @click=${() => this._handleClickEvent(displayObj)}
158
+ ></ds4go-card-catalog>`;
159
+ })}
160
+ </div>`;
161
+ }
162
+ }
@@ -8,7 +8,7 @@ import {
8
8
  filterObjectByValue,
9
9
  } from "@helpers";
10
10
  import { msg } from "@lit/localize";
11
- import type { Resource, SearchObject } from "@src/component";
11
+ import type { Resource, SearchObject, UnknownResource } from "@src/component";
12
12
  import { css, html, nothing, type PropertyValues } from "lit";
13
13
  import { customElement, state } from "lit/decorators.js";
14
14
 
@@ -24,11 +24,11 @@ export class Ds4goFactBundleHolder extends ComponentObjectsHandler {
24
24
  .card-grid-vertical {
25
25
  justify-content: stretch;
26
26
  }
27
- .card-grid-vertical tems-card-catalog {
27
+ .card-grid-vertical ds4go-card-catalog {
28
28
  width: 354px;
29
29
  height: auto;
30
30
  }
31
- tems-card-catalog {
31
+ ds4go-card-catalog {
32
32
  cursor: pointer;
33
33
  }
34
34
  `;
@@ -59,7 +59,7 @@ export class Ds4goFactBundleHolder extends ComponentObjectsHandler {
59
59
  break;
60
60
  }
61
61
 
62
- const tempResults = [];
62
+ const tempResults: UnknownResource[] = [];
63
63
  for (const filter of filterGroup) {
64
64
  switch (filter.type) {
65
65
  case "interval":
@@ -109,7 +109,7 @@ export class Ds4goFactBundleHolder extends ComponentObjectsHandler {
109
109
  );
110
110
  }
111
111
  }
112
- currentFilteredObjects = [...tempResults.flat()];
112
+ currentFilteredObjects = [...tempResults.flat()] as Resource[];
113
113
  }
114
114
 
115
115
  return currentFilteredObjects;
@@ -147,7 +147,7 @@ export class Ds4goFactBundleHolder extends ComponentObjectsHandler {
147
147
  type: "information",
148
148
  },
149
149
  ];
150
- return html`<tems-card-catalog
150
+ return html`<ds4go-card-catalog
151
151
  .object=${import.meta.env.DEV ? displayObj : nothing}
152
152
  type=${"bill-image"}
153
153
  .tags=${tags}
@@ -155,7 +155,7 @@ export class Ds4goFactBundleHolder extends ComponentObjectsHandler {
155
155
  .content=${displayObj.description || nothing}
156
156
  date=${displayObj.updated_at || nothing}
157
157
  @click=${() => this._handleClickEvent(displayObj)}
158
- ></tems-card-catalog>`;
158
+ ></ds4go-card-catalog>`;
159
159
  })}
160
160
  </div>`;
161
161
  }