@ebertjendustries/cswrapper 1.0.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/dist/index.mjs ADDED
@@ -0,0 +1,2037 @@
1
+ // src/components/CSAlert.tsx
2
+ import { Alert } from "@cloudscape-design/components";
3
+
4
+ // src/types/CSFormProps.ts
5
+ var FromPropsHelper = class {
6
+ static getBasicProps = (props) => {
7
+ const localisationObject = props.localiser.localiseField(props.fieldSpec.getLocalisationKey(), props.localisationVariables, props.alternateNs);
8
+ const uniqueId = props.fieldSpec.getDataTestId();
9
+ return { localisationObject, uniqueId };
10
+ };
11
+ static usesFormField = (props) => {
12
+ const localisation = props.localiser.localiseField(props.fieldSpec.getLocalisationKey(), props.localisationVariables, props.alternateNs);
13
+ return props.formField !== void 0 || localisation?.formField !== void 0;
14
+ };
15
+ static getLocalisedErrorText = (props, value, localiseValidity) => {
16
+ if (props.formField?.errorText !== void 0) {
17
+ return props.formField?.errorText;
18
+ }
19
+ const validityLevel = props.fieldSpec.getValueValidityLevel(value);
20
+ return localiseValidity(props.fieldSpec, validityLevel);
21
+ };
22
+ static sanitizeValueToString = (value) => {
23
+ if (value === null || value === void 0) {
24
+ return "";
25
+ }
26
+ return value;
27
+ };
28
+ };
29
+
30
+ // src/components/CSFormField.tsx
31
+ import { FormField } from "@cloudscape-design/components";
32
+ import { jsx } from "react/jsx-runtime";
33
+ var FORM_FIELD_ID_SUFFIX = "_FORM_FIELD";
34
+ function CSFormField(props) {
35
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
36
+ const formFieldId = uniqueId + FORM_FIELD_ID_SUFFIX;
37
+ if (!FromPropsHelper.usesFormField(props)) {
38
+ return props.children;
39
+ }
40
+ return (
41
+ // IMPORTANT: Order of props determines which one "wins". You can override Elements that are present in the
42
+ // localisation texts via the additional props. For instance, you can pass in
43
+ // non-static localisations that require variable values dynamically.
44
+ /* @__PURE__ */ jsx(FormField, { "data-testid": formFieldId, ...localisationObject?.formField, ...props.formField, children: props.children })
45
+ );
46
+ }
47
+
48
+ // src/components/ChildUtils.tsx
49
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
50
+ var ChildUtils = class {
51
+ static getChildren = (props, localisationObject) => {
52
+ const childrenRaw = props.children ?? localisationObject?.children;
53
+ const children = props.childrenWrapper ? props.childrenWrapper(childrenRaw) : childrenRaw;
54
+ let finalChildren = props.preventOverflow ? /* @__PURE__ */ jsx2("div", { style: {
55
+ whiteSpace: "nowrap",
56
+ overflow: "hidden",
57
+ textOverflow: "ellipsis"
58
+ }, children }) : children;
59
+ let formFieldProps = props.formField ?? localisationObject?.formField;
60
+ if (props.inlineLabel && FromPropsHelper.usesFormField(props)) {
61
+ finalChildren = /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexWrap: "nowrap" }, children: [
62
+ /* @__PURE__ */ jsx2("div", { style: {
63
+ flex: "none",
64
+ fontWeight: "bold",
65
+ paddingRight: "5px"
66
+ }, children: formFieldProps.label + ":" }),
67
+ finalChildren
68
+ ] });
69
+ formFieldProps = { ...formFieldProps, label: void 0 };
70
+ }
71
+ return { children: finalChildren, formProps: { ...props, formField: formFieldProps } };
72
+ };
73
+ };
74
+
75
+ // src/components/CSAlert.tsx
76
+ import { jsx as jsx3 } from "react/jsx-runtime";
77
+ function CSAlert(props) {
78
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
79
+ const { children, formProps } = ChildUtils.getChildren(props, localisationObject);
80
+ return /* @__PURE__ */ jsx3(CSFormField, { ...formProps, children: /* @__PURE__ */ jsx3(
81
+ Alert,
82
+ {
83
+ "data-testid": uniqueId,
84
+ ...props,
85
+ ...localisationObject,
86
+ children
87
+ }
88
+ ) });
89
+ }
90
+
91
+ // src/components/CSBox.tsx
92
+ import { Box } from "@cloudscape-design/components";
93
+ import { jsx as jsx4 } from "react/jsx-runtime";
94
+ function CSBox(props) {
95
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
96
+ const { children, formProps } = ChildUtils.getChildren(props, localisationObject);
97
+ return /* @__PURE__ */ jsx4(CSFormField, { ...formProps, children: /* @__PURE__ */ jsx4(
98
+ Box,
99
+ {
100
+ "data-testid": uniqueId,
101
+ ...props,
102
+ ...localisationObject,
103
+ children
104
+ }
105
+ ) });
106
+ }
107
+
108
+ // src/components/CSButton.tsx
109
+ import { Button } from "@cloudscape-design/components";
110
+ import { jsx as jsx5 } from "react/jsx-runtime";
111
+ function CSButton(props) {
112
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
113
+ const { children, formProps } = ChildUtils.getChildren(props, localisationObject);
114
+ return /* @__PURE__ */ jsx5(CSFormField, { ...formProps, children: /* @__PURE__ */ jsx5(
115
+ Button,
116
+ {
117
+ "data-testid": uniqueId,
118
+ ...props,
119
+ ...localisationObject,
120
+ children
121
+ }
122
+ ) });
123
+ }
124
+
125
+ // src/components/CSCheckbox.tsx
126
+ import { Checkbox } from "@cloudscape-design/components";
127
+ import { jsx as jsx6 } from "react/jsx-runtime";
128
+ function CSCheckbox(props) {
129
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
130
+ const { children, formProps } = ChildUtils.getChildren(props, localisationObject);
131
+ return /* @__PURE__ */ jsx6(CSFormField, { ...formProps, children: /* @__PURE__ */ jsx6(
132
+ Checkbox,
133
+ {
134
+ "data-testid": uniqueId,
135
+ name: uniqueId,
136
+ controlId: uniqueId,
137
+ onChange: props.onChange ? props.onChange : ({ detail }) => props.onChangeValue(props.fieldSpec.key, detail.checked),
138
+ ...props,
139
+ ...localisationObject,
140
+ children
141
+ }
142
+ ) });
143
+ }
144
+
145
+ // src/components/CSDatePicker.tsx
146
+ import { DatePicker } from "@cloudscape-design/components";
147
+ import { jsx as jsx7 } from "react/jsx-runtime";
148
+ function CSDatePicker(props) {
149
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
150
+ const sanitizeValue = () => {
151
+ return new Date(FromPropsHelper.sanitizeValueToString(props.value)).toISOString().split("T")[0];
152
+ };
153
+ return /* @__PURE__ */ jsx7(CSFormField, { ...props, children: /* @__PURE__ */ jsx7(
154
+ DatePicker,
155
+ {
156
+ "data-testid": uniqueId,
157
+ controlId: uniqueId,
158
+ onChange: ({ detail }) => props.onChangeValue(props.fieldSpec.key, detail.value),
159
+ ...props,
160
+ ...localisationObject,
161
+ value: sanitizeValue()
162
+ }
163
+ ) });
164
+ }
165
+
166
+ // src/components/CSMultiselect.tsx
167
+ import { Multiselect } from "@cloudscape-design/components";
168
+ import { jsx as jsx8 } from "react/jsx-runtime";
169
+ function CSMultiselect(props) {
170
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
171
+ const { formProps } = ChildUtils.getChildren(props, localisationObject);
172
+ const adaptedOnChange = ({ detail }) => {
173
+ if (props.enableSelectAll || props.enforceSelection) {
174
+ if (detail.selectedOptions.length === 0) {
175
+ props.onChangeValue(props.fieldSpec.key, [props.selectedOptions[0].value]);
176
+ } else {
177
+ props.onChangeValue(props.fieldSpec.key, detail.selectedOptions.map((sel) => sel.value));
178
+ }
179
+ } else {
180
+ props.onChangeValue(props.fieldSpec.key, detail.selectedOptions.map((sel) => sel.value));
181
+ }
182
+ };
183
+ const hideTokens = props.hideTokens ?? (props.tokenLimit !== void 0 && props.tokenLimit === 0);
184
+ return /* @__PURE__ */ jsx8(CSFormField, { ...formProps, children: /* @__PURE__ */ jsx8(
185
+ Multiselect,
186
+ {
187
+ "data-testid": uniqueId,
188
+ controlId: uniqueId,
189
+ filteringType: props.filteringType ?? "auto",
190
+ onChange: adaptedOnChange,
191
+ enableSelectAll: true,
192
+ ...props,
193
+ ...localisationObject,
194
+ hideTokens,
195
+ options: props.options
196
+ }
197
+ ) });
198
+ }
199
+
200
+ // src/types/ObjectWithId.ts
201
+ var ObjectWithId = class {
202
+ id;
203
+ static idToString = (objectWithId) => {
204
+ return objectWithId.id ? objectWithId.id.toString() : "<N/A>";
205
+ };
206
+ static toObjectWithId = (array, idExtractor) => {
207
+ return array.map((object) => ({
208
+ ...object,
209
+ id: idExtractor(object)
210
+ }));
211
+ };
212
+ };
213
+
214
+ // src/utils/SelectHelper.ts
215
+ var SelectHelper = class _SelectHelper {
216
+ static singleSelectOptionWithId = (objects, selectedObjectId, toOptionDefinition) => {
217
+ return this.singleSelectOption(objects, objects.find((importObject) => ObjectWithId.idToString(importObject) === selectedObjectId?.toString()), toOptionDefinition);
218
+ };
219
+ static singleSelectOption = (objects, selectedObject, toOptionDefinition) => {
220
+ const options = objects.map((object) => ({
221
+ value: ObjectWithId.idToString(object),
222
+ ...toOptionDefinition(object)
223
+ }));
224
+ const selectedOption = selectedObject === void 0 ? null : _SelectHelper.getSelectedOptions(options, [selectedObject.id])[0];
225
+ return {
226
+ options,
227
+ selectedOption
228
+ };
229
+ };
230
+ static singleSelectEnum = (enumFactory, selectedEnum, localiser, exclude) => {
231
+ const options = enumFactory.values.filter((enumInstance) => exclude === void 0 || !exclude.includes(enumInstance)).map((enumInstance) => {
232
+ const enumTranslation = localiser.getEnumLocalisation(enumFactory, enumInstance);
233
+ return {
234
+ value: enumInstance.toString(),
235
+ label: enumTranslation.label,
236
+ description: enumTranslation.description
237
+ };
238
+ });
239
+ const selectedOption = selectedEnum === void 0 ? null : _SelectHelper.getSelectedEnumOptions(options, [selectedEnum.toString()])[0];
240
+ return {
241
+ options,
242
+ selectedOption
243
+ };
244
+ };
245
+ static multiSelectOptions = (objects, selectedObjects, toOptionDefinition) => {
246
+ const options = objects.map((object) => ({
247
+ value: ObjectWithId.idToString(object),
248
+ ...toOptionDefinition(object)
249
+ }));
250
+ const selectedOptions = _SelectHelper.getSelectedOptions(options, selectedObjects.map((s) => s.id));
251
+ return {
252
+ options,
253
+ selectedOptions
254
+ };
255
+ };
256
+ static multiSelectEnums = (enumFactory, selectedEnums, localiser) => {
257
+ const options = enumFactory.values.map((enumInstance) => {
258
+ const enumTranslation = localiser.getEnumLocalisation(enumFactory, enumInstance);
259
+ return {
260
+ value: enumInstance.toString(),
261
+ label: enumTranslation.label,
262
+ description: enumTranslation.description
263
+ };
264
+ });
265
+ const selectedOptions = _SelectHelper.getSelectedEnumOptions(options, selectedEnums);
266
+ return {
267
+ options,
268
+ selectedOptions
269
+ };
270
+ };
271
+ static getSelectedOptions = (options, selectedIds) => {
272
+ const selectedIdsSet = {};
273
+ selectedIds.forEach((selId) => selId !== void 0 ? selectedIdsSet[selId] = true : null);
274
+ return options.filter((option) => option.value && selectedIdsSet[parseInt(option.value)]);
275
+ };
276
+ static getSelectedEnumOptions = (options, selectedEnums) => {
277
+ const selectedIdsSet = {};
278
+ selectedEnums.forEach((selId) => selId !== void 0 ? selectedIdsSet[selId.toString()] = true : null);
279
+ return options.filter((option) => option.value && selectedIdsSet[option.value]);
280
+ };
281
+ };
282
+
283
+ // src/components/CSEnumMultiselect.tsx
284
+ import { jsx as jsx9 } from "react/jsx-runtime";
285
+ function CSEnumMultiselect(props) {
286
+ return /* @__PURE__ */ jsx9(
287
+ CSMultiselect,
288
+ {
289
+ ...SelectHelper.multiSelectEnums(props.factory, props.selectedEnums, props.localiser),
290
+ ...props
291
+ }
292
+ );
293
+ }
294
+
295
+ // src/components/CSSegmentedControl.tsx
296
+ import { SegmentedControl } from "@cloudscape-design/components";
297
+ import { jsx as jsx10 } from "react/jsx-runtime";
298
+ function CSSegmentedControl(props) {
299
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
300
+ const { formProps } = ChildUtils.getChildren(props, localisationObject);
301
+ return /* @__PURE__ */ jsx10(CSFormField, { ...formProps, children: /* @__PURE__ */ jsx10(
302
+ SegmentedControl,
303
+ {
304
+ "data-testid": uniqueId,
305
+ onChange: ({ detail }) => props.onChangeValue(props.fieldSpec.key, detail.selectedId),
306
+ ...props,
307
+ ...localisationObject
308
+ }
309
+ ) });
310
+ }
311
+
312
+ // src/components/CSEnumSegmentedControl.tsx
313
+ import { jsx as jsx11 } from "react/jsx-runtime";
314
+ function CSEnumSegmentedControl(props) {
315
+ const options = props.factory.values.filter((e) => props.exclude === void 0 || !props.exclude.includes(e)).map((e) => ({
316
+ text: props.localiser.getEnumLabel(props.factory, e),
317
+ id: e.toString()
318
+ }));
319
+ return /* @__PURE__ */ jsx11(
320
+ CSSegmentedControl,
321
+ {
322
+ selectedId: props.selectedEnum === void 0 ? null : props.selectedEnum.toString(),
323
+ options,
324
+ label: props.formField ? props.formField.label : void 0,
325
+ ...props
326
+ }
327
+ );
328
+ }
329
+
330
+ // src/components/CSSelect.tsx
331
+ import { Select } from "@cloudscape-design/components";
332
+ import { jsx as jsx12 } from "react/jsx-runtime";
333
+ function CSSelect(props) {
334
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
335
+ const { formProps } = ChildUtils.getChildren(props, localisationObject);
336
+ return /* @__PURE__ */ jsx12(CSFormField, { ...formProps, children: /* @__PURE__ */ jsx12(
337
+ Select,
338
+ {
339
+ "data-testid": uniqueId,
340
+ controlId: uniqueId,
341
+ onChange: ({ detail }) => props.onChangeValue(props.fieldSpec.key, detail.selectedOption.value),
342
+ ...props,
343
+ ...localisationObject
344
+ }
345
+ ) });
346
+ }
347
+
348
+ // src/components/CSEnumSelect.tsx
349
+ import { jsx as jsx13 } from "react/jsx-runtime";
350
+ function CSEnumSelect(props) {
351
+ return /* @__PURE__ */ jsx13(
352
+ CSSelect,
353
+ {
354
+ ...SelectHelper.singleSelectEnum(props.factory, props.selectedEnum, props.localiser, props.exclude),
355
+ ...props
356
+ }
357
+ );
358
+ }
359
+
360
+ // src/components/CSEnumTiles.tsx
361
+ import { Tiles } from "@cloudscape-design/components";
362
+ import { jsx as jsx14 } from "react/jsx-runtime";
363
+ function CSEnumTiles(props) {
364
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
365
+ const items = props.factory.values.filter((enumInstance) => props.exclude === void 0 || !props.exclude.includes(enumInstance)).map((enumInstance) => {
366
+ const enumTranslation = props.localiser.getEnumLocalisation(props.factory, enumInstance);
367
+ return {
368
+ value: enumInstance.toString(),
369
+ label: enumTranslation.label,
370
+ description: enumTranslation.description
371
+ };
372
+ });
373
+ return /* @__PURE__ */ jsx14(
374
+ Tiles,
375
+ {
376
+ "data-testid": uniqueId,
377
+ controlId: uniqueId,
378
+ name: uniqueId,
379
+ onChange: ({ detail }) => props.onChangeValue(props.fieldSpec.key, detail.value),
380
+ value: props.selectedEnum ? props.selectedEnum.toString() : null,
381
+ items,
382
+ ...props,
383
+ ...localisationObject
384
+ }
385
+ );
386
+ }
387
+
388
+ // src/components/CSLink.tsx
389
+ import { Link } from "@cloudscape-design/components";
390
+
391
+ // src/utils/BrowserUtils.ts
392
+ var openInNewTab = (link) => {
393
+ const newWindow = window.open(link, "_blank", "noopener,noreferrer");
394
+ if (newWindow) newWindow.opener = null;
395
+ };
396
+ var warnWhenTabIsClosed = (isDirty) => {
397
+ const handleTabClose = (event) => {
398
+ if (isDirty !== void 0 && !isDirty()) {
399
+ return void 0;
400
+ }
401
+ event.preventDefault();
402
+ return event.returnValue = "Are you sure you want to exit?";
403
+ };
404
+ window.addEventListener("beforeunload", handleTabClose);
405
+ return () => {
406
+ window.removeEventListener("beforeunload", handleTabClose);
407
+ };
408
+ };
409
+
410
+ // src/components/CSLink.tsx
411
+ import { jsx as jsx15 } from "react/jsx-runtime";
412
+ function CSLink(props) {
413
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
414
+ const { children, formProps } = ChildUtils.getChildren(props, localisationObject);
415
+ return /* @__PURE__ */ jsx15(CSFormField, { ...formProps, children: /* @__PURE__ */ jsx15(
416
+ Link,
417
+ {
418
+ "data-testid": uniqueId,
419
+ ...props,
420
+ ...localisationObject,
421
+ children
422
+ }
423
+ ) });
424
+ }
425
+ function CSExternalLink(props) {
426
+ return /* @__PURE__ */ jsx15(CSLink, { ...props, external: true, onFollow: (detail) => detail.preventDefault(), children: /* @__PURE__ */ jsx15("span", { onClick: () => openInNewTab(props.link), children: props.children }) });
427
+ }
428
+
429
+ // src/components/CSHeader.tsx
430
+ import { Header } from "@cloudscape-design/components";
431
+ import { jsx as jsx16 } from "react/jsx-runtime";
432
+ function CSHeader(props) {
433
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
434
+ const { children } = ChildUtils.getChildren(props, localisationObject);
435
+ return /* @__PURE__ */ jsx16(
436
+ Header,
437
+ {
438
+ "data-testid": uniqueId,
439
+ ...props,
440
+ ...localisationObject,
441
+ children
442
+ }
443
+ );
444
+ }
445
+
446
+ // src/components/CSInput.tsx
447
+ import { Input } from "@cloudscape-design/components";
448
+ import { jsx as jsx17 } from "react/jsx-runtime";
449
+ function CSInput(props) {
450
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
451
+ const { formProps } = ChildUtils.getChildren(props, localisationObject);
452
+ const sanitizedValue = FromPropsHelper.sanitizeValueToString(props.value);
453
+ const errorText = FromPropsHelper.getLocalisedErrorText(props, sanitizedValue, props.localiser.getFieldValidityLocalisationFunction());
454
+ return /* @__PURE__ */ jsx17(CSFormField, { ...props, formField: { ...formProps, errorText }, children: /* @__PURE__ */ jsx17(
455
+ Input,
456
+ {
457
+ "data-testid": uniqueId,
458
+ controlId: uniqueId,
459
+ onChange: ({ detail }) => props.onChangeValue(props.fieldSpec.key, detail.value),
460
+ ...props,
461
+ ...localisationObject,
462
+ value: sanitizedValue
463
+ }
464
+ ) });
465
+ }
466
+
467
+ // src/components/CSNumericInput.tsx
468
+ import { Input as Input2 } from "@cloudscape-design/components";
469
+ import { jsx as jsx18 } from "react/jsx-runtime";
470
+ function CSNumericInput(props) {
471
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
472
+ const { formProps } = ChildUtils.getChildren(props, localisationObject);
473
+ const sanitizeValue = () => {
474
+ if (props.value === void 0 || props.value === null || isNaN(props.value)) {
475
+ return "";
476
+ }
477
+ return FromPropsHelper.sanitizeValueToString(props.value);
478
+ };
479
+ const sanitizedValue = sanitizeValue();
480
+ const errorText = FromPropsHelper.getLocalisedErrorText(props, sanitizedValue, props.localiser.getFieldValidityLocalisationFunction());
481
+ return /* @__PURE__ */ jsx18(CSFormField, { ...formProps, formField: { ...props.formField, errorText }, children: /* @__PURE__ */ jsx18(
482
+ Input2,
483
+ {
484
+ "data-testid": uniqueId,
485
+ controlId: uniqueId,
486
+ onChange: ({ detail }) => {
487
+ props.onChangeValue(props.fieldSpec.key, props.step && props.step !== "any" && props.step % 1 === 0 ? parseInt(detail.value) : parseFloat(detail.value));
488
+ },
489
+ ...props,
490
+ ...localisationObject,
491
+ value: sanitizedValue,
492
+ type: "number",
493
+ inputMode: "numeric"
494
+ }
495
+ ) });
496
+ }
497
+
498
+ // src/components/CSStatusIndicator.tsx
499
+ import { StatusIndicator } from "@cloudscape-design/components";
500
+ import { jsx as jsx19 } from "react/jsx-runtime";
501
+ function CSStatusIndicator(props) {
502
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
503
+ const { children, formProps } = ChildUtils.getChildren(props, localisationObject);
504
+ return /* @__PURE__ */ jsx19(CSFormField, { ...formProps, children: /* @__PURE__ */ jsx19(
505
+ StatusIndicator,
506
+ {
507
+ "data-testid": uniqueId,
508
+ ...props,
509
+ ...localisationObject,
510
+ children
511
+ }
512
+ ) });
513
+ }
514
+
515
+ // src/components/CSTextContent.tsx
516
+ import { TextContent } from "@cloudscape-design/components";
517
+ import { jsx as jsx20 } from "react/jsx-runtime";
518
+ function CSTextContent(props) {
519
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
520
+ const { children, formProps } = ChildUtils.getChildren(props, localisationObject);
521
+ return /* @__PURE__ */ jsx20(CSFormField, { ...formProps, children: /* @__PURE__ */ jsx20(
522
+ TextContent,
523
+ {
524
+ "data-testid": uniqueId,
525
+ ...props,
526
+ ...localisationObject,
527
+ children
528
+ }
529
+ ) });
530
+ }
531
+
532
+ // src/components/CSTextarea.tsx
533
+ import { Textarea } from "@cloudscape-design/components";
534
+ import { jsx as jsx21 } from "react/jsx-runtime";
535
+ function CSTextarea(props) {
536
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
537
+ const { formProps } = ChildUtils.getChildren(props, localisationObject);
538
+ const sanitizedValue = FromPropsHelper.sanitizeValueToString(props.value);
539
+ const errorText = FromPropsHelper.getLocalisedErrorText(props, sanitizedValue, props.localiser.getFieldValidityLocalisationFunction());
540
+ return /* @__PURE__ */ jsx21(CSFormField, { ...props, formField: { ...formProps, errorText }, children: /* @__PURE__ */ jsx21(
541
+ Textarea,
542
+ {
543
+ "data-testid": uniqueId,
544
+ controlId: uniqueId,
545
+ onChange: ({ detail }) => props.onChangeValue(props.fieldSpec.key, detail.value),
546
+ ...props,
547
+ ...localisationObject,
548
+ value: sanitizedValue
549
+ }
550
+ ) });
551
+ }
552
+
553
+ // src/components/CSTimeInput.tsx
554
+ import { TimeInput } from "@cloudscape-design/components";
555
+ import { jsx as jsx22 } from "react/jsx-runtime";
556
+ function CSTimeInput(props) {
557
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
558
+ const { formProps } = ChildUtils.getChildren(props, localisationObject);
559
+ const defaultFormat = "hh:mm";
560
+ return /* @__PURE__ */ jsx22(CSFormField, { ...formProps, children: /* @__PURE__ */ jsx22(
561
+ TimeInput,
562
+ {
563
+ "data-testid": uniqueId,
564
+ autoFocus: props.autoFocus,
565
+ onChange: ({ detail }) => props.onChangeValue(props.fieldSpec.key, detail.value),
566
+ format: props.format ? props.format : defaultFormat,
567
+ placeholder: props.placeholder ? props.placeholder : defaultFormat,
568
+ ...props,
569
+ ...localisationObject
570
+ }
571
+ ) });
572
+ }
573
+
574
+ // src/components/CSToggle.tsx
575
+ import { Toggle } from "@cloudscape-design/components";
576
+ import { jsx as jsx23 } from "react/jsx-runtime";
577
+ function CSToggle(props) {
578
+ const { localisationObject, uniqueId } = FromPropsHelper.getBasicProps(props);
579
+ const { children, formProps } = ChildUtils.getChildren(props, localisationObject);
580
+ return /* @__PURE__ */ jsx23(CSFormField, { ...formProps, children: /* @__PURE__ */ jsx23(
581
+ Toggle,
582
+ {
583
+ "data-testid": uniqueId,
584
+ name: uniqueId,
585
+ controlId: uniqueId,
586
+ onChange: props.onChange ? props.onChange : ({ detail }) => props.onChangeValue(props.fieldSpec.key, detail.checked),
587
+ ...props,
588
+ ...localisationObject,
589
+ children
590
+ }
591
+ ) });
592
+ }
593
+
594
+ // src/views/CSVEnumRatingView.tsx
595
+ import { Rating } from "@smastrom/react-rating";
596
+ import { useEffect, useState } from "react";
597
+
598
+ // src/utils/EnumFactory.ts
599
+ var EnumFactory = class {
600
+ constructor(enumName, values) {
601
+ this.enumName = enumName;
602
+ this.values = values;
603
+ if (this.values.length === 0) {
604
+ throw new Error("Empty localized enum array is not allowed here");
605
+ }
606
+ }
607
+ getEnumIndex(instance) {
608
+ return this.values.indexOf(instance);
609
+ }
610
+ };
611
+
612
+ // src/types/ElementValidityLevel.ts
613
+ var ElementValidityLevel = /* @__PURE__ */ ((ElementValidityLevel2) => {
614
+ ElementValidityLevel2["VALID"] = "VALID";
615
+ ElementValidityLevel2["REQUIRED_VALUE_IS_NOT_PRESENT"] = "REQUIRED_VALUE_IS_NOT_PRESENT";
616
+ ElementValidityLevel2["MAX_LENGTH_EXCEEDED"] = "MAX_LENGTH_EXCEEDED";
617
+ ElementValidityLevel2["LOWER_BOUND_ONLY_TOO_SMALL"] = "LOWER_BOUND_ONLY_TOO_SMALL";
618
+ ElementValidityLevel2["UPPER_BOUND_ONLY_TOO_BIG"] = "UPPER_BOUND_ONLY_TOO_BIG";
619
+ ElementValidityLevel2["BOTH_BOUNDS_OUT_OF_BOUNDS"] = "BOTH_BOUNDS_OUT_OF_BOUNDS";
620
+ return ElementValidityLevel2;
621
+ })(ElementValidityLevel || {});
622
+ var ELEMENT_VALIDITY_LEVEL_FACTORY = new EnumFactory("ElementValidityLevel", Object.values(ElementValidityLevel));
623
+
624
+ // src/logging/Log.ts
625
+ var DISABLE_LOGGING = false;
626
+ var Log = class _Log {
627
+ prefix;
628
+ debugLogging;
629
+ constructor(prefix) {
630
+ this.prefix = prefix ? "[" + prefix + "] " : "";
631
+ this.debugLogging = true;
632
+ }
633
+ static toReadableObjectString(object) {
634
+ return this.toObjectStr(object, (object2) => JSON.stringify(object2, null, 2));
635
+ }
636
+ static toCompactReadableObjectString(object, dependencyCharLimit) {
637
+ const str = this.toObjectStr(object, (object2) => JSON.stringify(object2));
638
+ const maxLen = Math.min(str.length, dependencyCharLimit);
639
+ if (maxLen < str.length) {
640
+ return str.substring(0, maxLen) + " ( ... continued)";
641
+ }
642
+ return str;
643
+ }
644
+ static toObjectStr(object, stringify) {
645
+ if (object === null) {
646
+ return "null";
647
+ }
648
+ if (object === void 0) {
649
+ return "undefined";
650
+ }
651
+ let s = stringify(object);
652
+ if (s === void 0) {
653
+ return "function";
654
+ }
655
+ return s.replaceAll("\\", "");
656
+ }
657
+ /**
658
+ * log at debugging level
659
+ */
660
+ debug(msg, ...supportingDetails) {
661
+ this.emitLogMessage("debug", msg, supportingDetails);
662
+ }
663
+ /**
664
+ * log at information level
665
+ */
666
+ info(msg, ...supportingDetails) {
667
+ this.emitLogMessage("info", msg, supportingDetails);
668
+ }
669
+ /**
670
+ * log at warning level
671
+ */
672
+ warn(msg, ...supportingDetails) {
673
+ this.emitLogMessage("warn", msg, supportingDetails);
674
+ }
675
+ /**
676
+ * log at error level
677
+ */
678
+ error(msg, ...supportingDetails) {
679
+ this.emitLogMessage("error", msg, supportingDetails);
680
+ }
681
+ object(prefixMsg, object) {
682
+ this.debug(prefixMsg + " " + _Log.toReadableObjectString(object));
683
+ }
684
+ effectStart(effectName, msg, dependencies, dependencyCharLimit) {
685
+ let dependenciesSuffix = "";
686
+ if (dependencies) {
687
+ let dependenciesStr = "";
688
+ for (let i = 0; i < dependencies.length; i++) {
689
+ const dependency = dependencies[i];
690
+ dependenciesStr = `${dependenciesStr} Dep[${i}]=<${_Log.toCompactReadableObjectString(dependency, dependencyCharLimit || 60)}>`;
691
+ }
692
+ dependenciesSuffix = (msg.length > 0 ? ", " : "") + "DEPS:" + dependenciesStr;
693
+ }
694
+ this.effect(`start - ${effectName}`, `${msg}${dependenciesSuffix}`);
695
+ }
696
+ effectEnd(effectName) {
697
+ this.debug(`EFFECT(end - ${effectName})`);
698
+ }
699
+ effect(effectName, msg) {
700
+ this.debug(`EFFECT(${effectName}): ${msg}`);
701
+ }
702
+ /**
703
+ * creates a log message with some detailed information
704
+ * @param msgType type of message (debug, info, warn, error)
705
+ * @param msg the message as string
706
+ * @param supportingDetails details that should be logged
707
+ */
708
+ emitLogMessage(msgType, msg, supportingDetails) {
709
+ if (DISABLE_LOGGING) {
710
+ return;
711
+ }
712
+ const logTS = (/* @__PURE__ */ new Date()).toISOString();
713
+ if (!this.debugLogging && msgType === "debug") {
714
+ return;
715
+ }
716
+ if (supportingDetails.length > 0) {
717
+ console[msgType](`${logTS} ${this.prefix}${msg}${supportingDetails}`);
718
+ } else {
719
+ console[msgType](`${logTS} ${this.prefix}${msg}`);
720
+ }
721
+ }
722
+ };
723
+
724
+ // src/types/ViewSpec.ts
725
+ var LOGGER = new Log("ViewSpec");
726
+ var ViewElementSpec = class {
727
+ constructor(key, instanceId) {
728
+ this.key = key;
729
+ this.instanceId = instanceId;
730
+ }
731
+ parent;
732
+ ns;
733
+ dataTestId;
734
+ localisationKey;
735
+ keyHierarchy;
736
+ getDataTestId() {
737
+ if (this.dataTestId === void 0) {
738
+ const parentDataTestId = this.parent ? this.parent.getDataTestId() : "";
739
+ this.dataTestId = this.instanceId ? `${parentDataTestId}${this.key}${this.instanceId}END` : `${parentDataTestId}${this.key}END`;
740
+ }
741
+ return this.dataTestId;
742
+ }
743
+ getLocalisationKey() {
744
+ if (this.localisationKey === void 0) {
745
+ const keys = this.getKeyHierarchy();
746
+ this.localisationKey = this.ns.createKey(...keys);
747
+ }
748
+ return this.localisationKey;
749
+ }
750
+ getKeyHierarchy() {
751
+ if (this.keyHierarchy === void 0) {
752
+ const parentHierarchy = this.parent ? this.parent.getKeyHierarchy() : [];
753
+ this.keyHierarchy = [...parentHierarchy, this.key];
754
+ }
755
+ return this.keyHierarchy;
756
+ }
757
+ };
758
+ var FieldSpec = class _FieldSpec extends ViewElementSpec {
759
+ constructor(key, required, maxLength, minValue, maxValue, customFieldValidator, instanceId) {
760
+ super(key, instanceId);
761
+ this.required = required;
762
+ this.maxLength = maxLength;
763
+ this.minValue = minValue;
764
+ this.maxValue = maxValue;
765
+ this.customFieldValidator = customFieldValidator;
766
+ }
767
+ static getTOValidityLevel(transportObject, elements) {
768
+ if (elements.length === 0) {
769
+ throw Error("At least one field property must be given");
770
+ }
771
+ for (let index = 0; index < elements.length; index++) {
772
+ const field = elements[index];
773
+ const fieldValidity = field.getValueValidityLevel(transportObject[field.key]);
774
+ if (fieldValidity !== "VALID" /* VALID */) {
775
+ return fieldValidity;
776
+ }
777
+ }
778
+ return "VALID" /* VALID */;
779
+ }
780
+ static isTOValid(transportObject, Elements) {
781
+ return this.getTOValidityLevel(transportObject, Elements) === "VALID" /* VALID */;
782
+ }
783
+ static debugLogElementValidityArray(elements, Elements) {
784
+ for (let index = 0; index < elements.length; index++) {
785
+ const element = elements[index];
786
+ _FieldSpec.debugLogElementValidity(element, "idx=" + index.toString(), Elements);
787
+ }
788
+ }
789
+ static debugLogElementValidity(element, elementId, Elements) {
790
+ for (const field of Elements) {
791
+ const fieldValidity = _FieldSpec.getTOValidityLevel(element, [field]);
792
+ LOGGER.info(`Field validity level, element id = <${elementId}>, field name = <${field.getDataTestId()}>, validity level = <${fieldValidity.toString()}>.`);
793
+ }
794
+ }
795
+ getValueValidityLevel(value) {
796
+ if (this.customFieldValidator) {
797
+ return this.customFieldValidator(this, value);
798
+ }
799
+ const isString = value !== void 0 && value !== null && (typeof value === "string" || value instanceof String);
800
+ const isNumber = value !== void 0 && value !== null && typeof value === "number";
801
+ if (this.required && (value === void 0 || value === null || isString && value.trim().length === 0 || isNumber && isNaN(value))) {
802
+ return "REQUIRED_VALUE_IS_NOT_PRESENT" /* REQUIRED_VALUE_IS_NOT_PRESENT */;
803
+ }
804
+ if (isString && this.maxLength !== void 0 && value.length > this.getMaxLength()) {
805
+ return "MAX_LENGTH_EXCEEDED" /* MAX_LENGTH_EXCEEDED */;
806
+ }
807
+ if (isNumber) {
808
+ if (this.minValue !== void 0 && this.maxValue === void 0 && this.minValue > value) {
809
+ return "LOWER_BOUND_ONLY_TOO_SMALL" /* LOWER_BOUND_ONLY_TOO_SMALL */;
810
+ }
811
+ if (this.maxValue !== void 0 && this.minValue === void 0 && this.maxValue < value) {
812
+ return "UPPER_BOUND_ONLY_TOO_BIG" /* UPPER_BOUND_ONLY_TOO_BIG */;
813
+ }
814
+ if (this.minValue !== void 0 && this.maxValue !== void 0 && (this.minValue > value || this.maxValue < value)) {
815
+ return "BOTH_BOUNDS_OUT_OF_BOUNDS" /* BOTH_BOUNDS_OUT_OF_BOUNDS */;
816
+ }
817
+ }
818
+ return "VALID" /* VALID */;
819
+ }
820
+ getMaxLength() {
821
+ return this.maxLength ? this.maxLength : Number.MAX_SAFE_INTEGER;
822
+ }
823
+ };
824
+ var ViewSpec = class _ViewSpec extends ViewElementSpec {
825
+ constructor(key, ns, instanceId, customViewValidator) {
826
+ super(key, instanceId);
827
+ this.ns = ns;
828
+ if (!customViewValidator) {
829
+ this.viewValidator = () => "VALID" /* VALID */;
830
+ } else {
831
+ this.viewValidator = customViewValidator;
832
+ }
833
+ }
834
+ elements;
835
+ viewValidator;
836
+ static create(key, ns, elementDefinition, instanceId, parent, customViewValidator) {
837
+ const viewSpec = new _ViewSpec(key, ns, instanceId, customViewValidator);
838
+ viewSpec.parent = parent;
839
+ viewSpec.elements = elementDefinition(viewSpec);
840
+ return viewSpec;
841
+ }
842
+ addField(fieldSpec) {
843
+ fieldSpec.parent = this;
844
+ fieldSpec.ns = this.ns;
845
+ return fieldSpec;
846
+ }
847
+ addFieldFromProps(fieldProps, customFieldValidator, instanceId) {
848
+ const fieldSpec = new FieldSpec(fieldProps.key, fieldProps.required, fieldProps.maxLength, fieldProps.minValue, fieldProps.maxValue, customFieldValidator, instanceId);
849
+ fieldSpec.parent = this;
850
+ fieldSpec.ns = this.ns;
851
+ return fieldSpec;
852
+ }
853
+ addView(viewSpecProvider, key, instanceId) {
854
+ const viewSpec = viewSpecProvider(this, key, instanceId);
855
+ viewSpec.ns = this.ns;
856
+ return viewSpec;
857
+ }
858
+ getAllElements() {
859
+ return Object.values(this.elements);
860
+ }
861
+ getValueValidityLevel(value) {
862
+ return this.viewValidator(this, value);
863
+ }
864
+ };
865
+
866
+ // src/views/CSVEnumRatingView.tsx
867
+ import { jsx as jsx24, jsxs as jsxs2 } from "react/jsx-runtime";
868
+ var CSV_ENUM_RATING_VIEW_SPEC = (parent, key, instanceId) => ViewSpec.create(key, parent.ns, (spec) => ({
869
+ rating: spec.addField(new FieldSpec("rating")),
870
+ boxRatingName: spec.addField(new FieldSpec("boxRatingName"))
871
+ }), instanceId, parent);
872
+ function getEnumRatingValues(factory, toOrderNumber) {
873
+ return toOrderNumber ? factory.values.sort((e1, e2) => toOrderNumber(e1) - toOrderNumber(e2)) : factory.values;
874
+ }
875
+ function getEnumRatingLabel(enumInstance, instanceId) {
876
+ return `${instanceId}_${enumInstance.toString()}`;
877
+ }
878
+ function CSVEnumRatingView(props) {
879
+ const spec = props.viewSpec;
880
+ const { elements } = spec;
881
+ const [hoveredValue, setHoveredValue] = useState(props.selectedEnum);
882
+ const valuesInOrder = getEnumRatingValues(props.factory, props.toOrderNumber);
883
+ const onHover = (hoveredIndex) => {
884
+ if (hoveredIndex === 0) {
885
+ setHoveredValue(props.selectedEnum);
886
+ } else {
887
+ setHoveredValue(valuesInOrder[hoveredIndex]);
888
+ }
889
+ };
890
+ const itemCount = Math.max(1, Math.min(valuesInOrder.length - 1, 10));
891
+ useEffect(() => {
892
+ setHoveredValue(props.selectedEnum);
893
+ }, [props.selectedEnum]);
894
+ return /* @__PURE__ */ jsxs2(CSFormField, { fieldSpec: elements.rating, localiser: props.localiser, children: [
895
+ /* @__PURE__ */ jsx24(
896
+ Rating,
897
+ {
898
+ "data-testid": elements.rating.getDataTestId(),
899
+ isDisabled: props.disabled,
900
+ style: { maxWidth: 100 },
901
+ items: itemCount,
902
+ value: !props.disabled ? valuesInOrder.indexOf(props.selectedEnum) : 0,
903
+ onHoverChange: onHover,
904
+ onChange: (selectedIndex) => props.onChangeValue(spec.key, valuesInOrder[selectedIndex]),
905
+ invisibleItemLabels: valuesInOrder.slice(1).map((e) => getEnumRatingLabel(e, spec.instanceId))
906
+ }
907
+ ),
908
+ /* @__PURE__ */ jsx24("div", { style: { textAlign: "left", paddingLeft: "5px" }, children: /* @__PURE__ */ jsx24(
909
+ CSBox,
910
+ {
911
+ fieldSpec: elements.boxRatingName,
912
+ localiser: props.localiser,
913
+ variant: !props.disabled ? "div" : "small",
914
+ children: hoveredValue !== void 0 ? props.localiser.getEnumLabel(props.factory, hoveredValue) : void 0
915
+ }
916
+ ) })
917
+ ] });
918
+ }
919
+
920
+ // src/views/CSVNoItemsView.tsx
921
+ import { Box as Box2, SpaceBetween } from "@cloudscape-design/components";
922
+ import { jsx as jsx25, jsxs as jsxs3 } from "react/jsx-runtime";
923
+ var CSV_NO_ITEMS_VIEW_SPEC = (ns) => ViewSpec.create("CSVNoItemsView", ns, (spec) => ({
924
+ boxHeading: spec.addField(new FieldSpec("boxHeading")),
925
+ boxBody: spec.addField(new FieldSpec("boxBody"))
926
+ }));
927
+ function CSVNoItemsView(props) {
928
+ const spec = props.viewSpec;
929
+ const { elements } = spec;
930
+ return /* @__PURE__ */ jsx25("div", { "data-testid": spec.getDataTestId(), children: /* @__PURE__ */ jsx25(Box2, { textAlign: "center", color: "inherit", children: /* @__PURE__ */ jsxs3(SpaceBetween, { size: "xxs", direction: "vertical", children: [
931
+ /* @__PURE__ */ jsx25(
932
+ CSBox,
933
+ {
934
+ fieldSpec: elements.boxHeading,
935
+ localiser: props.localiser,
936
+ alternateNs: spec.ns,
937
+ variant: "strong",
938
+ color: "inherit",
939
+ children: props.headingText
940
+ }
941
+ ),
942
+ /* @__PURE__ */ jsx25(
943
+ CSBox,
944
+ {
945
+ fieldSpec: elements.boxBody,
946
+ localiser: props.localiser,
947
+ alternateNs: spec.ns,
948
+ localisationVariables: { itemType: props.localiser.getEnumLabel(props.factory, props.itemType) },
949
+ variant: "p",
950
+ color: "inherit",
951
+ children: props.bodyText
952
+ }
953
+ ),
954
+ props.bodyNode
955
+ ] }) }) });
956
+ }
957
+
958
+ // src/views/CSVPriceInputView.tsx
959
+ import { Grid } from "@cloudscape-design/components";
960
+
961
+ // src/utils/PriceUtils.ts
962
+ var LOGGER2 = new Log("PriceUtils");
963
+ var PriceUtils = class {
964
+ static getFormattedPrice = (locale, price) => {
965
+ if (isNaN(price.priceInCents)) {
966
+ return "-";
967
+ }
968
+ return new Intl.NumberFormat(locale, {
969
+ style: "currency",
970
+ currency: price.currency.toString()
971
+ }).format(price.priceInCents / 100);
972
+ };
973
+ static sumPrices = (prices, defaultCurrency) => {
974
+ if (prices.length === 0) {
975
+ return { priceInCents: 0, currency: defaultCurrency };
976
+ }
977
+ const currencySet = this.getCurrenciesFromPrices(prices);
978
+ if (currencySet.size > 1) {
979
+ LOGGER2.warn("Different currencies found in price array to be summed - the final price is incorrect!", currencySet);
980
+ }
981
+ const summedPrice = prices.map((pr) => pr.priceInCents).reduce((sum, current) => sum + current);
982
+ return { priceInCents: summedPrice, currency: prices[0].currency };
983
+ };
984
+ static getCurrenciesFromPrices = (prices) => {
985
+ const currencySet = /* @__PURE__ */ new Set();
986
+ prices.forEach((pr) => currencySet.add(pr.currency));
987
+ return currencySet;
988
+ };
989
+ static getPriceValidityLevel = (spec, value) => {
990
+ const centsValidity = spec.elements.inputPrice.getValueValidityLevel(value.priceInCents);
991
+ if (centsValidity !== "VALID" /* VALID */) {
992
+ return centsValidity;
993
+ }
994
+ return spec.elements.selectCurrency.getValueValidityLevel(value.currency);
995
+ };
996
+ static parseFormattedPrice = (locale, formattedPrice, currency) => {
997
+ const thousandSeparator = Intl.NumberFormat(locale).format(11111).replace(/\p{Number}/gu, "");
998
+ const decimalSeparator = Intl.NumberFormat(locale).format(1.1).replace(/\p{Number}/gu, "");
999
+ const sanitizedPrice = formattedPrice.replace(new RegExp("\\" + thousandSeparator, "g"), "").replace(new RegExp("\\" + decimalSeparator), ".").replace(new RegExp("[^0-9.]", "g"), "").trim();
1000
+ const parsedPriceCents = Math.round(100 * parseFloat(sanitizedPrice));
1001
+ return { priceInCents: parsedPriceCents, currency };
1002
+ };
1003
+ static parseFormattedPriceWithCurrency = (locale, formattedPrice, currencySymbolMapping) => {
1004
+ const thousandSeparator = Intl.NumberFormat(locale).format(11111).replace(/\p{Number}/gu, "");
1005
+ const decimalSeparator = Intl.NumberFormat(locale).format(1.1).replace(/\p{Number}/gu, "");
1006
+ const sanitizedPrice = formattedPrice.replace(new RegExp("\\" + thousandSeparator, "g"), "").replace(new RegExp("\\" + decimalSeparator), ".").replace(new RegExp("[^0-9.]", "g"), "").trim();
1007
+ const parsedPriceCents = Math.round(100 * parseFloat(sanitizedPrice));
1008
+ const supportedCurrencies = Object.keys(currencySymbolMapping);
1009
+ const currencySymbolsFound = supportedCurrencies.filter((symbol) => formattedPrice.includes(symbol));
1010
+ if (currencySymbolsFound.length > 1) {
1011
+ throw new Error(`Multiple currency symbols found in formatter price string ${formattedPrice}, here are the supported currencies: ${supportedCurrencies}`);
1012
+ }
1013
+ return {
1014
+ priceInCents: parsedPriceCents,
1015
+ currency: currencySymbolMapping[currencySymbolsFound[0]]
1016
+ };
1017
+ };
1018
+ };
1019
+
1020
+ // src/views/CSVPriceInputView.tsx
1021
+ import { jsx as jsx26, jsxs as jsxs4 } from "react/jsx-runtime";
1022
+ var CSV_PRICE_INPUT_VIEW_SPEC = (parent, key) => ViewSpec.create(key, parent.ns, (spec) => ({
1023
+ inputPrice: spec.addField(new FieldSpec("inputPrice", true, void 0, 0)),
1024
+ selectCurrency: spec.addField(new FieldSpec("currency", true)),
1025
+ boxPriceDisplay: spec.addField(new FieldSpec("boxPriceDisplay"))
1026
+ }), key, parent, PriceUtils.getPriceValidityLevel);
1027
+ function CSVPriceInputView(props) {
1028
+ const spec = props.viewSpec;
1029
+ const { elements } = spec;
1030
+ const priceInCents = props.value ? props.value.priceInCents : 0;
1031
+ const currency = props.value ? props.value.currency : props.defaultCurrency;
1032
+ return /* @__PURE__ */ jsxs4(
1033
+ Grid,
1034
+ {
1035
+ gridDefinition: [{ colspan: 4 }, { colspan: { default: 4, xxs: 3 } }, { colspan: { default: 4, xxs: 5 } }],
1036
+ disableGutters: true,
1037
+ children: [
1038
+ /* @__PURE__ */ jsx26(
1039
+ CSNumericInput,
1040
+ {
1041
+ fieldSpec: elements.inputPrice,
1042
+ value: priceInCents / 100,
1043
+ step: 0.01,
1044
+ disabled: props.disabled,
1045
+ localiser: props.localiser,
1046
+ onChangeValue: (propertyName, changedValue) => props.onChange(props.viewSpec.key, {
1047
+ priceInCents: parseFloat(changedValue) * 100,
1048
+ currency
1049
+ })
1050
+ }
1051
+ ),
1052
+ /* @__PURE__ */ jsx26("div", { style: { paddingLeft: "8px" }, children: /* @__PURE__ */ jsx26(
1053
+ CSEnumSelect,
1054
+ {
1055
+ fieldSpec: elements.selectCurrency,
1056
+ localiser: props.localiser,
1057
+ factory: props.currencyFactory,
1058
+ selectedEnum: currency,
1059
+ disabled: props.disabled,
1060
+ onChangeValue: (propertyName, changedValue) => props.onChange(props.viewSpec.key, {
1061
+ priceInCents,
1062
+ currency: changedValue
1063
+ }),
1064
+ expandToViewport: props.expandToViewport
1065
+ }
1066
+ ) }),
1067
+ /* @__PURE__ */ jsx26("div", { style: { paddingTop: "30px", paddingLeft: "8px" }, children: /* @__PURE__ */ jsx26(
1068
+ CSBox,
1069
+ {
1070
+ fieldSpec: elements.boxPriceDisplay,
1071
+ localiser: props.localiser,
1072
+ fontSize: "heading-s",
1073
+ fontWeight: "heavy",
1074
+ variant: "awsui-key-label",
1075
+ children: PriceUtils.getFormattedPrice(props.localiser.language(), { priceInCents, currency })
1076
+ }
1077
+ ) })
1078
+ ]
1079
+ }
1080
+ );
1081
+ }
1082
+
1083
+ // src/views/CSVSearchFilterView.tsx
1084
+ import { SpaceBetween as SpaceBetween2 } from "@cloudscape-design/components";
1085
+ import { jsx as jsx27, jsxs as jsxs5 } from "react/jsx-runtime";
1086
+ var CSV_SEARCH_FILTER_VIEW_SPEC = (parent, key) => ViewSpec.create(key, parent.ns, (spec) => ({
1087
+ inputSearch: spec.addField(new FieldSpec("inputSearch")),
1088
+ buttonSearch: spec.addField(new FieldSpec("buttonSearch"))
1089
+ }), void 0, parent);
1090
+ function CSVSearchFilterView(props) {
1091
+ const spec = props.viewSpec;
1092
+ const { elements } = spec;
1093
+ return /* @__PURE__ */ jsxs5(SpaceBetween2, { size: "s", direction: "horizontal", children: [
1094
+ /* @__PURE__ */ jsx27("div", { style: { minWidth: "320px" }, children: props.inputSearch === void 0 || typeof props.inputSearch === "string" ? /* @__PURE__ */ jsx27(
1095
+ CSInput,
1096
+ {
1097
+ fieldSpec: elements.inputSearch,
1098
+ localiser: props.localiser,
1099
+ autoFocus: true,
1100
+ placeholder: props.inputSearch,
1101
+ onChangeValue: props.onChangeValue,
1102
+ value: props.searchString,
1103
+ type: "search"
1104
+ }
1105
+ ) : props.inputSearch }),
1106
+ props.buttonSearch === void 0 || typeof props.buttonSearch === "string" ? /* @__PURE__ */ jsx27(
1107
+ CSButton,
1108
+ {
1109
+ fieldSpec: elements.buttonSearch,
1110
+ localiser: props.localiser,
1111
+ variant: "primary",
1112
+ iconName: "search",
1113
+ onClick: props.onConfirmSearch,
1114
+ formAction: "submit",
1115
+ loading: props.loading,
1116
+ disabled: props.searchDisabled,
1117
+ children: props.buttonSearch
1118
+ }
1119
+ ) : props.buttonSearch
1120
+ ] });
1121
+ }
1122
+
1123
+ // src/views/CSVTextPromptModalView.tsx
1124
+ import { Box as Box3, Modal, SpaceBetween as SpaceBetween3 } from "@cloudscape-design/components";
1125
+ import { Fragment, jsx as jsx28, jsxs as jsxs6 } from "react/jsx-runtime";
1126
+ var CSV_TEXT_PROMPT_MODAL_VIEW_SPEC = (parent, key) => ViewSpec.create(key, parent.ns, (spec) => ({
1127
+ headerHeading: spec.addField(new FieldSpec("headerHeading")),
1128
+ boxBodyText: spec.addField(new FieldSpec("boxBodyText")),
1129
+ buttonPrimary: spec.addField(new FieldSpec("buttonPrimary")),
1130
+ buttonSecondary: spec.addField(new FieldSpec("buttonSecondary"))
1131
+ }), void 0, parent);
1132
+ function CSVTextPromptModalView(props) {
1133
+ const spec = props.viewSpec;
1134
+ const { elements } = spec;
1135
+ const secondaryAction = props.onSecondaryAction ? props.buttonSecondary === void 0 || typeof props.buttonSecondary === "string" ? /* @__PURE__ */ jsx28(
1136
+ CSButton,
1137
+ {
1138
+ fieldSpec: elements.buttonSecondary,
1139
+ localiser: props.localiser,
1140
+ variant: "normal",
1141
+ onClick: props.onSecondaryAction,
1142
+ children: props.buttonSecondary
1143
+ }
1144
+ ) : props.buttonSecondary : /* @__PURE__ */ jsx28(Fragment, {});
1145
+ return /* @__PURE__ */ jsx28(
1146
+ Modal,
1147
+ {
1148
+ "data-testid": props.viewSpec.getDataTestId(),
1149
+ onDismiss: props.onDismiss,
1150
+ visible: props.visible,
1151
+ header: props.headerHeading === void 0 || typeof props.headerHeading === "string" ? /* @__PURE__ */ jsx28(
1152
+ CSHeader,
1153
+ {
1154
+ fieldSpec: elements.headerHeading,
1155
+ localiser: props.localiser,
1156
+ children: props.headerHeading
1157
+ }
1158
+ ) : props.headerHeading,
1159
+ footer: /* @__PURE__ */ jsx28(Box3, { float: "right", children: /* @__PURE__ */ jsxs6(SpaceBetween3, { direction: "horizontal", size: "l", children: [
1160
+ props.buttonPrimary === void 0 || typeof props.buttonPrimary === "string" ? /* @__PURE__ */ jsx28(
1161
+ CSButton,
1162
+ {
1163
+ fieldSpec: elements.buttonPrimary,
1164
+ localiser: props.localiser,
1165
+ variant: "primary",
1166
+ onClick: props.onPrimaryAction,
1167
+ children: props.buttonPrimary
1168
+ }
1169
+ ) : props.buttonPrimary,
1170
+ secondaryAction
1171
+ ] }) }),
1172
+ children: props.boxBodyText === void 0 || typeof props.boxBodyText === "string" ? /* @__PURE__ */ jsx28(CSBox, { fieldSpec: elements.boxBodyText, localiser: props.localiser, children: props.boxBodyText }) : props.boxBodyText
1173
+ }
1174
+ );
1175
+ }
1176
+
1177
+ // src/hooks/ControllerState.ts
1178
+ var ControllerState = /* @__PURE__ */ ((ControllerState2) => {
1179
+ ControllerState2[ControllerState2["UNMOUNTED"] = 0] = "UNMOUNTED";
1180
+ ControllerState2[ControllerState2["INITIALIZING"] = 1] = "INITIALIZING";
1181
+ ControllerState2[ControllerState2["NORMAL"] = 2] = "NORMAL";
1182
+ ControllerState2[ControllerState2["FATAL_ERROR"] = 3] = "FATAL_ERROR";
1183
+ return ControllerState2;
1184
+ })(ControllerState || {});
1185
+
1186
+ // src/utils/DateUtils.ts
1187
+ var DateUtils = class _DateUtils {
1188
+ static dateAsString(date) {
1189
+ const dd = String(date.getDate()).padStart(2, "0");
1190
+ const mm = String(date.getMonth() + 1).padStart(2, "0");
1191
+ const yyyy = date.getFullYear();
1192
+ return yyyy + "-" + mm + "-" + dd;
1193
+ }
1194
+ static dateAsDateTimeString(date, language) {
1195
+ return date.toLocaleDateString(language) + " " + date.toLocaleTimeString(language);
1196
+ }
1197
+ static nextSundayAt(hour, minute, second) {
1198
+ const today = /* @__PURE__ */ new Date();
1199
+ const addDays = 7 - today.getDay();
1200
+ const nextSunday = new Date(today.getTime() + addDays * 24 * 60 * 60 * 1e3);
1201
+ nextSunday.setHours(hour, minute, second, 0);
1202
+ return nextSunday;
1203
+ }
1204
+ static getCurrentUserTimezone() {
1205
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
1206
+ }
1207
+ static dateTimeAsUTCISO8601String(date) {
1208
+ const hh = String(date.getHours()).padStart(2, "0");
1209
+ const MM = String(date.getMinutes()).padStart(2, "0");
1210
+ const ss = String(date.getSeconds()).padStart(2, "0");
1211
+ return _DateUtils.dateAsString(date) + "T" + hh + ":" + MM + ":" + ss + "Z";
1212
+ }
1213
+ static currentDateTimeAsUTCISO8601String() {
1214
+ const now = /* @__PURE__ */ new Date();
1215
+ return _DateUtils.dateTimeAsUTCISO8601String(now);
1216
+ }
1217
+ static currentDateAsISO8601String() {
1218
+ const now = /* @__PURE__ */ new Date();
1219
+ return _DateUtils.dateAsString(now);
1220
+ }
1221
+ static toFormattedLocalizedDate(locale, inputInUTCISO8601, timezone) {
1222
+ if (inputInUTCISO8601 === void 0 || inputInUTCISO8601 === null) {
1223
+ return "";
1224
+ }
1225
+ return new Intl.DateTimeFormat(locale, {
1226
+ year: "numeric",
1227
+ month: "2-digit",
1228
+ day: "2-digit",
1229
+ hour: "2-digit",
1230
+ minute: "2-digit",
1231
+ second: "2-digit",
1232
+ hour12: false,
1233
+ timeZone: timezone
1234
+ }).format(new Date(inputInUTCISO8601));
1235
+ }
1236
+ };
1237
+
1238
+ // src/types/FieldProperties.ts
1239
+ var FieldProperties = class {
1240
+ constructor(key, required, maxLength, minValue, maxValue) {
1241
+ this.key = key;
1242
+ this.required = required;
1243
+ this.maxLength = maxLength;
1244
+ this.minValue = minValue;
1245
+ this.maxValue = maxValue;
1246
+ }
1247
+ };
1248
+
1249
+ // src/utils/FixedWidth.tsx
1250
+ import { jsx as jsx29 } from "react/jsx-runtime";
1251
+ function FixedWidth(props) {
1252
+ return /* @__PURE__ */ jsx29("div", { style: { minWidth: props.minWidth, maxWidth: props.maxWidth }, children: props.children });
1253
+ }
1254
+
1255
+ // src/utils/LocalStorageService.ts
1256
+ var ITEM_SEP = ",";
1257
+ var LocalStorageService = class {
1258
+ static getItemStringArrayWithDefault(key, defaultValue) {
1259
+ const result = this.safeGetItem(key);
1260
+ if (result === null) {
1261
+ return defaultValue;
1262
+ }
1263
+ return result.split(ITEM_SEP);
1264
+ }
1265
+ static getItemEnumArrayWithDefault(enumClass, key, defaultValue) {
1266
+ const enumConstantsAsStrings = this.getItemStringArrayWithDefault(key, defaultValue.map((s) => s.toString()));
1267
+ const keys = Object.keys(enumClass);
1268
+ const values = Object.values(enumClass);
1269
+ const dict = {};
1270
+ for (let index = 0; index < keys.length; index++) {
1271
+ dict[values[index]] = keys[index];
1272
+ }
1273
+ return enumConstantsAsStrings.map((val) => dict[val]);
1274
+ }
1275
+ static setItemEnumArray(key, value) {
1276
+ this.setItemStringArray(key, value.map((e) => e.toString()));
1277
+ }
1278
+ static setItemStringArray(key, value) {
1279
+ this.safeSetItem(key, value.join(","));
1280
+ }
1281
+ static getItemWithDefault(key, defaultValue) {
1282
+ const result = this.safeGetItem(key);
1283
+ if (result === null) {
1284
+ return defaultValue;
1285
+ }
1286
+ return result;
1287
+ }
1288
+ static setItem(key, value) {
1289
+ return this.safeSetItem(key, value);
1290
+ }
1291
+ static clear() {
1292
+ window.localStorage.clear();
1293
+ }
1294
+ static setObject(key, value) {
1295
+ return this.safeSetItem(key, JSON.stringify(value));
1296
+ }
1297
+ static getObjectWithDefault(key, defaultValue) {
1298
+ const result = this.safeGetItem(key);
1299
+ if (result === null) {
1300
+ return defaultValue;
1301
+ }
1302
+ return JSON.parse(result);
1303
+ }
1304
+ static safeGetItem(key) {
1305
+ try {
1306
+ return localStorage.getItem(key);
1307
+ } catch (error) {
1308
+ console.log(`WARNING: could not get item with key ${key} from local storage due to exception: ${error}`);
1309
+ return null;
1310
+ }
1311
+ }
1312
+ static safeSetItem(key, value) {
1313
+ try {
1314
+ return localStorage.setItem(key, value);
1315
+ } catch (error) {
1316
+ console.log(`WARNING: could not set item with key ${key} and value ${value} in local storage due to exception: ${error}`);
1317
+ return null;
1318
+ }
1319
+ }
1320
+ };
1321
+
1322
+ // src/localisation/LocalisationNamespace.ts
1323
+ var LocalisationNamespace = class {
1324
+ constructor(name) {
1325
+ this.name = name;
1326
+ }
1327
+ /**
1328
+ *
1329
+ * @param parts The parts. Call this with comma-separated args, e.g. createKey(arg1, arg2, arg3) or with array using following syntax:
1330
+ * createKey(...[arg1, arg2, arg3]). DO NOT call it directly with an array!
1331
+ * This is WRONG: createKey([arg1, arg2, arg3]). It will treat the array as single arg and call toString() on it.
1332
+ */
1333
+ createKey(...parts) {
1334
+ return this.name + "." + parts.join(".");
1335
+ }
1336
+ };
1337
+ var NSK_CONTENT = "content";
1338
+
1339
+ // src/localisation/Localiser.ts
1340
+ var Localiser = class {
1341
+ constructor(translate, ns) {
1342
+ this.translate = translate;
1343
+ this.ns = ns;
1344
+ }
1345
+ getEnumLabel(factory, instance) {
1346
+ return this.getEnumLocalisation(factory, instance).label;
1347
+ }
1348
+ getAllEnumLabels(factory) {
1349
+ return factory.values.map((instance) => this.getEnumLabel(factory, instance));
1350
+ }
1351
+ };
1352
+
1353
+ // src/types/messaging/MessageSeverity.ts
1354
+ var MessageSeverity = /* @__PURE__ */ ((MessageSeverity2) => {
1355
+ MessageSeverity2["INFO"] = "INFO";
1356
+ MessageSeverity2["WARN"] = "WARN";
1357
+ MessageSeverity2["ERR"] = "ERR";
1358
+ MessageSeverity2["SUCCESS"] = "SUCCESS";
1359
+ return MessageSeverity2;
1360
+ })(MessageSeverity || {});
1361
+ var MESSAGE_SEVERITY_FACTORY = new EnumFactory("MessageSeverity", Object.values(MessageSeverity));
1362
+
1363
+ // src/types/messaging/MessageCTO.ts
1364
+ var MessageCTO = class {
1365
+ static TIMESTAMP_PROPS = new FieldProperties("timestamp", true);
1366
+ static DETAIL_MESSAGE_PROPS = new FieldProperties("detailMessage", true);
1367
+ static CORRELATION_ID_PROPS = new FieldProperties("correlationId", true);
1368
+ static OPERATION_PROPS = new FieldProperties("operation", true);
1369
+ code;
1370
+ timestamp;
1371
+ detailMessage;
1372
+ correlationId;
1373
+ operation;
1374
+ };
1375
+
1376
+ // src/types/messaging/MessageCodeTO.ts
1377
+ var MessageCodeTO = class {
1378
+ static CONTROLLER_ID_PROPS = new FieldProperties("componentId", true);
1379
+ static HTTP_STATUS_CODE_PROPS = new FieldProperties("httpStatusCode", true);
1380
+ static LOCAL_CODE_PROPS = new FieldProperties("localCode", true);
1381
+ static MESSAGE_SEVERITY_PROPS = new FieldProperties("messageSeverity", true);
1382
+ static UNIQUE_CODE_PROPS = new FieldProperties("uniqueCode", true);
1383
+ componentId;
1384
+ httpStatusCode;
1385
+ localCode;
1386
+ messageSeverity;
1387
+ uniqueCode;
1388
+ };
1389
+
1390
+ // src/types/messaging/MessageService.ts
1391
+ var TECHNICAL_CONTROLLER_ID = "T";
1392
+ var NO_HTTP_CODE = 0;
1393
+ var MessageService = class _MessageService {
1394
+ static getResponseTOWithMessagesFromUnknownResponse(json, op, status) {
1395
+ const response = json !== void 0 && json !== null && json.hasOwnProperty("messages") ? json : _MessageService.createGenericErrorMessageTO(status, op);
1396
+ response.messages.forEach((m) => m.operation = op);
1397
+ return response;
1398
+ }
1399
+ static getSuccessContentWithMessagesCTO(json, op) {
1400
+ let result = { content: void 0, messages: [] };
1401
+ if (json.hasOwnProperty("content")) {
1402
+ result.content = json.content;
1403
+ }
1404
+ if (json.hasOwnProperty("messages")) {
1405
+ result.messages = json.messages;
1406
+ }
1407
+ result.messages.forEach((m) => m.operation = op);
1408
+ return result;
1409
+ }
1410
+ static createContentWithSuccessMessage = (operation, message) => {
1411
+ return this.createContentWithMessage(this.createMessageTO(
1412
+ TECHNICAL_CONTROLLER_ID,
1413
+ NO_HTTP_CODE.toString(),
1414
+ 0,
1415
+ message,
1416
+ operation,
1417
+ "SUCCESS" /* SUCCESS */
1418
+ ));
1419
+ };
1420
+ static createContentWithoutMessages = (content) => {
1421
+ return {
1422
+ messages: [],
1423
+ content
1424
+ };
1425
+ };
1426
+ static createContentWithInfoMessage = (operation, message) => {
1427
+ return this.createContentWithMessage(this.createMessageTO(
1428
+ TECHNICAL_CONTROLLER_ID,
1429
+ NO_HTTP_CODE.toString(),
1430
+ 0,
1431
+ message,
1432
+ operation,
1433
+ "INFO" /* INFO */
1434
+ ));
1435
+ };
1436
+ static createGenericErrorMessageTO = (httpStatusCode, operation) => {
1437
+ if (this.isAPIClientCallError(httpStatusCode)) {
1438
+ return this.createContentWithMessage(this.createMessageTO(TECHNICAL_CONTROLLER_ID, "998", httpStatusCode, "Generic API call client error", operation));
1439
+ } else if (this.isBackendError(httpStatusCode)) {
1440
+ return this.createContentWithMessage(this.createMessageTO(TECHNICAL_CONTROLLER_ID, "999", httpStatusCode, "Generic backend error", operation));
1441
+ } else {
1442
+ throw new Error("Calling this methods with any http status code outside 400-599 is not allowed.");
1443
+ }
1444
+ };
1445
+ static createCriticalErrorFrontendProcessingMessageTO = (operation, message) => {
1446
+ return this.createMessageTO(TECHNICAL_CONTROLLER_ID, "997", -1, message, operation);
1447
+ };
1448
+ static isAPIClientCallError = (httpStatusCode) => {
1449
+ return httpStatusCode >= 400 && httpStatusCode <= 499;
1450
+ };
1451
+ static isBackendError = (httpStatusCode) => {
1452
+ return httpStatusCode >= 500 && httpStatusCode <= 599;
1453
+ };
1454
+ static createContentWithMessage(message) {
1455
+ return {
1456
+ messages: [message],
1457
+ content: void 0
1458
+ };
1459
+ }
1460
+ static createMessageTO = (componentId, localCode, httpStatusCode, detailMessage, operation, severity) => {
1461
+ const message = new MessageCTO();
1462
+ message.code = new MessageCodeTO();
1463
+ message.code.httpStatusCode = httpStatusCode;
1464
+ message.code.componentId = componentId;
1465
+ message.code.localCode = localCode;
1466
+ message.code.uniqueCode = componentId + localCode;
1467
+ message.code.messageSeverity = severity ? severity : "ERR" /* ERR */;
1468
+ message.operation = operation;
1469
+ message.correlationId = "N/A";
1470
+ message.timestamp = DateUtils.currentDateTimeAsUTCISO8601String();
1471
+ message.detailMessage = detailMessage;
1472
+ return message;
1473
+ };
1474
+ };
1475
+
1476
+ // src/utils/QueryParamHelper.ts
1477
+ var QUERY_START = "?";
1478
+ var QUERY_SEP = "&";
1479
+ var QueryParamHelper = class {
1480
+ static appendQueryParam(query, key, value) {
1481
+ let result = query;
1482
+ if (!query.includes(QUERY_START)) {
1483
+ result = result + QUERY_START;
1484
+ }
1485
+ if (result[result.length - 1] !== QUERY_START) {
1486
+ result = result + QUERY_SEP;
1487
+ }
1488
+ return result + encodeURIComponent(key) + "=" + encodeURIComponent(value);
1489
+ }
1490
+ static getQueryParams(queryString) {
1491
+ const returnedParams = {};
1492
+ if (queryString === void 0 || queryString.length === 0 || !queryString.startsWith(QUERY_START)) {
1493
+ return returnedParams;
1494
+ }
1495
+ queryString = queryString.substring(1);
1496
+ const params = queryString.split(QUERY_SEP);
1497
+ if (params.length === 0 || params.length === 1 && params[0] === "") {
1498
+ return returnedParams;
1499
+ }
1500
+ params.forEach((param) => {
1501
+ const paramRegex = /^(?<key>.*?)=(?<value>.*?)$/;
1502
+ const matchArray = param.match(paramRegex);
1503
+ if (matchArray !== null && matchArray.groups) {
1504
+ const key = decodeURIComponent(matchArray.groups["key"]);
1505
+ returnedParams[key] = decodeURIComponent(matchArray.groups["value"]);
1506
+ }
1507
+ });
1508
+ return returnedParams;
1509
+ }
1510
+ };
1511
+
1512
+ // src/utils/RestClient.ts
1513
+ var REST_CLIENT_LOGGER = new Log("RestClient");
1514
+ function logStart(logMsg, url) {
1515
+ REST_CLIENT_LOGGER.debug("START " + logMsg + " using URL <" + url + "> ...");
1516
+ }
1517
+ function logDone(logMsg, url) {
1518
+ REST_CLIENT_LOGGER.debug("DONE " + logMsg + " using URL <" + url + "> .");
1519
+ }
1520
+ function logError(logMsg, url) {
1521
+ REST_CLIENT_LOGGER.debug("ERROR: ", logMsg, ", using URL <" + url + "> .");
1522
+ }
1523
+ function createRestClient() {
1524
+ return new RestClient("");
1525
+ }
1526
+ var RestClient = class {
1527
+ // Base URL. May be empty.
1528
+ baseUrl = "";
1529
+ prepareFetchConfig(method, payload, header = {}) {
1530
+ let headers = {
1531
+ Accept: "application/json",
1532
+ "Content-Type": "application/json",
1533
+ ...header
1534
+ };
1535
+ let config;
1536
+ if (payload) {
1537
+ config = {
1538
+ method,
1539
+ headers,
1540
+ body: JSON.stringify(payload)
1541
+ };
1542
+ } else {
1543
+ config = {
1544
+ method,
1545
+ headers
1546
+ };
1547
+ }
1548
+ return config;
1549
+ }
1550
+ /**
1551
+ * Creates a new REST client.
1552
+ * @param baseUrl base URL, so client can be called with relative URLs.
1553
+ */
1554
+ constructor(baseUrl) {
1555
+ if (baseUrl != null) {
1556
+ this.baseUrl = baseUrl;
1557
+ }
1558
+ }
1559
+ /**
1560
+ * Make a GET request on the specified endpoint
1561
+ *
1562
+ * @param {string} endpoint the endpoint relative to the baseUrl with a preceeding slash. e.g. '/users'.
1563
+ * @param {string} operation the operation name for logging.
1564
+ * @param {string} headers the HTTP headers to pass.
1565
+ */
1566
+ get(endpoint, operation, headers) {
1567
+ return this.callApi("get", endpoint, null, operation, headers);
1568
+ }
1569
+ /**
1570
+ * Make a PUT request on the specified endpoint
1571
+ *
1572
+ * @param {string} endpoint the endpoint relative to the baseUrl with a preceeding slash. e.g. '/users'.
1573
+ * @param {object} payload the request payload as object.
1574
+ * @param {string} operation the operation name for logging.
1575
+ */
1576
+ put(endpoint, payload, operation) {
1577
+ return this.callApi("put", endpoint, payload, operation);
1578
+ }
1579
+ /**
1580
+ * Make a POST request on the specified endpoint
1581
+ *
1582
+ * @param {string} endpoint the endpoint relative to the baseUrl with a preceeding slash. e.g. '/users'.
1583
+ * @param {object} payload the request payload as object.
1584
+ * @param {string} operation the operation name for logging.
1585
+ */
1586
+ post(endpoint, payload, operation) {
1587
+ return this.callApi("post", endpoint, payload, operation);
1588
+ }
1589
+ /**
1590
+ * Make a DELETE request on the specified endpoint
1591
+ *
1592
+ * @param {string} endpoint the endpoint relative to the baseUrl with a preceeding slash. e.g. '/users'.
1593
+ * @param {object} payload the request payload as object.
1594
+ * @param {string} operation the operation name for logging.
1595
+ */
1596
+ del(endpoint, payload, operation) {
1597
+ return this.callApi("delete", endpoint, payload, operation);
1598
+ }
1599
+ callApi(method, endpoint = "", payload = null, operation, header) {
1600
+ const url = `${this.baseUrl}${endpoint}`;
1601
+ const config = this.prepareFetchConfig(method, payload, header);
1602
+ const op = operation ? operation : "Unknown operation";
1603
+ logStart(op, url);
1604
+ REST_CLIENT_LOGGER.debug("Calling API - " + method + "," + url);
1605
+ REST_CLIENT_LOGGER.object("Payload", payload);
1606
+ return new Promise((resolve, reject) => {
1607
+ fetch(url, config).then((response) => {
1608
+ const contentType = response.headers.get("content-type");
1609
+ if (contentType && contentType.indexOf("application/json") !== -1) {
1610
+ return response.json().then((json) => ({
1611
+ status: response.status,
1612
+ json
1613
+ }));
1614
+ } else {
1615
+ return response.text().then((text) => ({
1616
+ status: response.status,
1617
+ json: {}
1618
+ }));
1619
+ }
1620
+ }).then((result) => {
1621
+ const { status, json } = result;
1622
+ if (status >= 400) {
1623
+ logError(op, url);
1624
+ REST_CLIENT_LOGGER.error("Api call failed with response code " + status + ", response body=" + Log.toReadableObjectString(json));
1625
+ const responseWithMessages = MessageService.getResponseTOWithMessagesFromUnknownResponse(json, op, status);
1626
+ return reject(responseWithMessages);
1627
+ } else {
1628
+ logDone(op, url);
1629
+ REST_CLIENT_LOGGER.debug("Api call successful " + status + ", response body=" + Log.toReadableObjectString(json));
1630
+ if (json === null || json === void 0) {
1631
+ const msg = "Invalid response body - must never be null or undefined";
1632
+ REST_CLIENT_LOGGER.error(msg);
1633
+ const responseWithMessages2 = {
1634
+ content: void 0,
1635
+ messages: [MessageService.createCriticalErrorFrontendProcessingMessageTO(op, msg)]
1636
+ };
1637
+ return reject(responseWithMessages2);
1638
+ }
1639
+ const responseWithMessages = MessageService.getSuccessContentWithMessagesCTO(json, op);
1640
+ return resolve(responseWithMessages);
1641
+ }
1642
+ }).catch((error) => {
1643
+ const msg = "Api call failed with unknown/network error during promise processing " + error;
1644
+ REST_CLIENT_LOGGER.error(msg);
1645
+ const responseWithMessages = {
1646
+ content: void 0,
1647
+ messages: [MessageService.createCriticalErrorFrontendProcessingMessageTO(op, msg)]
1648
+ };
1649
+ return reject(responseWithMessages);
1650
+ });
1651
+ });
1652
+ }
1653
+ };
1654
+
1655
+ // src/hooks/useControllerDisplayState.ts
1656
+ import { useCallback, useState as useState2 } from "react";
1657
+ var RunFunctionResult = class {
1658
+ constructor(success, messages, result, resultHistory) {
1659
+ this.success = success;
1660
+ this.messages = messages;
1661
+ this.result = result;
1662
+ this.resultHistory = resultHistory;
1663
+ }
1664
+ };
1665
+ var fatalRunErrorFunction = (reason) => {
1666
+ throw new Error(`Fatal error - could not handle run failure - reason: ${reason}`);
1667
+ };
1668
+ function useControllerDisplayState(initialDisplayMode, messages, logger) {
1669
+ const [state, setState] = useState2(0 /* UNMOUNTED */);
1670
+ const [loadingIndication, setLoadingIndication] = useState2({});
1671
+ const [modified, setModified] = useState2(false);
1672
+ const [displayMode, setDisplayMode] = useState2(initialDisplayMode);
1673
+ const [modalState, setModalState] = useState2({
1674
+ show: (modalId, confirmFunction) => showModal(modalId, true, confirmFunction),
1675
+ hide: (modalId) => showModal(modalId, false)
1676
+ });
1677
+ const { addMessages } = messages;
1678
+ const isLoading = useCallback((service) => {
1679
+ return loadingIndication.hasOwnProperty(service.name) && loadingIndication[service.name] === true;
1680
+ }, [loadingIndication]);
1681
+ const load = useCallback((service) => {
1682
+ setLoadingIndication((oldIndication) => ({ ...oldIndication, [service.name]: true }));
1683
+ }, []);
1684
+ const doneLoading = useCallback((service) => {
1685
+ setLoadingIndication((oldIndication) => {
1686
+ return { ...oldIndication, [service.name]: false };
1687
+ });
1688
+ }, []);
1689
+ const enterDisplayMode = useCallback((mode) => {
1690
+ setDisplayMode((previousMode) => {
1691
+ if (mode !== displayMode) {
1692
+ logger.info("Entering display mode: ", mode);
1693
+ return mode;
1694
+ }
1695
+ return previousMode;
1696
+ });
1697
+ }, [displayMode, logger]);
1698
+ const showModal = useCallback((modalId, show, confirmFunction) => {
1699
+ if (show) {
1700
+ setModalState((originalModalState) => {
1701
+ if (originalModalState.modalId !== void 0) {
1702
+ throw Error("Cannot show multiple modals at the same time");
1703
+ }
1704
+ return { ...originalModalState, modalId, confirmFunction };
1705
+ });
1706
+ } else {
1707
+ setModalState((originalModalState) => {
1708
+ if (originalModalState.modalId === void 0 || originalModalState.modalId !== modalId) {
1709
+ throw Error("Cannot hide modal that isn't currently shown");
1710
+ }
1711
+ return { ...originalModalState, modalId: void 0, confirmFunction: void 0 };
1712
+ });
1713
+ }
1714
+ }, []);
1715
+ const run = useCallback(function(service, execute, failureIsFatal, resultHistory) {
1716
+ load(service);
1717
+ return execute().then((result) => {
1718
+ addMessages(result);
1719
+ return Promise.resolve(new RunFunctionResult(
1720
+ true,
1721
+ result.messages,
1722
+ result.content,
1723
+ resultHistory
1724
+ ));
1725
+ }).catch((error) => {
1726
+ if (failureIsFatal) {
1727
+ setState(3 /* FATAL_ERROR */);
1728
+ }
1729
+ addMessages(error);
1730
+ return Promise.resolve(new RunFunctionResult(false, error.messages, void 0, resultHistory));
1731
+ }).finally(() => doneLoading(service));
1732
+ }, [addMessages, doneLoading, load]);
1733
+ return {
1734
+ state,
1735
+ setState,
1736
+ setDirty: useCallback(setModified, [setModified]),
1737
+ isDirty: () => modified,
1738
+ isLoading,
1739
+ displayMode,
1740
+ enterDisplayMode,
1741
+ modalState,
1742
+ run
1743
+ };
1744
+ }
1745
+
1746
+ // src/utils/MiscUtils.ts
1747
+ var indexRangeArray = (length) => {
1748
+ return Array.from({ length }, (x, i) => i);
1749
+ };
1750
+ function filterArrayByIndices(items, indices) {
1751
+ return items.filter((value, index) => indices.includes(index));
1752
+ }
1753
+ function sortArrayByIndices(items, indices) {
1754
+ return items.filter((value, index) => indices.includes(index)).sort((left, right) => indices.indexOf(items.indexOf(left)) - indices.indexOf(items.indexOf(right)));
1755
+ }
1756
+ var sleep = (delaySeconds) => new Promise((resolve) => setTimeout(resolve, delaySeconds));
1757
+
1758
+ // src/types/messaging/ContentWithMessagesCTO.ts
1759
+ function isContentWithMessages(object) {
1760
+ return object.hasOwnProperty("messages");
1761
+ }
1762
+
1763
+ // src/hooks/useTOChangeHandler.ts
1764
+ import { useCallback as useCallback2 } from "react";
1765
+ var ArrayStateHandler = class {
1766
+ static updateFieldsOfArrayElement(elementToUpdate, currentArrayContent, properties, onChangedArrayElement) {
1767
+ const newArrayValue = [...currentArrayContent];
1768
+ const affectedElementIndex = newArrayValue.indexOf(elementToUpdate);
1769
+ newArrayValue[affectedElementIndex] = { ...elementToUpdate, ...properties };
1770
+ if (onChangedArrayElement) {
1771
+ onChangedArrayElement([newArrayValue[affectedElementIndex]], newArrayValue);
1772
+ }
1773
+ return newArrayValue;
1774
+ }
1775
+ static removeArrayElements(elementsToRemove, currentArrayContent, onRemovedArrayElement) {
1776
+ const newArrayValue = [...currentArrayContent.filter((element) => elementsToRemove.indexOf(element) === -1)];
1777
+ if (onRemovedArrayElement) {
1778
+ onRemovedArrayElement(elementsToRemove, newArrayValue);
1779
+ }
1780
+ return newArrayValue;
1781
+ }
1782
+ static addArrayElements(elementsToAdd, currentArrayContent, onAddedArrayElements) {
1783
+ const newArrayValue = [...currentArrayContent, ...elementsToAdd];
1784
+ if (onAddedArrayElements) {
1785
+ onAddedArrayElements(elementsToAdd, newArrayValue);
1786
+ }
1787
+ return newArrayValue;
1788
+ }
1789
+ };
1790
+ function useTOChangeHandler(logger, toName, setTOState, notifications, setDirty) {
1791
+ const onPropertyChangeMulti = useCallback2((properties, automaticChange) => {
1792
+ logger.debug(`Changing state of the ${toName} Elements ${Object.keys(properties)} for affected element, using change object:`, JSON.stringify(properties));
1793
+ setTOState((previousValue) => {
1794
+ const newValue = { ...previousValue, ...properties };
1795
+ if (notifications && notifications.onChange) {
1796
+ for (const propertyName of Object.keys(properties)) {
1797
+ const changedValue = properties[propertyName];
1798
+ notifications.onChange(newValue, propertyName, changedValue);
1799
+ }
1800
+ }
1801
+ if (previousValue !== void 0 && setDirty !== void 0 && !automaticChange) {
1802
+ setDirty(true);
1803
+ }
1804
+ return newValue;
1805
+ });
1806
+ }, [logger, notifications, setDirty, setTOState, toName]);
1807
+ const onPropertyChange = useCallback2((propertyName, changedValue, automaticChange) => {
1808
+ onPropertyChangeMulti({ [propertyName]: changedValue }, automaticChange);
1809
+ }, [onPropertyChangeMulti]);
1810
+ return { onPropertyChange, onPropertyChangeMulti };
1811
+ }
1812
+ var singleChangeHandlerToMulti = (onPropertyChangeMulti) => {
1813
+ return (propertyName, changedValue) => onPropertyChangeMulti({ [propertyName]: changedValue });
1814
+ };
1815
+ function useTOArrayChangeHandler(logger, toName, setArrayState, handlers, setDirty) {
1816
+ const onChangeElement = useCallback2((element, properties) => {
1817
+ if (element !== void 0) {
1818
+ logger.debug(`Changing state of the ${toName} Elements ${Object.keys(properties)} for affected element, using change object:`, JSON.stringify(properties));
1819
+ setArrayState((previousValue) => ArrayStateHandler.updateFieldsOfArrayElement(
1820
+ element,
1821
+ previousValue,
1822
+ properties,
1823
+ handlers.onChange
1824
+ ));
1825
+ if (setDirty !== void 0) {
1826
+ setDirty(true);
1827
+ }
1828
+ }
1829
+ }, [logger, toName, setArrayState, setDirty, handlers.onChange]);
1830
+ const onRemoveElements = useCallback2((removedElements) => {
1831
+ if (removedElements.length > 0) {
1832
+ logger.debug(`Removing ${removedElements.length} elements from array`);
1833
+ setArrayState((previousValue) => ArrayStateHandler.removeArrayElements(
1834
+ removedElements,
1835
+ previousValue,
1836
+ handlers.onRemove
1837
+ ));
1838
+ if (setDirty !== void 0) {
1839
+ setDirty(true);
1840
+ }
1841
+ }
1842
+ }, [logger, setArrayState, setDirty, handlers.onRemove]);
1843
+ const onAddElements = useCallback2((newElements) => {
1844
+ if (newElements.length === 0) {
1845
+ logger.debug(`Adding no new elements to array`);
1846
+ } else {
1847
+ logger.debug(`Adding ${newElements.length} elements to array`);
1848
+ setArrayState((previousValue) => ArrayStateHandler.addArrayElements(
1849
+ newElements,
1850
+ previousValue,
1851
+ handlers.onAdd
1852
+ ));
1853
+ if (setDirty !== void 0) {
1854
+ setDirty(true);
1855
+ }
1856
+ }
1857
+ }, [logger, setArrayState, setDirty, handlers.onAdd]);
1858
+ return { onChangeElement, onRemoveElements, onAddElements };
1859
+ }
1860
+
1861
+ // src/hooks/useAWSUIRef.ts
1862
+ import { useCallback as useCallback3, useRef } from "react";
1863
+ function useAWSUIRef() {
1864
+ const customRef = useRef(null);
1865
+ const isValidRef = () => {
1866
+ return customRef !== void 0 && customRef !== null && customRef.current !== void 0 && customRef.current !== null;
1867
+ };
1868
+ const focus = useCallback3(() => {
1869
+ if (isValidRef() && customRef.current.focus) {
1870
+ customRef.current.focus();
1871
+ }
1872
+ }, [customRef]);
1873
+ const scrollToView = useCallback3(() => {
1874
+ if (isValidRef() && customRef.current.scrollIntoView) {
1875
+ customRef.current.scrollIntoView(true);
1876
+ }
1877
+ }, [customRef]);
1878
+ const scrollToViewRef = useCallback3((element) => {
1879
+ if (element !== void 0 && element !== null && element.scrollIntoView) {
1880
+ element.scrollIntoView({ block: "nearest", behavior: "smooth" });
1881
+ }
1882
+ }, []);
1883
+ return {
1884
+ customRef,
1885
+ focus,
1886
+ scrollToView,
1887
+ scrollToViewRef
1888
+ };
1889
+ }
1890
+
1891
+ // src/hooks/useHotkeys.ts
1892
+ import { useCallback as useCallback4, useEffect as useEffect2, useLayoutEffect, useRef as useRef2 } from "react";
1893
+ var useHotkey = (key, shift, ctrl, alt, callback, node = null) => {
1894
+ const callbackRef = useRef2(callback);
1895
+ useLayoutEffect(() => {
1896
+ callbackRef.current = callback;
1897
+ });
1898
+ const handleKeyPress = useCallback4(
1899
+ (event) => {
1900
+ if (event.key === key && (!shift || event.shiftKey) && (!ctrl || event.ctrlKey) && (!alt || event.altKey)) {
1901
+ callbackRef.current(event);
1902
+ }
1903
+ },
1904
+ [alt, ctrl, key, shift]
1905
+ );
1906
+ useEffect2(() => {
1907
+ const targetNode = node ?? document;
1908
+ targetNode && targetNode.addEventListener("keydown", handleKeyPress);
1909
+ return () => targetNode && targetNode.removeEventListener("keydown", handleKeyPress);
1910
+ }, [handleKeyPress, node]);
1911
+ };
1912
+
1913
+ // src/hooks/useMessages.ts
1914
+ import { useCallback as useCallback5, useState as useState3 } from "react";
1915
+ function useMessages(LOGGER3) {
1916
+ const [messages, setMessages] = useState3([]);
1917
+ const onDismissMessage = useCallback5((message) => {
1918
+ const newMessages = messages.filter((existingMsg) => message !== existingMsg);
1919
+ setMessages(newMessages);
1920
+ }, [messages]);
1921
+ const onToggleMessageDetail = useCallback5((message) => {
1922
+ const idx = messages.indexOf(message);
1923
+ const newMessages = [...messages];
1924
+ newMessages[idx].showDetails = !newMessages[idx].showDetails;
1925
+ setMessages(newMessages);
1926
+ }, [messages]);
1927
+ const addMessages = useCallback5((newMessages) => {
1928
+ if (!newMessages.hasOwnProperty("messages")) {
1929
+ LOGGER3.error("Given response data structure does not contain messages - probably another runtime error occurred: ", newMessages);
1930
+ if (newMessages.hasOwnProperty("stack")) {
1931
+ LOGGER3.error("Stack trace: ", newMessages.stack);
1932
+ }
1933
+ } else {
1934
+ const addedMessages = newMessages.messages.map((msg) => {
1935
+ return { ...msg, showDetails: false };
1936
+ });
1937
+ addedMessages.forEach((msg) => LOGGER3.info(`New message = <${msg.detailMessage}`));
1938
+ setMessages((oldMessages) => [...oldMessages, ...addedMessages]);
1939
+ }
1940
+ }, [LOGGER3]);
1941
+ const clearMessages = useCallback5(() => {
1942
+ setMessages([]);
1943
+ }, []);
1944
+ return {
1945
+ messages,
1946
+ addMessages,
1947
+ onDismissMessage,
1948
+ onToggleMessageDetail,
1949
+ clearMessages
1950
+ };
1951
+ }
1952
+ export {
1953
+ CSAlert,
1954
+ CSBox,
1955
+ CSButton,
1956
+ CSCheckbox,
1957
+ CSDatePicker,
1958
+ CSEnumMultiselect,
1959
+ CSEnumSegmentedControl,
1960
+ CSEnumSelect,
1961
+ CSEnumTiles,
1962
+ CSExternalLink,
1963
+ CSFormField,
1964
+ CSHeader,
1965
+ CSInput,
1966
+ CSLink,
1967
+ CSMultiselect,
1968
+ CSNumericInput,
1969
+ CSSegmentedControl,
1970
+ CSSelect,
1971
+ CSStatusIndicator,
1972
+ CSTextContent,
1973
+ CSTextarea,
1974
+ CSTimeInput,
1975
+ CSToggle,
1976
+ CSVEnumRatingView,
1977
+ CSVNoItemsView,
1978
+ CSVPriceInputView,
1979
+ CSVSearchFilterView,
1980
+ CSVTextPromptModalView,
1981
+ CSV_ENUM_RATING_VIEW_SPEC,
1982
+ CSV_NO_ITEMS_VIEW_SPEC,
1983
+ CSV_PRICE_INPUT_VIEW_SPEC,
1984
+ CSV_SEARCH_FILTER_VIEW_SPEC,
1985
+ CSV_TEXT_PROMPT_MODAL_VIEW_SPEC,
1986
+ ChildUtils,
1987
+ ControllerState,
1988
+ DateUtils,
1989
+ ELEMENT_VALIDITY_LEVEL_FACTORY,
1990
+ ElementValidityLevel,
1991
+ EnumFactory,
1992
+ FORM_FIELD_ID_SUFFIX,
1993
+ FieldProperties,
1994
+ FieldSpec,
1995
+ FixedWidth,
1996
+ FromPropsHelper,
1997
+ LocalStorageService,
1998
+ LocalisationNamespace,
1999
+ Localiser,
2000
+ Log,
2001
+ MESSAGE_SEVERITY_FACTORY,
2002
+ MessageCTO,
2003
+ MessageCodeTO,
2004
+ MessageService,
2005
+ MessageSeverity,
2006
+ NO_HTTP_CODE,
2007
+ NSK_CONTENT,
2008
+ ObjectWithId,
2009
+ PriceUtils,
2010
+ QUERY_SEP,
2011
+ QUERY_START,
2012
+ QueryParamHelper,
2013
+ REST_CLIENT_LOGGER,
2014
+ RestClient,
2015
+ RunFunctionResult,
2016
+ SelectHelper,
2017
+ TECHNICAL_CONTROLLER_ID,
2018
+ ViewSpec,
2019
+ createRestClient,
2020
+ fatalRunErrorFunction,
2021
+ filterArrayByIndices,
2022
+ getEnumRatingLabel,
2023
+ getEnumRatingValues,
2024
+ indexRangeArray,
2025
+ isContentWithMessages,
2026
+ openInNewTab,
2027
+ singleChangeHandlerToMulti,
2028
+ sleep,
2029
+ sortArrayByIndices,
2030
+ useAWSUIRef,
2031
+ useControllerDisplayState,
2032
+ useHotkey,
2033
+ useMessages,
2034
+ useTOArrayChangeHandler,
2035
+ useTOChangeHandler,
2036
+ warnWhenTabIsClosed
2037
+ };