ngx-material-entity 0.1.4 → 0.1.5

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 (130) hide show
  1. package/capsulation/lodash.utilities.d.ts +62 -0
  2. package/capsulation/reflect.utilities.d.ts +56 -0
  3. package/classes/base.builder.d.ts +2 -1
  4. package/classes/date.utilities.d.ts +16 -4
  5. package/classes/entity.model.d.ts +7 -1
  6. package/classes/entity.service.d.ts +38 -1
  7. package/classes/entity.utilities.d.ts +43 -16
  8. package/classes/file.utilities.d.ts +52 -0
  9. package/components/input/add-array-item-dialog-data.builder.d.ts +3 -2
  10. package/components/input/add-array-item-dialog-data.d.ts +2 -1
  11. package/components/input/array/array-date-input/array-date-input.component.d.ts +22 -0
  12. package/components/input/array/array-date-range-input/array-date-range-input.component.d.ts +30 -0
  13. package/components/input/array/array-date-time-input/array-date-time-input.component.d.ts +32 -0
  14. package/components/input/array/array-string-autocomplete-chips/array-string-autocomplete-chips.component.d.ts +58 -0
  15. package/components/input/array/array-string-chips-input/array-string-chips-input.component.d.ts +51 -0
  16. package/components/input/array/array-table.class.d.ts +48 -0
  17. package/components/input/boolean/boolean-checkbox-input/boolean-checkbox-input.component.d.ts +17 -0
  18. package/components/input/boolean/boolean-dropdown-input/boolean-dropdown-input.component.d.ts +17 -0
  19. package/components/input/boolean/boolean-toggle-input/boolean-toggle-input.component.d.ts +17 -0
  20. package/components/input/date/date-input/date-input.component.d.ts +21 -0
  21. package/components/input/date/date-range-input/date-range-input.component.d.ts +27 -0
  22. package/components/input/date/date-time-input/date-time-input.component.d.ts +38 -0
  23. package/components/input/file/file-default-input/file-default-input.component.d.ts +21 -0
  24. package/components/input/file/file-image-input/file-image-input.component.d.ts +30 -0
  25. package/components/input/file/file-input/dragDrop.directive.d.ts +32 -0
  26. package/components/input/file/file-input/file-input.component.d.ts +32 -0
  27. package/components/input/input.component.d.ts +37 -92
  28. package/components/input/input.module.d.ts +37 -16
  29. package/components/input/number/number-dropdown-input/number-dropdown-input.component.d.ts +17 -0
  30. package/components/input/number/number-input/number-input.component.d.ts +17 -0
  31. package/components/input/string/string-autocomplete-input/string-autocomplete-input.component.d.ts +25 -0
  32. package/components/input/string/string-dropdown-input/string-dropdown-input.component.d.ts +17 -0
  33. package/components/input/string/string-input/string-input.component.d.ts +17 -0
  34. package/components/input/string/string-textbox-input/string-textbox-input.component.d.ts +17 -0
  35. package/components/table/create-dialog/create-entity-dialog-data.builder.d.ts +3 -2
  36. package/components/table/create-dialog/create-entity-dialog-data.d.ts +2 -1
  37. package/components/table/create-dialog/create-entity-dialog.component.d.ts +7 -2
  38. package/components/table/edit-dialog/edit-dialog-data.builder.d.ts +3 -2
  39. package/components/table/edit-dialog/edit-entity-dialog-data.d.ts +2 -1
  40. package/components/table/edit-dialog/edit-entity-dialog.builder.d.ts +3 -2
  41. package/components/table/edit-dialog/edit-entity-dialog.component.d.ts +5 -2
  42. package/components/table/table-data.builder.d.ts +5 -5
  43. package/components/table/table-data.d.ts +6 -6
  44. package/components/table/table.component.d.ts +2 -1
  45. package/decorators/array/array-decorator-internal.data.d.ts +71 -6
  46. package/decorators/array/array-decorator.data.d.ts +178 -12
  47. package/decorators/array/array.decorator.d.ts +3 -2
  48. package/decorators/base/base-property.decorator.d.ts +2 -3
  49. package/decorators/base/decorator-types.enum.d.ts +9 -3
  50. package/decorators/date/date-decorator-internal.data.d.ts +2 -2
  51. package/decorators/date/date.decorator.d.ts +8 -0
  52. package/decorators/file/file-decorator-internal.data.d.ts +92 -0
  53. package/decorators/file/file-decorator.data.d.ts +92 -0
  54. package/decorators/file/file.decorator.d.ts +9 -0
  55. package/decorators/object/object-decorator-internal.data.d.ts +2 -2
  56. package/decorators/object/object-decorator.data.d.ts +3 -3
  57. package/decorators/object/object.decorator.d.ts +2 -1
  58. package/esm2020/capsulation/lodash.utilities.mjs +75 -0
  59. package/esm2020/capsulation/reflect.utilities.mjs +69 -0
  60. package/esm2020/classes/base.builder.mjs +2 -3
  61. package/esm2020/classes/date.utilities.mjs +33 -13
  62. package/esm2020/classes/entity.model.mjs +1 -1
  63. package/esm2020/classes/entity.service.mjs +103 -6
  64. package/esm2020/classes/entity.utilities.mjs +202 -71
  65. package/esm2020/classes/file.utilities.mjs +123 -0
  66. package/esm2020/components/confirm-dialog/confirm-dialog-data.builder.mjs +4 -4
  67. package/esm2020/components/confirm-dialog/confirm-dialog.component.mjs +3 -3
  68. package/esm2020/components/input/add-array-item-dialog-data.builder.mjs +2 -2
  69. package/esm2020/components/input/add-array-item-dialog-data.mjs +1 -1
  70. package/esm2020/components/input/array/array-date-input/array-date-input.component.mjs +44 -0
  71. package/esm2020/components/input/array/array-date-range-input/array-date-range-input.component.mjs +68 -0
  72. package/esm2020/components/input/array/array-date-time-input/array-date-time-input.component.mjs +65 -0
  73. package/esm2020/components/input/array/array-string-autocomplete-chips/array-string-autocomplete-chips.component.mjs +131 -0
  74. package/esm2020/components/input/array/array-string-chips-input/array-string-chips-input.component.mjs +116 -0
  75. package/esm2020/components/input/array/array-table.class.mjs +92 -0
  76. package/esm2020/components/input/boolean/boolean-checkbox-input/boolean-checkbox-input.component.mjs +38 -0
  77. package/esm2020/components/input/boolean/boolean-dropdown-input/boolean-dropdown-input.component.mjs +35 -0
  78. package/esm2020/components/input/boolean/boolean-toggle-input/boolean-toggle-input.component.mjs +38 -0
  79. package/esm2020/components/input/date/date-input/date-input.component.mjs +38 -0
  80. package/esm2020/components/input/date/date-range-input/date-range-input.component.mjs +63 -0
  81. package/esm2020/components/input/date/date-time-input/date-time-input.component.mjs +74 -0
  82. package/esm2020/components/input/file/file-default-input/file-default-input.component.mjs +39 -0
  83. package/esm2020/components/input/file/file-image-input/file-image-input.component.mjs +95 -0
  84. package/esm2020/components/input/file/file-input/dragDrop.directive.mjs +64 -0
  85. package/esm2020/components/input/file/file-input/file-input.component.mjs +152 -0
  86. package/esm2020/components/input/input.component.mjs +124 -234
  87. package/esm2020/components/input/input.module.mjs +66 -3
  88. package/esm2020/components/input/number/number-dropdown-input/number-dropdown-input.component.mjs +36 -0
  89. package/esm2020/components/input/number/number-input/number-input.component.mjs +34 -0
  90. package/esm2020/components/input/string/string-autocomplete-input/string-autocomplete-input.component.mjs +52 -0
  91. package/esm2020/components/input/string/string-dropdown-input/string-dropdown-input.component.mjs +36 -0
  92. package/esm2020/components/input/string/string-input/string-input.component.mjs +34 -0
  93. package/esm2020/components/input/string/string-textbox-input/string-textbox-input.component.mjs +35 -0
  94. package/esm2020/components/table/create-dialog/create-dialog-data.builder.mjs +2 -2
  95. package/esm2020/components/table/create-dialog/create-entity-dialog-data.builder.mjs +1 -1
  96. package/esm2020/components/table/create-dialog/create-entity-dialog-data.mjs +1 -1
  97. package/esm2020/components/table/create-dialog/create-entity-dialog.component.mjs +15 -8
  98. package/esm2020/components/table/edit-dialog/edit-dialog-data.builder.mjs +2 -2
  99. package/esm2020/components/table/edit-dialog/edit-entity-dialog-data.mjs +1 -1
  100. package/esm2020/components/table/edit-dialog/edit-entity-dialog.builder.mjs +2 -2
  101. package/esm2020/components/table/edit-dialog/edit-entity-dialog.component.mjs +18 -10
  102. package/esm2020/components/table/table-data.builder.mjs +3 -3
  103. package/esm2020/components/table/table-data.mjs +1 -1
  104. package/esm2020/components/table/table.component.mjs +21 -23
  105. package/esm2020/decorators/array/array-decorator-internal.data.mjs +102 -14
  106. package/esm2020/decorators/array/array-decorator.data.mjs +2 -2
  107. package/esm2020/decorators/array/array.decorator.mjs +8 -2
  108. package/esm2020/decorators/base/base-property.decorator.mjs +4 -3
  109. package/esm2020/decorators/base/decorator-types.enum.mjs +6 -1
  110. package/esm2020/decorators/base/property-decorator-internal.data.mjs +10 -10
  111. package/esm2020/decorators/base/property-decorator.data.mjs +1 -1
  112. package/esm2020/decorators/boolean/boolean-decorator-internal.data.mjs +3 -3
  113. package/esm2020/decorators/date/date-decorator-internal.data.mjs +5 -5
  114. package/esm2020/decorators/date/date.decorator.mjs +21 -0
  115. package/esm2020/decorators/file/file-decorator-internal.data.mjs +98 -0
  116. package/esm2020/decorators/file/file-decorator.data.mjs +7 -0
  117. package/esm2020/decorators/file/file.decorator.mjs +22 -0
  118. package/esm2020/decorators/object/object-decorator-internal.data.mjs +1 -1
  119. package/esm2020/decorators/object/object-decorator.data.mjs +1 -1
  120. package/esm2020/decorators/object/object.decorator.mjs +1 -1
  121. package/esm2020/decorators/string/string.decorator.mjs +1 -1
  122. package/esm2020/mocks/placeholder-data.png.mjs +3 -0
  123. package/esm2020/public-api.mjs +6 -1
  124. package/fesm2015/ngx-material-entity.mjs +2452 -459
  125. package/fesm2015/ngx-material-entity.mjs.map +1 -1
  126. package/fesm2020/ngx-material-entity.mjs +2370 -464
  127. package/fesm2020/ngx-material-entity.mjs.map +1 -1
  128. package/mocks/placeholder-data.png.d.ts +1 -0
  129. package/package.json +1 -1
  130. package/public-api.d.ts +5 -0
@@ -1,45 +1,114 @@
1
1
  import 'reflect-metadata';
2
2
  import { __decorate, __metadata } from 'tslib';
3
3
  import { BehaviorSubject, firstValueFrom, Subject, takeUntil } from 'rxjs';
4
- import { cloneDeep, isEqual, omit, omitBy, isNil } from 'lodash';
4
+ import { isEqual, cloneDeep, omit, isNil, omitBy, isArray } from 'lodash';
5
5
  import * as i0 from '@angular/core';
6
- import { Component, Inject, NgModule, Input, ViewChild } from '@angular/core';
6
+ import { Component, Inject, NgModule, EventEmitter, Input, Output, Directive, HostListener, ViewChild } from '@angular/core';
7
7
  import * as i1 from '@angular/material/dialog';
8
8
  import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
9
9
  import * as i6 from '@angular/material/checkbox';
10
10
  import { MatCheckboxModule } from '@angular/material/checkbox';
11
- import * as i3 from '@angular/material/button';
11
+ import * as i4 from '@angular/material/button';
12
12
  import { MatButtonModule } from '@angular/material/button';
13
- import * as i12 from '@angular/common';
13
+ import * as i4$1 from '@angular/common';
14
14
  import { CommonModule } from '@angular/common';
15
- import * as i14 from '@angular/forms';
15
+ import * as i3 from '@angular/forms';
16
16
  import { FormsModule } from '@angular/forms';
17
- import * as i9 from '@angular/material/table';
17
+ import * as i5 from '@angular/material/table';
18
18
  import { MatTableDataSource, MatTableModule } from '@angular/material/table';
19
19
  import { SelectionModel } from '@angular/cdk/collections';
20
- import * as i2 from '@angular/material/form-field';
20
+ import * as i1$1 from '@angular/material/form-field';
21
21
  import { MatFormFieldModule } from '@angular/material/form-field';
22
- import * as i3$1 from '@angular/material/autocomplete';
22
+ import * as i4$2 from '@angular/material/input';
23
+ import { MatInputModule } from '@angular/material/input';
24
+ import * as i3$1 from '@angular/cdk/text-field';
25
+ import * as i2 from '@angular/material/autocomplete';
23
26
  import { MatAutocompleteModule } from '@angular/material/autocomplete';
24
- import * as i4 from '@angular/material/core';
25
- import * as i5 from '@angular/material/select';
27
+ import * as i3$2 from '@angular/material/core';
28
+ import * as i2$1 from '@angular/material/select';
26
29
  import { MatSelectModule } from '@angular/material/select';
27
- import * as i7 from '@angular/material/slide-toggle';
30
+ import * as i2$2 from '@angular/material/slide-toggle';
28
31
  import { MatSlideToggleModule } from '@angular/material/slide-toggle';
29
- import * as i10 from '@angular/material/chips';
30
- import { MatChipsModule } from '@angular/material/chips';
31
- import * as i11 from '@angular/material/datepicker';
32
+ import * as i3$3 from '@angular/material/datepicker';
32
33
  import { MatDatepickerModule } from '@angular/material/datepicker';
33
- import * as i13 from '@angular/material/input';
34
- import { MatInputModule } from '@angular/material/input';
35
- import * as i15 from '@angular/cdk/text-field';
34
+ import * as i2$3 from '@angular/material/chips';
35
+ import { MatChipsModule } from '@angular/material/chips';
36
36
  import { MatIconModule } from '@angular/material/icon';
37
- import * as i7$1 from '@angular/material/paginator';
37
+ import * as i7 from '@angular/material/paginator';
38
38
  import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
39
39
  import { MatSort } from '@angular/material/sort';
40
- import * as i4$1 from '@angular/material/menu';
40
+ import * as i4$3 from '@angular/material/menu';
41
41
  import { MatMenuModule } from '@angular/material/menu';
42
42
 
43
+ /**
44
+ * Encapsulates all functionality of Reflect.
45
+ */
46
+ class ReflectUtilities {
47
+ /**
48
+ * Gets the metadata value for the provided metadata key on the target object or its prototype chain.
49
+ *
50
+ * @param metadataKey - A key used to store and retrieve metadata.
51
+ * @param target - The target object on which the metadata is defined.
52
+ * @param propertyKey - The property key for the target.
53
+ * @returns The metadata value for the metadata key if found; otherwise, undefined.
54
+ */
55
+ static getMetadata(metadataKey, target, propertyKey) {
56
+ return Reflect.getMetadata(metadataKey, target, propertyKey);
57
+ }
58
+ /**
59
+ * Returns the string and symbol keys of the own properties of an object. The own properties of an object
60
+ * are those that are defined directly on that object, and are not inherited from the object's prototype.
61
+ *
62
+ * @param target - Object that contains the own properties.
63
+ * @returns The keys of the given object.
64
+ */
65
+ static ownKeys(target) {
66
+ return Reflect.ownKeys(target);
67
+ }
68
+ /**
69
+ * Gets the property of target, equivalent to `target[propertyKey]`.
70
+ *
71
+ * @param target - Object that contains the property on itself or in its prototype chain.
72
+ * @param propertyKey - The property name.
73
+ * @returns The property of the target of the given key.
74
+ */
75
+ static get(target, propertyKey) {
76
+ return Reflect.get(target, propertyKey);
77
+ }
78
+ /**
79
+ * Sets the property of target, equivalent to `target[propertyKey] = value`.
80
+ *
81
+ * @param target - Object that contains the property on itself or in its prototype chain.
82
+ * @param propertyKey - The property name.
83
+ * @param value - The value to set the property to.
84
+ * @returns If setting the value was successful.
85
+ */
86
+ static set(target, propertyKey, value) {
87
+ return Reflect.set(target, propertyKey, value);
88
+ }
89
+ /**
90
+ * Equivalent to `propertyKey in target`.
91
+ *
92
+ * @param target - Object that contains the property on itself or in its prototype chain.
93
+ * @param propertyKey - Name of the property.
94
+ * @returns Whether or not the given target has the key.
95
+ */
96
+ static has(target, propertyKey) {
97
+ return Reflect.has(target, propertyKey);
98
+ }
99
+ /**
100
+ * Define a unique metadata entry on the target.
101
+ *
102
+ * @param metadataKey - A key used to store and retrieve metadata.
103
+ * @param metadataValue - A value that contains attached metadata.
104
+ * @param target - The target object on which to define metadata.
105
+ * @param propertyKey - The property key for the target.
106
+ */
107
+ static defineMetadata(metadataKey, metadataValue, target, propertyKey) {
108
+ Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey);
109
+ }
110
+ }
111
+
43
112
  /**
44
113
  * The base decorator for setting metadata on properties.
45
114
  *
@@ -49,8 +118,8 @@ import { MatMenuModule } from '@angular/material/menu';
49
118
  */
50
119
  function baseProperty(metadata, type) {
51
120
  return function (target, propertyKey) {
52
- Reflect.defineMetadata('metadata', metadata, target, propertyKey);
53
- Reflect.defineMetadata('type', type, target, propertyKey);
121
+ ReflectUtilities.defineMetadata('metadata', metadata, target, propertyKey);
122
+ ReflectUtilities.defineMetadata('type', type, target, propertyKey);
54
123
  };
55
124
  }
56
125
 
@@ -70,11 +139,16 @@ var DecoratorTypes;
70
139
  DecoratorTypes["BOOLEAN_DROPDOWN"] = "booleanDropdown";
71
140
  DecoratorTypes["OBJECT"] = "object";
72
141
  DecoratorTypes["ARRAY"] = "array";
142
+ DecoratorTypes["ARRAY_DATE"] = "arrayDate";
143
+ DecoratorTypes["ARRAY_DATE_TIME"] = "arrayDateTime";
144
+ DecoratorTypes["ARRAY_DATE_RANGE"] = "arrayDateRange";
73
145
  DecoratorTypes["ARRAY_STRING_CHIPS"] = "arrayStringChips";
74
146
  DecoratorTypes["ARRAY_STRING_AUTOCOMPLETE_CHIPS"] = "arrayStringAutocompleteChips";
75
147
  DecoratorTypes["DATE"] = "date";
76
148
  DecoratorTypes["DATE_RANGE"] = "dateRange";
77
149
  DecoratorTypes["DATE_TIME"] = "dateTime";
150
+ DecoratorTypes["FILE_DEFAULT"] = "fileDefault";
151
+ DecoratorTypes["FILE_IMAGE"] = "fileImage";
78
152
  })(DecoratorTypes || (DecoratorTypes = {}));
79
153
 
80
154
  /**
@@ -83,11 +157,11 @@ var DecoratorTypes;
83
157
  class PositionInternal {
84
158
  constructor(data) {
85
159
  this.validateInput(data);
86
- this.row = data?.row ? data.row : -1;
87
- this.order = data?.order ? data.order : -1;
160
+ this.row = data?.row ?? -1;
161
+ this.order = data?.order ?? -1;
88
162
  }
89
163
  validateInput(data) {
90
- if (data?.order) {
164
+ if (data?.order != null) {
91
165
  if (data.order < 1) {
92
166
  throw new Error('order must be at least 1');
93
167
  }
@@ -95,7 +169,7 @@ class PositionInternal {
95
169
  throw new Error('order cannot be bigger than 12 (the minimum value for a bootstrap column)');
96
170
  }
97
171
  }
98
- if (data?.row && (data.row < 1)) {
172
+ if (data?.row != null && data.row < 1) {
99
173
  throw new Error('row must be at least 1');
100
174
  }
101
175
  }
@@ -105,12 +179,12 @@ class PositionInternal {
105
179
  */
106
180
  class PropertyDecoratorConfigInternal {
107
181
  constructor(data) {
108
- this.display = data.display != undefined ? data.display : true;
182
+ this.display = data.display ?? true;
109
183
  this.displayName = data.displayName;
110
- this.required = data.required != undefined ? data.required : true;
111
- this.omitForCreate = data.omitForCreate != undefined ? data.omitForCreate : false;
112
- this.omitForUpdate = data.omitForUpdate != undefined ? data.omitForUpdate : false;
113
- this.defaultWidths = data.defaultWidths ? data.defaultWidths : [6, 6, 12];
184
+ this.required = data.required ?? true;
185
+ this.omitForCreate = data.omitForCreate ?? false;
186
+ this.omitForUpdate = data.omitForUpdate ?? false;
187
+ this.defaultWidths = data.defaultWidths ?? [6, 6, 12];
114
188
  this.position = new PositionInternal(data.position);
115
189
  }
116
190
  }
@@ -200,6 +274,80 @@ __decorate([
200
274
  __metadata("design:type", String)
201
275
  ], Entity.prototype, "id", void 0);
202
276
 
277
+ /**
278
+ * Encapsulates all functionality of lodash.
279
+ */
280
+ class LodashUtilities {
281
+ /**
282
+ * Performs a deep comparison between two values to determine if they are
283
+ * equivalent.
284
+ *
285
+ * **Note:** This method supports comparing arrays, array buffers, booleans,
286
+ * date objects, error objects, maps, numbers, `Object` objects, regexps,
287
+ * sets, strings, symbols, and typed arrays. `Object` objects are compared
288
+ * by their own, not inherited, enumerable properties. Functions and DOM
289
+ * nodes are **not** supported.
290
+ *
291
+ * @param value - The value to compare.
292
+ * @param other - The other value to compare.
293
+ * @returns Returns `true` if the values are equivalent, else `false`.
294
+ */
295
+ static isEqual(value, other) {
296
+ return isEqual(value, other);
297
+ }
298
+ /**
299
+ * This method is like _.clone except that it recursively clones value.
300
+ *
301
+ * @param value - The value to recursively clone.
302
+ * @returns Returns the deep cloned value.
303
+ */
304
+ static cloneDeep(value) {
305
+ return cloneDeep(value);
306
+ }
307
+ /**
308
+ * The opposite of `_.pick`; this method creates an object composed of the
309
+ * own and inherited enumerable properties of `object` that are not omitted.
310
+ *
311
+ * @param object - The source object.
312
+ * @param paths - The property names to omit, specified
313
+ * individually or in arrays.
314
+ * @returns Returns the new object.
315
+ */
316
+ static omit(object, ...paths) {
317
+ return omit(object, ...paths);
318
+ }
319
+ /**
320
+ * Checks if `value` is `null` or `undefined`.
321
+ *
322
+ * @param value - The value to check.
323
+ * @returns Returns `true` if `value` is nullish, else `false`.
324
+ */
325
+ static isNil(value) {
326
+ return isNil(value);
327
+ }
328
+ /**
329
+ * The opposite of `_.pickBy`; this method creates an object composed of the
330
+ * own and inherited enumerable properties of `object` that `predicate`
331
+ * doesn't return truthy for.
332
+ *
333
+ * @param object - The source object.
334
+ * @param predicate - The function invoked per property.
335
+ * @returns Returns the new object.
336
+ */
337
+ static omitBy(object, predicate) {
338
+ return omitBy(object, predicate);
339
+ }
340
+ /**
341
+ * Checks if value is classified as an Array object.
342
+ *
343
+ * @param value - The value to check.
344
+ * @returns Returns true if value is correctly classified, else false.
345
+ */
346
+ static isArray(value) {
347
+ return isArray(value);
348
+ }
349
+ }
350
+
203
351
  const DAY_IN_MS = 1000 * 60 * 60 * 24;
204
352
  /**
205
353
  * Contains Helper Functions for handling date properties.
@@ -225,14 +373,14 @@ class DateUtilities {
225
373
  const res = [{ displayName: '-', value: undefined }];
226
374
  for (let hour = 0; hour < 24; hour++) {
227
375
  for (let minute = 0; minute < 60; minute += minuteSteps) {
228
- res.push(this.getTimeDropdownValue(format, hour, minute));
376
+ res.push(DateUtilities.getTimeDropdownValue(format, hour, minute));
229
377
  }
230
378
  }
231
379
  return res;
232
380
  }
233
381
  static getTimeDropdownValue(format, hour, minute) {
234
- const displayHour = this.getFormattedHour(format, cloneDeep(hour));
235
- const displayMinute = this.getFormattedMinute(format, hour, minute);
382
+ const displayHour = DateUtilities.getFormattedHour(format, LodashUtilities.cloneDeep(hour));
383
+ const displayMinute = DateUtilities.getFormattedMinute(format, hour, minute);
236
384
  return {
237
385
  displayName: `${displayHour}:${displayMinute}`,
238
386
  value: {
@@ -270,10 +418,7 @@ class DateUtilities {
270
418
  */
271
419
  static getTimeFromDate(value) {
272
420
  if (!value) {
273
- return {
274
- hours: undefined,
275
- minutes: undefined
276
- };
421
+ return undefined;
277
422
  }
278
423
  else {
279
424
  return {
@@ -287,10 +432,10 @@ class DateUtilities {
287
432
  *
288
433
  * @param startDate - The start date.
289
434
  * @param endDate - The end date.
290
- * @param metadataDateRangeDate - The metadata.
435
+ * @param filter - The custom filter from the metadata.
291
436
  * @returns All dates between the two provided dates. Includes start and end date.
292
437
  */
293
- static getDatesBetween(startDate, endDate, metadataDateRangeDate) {
438
+ static getDatesBetween(startDate, endDate, filter) {
294
439
  const res = [];
295
440
  while (startDate.getFullYear() < endDate.getFullYear()
296
441
  || startDate.getMonth() < endDate.getMonth()
@@ -298,8 +443,8 @@ class DateUtilities {
298
443
  res.push(new Date(startDate));
299
444
  startDate.setTime(startDate.getTime() + DAY_IN_MS);
300
445
  }
301
- if (metadataDateRangeDate.filter) {
302
- return res.filter(d => metadataDateRangeDate.filter?.(d));
446
+ if (filter) {
447
+ return res.filter(d => filter(d));
303
448
  }
304
449
  else {
305
450
  return res;
@@ -335,6 +480,152 @@ class DateUtilities {
335
480
  }
336
481
  return times;
337
482
  }
483
+ /**
484
+ * Checks if the time object has processable hours and minutes properties.
485
+ * Doesn't check custom validators like min/max from the metadata configuration.
486
+ *
487
+ * @param time - The time to check.
488
+ * @returns Whether or not the time object is unprocessable.
489
+ */
490
+ static timeIsUnprocessable(time) {
491
+ if (!time
492
+ || time.hours == null
493
+ || typeof time.hours !== 'number'
494
+ || Number.isNaN(time.hours)
495
+ || time.minutes == null
496
+ || typeof time.minutes !== 'number'
497
+ || Number.isNaN(time.minutes)) {
498
+ return true;
499
+ }
500
+ return false;
501
+ }
502
+ }
503
+ /**
504
+ * The default filter function to user when none was provided by the user.
505
+ */
506
+ DateUtilities.defaultDateFilter = () => true;
507
+
508
+ /**
509
+ * Provides functionality regarding files.
510
+ */
511
+ class FileUtilities {
512
+ /**
513
+ * Gets the accept value for the html input.
514
+ *
515
+ * @param mimeTypes - The mimeTypes to get the accept string from.
516
+ * @returns A comma separated string of all the provided mime types.
517
+ */
518
+ static getAcceptString(mimeTypes) {
519
+ if (!mimeTypes?.length) {
520
+ return '*';
521
+ }
522
+ return mimeTypes.join(', ');
523
+ }
524
+ // TODO: Find a way to use blobs with jest
525
+ /* istanbul ignore next */
526
+ /**
527
+ * Reads a url to display the given file.
528
+ *
529
+ * @param file - The file to get the url from.
530
+ * @returns A promise of the url. Undefined if no file was provided.
531
+ */
532
+ static async getDataURLFromFile(file) {
533
+ if (!file) {
534
+ return undefined;
535
+ }
536
+ return new Promise((resolve, reject) => {
537
+ const reader = new FileReader();
538
+ reader.onload = e => resolve(e.target?.result);
539
+ reader.onerror = e => reject(e);
540
+ reader.readAsDataURL(file);
541
+ });
542
+ }
543
+ // TODO: Find a way to use blobs with jest
544
+ /* istanbul ignore next */
545
+ /**
546
+ * Gets a file from the given url.
547
+ *
548
+ * @param url - The url to get the file from.
549
+ * @returns A promise of the File.
550
+ */
551
+ static async getFileFromUrl(url) {
552
+ const res = await fetch(url);
553
+ if (!res.ok) {
554
+ // TODO make error more robust
555
+ throw new Error(`Error fetching the file from the url ${url}`);
556
+ }
557
+ return await res.blob();
558
+ }
559
+ // TODO: Find a way to use blobs with jest
560
+ /* istanbul ignore next */
561
+ /**
562
+ * Gets the file data with the blob from the given File Data.
563
+ *
564
+ * @param data - The File Data to get the file data with blob from.
565
+ * @returns FileDataWithFile.
566
+ */
567
+ static async getFileData(data) {
568
+ if (data.file) {
569
+ return {
570
+ file: data.file,
571
+ name: data.name,
572
+ url: data.url,
573
+ type: data.type,
574
+ size: data.size
575
+ };
576
+ }
577
+ else {
578
+ return {
579
+ file: await FileUtilities.getFileFromUrl(data.url),
580
+ name: data.name,
581
+ url: data.url,
582
+ type: data.type,
583
+ size: data.size
584
+ };
585
+ }
586
+ }
587
+ /**
588
+ * Checks if the given file has a valid mime type.
589
+ *
590
+ * @param type - The type of the file to check.
591
+ * @param allowedMimeTypes - The allowed mime types.
592
+ * @returns Whether or not the given file has a valid mime type.
593
+ */
594
+ static isMimeTypeValid(type, allowedMimeTypes) {
595
+ if (allowedMimeTypes.includes('*')) {
596
+ return true;
597
+ }
598
+ for (const t of allowedMimeTypes) {
599
+ if (t === type) {
600
+ return true;
601
+ }
602
+ if (t.endsWith('*') && type.startsWith(t.split('*')[0])) {
603
+ return true;
604
+ }
605
+ }
606
+ return false;
607
+ }
608
+ /**
609
+ * Transform the given value to Megabytes.
610
+ *
611
+ * @param value - The original value.
612
+ * @param unit - If the value is B, KB or GB.
613
+ * @returns The given value as bytes.
614
+ */
615
+ static transformToMegaBytes(value, unit) {
616
+ const bytes = this.transformToBytes(value, unit);
617
+ return bytes / 1000000;
618
+ }
619
+ static transformToBytes(value, unit) {
620
+ switch (unit) {
621
+ case 'B':
622
+ return value;
623
+ case 'KB':
624
+ return value * 1000;
625
+ case 'GB':
626
+ return value * 1000000000;
627
+ }
628
+ }
338
629
  }
339
630
 
340
631
  /**
@@ -373,6 +664,26 @@ class EntityUtilities {
373
664
  }
374
665
  return res;
375
666
  }
667
+ /**
668
+ * Gets all properties on the given entity which are files.
669
+ *
670
+ * @param entity - The entity to check for file properties.
671
+ * @param omit - Whether to leave out values that are omitted for create or delete.
672
+ * @returns The keys of all file properties on the given entity.
673
+ */
674
+ static getFileProperties(entity, omit) {
675
+ const res = [];
676
+ for (const key of EntityUtilities.keysOf(entity)) {
677
+ const type = EntityUtilities.getPropertyType(entity, key);
678
+ if (type === DecoratorTypes.FILE_DEFAULT || type === DecoratorTypes.FILE_IMAGE) {
679
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
680
+ if (!(metadata.omitForCreate && omit === 'create') && !(metadata.omitForUpdate && omit === 'update')) {
681
+ res.push(key);
682
+ }
683
+ }
684
+ }
685
+ return res;
686
+ }
376
687
  /**
377
688
  * Gets the metadata included in an property.
378
689
  *
@@ -385,16 +696,11 @@ class EntityUtilities {
385
696
  static getPropertyMetadata(entity, propertyKey,
386
697
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
387
698
  type) {
388
- try {
389
- const metadata = Reflect.getMetadata('metadata', entity, propertyKey);
390
- if (!metadata) {
391
- throw new Error(`Could not find metadata for property ${String(propertyKey)} on the entity ${JSON.stringify(entity)}`);
392
- }
393
- return metadata;
394
- }
395
- catch (error) {
699
+ const metadata = ReflectUtilities.getMetadata('metadata', entity, propertyKey);
700
+ if (metadata == null) {
396
701
  throw new Error(`Could not find metadata for property ${String(propertyKey)} on the entity ${JSON.stringify(entity)}`);
397
702
  }
703
+ return metadata;
398
704
  }
399
705
  /**
400
706
  * Gets the type of the property-metadata.
@@ -406,8 +712,8 @@ class EntityUtilities {
406
712
  */
407
713
  static getPropertyType(entity, propertyKey) {
408
714
  try {
409
- const propertyType = Reflect.getMetadata('type', entity, propertyKey);
410
- if (!propertyType) {
715
+ const propertyType = ReflectUtilities.getMetadata('type', entity, propertyKey);
716
+ if (propertyType == null) {
411
717
  throw new Error(`Could not find type metadata for property ${String(propertyKey)} on the entity ${JSON.stringify(entity)}`);
412
718
  }
413
719
  return propertyType;
@@ -428,12 +734,10 @@ class EntityUtilities {
428
734
  static new(target, entity) {
429
735
  for (const key in target) {
430
736
  const type = EntityUtilities.getPropertyType(target, key);
431
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
432
- let value = entity ? Reflect.get(entity, key) : undefined;
737
+ let value = entity ? ReflectUtilities.get(entity, key) : undefined;
433
738
  switch (type) {
434
739
  case DecoratorTypes.OBJECT:
435
740
  const objectMetadata = EntityUtilities.getPropertyMetadata(target, key, DecoratorTypes.OBJECT);
436
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
437
741
  value = new objectMetadata.EntityClass(value);
438
742
  break;
439
743
  case DecoratorTypes.ARRAY:
@@ -451,7 +755,7 @@ class EntityUtilities {
451
755
  default:
452
756
  break;
453
757
  }
454
- Reflect.set(target, key, value);
758
+ ReflectUtilities.set(target, key, value);
455
759
  }
456
760
  }
457
761
  /**
@@ -488,28 +792,34 @@ class EntityUtilities {
488
792
  if (metadata.omitForUpdate && omit === 'update') {
489
793
  return true;
490
794
  }
491
- if (metadata.required && !entity[key]) {
795
+ if (metadata.required && entity[key] == null) {
492
796
  return false;
493
797
  }
494
798
  switch (type) {
495
799
  case DecoratorTypes.BOOLEAN_DROPDOWN:
800
+ break;
496
801
  case DecoratorTypes.BOOLEAN_CHECKBOX:
497
802
  case DecoratorTypes.BOOLEAN_TOGGLE:
498
- return true;
803
+ const entityBoolean = entity[key];
804
+ const booleanMetadata = metadata;
805
+ if (!EntityUtilities.isBooleanValid(entityBoolean, booleanMetadata)) {
806
+ return false;
807
+ }
808
+ break;
499
809
  case DecoratorTypes.STRING_DROPDOWN:
500
- return true;
810
+ break;
501
811
  case DecoratorTypes.STRING:
502
812
  case DecoratorTypes.STRING_AUTOCOMPLETE:
503
813
  const entityString = entity[key];
504
814
  const stringMetadata = metadata;
505
- if (!this.isStringValid(entityString, stringMetadata)) {
815
+ if (!EntityUtilities.isStringValid(entityString, stringMetadata)) {
506
816
  return false;
507
817
  }
508
818
  break;
509
819
  case DecoratorTypes.STRING_TEXTBOX:
510
820
  const entityTextbox = entity[key];
511
821
  const textboxMetadata = metadata;
512
- if (!this.isTextboxValid(entityTextbox, textboxMetadata)) {
822
+ if (!EntityUtilities.isTextboxValid(entityTextbox, textboxMetadata)) {
513
823
  return false;
514
824
  }
515
825
  break;
@@ -518,7 +828,7 @@ class EntityUtilities {
518
828
  case DecoratorTypes.NUMBER:
519
829
  const entityNumber = entity[key];
520
830
  const numberMetadata = metadata;
521
- if (!this.isNumberValid(entityNumber, numberMetadata)) {
831
+ if (!EntityUtilities.isNumberValid(entityNumber, numberMetadata)) {
522
832
  return false;
523
833
  }
524
834
  break;
@@ -532,6 +842,9 @@ class EntityUtilities {
532
842
  break;
533
843
  case DecoratorTypes.ARRAY_STRING_CHIPS:
534
844
  case DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS:
845
+ case DecoratorTypes.ARRAY_DATE:
846
+ case DecoratorTypes.ARRAY_DATE_TIME:
847
+ case DecoratorTypes.ARRAY_DATE_RANGE:
535
848
  case DecoratorTypes.ARRAY:
536
849
  const entityArray = entity[key];
537
850
  const arrayMetadata = metadata;
@@ -542,21 +855,29 @@ class EntityUtilities {
542
855
  case DecoratorTypes.DATE:
543
856
  const entityDate = new Date(entity[key]);
544
857
  const dateMetadata = metadata;
545
- if (!this.isDateValid(entityDate, dateMetadata)) {
858
+ if (!EntityUtilities.isDateValid(entityDate, dateMetadata)) {
546
859
  return false;
547
860
  }
548
861
  break;
549
862
  case DecoratorTypes.DATE_RANGE:
550
- const entityDateRange = cloneDeep(entity[key]);
863
+ const entityDateRange = LodashUtilities.cloneDeep(entity[key]);
551
864
  const dateRangeMetadata = metadata;
552
- if (!this.isDateRangeValid(entityDateRange, dateRangeMetadata)) {
865
+ if (!EntityUtilities.isDateRangeValid(entityDateRange, dateRangeMetadata)) {
553
866
  return false;
554
867
  }
555
868
  break;
556
869
  case DecoratorTypes.DATE_TIME:
557
870
  const entityDateTime = new Date(entity[key]);
558
871
  const dateTimeMetadata = metadata;
559
- if (!this.isDateTimeValid(entityDateTime, dateTimeMetadata)) {
872
+ if (!EntityUtilities.isDateTimeValid(entityDateTime, dateTimeMetadata)) {
873
+ return false;
874
+ }
875
+ break;
876
+ case DecoratorTypes.FILE_DEFAULT:
877
+ case DecoratorTypes.FILE_IMAGE:
878
+ const entityFile = entity[key];
879
+ const entityFileMetadata = metadata;
880
+ if (!EntityUtilities.isFileDataValid(entityFile, entityFileMetadata)) {
560
881
  return false;
561
882
  }
562
883
  break;
@@ -565,6 +886,12 @@ class EntityUtilities {
565
886
  }
566
887
  return true;
567
888
  }
889
+ static isBooleanValid(value, metadata) {
890
+ if (metadata.required && !value) {
891
+ return false;
892
+ }
893
+ return true;
894
+ }
568
895
  static isStringValid(value, metadata) {
569
896
  if (metadata.maxLength && value.length > metadata.maxLength) {
570
897
  return false;
@@ -608,8 +935,13 @@ class EntityUtilities {
608
935
  return true;
609
936
  }
610
937
  static isDateRangeValid(value, metadata) {
611
- if (metadata.required && (!value.start || !value.end)) {
612
- return false;
938
+ if (metadata.required) {
939
+ if (!value.start) {
940
+ return false;
941
+ }
942
+ if (!value.end) {
943
+ return false;
944
+ }
613
945
  }
614
946
  value.start = new Date(value.start);
615
947
  value.end = new Date(value.end);
@@ -679,6 +1011,29 @@ class EntityUtilities {
679
1011
  }
680
1012
  return true;
681
1013
  }
1014
+ static isFileDataValid(value, metadata) {
1015
+ const files = metadata.multiple ? value : [value];
1016
+ const maxSize = metadata.maxSize * 1000000;
1017
+ const maxSizeTotal = metadata.maxSizeTotal * 1000000;
1018
+ let fileSizeTotal = 0;
1019
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
1020
+ for (let i = 0; i < files.length; i++) {
1021
+ if (!files[i].name || !files[i].file && !files[i].url) {
1022
+ return false;
1023
+ }
1024
+ if (!FileUtilities.isMimeTypeValid(files[i].type, metadata.allowedMimeTypes)) {
1025
+ return false;
1026
+ }
1027
+ if (files[i].size > maxSize) {
1028
+ return false;
1029
+ }
1030
+ fileSizeTotal += files[i].size;
1031
+ if (fileSizeTotal > maxSizeTotal) {
1032
+ return false;
1033
+ }
1034
+ }
1035
+ return true;
1036
+ }
682
1037
  /**
683
1038
  * Checks if an entity is "dirty" (if its values have changed).
684
1039
  *
@@ -686,19 +1041,21 @@ class EntityUtilities {
686
1041
  * @param entityPriorChanges - The entity before the changes.
687
1042
  * @returns Whether or not the entity is dirty.
688
1043
  */
689
- static dirty(entity, entityPriorChanges) {
1044
+ static async dirty(entity, entityPriorChanges) {
690
1045
  if (!entityPriorChanges) {
691
1046
  return false;
692
1047
  }
693
1048
  else {
694
- const differences = this.differencesForDirty(entity, entityPriorChanges);
1049
+ const differences = await EntityUtilities.differencesForDirty(entity, entityPriorChanges);
695
1050
  return differences.length ? true : false;
696
1051
  }
697
1052
  }
698
- static differencesForDirty(entity, entityPriorChanges) {
1053
+ static async differencesForDirty(entity, entityPriorChanges) {
699
1054
  const res = [];
700
1055
  for (const key in entity) {
701
- if (!this.isEqual(entity[key], entityPriorChanges[key], EntityUtilities.getPropertyMetadata(entity, key))) {
1056
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
1057
+ const type = EntityUtilities.getPropertyType(entity, key);
1058
+ if (!(await EntityUtilities.isEqual(entity[key], entityPriorChanges[key], metadata, type))) {
702
1059
  res.push({
703
1060
  key: key,
704
1061
  before: entityPriorChanges[key],
@@ -715,48 +1072,111 @@ class EntityUtilities {
715
1072
  * @param entityPriorChanges - The second entity to compare.
716
1073
  * @returns The difference between the two Entities in form of a Partial.
717
1074
  */
718
- static difference(entity, entityPriorChanges) {
1075
+ static async difference(entity, entityPriorChanges) {
719
1076
  const res = {};
720
1077
  for (const key in entity) {
721
- if (!this.isEqual(entity[key], entityPriorChanges[key], EntityUtilities.getPropertyMetadata(entity, key))) {
1078
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
1079
+ const type = EntityUtilities.getPropertyType(entity, key);
1080
+ if (!(await EntityUtilities.isEqual(entity[key], entityPriorChanges[key], metadata, type))) {
722
1081
  res[key] = entity[key];
723
1082
  }
724
1083
  }
725
1084
  return res;
726
1085
  }
727
- static isEqual(value, valuePriorChanges, metadata) {
728
- if (this.isDateRange(value) && this.isDateRange(valuePriorChanges)) {
729
- const dateRange = cloneDeep(value);
730
- dateRange.start = new Date(value.start);
731
- dateRange.end = new Date(value.end);
732
- dateRange.values = DateUtilities.getDatesBetween(dateRange.start, dateRange.end, metadata);
733
- const dateRangePriorChanges = cloneDeep(valuePriorChanges);
734
- dateRangePriorChanges.start = new Date(valuePriorChanges.start);
735
- dateRangePriorChanges.end = new Date(valuePriorChanges.end);
736
- dateRangePriorChanges.values = DateUtilities.getDatesBetween(dateRangePriorChanges.start, dateRangePriorChanges.end, metadata);
737
- return isEqual(dateRange, dateRangePriorChanges);
738
- }
739
- if (metadata.displayStyle === 'date') {
740
- const date = new Date(DateUtilities.asDate(value));
741
- const datePriorChanges = new Date(DateUtilities.asDate(valuePriorChanges));
742
- date.setHours(0, 0, 0, 0);
743
- datePriorChanges.setHours(0, 0, 0, 0);
744
- return isEqual(date, datePriorChanges);
745
- }
746
- return isEqual(value, valuePriorChanges);
747
- }
748
- static isDateRange(value) {
749
- const dateRange = value;
750
- if (dateRange.start && dateRange.end) {
751
- try {
752
- new Date(dateRange.start);
753
- new Date(dateRange.end);
754
- return true;
1086
+ /**
1087
+ * Checks if two given values are equal.
1088
+ * It uses the isEqual method from LodashUtilities and extends it with functionality regarding Dates.
1089
+ *
1090
+ * @param value - The updated value.
1091
+ * @param valuePriorChanges - The value before any changes.
1092
+ * @param metadata - The metadata of the property.
1093
+ * @param type - The type of the property.
1094
+ * @returns Whether or not the given values are equal.
1095
+ */
1096
+ // eslint-disable-next-line max-len
1097
+ static async isEqual(value, valuePriorChanges, metadata, type) {
1098
+ switch (type) {
1099
+ case DecoratorTypes.DATE_RANGE:
1100
+ return EntityUtilities.isEqualDateRange(value, valuePriorChanges, metadata.filter);
1101
+ case DecoratorTypes.DATE:
1102
+ return EntityUtilities.isEqualDate(value, valuePriorChanges);
1103
+ case DecoratorTypes.DATE_TIME:
1104
+ return EntityUtilities.isEqualDateTime(value, valuePriorChanges);
1105
+ case DecoratorTypes.ARRAY_DATE:
1106
+ case DecoratorTypes.ARRAY_DATE_TIME:
1107
+ return EntityUtilities.isEqualArrayDate(value, valuePriorChanges);
1108
+ case DecoratorTypes.ARRAY_DATE_RANGE:
1109
+ return EntityUtilities.isEqualArrayDateRange(value, valuePriorChanges, metadata.filter);
1110
+ case DecoratorTypes.FILE_IMAGE:
1111
+ case DecoratorTypes.FILE_DEFAULT:
1112
+ return EntityUtilities.isEqualFile(value, valuePriorChanges, metadata.multiple);
1113
+ default:
1114
+ return LodashUtilities.isEqual(value, valuePriorChanges);
1115
+ }
1116
+ }
1117
+ static isEqualArrayDate(value, valuePriorChanges) {
1118
+ const newValue = value.map(v => new Date(v)).sort();
1119
+ const newValuePriorChanges = valuePriorChanges.map(v => new Date(v)).sort();
1120
+ return LodashUtilities.isEqual(newValue, newValuePriorChanges);
1121
+ }
1122
+ static isEqualArrayDateRange(value, valuePriorChanges, filter) {
1123
+ const dateRanges = value.sort();
1124
+ const dateRangesPriorChanges = valuePriorChanges.sort();
1125
+ if (dateRanges.length !== dateRangesPriorChanges.length) {
1126
+ return false;
1127
+ }
1128
+ for (let i = 0; i < dateRanges.length; i++) {
1129
+ if (!EntityUtilities.isEqualDateRange(dateRanges[i], dateRangesPriorChanges[i], filter)) {
1130
+ return false;
755
1131
  }
756
- catch (error) { }
757
- ;
758
1132
  }
759
- return false;
1133
+ return true;
1134
+ }
1135
+ static isEqualDateTime(value, valuePriorChanges) {
1136
+ const date = new Date(value);
1137
+ const datePriorChanges = new Date(valuePriorChanges);
1138
+ return LodashUtilities.isEqual(date, datePriorChanges);
1139
+ }
1140
+ static isEqualDate(value, valuePriorChanges) {
1141
+ const date = new Date(value);
1142
+ const datePriorChanges = new Date(valuePriorChanges);
1143
+ date.setHours(0, 0, 0, 0);
1144
+ datePriorChanges.setHours(0, 0, 0, 0);
1145
+ return LodashUtilities.isEqual(date, datePriorChanges);
1146
+ }
1147
+ static isEqualDateRange(value, valuePriorChanges, filter) {
1148
+ const dateRange = LodashUtilities.cloneDeep(value);
1149
+ dateRange.start = new Date(value.start);
1150
+ dateRange.end = new Date(value.end);
1151
+ dateRange.values = DateUtilities.getDatesBetween(dateRange.start, dateRange.end, filter);
1152
+ const dateRangePriorChanges = LodashUtilities.cloneDeep(valuePriorChanges);
1153
+ dateRangePriorChanges.start = new Date(valuePriorChanges.start);
1154
+ dateRangePriorChanges.end = new Date(valuePriorChanges.end);
1155
+ dateRangePriorChanges.values = DateUtilities.getDatesBetween(dateRangePriorChanges.start, dateRangePriorChanges.end, filter);
1156
+ return LodashUtilities.isEqual(dateRange, dateRangePriorChanges);
1157
+ }
1158
+ // TODO: Find a way to use blobs with jest
1159
+ /* istanbul ignore next */
1160
+ static async isEqualFile(value, valuePriorChanges, multiple) {
1161
+ const files = multiple ? value.sort() : [value].sort();
1162
+ const filesPriorChanges = multiple ? valuePriorChanges.sort() : [valuePriorChanges].sort();
1163
+ if (files.length !== filesPriorChanges.length) {
1164
+ return false;
1165
+ }
1166
+ for (let i = 0; i < files.length; i++) {
1167
+ // checks this before actually getting any files due to performance reasons.
1168
+ if (!LodashUtilities.isEqual(files[i]?.name, filesPriorChanges[i]?.name)
1169
+ || !LodashUtilities.isEqual(files[i]?.url, filesPriorChanges[i]?.url)) {
1170
+ return false;
1171
+ }
1172
+ files[i] = filesPriorChanges[i].file && !files[i].file ? await FileUtilities.getFileData(files[i]) : files[i];
1173
+ // eslint-disable-next-line max-len
1174
+ filesPriorChanges[i] = files[i].file && !filesPriorChanges[i].file ? await FileUtilities.getFileData(filesPriorChanges[i]) : filesPriorChanges[i];
1175
+ if (!LodashUtilities.isEqual(await files[i].file?.text(), await filesPriorChanges[i].file?.text())) {
1176
+ return false;
1177
+ }
1178
+ }
1179
+ return true;
760
1180
  }
761
1181
  /**
762
1182
  * Compare function for sorting entity keys by their order value.
@@ -778,7 +1198,7 @@ class EntityUtilities {
778
1198
  else if (metadataB.position.order === -1) {
779
1199
  return -1;
780
1200
  }
781
- return ((metadataA.position.order) - (metadataB.position.order));
1201
+ return metadataA.position.order - metadataB.position.order;
782
1202
  }
783
1203
  /**
784
1204
  * Gets the bootstrap column values for "lg", "md", "sm".
@@ -807,7 +1227,7 @@ class EntityUtilities {
807
1227
  */
808
1228
  static resetChangesOnEntity(entity, entityPriorChanges) {
809
1229
  for (const key in entityPriorChanges) {
810
- Reflect.set(entity, key, Reflect.get(entityPriorChanges, key));
1230
+ ReflectUtilities.set(entity, key, ReflectUtilities.get(entityPriorChanges, key));
811
1231
  }
812
1232
  }
813
1233
  /**
@@ -821,17 +1241,17 @@ class EntityUtilities {
821
1241
  static getEntityRows(entity, hideOmitForCreate = false, hideOmitForEdit = false) {
822
1242
  const res = [];
823
1243
  const keys = EntityUtilities.keysOf(entity, hideOmitForCreate, hideOmitForEdit);
824
- const numberOfRows = this.getNumberOfRows(keys, entity);
1244
+ const numberOfRows = EntityUtilities.getNumberOfRows(keys, entity);
825
1245
  for (let i = 1; i <= numberOfRows; i++) {
826
1246
  const row = {
827
1247
  row: i,
828
- keys: this.getKeysForRow(keys, entity, i)
1248
+ keys: EntityUtilities.getKeysForRow(keys, entity, i)
829
1249
  };
830
1250
  res.push(row);
831
1251
  }
832
1252
  const lastRow = {
833
1253
  row: numberOfRows + 1,
834
- keys: this.getKeysForRow(keys, entity, -1)
1254
+ keys: EntityUtilities.getKeysForRow(keys, entity, -1)
835
1255
  };
836
1256
  res.push(lastRow);
837
1257
  return res;
@@ -855,7 +1275,7 @@ class EntityUtilities {
855
1275
  * @returns An array of keys of the entity.
856
1276
  */
857
1277
  static keysOf(entity, hideOmitForCreate = false, hideOmitForEdit = false) {
858
- let keys = Reflect.ownKeys(entity);
1278
+ let keys = ReflectUtilities.ownKeys(entity);
859
1279
  if (hideOmitForCreate) {
860
1280
  const omitForCreateKeys = EntityUtilities.getOmitForCreate(entity);
861
1281
  keys = keys.filter(k => !omitForCreateKeys.includes(k));
@@ -909,7 +1329,54 @@ class EntityService {
909
1329
  * @returns A Promise of the created entity.
910
1330
  */
911
1331
  async create(entity) {
912
- const body = omit(entity, EntityUtilities.getOmitForCreate(entity));
1332
+ const body = LodashUtilities.omit(entity, EntityUtilities.getOmitForCreate(entity));
1333
+ const filePropertyKeys = EntityUtilities.getFileProperties(entity);
1334
+ if (!filePropertyKeys.length) {
1335
+ return await this.createWithJson(body);
1336
+ }
1337
+ else {
1338
+ return await this.createWithFormData(body, filePropertyKeys, entity);
1339
+ }
1340
+ }
1341
+ // TODO: Find a way to use blobs with jest
1342
+ /* istanbul ignore next */
1343
+ /**
1344
+ * Creates the entity with form data when the entity contains files in contrast to creating it with a normal json body.
1345
+ * All file values are stored inside their respective property key and their name.
1346
+ * Form data is able to handle setting multiple files to the same key.
1347
+ *
1348
+ * @param body - The body Of the request.
1349
+ * @param filePropertyKeys - All property keys that are files and need to be added to the form data.
1350
+ * @param entity - The entity to create. This is needed in addition to the body because the body doesn't contain any metadata.
1351
+ * @returns The created entity from the server.
1352
+ */
1353
+ async createWithFormData(body, filePropertyKeys, entity) {
1354
+ const formData = new FormData();
1355
+ formData.append('body', JSON.stringify(LodashUtilities.omit(body, filePropertyKeys)));
1356
+ for (const key of filePropertyKeys) {
1357
+ if (EntityUtilities.getPropertyMetadata(entity, key, DecoratorTypes.FILE_DEFAULT).multiple) {
1358
+ const fileDataValues = body[key];
1359
+ for (const value of fileDataValues) {
1360
+ formData.append(key, (await FileUtilities.getFileData(value)).file, value.name);
1361
+ }
1362
+ }
1363
+ else {
1364
+ const fileData = body[key];
1365
+ formData.append(key, (await FileUtilities.getFileData(fileData)).file, fileData.name);
1366
+ }
1367
+ }
1368
+ const e = await firstValueFrom(this.http.post(this.baseUrl, formData));
1369
+ this.entities.push(e);
1370
+ this.entitiesSubject.next(this.entities);
1371
+ return e;
1372
+ }
1373
+ /**
1374
+ * Creates the entity with a normal json body in contrast to creating it with form data when the entity contains files.
1375
+ *
1376
+ * @param body - The body Of the request.
1377
+ * @returns The created entity from the server.
1378
+ */
1379
+ async createWithJson(body) {
913
1380
  const e = await firstValueFrom(this.http.post(this.baseUrl, body));
914
1381
  this.entities.push(e);
915
1382
  this.entitiesSubject.next(this.entities);
@@ -934,9 +1401,57 @@ class EntityService {
934
1401
  * It Is used to get changed values and only update them instead of sending the whole entity data.
935
1402
  */
936
1403
  async update(entity, entityPriorChanges) {
937
- const reqBody = omit(EntityUtilities.difference(entity, entityPriorChanges), EntityUtilities.getOmitForUpdate(entity));
938
- const updatedEntity = await firstValueFrom(this.http.patch(`${this.baseUrl}/${entityPriorChanges[this.idKey]}`, omitBy(reqBody, isNil)));
939
- this.entities[this.entities.findIndex(e => e[this.idKey] === entityPriorChanges[this.idKey])] = updatedEntity;
1404
+ const body = LodashUtilities.omit(await EntityUtilities.difference(entity, entityPriorChanges), EntityUtilities.getOmitForUpdate(entity));
1405
+ const filePropertyKeys = EntityUtilities.getFileProperties(entityPriorChanges);
1406
+ if (!filePropertyKeys.length) {
1407
+ await this.updateWithJson(body, entityPriorChanges[this.idKey]);
1408
+ }
1409
+ else {
1410
+ await this.updateWithFormData(body, filePropertyKeys, entity, entityPriorChanges[this.idKey]);
1411
+ }
1412
+ }
1413
+ // TODO: Find a way to use blobs with jest
1414
+ /* istanbul ignore next */
1415
+ /**
1416
+ * Updates the entity with form data when the entity contains files in contrast to creating it with a normal json body.
1417
+ * All file values are stored inside their respective property key and their name.
1418
+ * Form data is able to handle setting multiple files to the same key.
1419
+ *
1420
+ * @param body - The request body. Already contains only properties that have changed.
1421
+ * @param filePropertyKeys - The keys of all properties which are files and need to separately be appended to the form data.
1422
+ * @param entity - The original entity. Is needed to get the metadata of all the files.
1423
+ * @param id - The id of the entity to update.
1424
+ */
1425
+ async updateWithFormData(body, filePropertyKeys, entity, id) {
1426
+ const formData = new FormData();
1427
+ formData.append('body', JSON.stringify(LodashUtilities.omitBy(body, LodashUtilities.isNil)));
1428
+ for (const key of filePropertyKeys) {
1429
+ if (EntityUtilities.getPropertyMetadata(entity, key, DecoratorTypes.FILE_DEFAULT).multiple) {
1430
+ // eslint-disable-next-line max-len
1431
+ const fileDataValues = body[key];
1432
+ for (const value of fileDataValues) {
1433
+ formData.append(key, (await FileUtilities.getFileData(value)).file, value.name);
1434
+ }
1435
+ }
1436
+ else {
1437
+ // eslint-disable-next-line max-len
1438
+ const fileData = body[key];
1439
+ formData.append(key, (await FileUtilities.getFileData(fileData)).file, fileData.name);
1440
+ }
1441
+ }
1442
+ const updatedEntity = await firstValueFrom(this.http.patch(`${this.baseUrl}/${id}`, formData));
1443
+ this.entities[this.entities.findIndex(e => e[this.idKey] === id)] = updatedEntity;
1444
+ this.entitiesSubject.next(this.entities);
1445
+ }
1446
+ /**
1447
+ * Updates the entity with a normal json body in contrast to updating it with form data when the entity contains files.
1448
+ *
1449
+ * @param body - The body of the Request. Has already removed all unnecessary values.
1450
+ * @param id - The id of the entity to update.
1451
+ */
1452
+ async updateWithJson(body, id) {
1453
+ const updatedEntity = await firstValueFrom(this.http.patch(`${this.baseUrl}/${id}`, LodashUtilities.omitBy(body, LodashUtilities.isNil)));
1454
+ this.entities[this.entities.findIndex(e => e[this.idKey] === id)] = updatedEntity;
940
1455
  this.entitiesSubject.next(this.entities);
941
1456
  }
942
1457
  /**
@@ -971,7 +1486,6 @@ class BaseBuilder {
971
1486
  validateInput(data) {
972
1487
  // By default, no validation is done
973
1488
  }
974
- ;
975
1489
  /**
976
1490
  * Sets the value for the given key if no user value was provided.
977
1491
  *
@@ -980,7 +1494,7 @@ class BaseBuilder {
980
1494
  * @returns The Builder.
981
1495
  */
982
1496
  withDefault(key, value) {
983
- if (!this.inputData || !this.inputData[key]) {
1497
+ if (this.inputData == null || this.inputData[key] == null) {
984
1498
  this.data[key] = value;
985
1499
  }
986
1500
  return this;
@@ -1018,18 +1532,18 @@ class ConfirmDialogDataBuilder extends BaseBuilder {
1018
1532
  }
1019
1533
  // eslint-disable-next-line jsdoc/require-jsdoc
1020
1534
  generateBaseData(data) {
1021
- return new ConfirmDialogDataInternal(data?.text ? data.text : ['Do you really want to do this?'], data?.type ? data.type : 'default', data?.confirmButtonLabel ? data.confirmButtonLabel : 'Confirm', data?.cancelButtonLabel ? data.cancelButtonLabel : 'Cancel', data?.title ? data.title : 'Confirmation', data?.requireConfirmation ? data.requireConfirmation : false, data?.confirmationText);
1535
+ return new ConfirmDialogDataInternal(data?.text ?? ['Do you really want to do this?'], data?.type ?? 'default', data?.confirmButtonLabel ?? 'Confirm', data?.cancelButtonLabel ?? 'Cancel', data?.title ?? 'Confirmation', data?.requireConfirmation ?? false, data?.confirmationText);
1022
1536
  }
1023
1537
  // eslint-disable-next-line jsdoc/require-jsdoc
1024
1538
  validateInput(data) {
1025
1539
  if (!data) {
1026
1540
  return;
1027
1541
  }
1028
- if (data.requireConfirmation && !data.confirmationText) {
1542
+ if (data.requireConfirmation === true && !data.confirmationText) {
1029
1543
  throw new Error(`Missing required Input data "confirmationText".
1030
1544
  You can only omit this value when "requireConfirmation" is false.`);
1031
1545
  }
1032
- if (!data.requireConfirmation && data.confirmationText) {
1546
+ if (data.requireConfirmation !== true && data.confirmationText) {
1033
1547
  throw new Error('The "confirmationText" will never be shown because "requireConfirmation" is not set to true');
1034
1548
  }
1035
1549
  if (data.type === 'info-only' && data.cancelButtonLabel) {
@@ -1067,10 +1581,10 @@ class NgxMatEntityConfirmDialogComponent {
1067
1581
  }
1068
1582
  }
1069
1583
  NgxMatEntityConfirmDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityConfirmDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
1070
- NgxMatEntityConfirmDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityConfirmDialogComponent, selector: "ngx-mat-entity-confirm-dialog", ngImport: i0, template: "<h2 mat-dialog-title *ngIf=\"data.title\">{{data.title}}</h2>\n\n<mat-dialog-content>\n <p *ngFor=\"let paragraph of data.text\">{{paragraph}}</p>\n <div *ngIf=\"data.requireConfirmation\" class=\"checkbox-wrapper\">\n <mat-checkbox [(ngModel)]=\"confirm\" name=\"confirm\">\n {{data.confirmationText}}\n </mat-checkbox>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button *ngIf=\"data.type === 'delete'\" mat-raised-button color=\"warn\" (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button *ngIf=\"data.type !== 'delete'\" mat-raised-button (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: [".checkbox-wrapper{min-height:50px;display:flex}.checkbox-wrapper>mat-checkbox{align-self:center}mat-dialog-actions{display:flex;justify-content:space-between}\n"], components: [{ type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i3.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i12.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i12.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }] });
1584
+ NgxMatEntityConfirmDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityConfirmDialogComponent, selector: "ngx-mat-entity-confirm-dialog", ngImport: i0, template: "<h2 mat-dialog-title *ngIf=\"data.title\">{{data.title}}</h2>\n\n<mat-dialog-content>\n <p *ngFor=\"let paragraph of data.text\">{{paragraph}}</p>\n <div *ngIf=\"data.requireConfirmation\" class=\"checkbox-wrapper\">\n <mat-checkbox [(ngModel)]=\"confirm\" name=\"confirm\">\n {{data.confirmationText}}\n </mat-checkbox>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button *ngIf=\"data.type === 'delete'\" mat-raised-button color=\"warn\" (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button *ngIf=\"data.type !== 'delete'\" mat-raised-button (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button *ngIf=\"data.type !== 'info-only'\" mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: [".checkbox-wrapper{min-height:50px;display:flex}.checkbox-wrapper>mat-checkbox{align-self:center}mat-dialog-actions{display:flex;justify-content:space-between}\n"], components: [{ type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i4.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }] });
1071
1585
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityConfirmDialogComponent, decorators: [{
1072
1586
  type: Component,
1073
- args: [{ selector: 'ngx-mat-entity-confirm-dialog', template: "<h2 mat-dialog-title *ngIf=\"data.title\">{{data.title}}</h2>\n\n<mat-dialog-content>\n <p *ngFor=\"let paragraph of data.text\">{{paragraph}}</p>\n <div *ngIf=\"data.requireConfirmation\" class=\"checkbox-wrapper\">\n <mat-checkbox [(ngModel)]=\"confirm\" name=\"confirm\">\n {{data.confirmationText}}\n </mat-checkbox>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button *ngIf=\"data.type === 'delete'\" mat-raised-button color=\"warn\" (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button *ngIf=\"data.type !== 'delete'\" mat-raised-button (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: [".checkbox-wrapper{min-height:50px;display:flex}.checkbox-wrapper>mat-checkbox{align-self:center}mat-dialog-actions{display:flex;justify-content:space-between}\n"] }]
1587
+ args: [{ selector: 'ngx-mat-entity-confirm-dialog', template: "<h2 mat-dialog-title *ngIf=\"data.title\">{{data.title}}</h2>\n\n<mat-dialog-content>\n <p *ngFor=\"let paragraph of data.text\">{{paragraph}}</p>\n <div *ngIf=\"data.requireConfirmation\" class=\"checkbox-wrapper\">\n <mat-checkbox [(ngModel)]=\"confirm\" name=\"confirm\">\n {{data.confirmationText}}\n </mat-checkbox>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button *ngIf=\"data.type === 'delete'\" mat-raised-button color=\"warn\" (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button *ngIf=\"data.type !== 'delete'\" mat-raised-button (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button *ngIf=\"data.type !== 'info-only'\" mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: [".checkbox-wrapper{min-height:50px;display:flex}.checkbox-wrapper>mat-checkbox{align-self:center}mat-dialog-actions{display:flex;justify-content:space-between}\n"] }]
1074
1588
  }], ctorParameters: function () { return [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{
1075
1589
  type: Inject,
1076
1590
  args: [MAT_DIALOG_DATA]
@@ -1153,7 +1667,7 @@ class CreateDialogDataBuilder extends BaseBuilder {
1153
1667
  .withDefault('text', ['Do you really want to create this entity?'])
1154
1668
  .withDefault('title', 'Create')
1155
1669
  .getResult();
1156
- return new CreateDialogDataInternal(data?.title ? data.title : 'Create', data?.createButtonLabel ? data.createButtonLabel : 'Create', data?.cancelButtonLabel ? data.cancelButtonLabel : 'Cancel', data?.createRequiresConfirmDialog ? data.createRequiresConfirmDialog : false, confirmCreateDialogData);
1670
+ return new CreateDialogDataInternal(data?.title ?? 'Create', data?.createButtonLabel ?? 'Create', data?.cancelButtonLabel ?? 'Cancel', data?.createRequiresConfirmDialog ?? false, confirmCreateDialogData);
1157
1671
  }
1158
1672
  }
1159
1673
 
@@ -1180,181 +1694,1440 @@ class AddArrayItemDialogDataBuilder extends BaseBuilder {
1180
1694
  .withDefault('createButtonLabel', 'Add')
1181
1695
  .withDefault('title', 'Add to array')
1182
1696
  .getResult();
1183
- return new AddArrayItemDialogDataInternal(data.entity, createDialogData, data.getValidationErrorMessage ? data.getValidationErrorMessage : getValidationErrorMessage);
1697
+ return new AddArrayItemDialogDataInternal(data.entity, createDialogData, data.getValidationErrorMessage ?? getValidationErrorMessage);
1184
1698
  }
1185
1699
  }
1186
1700
 
1187
- /**
1188
- * The default input component. It gets the metadata of the property from the given @Input "entity" and @Input "propertyKey"
1189
- * and displays the input field accordingly.
1190
- *
1191
- * You can also define a method that generates error-messages and if the input should be hidden when its metadata says
1192
- * that it should be omitted for creating or updating.
1193
- * The last part being mostly relevant if you want to use this component inside an ngFor.
1194
- */
1195
- class NgxMatEntityInputComponent {
1196
- constructor(dialog) {
1197
- this.dialog = dialog;
1198
- this.chipsInput = '';
1199
- this.selection = new SelectionModel(true, []);
1200
- this.DecoratorTypes = DecoratorTypes;
1201
- this.EntityUtilities = EntityUtilities;
1202
- this.DateUtilities = DateUtilities;
1203
- this.defaultDateFilter = () => true;
1204
- }
1205
- /**
1206
- * This is needed for the inputs to work inside an ngFor.
1207
- *
1208
- * @param index - The index of the element in the ngFor.
1209
- * @returns The index.
1210
- */
1211
- trackByFn(index) {
1212
- return index;
1701
+ /* eslint-disable jsdoc/require-jsdoc */
1702
+ class StringInputComponent {
1703
+ constructor() {
1704
+ this.inputChangeEvent = new EventEmitter();
1213
1705
  }
1214
1706
  ngOnInit() {
1215
- if (!this.entity) {
1707
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.STRING);
1708
+ }
1709
+ emitChange() {
1710
+ this.inputChangeEvent.emit();
1711
+ }
1712
+ }
1713
+ StringInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1714
+ StringInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: StringInputComponent, selector: "string-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[key]\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [pattern]=\"metadata.regex ?? '[\\\\s\\\\S]*'\"\n [minlength]=\"metadata.minLength ?? null\"\n [maxlength]=\"metadata.maxLength ?? null\"\n (ngModelChange)=\"emitChange()\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i3.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i3.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i3.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
1715
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringInputComponent, decorators: [{
1716
+ type: Component,
1717
+ args: [{ selector: 'string-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[key]\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [pattern]=\"metadata.regex ?? '[\\\\s\\\\S]*'\"\n [minlength]=\"metadata.minLength ?? null\"\n [maxlength]=\"metadata.maxLength ?? null\"\n (ngModelChange)=\"emitChange()\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
1718
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
1719
+ type: Input
1720
+ }], key: [{
1721
+ type: Input
1722
+ }], getValidationErrorMessage: [{
1723
+ type: Input
1724
+ }], inputChangeEvent: [{
1725
+ type: Output
1726
+ }] } });
1727
+
1728
+ /* eslint-disable jsdoc/require-jsdoc */
1729
+ class StringTextboxInputComponent {
1730
+ constructor() {
1731
+ this.inputChangeEvent = new EventEmitter();
1732
+ }
1733
+ ngOnInit() {
1734
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.STRING_TEXTBOX);
1735
+ }
1736
+ emitChange() {
1737
+ this.inputChangeEvent.emit();
1738
+ }
1739
+ }
1740
+ StringTextboxInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringTextboxInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1741
+ StringTextboxInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: StringTextboxInputComponent, selector: "string-textbox-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <textarea\n matInput\n [(ngModel)]=\"entity[key]\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"10\"\n [required]=\"metadata.required\"\n [minlength]=\"metadata.minLength ?? null\"\n [maxlength]=\"metadata.maxLength ?? null\"\n (ngModelChange)=\"emitChange()\"\n >\n </textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i3$1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i3.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i3.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
1742
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringTextboxInputComponent, decorators: [{
1743
+ type: Component,
1744
+ args: [{ selector: 'string-textbox-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <textarea\n matInput\n [(ngModel)]=\"entity[key]\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"10\"\n [required]=\"metadata.required\"\n [minlength]=\"metadata.minLength ?? null\"\n [maxlength]=\"metadata.maxLength ?? null\"\n (ngModelChange)=\"emitChange()\"\n >\n </textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
1745
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
1746
+ type: Input
1747
+ }], key: [{
1748
+ type: Input
1749
+ }], getValidationErrorMessage: [{
1750
+ type: Input
1751
+ }], inputChangeEvent: [{
1752
+ type: Output
1753
+ }] } });
1754
+
1755
+ /* eslint-disable jsdoc/require-jsdoc */
1756
+ class StringAutocompleteInputComponent {
1757
+ constructor() {
1758
+ this.inputChangeEvent = new EventEmitter();
1759
+ }
1760
+ ngOnInit() {
1761
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.STRING_AUTOCOMPLETE);
1762
+ this.autocompleteStrings = this.metadata.autocompleteValues;
1763
+ this.filteredAutocompleteStrings = LodashUtilities.cloneDeep(this.autocompleteStrings);
1764
+ }
1765
+ /**
1766
+ * Dynamically filters the Autocomplete options when the user inputs something.
1767
+ *
1768
+ * @param input - The input of the user.
1769
+ */
1770
+ filterAutocompleteStrings(input) {
1771
+ const inputString = input;
1772
+ if (inputString) {
1773
+ const filterValue = inputString.toLowerCase();
1774
+ this.filteredAutocompleteStrings = this.autocompleteStrings.filter(s => s.toLowerCase().includes(filterValue));
1775
+ }
1776
+ }
1777
+ emitChange() {
1778
+ this.inputChangeEvent.emit();
1779
+ }
1780
+ }
1781
+ StringAutocompleteInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringAutocompleteInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1782
+ StringAutocompleteInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: StringAutocompleteInputComponent, selector: "string-autocomplete-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[key]\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matAutocomplete]=\"auto\"\n (keyup)=\"filterAutocompleteStrings(entity[key])\"\n [required]=\"metadata.required\"\n [minlength]=\"metadata.minLength ?? null\"\n [maxlength]=\"metadata.maxLength ?? null\"\n [pattern]=\"metadata.regex ?? '[\\\\s\\\\S]*'\"\n (ngModelChange)=\"emitChange()\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2.MatAutocomplete, selector: "mat-autocomplete", inputs: ["disableRipple"], exportAs: ["matAutocomplete"] }, { type: i3$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i2.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", exportAs: ["matAutocompleteTrigger"] }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i3.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i3.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i3.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
1783
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringAutocompleteInputComponent, decorators: [{
1784
+ type: Component,
1785
+ args: [{ selector: 'string-autocomplete-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[key]\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matAutocomplete]=\"auto\"\n (keyup)=\"filterAutocompleteStrings(entity[key])\"\n [required]=\"metadata.required\"\n [minlength]=\"metadata.minLength ?? null\"\n [maxlength]=\"metadata.maxLength ?? null\"\n [pattern]=\"metadata.regex ?? '[\\\\s\\\\S]*'\"\n (ngModelChange)=\"emitChange()\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
1786
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
1787
+ type: Input
1788
+ }], key: [{
1789
+ type: Input
1790
+ }], getValidationErrorMessage: [{
1791
+ type: Input
1792
+ }], inputChangeEvent: [{
1793
+ type: Output
1794
+ }] } });
1795
+
1796
+ /* eslint-disable jsdoc/require-jsdoc */
1797
+ class StringDropdownInputComponent {
1798
+ constructor() {
1799
+ this.inputChangeEvent = new EventEmitter();
1800
+ }
1801
+ ngOnInit() {
1802
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.STRING_DROPDOWN);
1803
+ }
1804
+ emitChange() {
1805
+ this.inputChangeEvent.emit();
1806
+ }
1807
+ }
1808
+ StringDropdownInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringDropdownInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1809
+ StringDropdownInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: StringDropdownInputComponent, selector: "string-dropdown-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select (ngModelChange)=\"emitChange()\" [(ngModel)]=\"entity[key]\" [name]=\"key.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadata.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2$1.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i3$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
1810
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringDropdownInputComponent, decorators: [{
1811
+ type: Component,
1812
+ args: [{ selector: 'string-dropdown-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select (ngModelChange)=\"emitChange()\" [(ngModel)]=\"entity[key]\" [name]=\"key.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadata.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
1813
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
1814
+ type: Input
1815
+ }], key: [{
1816
+ type: Input
1817
+ }], getValidationErrorMessage: [{
1818
+ type: Input
1819
+ }], inputChangeEvent: [{
1820
+ type: Output
1821
+ }] } });
1822
+
1823
+ /* eslint-disable jsdoc/require-jsdoc */
1824
+ class BooleanCheckboxInputComponent {
1825
+ constructor() {
1826
+ this.inputChangeEvent = new EventEmitter();
1827
+ }
1828
+ ngOnInit() {
1829
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.BOOLEAN_CHECKBOX);
1830
+ if (this.entity[this.key] == null) {
1831
+ this.entity[this.key] = false;
1832
+ }
1833
+ }
1834
+ emitChange() {
1835
+ this.inputChangeEvent.emit();
1836
+ }
1837
+ }
1838
+ BooleanCheckboxInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanCheckboxInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1839
+ BooleanCheckboxInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: BooleanCheckboxInputComponent, selector: "boolean-checkbox-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-checkbox (ngModelChange)=\"emitChange()\" (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[key]\" [name]=\"key.toString()\"></mat-checkbox>\n <!-- hidden input is needed so that the checkbox can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[key]\"\n [name]=\"key.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\">\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["::ng-deep .hideUnderline .mat-form-field-underline{opacity:0%}mat-form-field{width:100%}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
1840
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanCheckboxInputComponent, decorators: [{
1841
+ type: Component,
1842
+ args: [{ selector: 'boolean-checkbox-input', template: "<mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-checkbox (ngModelChange)=\"emitChange()\" (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[key]\" [name]=\"key.toString()\"></mat-checkbox>\n <!-- hidden input is needed so that the checkbox can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[key]\"\n [name]=\"key.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\">\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["::ng-deep .hideUnderline .mat-form-field-underline{opacity:0%}mat-form-field{width:100%}\n"] }]
1843
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
1844
+ type: Input
1845
+ }], key: [{
1846
+ type: Input
1847
+ }], getValidationErrorMessage: [{
1848
+ type: Input
1849
+ }], inputChangeEvent: [{
1850
+ type: Output
1851
+ }] } });
1852
+
1853
+ /* eslint-disable jsdoc/require-jsdoc */
1854
+ class BooleanToggleInputComponent {
1855
+ constructor() {
1856
+ this.inputChangeEvent = new EventEmitter();
1857
+ }
1858
+ ngOnInit() {
1859
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.BOOLEAN_TOGGLE);
1860
+ if (this.entity[this.key] == null) {
1861
+ this.entity[this.key] = false;
1862
+ }
1863
+ }
1864
+ emitChange() {
1865
+ this.inputChangeEvent.emit();
1866
+ }
1867
+ }
1868
+ BooleanToggleInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanToggleInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1869
+ BooleanToggleInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: BooleanToggleInputComponent, selector: "boolean-toggle-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-slide-toggle (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[key]\" [name]=\"key.toString()\"></mat-slide-toggle>\n <!-- hidden input is needed so that the toggle can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[key]\"\n [name]=\"key.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\"\n (ngModelChange)=\"emitChange\"\n >\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["::ng-deep .hideUnderline .mat-form-field-underline{opacity:0%}mat-form-field{width:100%}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2$2.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex", "name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "checked"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
1870
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanToggleInputComponent, decorators: [{
1871
+ type: Component,
1872
+ args: [{ selector: 'boolean-toggle-input', template: "<mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-slide-toggle (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[key]\" [name]=\"key.toString()\"></mat-slide-toggle>\n <!-- hidden input is needed so that the toggle can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[key]\"\n [name]=\"key.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\"\n (ngModelChange)=\"emitChange\"\n >\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["::ng-deep .hideUnderline .mat-form-field-underline{opacity:0%}mat-form-field{width:100%}\n"] }]
1873
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
1874
+ type: Input
1875
+ }], key: [{
1876
+ type: Input
1877
+ }], getValidationErrorMessage: [{
1878
+ type: Input
1879
+ }], inputChangeEvent: [{
1880
+ type: Output
1881
+ }] } });
1882
+
1883
+ /* eslint-disable jsdoc/require-jsdoc */
1884
+ class BooleanDropdownInputComponent {
1885
+ constructor() {
1886
+ this.inputChangeEvent = new EventEmitter();
1887
+ }
1888
+ ngOnInit() {
1889
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.BOOLEAN_DROPDOWN);
1890
+ }
1891
+ emitChange() {
1892
+ this.inputChangeEvent.emit();
1893
+ }
1894
+ }
1895
+ BooleanDropdownInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanDropdownInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1896
+ BooleanDropdownInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: BooleanDropdownInputComponent, selector: "boolean-dropdown-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select (ngModelChange)=\"emitChange()\" [(ngModel)]=\"entity[key]\" [name]=\"key.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option [value]=\"undefined\">-</mat-option>\n <mat-option [value]=\"true\">{{metadata.dropdownTrue}}</mat-option>\n <mat-option [value]=\"false\">{{metadata.dropdownFalse}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2$1.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i3$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
1897
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanDropdownInputComponent, decorators: [{
1898
+ type: Component,
1899
+ args: [{ selector: 'boolean-dropdown-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select (ngModelChange)=\"emitChange()\" [(ngModel)]=\"entity[key]\" [name]=\"key.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option [value]=\"undefined\">-</mat-option>\n <mat-option [value]=\"true\">{{metadata.dropdownTrue}}</mat-option>\n <mat-option [value]=\"false\">{{metadata.dropdownFalse}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
1900
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
1901
+ type: Input
1902
+ }], key: [{
1903
+ type: Input
1904
+ }], getValidationErrorMessage: [{
1905
+ type: Input
1906
+ }], inputChangeEvent: [{
1907
+ type: Output
1908
+ }] } });
1909
+
1910
+ /* eslint-disable jsdoc/require-jsdoc */
1911
+ class NumberInputComponent {
1912
+ constructor() {
1913
+ this.inputChangeEvent = new EventEmitter();
1914
+ }
1915
+ ngOnInit() {
1916
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.NUMBER);
1917
+ }
1918
+ emitChange() {
1919
+ this.inputChangeEvent.emit();
1920
+ }
1921
+ }
1922
+ NumberInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1923
+ NumberInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NumberInputComponent, selector: "number-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n type=\"number\"\n [(ngModel)]=\"entity[key]\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadata.min ?? null\"\n [max]=\"metadata.max ?? null\"\n (ngModelChange)=\"emitChange()\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { type: i3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { type: i3.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
1924
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberInputComponent, decorators: [{
1925
+ type: Component,
1926
+ args: [{ selector: 'number-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n type=\"number\"\n [(ngModel)]=\"entity[key]\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadata.min ?? null\"\n [max]=\"metadata.max ?? null\"\n (ngModelChange)=\"emitChange()\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
1927
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
1928
+ type: Input
1929
+ }], key: [{
1930
+ type: Input
1931
+ }], getValidationErrorMessage: [{
1932
+ type: Input
1933
+ }], inputChangeEvent: [{
1934
+ type: Output
1935
+ }] } });
1936
+
1937
+ /* eslint-disable jsdoc/require-jsdoc */
1938
+ class NumberDropdownInputComponent {
1939
+ constructor() {
1940
+ this.inputChangeEvent = new EventEmitter();
1941
+ }
1942
+ ngOnInit() {
1943
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.NUMBER_DROPDOWN);
1944
+ }
1945
+ emitChange() {
1946
+ this.inputChangeEvent.emit();
1947
+ }
1948
+ }
1949
+ NumberDropdownInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberDropdownInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1950
+ NumberDropdownInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NumberDropdownInputComponent, selector: "number-dropdown-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select (ngModelChange)=\"emitChange()\" [(ngModel)]=\"entity[key]\" [name]=\"key.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadata.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2$1.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i3$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
1951
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberDropdownInputComponent, decorators: [{
1952
+ type: Component,
1953
+ args: [{ selector: 'number-dropdown-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select (ngModelChange)=\"emitChange()\" [(ngModel)]=\"entity[key]\" [name]=\"key.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadata.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
1954
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
1955
+ type: Input
1956
+ }], key: [{
1957
+ type: Input
1958
+ }], getValidationErrorMessage: [{
1959
+ type: Input
1960
+ }], inputChangeEvent: [{
1961
+ type: Output
1962
+ }] } });
1963
+
1964
+ /* eslint-disable jsdoc/require-jsdoc */
1965
+ /**
1966
+ * The base data needed for all arrays that are displayed as a table.
1967
+ */
1968
+ class ArrayTable {
1969
+ constructor(matDialog) {
1970
+ this.matDialog = matDialog;
1971
+ this.input = undefined;
1972
+ this.dataSource = new MatTableDataSource();
1973
+ this.selection = new SelectionModel(true, []);
1974
+ }
1975
+ init() {
1976
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key);
1977
+ if (this.entity[this.key] == null) {
1978
+ this.entity[this.key] = [];
1979
+ }
1980
+ this.arrayValues = this.entity[this.key];
1981
+ const givenDisplayColumns = this.metadata.displayColumns.map((v) => v.displayName);
1982
+ if (givenDisplayColumns.find(s => s === 'select')) {
1983
+ throw new Error(`The name "select" for a display column is reserved.
1984
+ Please choose a different name.`);
1985
+ }
1986
+ this.displayedColumns = ['select'].concat(givenDisplayColumns);
1987
+ this.dataSource.data = this.arrayValues;
1988
+ }
1989
+ /**
1990
+ * Toggles all array-items in the table.
1991
+ *
1992
+ */
1993
+ masterToggle() {
1994
+ if (this.isAllSelected()) {
1995
+ this.selection.clear();
1996
+ }
1997
+ else {
1998
+ this.dataSource.data.forEach(row => this.selection.select(row));
1999
+ }
2000
+ }
2001
+ /**
2002
+ * Checks if all array-items in the table have been selected.
2003
+ * This is needed to display the "masterToggle"-checkbox correctly.
2004
+ *
2005
+ * @returns Whether or not all array-items in the table have been selected.
2006
+ */
2007
+ isAllSelected() {
2008
+ const numSelected = this.selection.selected.length;
2009
+ const numRows = this.dataSource.data.length;
2010
+ return numSelected === numRows;
2011
+ }
2012
+ /**
2013
+ * Tries to add an item to the array.
2014
+ */
2015
+ add() {
2016
+ if (this.input != null) {
2017
+ if (!this.metadata.allowDuplicates
2018
+ && this.arrayValues.find(async (v) => await EntityUtilities.isEqual(this.input, v, this.metadata, this.metadata.itemType)) != null) {
2019
+ this.matDialog.open(NgxMatEntityConfirmDialogComponent, {
2020
+ data: this.metadata.duplicatesErrorDialog,
2021
+ autoFocus: false,
2022
+ restoreFocus: false
2023
+ });
2024
+ return;
2025
+ }
2026
+ this.arrayValues.push(LodashUtilities.cloneDeep(this.input));
2027
+ this.dataSource.data = this.arrayValues;
2028
+ this.resetInput();
2029
+ this.emitChange();
2030
+ }
2031
+ }
2032
+ /**
2033
+ * Is split up from the add method to override this functionality more easily.
2034
+ */
2035
+ resetInput() {
2036
+ this.input = undefined;
2037
+ }
2038
+ /**
2039
+ * Removes all selected entries from the entity array.
2040
+ */
2041
+ remove() {
2042
+ this.selection.selected.forEach(s => {
2043
+ this.arrayValues.splice(this.arrayValues.indexOf(s), 1);
2044
+ });
2045
+ this.dataSource.data = this.arrayValues;
2046
+ this.selection.clear();
2047
+ this.emitChange();
2048
+ }
2049
+ }
2050
+
2051
+ /* eslint-disable jsdoc/require-jsdoc */
2052
+ class ArrayDateInputComponent extends ArrayTable {
2053
+ constructor(dialog) {
2054
+ super(dialog);
2055
+ this.dialog = dialog;
2056
+ this.DateUtilities = DateUtilities;
2057
+ this.inputChangeEvent = new EventEmitter();
2058
+ }
2059
+ ngOnInit() {
2060
+ this.init();
2061
+ }
2062
+ emitChange() {
2063
+ this.inputChangeEvent.emit();
2064
+ }
2065
+ }
2066
+ ArrayDateInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateInputComponent, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
2067
+ ArrayDateInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: ArrayDateInputComponent, selector: "array-date-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, usesInheritance: true, ngImport: i0, template: "<div class=\"mat-elevation-z8\" style=\"border-radius: 5px;padding: 15px;margin-bottom: 15px;margin-top: 15px;\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"input\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadata.min ? metadata.min(input) : undefined\"\n [max]=\"metadata.max ? metadata.max(input) : undefined\"\n [matDatepickerFilter]=\"metadata.filter ?? DateUtilities.defaultDateFilter\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n \n <div class=\"buttons\">\n <button mat-raised-button\n [disabled]=\"model.errors\"\n (click)=\"add()\">\n {{metadata.addButtonLabel}}\n </button>\n <button mat-raised-button\n [disabled]=\"!selection.selected.length\"\n (click)=\"remove()\">\n {{metadata.removeButtonLabel}}\n </button>\n </div>\n\n <mat-table [dataSource]=\"dataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"></mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"></mat-checkbox>\n </mat-cell>\n </ng-container>\n \n <ng-container *ngFor=\"let dCol of metadata.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n\n <div class=\"array-error\" *ngIf=\"metadata.required && !dataSource.data.length\">\n {{metadata.missingErrorMessage}}\n </div>\n</div>", styles: ["mat-form-field{width:100%}.buttons{display:flex;justify-content:space-between;margin-bottom:10px;margin-top:5px}mat-table{border:1px solid #E0E0E0;border-radius:5px;padding-top:5px;padding-bottom:25px}.mat-column-select{flex:0 0 75px}.array-error{display:flex;align-items:center;justify-content:center;margin-top:-25.8px;border:1px solid #E0E0E0;background-color:#f8d3d7;color:#721c24;height:25.8px;border-bottom-left-radius:5px;border-bottom-right-radius:5px}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i3$3.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i3$3.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { type: i4.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3$3.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i1$1.MatSuffix, selector: "[matSuffix]" }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }, { type: i5.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i5.MatCellDef, selector: "[matCellDef]" }, { type: i5.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i5.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
2068
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateInputComponent, decorators: [{
2069
+ type: Component,
2070
+ args: [{ selector: 'array-date-input', template: "<div class=\"mat-elevation-z8\" style=\"border-radius: 5px;padding: 15px;margin-bottom: 15px;margin-top: 15px;\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"input\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadata.min ? metadata.min(input) : undefined\"\n [max]=\"metadata.max ? metadata.max(input) : undefined\"\n [matDatepickerFilter]=\"metadata.filter ?? DateUtilities.defaultDateFilter\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n \n <div class=\"buttons\">\n <button mat-raised-button\n [disabled]=\"model.errors\"\n (click)=\"add()\">\n {{metadata.addButtonLabel}}\n </button>\n <button mat-raised-button\n [disabled]=\"!selection.selected.length\"\n (click)=\"remove()\">\n {{metadata.removeButtonLabel}}\n </button>\n </div>\n\n <mat-table [dataSource]=\"dataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"></mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"></mat-checkbox>\n </mat-cell>\n </ng-container>\n \n <ng-container *ngFor=\"let dCol of metadata.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n\n <div class=\"array-error\" *ngIf=\"metadata.required && !dataSource.data.length\">\n {{metadata.missingErrorMessage}}\n </div>\n</div>", styles: ["mat-form-field{width:100%}.buttons{display:flex;justify-content:space-between;margin-bottom:10px;margin-top:5px}mat-table{border:1px solid #E0E0E0;border-radius:5px;padding-top:5px;padding-bottom:25px}.mat-column-select{flex:0 0 75px}.array-error{display:flex;align-items:center;justify-content:center;margin-top:-25.8px;border:1px solid #E0E0E0;background-color:#f8d3d7;color:#721c24;height:25.8px;border-bottom-left-radius:5px;border-bottom-right-radius:5px}\n"] }]
2071
+ }], ctorParameters: function () { return [{ type: i1.MatDialog }]; }, propDecorators: { entity: [{
2072
+ type: Input
2073
+ }], key: [{
2074
+ type: Input
2075
+ }], getValidationErrorMessage: [{
2076
+ type: Input
2077
+ }], inputChangeEvent: [{
2078
+ type: Output
2079
+ }] } });
2080
+
2081
+ /* eslint-disable jsdoc/require-jsdoc */
2082
+ class ArrayDateTimeInputComponent extends ArrayTable {
2083
+ constructor(dialog) {
2084
+ super(dialog);
2085
+ this.dialog = dialog;
2086
+ this.DateUtilities = DateUtilities;
2087
+ this.inputChangeEvent = new EventEmitter();
2088
+ }
2089
+ ngOnInit() {
2090
+ this.init();
2091
+ this.time = DateUtilities.getTimeFromDate(this.entity[this.key]);
2092
+ this.timeDropdownValues = this.metadata.times;
2093
+ if (this.entity[this.key] != null) {
2094
+ this.dateTime = new Date(this.entity[this.key]);
2095
+ }
2096
+ }
2097
+ resetInput() {
2098
+ this.input = undefined;
2099
+ this.time = undefined;
2100
+ }
2101
+ /**
2102
+ * Adds a date time to the array.
2103
+ */
2104
+ addDateTime() {
2105
+ if (this.input && this.time) {
2106
+ this.input = new Date(this.input);
2107
+ this.input.setHours(this.time.hours, this.time.minutes, 0, 0);
2108
+ this.add();
2109
+ }
2110
+ }
2111
+ emitChange() {
2112
+ this.inputChangeEvent.emit();
2113
+ }
2114
+ }
2115
+ ArrayDateTimeInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateTimeInputComponent, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
2116
+ ArrayDateTimeInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: ArrayDateTimeInputComponent, selector: "array-date-time-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, usesInheritance: true, ngImport: i0, template: "<div class=\"mat-elevation-z8\" style=\"border-radius: 5px;padding: 15px;margin-bottom: 15px;margin-top: 15px;\">\n \n <div class=\"date-time\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"input\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadata.minDate ? metadata.minDate(input) : undefined\"\n [max]=\"metadata.maxDate ? metadata.maxDate(input) : undefined\"\n [matDatepickerFilter]=\"metadata.filterDate ?? DateUtilities.defaultDateFilter\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n <mat-form-field class=\"timepicker\">\n <mat-label>{{metadata.timeDisplayName}}</mat-label>\n <mat-select\n [(ngModel)]=\"time\"\n [name]=\"key.toString() + 'time'\"\n #timeModel=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-option *ngFor=\"let validTime of DateUtilities.getValidTimesForDropdown(\n DateUtilities.asDate(input),\n metadata.times,\n metadata.minTime,\n metadata.maxTime,\n metadata.filterTime\n )\"\n [value]=\"validTime.value\"\n >\n {{validTime.displayName}}\n </mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(timeModel)}}</mat-error>\n </mat-form-field>\n </div>\n <div class=\"buttons\">\n <button mat-raised-button\n [disabled]=\"model.errors || timeModel.errors || DateUtilities.timeIsUnprocessable(time)\"\n (click)=\"addDateTime()\">\n {{metadata.addButtonLabel}}\n </button>\n <button mat-raised-button\n [disabled]=\"!selection.selected.length\"\n (click)=\"remove()\">\n {{metadata.removeButtonLabel}}\n </button>\n </div>\n\n <mat-table [dataSource]=\"dataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"></mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"></mat-checkbox>\n </mat-cell>\n </ng-container>\n \n <ng-container *ngFor=\"let dCol of metadata.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n\n <div class=\"array-error\" *ngIf=\"metadata.required && !dataSource.data.length\">\n {{metadata.missingErrorMessage}}\n </div>\n</div>", styles: ["mat-form-field{width:100%}.buttons{display:flex;justify-content:space-between;margin-bottom:10px;margin-top:5px}mat-table{border:1px solid #E0E0E0;border-radius:5px;padding-top:5px;padding-bottom:25px}.mat-column-select{flex:0 0 75px}.array-error{display:flex;align-items:center;justify-content:center;margin-top:-25.8px;border:1px solid #E0E0E0;background-color:#f8d3d7;color:#721c24;height:25.8px;border-bottom-left-radius:5px;border-bottom-right-radius:5px}.date-time{display:flex;align-items:baseline}.date-time .timepicker{margin-left:10px}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i3$3.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i3$3.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { type: i2$1.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i3$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { type: i4.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3$3.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i1$1.MatSuffix, selector: "[matSuffix]" }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i5.MatCellDef, selector: "[matCellDef]" }, { type: i5.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i5.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i5.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
2117
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateTimeInputComponent, decorators: [{
2118
+ type: Component,
2119
+ args: [{ selector: 'array-date-time-input', template: "<div class=\"mat-elevation-z8\" style=\"border-radius: 5px;padding: 15px;margin-bottom: 15px;margin-top: 15px;\">\n \n <div class=\"date-time\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"input\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadata.minDate ? metadata.minDate(input) : undefined\"\n [max]=\"metadata.maxDate ? metadata.maxDate(input) : undefined\"\n [matDatepickerFilter]=\"metadata.filterDate ?? DateUtilities.defaultDateFilter\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n <mat-form-field class=\"timepicker\">\n <mat-label>{{metadata.timeDisplayName}}</mat-label>\n <mat-select\n [(ngModel)]=\"time\"\n [name]=\"key.toString() + 'time'\"\n #timeModel=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-option *ngFor=\"let validTime of DateUtilities.getValidTimesForDropdown(\n DateUtilities.asDate(input),\n metadata.times,\n metadata.minTime,\n metadata.maxTime,\n metadata.filterTime\n )\"\n [value]=\"validTime.value\"\n >\n {{validTime.displayName}}\n </mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(timeModel)}}</mat-error>\n </mat-form-field>\n </div>\n <div class=\"buttons\">\n <button mat-raised-button\n [disabled]=\"model.errors || timeModel.errors || DateUtilities.timeIsUnprocessable(time)\"\n (click)=\"addDateTime()\">\n {{metadata.addButtonLabel}}\n </button>\n <button mat-raised-button\n [disabled]=\"!selection.selected.length\"\n (click)=\"remove()\">\n {{metadata.removeButtonLabel}}\n </button>\n </div>\n\n <mat-table [dataSource]=\"dataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"></mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"></mat-checkbox>\n </mat-cell>\n </ng-container>\n \n <ng-container *ngFor=\"let dCol of metadata.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n\n <div class=\"array-error\" *ngIf=\"metadata.required && !dataSource.data.length\">\n {{metadata.missingErrorMessage}}\n </div>\n</div>", styles: ["mat-form-field{width:100%}.buttons{display:flex;justify-content:space-between;margin-bottom:10px;margin-top:5px}mat-table{border:1px solid #E0E0E0;border-radius:5px;padding-top:5px;padding-bottom:25px}.mat-column-select{flex:0 0 75px}.array-error{display:flex;align-items:center;justify-content:center;margin-top:-25.8px;border:1px solid #E0E0E0;background-color:#f8d3d7;color:#721c24;height:25.8px;border-bottom-left-radius:5px;border-bottom-right-radius:5px}.date-time{display:flex;align-items:baseline}.date-time .timepicker{margin-left:10px}\n"] }]
2120
+ }], ctorParameters: function () { return [{ type: i1.MatDialog }]; }, propDecorators: { entity: [{
2121
+ type: Input
2122
+ }], key: [{
2123
+ type: Input
2124
+ }], getValidationErrorMessage: [{
2125
+ type: Input
2126
+ }], inputChangeEvent: [{
2127
+ type: Output
2128
+ }] } });
2129
+
2130
+ /**
2131
+ * The internal EntityArrayDecoratorConfig. Sets default values.
2132
+ */
2133
+ class EntityArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2134
+ constructor(data) {
2135
+ super(data);
2136
+ this.createInline = data.createInline ?? true;
2137
+ this.itemType = data.itemType;
2138
+ this.allowDuplicates = data.allowDuplicates ?? false;
2139
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
2140
+ this.EntityClass = data.EntityClass;
2141
+ this.displayColumns = data.displayColumns;
2142
+ this.createInline = data.createInline ?? true;
2143
+ this.missingErrorMessage = data.missingErrorMessage ?? 'Needs to contain at least one value';
2144
+ this.defaultWidths = data.defaultWidths ?? [12, 12, 12];
2145
+ this.addButtonLabel = data.addButtonLabel ?? 'Add';
2146
+ this.removeButtonLabel = data.removeButtonLabel ?? 'Remove';
2147
+ }
2148
+ }
2149
+ /**
2150
+ * The internal DateArrayDecoratorConfig. Sets default values.
2151
+ */
2152
+ class DateArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2153
+ constructor(data) {
2154
+ super(data);
2155
+ this.itemType = data.itemType;
2156
+ this.allowDuplicates = data.allowDuplicates ?? false;
2157
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
2158
+ this.displayColumns = data.displayColumns;
2159
+ this.defaultWidths = data.defaultWidths ?? [12, 12, 12];
2160
+ this.addButtonLabel = data.addButtonLabel ?? 'Add';
2161
+ this.removeButtonLabel = data.removeButtonLabel ?? 'Remove';
2162
+ this.missingErrorMessage = data.missingErrorMessage ?? 'Needs to contain at least one value';
2163
+ this.min = data.min;
2164
+ this.max = data.max;
2165
+ this.filter = data.filter;
2166
+ }
2167
+ }
2168
+ /**
2169
+ * The internal DateTimeArrayDecoratorConfig. Sets default values.
2170
+ */
2171
+ class DateTimeArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2172
+ constructor(data) {
2173
+ super(data);
2174
+ this.itemType = data.itemType;
2175
+ this.allowDuplicates = data.allowDuplicates ?? false;
2176
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
2177
+ this.displayColumns = data.displayColumns;
2178
+ this.defaultWidths = data.defaultWidths ?? [12, 12, 12];
2179
+ this.addButtonLabel = data.addButtonLabel ?? 'Add';
2180
+ this.removeButtonLabel = data.removeButtonLabel ?? 'Remove';
2181
+ this.missingErrorMessage = data.missingErrorMessage ?? 'Needs to contain at least one value';
2182
+ this.times = data.times ?? DateUtilities.getDefaultTimes();
2183
+ this.timeDisplayName = data.timeDisplayName ?? 'Time';
2184
+ this.minDate = data.minDate;
2185
+ this.maxDate = data.maxDate;
2186
+ this.filterDate = data.filterDate;
2187
+ this.minTime = data.minTime;
2188
+ this.maxTime = data.maxTime;
2189
+ this.filterTime = data.filterTime;
2190
+ }
2191
+ }
2192
+ /**
2193
+ * The internal DateRangeArrayDecoratorConfig. Sets default values.
2194
+ */
2195
+ class DateRangeArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2196
+ constructor(data) {
2197
+ super(data);
2198
+ this.itemType = data.itemType;
2199
+ this.allowDuplicates = data.allowDuplicates ?? false;
2200
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
2201
+ this.displayColumns = data.displayColumns;
2202
+ this.defaultWidths = data.defaultWidths ?? [12, 12, 12];
2203
+ this.addButtonLabel = data.addButtonLabel ?? 'Add';
2204
+ this.removeButtonLabel = data.removeButtonLabel ?? 'Remove';
2205
+ this.missingErrorMessage = data.missingErrorMessage ?? 'Needs to contain at least one value';
2206
+ this.placeholderStart = data.placeholderStart ?? 'Start';
2207
+ this.placeholderEnd = data.placeholderEnd ?? 'End';
2208
+ this.minStart = data.minStart;
2209
+ this.maxStart = data.maxStart;
2210
+ this.minEnd = data.minEnd;
2211
+ this.maxEnd = data.maxEnd;
2212
+ this.filter = data.filter;
2213
+ }
2214
+ }
2215
+ /**
2216
+ * The internal StringChipsArrayDecoratorConfig. Sets default values.
2217
+ */
2218
+ class StringChipsArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2219
+ constructor(data) {
2220
+ super(data);
2221
+ this.deleteIcon = data.deleteIcon ?? 'fas fa-circle-minus';
2222
+ this.itemType = data.itemType;
2223
+ this.allowDuplicates = data.allowDuplicates ?? false;
2224
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
2225
+ this.maxLength = data.maxLength;
2226
+ this.minLength = data.minLength;
2227
+ this.regex = data.regex;
2228
+ this.defaultWidths = data.defaultWidths ?? [6, 12, 12];
2229
+ }
2230
+ }
2231
+ /**
2232
+ * The internal AutocompleteStringChipsArrayDecoratorConfig. Sets default values.
2233
+ */
2234
+ class AutocompleteStringChipsArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2235
+ constructor(data) {
2236
+ super(data);
2237
+ this.autocompleteValues = data.autocompleteValues;
2238
+ this.deleteIcon = data.deleteIcon ?? 'fas fa-circle-minus';
2239
+ this.itemType = data.itemType;
2240
+ this.allowDuplicates = data.allowDuplicates ?? false;
2241
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
2242
+ this.maxLength = data.maxLength;
2243
+ this.minLength = data.minLength;
2244
+ this.regex = data.regex;
2245
+ this.defaultWidths = data.defaultWidths ?? [6, 12, 12];
2246
+ }
2247
+ }
2248
+ /**
2249
+ * Gets the default dialog data for the error dialog to display when the user tries to add a duplicate value.
2250
+ *
2251
+ * @param data - The Array Decorator data.
2252
+ * @returns The dialog data with set default values.
2253
+ */
2254
+ function getDefaultDuplicateErrorDialogData(data) {
2255
+ return {
2256
+ type: data.duplicatesErrorDialog?.type ?? 'info-only',
2257
+ // eslint-disable-next-line max-len
2258
+ text: data.duplicatesErrorDialog?.text ?? ['Adding duplicate entries to the array is not allowed.'],
2259
+ title: data.duplicatesErrorDialog?.title ?? 'Error adding duplicate item',
2260
+ confirmButtonLabel: data.duplicatesErrorDialog?.confirmButtonLabel,
2261
+ cancelButtonLabel: data.duplicatesErrorDialog?.cancelButtonLabel,
2262
+ requireConfirmation: data.duplicatesErrorDialog?.requireConfirmation,
2263
+ confirmationText: data.duplicatesErrorDialog?.confirmationText
2264
+ };
2265
+ }
2266
+
2267
+ /* eslint-disable jsdoc/require-jsdoc */
2268
+ class ArrayDateRangeInputComponent extends ArrayTable {
2269
+ constructor(dialog) {
2270
+ super(dialog);
2271
+ this.dialog = dialog;
2272
+ this.DateUtilities = DateUtilities;
2273
+ this.inputChangeEvent = new EventEmitter();
2274
+ }
2275
+ ngOnInit() {
2276
+ this.init();
2277
+ this.input = {
2278
+ start: undefined,
2279
+ end: undefined,
2280
+ values: undefined
2281
+ };
2282
+ }
2283
+ /**
2284
+ * Adds a DateRange to the array.
2285
+ */
2286
+ addDateRange() {
2287
+ if (this.input && this.dateRangeStart && this.dateRangeEnd) {
2288
+ this.input.start = new Date(this.dateRangeStart);
2289
+ this.input.end = new Date(this.dateRangeEnd);
2290
+ const values = DateUtilities.getDatesBetween(this.input.start, this.input.end, this.metadata.filter);
2291
+ this.input.values = values.length ? values : undefined;
2292
+ this.add();
2293
+ }
2294
+ }
2295
+ resetInput() {
2296
+ this.input = undefined;
2297
+ this.dateRangeStart = undefined;
2298
+ this.dateRangeEnd = undefined;
2299
+ }
2300
+ emitChange() {
2301
+ this.inputChangeEvent.emit();
2302
+ }
2303
+ }
2304
+ ArrayDateRangeInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateRangeInputComponent, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
2305
+ ArrayDateRangeInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: ArrayDateRangeInputComponent, selector: "array-date-range-input", inputs: { entity: "entity", key: "key", metadata: "metadata", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, usesInheritance: true, ngImport: i0, template: "<div class=\"mat-elevation-z8\" style=\"border-radius: 5px;padding: 15px;margin-bottom: 15px;margin-top: 15px;\">\n\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n \n <mat-date-range-input [rangePicker]=\"picker\" [required]=\"metadata.required\" [dateFilter]=\"metadata.filter ? metadata.filter : DateUtilities.defaultDateFilter\">\n <input matStartDate\n [(ngModel)]=\"dateRangeStart\"\n [name]=\"key.toString() + 'start'\"\n #startModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadata.minStart ? metadata.minStart(input?.start) : undefined\"\n [max]=\"metadata.maxStart ? metadata.maxStart(input?.start) : undefined\"\n [placeholder]=\"metadata.placeholderStart\"\n >\n <input matEndDate\n [(ngModel)]=\"dateRangeEnd\"\n [name]=\"key.toString() + 'end'\"\n #endModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadata.minEnd ? metadata.minEnd(input?.end) : undefined\"\n [max]=\"metadata.maxEnd ? metadata.maxEnd(input?.end) : undefined\"\n [placeholder]=\"metadata.placeholderEnd\"\n >\n </mat-date-range-input>\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-date-range-picker #picker></mat-date-range-picker>\n\n <mat-error *ngIf=\"startModel.errors\">{{getValidationErrorMessage(startModel)}}</mat-error>\n <mat-error *ngIf=\"!startModel.errors && endModel.errors\">{{getValidationErrorMessage(endModel)}}</mat-error>\n </mat-form-field>\n \n <div class=\"buttons\">\n <button mat-raised-button\n [disabled]=\"startModel.errors || endModel.errors\"\n (click)=\"addDateRange()\">\n {{metadata.addButtonLabel}}\n </button>\n <button mat-raised-button\n [disabled]=\"!selection.selected.length\"\n (click)=\"remove()\">\n {{metadata.removeButtonLabel}}\n </button>\n </div>\n\n <mat-table [dataSource]=\"dataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"></mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"></mat-checkbox>\n </mat-cell>\n </ng-container>\n \n <ng-container *ngFor=\"let dCol of metadata.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n\n <div class=\"array-error\" *ngIf=\"metadata.required && !dataSource.data.length\">\n {{metadata.missingErrorMessage}}\n </div>\n</div>", styles: ["mat-form-field{width:100%}.buttons{display:flex;justify-content:space-between;margin-bottom:10px;margin-top:5px}mat-table{border:1px solid #E0E0E0;border-radius:5px;padding-top:5px;padding-bottom:25px}.mat-column-select{flex:0 0 75px}.array-error{display:flex;align-items:center;justify-content:center;margin-top:-25.8px;border:1px solid #E0E0E0;background-color:#f8d3d7;color:#721c24;height:25.8px;border-bottom-left-radius:5px;border-bottom-right-radius:5px}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i3$3.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { type: i3$3.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i3$3.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { type: i4.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i3$3.MatStartDate, selector: "input[matStartDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i3$3.MatEndDate, selector: "input[matEndDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i1$1.MatSuffix, selector: "[matSuffix]" }, { type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }, { type: i5.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i5.MatCellDef, selector: "[matCellDef]" }, { type: i5.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i5.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }] });
2306
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateRangeInputComponent, decorators: [{
2307
+ type: Component,
2308
+ args: [{ selector: 'array-date-range-input', template: "<div class=\"mat-elevation-z8\" style=\"border-radius: 5px;padding: 15px;margin-bottom: 15px;margin-top: 15px;\">\n\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n \n <mat-date-range-input [rangePicker]=\"picker\" [required]=\"metadata.required\" [dateFilter]=\"metadata.filter ? metadata.filter : DateUtilities.defaultDateFilter\">\n <input matStartDate\n [(ngModel)]=\"dateRangeStart\"\n [name]=\"key.toString() + 'start'\"\n #startModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadata.minStart ? metadata.minStart(input?.start) : undefined\"\n [max]=\"metadata.maxStart ? metadata.maxStart(input?.start) : undefined\"\n [placeholder]=\"metadata.placeholderStart\"\n >\n <input matEndDate\n [(ngModel)]=\"dateRangeEnd\"\n [name]=\"key.toString() + 'end'\"\n #endModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadata.minEnd ? metadata.minEnd(input?.end) : undefined\"\n [max]=\"metadata.maxEnd ? metadata.maxEnd(input?.end) : undefined\"\n [placeholder]=\"metadata.placeholderEnd\"\n >\n </mat-date-range-input>\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-date-range-picker #picker></mat-date-range-picker>\n\n <mat-error *ngIf=\"startModel.errors\">{{getValidationErrorMessage(startModel)}}</mat-error>\n <mat-error *ngIf=\"!startModel.errors && endModel.errors\">{{getValidationErrorMessage(endModel)}}</mat-error>\n </mat-form-field>\n \n <div class=\"buttons\">\n <button mat-raised-button\n [disabled]=\"startModel.errors || endModel.errors\"\n (click)=\"addDateRange()\">\n {{metadata.addButtonLabel}}\n </button>\n <button mat-raised-button\n [disabled]=\"!selection.selected.length\"\n (click)=\"remove()\">\n {{metadata.removeButtonLabel}}\n </button>\n </div>\n\n <mat-table [dataSource]=\"dataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"></mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"></mat-checkbox>\n </mat-cell>\n </ng-container>\n \n <ng-container *ngFor=\"let dCol of metadata.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n\n <div class=\"array-error\" *ngIf=\"metadata.required && !dataSource.data.length\">\n {{metadata.missingErrorMessage}}\n </div>\n</div>", styles: ["mat-form-field{width:100%}.buttons{display:flex;justify-content:space-between;margin-bottom:10px;margin-top:5px}mat-table{border:1px solid #E0E0E0;border-radius:5px;padding-top:5px;padding-bottom:25px}.mat-column-select{flex:0 0 75px}.array-error{display:flex;align-items:center;justify-content:center;margin-top:-25.8px;border:1px solid #E0E0E0;background-color:#f8d3d7;color:#721c24;height:25.8px;border-bottom-left-radius:5px;border-bottom-right-radius:5px}\n"] }]
2309
+ }], ctorParameters: function () { return [{ type: i1.MatDialog }]; }, propDecorators: { entity: [{
2310
+ type: Input
2311
+ }], key: [{
2312
+ type: Input
2313
+ }], metadata: [{
2314
+ type: Input
2315
+ }], getValidationErrorMessage: [{
2316
+ type: Input
2317
+ }], inputChangeEvent: [{
2318
+ type: Output
2319
+ }] } });
2320
+
2321
+ /* eslint-disable jsdoc/require-jsdoc */
2322
+ class ArrayStringChipsInputComponent {
2323
+ constructor() {
2324
+ this.inputChangeEvent = new EventEmitter();
2325
+ this.chipsInput = '';
2326
+ }
2327
+ ngOnInit() {
2328
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.ARRAY_STRING_CHIPS);
2329
+ if (this.entity[this.key]?.length) {
2330
+ this.stringChipsArrayValues = this.entity[this.key];
2331
+ }
2332
+ }
2333
+ /**
2334
+ * Handles adding strings to the chipsArray.
2335
+ * Checks validation and also creates a new array if it is undefined.
2336
+ * This is needed because two things are validated: The array itself
2337
+ * and the contents of the array. And we need a way to display an
2338
+ * mat-error. As the only validation for the array is whether or not
2339
+ * it contains values, we can set it to undefined when the last element is removed
2340
+ * (removeStringChipArrayValue). That way we can use the "required" validator.
2341
+ *
2342
+ * @param event - The event that fires when a new chip is completed.
2343
+ */
2344
+ addStringChipArrayValue(event) {
2345
+ const value = (event.value || '').trim();
2346
+ if (value) {
2347
+ if (this.metadata.minLength && value.length < this.metadata.minLength) {
2348
+ return;
2349
+ }
2350
+ if (this.metadata.maxLength && value.length > this.metadata.maxLength) {
2351
+ return;
2352
+ }
2353
+ if (this.metadata.regex && !value.match(this.metadata.regex)) {
2354
+ return;
2355
+ }
2356
+ if (!this.stringChipsArrayValues) {
2357
+ if (this.entity[this.key] == null) {
2358
+ this.entity[this.key] = [];
2359
+ }
2360
+ this.stringChipsArrayValues = this.entity[this.key];
2361
+ }
2362
+ this.stringChipsArrayValues.push(value);
2363
+ }
2364
+ event.chipInput?.clear();
2365
+ }
2366
+ /**
2367
+ * Removes the given value from the array.
2368
+ * Sets the array to undefined if it is now empty.
2369
+ * This is needed because two things are validated: The array itself
2370
+ * and the contents of the array. And we need a way to display an
2371
+ * mat-error. As the only validation for the array is whether or not
2372
+ * it is empty, setting it to undefined here enables us to use the "required" validator.
2373
+ *
2374
+ * @param value - The string to remove from the array.
2375
+ */
2376
+ removeStringChipArrayValue(value) {
2377
+ this.stringChipsArrayValues?.splice(this.stringChipsArrayValues.indexOf(value), 1);
2378
+ if (!this.stringChipsArrayValues?.length) {
2379
+ this.entity[this.key] = undefined;
2380
+ this.stringChipsArrayValues = this.entity[this.key];
2381
+ }
2382
+ }
2383
+ /**
2384
+ * Handles adding a string to the array when an autocomplete value has been selected.
2385
+ *
2386
+ * @param event - The autocomplete selected event.
2387
+ * @param chipsInput - The element where the user typed the value.
2388
+ */
2389
+ selected(event, chipsInput) {
2390
+ const value = (event.option.viewValue || '').trim();
2391
+ if (this.metadata.minLength && value.length < this.metadata.minLength) {
2392
+ return;
2393
+ }
2394
+ if (this.metadata.maxLength && value.length > this.metadata.maxLength) {
2395
+ return;
2396
+ }
2397
+ if (this.metadata.regex && !value.match(this.metadata.regex)) {
2398
+ return;
2399
+ }
2400
+ if (!this.stringChipsArrayValues) {
2401
+ if (this.entity[this.key] == null) {
2402
+ this.entity[this.key] = [];
2403
+ }
2404
+ this.stringChipsArrayValues = this.entity[this.key];
2405
+ }
2406
+ this.stringChipsArrayValues.push(value);
2407
+ chipsInput.value = '';
2408
+ }
2409
+ emitChange() {
2410
+ this.inputChangeEvent.emit();
2411
+ }
2412
+ }
2413
+ ArrayStringChipsInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayStringChipsInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2414
+ ArrayStringChipsInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: ArrayStringChipsInputComponent, selector: "array-string-chips-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n (ngModelChange)=\"emitChange()\"\n [(ngModel)]=\"entity[key]\" [name]=\"key.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadata.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n [(ngModel)]=\"chipsInput\" [name]=\"key.toString()\" #chipsModel=\"ngModel\"\n [minlength]='metadata.minLength ?? null'\n [maxlength]='metadata.maxLength ?? null'\n [pattern]=\"metadata.regex ?? '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2$3.MatChipList, selector: "mat-chip-list", inputs: ["errorStateMatcher", "multiple", "compareWith", "value", "required", "placeholder", "disabled", "aria-orientation", "selectable", "tabIndex"], outputs: ["change", "valueChange"], exportAs: ["matChipList"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2$3.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["color", "disableRipple", "tabIndex", "selected", "value", "selectable", "disabled", "removable"], outputs: ["selectionChange", "destroyed", "removed"], exportAs: ["matChip"] }, { type: i2$3.MatChipRemove, selector: "[matChipRemove]" }, { type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i2$3.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i3.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i3.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
2415
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayStringChipsInputComponent, decorators: [{
2416
+ type: Component,
2417
+ args: [{ selector: 'array-string-chips-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n (ngModelChange)=\"emitChange()\"\n [(ngModel)]=\"entity[key]\" [name]=\"key.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadata.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n [(ngModel)]=\"chipsInput\" [name]=\"key.toString()\" #chipsModel=\"ngModel\"\n [minlength]='metadata.minLength ?? null'\n [maxlength]='metadata.maxLength ?? null'\n [pattern]=\"metadata.regex ?? '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
2418
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
2419
+ type: Input
2420
+ }], key: [{
2421
+ type: Input
2422
+ }], getValidationErrorMessage: [{
2423
+ type: Input
2424
+ }], inputChangeEvent: [{
2425
+ type: Output
2426
+ }] } });
2427
+
2428
+ /* eslint-disable jsdoc/require-jsdoc */
2429
+ class ArrayStringAutocompleteChipsComponent {
2430
+ constructor() {
2431
+ this.inputChangeEvent = new EventEmitter();
2432
+ this.chipsInput = '';
2433
+ }
2434
+ ngOnInit() {
2435
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS);
2436
+ this.filteredAutocompleteStrings = LodashUtilities.cloneDeep(this.metadata.autocompleteValues);
2437
+ if (this.entity[this.key]?.length) {
2438
+ this.stringChipsArrayValues = this.entity[this.key];
2439
+ }
2440
+ }
2441
+ /**
2442
+ * Handles adding strings to the chipsArray.
2443
+ * Checks validation and also creates a new array if it is undefined.
2444
+ * This is needed because two things are validated: The array itself
2445
+ * and the contents of the array. And we need a way to display an
2446
+ * mat-error. As the only validation for the array is whether or not
2447
+ * it contains values, we can set it to undefined when the last element is removed
2448
+ * (removeStringChipArrayValue). That way we can use the "required" validator.
2449
+ *
2450
+ * @param event - The event that fires when a new chip is completed.
2451
+ */
2452
+ addStringChipArrayValue(event) {
2453
+ const value = (event.value || '').trim();
2454
+ if (value) {
2455
+ if (this.metadata.minLength && value.length < this.metadata.minLength) {
2456
+ return;
2457
+ }
2458
+ if (this.metadata.maxLength && value.length > this.metadata.maxLength) {
2459
+ return;
2460
+ }
2461
+ if (this.metadata.regex && !value.match(this.metadata.regex)) {
2462
+ return;
2463
+ }
2464
+ if (!this.stringChipsArrayValues) {
2465
+ if (this.entity[this.key] == null) {
2466
+ this.entity[this.key] = [];
2467
+ }
2468
+ this.stringChipsArrayValues = this.entity[this.key];
2469
+ }
2470
+ this.stringChipsArrayValues.push(value);
2471
+ }
2472
+ event.chipInput?.clear();
2473
+ }
2474
+ /**
2475
+ * Removes the given value from the array.
2476
+ * Sets the array to undefined if it is now empty.
2477
+ * This is needed because two things are validated: The array itself
2478
+ * and the contents of the array. And we need a way to display an
2479
+ * mat-error. As the only validation for the array is whether or not
2480
+ * it is empty, setting it to undefined here enables us to use the "required" validator.
2481
+ *
2482
+ * @param value - The string to remove from the array.
2483
+ */
2484
+ removeStringChipArrayValue(value) {
2485
+ this.stringChipsArrayValues?.splice(this.stringChipsArrayValues.indexOf(value), 1);
2486
+ if (!this.stringChipsArrayValues?.length) {
2487
+ this.entity[this.key] = undefined;
2488
+ this.stringChipsArrayValues = this.entity[this.key];
2489
+ }
2490
+ }
2491
+ /**
2492
+ * Handles adding a string to the array when an autocomplete value has been selected.
2493
+ *
2494
+ * @param event - The autocomplete selected event.
2495
+ * @param chipsInput - The element where the user typed the value.
2496
+ */
2497
+ selected(event, chipsInput) {
2498
+ const value = (event.option.viewValue || '').trim();
2499
+ if (this.metadata.minLength && value.length < this.metadata.minLength) {
2500
+ return;
2501
+ }
2502
+ if (this.metadata.maxLength && value.length > this.metadata.maxLength) {
2503
+ return;
2504
+ }
2505
+ if (this.metadata.regex && !value.match(this.metadata.regex)) {
2506
+ return;
2507
+ }
2508
+ if (!this.stringChipsArrayValues) {
2509
+ if (this.entity[this.key] == null) {
2510
+ this.entity[this.key] = [];
2511
+ }
2512
+ this.stringChipsArrayValues = this.entity[this.key];
2513
+ }
2514
+ this.stringChipsArrayValues.push(value);
2515
+ chipsInput.value = '';
2516
+ }
2517
+ /**
2518
+ * Dynamically filters the Autocomplete options when the user inputs something.
2519
+ *
2520
+ * @param input - The input of the user.
2521
+ */
2522
+ filterAutocompleteStrings(input) {
2523
+ if (input != null) {
2524
+ const filterValue = input.toLowerCase();
2525
+ this.filteredAutocompleteStrings = this.metadata.autocompleteValues.filter(s => s.toLowerCase().includes(filterValue));
2526
+ }
2527
+ }
2528
+ emitChange() {
2529
+ this.inputChangeEvent.emit();
2530
+ }
2531
+ }
2532
+ ArrayStringAutocompleteChipsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayStringAutocompleteChipsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2533
+ ArrayStringAutocompleteChipsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: ArrayStringAutocompleteChipsComponent, selector: "array-string-autocomplete-chips", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n (ngModelChange)=\"emitChange()\"\n [(ngModel)]=\"entity[key]\" [name]=\"key.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadata.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matAutocomplete]=\"auto\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n (keyup)=\"filterAutocompleteStrings(chipsInput)\"\n [(ngModel)]=\"chipsInput\" [name]=\"key.toString()\" #chipsModel=\"ngModel\"\n #chipsElement\n [minlength]='metadata.minLength ?? null'\n [maxlength]='metadata.maxLength ?? null'\n [pattern]=\"metadata.regex ?? '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event, chipsElement)\">\n <mat-option *ngFor=\"let value of metadata.autocompleteValues\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2$3.MatChipList, selector: "mat-chip-list", inputs: ["errorStateMatcher", "multiple", "compareWith", "value", "required", "placeholder", "disabled", "aria-orientation", "selectable", "tabIndex"], outputs: ["change", "valueChange"], exportAs: ["matChipList"] }, { type: i2.MatAutocomplete, selector: "mat-autocomplete", inputs: ["disableRipple"], exportAs: ["matAutocomplete"] }, { type: i3$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2$3.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["color", "disableRipple", "tabIndex", "selected", "value", "selectable", "disabled", "removable"], outputs: ["selectionChange", "destroyed", "removed"], exportAs: ["matChip"] }, { type: i2$3.MatChipRemove, selector: "[matChipRemove]" }, { type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i2$3.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { type: i2.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", exportAs: ["matAutocompleteTrigger"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i3.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i3.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
2534
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayStringAutocompleteChipsComponent, decorators: [{
2535
+ type: Component,
2536
+ args: [{ selector: 'array-string-autocomplete-chips', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n (ngModelChange)=\"emitChange()\"\n [(ngModel)]=\"entity[key]\" [name]=\"key.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadata.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matAutocomplete]=\"auto\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n (keyup)=\"filterAutocompleteStrings(chipsInput)\"\n [(ngModel)]=\"chipsInput\" [name]=\"key.toString()\" #chipsModel=\"ngModel\"\n #chipsElement\n [minlength]='metadata.minLength ?? null'\n [maxlength]='metadata.maxLength ?? null'\n [pattern]=\"metadata.regex ?? '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event, chipsElement)\">\n <mat-option *ngFor=\"let value of metadata.autocompleteValues\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
2537
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
2538
+ type: Input
2539
+ }], key: [{
2540
+ type: Input
2541
+ }], getValidationErrorMessage: [{
2542
+ type: Input
2543
+ }], inputChangeEvent: [{
2544
+ type: Output
2545
+ }] } });
2546
+
2547
+ /* eslint-disable jsdoc/require-jsdoc */
2548
+ class DateInputComponent {
2549
+ constructor() {
2550
+ this.DateUtilities = DateUtilities;
2551
+ this.inputChangeEvent = new EventEmitter();
2552
+ this.defaultDateFilter = () => true;
2553
+ }
2554
+ ngOnInit() {
2555
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.DATE);
2556
+ }
2557
+ emitChange() {
2558
+ this.inputChangeEvent.emit();
2559
+ }
2560
+ }
2561
+ DateInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2562
+ DateInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: DateInputComponent, selector: "date-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n (ngModelChange)=\"emitChange()\"\n matInput\n [(ngModel)]=\"entity[key]\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadata.min ? metadata.min(DateUtilities.asDate(entity[key])) : undefined\"\n [max]=\"metadata.max ? metadata.max(DateUtilities.asDate(entity[key])) : undefined\"\n [matDatepickerFilter]=\"metadata.filter ?? defaultDateFilter\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i3$3.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i3$3.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3$3.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i1$1.MatSuffix, selector: "[matSuffix]" }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
2563
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateInputComponent, decorators: [{
2564
+ type: Component,
2565
+ args: [{ selector: 'date-input', template: "<mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n (ngModelChange)=\"emitChange()\"\n matInput\n [(ngModel)]=\"entity[key]\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadata.min ? metadata.min(DateUtilities.asDate(entity[key])) : undefined\"\n [max]=\"metadata.max ? metadata.max(DateUtilities.asDate(entity[key])) : undefined\"\n [matDatepickerFilter]=\"metadata.filter ?? defaultDateFilter\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
2566
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
2567
+ type: Input
2568
+ }], key: [{
2569
+ type: Input
2570
+ }], getValidationErrorMessage: [{
2571
+ type: Input
2572
+ }], inputChangeEvent: [{
2573
+ type: Output
2574
+ }] } });
2575
+
2576
+ /* eslint-disable jsdoc/require-jsdoc */
2577
+ const EMPTY_DATERANGE = {
2578
+ start: undefined,
2579
+ end: undefined,
2580
+ values: undefined
2581
+ };
2582
+ class DateRangeInputComponent {
2583
+ constructor() {
2584
+ this.inputChangeEvent = new EventEmitter();
2585
+ this.defaultDateFilter = () => true;
2586
+ }
2587
+ ngOnInit() {
2588
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.DATE_RANGE);
2589
+ this.dateRange = LodashUtilities.cloneDeep(this.entity[this.key]) ?? EMPTY_DATERANGE;
2590
+ this.dateRangeStart = new Date(this.dateRange.start);
2591
+ this.dateRangeEnd = new Date(this.dateRange.end);
2592
+ this.setDateRangeValues();
2593
+ }
2594
+ /**
2595
+ * Updates the date range values based on the start and end date.
2596
+ */
2597
+ setDateRangeValues() {
2598
+ if (this.dateRangeStart && this.dateRangeEnd) {
2599
+ this.dateRange.start = new Date(this.dateRangeStart);
2600
+ this.dateRange.end = new Date(this.dateRangeEnd);
2601
+ const values = DateUtilities.getDatesBetween(new Date(this.dateRange.start), new Date(this.dateRange.end), this.metadata.filter);
2602
+ this.dateRange.values = values.length ? values : undefined;
2603
+ }
2604
+ else {
2605
+ this.dateRange.values = undefined;
2606
+ }
2607
+ this.entity[this.key] = this.dateRange;
2608
+ this.emitChange();
2609
+ }
2610
+ emitChange() {
2611
+ this.inputChangeEvent.emit();
2612
+ }
2613
+ }
2614
+ DateRangeInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateRangeInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2615
+ DateRangeInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: DateRangeInputComponent, selector: "date-range-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n \n <mat-date-range-input [rangePicker]=\"picker\" [required]=\"metadata.required\" [dateFilter]=\"metadata.filter ?? defaultDateFilter\">\n <input matStartDate\n [(ngModel)]=\"dateRangeStart\"\n [name]=\"key.toString() + 'start'\"\n #startModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadata.minStart ? metadata.minStart(dateRange.start) : undefined\"\n [max]=\"metadata.maxStart ? metadata.maxStart(dateRange.start) : undefined\"\n [placeholder]=\"metadata.placeholderStart\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n <input matEndDate\n [(ngModel)]=\"dateRangeEnd\"\n [name]=\"key.toString() + 'end'\"\n #endModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadata.minEnd ? metadata.minEnd(dateRange.end) : undefined\"\n [max]=\"metadata.maxEnd ? metadata.maxEnd(dateRange.end) : undefined\"\n [placeholder]=\"metadata.placeholderEnd\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n </mat-date-range-input>\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-date-range-picker #picker></mat-date-range-picker>\n\n <mat-error *ngIf=\"startModel.errors\">{{getValidationErrorMessage(startModel)}}</mat-error>\n <mat-error *ngIf=\"!startModel.errors && endModel.errors\">{{getValidationErrorMessage(endModel)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i3$3.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { type: i3$3.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i3$3.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i3$3.MatStartDate, selector: "input[matStartDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i3$3.MatEndDate, selector: "input[matEndDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i1$1.MatSuffix, selector: "[matSuffix]" }, { type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
2616
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateRangeInputComponent, decorators: [{
2617
+ type: Component,
2618
+ args: [{ selector: 'date-range-input', template: "<mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n \n <mat-date-range-input [rangePicker]=\"picker\" [required]=\"metadata.required\" [dateFilter]=\"metadata.filter ?? defaultDateFilter\">\n <input matStartDate\n [(ngModel)]=\"dateRangeStart\"\n [name]=\"key.toString() + 'start'\"\n #startModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadata.minStart ? metadata.minStart(dateRange.start) : undefined\"\n [max]=\"metadata.maxStart ? metadata.maxStart(dateRange.start) : undefined\"\n [placeholder]=\"metadata.placeholderStart\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n <input matEndDate\n [(ngModel)]=\"dateRangeEnd\"\n [name]=\"key.toString() + 'end'\"\n #endModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadata.minEnd ? metadata.minEnd(dateRange.end) : undefined\"\n [max]=\"metadata.maxEnd ? metadata.maxEnd(dateRange.end) : undefined\"\n [placeholder]=\"metadata.placeholderEnd\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n </mat-date-range-input>\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-date-range-picker #picker></mat-date-range-picker>\n\n <mat-error *ngIf=\"startModel.errors\">{{getValidationErrorMessage(startModel)}}</mat-error>\n <mat-error *ngIf=\"!startModel.errors && endModel.errors\">{{getValidationErrorMessage(endModel)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
2619
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
2620
+ type: Input
2621
+ }], key: [{
2622
+ type: Input
2623
+ }], getValidationErrorMessage: [{
2624
+ type: Input
2625
+ }], inputChangeEvent: [{
2626
+ type: Output
2627
+ }] } });
2628
+
2629
+ /* eslint-disable jsdoc/require-jsdoc */
2630
+ class DateTimeInputComponent {
2631
+ constructor() {
2632
+ this.DateUtilities = DateUtilities;
2633
+ this.inputChangeEvent = new EventEmitter();
2634
+ this.defaultDateFilter = () => true;
2635
+ }
2636
+ ngOnInit() {
2637
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.DATE_TIME);
2638
+ this.time = DateUtilities.getTimeFromDate(this.entity[this.key]);
2639
+ this.timeDropdownValues = this.metadata.times;
2640
+ if (this.entity[this.key] != null) {
2641
+ this.dateTime = new Date(this.entity[this.key]);
2642
+ }
2643
+ }
2644
+ /**
2645
+ * Checks if two times are equal. Is needed for the dropdown.
2646
+ *
2647
+ * @param time1 - The first time to compare.
2648
+ * @param time2 - The second time to compare.
2649
+ * @returns Whether or not the time objects are the same.
2650
+ */
2651
+ compareTimes(time1, time2) {
2652
+ return time1.hours === time2.hours && time1.minutes === time2.minutes;
2653
+ }
2654
+ /**
2655
+ * Sets the time on a datetime property.
2656
+ */
2657
+ setTime() {
2658
+ if (!this.dateTime) {
2659
+ this.entity[this.key] = undefined;
2660
+ this.emitChange();
2661
+ return;
2662
+ }
2663
+ this.entity[this.key] = new Date(this.dateTime);
2664
+ if (this.time?.hours != null && this.time?.minutes != null) {
2665
+ this.entity[this.key].setHours(this.time.hours, this.time.minutes, 0, 0);
2666
+ }
2667
+ else {
2668
+ this.entity[this.key].setHours(0, 0, 0, 0);
2669
+ }
2670
+ this.emitChange();
2671
+ }
2672
+ emitChange() {
2673
+ this.inputChangeEvent.emit();
2674
+ }
2675
+ }
2676
+ DateTimeInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateTimeInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2677
+ DateTimeInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: DateTimeInputComponent, selector: "date-time-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<div class=\"date-time\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"dateTime\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadata.minDate ? metadata.minDate(dateTime) : undefined\"\n [max]=\"metadata.maxDate ? metadata.maxDate(dateTime) : undefined\"\n [matDatepickerFilter]=\"metadata.filterDate ?? defaultDateFilter\"\n (dateInput)=\"setTime()\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n <mat-form-field class=\"timepicker\">\n <mat-label>{{metadata.timeDisplayName}}</mat-label>\n <mat-select\n [(ngModel)]=\"time\"\n [name]=\"key.toString() + 'time'\"\n #timeModel=\"ngModel\"\n [required]=\"metadata.required\"\n [compareWith]=\"compareTimes\"\n (ngModelChange)=\"setTime()\"\n >\n <mat-option *ngFor=\"let validTime of DateUtilities.getValidTimesForDropdown(\n DateUtilities.asDate(entity[key]),\n metadata.times,\n metadata.minTime,\n metadata.maxTime,\n metadata.filterTime\n )\"\n [value]=\"validTime.value\"\n >\n {{validTime.displayName}}\n </mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(timeModel)}}</mat-error>\n </mat-form-field>\n</div>", styles: ["mat-form-field{width:100%}.date-time{display:flex;align-items:baseline}.date-time .timepicker{margin-left:10px}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i3$3.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i3$3.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { type: i2$1.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i3$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3$3.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i1$1.MatSuffix, selector: "[matSuffix]" }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
2678
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateTimeInputComponent, decorators: [{
2679
+ type: Component,
2680
+ args: [{ selector: 'date-time-input', template: "<div class=\"date-time\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"dateTime\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadata.minDate ? metadata.minDate(dateTime) : undefined\"\n [max]=\"metadata.maxDate ? metadata.maxDate(dateTime) : undefined\"\n [matDatepickerFilter]=\"metadata.filterDate ?? defaultDateFilter\"\n (dateInput)=\"setTime()\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n <mat-form-field class=\"timepicker\">\n <mat-label>{{metadata.timeDisplayName}}</mat-label>\n <mat-select\n [(ngModel)]=\"time\"\n [name]=\"key.toString() + 'time'\"\n #timeModel=\"ngModel\"\n [required]=\"metadata.required\"\n [compareWith]=\"compareTimes\"\n (ngModelChange)=\"setTime()\"\n >\n <mat-option *ngFor=\"let validTime of DateUtilities.getValidTimesForDropdown(\n DateUtilities.asDate(entity[key]),\n metadata.times,\n metadata.minTime,\n metadata.maxTime,\n metadata.filterTime\n )\"\n [value]=\"validTime.value\"\n >\n {{validTime.displayName}}\n </mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(timeModel)}}</mat-error>\n </mat-form-field>\n</div>", styles: ["mat-form-field{width:100%}.date-time{display:flex;align-items:baseline}.date-time .timepicker{margin-left:10px}\n"] }]
2681
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
2682
+ type: Input
2683
+ }], key: [{
2684
+ type: Input
2685
+ }], getValidationErrorMessage: [{
2686
+ type: Input
2687
+ }], inputChangeEvent: [{
2688
+ type: Output
2689
+ }] } });
2690
+
2691
+ /**
2692
+ * Adds drag and drop functionality to an element.
2693
+ */
2694
+ class DragDropDirective {
2695
+ constructor() {
2696
+ /**
2697
+ * Emits the dropped files to the parent.
2698
+ */
2699
+ this.files = new EventEmitter();
2700
+ }
2701
+ /**
2702
+ * Prevents the event default.
2703
+ *
2704
+ * @param evt - The Event when dragged files hover over the parent.
2705
+ */
2706
+ onDragOver(evt) {
2707
+ evt.preventDefault();
2708
+ evt.stopPropagation();
2709
+ }
2710
+ /**
2711
+ * Prevents the event default.
2712
+ *
2713
+ * @param evt - The Event when dragged files leave the parent.
2714
+ */
2715
+ onDragLeave(evt) {
2716
+ evt.preventDefault();
2717
+ evt.stopPropagation();
2718
+ }
2719
+ /**
2720
+ * Prevents the event default and emits the dropped files with the output.
2721
+ *
2722
+ * @param evt - The Event when files are dropped.
2723
+ */
2724
+ onDrop(evt) {
2725
+ evt.preventDefault();
2726
+ evt.stopPropagation();
2727
+ if (evt.dataTransfer && evt.dataTransfer.files.length > 0) {
2728
+ this.files.emit(Array.from(evt.dataTransfer.files));
2729
+ }
2730
+ }
2731
+ }
2732
+ DragDropDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DragDropDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2733
+ DragDropDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.11", type: DragDropDirective, selector: "[dragDrop]", outputs: { files: "files" }, host: { listeners: { "dragover": "onDragOver($event)", "dragleave": "onDragLeave($event)", "drop": "onDrop($event)" } }, ngImport: i0 });
2734
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DragDropDirective, decorators: [{
2735
+ type: Directive,
2736
+ args: [{
2737
+ // eslint-disable-next-line @angular-eslint/directive-selector
2738
+ selector: '[dragDrop]'
2739
+ }]
2740
+ }], ctorParameters: function () { return []; }, propDecorators: { files: [{
2741
+ type: Output
2742
+ }], onDragOver: [{
2743
+ type: HostListener,
2744
+ args: ['dragover', ['$event']]
2745
+ }], onDragLeave: [{
2746
+ type: HostListener,
2747
+ args: ['dragleave', ['$event']]
2748
+ }], onDrop: [{
2749
+ type: HostListener,
2750
+ args: ['drop', ['$event']]
2751
+ }] } });
2752
+
2753
+ /* eslint-disable jsdoc/require-jsdoc */
2754
+ class FileInputComponent {
2755
+ constructor(dialog) {
2756
+ this.dialog = dialog;
2757
+ this.FileUtilities = FileUtilities;
2758
+ this.fileDataChangeEvent = new EventEmitter();
2759
+ }
2760
+ async ngOnInit() {
2761
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.FILE_DEFAULT);
2762
+ if (this.metadata.multiple) {
2763
+ this.initMultiFile();
2764
+ }
2765
+ else {
2766
+ this.initSingleFile();
2767
+ }
2768
+ this.fileDataChangeEvent.emit(this.singleFileData ?? this.multiFileData);
2769
+ }
2770
+ initMultiFile() {
2771
+ this.multiFileData = this.entity[this.key];
2772
+ if (this.multiFileData) {
2773
+ this.filenames = this.multiFileData.map(f => f.name);
2774
+ }
2775
+ }
2776
+ initSingleFile() {
2777
+ this.singleFileData = this.entity[this.key];
2778
+ if (this.singleFileData) {
2779
+ this.filenames = LodashUtilities.cloneDeep([this.singleFileData.name]);
2780
+ }
2781
+ }
2782
+ async setFileFromInput(event) {
2783
+ const files = event.target.files ?? [];
2784
+ await this.setFile(Array.from(files));
2785
+ }
2786
+ async setFile(files) {
2787
+ // validation done inline
2788
+ if (files.find(f => !FileUtilities.isMimeTypeValid(f.type, this.metadata.allowedMimeTypes))) {
2789
+ this.dialog.open(NgxMatEntityConfirmDialogComponent, {
2790
+ data: this.metadata.mimeTypeErrorDialog,
2791
+ autoFocus: false,
2792
+ restoreFocus: false
2793
+ });
2794
+ this.resetFileInputs();
2795
+ return;
2796
+ }
2797
+ if (files.find(f => f.size > (this.metadata.maxSize * 1000000))) {
2798
+ this.dialog.open(NgxMatEntityConfirmDialogComponent, {
2799
+ data: this.metadata.maxSizeErrorDialog,
2800
+ autoFocus: false,
2801
+ restoreFocus: false
2802
+ });
2803
+ this.resetFileInputs();
2804
+ return;
2805
+ }
2806
+ let fileSizeTotal = 0;
2807
+ for (const file of files) {
2808
+ fileSizeTotal += file.size;
2809
+ }
2810
+ if (fileSizeTotal > (this.metadata.maxSizeTotal * 1000000)) {
2811
+ this.dialog.open(NgxMatEntityConfirmDialogComponent, {
2812
+ data: this.metadata.maxSizeTotalErrorDialog,
2813
+ autoFocus: false,
2814
+ restoreFocus: false
2815
+ });
2816
+ this.resetFileInputs();
2817
+ return;
2818
+ }
2819
+ if (this.metadata.multiple) {
2820
+ await this.setMultiFile(Array.from(files));
2821
+ }
2822
+ else {
2823
+ await this.setSingleFile(files[0]);
2824
+ }
2825
+ this.fileDataChangeEvent.emit(this.singleFileData ?? this.multiFileData);
2826
+ }
2827
+ resetFileInputs() {
2828
+ this.filenames = undefined;
2829
+ this.singleFileData = undefined;
2830
+ this.multiFileData = undefined;
2831
+ this.fileDataChangeEvent.emit();
2832
+ }
2833
+ async setMultiFile(files) {
2834
+ const data = [];
2835
+ for (const file of files) {
2836
+ const fileData = {
2837
+ file: file,
2838
+ name: file.name,
2839
+ type: file.type,
2840
+ size: file.size
2841
+ };
2842
+ data.push(fileData);
2843
+ }
2844
+ this.multiFileData = LodashUtilities.cloneDeep(data);
2845
+ this.filenames = this.multiFileData.map(f => f.name);
2846
+ }
2847
+ async setSingleFile(file) {
2848
+ this.singleFileData = {
2849
+ file: file,
2850
+ name: file.name,
2851
+ type: file.type,
2852
+ size: file.size
2853
+ };
2854
+ this.filenames = LodashUtilities.cloneDeep([this.singleFileData.name]);
2855
+ }
2856
+ removeFile(name) {
2857
+ if (this.metadata.multiple) {
2858
+ this.filenames?.splice(this.filenames.indexOf(name), 1);
2859
+ if (!this.filenames?.length) {
2860
+ this.filenames = undefined;
2861
+ }
2862
+ const fileDataToRemove = this.multiFileData?.find(f => f.name === name);
2863
+ this.multiFileData?.splice(this.multiFileData.indexOf(fileDataToRemove), 1);
2864
+ if (!this.multiFileData?.length) {
2865
+ this.multiFileData = undefined;
2866
+ }
2867
+ }
2868
+ else {
2869
+ this.filenames = undefined;
2870
+ this.singleFileData = undefined;
2871
+ }
2872
+ this.fileDataChangeEvent.emit(this.singleFileData ?? this.multiFileData);
2873
+ }
2874
+ }
2875
+ FileInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileInputComponent, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
2876
+ FileInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: FileInputComponent, selector: "file-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { fileDataChangeEvent: "fileDataChangeEvent" }, ngImport: i0, template: "<input #fileInput\n type=\"file\" hidden\n [multiple]=\"metadata.multiple\"\n [accept]=\"FileUtilities.getAcceptString(metadata.allowedMimeTypes)\"\n (change)=\"setFileFromInput($event)\"\n>\n\n<mat-form-field floatLabel=\"always\" (click)=\"fileInput.click()\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"filenames\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let name of filenames\" (removed)=\"removeFile(name)\">\n {{name}}\n <button matChipRemove>\n <i class=\"{{metadata.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input [matChipInputFor]=\"chipList\" [readonly]=\"true\">\n </mat-chip-list>\n <button mat-icon-button matSuffix>\n <i class=\"fas fa-upload\"></i>\n </button>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>\n\n<div *ngIf=\"metadata.dragAndDrop\" class=\"dropdown\" dragDrop (files)=\"setFile($event)\">\n <i class=\"fas fa-file-arrow-up\"></i>\n</div>", styles: ["mat-form-field{width:100%}input:hover,mat-form-field:hover{cursor:pointer}i{color:#757575}.dropdown{display:flex;align-items:center;justify-content:center;height:200px;border:2px dashed #757575;border-radius:15px;margin-top:5px;margin-bottom:5px}.dropdown i{font-size:30px}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2$3.MatChipList, selector: "mat-chip-list", inputs: ["errorStateMatcher", "multiple", "compareWith", "value", "required", "placeholder", "disabled", "aria-orientation", "selectable", "tabIndex"], outputs: ["change", "valueChange"], exportAs: ["matChipList"] }, { type: i4.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2$3.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["color", "disableRipple", "tabIndex", "selected", "value", "selectable", "disabled", "removable"], outputs: ["selectionChange", "destroyed", "removed"], exportAs: ["matChip"] }, { type: i2$3.MatChipRemove, selector: "[matChipRemove]" }, { type: i2$3.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { type: i1$1.MatSuffix, selector: "[matSuffix]" }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }, { type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: DragDropDirective, selector: "[dragDrop]", outputs: ["files"] }] });
2877
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileInputComponent, decorators: [{
2878
+ type: Component,
2879
+ args: [{ selector: 'file-input', template: "<input #fileInput\n type=\"file\" hidden\n [multiple]=\"metadata.multiple\"\n [accept]=\"FileUtilities.getAcceptString(metadata.allowedMimeTypes)\"\n (change)=\"setFileFromInput($event)\"\n>\n\n<mat-form-field floatLabel=\"always\" (click)=\"fileInput.click()\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"filenames\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let name of filenames\" (removed)=\"removeFile(name)\">\n {{name}}\n <button matChipRemove>\n <i class=\"{{metadata.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input [matChipInputFor]=\"chipList\" [readonly]=\"true\">\n </mat-chip-list>\n <button mat-icon-button matSuffix>\n <i class=\"fas fa-upload\"></i>\n </button>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>\n\n<div *ngIf=\"metadata.dragAndDrop\" class=\"dropdown\" dragDrop (files)=\"setFile($event)\">\n <i class=\"fas fa-file-arrow-up\"></i>\n</div>", styles: ["mat-form-field{width:100%}input:hover,mat-form-field:hover{cursor:pointer}i{color:#757575}.dropdown{display:flex;align-items:center;justify-content:center;height:200px;border:2px dashed #757575;border-radius:15px;margin-top:5px;margin-bottom:5px}.dropdown i{font-size:30px}\n"] }]
2880
+ }], ctorParameters: function () { return [{ type: i1.MatDialog }]; }, propDecorators: { entity: [{
2881
+ type: Input
2882
+ }], key: [{
2883
+ type: Input
2884
+ }], getValidationErrorMessage: [{
2885
+ type: Input
2886
+ }], fileDataChangeEvent: [{
2887
+ type: Output
2888
+ }] } });
2889
+
2890
+ /* eslint-disable jsdoc/require-jsdoc */
2891
+ class FileDefaultInputComponent {
2892
+ constructor() {
2893
+ this.FileUtilities = FileUtilities;
2894
+ this.inputChangeEvent = new EventEmitter();
2895
+ }
2896
+ async ngOnInit() {
2897
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.FILE_DEFAULT);
2898
+ }
2899
+ async refreshFileData(fileData) {
2900
+ this.entity[this.key] = fileData;
2901
+ this.emitChange();
2902
+ }
2903
+ emitChange() {
2904
+ this.inputChangeEvent.emit();
2905
+ }
2906
+ }
2907
+ FileDefaultInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileDefaultInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2908
+ FileDefaultInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: FileDefaultInputComponent, selector: "file-default-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<div *ngIf=\"metadata.dragAndDrop\" class=\"file-input mat-elevation-z8\">\n <file-input (fileDataChangeEvent)=\"refreshFileData($event)\" [entity]=\"entity\" [key]=\"key\" [getValidationErrorMessage]=\"getValidationErrorMessage\"></file-input>\n</div>\n\n<div *ngIf=\"!metadata.dragAndDrop\">\n <file-input (fileDataChangeEvent)=\"refreshFileData($event)\" [entity]=\"entity\" [key]=\"key\" [getValidationErrorMessage]=\"getValidationErrorMessage\"></file-input>\n</div>", styles: [".file-input{margin-top:15px;margin-bottom:15px;padding:15px;border-radius:5px}\n"], components: [{ type: FileInputComponent, selector: "file-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["fileDataChangeEvent"] }], directives: [{ type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
2909
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileDefaultInputComponent, decorators: [{
2910
+ type: Component,
2911
+ args: [{ selector: 'file-default-input', template: "<div *ngIf=\"metadata.dragAndDrop\" class=\"file-input mat-elevation-z8\">\n <file-input (fileDataChangeEvent)=\"refreshFileData($event)\" [entity]=\"entity\" [key]=\"key\" [getValidationErrorMessage]=\"getValidationErrorMessage\"></file-input>\n</div>\n\n<div *ngIf=\"!metadata.dragAndDrop\">\n <file-input (fileDataChangeEvent)=\"refreshFileData($event)\" [entity]=\"entity\" [key]=\"key\" [getValidationErrorMessage]=\"getValidationErrorMessage\"></file-input>\n</div>", styles: [".file-input{margin-top:15px;margin-bottom:15px;padding:15px;border-radius:5px}\n"] }]
2912
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
2913
+ type: Input
2914
+ }], key: [{
2915
+ type: Input
2916
+ }], getValidationErrorMessage: [{
2917
+ type: Input
2918
+ }], inputChangeEvent: [{
2919
+ type: Output
2920
+ }] } });
2921
+
2922
+ // eslint-disable-next-line max-len
2923
+ const placeholder = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABLAAAAMgCAMAAAAEPmswAAAANlBMVEXx8/XCy9LFztXu8PPs7/Lp7e/W3OHL0tnZ3+PN1NrS2d7i5urn6u7f5OjI0Nfc4ebP1tzk6excnoRZAAAXh0lEQVR42uzUAQ0AAAzDoN+/6eloAiK4B4gQFpAhLCBDWECGsIAMYQEZwgIyhAVkCAvIEBaQISwgQ1hAhrCADGEBGcICMoQFZAgLyBAWkCEsIENYQIawgAxhARnCAjKEBWQIC8gQFpAhLCBDWECGsIAMYQEZwgIyhAVkCAvIEBaQISwgQ1hAhrCADGEBGcICMoQFZAgLyBAWkCEsIENYQIawgAxhARnCAjKEBWQIC8gQFpAhLGDs1AEJAAAAgKD/r9sR6Ag3hAVsCAvYEBawISxgQ1jAhrCADWEBG8ICNoQFbAgL2BAWsCEsYENYwIawgA1hARvCAjaEBWwIC9gQFrAhLGBDWMCGsIANYQEbwgI2hAVsCAvYEBawISxgQ1jAhrCADWEBG8ICNoQFbAgL2BAWsCEsYENYwIawgA1hARvCAjaEBWwIC9gQFrAhLGBDWMCGsIANYQEbwgI2hAVsCAvYEBbETh2QAAAAAAj6/7odgY6QDWEBG8ICNoQFbAgL2BAWsCEsYENYwIawgA1hARvCAjaEBWwIC9gQFrAhLGBDWMCGsIANYQEbwgI2hAVsCAvYEBawISxgQ1jAhrCADWEBG8ICNoQFbAgL2BAWsCEsYENYwIawgA1hARvCAjaEBWwIC9gQFrAhLGBDWMCGsIANYQEbwgI2hAVsCAvYEBawISxgQ1jAhrCADWEBG8ICNoRF7NQBCQAAAICg/6/bEegIYUNYwIawgA1hARvCAjaEBWwIC9gQFrAhLGBDWMCGsIANYQEbwgI2hAVsCAvYEBawISxgQ1jAhrCADWEBG8ICNoQFbAgL2BAWsCEsYENYwIawgA1hARvCAjaEBWwIC9gQFrAhLGBDWMCGsIANYQEbwgI2hAVsCAvYEBawISxgQ1jAhrCADWEBG8ICNoQFbAgL2BAWsCEsYENYwIawgA1hxc6dJtcKAgEURgREwGn/m32Vd1Op/Ih3cO72fIs4BU0rADEIFgAxCBYAMQgWADEIFgAxCBbwm+3bFOKQ8zSV4r13zvky5a4bYgxjYyuch2ABD7ZJMRdnXnIlDyE1FY5HsADbhmFy5lM+x7GvcCSChXtrQufNCnXpQlvhIAQLt2XHONVmE2VIzLaOQLBwT230ZlsuBy6IeyNYuB+bOmd24TpOWrsiWLiZJhazKz8w09oNwcKd9NGbA9SZg9Y+CBZuw4ZijlMiE63tESzcg02TOZqnWVsjWLiDpqvNKXxkI35LBAv6pWJO5APzrM0QLChnozNnm5jBb4RgQbU2m0uoO3YdtkCwoFjy5jp85Ji1GsGCWpfK1X95rLAKwYJS4XK54pi1HsGCSuH8SfucjkWH5QgWFLpwrr6UVGEZggV10rVz9cVxM1yGYEGZthgJ6oHPdhYgWFClv8jeFcOsfRAsKGIHI8rENumHCBb0iLWRhvn7ZwgWtGgvuXj1kidZHyBY0MF2RiqS9T6CBRWCvNsgyVqAYEGBRsYqA8lajWBBPGlvg38rvBi+gWBBuvb6i+3vmdjLeolgQTYdx6tvme33FwgWRBO6yzBr4BvDpwgWJNN0vHqo+Sz6GYIFuRplx6sHx4PhPIIFsaJRigfDWQQLQvXid6+Yvn+OYEGmUfRq+2uMsv5EsCCSvmk7o6x3ECwIpPo6yCLpEwQL8iTl10G2smYRLIij/zrIvXAOwYIwvcrlq1kT74W/ESzIMmr51Plddazwg2BBlGDux7NH+oNgQRK5/0Fm+L4JgvWPvbvRSRiGAjBaBoqK+PP+L2s0xGSj3QiQ9I57zkN86brblvVItn1l8/2cYLEar1mmGWoOFlm/BIu1yLh9ZZE1IVisRNLtK4usEcFiFYbvwtYiS7BYg7zb7WPfFlmCRXj7bNOiFlkNgkV8j373lZ2siwkW4SX/PTi1+9pkJljEluhyhgsdMy+yBIvQDoWpXeLThYJFYMYZ6vJe4SBYxDWkuAv5Gu9Z78kSLMIajF8ZcBgRLOL6MH5l731MsAhrb/zK3vuEYBFV6ttk7L3XCRZBvRUcLpwSLGLSK3PvFYJFSHrls7BGsIhIr3wWVgkWATnu7G9hnWARj175LGwQLMLRK5+FLYJFNHp1jd1+k4NgEYpeXel5k4JgEYleXe24yUCwCESvXDkzR7CIxPzVTbYJxt4FizD0ynzDPMEiDr3yCtgCwSKMr8Ltnh58I0uwiOG1cA/bxz6oI1iE4L4+E1nLBIsY3IdsIusCgkUI3pu4q/fH3XoXLPob9OqXo4VLBIsAvD944tnCBYJFAN53PjFDukCw6O9Q+GPrfYlg0d2x8M+tfrMEi94+CyOm3tsEi65cKDNl6n2OYNGTA89Vpt5bBIuOHCCs8rOwSbDoaW9gtMbPwhbBohsD7k1+FjYIFv0MBkbb/CysESx6MTA6z8nCCsGiEwNYS7xOcU6w6OWlsMB4ww9794LdJgyEUXgwAsfFL/a/2Z4+T2zjWCMgnl/cbwttbxppNNwjWHgLBrByMN5wj2Ct4HztL+OxS621qTuOp/5a06HnItgw+v0uTRUI1qL2/dDao3b8qO+RRDkGGt5haGpAsJZzPbX2XDvUc/I5ExuwsrE4+QbBWsz+I9kr6VLR/XI5Nsq8SVdBsQjWIg6D5Rn5bxYbGpwYyPqPYC3iMFq+4+aTxSeevdg38xfBWsB5MJ+j/s+5Oc5cEDoxQvoPwZrvozW3SwWHCWX4RM67iX9Oh2DNc+isRFL/QVduNBRg6P0XgjVTv/nJYx9eEAYgXSyCNcNu2PpUjBMXhCEo/7AkWKVm78tM8jc2XqxEDkL4mQ7BKnZot35j48QFYRi6z3QIVqlru/kbGx8uCAORLRbBKvSD808nVoxGorrpnWCVuTIV48TKvlhEL30IVoEl1zlt5xyLlX2xaBaLYJU4J153+bCyLx7J5Q0Ey23hw+Ok+NfGiwP3iBSLRbAKDLaksdkCDtwDSnrLuwmWX29mDB57MOEelF6xCJbTGocx9R9jMeEelNxKP4Ll1tlvHGPl4psTgbVixSJYXr39wS+FuVgpE5lYsQiW0661FcgdJTiwUiY2rd8KCZbTyf7ipjAPO9yjk/o/FsHy2dstBt5fYEVDfErFIlg+g63j2FSLidHwhJ5bECyXs33GaMNLfDRVgk6xCJbLyT7jFOsVJkZFyBSLYHnsbD1C5wgOe4MElWIRLI/e7rFn+ws8eRYiUiyC5dHZelJTIZ4869C4KyRYDnu7x2TDF9gxqkWiWATL4WJrOjW14cmzFoViESyHZGtqm8rw5FmNwCsdgpXvbI8YxXqGJ8+C4heLYOXr7RE7G57gAEtS+I1+BCvfyaYwOzqFAyxR0YtFsPIle8Qh1iQOsGQFLxbByrazCQy7T2ICS1fsb+kQrGwHe4rPQN/iCaGy0MUiWNl6m8Kp+yN2YGmL/E1ogpXtYtMYHb3HDixxgYtFsLIN9gRb/G6xxF1e3AtrgpXtaM/w/vkzlrhXYGiCIljZOntAsKbsOMDSF7VYBCtbsrVV8ofBk5waBD1QreTfyPoIVh6e5NQi5kbJOv6NfAtbX9zLmVw8yanHT/buBDt1GIbCsJwRCOP+N/t62vNaphLbSZEs/98O2gOXyJFkk102BFYkAisGIzmeDMEeAitaK09REl5hJMcVg6MXHr4jb8EZVgRGcpyxl1gOviPv0stzrGv4MdLR4Iu5pZIEViQaR+cxkuOOucu/CKxIjObMYiTHIWsXUxBY0TbynPtevUiM5LhkbKEfgRWJ9TIz6GhwytZ6LAIrEgv8ZtDR4JWpZTMEViRWJM/ZCXyytGyGwIrFJRSvsGTUM0OHqwRWLK75eoUdDa7ZGYQmsOLt5CnO3EOgxd05M59NAisWV9W/MgpcszIITWAl6OUeR1ifaHH37xxMILASnOSBz5NNY/8ZGGBkSIfASjDKDZ8/YelY2lcFG0M6BFaKXh4w+UyLeyU6Cw2kBFaKQW75fHOc7CCogYUhHQIrRSN3aHMPtLjXw0CnIIGV5CT3vN8DN4eCsCb6L4YIrCRHuUYTVgi0uFdFvYGUwEpzkP/cPWxnocW9MkPQRGClGuUKPQ1sca/OOSgisJId5BsnWB/2gqqoNpASWMmaVv6ArTW00biXvkLtMaghsNIN8snXUWYeZp6rpNiORWBl2Mva+lAqZp5rtA9aCKxk36s1aWlg5rlWU1BCYOXYyQcKQmae63UKOgisLAcRoQWLgrBiQ1BBYGVpem8z8BkoCKt2DhoIrDzHztmWoXQUhHXT+dwSWJnGtvoDd2ae66ZSGRBYubbVX/ZMQVg5jXYsAivbueyzSyN/Pwo2hbcjsPJt25qfrygIodDcQGAtMHZlj5EuwFZkqBQIBNYSx16W6Ip9P0hBCJ3mBgJrkeYg+S7F9l9REEKpuYHAWmiobx4nBApCKDU3EFhLjb3k6As+vuKaHGhtbiCwlhvayh6vKAihdZEOgbWCZpI0l2L3i36ZBFD59SWwVjFOKXFVdDUYKAih101IYK0iIbKm0uMqNFyTA615WAJrNcdNL3O6TcGtV18oCKH4qpDAWtP21MnvukOxdw/+oCCE5qtCAmtlx2Hq5FE7DQ6erUKgIITqHDSB9Qea7XCaLvu+a7u+30+nYVtwT/stCkKovioksJCAgvAfe3eU6ygMBFG0GhtCSAxh/5udUWby8Z4COGCgI92ziJLLuBuc+6mQwEI+nozi9KlCAgu5KIQ4/VMhgYVMFEKc/6mQwEIeCiEcTBUSWMhDIYSDBaQEFrJQCOFhASmBhRwUQiwLve2LwEIetozCxb8KCSxk4LcT8DGjQ2BhGYUQTmZ0CCwsoxDCyYwOgYVFFEJ4mdEhsLCEQgg3MzoEFpZQCPGJ0XZDYGERhRCfGWwvBBaWUAjh6OKdwMI8CiE+drF9EFhYQCGEp4t3AgtzKIRwdfFOYGEOhRCuLt4JLMy6CvBz8U5gYU5VC/Dz4p3AwpxBgKNVMwQWJlEI4W3VDIGFGRRC+Fo1Q2BhCoUQ7na8E1iYdBHga8c7gYUJFEL4u3gnsDClFeDs4p3AwjsUQrj8uarsCP21a4Z0G+sYQwiSQoixvo9paJvHpTI4RCFEAVcrSrar/tEMY9SCeL+1zaM3OEIhhMPFDbK9VF07Bn2kTs2V45YPFEJ4XNwg20PfpKgJOallONtdgL/FDbLSqi7V2qpOHUetU1AI8eR0cYOsqKq7BRVybzlpHY5CiH+cvh+VlVN1o8oKt4ar+CNRCPHi8/2orJRrCtpDTA/DISiE2EeyUmRFVG3UfgKZdQAKIX7y+H5UVkA/BP1GZn0vCiGeHP74S7bZJek9Mus7NQL+8vh+VLZRlXSckC6GnfUCnhyOQcu2aYOOVTc80CqOQoj33O0flW3RRR0vJN5nlUUhxAR3Y9Cy9aqb8nHM+g59EPDi7hpLtloXdCKOWYVQCDHP1Ri0LJOf49VL3Rm2ohBiga9rLFkeX8er/yLNcBsKIXI4+o2ObAU//38KA7OGJY0CfvM0Bi1bofd00cHTrLUohDja3TaSfe4R5crIC/gVKIR/2Lvb5NRhGArD54RvCC3sf7N3Op07UyhJ7PQHsvU+W4BxIvlIQbkw2/zkMrFH+em/V6MgRKlIbSy50hDzX82RVYeCEMUitbHkOh9hP/60ozAsRkGIGoHaWHKVQ7D21YORI6sCkVGUC9PGkqcFTV9xZP0RBSGqRWljyb+1/J/myKrAllG8w2bwavKEwGnReXdyWXMoCPF2o1eTi719eLDUlYGdOa1kVdCvo9eSH/RwXkmbI0fWSxSEiOHmleRnTcWvpmz3RoWwYRX0afVuLLnI0FyLg1jWMwpCxHH3OnKJocUn8Ej3/QcKQoRy9Cryt/7OK7rvDygIEcvJa8hf+jyvaGX91HpcBZ1Z18aS7W7PK0kjq9+XnAS8wcUryO75vKIutE1BiJD2rifb7ut+8NmGupCCEBEdXE3dn1eSdtSFFISIZze4lvxf10soqQsnDJH3BaF3V9dSivNK2rKR9KWrgPc5u5LcyfzgogsfBPvtJuB96hcmK08/luY7BSGi2bmOMk2YMazT8Rs02vTpKvKks/pzNPr+hdGam2soWXuDhAOfyUEodSM68oRTr//mTxIOvV0Bo2l3V5BfO/R6XvGS1dAnRZDC3uWU8fro02AJFsI4uJhSfkNlx3UhM88Io2JER0nzz+mvC/vK2KFtV5dSigAWL1nMPCOyswspbzwn80tW3z1KNKd4REeJH75j3ulCIu6IZXQZ+dlHnofvJusKhyTv0GjI0UXU20bkOpeUKVIi7ojn5BJKXixsM6ZIOw+toEllIzpKeEGYPUWa7zdGC64uIJob2XrvaS5V0JizlynLBCGb/Ug0ILbN4EXK23BP2ntP1qREQ+5eJPaNfNmmyb2zowFx7b1ENGO/JSkLcxb9aMXBC5S74Z6uLMxa9KMNOy8Qz95MkSx2NCC2q+cpfcM90zh0n3v60ZObZ4nLox/ufZeFQ/aXaMS3EHgXl0d5ysK8t8Box8VzRPo5zW1h6ltgNGPvGSL9nOW2kAYWmjC7zE80sJIsT+ahhEaMniZqhSR7/f6xdy+4iQNBEEDdQYEA4Xf/y+5ukk2AYAkFKXKX3ztEWe6p6THAoouXGjUYYM1j5YyPEn2saszgX2EWK2cMsGhk/KHCwb/CTYtjJfFRopVDjRj8K8yh9m4pMr0c67bBAGsG/QZXCGlmrPA++FcY9ZwyyJr5Hg462tZNA/GDLK960dCmvhNYMxhk2cNBR7cK7wJrBoOs3QANneobgZU/yLKHg6aWdU1gxQ+ynALT1qquCKz0jTMao/T1WlcE1l121ZbGKI291CWBdZ/XrqN3A3daW9UFgZX90KqBO7091wWBFb0jy8Cd7g51TmAld0g13OlvXWcEVnCHVMOdABe3oAVW8Ojdon4S7OqLwModvdtzRoZjfRJYsaN3K2UIcfZTKLBSR+8OCImxrf8EVmjr3QEhQTb1QWBljt4dEJJk8VTvBFbm6N1DSETZ1juBFblwxpsThNnUG4GVuHBGoYE0Hz+FAivwsNCNZ/Js6x+B9VPbmiqP0pNoWX8JrLjDwpVCA4nefgoFVtph4d5KZDKdqkpgPWCxrslRwCLWskpgPWRyNwufrHAn1mJfAivqsFBekexUAivqZqGCO9GWAutRpwkdFtrYR7bFXmDlPGXvSS/SnQRWTL1BXpHPNY6Uu9AuPDMDatEhd6HlFdCl3iCvgC71BnkFdLkLbd4OdKk3yCugS71BXgFd6g367UCTeoP7zsAPHeoe9l8BU7CrX7WyXxRoUm9Yu6gA/GHvDnMThmEwgNZpF9LQUrj/ZfdvmmBMDEabSu8dIkrsz85O4g3VeQW8ZhjjPv+lAk3pa9whzgA0J8ePxBmABs3xZqP2ILCTVe/2LgI7aRYm04NA1+1iFvog3Q503S6ahZ6DwJe2FycnaQbgLY4p/lnVHQS+abj07noFXGl2TsfsIHCrydS76xVwq8lCViquV8D7fRwU24HdyPGa0aQzsJrpFM8bFa+ANfUlnnS+dADrGmo8oZobBLYwLKf4k1NRagc2M9UUD0rZWxDYVj8/cmalOotdAS2Yyhi/OBcpBqAh/WXJY4or6ZwXhxXQpGE6znMpOZdlmY+TVyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDJHhwIAAAAAAD5vzaCqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqwBwcCAAAAAED+r42gqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqirswYEAAAAAAJD/ayOoqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqkp7cCAAAAAAIMjfepArAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgKcAnTNeiLeG1rEAAAAASUVORK5CYII=';
2924
+
2925
+ /* eslint-disable jsdoc/require-jsdoc */
2926
+ class FileImageInputComponent {
2927
+ constructor() {
2928
+ this.FileUtilities = FileUtilities;
2929
+ this.inputChangeEvent = new EventEmitter();
2930
+ this.imageIndex = 0;
2931
+ this.placeHolder = placeholder;
2932
+ }
2933
+ async ngOnInit() {
2934
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.FILE_IMAGE);
2935
+ // setting the image is done inside the refresh method
2936
+ }
2937
+ async setSinglePreviewImage() {
2938
+ let singleFileData = this.entity[this.key];
2939
+ if (singleFileData) {
2940
+ singleFileData = await FileUtilities.getFileData(singleFileData);
2941
+ this.singlePreviewImage = await FileUtilities.getDataURLFromFile(singleFileData.file);
2942
+ }
2943
+ else {
2944
+ this.singlePreviewImage = undefined;
2945
+ }
2946
+ }
2947
+ async setMultiPreviewImages(index) {
2948
+ const multiFileData = this.entity[this.key];
2949
+ const previewImages = [];
2950
+ if (multiFileData?.length) {
2951
+ for (let i = 0; i < multiFileData.length; i++) {
2952
+ if (i === index) {
2953
+ multiFileData[index] = await FileUtilities.getFileData(multiFileData[index]);
2954
+ previewImages.push(await FileUtilities.getDataURLFromFile(multiFileData[index].file));
2955
+ }
2956
+ else {
2957
+ previewImages.push('empty');
2958
+ }
2959
+ }
2960
+ }
2961
+ this.multiPreviewImages = previewImages;
2962
+ }
2963
+ async refreshFileData(fileData) {
2964
+ this.entity[this.key] = fileData;
2965
+ this.emitChange();
2966
+ if (this.metadata.multiple) {
2967
+ if (!(fileData?.[this.imageIndex])) {
2968
+ this.imageIndex = 0;
2969
+ }
2970
+ await this.setMultiPreviewImages(this.imageIndex);
2971
+ }
2972
+ else {
2973
+ await this.setSinglePreviewImage();
2974
+ }
2975
+ }
2976
+ async prev() {
2977
+ if (this.imageIndex > 0) {
2978
+ await this.setMultiPreviewImages(this.imageIndex - 1);
2979
+ this.imageIndex--;
2980
+ }
2981
+ }
2982
+ async next() {
2983
+ if (this.multiPreviewImages?.length && this.imageIndex !== (this.multiPreviewImages.length - 1)) {
2984
+ await this.setMultiPreviewImages(this.imageIndex + 1);
2985
+ this.imageIndex++;
2986
+ }
2987
+ }
2988
+ async setIndex(index) {
2989
+ await this.setMultiPreviewImages(index);
2990
+ this.imageIndex = index;
2991
+ }
2992
+ emitChange() {
2993
+ this.inputChangeEvent.emit();
2994
+ }
2995
+ }
2996
+ FileImageInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileImageInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2997
+ FileImageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: FileImageInputComponent, selector: "file-image-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: "<div *ngIf=\"!metadata.dragAndDrop && !metadata.preview\">\n <file-input (fileDataChangeEvent)=\"refreshFileData($event)\" [entity]=\"entity\" [key]=\"key\" [getValidationErrorMessage]=\"getValidationErrorMessage\"></file-input>\n</div>\n\n<div *ngIf=\"metadata.dragAndDrop || metadata.preview\" class=\"file-input mat-elevation-z8\">\n <file-input (fileDataChangeEvent)=\"refreshFileData($event)\" [entity]=\"entity\" [key]=\"key\" [getValidationErrorMessage]=\"getValidationErrorMessage\"></file-input>\n\n <div class=\"image-preview\" *ngIf=\"metadata.preview && metadata.multiple\">\n <i (click)=\"prev()\" [class.disabled]=\"imageIndex === 0\" class=\"prev-button fa-solid fa-angle-left\"></i>\n <img *ngIf=\"multiPreviewImages?.[imageIndex]\" class=\"mat-elevation-z2\" [src]=\"multiPreviewImages?.[imageIndex]\">\n <img *ngIf=\"!multiPreviewImages?.[imageIndex]\" class=\"mat-elevation-z2\" [src]=\"metadata.previewPlaceholderUrl ?? placeHolder\">\n <i (click)=\"next()\" [class.disabled]=\"!multiPreviewImages || !multiPreviewImages.length || imageIndex === (multiPreviewImages.length - 1)\" class=\"next-button fa-solid fa-angle-right\"></i>\n </div>\n <div class=\"preview-nav\" *ngIf=\"metadata.preview && metadata.multiple\">\n <button (click)=\"setIndex(imageIndex-4)\" mat-icon-button *ngIf=\"\n this.multiPreviewImages\n && multiPreviewImages[imageIndex-4]\n && imageIndex === (this.multiPreviewImages.length - 1)\"\n >\n <span class=\"dot\"></span>\n <span class=\"image-index\">{{imageIndex - 3}}</span>\n </button>\n <!-- eslint-disable-next-line @angular-eslint/template/conditional-complexity -->\n <button (click)=\"setIndex(imageIndex-3)\" mat-icon-button *ngIf=\"this.multiPreviewImages\n && multiPreviewImages[imageIndex-3]\n && (\n imageIndex === (this.multiPreviewImages.length - 2)\n || imageIndex === (this.multiPreviewImages.length - 1)\n )\"\n >\n <span class=\"dot\"></span>\n <span class=\"image-index\">{{imageIndex - 2}}</span>\n </button>\n <button (click)=\"setIndex(imageIndex-2)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex-2]\">\n <span class=\"dot\"></span>\n <span class=\"image-index\">{{imageIndex - 1}}</span>\n </button>\n <button (click)=\"setIndex(imageIndex-1)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex-1]\">\n <i class=\"dot\"></i>\n <span class=\"image-index\">{{imageIndex}}</span>\n </button>\n <button mat-icon-button disabled>\n <i class=\"dot selected\"></i>\n <span class=\"image-index\">{{imageIndex + 1}}</span>\n </button>\n <button (click)=\"setIndex(imageIndex+1)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+1]\">\n <span class=\"dot\"></span>\n <span class=\"image-index\">{{imageIndex + 2}}</span>\n </button>\n <button (click)=\"setIndex(imageIndex+2)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+2]\">\n <span class=\"dot\"></span>\n <span class=\"image-index\">{{imageIndex + 3}}</span>\n </button>\n <button (click)=\"setIndex(imageIndex+3)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+3] && imageIndex <= 1\">\n <span class=\"dot\"></span>\n <span class=\"image-index\">{{imageIndex + 4}}</span>\n </button>\n <button (click)=\"setIndex(imageIndex+4)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+4] && imageIndex === 0\">\n <span class=\"dot\"></span>\n <span class=\"image-index\">{{imageIndex + 5}}</span>\n </button>\n </div>\n\n <div class=\"image-preview\" *ngIf=\"metadata.preview && !metadata.multiple\">\n <i class=\"prev-button disabled fa-solid fa-angle-left\"></i>\n <img class=\"mat-elevation-z2\" [src]=\"singlePreviewImage ?? metadata.previewPlaceholderUrl ?? placeHolder\">\n <i class=\"next-button disabled fa-solid fa-angle-right\"></i>\n </div>\n <div class=\"preview-nav\" *ngIf=\"metadata.preview && !metadata.multiple\">\n <button disabled mat-icon-button>\n <span class=\"dot selected\"></span>\n <span class=\"image-index\">1</span>\n </button>\n </div>\n</div>", styles: [".file-input{margin-top:15px;margin-bottom:15px;padding:15px;border-radius:5px}.image-preview{height:250px;display:flex;align-items:center;padding-top:15px;padding-bottom:15px}.image-preview .prev-button{font-size:100px;margin-left:5px}.image-preview .next-button{font-size:100px;margin-right:5px}.image-preview .prev-button:hover,.image-preview .next-button:hover{cursor:pointer}.image-preview .prev-button.disabled,.image-preview .next-button.disabled{color:#00000061}.image-preview .prev-button.disabled:hover,.image-preview .next-button.disabled:hover{cursor:default}.image-preview img{max-width:calc(100% - 100px);max-height:100%;margin-left:auto;margin-right:auto;border-radius:3px}.preview-nav{text-align:center}.preview-nav button{display:inline-block;width:18px;height:18px;margin-left:5px;margin-right:5px}.preview-nav button .dot{height:100%;width:100%;background-color:#00000061;border-radius:50%;display:block}.preview-nav button .dot.selected{background-color:#000000de}.preview-nav button .image-index{position:absolute;height:100%;width:100%;display:block;top:-11.5px;color:#fff}.preview-nav button:hover{background-color:#000}\n"], components: [{ type: FileInputComponent, selector: "file-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["fileDataChangeEvent"] }, { type: i4.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
2998
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileImageInputComponent, decorators: [{
2999
+ type: Component,
3000
+ args: [{ selector: 'file-image-input', template: "<div *ngIf=\"!metadata.dragAndDrop && !metadata.preview\">\n <file-input (fileDataChangeEvent)=\"refreshFileData($event)\" [entity]=\"entity\" [key]=\"key\" [getValidationErrorMessage]=\"getValidationErrorMessage\"></file-input>\n</div>\n\n<div *ngIf=\"metadata.dragAndDrop || metadata.preview\" class=\"file-input mat-elevation-z8\">\n <file-input (fileDataChangeEvent)=\"refreshFileData($event)\" [entity]=\"entity\" [key]=\"key\" [getValidationErrorMessage]=\"getValidationErrorMessage\"></file-input>\n\n <div class=\"image-preview\" *ngIf=\"metadata.preview && metadata.multiple\">\n <i (click)=\"prev()\" [class.disabled]=\"imageIndex === 0\" class=\"prev-button fa-solid fa-angle-left\"></i>\n <img *ngIf=\"multiPreviewImages?.[imageIndex]\" class=\"mat-elevation-z2\" [src]=\"multiPreviewImages?.[imageIndex]\">\n <img *ngIf=\"!multiPreviewImages?.[imageIndex]\" class=\"mat-elevation-z2\" [src]=\"metadata.previewPlaceholderUrl ?? placeHolder\">\n <i (click)=\"next()\" [class.disabled]=\"!multiPreviewImages || !multiPreviewImages.length || imageIndex === (multiPreviewImages.length - 1)\" class=\"next-button fa-solid fa-angle-right\"></i>\n </div>\n <div class=\"preview-nav\" *ngIf=\"metadata.preview && metadata.multiple\">\n <button (click)=\"setIndex(imageIndex-4)\" mat-icon-button *ngIf=\"\n this.multiPreviewImages\n && multiPreviewImages[imageIndex-4]\n && imageIndex === (this.multiPreviewImages.length - 1)\"\n >\n <span class=\"dot\"></span>\n <span class=\"image-index\">{{imageIndex - 3}}</span>\n </button>\n <!-- eslint-disable-next-line @angular-eslint/template/conditional-complexity -->\n <button (click)=\"setIndex(imageIndex-3)\" mat-icon-button *ngIf=\"this.multiPreviewImages\n && multiPreviewImages[imageIndex-3]\n && (\n imageIndex === (this.multiPreviewImages.length - 2)\n || imageIndex === (this.multiPreviewImages.length - 1)\n )\"\n >\n <span class=\"dot\"></span>\n <span class=\"image-index\">{{imageIndex - 2}}</span>\n </button>\n <button (click)=\"setIndex(imageIndex-2)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex-2]\">\n <span class=\"dot\"></span>\n <span class=\"image-index\">{{imageIndex - 1}}</span>\n </button>\n <button (click)=\"setIndex(imageIndex-1)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex-1]\">\n <i class=\"dot\"></i>\n <span class=\"image-index\">{{imageIndex}}</span>\n </button>\n <button mat-icon-button disabled>\n <i class=\"dot selected\"></i>\n <span class=\"image-index\">{{imageIndex + 1}}</span>\n </button>\n <button (click)=\"setIndex(imageIndex+1)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+1]\">\n <span class=\"dot\"></span>\n <span class=\"image-index\">{{imageIndex + 2}}</span>\n </button>\n <button (click)=\"setIndex(imageIndex+2)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+2]\">\n <span class=\"dot\"></span>\n <span class=\"image-index\">{{imageIndex + 3}}</span>\n </button>\n <button (click)=\"setIndex(imageIndex+3)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+3] && imageIndex <= 1\">\n <span class=\"dot\"></span>\n <span class=\"image-index\">{{imageIndex + 4}}</span>\n </button>\n <button (click)=\"setIndex(imageIndex+4)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+4] && imageIndex === 0\">\n <span class=\"dot\"></span>\n <span class=\"image-index\">{{imageIndex + 5}}</span>\n </button>\n </div>\n\n <div class=\"image-preview\" *ngIf=\"metadata.preview && !metadata.multiple\">\n <i class=\"prev-button disabled fa-solid fa-angle-left\"></i>\n <img class=\"mat-elevation-z2\" [src]=\"singlePreviewImage ?? metadata.previewPlaceholderUrl ?? placeHolder\">\n <i class=\"next-button disabled fa-solid fa-angle-right\"></i>\n </div>\n <div class=\"preview-nav\" *ngIf=\"metadata.preview && !metadata.multiple\">\n <button disabled mat-icon-button>\n <span class=\"dot selected\"></span>\n <span class=\"image-index\">1</span>\n </button>\n </div>\n</div>", styles: [".file-input{margin-top:15px;margin-bottom:15px;padding:15px;border-radius:5px}.image-preview{height:250px;display:flex;align-items:center;padding-top:15px;padding-bottom:15px}.image-preview .prev-button{font-size:100px;margin-left:5px}.image-preview .next-button{font-size:100px;margin-right:5px}.image-preview .prev-button:hover,.image-preview .next-button:hover{cursor:pointer}.image-preview .prev-button.disabled,.image-preview .next-button.disabled{color:#00000061}.image-preview .prev-button.disabled:hover,.image-preview .next-button.disabled:hover{cursor:default}.image-preview img{max-width:calc(100% - 100px);max-height:100%;margin-left:auto;margin-right:auto;border-radius:3px}.preview-nav{text-align:center}.preview-nav button{display:inline-block;width:18px;height:18px;margin-left:5px;margin-right:5px}.preview-nav button .dot{height:100%;width:100%;background-color:#00000061;border-radius:50%;display:block}.preview-nav button .dot.selected{background-color:#000000de}.preview-nav button .image-index{position:absolute;height:100%;width:100%;display:block;top:-11.5px;color:#fff}.preview-nav button:hover{background-color:#000}\n"] }]
3001
+ }], ctorParameters: function () { return []; }, propDecorators: { entity: [{
3002
+ type: Input
3003
+ }], key: [{
3004
+ type: Input
3005
+ }], getValidationErrorMessage: [{
3006
+ type: Input
3007
+ }], inputChangeEvent: [{
3008
+ type: Output
3009
+ }] } });
3010
+
3011
+ /**
3012
+ * The default input component. It gets the metadata of the property from the given @Input "entity" and @Input "propertyKey"
3013
+ * and displays the input field accordingly.
3014
+ *
3015
+ * You can also define a method that generates error-messages and if the input should be hidden when its metadata says
3016
+ * that it should be omitted for creating or updating.
3017
+ * The last part being mostly relevant if you want to use this component inside an ngFor.
3018
+ */
3019
+ class NgxMatEntityInputComponent {
3020
+ constructor(dialog) {
3021
+ this.dialog = dialog;
3022
+ this.inputChangeEvent = new EventEmitter();
3023
+ this.selection = new SelectionModel(true, []);
3024
+ this.isArrayItemValid = false;
3025
+ this.isDialogArrayItemValid = false;
3026
+ this.DecoratorTypes = DecoratorTypes;
3027
+ this.EntityUtilities = EntityUtilities;
3028
+ this.DateUtilities = DateUtilities;
3029
+ }
3030
+ /**
3031
+ * This is needed for the inputs to work inside an ngFor.
3032
+ *
3033
+ * @param index - The index of the element in the ngFor.
3034
+ * @returns The index.
3035
+ */
3036
+ trackByFn(index) {
3037
+ return index;
3038
+ }
3039
+ ngOnInit() {
3040
+ if (!this.entity) {
1216
3041
  throw new Error('Missing required Input data "entity"');
1217
3042
  }
1218
- if (!this.propertyKey) {
3043
+ this.internalEntity = this.entity;
3044
+ if (this.propertyKey == null) {
1219
3045
  throw new Error('Missing required Input data "propertyKey"');
1220
3046
  }
3047
+ this.internalPropertyKey = this.propertyKey;
3048
+ this.internalGetValidationErrorMessage = this.getValidationErrorMessage ?? getValidationErrorMessage;
1221
3049
  this.type = EntityUtilities.getPropertyType(this.entity, this.propertyKey);
1222
3050
  this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.propertyKey, this.type);
1223
- this.metadataDefaultString = this.metadata;
1224
- this.metadataTextboxString = this.metadata;
1225
- this.metadataAutocompleteString = this.metadata;
1226
- this.autocompleteStrings = this.metadataAutocompleteString.autocompleteValues;
1227
- this.filteredAutocompleteStrings = cloneDeep(this.autocompleteStrings);
1228
- this.metadataDropdownString = this.metadata;
1229
- this.metadataDropdownBoolean = this.metadata;
1230
- if ((this.type === DecoratorTypes.BOOLEAN_CHECKBOX || this.type === DecoratorTypes.BOOLEAN_TOGGLE)
1231
- && this.entity[this.propertyKey] === undefined) {
1232
- this.entity[this.propertyKey] = false;
1233
- }
1234
- this.metadataDefaultNumber = this.metadata;
1235
- this.metadataDropdownNumber = this.metadata;
1236
- this.metadataDefaultObject = this.metadata;
1237
- this.objectProperty = this.entity[this.propertyKey];
1238
3051
  if (this.type === DecoratorTypes.OBJECT) {
1239
- this.objectPropertyRows = EntityUtilities.getEntityRows(this.objectProperty, this.hideOmitForCreate, this.hideOmitForEdit);
3052
+ this.initObjectInput();
1240
3053
  }
1241
- this.metadataEntityArray = this.metadata;
1242
3054
  if (this.type === DecoratorTypes.ARRAY) {
1243
- if (!this.entity[this.propertyKey]) {
1244
- this.entity[this.propertyKey] = [];
1245
- }
1246
- this.entityArrayValues = this.entity[this.propertyKey];
1247
- if (this.metadataEntityArray.createInline === undefined) {
1248
- this.metadataEntityArray.createInline = true;
1249
- }
1250
- if (!this.metadataEntityArray.createInline && !this.metadataEntityArray.createDialogData) {
1251
- this.metadataEntityArray.createDialogData = {
1252
- title: 'Add'
1253
- };
1254
- }
1255
- const givenDisplayColumns = this.metadataEntityArray.displayColumns.map((v) => v.displayName);
1256
- if (givenDisplayColumns.find(s => s === 'select')) {
1257
- throw new Error(`The name "select" for a display column is reserved.
1258
- Please choose a different name.`);
1259
- }
1260
- this.displayedColumns = ['select'].concat(givenDisplayColumns);
1261
- this.dataSource = new MatTableDataSource();
1262
- this.dataSource.data = this.entityArrayValues;
1263
- this.arrayItem = new this.metadataEntityArray.EntityClass();
1264
- this.arrayItemInlineRows = EntityUtilities.getEntityRows(this.arrayItem, this.hideOmitForCreate === false ? false : true, this.hideOmitForEdit ? true : false);
1265
- this.arrayItemPriorChanges = cloneDeep(this.arrayItem);
1266
- this.dialogInputData = {
1267
- entity: this.arrayItem,
1268
- createDialogData: this.metadataEntityArray.createDialogData,
1269
- getValidationErrorMessage: this.getValidationErrorMessage
3055
+ this.initEntityArray();
3056
+ }
3057
+ }
3058
+ initEntityArray() {
3059
+ this.metadataEntityArray = this.metadata;
3060
+ if (this.internalEntity[this.internalPropertyKey] == null) {
3061
+ this.internalEntity[this.internalPropertyKey] = [];
3062
+ }
3063
+ this.entityArrayValues = this.internalEntity[this.internalPropertyKey];
3064
+ if (!this.metadataEntityArray.createInline && !this.metadataEntityArray.createDialogData) {
3065
+ this.metadataEntityArray.createDialogData = {
3066
+ title: 'Add'
1270
3067
  };
1271
- this.dialogData = new AddArrayItemDialogDataBuilder(this.dialogInputData).getResult();
1272
- this.arrayItemDialogRows = EntityUtilities.getEntityRows(this.dialogData.entity, true);
1273
- }
1274
- this.metadataStringChipsArray = this.metadata;
1275
- if ((this.type === DecoratorTypes.ARRAY_STRING_CHIPS || this.type === DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS)
1276
- && this.entity[this.propertyKey]?.length) {
1277
- this.stringChipsArrayValues = this.entity[this.propertyKey];
1278
- }
1279
- this.metadataAutocompleteStringChipsArray = this.metadata;
1280
- if (!this.getValidationErrorMessage) {
1281
- this.getValidationErrorMessage = getValidationErrorMessage;
1282
- }
1283
- this.metadataDefaultDate = this.metadata;
1284
- this.metadataDateRangeDate = this.metadata;
1285
- this.metadataDateTimeDate = this.metadata;
1286
- if (this.type === DecoratorTypes.DATE_RANGE) {
1287
- this.dateRange = cloneDeep(this.entity[this.propertyKey]);
1288
- if (!this.dateRange) {
1289
- this.dateRange = {
1290
- start: undefined,
1291
- end: undefined,
1292
- values: undefined
1293
- };
1294
- }
1295
- this.dateRangeStart = new Date(this.dateRange.start);
1296
- this.dateRangeEnd = new Date(this.dateRange.end);
1297
- this.setDateRangeValues();
1298
- }
1299
- if (this.type === DecoratorTypes.DATE_TIME) {
1300
- this.time = DateUtilities.getTimeFromDate(DateUtilities.asDate(this.entity[this.propertyKey]));
1301
- this.timeDropdownValues = this.metadataDateTimeDate.times;
1302
- if (this.entity[this.propertyKey]) {
1303
- this.dateTime = new Date(this.entity[this.propertyKey]);
1304
- }
1305
3068
  }
3069
+ const givenDisplayColumns = this.metadataEntityArray.displayColumns.map((v) => v.displayName);
3070
+ if (givenDisplayColumns.find(s => s === 'select')) {
3071
+ throw new Error(`The name "select" for a display column is reserved.
3072
+ Please choose a different name.`);
3073
+ }
3074
+ this.displayedColumns = ['select'].concat(givenDisplayColumns);
3075
+ this.dataSource = new MatTableDataSource();
3076
+ this.dataSource.data = this.entityArrayValues;
3077
+ this.arrayItem = new this.metadataEntityArray.EntityClass();
3078
+ this.arrayItemInlineRows = EntityUtilities.getEntityRows(this.arrayItem, this.hideOmitForCreate ?? true, this.hideOmitForEdit);
3079
+ this.arrayItemPriorChanges = LodashUtilities.cloneDeep(this.arrayItem);
3080
+ this.dialogInputData = {
3081
+ entity: this.arrayItem,
3082
+ createDialogData: this.metadataEntityArray.createDialogData,
3083
+ getValidationErrorMessage: this.getValidationErrorMessage
3084
+ };
3085
+ this.dialogData = new AddArrayItemDialogDataBuilder(this.dialogInputData).getResult();
3086
+ this.arrayItemDialogRows = EntityUtilities.getEntityRows(this.dialogData.entity, true);
3087
+ }
3088
+ initObjectInput() {
3089
+ this.metadataDefaultObject = this.metadata;
3090
+ this.objectProperty = this.internalEntity[this.internalPropertyKey];
3091
+ this.objectPropertyRows = EntityUtilities.getEntityRows(this.objectProperty, this.hideOmitForCreate, this.hideOmitForEdit);
1306
3092
  }
1307
3093
  /**
1308
- * Checks if two times are equal. Is needed for the dropdown.
1309
- *
1310
- * @param time1 - The first time to compare.
1311
- * @param time2 - The second time to compare.
1312
- * @returns Whether or not the time objects are the same.
3094
+ * Checks if the arrayItem is valid.
1313
3095
  */
1314
- compareTimes(time1, time2) {
1315
- return time1 && time2 && time1.hours === time2.hours && time1.minutes === time2.minutes;
3096
+ checkIsArrayItemValid() {
3097
+ this.isArrayItemValid = EntityUtilities.isEntityValid(this.arrayItem, 'create');
1316
3098
  }
1317
3099
  /**
1318
- * Updates the date range values based on the start and end date.
3100
+ * Checks if the arrayItem inside the dialog is valid.
1319
3101
  */
1320
- setDateRangeValues() {
1321
- if (this.dateRangeStart && this.dateRangeEnd) {
1322
- this.dateRange.start = new Date(this.dateRangeStart);
1323
- this.dateRange.end = new Date(this.dateRangeEnd);
1324
- const values = DateUtilities.getDatesBetween(new Date(this.dateRange.start), new Date(this.dateRange.end), this.metadataDateRangeDate);
1325
- this.dateRange.values = values.length ? values : undefined;
1326
- }
1327
- else {
1328
- this.dateRange.values = undefined;
1329
- }
1330
- this.entity[this.propertyKey] = this.dateRange;
3102
+ checkIsDialogArrayItemValid() {
3103
+ this.isDialogArrayItemValid = EntityUtilities.isEntityValid(this.dialogData.entity, 'create');
1331
3104
  }
1332
3105
  /**
1333
- * Sets the time on a datetime property.
3106
+ * Emits that a the value has been changed.
1334
3107
  */
1335
- setTime() {
1336
- if (!this.dateTime) {
1337
- this.entity[this.propertyKey] = undefined;
1338
- return;
1339
- }
1340
- this.entity[this.propertyKey] = new Date(this.dateTime);
1341
- if (this.time?.hours != null && this.time?.minutes != null) {
1342
- DateUtilities.asDate(this.entity[this.propertyKey]).setHours(this.time.hours, this.time.minutes, 0, 0);
1343
- }
1344
- else {
1345
- DateUtilities.asDate(this.entity[this.propertyKey]).setHours(0, 0, 0, 0);
1346
- }
3108
+ emitChange() {
3109
+ this.inputChangeEvent.emit();
1347
3110
  }
1348
3111
  /**
1349
- * Tries to add an item to the array.
3112
+ * Tries to add an item to the entity array.
1350
3113
  * Does this either inline if the "createInline"-metadata is set to true
1351
3114
  * or in a separate dialog if it is set to false.
1352
3115
  */
1353
- add() {
3116
+ addEntity() {
1354
3117
  if (this.metadataEntityArray.createInline) {
1355
- this.entityArrayValues.push(cloneDeep(this.arrayItem));
3118
+ if (!this.metadataEntityArray.allowDuplicates
3119
+ && this.entityArrayValues.find(async (v) => await EntityUtilities.isEqual(this.arrayItem, v, this.metadata, this.metadataEntityArray.itemType))) {
3120
+ this.dialog.open(NgxMatEntityConfirmDialogComponent, {
3121
+ data: this.metadataEntityArray.duplicatesErrorDialog,
3122
+ autoFocus: false,
3123
+ restoreFocus: false
3124
+ });
3125
+ return;
3126
+ }
3127
+ this.entityArrayValues.push(LodashUtilities.cloneDeep(this.arrayItem));
1356
3128
  this.dataSource.data = this.entityArrayValues;
1357
3129
  EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
3130
+ this.emitChange();
1358
3131
  }
1359
3132
  else {
1360
3133
  this.addArrayItemDialogRef = this.dialog.open(this.addArrayItemDialog, {
@@ -1369,9 +3142,10 @@ class NgxMatEntityInputComponent {
1369
3142
  */
1370
3143
  addArrayItem() {
1371
3144
  this.addArrayItemDialogRef.close();
1372
- this.entityArrayValues.push(cloneDeep(this.arrayItem));
3145
+ this.entityArrayValues.push(LodashUtilities.cloneDeep(this.arrayItem));
1373
3146
  this.dataSource.data = this.entityArrayValues;
1374
3147
  EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
3148
+ this.emitChange();
1375
3149
  }
1376
3150
  /**
1377
3151
  * Cancels adding the array item defined in the dialog.
@@ -1379,132 +3153,59 @@ class NgxMatEntityInputComponent {
1379
3153
  cancelAddArrayItem() {
1380
3154
  this.addArrayItemDialogRef.close();
1381
3155
  EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
3156
+ this.emitChange();
1382
3157
  }
1383
3158
  /**
1384
- * Removes all selected entries from the array.
3159
+ * Removes all selected entries from the entity array.
3160
+ *
3161
+ * @param selection - The selection containing the items to remove.
3162
+ * @param values - The values of the dataSource.
3163
+ * @param dataSource - The dataSource.
1385
3164
  */
1386
- remove() {
1387
- this.selection.selected.forEach(s => {
1388
- this.entityArrayValues.splice(this.entityArrayValues.indexOf(s), 1);
3165
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3166
+ remove(selection, values, dataSource) {
3167
+ selection.selected.forEach(s => {
3168
+ values.splice(values.indexOf(s), 1);
1389
3169
  });
1390
- this.dataSource.data = this.entityArrayValues;
1391
- this.selection.clear();
3170
+ dataSource.data = values;
3171
+ selection.clear();
3172
+ this.emitChange();
1392
3173
  }
1393
3174
  /**
1394
3175
  * Toggles all array-items in the table.
3176
+ *
3177
+ * @param selection - The selection to toggle.
3178
+ * @param dataSource - The dataSource of the selection.
1395
3179
  */
1396
- masterToggle() {
1397
- if (this.isAllSelected()) {
1398
- this.selection.clear();
3180
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3181
+ masterToggle(selection, dataSource) {
3182
+ if (this.isAllSelected(selection, dataSource)) {
3183
+ selection.clear();
1399
3184
  }
1400
3185
  else {
1401
- this.dataSource.data.forEach(row => this.selection.select(row));
3186
+ dataSource.data.forEach(row => selection.select(row));
1402
3187
  }
1403
3188
  }
1404
3189
  /**
1405
3190
  * Checks if all array-items in the table have been selected.
1406
3191
  * This is needed to display the "masterToggle"-checkbox correctly.
1407
3192
  *
3193
+ * @param selection - The selection to check.
3194
+ * @param dataSource - The dataSource of the selection.
1408
3195
  * @returns Whether or not all array-items in the table have been selected.
1409
3196
  */
1410
- isAllSelected() {
1411
- const numSelected = this.selection.selected.length;
1412
- const numRows = this.dataSource.data.length;
3197
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3198
+ isAllSelected(selection, dataSource) {
3199
+ const numSelected = selection.selected.length;
3200
+ const numRows = dataSource.data.length;
1413
3201
  return numSelected === numRows;
1414
3202
  }
1415
- /**
1416
- * Handles adding strings to the chipsArray.
1417
- * Checks validation and also creates a new array if it is undefined.
1418
- * This is needed because two things are validated: The array itself
1419
- * and the contents of the array. And we need a way to display an
1420
- * mat-error. As the only validation for the array is whether or not
1421
- * it contains values, we can set it to undefined when the last element is removed
1422
- * (removeStringChipArrayValue). That way we can use the "required" validator.
1423
- *
1424
- * @param event - The event that fires when a new chip is completed.
1425
- */
1426
- addStringChipArrayValue(event) {
1427
- const value = (event.value || '').trim();
1428
- if (value) {
1429
- if (this.metadataStringChipsArray.minLength && value.length < this.metadataStringChipsArray.minLength) {
1430
- return;
1431
- }
1432
- if (this.metadataStringChipsArray.maxLength && value.length > this.metadataStringChipsArray.maxLength) {
1433
- return;
1434
- }
1435
- if (this.metadataStringChipsArray.regex && !value.match(this.metadataStringChipsArray.regex)) {
1436
- return;
1437
- }
1438
- if (!this.stringChipsArrayValues) {
1439
- if (!this.entity[this.propertyKey]) {
1440
- this.entity[this.propertyKey] = [];
1441
- }
1442
- this.stringChipsArrayValues = this.entity[this.propertyKey];
1443
- }
1444
- this.stringChipsArrayValues.push(value);
1445
- }
1446
- event.chipInput.clear();
1447
- }
1448
- /**
1449
- * Removes the given value from the array.
1450
- * Sets the array to undefined if it is now empty.
1451
- * This is needed because two things are validated: The array itself
1452
- * and the contents of the array. And we need a way to display an
1453
- * mat-error. As the only validation for the array is whether or not
1454
- * it is empty, setting it to undefined here enables us to use the "required" validator.
1455
- *
1456
- * @param value - The string to remove from the array.
1457
- */
1458
- removeStringChipArrayValue(value) {
1459
- this.stringChipsArrayValues.splice(this.stringChipsArrayValues.indexOf(value), 1);
1460
- if (!this.stringChipsArrayValues.length) {
1461
- this.entity[this.propertyKey] = undefined;
1462
- this.stringChipsArrayValues = this.entity[this.propertyKey];
1463
- }
1464
- }
1465
- /**
1466
- * Handles adding a string to the array when an autocomplete value has been selected.
1467
- *
1468
- * @param event - The autocomplete selected event.
1469
- * @param chipsInput - The element where the user typed the value.
1470
- */
1471
- selected(event, chipsInput) {
1472
- const value = (event.option.viewValue || '').trim();
1473
- if (this.metadataStringChipsArray.minLength && value.length < this.metadataStringChipsArray.minLength) {
1474
- return;
1475
- }
1476
- if (this.metadataStringChipsArray.maxLength && value.length > this.metadataStringChipsArray.maxLength) {
1477
- return;
1478
- }
1479
- if (this.metadataStringChipsArray.regex && !value.match(this.metadataStringChipsArray.regex)) {
1480
- return;
1481
- }
1482
- if (!this.stringChipsArrayValues) {
1483
- if (!this.entity[this.propertyKey]) {
1484
- this.entity[this.propertyKey] = [];
1485
- }
1486
- this.stringChipsArrayValues = this.entity[this.propertyKey];
1487
- }
1488
- this.stringChipsArrayValues.push(value);
1489
- chipsInput.value = '';
1490
- }
1491
- /**
1492
- * Dynamically filters the Autocomplete options when the user inputs something.
1493
- *
1494
- * @param input - The input of the user.
1495
- */
1496
- filterAutocompleteStrings(input) {
1497
- if (input) {
1498
- const filterValue = input.toLowerCase();
1499
- this.filteredAutocompleteStrings = this.autocompleteStrings.filter(s => s.toLowerCase().includes(filterValue));
1500
- }
1501
- }
1502
3203
  }
1503
3204
  NgxMatEntityInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputComponent, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
1504
- NgxMatEntityInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: { entity: "entity", propertyKey: "propertyKey", getValidationErrorMessage: "getValidationErrorMessage", hideOmitForCreate: "hideOmitForCreate", hideOmitForEdit: "hideOmitForEdit" }, viewQueries: [{ propertyName: "addArrayItemDialog", first: true, predicate: ["addArrayItemDialog"], descendants: true }], ngImport: i0, template: "<div [ngSwitch]=\"type\" *ngIf=\"!(hideOmitForCreate && metadata.omitForCreate) && !(hideOmitForEdit && metadata.omitForUpdate)\">\n <!-------------------------------------------->\n <!-----------------Strings-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.STRING\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [pattern]=\"metadataDefaultString.regex ? metadataDefaultString.regex : '[\\\\s\\\\S]*'\"\n [minlength]=\"metadataDefaultString.minLength ? metadataDefaultString.minLength : null\"\n [maxlength]=\"metadataDefaultString.maxLength ? metadataDefaultString.maxLength : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_TEXTBOX\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <textarea\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"10\"\n [required]=\"metadata.required\"\n [minlength]=\"metadataTextboxString.minLength ? metadataTextboxString.minLength : null\"\n [maxlength]=\"metadataTextboxString.maxLength ? metadataTextboxString.maxLength : null\"\n >\n </textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_AUTOCOMPLETE\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matAutocomplete]=\"auto\"\n (keyup)=\"filterAutocompleteStrings(entity[propertyKey])\"\n [required]=\"metadata.required\"\n [minlength]=\"metadataAutocompleteString.minLength ? metadataAutocompleteString.minLength : null\"\n [maxlength]=\"metadataAutocompleteString.maxLength ? metadataAutocompleteString.maxLength : null\"\n [pattern]=\"metadataAutocompleteString.regex ? metadataAutocompleteString.regex : '[\\\\s\\\\S]*'\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadataDropdownString.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-----------------Booleans------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_CHECKBOX\">\n <mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-checkbox (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\"></mat-checkbox>\n <!-- hidden input is needed so that the checkbox can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\">\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_TOGGLE\">\n <mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-slide-toggle (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\"></mat-slide-toggle>\n <!-- hidden input is needed so that the toggle can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\">\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option [value]=\"undefined\">-</mat-option>\n <mat-option [value]=\"true\">{{metadataDropdownBoolean.dropdownTrue}}</mat-option>\n <mat-option [value]=\"false\">{{metadataDropdownBoolean.dropdownFalse}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!------------------Numbers------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n type=\"number\"\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDefaultNumber.min ? metadataDefaultNumber.min : null\"\n [max]=\"metadataDefaultNumber.max ? metadataDefaultNumber.max : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadataDropdownNumber.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Object------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.OBJECT\">\n <b>{{metadataDefaultObject.displayName}}</b>\n <!-- iterates over the object properties -->\n\n <div class=\"row\" *ngFor=\"let row of objectPropertyRows\">\n <!--\n displays another ngx-material-entity with the:\n object as the entity,\n the current key in the loop received by the keyvalue direction as the propertyKey\n and the getValidationErrorMessage of the current component\n -->\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"objectProperty\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n class=\"col-lg-{{EntityUtilities.getWidth(objectProperty, key, 'lg')}} col-md-{{EntityUtilities.getWidth(objectProperty, key, 'md')}} col-sm-{{EntityUtilities.getWidth(objectProperty, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Array-------------------->\n <!-------------------------------------------->\n <div class=\"entityArray\" *ngSwitchCase=\"DecoratorTypes.ARRAY\">\n <div class=\"mat-elevation-z8\" style=\"border-radius: 5px;padding: 15px;margin-bottom: 15px;margin-top: 15px;\">\n\n <div style=\"padding-bottom: 10px\">\n <b>{{metadataEntityArray.displayName}}</b>\n </div>\n <div *ngIf=\"metadataEntityArray.createInline\">\n <div class=\"row\" *ngFor=\"let row of arrayItemInlineRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(arrayItem, key, 'lg')}} col-md-{{EntityUtilities.getWidth(arrayItem, key, 'md')}} col-sm-{{EntityUtilities.getWidth(arrayItem, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n \n <div class=\"buttons\">\n <button mat-raised-button\n [disabled]=\"metadataEntityArray.createInline && !EntityUtilities.isEntityValid(arrayItem, 'create')\"\n (click)=\"add()\">\n {{metadataEntityArray.addButtonLabel}}\n </button>\n <button mat-raised-button\n [disabled]=\"!selection.selected.length\"\n (click)=\"remove()\">\n {{metadataEntityArray.removeButtonLabel}}\n </button>\n </div>\n \n <mat-table [dataSource]=\"dataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"></mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\" class=\"module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"></mat-checkbox>\n </mat-cell>\n </ng-container>\n \n <ng-container *ngFor=\"let dCol of metadataEntityArray.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n \n <div class=\"array-error\" *ngIf=\"metadataEntityArray.required && !dataSource.data.length\">\n {{metadataEntityArray.missingErrorMessage}}\n </div>\n </div>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadataStringChipsArray.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadataStringChipsArray.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matAutocomplete]=\"auto\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n (keyup)=\"filterAutocompleteStrings(chipsInput)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n #chipsElement\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event, chipsElement)\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Dates-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.DATE\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadataDefaultDate.min ? metadataDefaultDate.min(DateUtilities.asDate(entity[propertyKey])) : undefined\"\n [max]=\"metadataDefaultDate.max ? metadataDefaultDate.max(DateUtilities.asDate(entity[propertyKey])) : undefined\"\n [matDatepickerFilter]=\"metadataDefaultDate.filter ? metadataDefaultDate.filter : defaultDateFilter\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.DATE_RANGE\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n \n <mat-date-range-input [rangePicker]=\"picker\" [required]=\"metadata.required\" [dateFilter]=\"metadataDateRangeDate.filter ? metadataDateRangeDate.filter : defaultDateFilter\">\n <input matStartDate\n [(ngModel)]=\"dateRangeStart\"\n [name]=\"propertyKey.toString() + 'start'\"\n #startModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateRangeDate.minStart ? metadataDateRangeDate.minStart(dateRange.start) : undefined\"\n [max]=\"metadataDateRangeDate.maxStart ? metadataDateRangeDate.maxStart(dateRange.start) : undefined\"\n [placeholder]=\"metadataDateRangeDate.placeholderStart ? metadataDateRangeDate.placeholderStart : 'Start'\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n <input matEndDate\n [(ngModel)]=\"dateRangeEnd\"\n [name]=\"propertyKey.toString() + 'end'\"\n #endModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateRangeDate.minEnd ? metadataDateRangeDate.minEnd(dateRange.end) : undefined\"\n [max]=\"metadataDateRangeDate.maxEnd ? metadataDateRangeDate.maxEnd(dateRange.end) : undefined\"\n [placeholder]=\"metadataDateRangeDate.placeholderEnd ? metadataDateRangeDate.placeholderEnd : 'End'\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n </mat-date-range-input>\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-date-range-picker #picker></mat-date-range-picker>\n\n <mat-error *ngIf=\"startModel.errors\">{{getValidationErrorMessage(startModel)}}</mat-error>\n <mat-error *ngIf=\"!startModel.errors && endModel.errors\">{{getValidationErrorMessage(endModel)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.DATE_TIME\" class=\"date-time\">\n <mat-form-field appearance=\"standard\" class=\"datepicker\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"dateTime\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateTimeDate.minDate ? metadataDateTimeDate.minDate(dateTime) : undefined\"\n [max]=\"metadataDateTimeDate.maxDate ? metadataDateTimeDate.maxDate(dateTime) : undefined\"\n [matDatepickerFilter]=\"metadataDateTimeDate.filterDate ? metadataDateTimeDate.filterDate : defaultDateFilter\"\n (dateInput)=\"setTime()\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n <mat-form-field class=\"timepicker\">\n <mat-label>{{metadataDateTimeDate.timeDisplayName}}</mat-label>\n <mat-select\n [(ngModel)]=\"time\"\n [name]=\"propertyKey.toString() + 'time'\"\n #timeModel=\"ngModel\"\n [required]=\"metadata.required\"\n [compareWith]=\"compareTimes\"\n (ngModelChange)=\"setTime()\"\n >\n <mat-option *ngFor=\"let validTime of DateUtilities.getValidTimesForDropdown(\n DateUtilities.asDate(entity[propertyKey]),\n metadataDateTimeDate.times,\n metadataDateTimeDate.minTime,\n metadataDateTimeDate.maxTime,\n metadataDateTimeDate.filterTime\n )\"\n [value]=\"validTime.value\"\n >\n {{validTime.displayName}}\n </mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(timeModel)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchDefault>ERROR: The type {{type}} is not known.</div>\n</div>\n\n<!--------------------------------------------------------->\n<!--------------------Add Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #addArrayItemDialog>\n <h2 mat-dialog-title>{{dialogData.createDialogData.title}}</h2>\n\n <mat-dialog-content>\n <form #form=\"ngForm\" class=\"row\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"dialogData.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"dialogData.getValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(dialogData.entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(dialogData.entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(dialogData.entity, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n </mat-dialog-content>\n\n <mat-dialog-actions>\n <button mat-raised-button (click)=\"addArrayItem()\" [disabled]=\"!EntityUtilities.isEntityValid(dialogData.entity, 'create')\">\n {{dialogData.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancelAddArrayItem()\" class=\"cancel-button\">\n {{dialogData.createDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n\n</ng-template>", styles: ["mat-form-field{width:100%}::ng-deep .hideUnderline .mat-form-field-underline{opacity:0%}.entityArray .buttons{display:flex;justify-content:space-between;margin-bottom:10px;margin-top:5px}.entityArray mat-table{border:1px solid #E0E0E0;border-radius:5px;padding-top:5px;padding-bottom:25px}.entityArray .mat-column-select{flex:0 0 75px}.entityArray .array-error{display:flex;align-items:center;justify-content:center;margin-top:-25.8px;border:1px solid #E0E0E0;background-color:#f8d3d7;color:#721c24;height:25.8px;border-bottom-left-radius:5px;border-bottom-right-radius:5px}.date-time{display:flex;align-items:baseline}.date-time .timepicker{margin-left:10px}\n"], components: [{ type: i2.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i3$1.MatAutocomplete, selector: "mat-autocomplete", inputs: ["disableRipple"], exportAs: ["matAutocomplete"] }, { type: i4.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { type: i5.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex", "name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "checked"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit"] }, { type: i3.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { type: i10.MatChipList, selector: "mat-chip-list", inputs: ["errorStateMatcher", "multiple", "compareWith", "value", "required", "placeholder", "disabled", "aria-orientation", "selectable", "tabIndex"], outputs: ["change", "valueChange"], exportAs: ["matChipList"] }, { type: i11.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i11.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { type: i11.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { type: i11.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }], directives: [{ type: i12.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i12.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i12.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i2.MatLabel, selector: "mat-label" }, { type: i13.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i14.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i14.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i14.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i14.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i14.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i2.MatError, selector: "mat-error", inputs: ["id"] }, { type: i15.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { type: i3$1.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", exportAs: ["matAutocompleteTrigger"] }, { type: i12.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i14.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { type: i14.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { type: i14.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i9.MatCellDef, selector: "[matCellDef]" }, { type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { type: i10.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["color", "disableRipple", "tabIndex", "selected", "value", "selectable", "disabled", "removable"], outputs: ["selectionChange", "destroyed", "removed"], exportAs: ["matChip"] }, { type: i10.MatChipRemove, selector: "[matChipRemove]" }, { type: i10.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { type: i11.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { type: i2.MatSuffix, selector: "[matSuffix]" }, { type: i11.MatStartDate, selector: "input[matStartDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i11.MatEndDate, selector: "input[matEndDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i12.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i14.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i14.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i14.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }] });
3205
+ NgxMatEntityInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: { entity: "entity", propertyKey: "propertyKey", getValidationErrorMessage: "getValidationErrorMessage", hideOmitForCreate: "hideOmitForCreate", hideOmitForEdit: "hideOmitForEdit" }, outputs: { inputChangeEvent: "inputChangeEvent" }, viewQueries: [{ propertyName: "addArrayItemDialog", first: true, predicate: ["addArrayItemDialog"], descendants: true }], ngImport: i0, template: "<div [ngSwitch]=\"type\" *ngIf=\"!(hideOmitForCreate && metadata.omitForCreate) && !(hideOmitForEdit && metadata.omitForUpdate)\">\n <!-------------------------------------------->\n <!-----------------Strings-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.STRING\">\n <string-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></string-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.STRING_TEXTBOX\">\n <string-textbox-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></string-textbox-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.STRING_AUTOCOMPLETE\">\n <string-autocomplete-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></string-autocomplete-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.STRING_DROPDOWN\">\n <string-dropdown-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></string-dropdown-input>\n </div>\n\n <!-------------------------------------------->\n <!-----------------Booleans------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_CHECKBOX\">\n <boolean-checkbox-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></boolean-checkbox-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_TOGGLE\">\n <boolean-toggle-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></boolean-toggle-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_DROPDOWN\">\n <boolean-dropdown-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></boolean-dropdown-input>\n </div>\n\n <!-------------------------------------------->\n <!------------------Numbers------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER\">\n <number-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></number-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER_DROPDOWN\">\n <number-dropdown-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></number-dropdown-input>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Object------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.OBJECT\">\n <b>{{metadataDefaultObject.displayName}}</b>\n <!-- iterates over the object properties -->\n <div class=\"row\" *ngFor=\"let row of objectPropertyRows\">\n <ngx-mat-entity-input *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"objectProperty\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n class=\"col-lg-{{EntityUtilities.getWidth(objectProperty, key, 'lg')}} col-md-{{EntityUtilities.getWidth(objectProperty, key, 'md')}} col-sm-{{EntityUtilities.getWidth(objectProperty, key, 'sm')}}\"\n (inputChangeEvent)=\"emitChange()\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Array-------------------->\n <!-------------------------------------------->\n <div class=\"entityArray\" *ngSwitchCase=\"DecoratorTypes.ARRAY\">\n <div class=\"mat-elevation-z8\" style=\"border-radius: 5px;padding: 15px;margin-bottom: 15px;margin-top: 15px;\">\n <div style=\"padding-bottom: 10px\">\n <b>{{metadataEntityArray.displayName}}</b>\n </div>\n <div *ngIf=\"metadataEntityArray.createInline\">\n <div class=\"row\" *ngFor=\"let row of arrayItemInlineRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(arrayItem, key, 'lg')}} col-md-{{EntityUtilities.getWidth(arrayItem, key, 'md')}} col-sm-{{EntityUtilities.getWidth(arrayItem, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsArrayItemValid()\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n \n <div class=\"buttons\">\n <button mat-raised-button\n [disabled]=\"metadataEntityArray.createInline && !isArrayItemValid\"\n (click)=\"addEntity()\">\n {{metadataEntityArray.addButtonLabel}}\n </button>\n <button mat-raised-button\n [disabled]=\"!selection.selected.length\"\n (click)=\"remove(selection, entityArrayValues, dataSource)\">\n {{metadataEntityArray.removeButtonLabel}}\n </button>\n </div>\n \n <mat-table [dataSource]=\"dataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle(selection, dataSource) : null\" [checked]=\"selection.hasValue() && isAllSelected(selection, dataSource)\" [indeterminate]=\"selection.hasValue() && !isAllSelected(selection, dataSource)\"></mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"></mat-checkbox>\n </mat-cell>\n </ng-container>\n \n <ng-container *ngFor=\"let dCol of metadataEntityArray.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n \n <div class=\"array-error\" *ngIf=\"metadataEntityArray.required && !dataSource.data.length\">\n {{metadataEntityArray.missingErrorMessage}}\n </div>\n </div>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_DATE\">\n <array-date-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></array-date-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_DATE_TIME\">\n <array-date-time-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></array-date-time-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_DATE_RANGE\">\n <array-date-range-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></array-date-range-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_CHIPS\">\n <array-string-chips-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></array-string-chips-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS\">\n <array-string-autocomplete-chips (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></array-string-autocomplete-chips>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Dates-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.DATE\">\n <date-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></date-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.DATE_RANGE\">\n <date-range-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></date-range-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.DATE_TIME\">\n <date-time-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></date-time-input>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Files-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.FILE_DEFAULT\">\n <file-default-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></file-default-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.FILE_IMAGE\">\n <file-image-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></file-image-input>\n </div>\n\n <div *ngSwitchDefault>ERROR: The type {{type}} is not known.</div>\n</div>\n\n<!--------------------------------------------------------->\n<!--------------------Add Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #addArrayItemDialog>\n <h2 mat-dialog-title>{{dialogData.createDialogData.title}}</h2>\n\n <mat-dialog-content>\n <form #form=\"ngForm\" class=\"row\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"dialogData.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"dialogData.getValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(dialogData.entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(dialogData.entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(dialogData.entity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsDialogArrayItemValid()\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n </mat-dialog-content>\n\n <mat-dialog-actions>\n <button mat-raised-button (click)=\"addArrayItem()\" [disabled]=\"!isDialogArrayItemValid\">\n {{dialogData.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancelAddArrayItem()\" class=\"cancel-button\">\n {{dialogData.createDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n\n</ng-template>", styles: ["mat-form-field{width:100%}.entityArray .buttons{display:flex;justify-content:space-between;margin-bottom:10px;margin-top:5px}.entityArray mat-table{border:1px solid #E0E0E0;border-radius:5px;padding-top:5px;padding-bottom:25px}.entityArray .mat-column-select{flex:0 0 75px}.entityArray .array-error{display:flex;align-items:center;justify-content:center;margin-top:-25.8px;border:1px solid #E0E0E0;background-color:#f8d3d7;color:#721c24;height:25.8px;border-bottom-left-radius:5px;border-bottom-right-radius:5px}\n"], components: [{ type: StringInputComponent, selector: "string-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: StringTextboxInputComponent, selector: "string-textbox-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: StringAutocompleteInputComponent, selector: "string-autocomplete-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: StringDropdownInputComponent, selector: "string-dropdown-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: BooleanCheckboxInputComponent, selector: "boolean-checkbox-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: BooleanToggleInputComponent, selector: "boolean-toggle-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: BooleanDropdownInputComponent, selector: "boolean-dropdown-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: NumberInputComponent, selector: "number-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: NumberDropdownInputComponent, selector: "number-dropdown-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit"], outputs: ["inputChangeEvent"] }, { type: i4.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { type: ArrayDateInputComponent, selector: "array-date-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: ArrayDateTimeInputComponent, selector: "array-date-time-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: ArrayDateRangeInputComponent, selector: "array-date-range-input", inputs: ["entity", "key", "metadata", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: ArrayStringChipsInputComponent, selector: "array-string-chips-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: ArrayStringAutocompleteChipsComponent, selector: "array-string-autocomplete-chips", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: DateInputComponent, selector: "date-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: DateRangeInputComponent, selector: "date-range-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: DateTimeInputComponent, selector: "date-time-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: FileDefaultInputComponent, selector: "file-default-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }, { type: FileImageInputComponent, selector: "file-image-input", inputs: ["entity", "key", "getValidationErrorMessage"], outputs: ["inputChangeEvent"] }], directives: [{ type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i4$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i5.MatCellDef, selector: "[matCellDef]" }, { type: i5.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i5.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i5.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { type: i4$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }] });
1505
3206
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputComponent, decorators: [{
1506
3207
  type: Component,
1507
- args: [{ selector: 'ngx-mat-entity-input', template: "<div [ngSwitch]=\"type\" *ngIf=\"!(hideOmitForCreate && metadata.omitForCreate) && !(hideOmitForEdit && metadata.omitForUpdate)\">\n <!-------------------------------------------->\n <!-----------------Strings-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.STRING\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [pattern]=\"metadataDefaultString.regex ? metadataDefaultString.regex : '[\\\\s\\\\S]*'\"\n [minlength]=\"metadataDefaultString.minLength ? metadataDefaultString.minLength : null\"\n [maxlength]=\"metadataDefaultString.maxLength ? metadataDefaultString.maxLength : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_TEXTBOX\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <textarea\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"10\"\n [required]=\"metadata.required\"\n [minlength]=\"metadataTextboxString.minLength ? metadataTextboxString.minLength : null\"\n [maxlength]=\"metadataTextboxString.maxLength ? metadataTextboxString.maxLength : null\"\n >\n </textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_AUTOCOMPLETE\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matAutocomplete]=\"auto\"\n (keyup)=\"filterAutocompleteStrings(entity[propertyKey])\"\n [required]=\"metadata.required\"\n [minlength]=\"metadataAutocompleteString.minLength ? metadataAutocompleteString.minLength : null\"\n [maxlength]=\"metadataAutocompleteString.maxLength ? metadataAutocompleteString.maxLength : null\"\n [pattern]=\"metadataAutocompleteString.regex ? metadataAutocompleteString.regex : '[\\\\s\\\\S]*'\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadataDropdownString.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-----------------Booleans------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_CHECKBOX\">\n <mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-checkbox (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\"></mat-checkbox>\n <!-- hidden input is needed so that the checkbox can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\">\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_TOGGLE\">\n <mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-slide-toggle (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\"></mat-slide-toggle>\n <!-- hidden input is needed so that the toggle can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\">\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option [value]=\"undefined\">-</mat-option>\n <mat-option [value]=\"true\">{{metadataDropdownBoolean.dropdownTrue}}</mat-option>\n <mat-option [value]=\"false\">{{metadataDropdownBoolean.dropdownFalse}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!------------------Numbers------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n type=\"number\"\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDefaultNumber.min ? metadataDefaultNumber.min : null\"\n [max]=\"metadataDefaultNumber.max ? metadataDefaultNumber.max : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadataDropdownNumber.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Object------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.OBJECT\">\n <b>{{metadataDefaultObject.displayName}}</b>\n <!-- iterates over the object properties -->\n\n <div class=\"row\" *ngFor=\"let row of objectPropertyRows\">\n <!--\n displays another ngx-material-entity with the:\n object as the entity,\n the current key in the loop received by the keyvalue direction as the propertyKey\n and the getValidationErrorMessage of the current component\n -->\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"objectProperty\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n class=\"col-lg-{{EntityUtilities.getWidth(objectProperty, key, 'lg')}} col-md-{{EntityUtilities.getWidth(objectProperty, key, 'md')}} col-sm-{{EntityUtilities.getWidth(objectProperty, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Array-------------------->\n <!-------------------------------------------->\n <div class=\"entityArray\" *ngSwitchCase=\"DecoratorTypes.ARRAY\">\n <div class=\"mat-elevation-z8\" style=\"border-radius: 5px;padding: 15px;margin-bottom: 15px;margin-top: 15px;\">\n\n <div style=\"padding-bottom: 10px\">\n <b>{{metadataEntityArray.displayName}}</b>\n </div>\n <div *ngIf=\"metadataEntityArray.createInline\">\n <div class=\"row\" *ngFor=\"let row of arrayItemInlineRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(arrayItem, key, 'lg')}} col-md-{{EntityUtilities.getWidth(arrayItem, key, 'md')}} col-sm-{{EntityUtilities.getWidth(arrayItem, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n \n <div class=\"buttons\">\n <button mat-raised-button\n [disabled]=\"metadataEntityArray.createInline && !EntityUtilities.isEntityValid(arrayItem, 'create')\"\n (click)=\"add()\">\n {{metadataEntityArray.addButtonLabel}}\n </button>\n <button mat-raised-button\n [disabled]=\"!selection.selected.length\"\n (click)=\"remove()\">\n {{metadataEntityArray.removeButtonLabel}}\n </button>\n </div>\n \n <mat-table [dataSource]=\"dataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"></mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\" class=\"module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"></mat-checkbox>\n </mat-cell>\n </ng-container>\n \n <ng-container *ngFor=\"let dCol of metadataEntityArray.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n \n <div class=\"array-error\" *ngIf=\"metadataEntityArray.required && !dataSource.data.length\">\n {{metadataEntityArray.missingErrorMessage}}\n </div>\n </div>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadataStringChipsArray.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadataStringChipsArray.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matAutocomplete]=\"auto\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n (keyup)=\"filterAutocompleteStrings(chipsInput)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n #chipsElement\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event, chipsElement)\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Dates-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.DATE\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadataDefaultDate.min ? metadataDefaultDate.min(DateUtilities.asDate(entity[propertyKey])) : undefined\"\n [max]=\"metadataDefaultDate.max ? metadataDefaultDate.max(DateUtilities.asDate(entity[propertyKey])) : undefined\"\n [matDatepickerFilter]=\"metadataDefaultDate.filter ? metadataDefaultDate.filter : defaultDateFilter\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.DATE_RANGE\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n \n <mat-date-range-input [rangePicker]=\"picker\" [required]=\"metadata.required\" [dateFilter]=\"metadataDateRangeDate.filter ? metadataDateRangeDate.filter : defaultDateFilter\">\n <input matStartDate\n [(ngModel)]=\"dateRangeStart\"\n [name]=\"propertyKey.toString() + 'start'\"\n #startModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateRangeDate.minStart ? metadataDateRangeDate.minStart(dateRange.start) : undefined\"\n [max]=\"metadataDateRangeDate.maxStart ? metadataDateRangeDate.maxStart(dateRange.start) : undefined\"\n [placeholder]=\"metadataDateRangeDate.placeholderStart ? metadataDateRangeDate.placeholderStart : 'Start'\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n <input matEndDate\n [(ngModel)]=\"dateRangeEnd\"\n [name]=\"propertyKey.toString() + 'end'\"\n #endModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateRangeDate.minEnd ? metadataDateRangeDate.minEnd(dateRange.end) : undefined\"\n [max]=\"metadataDateRangeDate.maxEnd ? metadataDateRangeDate.maxEnd(dateRange.end) : undefined\"\n [placeholder]=\"metadataDateRangeDate.placeholderEnd ? metadataDateRangeDate.placeholderEnd : 'End'\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n </mat-date-range-input>\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-date-range-picker #picker></mat-date-range-picker>\n\n <mat-error *ngIf=\"startModel.errors\">{{getValidationErrorMessage(startModel)}}</mat-error>\n <mat-error *ngIf=\"!startModel.errors && endModel.errors\">{{getValidationErrorMessage(endModel)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.DATE_TIME\" class=\"date-time\">\n <mat-form-field appearance=\"standard\" class=\"datepicker\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"dateTime\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateTimeDate.minDate ? metadataDateTimeDate.minDate(dateTime) : undefined\"\n [max]=\"metadataDateTimeDate.maxDate ? metadataDateTimeDate.maxDate(dateTime) : undefined\"\n [matDatepickerFilter]=\"metadataDateTimeDate.filterDate ? metadataDateTimeDate.filterDate : defaultDateFilter\"\n (dateInput)=\"setTime()\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n <mat-form-field class=\"timepicker\">\n <mat-label>{{metadataDateTimeDate.timeDisplayName}}</mat-label>\n <mat-select\n [(ngModel)]=\"time\"\n [name]=\"propertyKey.toString() + 'time'\"\n #timeModel=\"ngModel\"\n [required]=\"metadata.required\"\n [compareWith]=\"compareTimes\"\n (ngModelChange)=\"setTime()\"\n >\n <mat-option *ngFor=\"let validTime of DateUtilities.getValidTimesForDropdown(\n DateUtilities.asDate(entity[propertyKey]),\n metadataDateTimeDate.times,\n metadataDateTimeDate.minTime,\n metadataDateTimeDate.maxTime,\n metadataDateTimeDate.filterTime\n )\"\n [value]=\"validTime.value\"\n >\n {{validTime.displayName}}\n </mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(timeModel)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchDefault>ERROR: The type {{type}} is not known.</div>\n</div>\n\n<!--------------------------------------------------------->\n<!--------------------Add Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #addArrayItemDialog>\n <h2 mat-dialog-title>{{dialogData.createDialogData.title}}</h2>\n\n <mat-dialog-content>\n <form #form=\"ngForm\" class=\"row\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"dialogData.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"dialogData.getValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(dialogData.entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(dialogData.entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(dialogData.entity, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n </mat-dialog-content>\n\n <mat-dialog-actions>\n <button mat-raised-button (click)=\"addArrayItem()\" [disabled]=\"!EntityUtilities.isEntityValid(dialogData.entity, 'create')\">\n {{dialogData.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancelAddArrayItem()\" class=\"cancel-button\">\n {{dialogData.createDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n\n</ng-template>", styles: ["mat-form-field{width:100%}::ng-deep .hideUnderline .mat-form-field-underline{opacity:0%}.entityArray .buttons{display:flex;justify-content:space-between;margin-bottom:10px;margin-top:5px}.entityArray mat-table{border:1px solid #E0E0E0;border-radius:5px;padding-top:5px;padding-bottom:25px}.entityArray .mat-column-select{flex:0 0 75px}.entityArray .array-error{display:flex;align-items:center;justify-content:center;margin-top:-25.8px;border:1px solid #E0E0E0;background-color:#f8d3d7;color:#721c24;height:25.8px;border-bottom-left-radius:5px;border-bottom-right-radius:5px}.date-time{display:flex;align-items:baseline}.date-time .timepicker{margin-left:10px}\n"] }]
3208
+ args: [{ selector: 'ngx-mat-entity-input', template: "<div [ngSwitch]=\"type\" *ngIf=\"!(hideOmitForCreate && metadata.omitForCreate) && !(hideOmitForEdit && metadata.omitForUpdate)\">\n <!-------------------------------------------->\n <!-----------------Strings-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.STRING\">\n <string-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></string-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.STRING_TEXTBOX\">\n <string-textbox-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></string-textbox-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.STRING_AUTOCOMPLETE\">\n <string-autocomplete-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></string-autocomplete-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.STRING_DROPDOWN\">\n <string-dropdown-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></string-dropdown-input>\n </div>\n\n <!-------------------------------------------->\n <!-----------------Booleans------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_CHECKBOX\">\n <boolean-checkbox-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></boolean-checkbox-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_TOGGLE\">\n <boolean-toggle-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></boolean-toggle-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_DROPDOWN\">\n <boolean-dropdown-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></boolean-dropdown-input>\n </div>\n\n <!-------------------------------------------->\n <!------------------Numbers------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER\">\n <number-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></number-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER_DROPDOWN\">\n <number-dropdown-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></number-dropdown-input>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Object------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.OBJECT\">\n <b>{{metadataDefaultObject.displayName}}</b>\n <!-- iterates over the object properties -->\n <div class=\"row\" *ngFor=\"let row of objectPropertyRows\">\n <ngx-mat-entity-input *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"objectProperty\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n class=\"col-lg-{{EntityUtilities.getWidth(objectProperty, key, 'lg')}} col-md-{{EntityUtilities.getWidth(objectProperty, key, 'md')}} col-sm-{{EntityUtilities.getWidth(objectProperty, key, 'sm')}}\"\n (inputChangeEvent)=\"emitChange()\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Array-------------------->\n <!-------------------------------------------->\n <div class=\"entityArray\" *ngSwitchCase=\"DecoratorTypes.ARRAY\">\n <div class=\"mat-elevation-z8\" style=\"border-radius: 5px;padding: 15px;margin-bottom: 15px;margin-top: 15px;\">\n <div style=\"padding-bottom: 10px\">\n <b>{{metadataEntityArray.displayName}}</b>\n </div>\n <div *ngIf=\"metadataEntityArray.createInline\">\n <div class=\"row\" *ngFor=\"let row of arrayItemInlineRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(arrayItem, key, 'lg')}} col-md-{{EntityUtilities.getWidth(arrayItem, key, 'md')}} col-sm-{{EntityUtilities.getWidth(arrayItem, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsArrayItemValid()\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n \n <div class=\"buttons\">\n <button mat-raised-button\n [disabled]=\"metadataEntityArray.createInline && !isArrayItemValid\"\n (click)=\"addEntity()\">\n {{metadataEntityArray.addButtonLabel}}\n </button>\n <button mat-raised-button\n [disabled]=\"!selection.selected.length\"\n (click)=\"remove(selection, entityArrayValues, dataSource)\">\n {{metadataEntityArray.removeButtonLabel}}\n </button>\n </div>\n \n <mat-table [dataSource]=\"dataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle(selection, dataSource) : null\" [checked]=\"selection.hasValue() && isAllSelected(selection, dataSource)\" [indeterminate]=\"selection.hasValue() && !isAllSelected(selection, dataSource)\"></mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"></mat-checkbox>\n </mat-cell>\n </ng-container>\n \n <ng-container *ngFor=\"let dCol of metadataEntityArray.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n \n <div class=\"array-error\" *ngIf=\"metadataEntityArray.required && !dataSource.data.length\">\n {{metadataEntityArray.missingErrorMessage}}\n </div>\n </div>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_DATE\">\n <array-date-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></array-date-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_DATE_TIME\">\n <array-date-time-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></array-date-time-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_DATE_RANGE\">\n <array-date-range-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></array-date-range-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_CHIPS\">\n <array-string-chips-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></array-string-chips-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS\">\n <array-string-autocomplete-chips (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></array-string-autocomplete-chips>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Dates-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.DATE\">\n <date-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></date-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.DATE_RANGE\">\n <date-range-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></date-range-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.DATE_TIME\">\n <date-time-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></date-time-input>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Files-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.FILE_DEFAULT\">\n <file-default-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></file-default-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.FILE_IMAGE\">\n <file-image-input (inputChangeEvent)=\"emitChange()\" [entity]=\"internalEntity\" [key]=\"internalPropertyKey\" [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"></file-image-input>\n </div>\n\n <div *ngSwitchDefault>ERROR: The type {{type}} is not known.</div>\n</div>\n\n<!--------------------------------------------------------->\n<!--------------------Add Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #addArrayItemDialog>\n <h2 mat-dialog-title>{{dialogData.createDialogData.title}}</h2>\n\n <mat-dialog-content>\n <form #form=\"ngForm\" class=\"row\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"dialogData.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"dialogData.getValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(dialogData.entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(dialogData.entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(dialogData.entity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsDialogArrayItemValid()\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n </mat-dialog-content>\n\n <mat-dialog-actions>\n <button mat-raised-button (click)=\"addArrayItem()\" [disabled]=\"!isDialogArrayItemValid\">\n {{dialogData.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancelAddArrayItem()\" class=\"cancel-button\">\n {{dialogData.createDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n\n</ng-template>", styles: ["mat-form-field{width:100%}.entityArray .buttons{display:flex;justify-content:space-between;margin-bottom:10px;margin-top:5px}.entityArray mat-table{border:1px solid #E0E0E0;border-radius:5px;padding-top:5px;padding-bottom:25px}.entityArray .mat-column-select{flex:0 0 75px}.entityArray .array-error{display:flex;align-items:center;justify-content:center;margin-top:-25.8px;border:1px solid #E0E0E0;background-color:#f8d3d7;color:#721c24;height:25.8px;border-bottom-left-radius:5px;border-bottom-right-radius:5px}\n"] }]
1508
3209
  }], ctorParameters: function () { return [{ type: i1.MatDialog }]; }, propDecorators: { entity: [{
1509
3210
  type: Input
1510
3211
  }], propertyKey: [{
@@ -1515,6 +3216,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1515
3216
  type: Input
1516
3217
  }], hideOmitForEdit: [{
1517
3218
  type: Input
3219
+ }], inputChangeEvent: [{
3220
+ type: Output
1518
3221
  }], addArrayItemDialog: [{
1519
3222
  type: ViewChild,
1520
3223
  args: ['addArrayItemDialog']
@@ -1523,7 +3226,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1523
3226
  class NgxMatEntityInputModule {
1524
3227
  }
1525
3228
  NgxMatEntityInputModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1526
- NgxMatEntityInputModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputModule, declarations: [NgxMatEntityInputComponent], imports: [CommonModule,
3229
+ NgxMatEntityInputModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputModule, declarations: [StringInputComponent,
3230
+ StringTextboxInputComponent,
3231
+ StringAutocompleteInputComponent,
3232
+ StringDropdownInputComponent,
3233
+ BooleanCheckboxInputComponent,
3234
+ BooleanToggleInputComponent,
3235
+ BooleanDropdownInputComponent,
3236
+ NumberInputComponent,
3237
+ NumberDropdownInputComponent,
3238
+ ArrayStringChipsInputComponent,
3239
+ ArrayStringAutocompleteChipsComponent,
3240
+ DateInputComponent,
3241
+ DateRangeInputComponent,
3242
+ DateTimeInputComponent,
3243
+ ArrayDateInputComponent,
3244
+ ArrayDateTimeInputComponent,
3245
+ ArrayDateRangeInputComponent,
3246
+ FileInputComponent,
3247
+ FileImageInputComponent,
3248
+ FileDefaultInputComponent,
3249
+ DragDropDirective,
3250
+ NgxMatEntityInputComponent], imports: [CommonModule,
1527
3251
  MatInputModule,
1528
3252
  FormsModule,
1529
3253
  MatFormFieldModule,
@@ -1557,7 +3281,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1557
3281
  type: NgModule,
1558
3282
  args: [{
1559
3283
  declarations: [
1560
- NgxMatEntityInputComponent,
3284
+ StringInputComponent,
3285
+ StringTextboxInputComponent,
3286
+ StringAutocompleteInputComponent,
3287
+ StringDropdownInputComponent,
3288
+ BooleanCheckboxInputComponent,
3289
+ BooleanToggleInputComponent,
3290
+ BooleanDropdownInputComponent,
3291
+ NumberInputComponent,
3292
+ NumberDropdownInputComponent,
3293
+ ArrayStringChipsInputComponent,
3294
+ ArrayStringAutocompleteChipsComponent,
3295
+ DateInputComponent,
3296
+ DateRangeInputComponent,
3297
+ DateTimeInputComponent,
3298
+ ArrayDateInputComponent,
3299
+ ArrayDateTimeInputComponent,
3300
+ ArrayDateRangeInputComponent,
3301
+ FileInputComponent,
3302
+ FileImageInputComponent,
3303
+ FileDefaultInputComponent,
3304
+ DragDropDirective,
3305
+ NgxMatEntityInputComponent
1561
3306
  ],
1562
3307
  imports: [
1563
3308
  CommonModule,
@@ -1616,7 +3361,7 @@ class NgxMatEntityCreateDialogComponent {
1616
3361
  this.injector = injector;
1617
3362
  this.dialog = dialog;
1618
3363
  this.EntityUtilities = EntityUtilities;
1619
- this.getWidth = EntityUtilities.getWidth;
3364
+ this.isEntityValid = false;
1620
3365
  }
1621
3366
  ngOnInit() {
1622
3367
  this.data = new CreateEntityDialogDataBuilder(this.inputData).getResult();
@@ -1624,15 +3369,22 @@ class NgxMatEntityCreateDialogComponent {
1624
3369
  this.entityRows = EntityUtilities.getEntityRows(this.data.entity, true);
1625
3370
  this.entityService = this.injector.get(this.data.EntityServiceClass);
1626
3371
  }
3372
+ /**
3373
+ * Checks if the entity is valid.
3374
+ */
3375
+ checkIsEntityValid() {
3376
+ this.isEntityValid = EntityUtilities.isEntityValid(this.data.entity, 'create');
3377
+ }
1627
3378
  /**
1628
3379
  * Tries add the new entity and close the dialog afterwards.
1629
3380
  * Also handles the confirmation if required.
1630
3381
  */
1631
3382
  create() {
1632
- if (!this.data.createDialogData?.createRequiresConfirmDialog) {
1633
- return this.confirmCreate();
3383
+ if (!this.data.createDialogData.createRequiresConfirmDialog) {
3384
+ this.confirmCreate();
3385
+ return;
1634
3386
  }
1635
- const dialogData = new ConfirmDialogDataBuilder(this.data.createDialogData?.confirmCreateDialogData)
3387
+ const dialogData = new ConfirmDialogDataBuilder(this.data.createDialogData.confirmCreateDialogData)
1636
3388
  .withDefault('text', ['Do you really want to create this entity?'])
1637
3389
  .withDefault('confirmButtonLabel', 'Create')
1638
3390
  .withDefault('title', 'Create')
@@ -1649,7 +3401,7 @@ class NgxMatEntityCreateDialogComponent {
1649
3401
  });
1650
3402
  }
1651
3403
  confirmCreate() {
1652
- this.entityService.create(this.data.entity).then(() => this.dialogRef.close());
3404
+ void this.entityService.create(this.data.entity).then(() => this.dialogRef.close());
1653
3405
  }
1654
3406
  /**
1655
3407
  * Closes the dialog.
@@ -1659,10 +3411,10 @@ class NgxMatEntityCreateDialogComponent {
1659
3411
  }
1660
3412
  }
1661
3413
  NgxMatEntityCreateDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityCreateDialogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1.MatDialogRef }, { token: i0.Injector }, { token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
1662
- NgxMatEntityCreateDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityCreateDialogComponent, selector: "ngx-mat-entity-create-dialog", ngImport: i0, template: "<h2 mat-dialog-title>{{data.createDialogData.title}}</h2>\n\n<mat-dialog-content>\n <form #form=\"ngForm\">\n <div class=\"row\" *ngFor=\"let row of entityRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"data.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{getWidth(data.entity, key, 'lg')}} col-md-{{getWidth(data.entity, key, 'md')}} col-sm-{{getWidth(data.entity, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button mat-raised-button (click)=\"create()\" [disabled]=\"!EntityUtilities.isEntityValid(data.entity, 'create')\">\n {{data.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.createDialogData.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: ["mat-dialog-actions{display:flex;justify-content:space-between}\n"], components: [{ type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit"] }, { type: i3.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i14.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i14.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i14.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i12.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }] });
3414
+ NgxMatEntityCreateDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityCreateDialogComponent, selector: "ngx-mat-entity-create-dialog", ngImport: i0, template: "<h2 mat-dialog-title>{{data.createDialogData.title}}</h2>\n\n<mat-dialog-content>\n <form #form=\"ngForm\">\n <div class=\"row\" *ngFor=\"let row of entityRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"data.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(data.entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(data.entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(data.entity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsEntityValid()\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button mat-raised-button (click)=\"create()\" [disabled]=\"!isEntityValid\">\n {{data.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.createDialogData.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: ["mat-dialog-actions{display:flex;justify-content:space-between}\n"], components: [{ type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit"], outputs: ["inputChangeEvent"] }, { type: i4.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }] });
1663
3415
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityCreateDialogComponent, decorators: [{
1664
3416
  type: Component,
1665
- args: [{ selector: 'ngx-mat-entity-create-dialog', template: "<h2 mat-dialog-title>{{data.createDialogData.title}}</h2>\n\n<mat-dialog-content>\n <form #form=\"ngForm\">\n <div class=\"row\" *ngFor=\"let row of entityRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"data.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{getWidth(data.entity, key, 'lg')}} col-md-{{getWidth(data.entity, key, 'md')}} col-sm-{{getWidth(data.entity, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button mat-raised-button (click)=\"create()\" [disabled]=\"!EntityUtilities.isEntityValid(data.entity, 'create')\">\n {{data.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.createDialogData.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: ["mat-dialog-actions{display:flex;justify-content:space-between}\n"] }]
3417
+ args: [{ selector: 'ngx-mat-entity-create-dialog', template: "<h2 mat-dialog-title>{{data.createDialogData.title}}</h2>\n\n<mat-dialog-content>\n <form #form=\"ngForm\">\n <div class=\"row\" *ngFor=\"let row of entityRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"data.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(data.entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(data.entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(data.entity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsEntityValid()\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button mat-raised-button (click)=\"create()\" [disabled]=\"!isEntityValid\">\n {{data.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.createDialogData.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: ["mat-dialog-actions{display:flex;justify-content:space-between}\n"] }]
1666
3418
  }], ctorParameters: function () { return [{ type: undefined, decorators: [{
1667
3419
  type: Inject,
1668
3420
  args: [MAT_DIALOG_DATA]
@@ -1703,7 +3455,7 @@ class EditDialogDataBuilder extends BaseBuilder {
1703
3455
  .withDefault('text', ['Do you really want to delete this entity?'])
1704
3456
  .withDefault('title', 'Delete')
1705
3457
  .getResult();
1706
- return new EditDialogDataInternal(data?.title ? data.title : () => 'Edit', data?.confirmButtonLabel ? data.confirmButtonLabel : 'Save', data?.deleteButtonLabel ? data.deleteButtonLabel : 'Delete', data?.cancelButtonLabel ? data.cancelButtonLabel : 'Cancel', data?.deleteRequiresConfirmDialog ? data.deleteRequiresConfirmDialog : true, data?.editRequiresConfirmDialog ? data.editRequiresConfirmDialog : false, confirmDeleteDialogData, confirmEditDialogData);
3458
+ return new EditDialogDataInternal(data?.title ?? (() => 'Edit'), data?.confirmButtonLabel ?? 'Save', data?.deleteButtonLabel ?? 'Delete', data?.cancelButtonLabel ?? 'Cancel', data?.deleteRequiresConfirmDialog ?? true, data?.editRequiresConfirmDialog ?? false, confirmDeleteDialogData, confirmEditDialogData);
1707
3459
  }
1708
3460
  }
1709
3461
 
@@ -1728,7 +3480,7 @@ class EditEntityDialogDataBuilder extends BaseBuilder {
1728
3480
  // eslint-disable-next-line jsdoc/require-jsdoc
1729
3481
  generateBaseData(data) {
1730
3482
  const editDialogData = new EditDialogDataBuilder(data.editDialogData).getResult();
1731
- return new EditEntityDialogDataInternal(data.entity, data.EntityServiceClass, editDialogData, data.allowDelete ? data.allowDelete : () => true);
3483
+ return new EditEntityDialogDataInternal(data.entity, data.EntityServiceClass, editDialogData, data.allowDelete ?? (() => true));
1732
3484
  }
1733
3485
  }
1734
3486
 
@@ -1745,14 +3497,20 @@ class NgxMatEntityEditDialogComponent {
1745
3497
  this.injector = injector;
1746
3498
  this.dialog = dialog;
1747
3499
  this.EntityUtilities = EntityUtilities;
1748
- this.getWidth = EntityUtilities.getWidth;
3500
+ this.isEntityValid = true;
3501
+ this.isEntityDirty = (async () => false).call(this);
1749
3502
  }
1750
3503
  ngOnInit() {
1751
3504
  this.data = new EditEntityDialogDataBuilder(this.inputData).getResult();
1752
3505
  this.dialogRef.disableClose = true;
1753
3506
  this.entityRows = EntityUtilities.getEntityRows(this.data.entity, false, true);
1754
3507
  this.entityService = this.injector.get(this.data.EntityServiceClass);
1755
- this.entityPriorChanges = cloneDeep(this.data.entity);
3508
+ this.entityPriorChanges = LodashUtilities.cloneDeep(this.data.entity);
3509
+ }
3510
+ // eslint-disable-next-line jsdoc/require-jsdoc
3511
+ checkEntity() {
3512
+ this.isEntityValid = EntityUtilities.isEntityValid(this.data.entity, 'update');
3513
+ this.isEntityDirty = EntityUtilities.dirty(this.data.entity, this.entityPriorChanges);
1756
3514
  }
1757
3515
  /**
1758
3516
  * Tries to save the changes and close the dialog afterwards.
@@ -1760,7 +3518,8 @@ class NgxMatEntityEditDialogComponent {
1760
3518
  */
1761
3519
  edit() {
1762
3520
  if (!this.data.editDialogData.editRequiresConfirmDialog) {
1763
- return this.confirmEdit();
3521
+ this.confirmEdit();
3522
+ return;
1764
3523
  }
1765
3524
  const dialogData = new ConfirmDialogDataBuilder(this.data.editDialogData.confirmEditDialogData)
1766
3525
  .withDefault('text', ['Do you really want to save all changes?'])
@@ -1779,7 +3538,7 @@ class NgxMatEntityEditDialogComponent {
1779
3538
  });
1780
3539
  }
1781
3540
  confirmEdit() {
1782
- this.entityService.update(this.data.entity, this.entityPriorChanges).then(() => this.dialogRef.close(1));
3541
+ void this.entityService.update(this.data.entity, this.entityPriorChanges).then(() => this.dialogRef.close(1));
1783
3542
  }
1784
3543
  /**
1785
3544
  * Tries to delete the entity and close the dialog afterwards.
@@ -1787,7 +3546,8 @@ class NgxMatEntityEditDialogComponent {
1787
3546
  */
1788
3547
  delete() {
1789
3548
  if (!this.data.editDialogData.deleteRequiresConfirmDialog) {
1790
- return this.confirmDelete();
3549
+ this.confirmDelete();
3550
+ return;
1791
3551
  }
1792
3552
  const dialogData = new ConfirmDialogDataBuilder(this.data.editDialogData.confirmDeleteDialogData)
1793
3553
  .withDefault('text', ['Do you really want to delete this entity?'])
@@ -1807,7 +3567,7 @@ class NgxMatEntityEditDialogComponent {
1807
3567
  });
1808
3568
  }
1809
3569
  confirmDelete() {
1810
- this.entityService.delete(this.entityPriorChanges).then(() => this.dialogRef.close(2));
3570
+ void this.entityService.delete(this.entityPriorChanges).then(() => this.dialogRef.close(2));
1811
3571
  }
1812
3572
  /**
1813
3573
  * Reverts all changes made and closes the dialog.
@@ -1818,10 +3578,10 @@ class NgxMatEntityEditDialogComponent {
1818
3578
  }
1819
3579
  }
1820
3580
  NgxMatEntityEditDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityEditDialogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1.MatDialogRef }, { token: i0.Injector }, { token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
1821
- NgxMatEntityEditDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityEditDialogComponent, selector: "ngx-mat-entity-edit-dialog", ngImport: i0, template: "<h2 mat-dialog-title>\n {{data.editDialogData.title(data.entity)}}\n <button *ngIf=\"data.allowDelete(data.entity)\" mat-raised-button (click)=\"delete()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{data.editDialogData.deleteButtonLabel}}\n </button>\n</h2>\n\n<mat-dialog-content>\n <form #form=\"ngForm\" class=\"row\">\n <div class=\"row\" *ngFor=\"let row of entityRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"data.entity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{getWidth(data.entity, key, 'lg')}} col-md-{{getWidth(data.entity, key, 'md')}} col-sm-{{getWidth(data.entity, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button mat-raised-button (click)=\"edit()\" [disabled]=\"!EntityUtilities.isEntityValid(data.entity, 'update') || !EntityUtilities.dirty(data.entity, entityPriorChanges)\">\n {{data.editDialogData.confirmButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.editDialogData.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: ["mat-dialog-actions{display:flex;justify-content:space-between}.delete-button{float:right}\n"], components: [{ type: i3.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit"] }], directives: [{ type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i12.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i14.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i14.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i14.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i12.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }] });
3581
+ NgxMatEntityEditDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityEditDialogComponent, selector: "ngx-mat-entity-edit-dialog", ngImport: i0, template: "<h2 mat-dialog-title>\n {{data.editDialogData.title(data.entity)}}\n <button *ngIf=\"data.allowDelete(data.entity)\" mat-raised-button (click)=\"delete()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{data.editDialogData.deleteButtonLabel}}\n </button>\n</h2>\n\n<mat-dialog-content>\n <form #form=\"ngForm\" class=\"row\">\n <div class=\"row\" *ngFor=\"let row of entityRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"data.entity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(data.entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(data.entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(data.entity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkEntity()\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button mat-raised-button (click)=\"edit()\" [disabled]=\"!isEntityValid || (isEntityDirty | async) === false\">\n {{data.editDialogData.confirmButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.editDialogData.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: ["mat-dialog-actions{display:flex;justify-content:space-between}.delete-button{float:right}\n"], components: [{ type: i4.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit"], outputs: ["inputChangeEvent"] }], directives: [{ type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }], pipes: { "async": i4$1.AsyncPipe } });
1822
3582
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityEditDialogComponent, decorators: [{
1823
3583
  type: Component,
1824
- args: [{ selector: 'ngx-mat-entity-edit-dialog', template: "<h2 mat-dialog-title>\n {{data.editDialogData.title(data.entity)}}\n <button *ngIf=\"data.allowDelete(data.entity)\" mat-raised-button (click)=\"delete()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{data.editDialogData.deleteButtonLabel}}\n </button>\n</h2>\n\n<mat-dialog-content>\n <form #form=\"ngForm\" class=\"row\">\n <div class=\"row\" *ngFor=\"let row of entityRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"data.entity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{getWidth(data.entity, key, 'lg')}} col-md-{{getWidth(data.entity, key, 'md')}} col-sm-{{getWidth(data.entity, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button mat-raised-button (click)=\"edit()\" [disabled]=\"!EntityUtilities.isEntityValid(data.entity, 'update') || !EntityUtilities.dirty(data.entity, entityPriorChanges)\">\n {{data.editDialogData.confirmButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.editDialogData.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: ["mat-dialog-actions{display:flex;justify-content:space-between}.delete-button{float:right}\n"] }]
3584
+ args: [{ selector: 'ngx-mat-entity-edit-dialog', template: "<h2 mat-dialog-title>\n {{data.editDialogData.title(data.entity)}}\n <button *ngIf=\"data.allowDelete(data.entity)\" mat-raised-button (click)=\"delete()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{data.editDialogData.deleteButtonLabel}}\n </button>\n</h2>\n\n<mat-dialog-content>\n <form #form=\"ngForm\" class=\"row\">\n <div class=\"row\" *ngFor=\"let row of entityRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"data.entity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(data.entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(data.entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(data.entity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkEntity()\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button mat-raised-button (click)=\"edit()\" [disabled]=\"!isEntityValid || (isEntityDirty | async) === false\">\n {{data.editDialogData.confirmButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.editDialogData.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: ["mat-dialog-actions{display:flex;justify-content:space-between}.delete-button{float:right}\n"] }]
1825
3585
  }], ctorParameters: function () { return [{ type: undefined, decorators: [{
1826
3586
  type: Inject,
1827
3587
  args: [MAT_DIALOG_DATA]
@@ -1846,7 +3606,7 @@ class BaseDataBuilder extends BaseBuilder {
1846
3606
  }
1847
3607
  // eslint-disable-next-line jsdoc/require-jsdoc
1848
3608
  generateBaseData(data) {
1849
- return new BaseDataInternal(data.title, data.displayColumns, data.EntityServiceClass, data.searchLabel ? data.searchLabel : 'Search', data.createButtonLabel ? data.createButtonLabel : 'Create', data.searchString ? data.searchString : defaultSearchFunction, data.allowCreate === false ? data.allowCreate : true, data.allowEdit ? data.allowEdit : () => true, data.allowDelete ? data.allowDelete : () => true, data.multiSelectActions ? data.multiSelectActions : [], data.multiSelectLabel ? data.multiSelectLabel : 'Actions', data.EntityClass, data.edit, data.create);
3609
+ return new BaseDataInternal(data.title, data.displayColumns, data.EntityServiceClass, data.searchLabel ?? 'Search', data.createButtonLabel ?? 'Create', data.searchString ?? defaultSearchFunction, data.allowCreate ?? true, data.allowEdit ?? (() => true), data.allowDelete ?? (() => true), data.multiSelectActions ?? [], data.multiSelectLabel ?? 'Actions', data.EntityClass, data.edit, data.create);
1850
3610
  }
1851
3611
  }
1852
3612
  /**
@@ -1892,7 +3652,7 @@ class TableDataBuilder extends BaseBuilder {
1892
3652
  }
1893
3653
  if ((data.baseData.allowEdit && data.baseData.allowEdit !== (() => false)
1894
3654
  || data.baseData.allowDelete && data.baseData.allowDelete !== (() => false)
1895
- || data.baseData.allowCreate)
3655
+ || data.baseData.allowCreate === true)
1896
3656
  && !data.baseData.EntityClass) {
1897
3657
  throw new Error(`
1898
3658
  Missing required Input data "EntityClass".
@@ -1960,21 +3720,19 @@ class NgxMatEntityTableComponent {
1960
3720
  return this.data.baseData.displayColumns.find((dp) => dp.displayName === header)?.value(entity);
1961
3721
  };
1962
3722
  this.dataSource.sort = this.sort;
1963
- if (this.data.baseData.searchString) {
1964
- this.dataSource.filterPredicate = (entity, filter) => {
1965
- const searchStr = this.data.baseData.searchString(entity);
1966
- const formattedSearchString = searchStr.toLowerCase();
1967
- const formattedFilterString = filter.toLowerCase();
1968
- return formattedSearchString.includes(formattedFilterString);
1969
- };
1970
- }
3723
+ this.dataSource.filterPredicate = (entity, filter) => {
3724
+ const searchStr = this.data.baseData.searchString(entity);
3725
+ const formattedSearchString = searchStr.toLowerCase();
3726
+ const formattedFilterString = filter.toLowerCase();
3727
+ return formattedSearchString.includes(formattedFilterString);
3728
+ };
1971
3729
  this.dataSource.filter = this.filter;
1972
3730
  this.dataSource.paginator = this.paginator;
1973
3731
  this.entityService.entitiesSubject.pipe(takeUntil(this.onDestroy)).subscribe((entities) => {
1974
3732
  this.dataSource.data = entities;
1975
3733
  this.selection.clear();
1976
3734
  });
1977
- this.entityService.read();
3735
+ void this.entityService.read();
1978
3736
  }
1979
3737
  /**
1980
3738
  * Edits an entity. This either calls the edit-Method provided by the user or uses a default edit-dialog.
@@ -1991,11 +3749,11 @@ class NgxMatEntityTableComponent {
1991
3749
  this.data.baseData.edit(new this.data.baseData.EntityClass(entity));
1992
3750
  }
1993
3751
  else {
1994
- this.editDefault(new this.data.baseData.EntityClass(entity));
3752
+ void this.editDefault(new this.data.baseData.EntityClass(entity));
1995
3753
  }
1996
3754
  }
1997
3755
  }
1998
- editDefault(entity) {
3756
+ async editDefault(entity) {
1999
3757
  const inputDialogData = {
2000
3758
  entity: entity,
2001
3759
  EntityServiceClass: this.data.baseData.EntityServiceClass,
@@ -2003,19 +3761,18 @@ class NgxMatEntityTableComponent {
2003
3761
  editDialogData: this.data.editDialogData
2004
3762
  };
2005
3763
  const dialogData = new EditEntityDialogDataBuilder(inputDialogData).getResult();
2006
- firstValueFrom(this.dialog.open(NgxMatEntityEditDialogComponent, {
3764
+ const res = await firstValueFrom(this.dialog.open(NgxMatEntityEditDialogComponent, {
2007
3765
  data: dialogData,
2008
3766
  minWidth: '60%',
2009
3767
  autoFocus: false,
2010
3768
  restoreFocus: false
2011
- }).afterClosed()).then((res) => {
2012
- if (res === 0) {
2013
- const data = this.dataSource.data;
2014
- data[this.dataSource.data.findIndex((e) => e[this.entityService.idKey] === entity[this.entityService.idKey])] = entity;
2015
- this.dataSource.data = data;
2016
- this.selection.clear();
2017
- }
2018
- });
3769
+ }).afterClosed());
3770
+ if (res === 0) {
3771
+ const data = this.dataSource.data;
3772
+ data[this.dataSource.data.findIndex((e) => e[this.entityService.idKey] === entity[this.entityService.idKey])] = entity;
3773
+ this.dataSource.data = data;
3774
+ this.selection.clear();
3775
+ }
2019
3776
  }
2020
3777
  /**
2021
3778
  * Creates a new Entity. This either calls the create-Method provided by the user or uses a default create-dialog.
@@ -2056,7 +3813,8 @@ class NgxMatEntityTableComponent {
2056
3813
  */
2057
3814
  runMultiAction(action) {
2058
3815
  if (!action.requireConfirmDialog || !action.requireConfirmDialog(this.selection.selected)) {
2059
- return this.confirmRunMultiAction(action);
3816
+ this.confirmRunMultiAction(action);
3817
+ return;
2060
3818
  }
2061
3819
  const dialogData = new ConfirmDialogDataBuilder(action.confirmDialogData)
2062
3820
  .withDefault('text', [`Do you really want to run this action on ${this.selection.selected.length} entries?`])
@@ -2099,7 +3857,7 @@ class NgxMatEntityTableComponent {
2099
3857
  this.selection.clear();
2100
3858
  }
2101
3859
  else {
2102
- this.dataSource.data.forEach((row) => this.selection.select(row));
3860
+ this.dataSource.data.forEach(row => this.selection.select(row));
2103
3861
  }
2104
3862
  }
2105
3863
  /**
@@ -2128,7 +3886,7 @@ class NgxMatEntityTableComponent {
2128
3886
  }
2129
3887
  }
2130
3888
  NgxMatEntityTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityTableComponent, deps: [{ token: i1.MatDialog }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
2131
- NgxMatEntityTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityTableComponent, selector: "ngx-mat-entity-table", inputs: { tableData: "tableData" }, viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, static: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true, static: true }, { propertyName: "filter", first: true, predicate: ["filter"], descendants: true, static: true }], ngImport: i0, template: "<h1 class=\"title\">{{data.baseData.title}}</h1>\n\n<div class=\"row\">\n <mat-form-field class=\"col-lg-8 col-md-6 col-sm-12\">\n <mat-label>{{data.baseData.searchLabel}}</mat-label>\n <input matInput (keyup)=\"applyFilter($event)\" />\n </mat-form-field>\n <div\n *ngIf=\"data.baseData.multiSelectActions.length\"\n [class.col-lg-2]=\"data.baseData.allowCreate\"\n [class.col-lg-4]=\"!data.baseData.allowCreate\"\n [class.col-md-3]=\"data.baseData.allowCreate\"\n [class.col-md-6]=\"!data.baseData.allowCreate\"\n [class.col-sm-6]=\"data.baseData.allowCreate\"\n [class.col-sm-12]=\"!data.baseData.allowCreate\"\n >\n <button class=\"actions-button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{data.baseData.multiSelectLabel}}\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button *ngFor=\"let action of data.baseData.multiSelectActions\" [disabled]=\"multiActionDisabled(action)\" (click)=\"runMultiAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n\n <div\n *ngIf=\"data.baseData.allowCreate\"\n [class.col-lg-2]=\"data.baseData.multiSelectActions.length\"\n [class.col-lg-4]=\"!data.baseData.multiSelectActions.length\"\n [class.col-md-3]=\"data.baseData.multiSelectActions.length\"\n [class.col-md-6]=\"!data.baseData.multiSelectActions.length\"\n [class.col-sm-6]=\"data.baseData.multiSelectActions.length\"\n [class.col-sm-12]=\"!data.baseData.multiSelectActions.length\"\n >\n <button class=\"create-button\" (click)=\"createEntity()\" mat-raised-button>\n {{data.baseData.createButtonLabel}}\n </button>\n </div>\n</div>\n\n<div class=\"mat-elevation-z8\">\n <mat-table *ngIf=\"dataSource\" [dataSource]=\"dataSource\" matSort>\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"> </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\" class=\"module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"> </mat-checkbox>\n </mat-cell>\n </ng-container>\n\n <ng-container *ngFor=\"let dCol of data.baseData.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" [class.enabled]=\"data.baseData.allowEdit(entity)\" (click)=\"editEntity(entity)\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n\n <mat-paginator *ngIf=\"dataSource\" id=\"paginator\" [length]=\"dataSource.filteredData.length\" [pageIndex]=\"0\" [pageSize]=\"10\" [pageSizeOptions]=\"[5, 10, 25, 50]\"> </mat-paginator>\n</div>\n", styles: [".title{text-align:center}button{width:100%}.mat-column-select{flex:0 0 75px}.enabled:hover{cursor:pointer}@media (max-width: 767px){.actions-button,.create-button{margin-bottom:15px}}\n"], components: [{ type: i2.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i3.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i4$1.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { type: i4$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { type: i7$1.MatPaginator, selector: "mat-paginator", inputs: ["disabled"], exportAs: ["matPaginator"] }], directives: [{ type: i2.MatLabel, selector: "mat-label" }, { type: i13.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i12.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { type: i12.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i9.MatCellDef, selector: "[matCellDef]" }, { type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }] });
3889
+ NgxMatEntityTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityTableComponent, selector: "ngx-mat-entity-table", inputs: { tableData: "tableData" }, viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, static: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true, static: true }, { propertyName: "filter", first: true, predicate: ["filter"], descendants: true, static: true }], ngImport: i0, template: "<h1 class=\"title\">{{data.baseData.title}}</h1>\n\n<div class=\"row\">\n <mat-form-field class=\"col-lg-8 col-md-6 col-sm-12\">\n <mat-label>{{data.baseData.searchLabel}}</mat-label>\n <input matInput (keyup)=\"applyFilter($event)\" />\n </mat-form-field>\n <div\n *ngIf=\"data.baseData.multiSelectActions.length\"\n [class.col-lg-2]=\"data.baseData.allowCreate\"\n [class.col-lg-4]=\"!data.baseData.allowCreate\"\n [class.col-md-3]=\"data.baseData.allowCreate\"\n [class.col-md-6]=\"!data.baseData.allowCreate\"\n [class.col-sm-6]=\"data.baseData.allowCreate\"\n [class.col-sm-12]=\"!data.baseData.allowCreate\"\n >\n <button class=\"actions-button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{data.baseData.multiSelectLabel}}\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button *ngFor=\"let action of data.baseData.multiSelectActions\" [disabled]=\"multiActionDisabled(action)\" (click)=\"runMultiAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n\n <div\n *ngIf=\"data.baseData.allowCreate\"\n [class.col-lg-2]=\"data.baseData.multiSelectActions.length\"\n [class.col-lg-4]=\"!data.baseData.multiSelectActions.length\"\n [class.col-md-3]=\"data.baseData.multiSelectActions.length\"\n [class.col-md-6]=\"!data.baseData.multiSelectActions.length\"\n [class.col-sm-6]=\"data.baseData.multiSelectActions.length\"\n [class.col-sm-12]=\"!data.baseData.multiSelectActions.length\"\n >\n <button class=\"create-button\" (click)=\"createEntity()\" mat-raised-button>\n {{data.baseData.createButtonLabel}}\n </button>\n </div>\n</div>\n\n<div class=\"mat-elevation-z8\">\n <mat-table *ngIf=\"dataSource\" [dataSource]=\"dataSource\" matSort>\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"> </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\" class=\"module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"> </mat-checkbox>\n </mat-cell>\n </ng-container>\n\n <ng-container *ngFor=\"let dCol of data.baseData.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" [class.enabled]=\"data.baseData.allowEdit(entity)\" (click)=\"editEntity(entity)\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n\n <mat-paginator *ngIf=\"dataSource\" id=\"paginator\" [length]=\"dataSource.filteredData.length\" [pageIndex]=\"0\" [pageSize]=\"10\" [pageSizeOptions]=\"[5, 10, 25, 50]\"> </mat-paginator>\n</div>\n", styles: [".title{text-align:center}button{width:100%}.mat-column-select{flex:0 0 75px}.enabled:hover{cursor:pointer}@media (max-width: 767px){.actions-button,.create-button{margin-bottom:15px}}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i4.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i4$3.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { type: i4$3.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { type: i5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { type: i7.MatPaginator, selector: "mat-paginator", inputs: ["disabled"], exportAs: ["matPaginator"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i4$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4$3.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { type: i4$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i5.MatCellDef, selector: "[matCellDef]" }, { type: i5.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i5.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i5.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }] });
2132
3890
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityTableComponent, decorators: [{
2133
3891
  type: Component,
2134
3892
  args: [{ selector: 'ngx-mat-entity-table', template: "<h1 class=\"title\">{{data.baseData.title}}</h1>\n\n<div class=\"row\">\n <mat-form-field class=\"col-lg-8 col-md-6 col-sm-12\">\n <mat-label>{{data.baseData.searchLabel}}</mat-label>\n <input matInput (keyup)=\"applyFilter($event)\" />\n </mat-form-field>\n <div\n *ngIf=\"data.baseData.multiSelectActions.length\"\n [class.col-lg-2]=\"data.baseData.allowCreate\"\n [class.col-lg-4]=\"!data.baseData.allowCreate\"\n [class.col-md-3]=\"data.baseData.allowCreate\"\n [class.col-md-6]=\"!data.baseData.allowCreate\"\n [class.col-sm-6]=\"data.baseData.allowCreate\"\n [class.col-sm-12]=\"!data.baseData.allowCreate\"\n >\n <button class=\"actions-button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{data.baseData.multiSelectLabel}}\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button *ngFor=\"let action of data.baseData.multiSelectActions\" [disabled]=\"multiActionDisabled(action)\" (click)=\"runMultiAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n\n <div\n *ngIf=\"data.baseData.allowCreate\"\n [class.col-lg-2]=\"data.baseData.multiSelectActions.length\"\n [class.col-lg-4]=\"!data.baseData.multiSelectActions.length\"\n [class.col-md-3]=\"data.baseData.multiSelectActions.length\"\n [class.col-md-6]=\"!data.baseData.multiSelectActions.length\"\n [class.col-sm-6]=\"data.baseData.multiSelectActions.length\"\n [class.col-sm-12]=\"!data.baseData.multiSelectActions.length\"\n >\n <button class=\"create-button\" (click)=\"createEntity()\" mat-raised-button>\n {{data.baseData.createButtonLabel}}\n </button>\n </div>\n</div>\n\n<div class=\"mat-elevation-z8\">\n <mat-table *ngIf=\"dataSource\" [dataSource]=\"dataSource\" matSort>\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"> </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\" class=\"module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"> </mat-checkbox>\n </mat-cell>\n </ng-container>\n\n <ng-container *ngFor=\"let dCol of data.baseData.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" [class.enabled]=\"data.baseData.allowEdit(entity)\" (click)=\"editEntity(entity)\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n\n <mat-paginator *ngIf=\"dataSource\" id=\"paginator\" [length]=\"dataSource.filteredData.length\" [pageIndex]=\"0\" [pageSize]=\"10\" [pageSizeOptions]=\"[5, 10, 25, 50]\"> </mat-paginator>\n</div>\n", styles: [".title{text-align:center}button{width:100%}.mat-column-select{flex:0 0 75px}.enabled:hover{cursor:pointer}@media (max-width: 767px){.actions-button,.create-button{margin-bottom:15px}}\n"] }]
@@ -2259,56 +4017,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
2259
4017
  }]
2260
4018
  }] });
2261
4019
 
2262
- /**
2263
- * The internal EntityArrayDecoratorConfig. Sets default values.
2264
- */
2265
- class EntityArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2266
- constructor(data) {
2267
- super(data);
2268
- this.createInline = data.createInline != undefined ? data.createInline : true;
2269
- this.displayStyle = data.displayStyle;
2270
- this.itemType = data.itemType;
2271
- this.EntityClass = data.EntityClass;
2272
- this.displayColumns = data.displayColumns;
2273
- this.createInline = data.createInline != undefined ? data.createInline : true;
2274
- this.missingErrorMessage = data.missingErrorMessage ? data.missingErrorMessage : 'Needs to contain at least one value';
2275
- this.defaultWidths = data.defaultWidths ? data.defaultWidths : [12, 12, 12];
2276
- this.addButtonLabel = data.addButtonLabel ? data.addButtonLabel : 'Add';
2277
- this.removeButtonLabel = data.removeButtonLabel ? data.removeButtonLabel : 'Remove';
2278
- }
2279
- }
2280
- /**
2281
- * The internal StringChipsArrayDecoratorConfig. Sets default values.
2282
- */
2283
- class StringChipsArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2284
- constructor(data) {
2285
- super(data);
2286
- this.deleteIcon = data.deleteIcon ? data.deleteIcon : 'fas fa-circle-minus';
2287
- this.displayStyle = data.displayStyle;
2288
- this.itemType = data.itemType;
2289
- this.maxLength = data.maxLength;
2290
- this.minLength = data.minLength;
2291
- this.regex = data.regex;
2292
- this.defaultWidths = data.defaultWidths ? data.defaultWidths : [6, 12, 12];
2293
- }
2294
- }
2295
- /**
2296
- * The internal AutocompleteStringChipsArrayDecoratorConfig. Sets default values.
2297
- */
2298
- class AutocompleteStringChipsArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2299
- constructor(data) {
2300
- super(data);
2301
- this.autocompleteValues = data.autocompleteValues;
2302
- this.deleteIcon = data.deleteIcon ? data.deleteIcon : 'fas fa-circle-minus';
2303
- this.displayStyle = data.displayStyle;
2304
- this.itemType = data.itemType;
2305
- this.maxLength = data.maxLength;
2306
- this.minLength = data.minLength;
2307
- this.regex = data.regex;
2308
- this.defaultWidths = data.defaultWidths ? data.defaultWidths : [6, 12, 12];
2309
- }
2310
- }
2311
-
2312
4020
  /**
2313
4021
  * Decorator for setting and getting array property metadata.
2314
4022
  *
@@ -2320,6 +4028,12 @@ function array(metadata) {
2320
4028
  switch (metadata.itemType) {
2321
4029
  case DecoratorTypes.OBJECT:
2322
4030
  return baseProperty(new EntityArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY);
4031
+ case DecoratorTypes.DATE:
4032
+ return baseProperty(new DateArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY_DATE);
4033
+ case DecoratorTypes.DATE_TIME:
4034
+ return baseProperty(new DateTimeArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY_DATE_TIME);
4035
+ case DecoratorTypes.DATE_RANGE:
4036
+ return baseProperty(new DateRangeArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY_DATE_RANGE);
2323
4037
  case DecoratorTypes.STRING:
2324
4038
  return baseProperty(new StringChipsArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY_STRING_CHIPS);
2325
4039
  case DecoratorTypes.STRING_AUTOCOMPLETE:
@@ -2360,7 +4074,7 @@ class CheckboxBooleanDecoratorConfigInternal extends PropertyDecoratorConfigInte
2360
4074
  constructor(data) {
2361
4075
  super(data);
2362
4076
  this.displayStyle = data.displayStyle;
2363
- this.required = data.required === undefined ? false : data.required;
4077
+ this.required = data.required ?? false;
2364
4078
  }
2365
4079
  }
2366
4080
  /**
@@ -2370,7 +4084,7 @@ class ToggleBooleanDecoratorConfigInternal extends PropertyDecoratorConfigIntern
2370
4084
  constructor(data) {
2371
4085
  super(data);
2372
4086
  this.displayStyle = data.displayStyle;
2373
- this.required = data.required === undefined ? false : data.required;
4087
+ this.required = data.required ?? false;
2374
4088
  }
2375
4089
  }
2376
4090
 
@@ -2398,6 +4112,76 @@ function boolean(metadata) {
2398
4112
  class BooleanDecoratorConfig extends PropertyDecoratorConfig {
2399
4113
  }
2400
4114
 
4115
+ /**
4116
+ * The internal DefaultDateDecoratorConfig. Sets default values.
4117
+ */
4118
+ class DefaultDateDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4119
+ constructor(data) {
4120
+ super(data);
4121
+ this.displayStyle = data.displayStyle;
4122
+ this.max = data.max;
4123
+ this.min = data.min;
4124
+ this.filter = data.filter;
4125
+ }
4126
+ }
4127
+ /**
4128
+ * The internal DateRangeDateDecoratorConfig. Sets default values.
4129
+ */
4130
+ class DateRangeDateDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4131
+ constructor(data) {
4132
+ super(data);
4133
+ this.displayStyle = data.displayStyle;
4134
+ this.minStart = data.minStart;
4135
+ this.maxStart = data.maxStart;
4136
+ this.minEnd = data.minEnd;
4137
+ this.maxEnd = data.maxEnd;
4138
+ this.filter = data.filter;
4139
+ this.placeholderStart = data.placeholderStart ?? 'Start';
4140
+ this.placeholderEnd = data.placeholderEnd ?? 'End';
4141
+ }
4142
+ }
4143
+ /**
4144
+ * The internal DateTimeDateDecoratorConfig. Sets default values.
4145
+ */
4146
+ class DateTimeDateDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4147
+ constructor(data) {
4148
+ super(data);
4149
+ this.displayStyle = data.displayStyle;
4150
+ this.times = data.times ?? DateUtilities.getDefaultTimes();
4151
+ this.timeDisplayName = data.timeDisplayName ?? 'Time';
4152
+ this.minDate = data.minDate;
4153
+ this.maxDate = data.maxDate;
4154
+ this.filterDate = data.filterDate;
4155
+ this.minTime = data.minTime;
4156
+ this.maxTime = data.maxTime;
4157
+ this.filterTime = data.filterTime;
4158
+ }
4159
+ }
4160
+
4161
+ /**
4162
+ * Decorator for setting and getting date property metadata.
4163
+ *
4164
+ * @param metadata - The metadata of the date property.
4165
+ * @returns The method that defines the metadata.
4166
+ */
4167
+ function date(metadata) {
4168
+ if (metadata.displayStyle === 'date') {
4169
+ return baseProperty(new DefaultDateDecoratorConfigInternal(metadata), DecoratorTypes.DATE);
4170
+ }
4171
+ else if (metadata.displayStyle === 'datetime') {
4172
+ return baseProperty(new DateTimeDateDecoratorConfigInternal(metadata), DecoratorTypes.DATE_TIME);
4173
+ }
4174
+ else {
4175
+ return baseProperty(new DateRangeDateDecoratorConfigInternal(metadata), DecoratorTypes.DATE_RANGE);
4176
+ }
4177
+ }
4178
+
4179
+ /**
4180
+ * Definition for the @date metadata.
4181
+ */
4182
+ class DateDecoratorConfig extends PropertyDecoratorConfig {
4183
+ }
4184
+
2401
4185
  /**
2402
4186
  * The internal DefaultNumberDecoratorConfig. Sets default values.
2403
4187
  */
@@ -2474,6 +4258,128 @@ class ObjectDecoratorConfig extends PropertyDecoratorConfig {
2474
4258
  class StringDecoratorConfig extends PropertyDecoratorConfig {
2475
4259
  }
2476
4260
 
4261
+ /**
4262
+ * The internal DefaultFileDecoratorConfig. Sets default values.
4263
+ */
4264
+ class DefaultFileDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4265
+ constructor(data) {
4266
+ super(data);
4267
+ this.type = data.type;
4268
+ this.preview = false;
4269
+ this.multiple = data.multiple;
4270
+ this.deleteIcon = data.deleteIcon ?? 'fas fa-circle-minus';
4271
+ this.allowedMimeTypes = data.allowedMimeTypes ?? ['*'];
4272
+ this.maxSize = data.maxSize ?? 10;
4273
+ this.maxSizeTotal = data.maxSizeTotal ?? 100;
4274
+ this.mimeTypeErrorDialog = data.mimeTypeErrorDialog ?? getDefaultMimeTypeErrorDialogData(data);
4275
+ this.maxSizeErrorDialog = data.maxSizeErrorDialog ?? getDefaultMaxSizeErrorDialogData(data);
4276
+ this.maxSizeTotalErrorDialog = data.maxSizeTotalErrorDialog ?? getDefaultMaxSizeTotalErrorDialogData(data);
4277
+ this.dragAndDrop = data.dragAndDrop ?? data.multiple;
4278
+ }
4279
+ }
4280
+ /**
4281
+ * The internal ImageFileDecoratorConfig. Sets default values.
4282
+ */
4283
+ class ImageFileDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4284
+ constructor(data) {
4285
+ super(data);
4286
+ this.type = data.type;
4287
+ this.allowedMimeTypes = data.allowedMimeTypes ?? ['image/*'];
4288
+ this.multiple = data.multiple;
4289
+ this.preview = data.preview ?? true;
4290
+ this.deleteIcon = data.deleteIcon ?? 'fas fa-circle-minus';
4291
+ this.maxSize = data.maxSize ?? 10;
4292
+ this.maxSizeTotal = data.maxSizeTotal ?? 100;
4293
+ this.mimeTypeErrorDialog = data.mimeTypeErrorDialog ?? getDefaultMimeTypeErrorDialogData(data);
4294
+ this.maxSizeErrorDialog = data.maxSizeErrorDialog ?? getDefaultMaxSizeErrorDialogData(data);
4295
+ this.maxSizeTotalErrorDialog = data.maxSizeTotalErrorDialog ?? getDefaultMaxSizeTotalErrorDialogData(data);
4296
+ this.previewPlaceholderUrl = data.previewPlaceholderUrl;
4297
+ this.dragAndDrop = data.dragAndDrop ?? data.multiple;
4298
+ }
4299
+ }
4300
+ /**
4301
+ * Gets the default dialog data for the error dialog to display
4302
+ * when the user tries to add a file with a wrong type.
4303
+ *
4304
+ * @param data - The File Decorator data.
4305
+ * @returns The dialog data with set default values.
4306
+ */
4307
+ function getDefaultMimeTypeErrorDialogData(data) {
4308
+ return {
4309
+ type: data.mimeTypeErrorDialog?.type ?? 'info-only',
4310
+ // eslint-disable-next-line max-len
4311
+ text: data.mimeTypeErrorDialog?.text ?? (data.multiple ? ['One of the uploaded files has the wrong type.'] : ['The uploaded file has the wrong type.']),
4312
+ title: data.mimeTypeErrorDialog?.title ?? (data.multiple ? 'Error adding files' : 'Error adding file'),
4313
+ confirmButtonLabel: data.mimeTypeErrorDialog?.confirmButtonLabel,
4314
+ cancelButtonLabel: data.mimeTypeErrorDialog?.cancelButtonLabel,
4315
+ requireConfirmation: data.mimeTypeErrorDialog?.requireConfirmation,
4316
+ confirmationText: data.mimeTypeErrorDialog?.confirmationText
4317
+ };
4318
+ }
4319
+ /**
4320
+ * Gets the default dialog data for the error dialog to display
4321
+ * when the user tries to add a single file that is bigger than the allowed maxSize.
4322
+ *
4323
+ * @param data - The File Decorator data.
4324
+ * @returns The dialog data with set default values.
4325
+ */
4326
+ function getDefaultMaxSizeErrorDialogData(data) {
4327
+ return {
4328
+ type: data.mimeTypeErrorDialog?.type ?? 'info-only',
4329
+ // eslint-disable-next-line max-len
4330
+ text: data.mimeTypeErrorDialog?.text ?? (data.multiple ? ['One of the uploaded files is too big'] : ['The uploaded files is too big']),
4331
+ title: data.mimeTypeErrorDialog?.title ?? (data.multiple ? 'Error adding files' : 'Error adding file'),
4332
+ confirmButtonLabel: data.mimeTypeErrorDialog?.confirmButtonLabel,
4333
+ cancelButtonLabel: data.mimeTypeErrorDialog?.cancelButtonLabel,
4334
+ requireConfirmation: data.mimeTypeErrorDialog?.requireConfirmation,
4335
+ confirmationText: data.mimeTypeErrorDialog?.confirmationText
4336
+ };
4337
+ }
4338
+ /**
4339
+ * Gets the default dialog data for the error dialog to display
4340
+ * when the user tries to add a single file that is bigger than the allowed maxSize.
4341
+ *
4342
+ * @param data - The File Decorator data.
4343
+ * @returns The dialog data with set default values.
4344
+ */
4345
+ function getDefaultMaxSizeTotalErrorDialogData(data) {
4346
+ return {
4347
+ type: data.mimeTypeErrorDialog?.type ?? 'info-only',
4348
+ // eslint-disable-next-line max-len
4349
+ text: data.mimeTypeErrorDialog?.text ?? ['The size of all files combined is too big'],
4350
+ title: data.mimeTypeErrorDialog?.title ?? (data.multiple ? 'Error adding files' : 'Error adding file'),
4351
+ confirmButtonLabel: data.mimeTypeErrorDialog?.confirmButtonLabel,
4352
+ cancelButtonLabel: data.mimeTypeErrorDialog?.cancelButtonLabel,
4353
+ requireConfirmation: data.mimeTypeErrorDialog?.requireConfirmation,
4354
+ confirmationText: data.mimeTypeErrorDialog?.confirmationText
4355
+ };
4356
+ }
4357
+
4358
+ /**
4359
+ * Decorator for setting and getting file property metadata.
4360
+ *
4361
+ * @param metadata - The metadata of the file property.
4362
+ * @returns The method that defines the metadata.
4363
+ * @throws When an unknown metadata type was provided.
4364
+ */
4365
+ function file(metadata) {
4366
+ switch (metadata.type) {
4367
+ case 'other':
4368
+ return baseProperty(new DefaultFileDecoratorConfigInternal(metadata), DecoratorTypes.FILE_DEFAULT);
4369
+ case 'image':
4370
+ return baseProperty(new ImageFileDecoratorConfigInternal(metadata), DecoratorTypes.FILE_IMAGE);
4371
+ default:
4372
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
4373
+ throw new Error(`Unknown metadata type ${metadata.type}`);
4374
+ }
4375
+ }
4376
+
4377
+ /**
4378
+ * Definition for the @file metadata.
4379
+ */
4380
+ class FileDecoratorConfig extends PropertyDecoratorConfig {
4381
+ }
4382
+
2477
4383
  /**
2478
4384
  * Public API Surface of ngx-material-entity.
2479
4385
  */
@@ -2482,5 +4388,5 @@ class StringDecoratorConfig extends PropertyDecoratorConfig {
2482
4388
  * Generated bundle index. Do not edit.
2483
4389
  */
2484
4390
 
2485
- export { DateUtilities, DecoratorTypes, Entity, EntityService, EntityUtilities, NgxMatEntityConfirmDialogComponent, NgxMatEntityConfirmDialogModule, NgxMatEntityCreateDialogComponent, NgxMatEntityCreateDialogModule, NgxMatEntityEditDialogComponent, NgxMatEntityEditDialogModule, NgxMatEntityInputComponent, NgxMatEntityInputModule, NgxMatEntityTableComponent, NgxMatEntityTableModule, array, boolean, getValidationErrorMessage, number, object, string };
4391
+ export { ArrayDecoratorConfig, DateUtilities, DecoratorTypes, Entity, EntityService, EntityUtilities, FileUtilities, NgxMatEntityConfirmDialogComponent, NgxMatEntityConfirmDialogModule, NgxMatEntityCreateDialogComponent, NgxMatEntityCreateDialogModule, NgxMatEntityEditDialogComponent, NgxMatEntityEditDialogModule, NgxMatEntityInputComponent, NgxMatEntityInputModule, NgxMatEntityTableComponent, NgxMatEntityTableModule, array, boolean, date, file, getValidationErrorMessage, number, object, string };
2486
4392
  //# sourceMappingURL=ngx-material-entity.mjs.map