ngx-material-entity 0.1.4 → 1.0.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 (156) hide show
  1. package/README.md +416 -39
  2. package/capsulation/lodash.utilities.d.ts +62 -0
  3. package/capsulation/reflect.utilities.d.ts +56 -0
  4. package/classes/base.builder.d.ts +2 -1
  5. package/classes/date.utilities.d.ts +18 -6
  6. package/classes/entity.model.d.ts +9 -2
  7. package/classes/entity.service.d.ts +38 -1
  8. package/classes/entity.utilities.d.ts +45 -16
  9. package/classes/file.utilities.d.ts +52 -0
  10. package/components/input/add-array-item-dialog-data.builder.d.ts +3 -2
  11. package/components/input/add-array-item-dialog-data.d.ts +2 -1
  12. package/components/input/array/array-date-input/array-date-input.component.d.ts +11 -0
  13. package/components/input/array/array-date-range-input/array-date-range-input.component.d.ts +20 -0
  14. package/components/input/array/array-date-time-input/array-date-time-input.component.d.ts +22 -0
  15. package/components/input/array/array-string-autocomplete-chips/array-string-autocomplete-chips.component.d.ts +50 -0
  16. package/components/input/array/array-string-chips-input/array-string-chips-input.component.d.ts +42 -0
  17. package/components/input/array/array-table.class.d.ts +48 -0
  18. package/components/input/base-input.component.d.ts +57 -0
  19. package/components/input/boolean/boolean-checkbox-input/boolean-checkbox-input.component.d.ts +10 -0
  20. package/components/input/boolean/boolean-dropdown-input/boolean-dropdown-input.component.d.ts +9 -0
  21. package/components/input/boolean/boolean-toggle-input/boolean-toggle-input.component.d.ts +10 -0
  22. package/components/input/custom/custom.component.d.ts +13 -0
  23. package/components/input/date/date-input/date-input.component.d.ts +11 -0
  24. package/components/input/date/date-range-input/date-range-input.component.d.ts +19 -0
  25. package/components/input/date/date-time-input/date-time-input.component.d.ts +30 -0
  26. package/components/input/file/file-default-input/file-default-input.component.d.ts +13 -0
  27. package/components/input/file/file-image-input/file-image-input.component.d.ts +22 -0
  28. package/components/input/file/file-input/dragDrop.directive.d.ts +32 -0
  29. package/components/input/file/file-input/file-input.component.d.ts +33 -0
  30. package/components/input/input.component.d.ts +49 -92
  31. package/components/input/input.module.d.ts +41 -16
  32. package/components/input/number/number-dropdown-input/number-dropdown-input.component.d.ts +9 -0
  33. package/components/input/number/number-input/number-input.component.d.ts +9 -0
  34. package/components/input/number/number-slider-input/number-slider-input.component.d.ts +9 -0
  35. package/components/input/string/string-autocomplete-input/string-autocomplete-input.component.d.ts +18 -0
  36. package/components/input/string/string-dropdown-input/string-dropdown-input.component.d.ts +9 -0
  37. package/components/input/string/string-input/string-input.component.d.ts +9 -0
  38. package/components/input/string/string-password-input/string-password-input.component.d.ts +15 -0
  39. package/components/input/string/string-textbox-input/string-textbox-input.component.d.ts +9 -0
  40. package/components/table/create-dialog/create-entity-dialog-data.builder.d.ts +3 -2
  41. package/components/table/create-dialog/create-entity-dialog-data.d.ts +2 -1
  42. package/components/table/create-dialog/create-entity-dialog.component.d.ts +7 -2
  43. package/components/table/edit-dialog/edit-dialog-data.builder.d.ts +3 -2
  44. package/components/table/edit-dialog/edit-entity-dialog-data.d.ts +6 -1
  45. package/components/table/edit-dialog/edit-entity-dialog.builder.d.ts +5 -3
  46. package/components/table/edit-dialog/edit-entity-dialog.component.d.ts +6 -2
  47. package/components/table/table-data.builder.d.ts +9 -8
  48. package/components/table/table-data.d.ts +18 -10
  49. package/components/table/table.component.d.ts +2 -1
  50. package/decorators/array/array-decorator-internal.data.d.ts +71 -6
  51. package/decorators/array/array-decorator.data.d.ts +178 -12
  52. package/decorators/array/array.decorator.d.ts +3 -2
  53. package/decorators/base/base-property.decorator.d.ts +2 -3
  54. package/decorators/base/decorator-types.enum.d.ts +15 -5
  55. package/decorators/custom/custom-decorator-internal.data.d.ts +17 -0
  56. package/decorators/custom/custom-decorator.data.d.ts +37 -0
  57. package/decorators/custom/custom.decorator.d.ts +11 -0
  58. package/decorators/date/date-decorator-internal.data.d.ts +2 -2
  59. package/decorators/date/date.decorator.d.ts +8 -0
  60. package/decorators/file/file-decorator-internal.data.d.ts +92 -0
  61. package/decorators/file/file-decorator.data.d.ts +92 -0
  62. package/decorators/file/file.decorator.d.ts +9 -0
  63. package/decorators/number/number-decorator-internal.data.d.ts +20 -1
  64. package/decorators/number/number-decorator.data.d.ts +27 -1
  65. package/decorators/number/number.decorator.d.ts +2 -2
  66. package/decorators/object/object-decorator-internal.data.d.ts +2 -2
  67. package/decorators/object/object-decorator.data.d.ts +3 -3
  68. package/decorators/object/object.decorator.d.ts +2 -1
  69. package/decorators/string/string-decorator-internal.data.d.ts +14 -1
  70. package/decorators/string/string-decorator.data.d.ts +37 -1
  71. package/decorators/string/string.decorator.d.ts +2 -2
  72. package/esm2020/capsulation/lodash.utilities.mjs +75 -0
  73. package/esm2020/capsulation/reflect.utilities.mjs +69 -0
  74. package/esm2020/classes/base.builder.mjs +2 -3
  75. package/esm2020/classes/date.utilities.mjs +35 -15
  76. package/esm2020/classes/entity.model.mjs +5 -1
  77. package/esm2020/classes/entity.service.mjs +103 -6
  78. package/esm2020/classes/entity.utilities.mjs +241 -71
  79. package/esm2020/classes/file.utilities.mjs +124 -0
  80. package/esm2020/components/confirm-dialog/confirm-dialog-data.builder.mjs +4 -4
  81. package/esm2020/components/confirm-dialog/confirm-dialog.component.mjs +3 -3
  82. package/esm2020/components/input/add-array-item-dialog-data.builder.mjs +2 -2
  83. package/esm2020/components/input/add-array-item-dialog-data.mjs +1 -1
  84. package/esm2020/components/input/array/array-date-input/array-date-input.component.mjs +26 -0
  85. package/esm2020/components/input/array/array-date-range-input/array-date-range-input.component.mjs +50 -0
  86. package/esm2020/components/input/array/array-date-time-input/array-date-time-input.component.mjs +50 -0
  87. package/esm2020/components/input/array/array-string-autocomplete-chips/array-string-autocomplete-chips.component.mjs +103 -0
  88. package/esm2020/components/input/array/array-string-chips-input/array-string-chips-input.component.mjs +85 -0
  89. package/esm2020/components/input/array/array-table.class.mjs +104 -0
  90. package/esm2020/components/input/base-input.component.mjs +65 -0
  91. package/esm2020/components/input/boolean/boolean-checkbox-input/boolean-checkbox-input.component.mjs +21 -0
  92. package/esm2020/components/input/boolean/boolean-dropdown-input/boolean-dropdown-input.component.mjs +17 -0
  93. package/esm2020/components/input/boolean/boolean-toggle-input/boolean-toggle-input.component.mjs +21 -0
  94. package/esm2020/components/input/custom/custom.component.mjs +26 -0
  95. package/esm2020/components/input/date/date-input/date-input.component.mjs +22 -0
  96. package/esm2020/components/input/date/date-range-input/date-range-input.component.mjs +51 -0
  97. package/esm2020/components/input/date/date-time-input/date-time-input.component.mjs +63 -0
  98. package/esm2020/components/input/file/file-default-input/file-default-input.component.mjs +23 -0
  99. package/esm2020/components/input/file/file-image-input/file-image-input.component.mjs +84 -0
  100. package/esm2020/components/input/file/file-input/dragDrop.directive.mjs +64 -0
  101. package/esm2020/components/input/file/file-input/file-input.component.mjs +154 -0
  102. package/esm2020/components/input/input.component.mjs +137 -236
  103. package/esm2020/components/input/input.module.mjs +82 -6
  104. package/esm2020/components/input/number/number-dropdown-input/number-dropdown-input.component.mjs +18 -0
  105. package/esm2020/components/input/number/number-input/number-input.component.mjs +16 -0
  106. package/esm2020/components/input/number/number-slider-input/number-slider-input.component.mjs +17 -0
  107. package/esm2020/components/input/string/string-autocomplete-input/string-autocomplete-input.component.mjs +35 -0
  108. package/esm2020/components/input/string/string-dropdown-input/string-dropdown-input.component.mjs +18 -0
  109. package/esm2020/components/input/string/string-input/string-input.component.mjs +16 -0
  110. package/esm2020/components/input/string/string-password-input/string-password-input.component.mjs +36 -0
  111. package/esm2020/components/input/string/string-textbox-input/string-textbox-input.component.mjs +17 -0
  112. package/esm2020/components/table/create-dialog/create-dialog-data.builder.mjs +2 -2
  113. package/esm2020/components/table/create-dialog/create-entity-dialog-data.builder.mjs +1 -1
  114. package/esm2020/components/table/create-dialog/create-entity-dialog-data.mjs +1 -1
  115. package/esm2020/components/table/create-dialog/create-entity-dialog.component.mjs +15 -8
  116. package/esm2020/components/table/edit-dialog/edit-dialog-data.builder.mjs +2 -2
  117. package/esm2020/components/table/edit-dialog/edit-entity-dialog-data.mjs +1 -1
  118. package/esm2020/components/table/edit-dialog/edit-entity-dialog.builder.mjs +4 -3
  119. package/esm2020/components/table/edit-dialog/edit-entity-dialog.component.mjs +19 -10
  120. package/esm2020/components/table/table-data.builder.mjs +13 -10
  121. package/esm2020/components/table/table-data.mjs +1 -1
  122. package/esm2020/components/table/table.component.mjs +35 -35
  123. package/esm2020/decorators/array/array-decorator-internal.data.mjs +102 -14
  124. package/esm2020/decorators/array/array-decorator.data.mjs +2 -2
  125. package/esm2020/decorators/array/array.decorator.mjs +8 -2
  126. package/esm2020/decorators/base/base-property.decorator.mjs +4 -3
  127. package/esm2020/decorators/base/decorator-types.enum.mjs +9 -1
  128. package/esm2020/decorators/base/property-decorator-internal.data.mjs +10 -10
  129. package/esm2020/decorators/base/property-decorator.data.mjs +1 -1
  130. package/esm2020/decorators/boolean/boolean-decorator-internal.data.mjs +3 -3
  131. package/esm2020/decorators/custom/custom-decorator-internal.data.mjs +26 -0
  132. package/esm2020/decorators/custom/custom-decorator.data.mjs +2 -0
  133. package/esm2020/decorators/custom/custom.decorator.mjs +13 -0
  134. package/esm2020/decorators/date/date-decorator-internal.data.mjs +5 -5
  135. package/esm2020/decorators/date/date.decorator.mjs +21 -0
  136. package/esm2020/decorators/file/file-decorator-internal.data.mjs +98 -0
  137. package/esm2020/decorators/file/file-decorator.data.mjs +7 -0
  138. package/esm2020/decorators/file/file.decorator.mjs +22 -0
  139. package/esm2020/decorators/number/number-decorator-internal.data.mjs +24 -1
  140. package/esm2020/decorators/number/number-decorator.data.mjs +1 -1
  141. package/esm2020/decorators/number/number.decorator.mjs +9 -7
  142. package/esm2020/decorators/object/object-decorator-internal.data.mjs +1 -1
  143. package/esm2020/decorators/object/object-decorator.data.mjs +1 -1
  144. package/esm2020/decorators/object/object.decorator.mjs +1 -1
  145. package/esm2020/decorators/string/string-decorator-internal.data.mjs +16 -1
  146. package/esm2020/decorators/string/string-decorator.data.mjs +1 -1
  147. package/esm2020/decorators/string/string.decorator.mjs +13 -13
  148. package/esm2020/mocks/placeholder-data.png.mjs +3 -0
  149. package/esm2020/public-api.mjs +9 -1
  150. package/fesm2015/ngx-material-entity.mjs +2488 -524
  151. package/fesm2015/ngx-material-entity.mjs.map +1 -1
  152. package/fesm2020/ngx-material-entity.mjs +2363 -493
  153. package/fesm2020/ngx-material-entity.mjs.map +1 -1
  154. package/mocks/placeholder-data.png.d.ts +1 -0
  155. package/package.json +1 -1
  156. package/public-api.d.ts +8 -0
@@ -1,45 +1,116 @@
1
1
  import 'reflect-metadata';
2
- import { __decorate, __metadata, __awaiter } from 'tslib';
2
+ import { __awaiter, __decorate, __metadata } from 'tslib';
3
+ import { isEqual, cloneDeep, omit, isNil, omitBy, isArray } from 'lodash';
3
4
  import { BehaviorSubject, firstValueFrom, Subject, takeUntil } from 'rxjs';
4
- import { cloneDeep, isEqual, omit, omitBy, isNil } 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
- import * as i6 from '@angular/material/checkbox';
9
+ import * as i2 from '@angular/material/checkbox';
10
10
  import { MatCheckboxModule } from '@angular/material/checkbox';
11
11
  import * as i3 from '@angular/material/button';
12
12
  import { MatButtonModule } from '@angular/material/button';
13
- import * as i12 from '@angular/common';
13
+ import * as i6 from '@angular/common';
14
14
  import { CommonModule } from '@angular/common';
15
- import * as i14 from '@angular/forms';
15
+ import * as i4 from '@angular/forms';
16
16
  import { FormsModule } from '@angular/forms';
17
- import * as i9 from '@angular/material/table';
17
+ import * as i4$2 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$1 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$1 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$2 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$3 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 i2$4 from '@angular/material/slider';
33
+ import { MatSliderModule } from '@angular/material/slider';
34
+ import * as i2$5 from '@angular/material/datepicker';
32
35
  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';
36
+ import * as i2$6 from '@angular/material/chips';
37
+ import { MatChipsModule } from '@angular/material/chips';
36
38
  import { MatIconModule } from '@angular/material/icon';
37
- import * as i7$1 from '@angular/material/paginator';
39
+ import * as i7 from '@angular/material/paginator';
38
40
  import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
39
41
  import { MatSort } from '@angular/material/sort';
40
- import * as i4$1 from '@angular/material/menu';
42
+ import * as i4$3 from '@angular/material/menu';
41
43
  import { MatMenuModule } from '@angular/material/menu';
42
44
 
45
+ /**
46
+ * Encapsulates all functionality of Reflect.
47
+ */
48
+ class ReflectUtilities {
49
+ /**
50
+ * Gets the metadata value for the provided metadata key on the target object or its prototype chain.
51
+ *
52
+ * @param metadataKey - A key used to store and retrieve metadata.
53
+ * @param target - The target object on which the metadata is defined.
54
+ * @param propertyKey - The property key for the target.
55
+ * @returns The metadata value for the metadata key if found; otherwise, undefined.
56
+ */
57
+ static getMetadata(metadataKey, target, propertyKey) {
58
+ return Reflect.getMetadata(metadataKey, target, propertyKey);
59
+ }
60
+ /**
61
+ * Returns the string and symbol keys of the own properties of an object. The own properties of an object
62
+ * are those that are defined directly on that object, and are not inherited from the object's prototype.
63
+ *
64
+ * @param target - Object that contains the own properties.
65
+ * @returns The keys of the given object.
66
+ */
67
+ static ownKeys(target) {
68
+ return Reflect.ownKeys(target);
69
+ }
70
+ /**
71
+ * Gets the property of target, equivalent to `target[propertyKey]`.
72
+ *
73
+ * @param target - Object that contains the property on itself or in its prototype chain.
74
+ * @param propertyKey - The property name.
75
+ * @returns The property of the target of the given key.
76
+ */
77
+ static get(target, propertyKey) {
78
+ return Reflect.get(target, propertyKey);
79
+ }
80
+ /**
81
+ * Sets the property of target, equivalent to `target[propertyKey] = value`.
82
+ *
83
+ * @param target - Object that contains the property on itself or in its prototype chain.
84
+ * @param propertyKey - The property name.
85
+ * @param value - The value to set the property to.
86
+ * @returns If setting the value was successful.
87
+ */
88
+ static set(target, propertyKey, value) {
89
+ return Reflect.set(target, propertyKey, value);
90
+ }
91
+ /**
92
+ * Equivalent to `propertyKey in target`.
93
+ *
94
+ * @param target - Object that contains the property on itself or in its prototype chain.
95
+ * @param propertyKey - Name of the property.
96
+ * @returns Whether or not the given target has the key.
97
+ */
98
+ static has(target, propertyKey) {
99
+ return Reflect.has(target, propertyKey);
100
+ }
101
+ /**
102
+ * Define a unique metadata entry on the target.
103
+ *
104
+ * @param metadataKey - A key used to store and retrieve metadata.
105
+ * @param metadataValue - A value that contains attached metadata.
106
+ * @param target - The target object on which to define metadata.
107
+ * @param propertyKey - The property key for the target.
108
+ */
109
+ static defineMetadata(metadataKey, metadataValue, target, propertyKey) {
110
+ Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey);
111
+ }
112
+ }
113
+
43
114
  /**
44
115
  * The base decorator for setting metadata on properties.
45
116
  *
@@ -49,8 +120,8 @@ import { MatMenuModule } from '@angular/material/menu';
49
120
  */
50
121
  function baseProperty(metadata, type) {
51
122
  return function (target, propertyKey) {
52
- Reflect.defineMetadata('metadata', metadata, target, propertyKey);
53
- Reflect.defineMetadata('type', type, target, propertyKey);
123
+ ReflectUtilities.defineMetadata('metadata', metadata, target, propertyKey);
124
+ ReflectUtilities.defineMetadata('type', type, target, propertyKey);
54
125
  };
55
126
  }
56
127
 
@@ -63,18 +134,26 @@ var DecoratorTypes;
63
134
  DecoratorTypes["STRING_DROPDOWN"] = "stringDropdown";
64
135
  DecoratorTypes["STRING_AUTOCOMPLETE"] = "stringAutocomplete";
65
136
  DecoratorTypes["STRING_TEXTBOX"] = "stringTextbox";
137
+ DecoratorTypes["STRING_PASSWORD"] = "stringPassword";
66
138
  DecoratorTypes["NUMBER"] = "number";
67
139
  DecoratorTypes["NUMBER_DROPDOWN"] = "numberDropdown";
140
+ DecoratorTypes["NUMBER_SLIDER"] = "numberSlider";
68
141
  DecoratorTypes["BOOLEAN_CHECKBOX"] = "boolean";
69
142
  DecoratorTypes["BOOLEAN_TOGGLE"] = "booleanToggle";
70
143
  DecoratorTypes["BOOLEAN_DROPDOWN"] = "booleanDropdown";
71
144
  DecoratorTypes["OBJECT"] = "object";
72
145
  DecoratorTypes["ARRAY"] = "array";
146
+ DecoratorTypes["ARRAY_DATE"] = "arrayDate";
147
+ DecoratorTypes["ARRAY_DATE_TIME"] = "arrayDateTime";
148
+ DecoratorTypes["ARRAY_DATE_RANGE"] = "arrayDateRange";
73
149
  DecoratorTypes["ARRAY_STRING_CHIPS"] = "arrayStringChips";
74
150
  DecoratorTypes["ARRAY_STRING_AUTOCOMPLETE_CHIPS"] = "arrayStringAutocompleteChips";
75
151
  DecoratorTypes["DATE"] = "date";
76
152
  DecoratorTypes["DATE_RANGE"] = "dateRange";
77
153
  DecoratorTypes["DATE_TIME"] = "dateTime";
154
+ DecoratorTypes["FILE_DEFAULT"] = "fileDefault";
155
+ DecoratorTypes["FILE_IMAGE"] = "fileImage";
156
+ DecoratorTypes["CUSTOM"] = "custom";
78
157
  })(DecoratorTypes || (DecoratorTypes = {}));
79
158
 
80
159
  /**
@@ -82,12 +161,13 @@ var DecoratorTypes;
82
161
  */
83
162
  class PositionInternal {
84
163
  constructor(data) {
164
+ var _a, _b;
85
165
  this.validateInput(data);
86
- this.row = (data === null || data === void 0 ? void 0 : data.row) ? data.row : -1;
87
- this.order = (data === null || data === void 0 ? void 0 : data.order) ? data.order : -1;
166
+ this.row = (_a = data === null || data === void 0 ? void 0 : data.row) !== null && _a !== void 0 ? _a : -1;
167
+ this.order = (_b = data === null || data === void 0 ? void 0 : data.order) !== null && _b !== void 0 ? _b : -1;
88
168
  }
89
169
  validateInput(data) {
90
- if (data === null || data === void 0 ? void 0 : data.order) {
170
+ if ((data === null || data === void 0 ? void 0 : data.order) != null) {
91
171
  if (data.order < 1) {
92
172
  throw new Error('order must be at least 1');
93
173
  }
@@ -95,7 +175,7 @@ class PositionInternal {
95
175
  throw new Error('order cannot be bigger than 12 (the minimum value for a bootstrap column)');
96
176
  }
97
177
  }
98
- if ((data === null || data === void 0 ? void 0 : data.row) && (data.row < 1)) {
178
+ if ((data === null || data === void 0 ? void 0 : data.row) != null && data.row < 1) {
99
179
  throw new Error('row must be at least 1');
100
180
  }
101
181
  }
@@ -105,12 +185,13 @@ class PositionInternal {
105
185
  */
106
186
  class PropertyDecoratorConfigInternal {
107
187
  constructor(data) {
108
- this.display = data.display != undefined ? data.display : true;
188
+ var _a, _b, _c, _d, _e;
189
+ this.display = (_a = data.display) !== null && _a !== void 0 ? _a : true;
109
190
  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];
191
+ this.required = (_b = data.required) !== null && _b !== void 0 ? _b : true;
192
+ this.omitForCreate = (_c = data.omitForCreate) !== null && _c !== void 0 ? _c : false;
193
+ this.omitForUpdate = (_d = data.omitForUpdate) !== null && _d !== void 0 ? _d : false;
194
+ this.defaultWidths = (_e = data.defaultWidths) !== null && _e !== void 0 ? _e : [6, 6, 12];
114
195
  this.position = new PositionInternal(data.position);
115
196
  }
116
197
  }
@@ -161,6 +242,22 @@ class AutocompleteStringDecoratorConfigInternal extends PropertyDecoratorConfigI
161
242
  this.regex = data.regex;
162
243
  }
163
244
  }
245
+ /**
246
+ * The internal PasswordStringDecoratorConfig. Sets default values.
247
+ */
248
+ class PasswordStringDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
249
+ constructor(data) {
250
+ var _a, _b, _c;
251
+ super(data);
252
+ this.displayStyle = data.displayStyle;
253
+ this.minLength = data.minLength;
254
+ this.maxLength = data.maxLength;
255
+ this.regex = data.regex;
256
+ this.needsConfirmation = (_a = data.needsConfirmation) !== null && _a !== void 0 ? _a : true;
257
+ this.confirmationDisplayName = (_b = data.confirmationDisplayName) !== null && _b !== void 0 ? _b : 'Confirm Password';
258
+ this.passwordsDontMatchErrorMessage = (_c = data.passwordsDontMatchErrorMessage) !== null && _c !== void 0 ? _c : 'Passwords need to match!';
259
+ }
260
+ }
164
261
 
165
262
  /**
166
263
  * Decorator for setting and getting string Property metadata.
@@ -169,36 +266,93 @@ class AutocompleteStringDecoratorConfigInternal extends PropertyDecoratorConfigI
169
266
  * @returns The method that defines the metadata.
170
267
  */
171
268
  function string(metadata) {
172
- if (metadata.displayStyle === 'dropdown') {
173
- return baseProperty(new DropdownStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_DROPDOWN);
174
- }
175
- else if (metadata.displayStyle === 'autocomplete') {
176
- return baseProperty(new AutocompleteStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_AUTOCOMPLETE);
177
- }
178
- else if (metadata.displayStyle === 'textbox') {
179
- return baseProperty(new TextboxStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_TEXTBOX);
180
- }
181
- else {
182
- return baseProperty(new DefaultStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING);
269
+ switch (metadata.displayStyle) {
270
+ case 'dropdown':
271
+ return baseProperty(new DropdownStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_DROPDOWN);
272
+ case 'autocomplete':
273
+ return baseProperty(new AutocompleteStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_AUTOCOMPLETE);
274
+ case 'textbox':
275
+ return baseProperty(new TextboxStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_TEXTBOX);
276
+ case 'password':
277
+ return baseProperty(new PasswordStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_PASSWORD);
278
+ default:
279
+ return baseProperty(new DefaultStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING);
183
280
  }
184
281
  }
185
282
 
186
283
  /**
187
- * A base Entity class with a builtin id.
284
+ * Encapsulates all functionality of lodash.
188
285
  */
189
- class Entity {
286
+ class LodashUtilities {
287
+ /**
288
+ * Performs a deep comparison between two values to determine if they are
289
+ * equivalent.
290
+ *
291
+ * **Note:** This method supports comparing arrays, array buffers, booleans,
292
+ * date objects, error objects, maps, numbers, `Object` objects, regexps,
293
+ * sets, strings, symbols, and typed arrays. `Object` objects are compared
294
+ * by their own, not inherited, enumerable properties. Functions and DOM
295
+ * nodes are **not** supported.
296
+ *
297
+ * @param value - The value to compare.
298
+ * @param other - The other value to compare.
299
+ * @returns Returns `true` if the values are equivalent, else `false`.
300
+ */
301
+ static isEqual(value, other) {
302
+ return isEqual(value, other);
303
+ }
304
+ /**
305
+ * This method is like _.clone except that it recursively clones value.
306
+ *
307
+ * @param value - The value to recursively clone.
308
+ * @returns Returns the deep cloned value.
309
+ */
310
+ static cloneDeep(value) {
311
+ return cloneDeep(value);
312
+ }
313
+ /**
314
+ * The opposite of `_.pick`; this method creates an object composed of the
315
+ * own and inherited enumerable properties of `object` that are not omitted.
316
+ *
317
+ * @param object - The source object.
318
+ * @param paths - The property names to omit, specified
319
+ * individually or in arrays.
320
+ * @returns Returns the new object.
321
+ */
322
+ static omit(object, ...paths) {
323
+ return omit(object, ...paths);
324
+ }
325
+ /**
326
+ * Checks if `value` is `null` or `undefined`.
327
+ *
328
+ * @param value - The value to check.
329
+ * @returns Returns `true` if `value` is nullish, else `false`.
330
+ */
331
+ static isNil(value) {
332
+ return isNil(value);
333
+ }
334
+ /**
335
+ * The opposite of `_.pickBy`; this method creates an object composed of the
336
+ * own and inherited enumerable properties of `object` that `predicate`
337
+ * doesn't return truthy for.
338
+ *
339
+ * @param object - The source object.
340
+ * @param predicate - The function invoked per property.
341
+ * @returns Returns the new object.
342
+ */
343
+ static omitBy(object, predicate) {
344
+ return omitBy(object, predicate);
345
+ }
346
+ /**
347
+ * Checks if value is classified as an Array object.
348
+ *
349
+ * @param value - The value to check.
350
+ * @returns Returns true if value is correctly classified, else false.
351
+ */
352
+ static isArray(value) {
353
+ return isArray(value);
354
+ }
190
355
  }
191
- __decorate([
192
- string({
193
- omitForCreate: true,
194
- omitForUpdate: true,
195
- display: false,
196
- displayStyle: 'line',
197
- displayName: 'ID',
198
- required: true
199
- }),
200
- __metadata("design:type", String)
201
- ], Entity.prototype, "id", void 0);
202
356
 
203
357
  const DAY_IN_MS = 1000 * 60 * 60 * 24;
204
358
  /**
@@ -225,14 +379,14 @@ class DateUtilities {
225
379
  const res = [{ displayName: '-', value: undefined }];
226
380
  for (let hour = 0; hour < 24; hour++) {
227
381
  for (let minute = 0; minute < 60; minute += minuteSteps) {
228
- res.push(this.getTimeDropdownValue(format, hour, minute));
382
+ res.push(DateUtilities.getTimeDropdownValue(format, hour, minute));
229
383
  }
230
384
  }
231
385
  return res;
232
386
  }
233
387
  static getTimeDropdownValue(format, hour, minute) {
234
- const displayHour = this.getFormattedHour(format, cloneDeep(hour));
235
- const displayMinute = this.getFormattedMinute(format, hour, minute);
388
+ const displayHour = DateUtilities.getFormattedHour(format, LodashUtilities.cloneDeep(hour));
389
+ const displayMinute = DateUtilities.getFormattedMinute(format, hour, minute);
236
390
  return {
237
391
  displayName: `${displayHour}:${displayMinute}`,
238
392
  value: {
@@ -270,10 +424,7 @@ class DateUtilities {
270
424
  */
271
425
  static getTimeFromDate(value) {
272
426
  if (!value) {
273
- return {
274
- hours: undefined,
275
- minutes: undefined
276
- };
427
+ return undefined;
277
428
  }
278
429
  else {
279
430
  return {
@@ -287,10 +438,10 @@ class DateUtilities {
287
438
  *
288
439
  * @param startDate - The start date.
289
440
  * @param endDate - The end date.
290
- * @param metadataDateRangeDate - The metadata.
441
+ * @param filter - The custom filter from the metadata.
291
442
  * @returns All dates between the two provided dates. Includes start and end date.
292
443
  */
293
- static getDatesBetween(startDate, endDate, metadataDateRangeDate) {
444
+ static getDatesBetween(startDate, endDate, filter) {
294
445
  const res = [];
295
446
  while (startDate.getFullYear() < endDate.getFullYear()
296
447
  || startDate.getMonth() < endDate.getMonth()
@@ -298,8 +449,8 @@ class DateUtilities {
298
449
  res.push(new Date(startDate));
299
450
  startDate.setTime(startDate.getTime() + DAY_IN_MS);
300
451
  }
301
- if (metadataDateRangeDate.filter) {
302
- return res.filter(d => { var _a; return (_a = metadataDateRangeDate.filter) === null || _a === void 0 ? void 0 : _a.call(metadataDateRangeDate, d); });
452
+ if (filter) {
453
+ return res.filter(d => filter(d));
303
454
  }
304
455
  else {
305
456
  return res;
@@ -308,14 +459,14 @@ class DateUtilities {
308
459
  /**
309
460
  * Get all valid times for the dropdown of a datetime property.
310
461
  *
311
- * @param date - The date of the datetime.
312
462
  * @param times - All given times to filter.
463
+ * @param date - The date of the datetime.
313
464
  * @param min - The function that defines the minimum time.
314
465
  * @param max - The function that defines the maximum time.
315
466
  * @param filter - A filter function to do more specific time filtering. This could be e.g. The removal of lunch breaks.
316
467
  * @returns All valid dropdown values for the datetime property.
317
468
  */
318
- static getValidTimesForDropdown(date, times, min, max, filter) {
469
+ static getValidTimesForDropdown(times, date, min, max, filter) {
319
470
  if (min) {
320
471
  const minTime = min(date);
321
472
  times = times.filter(t => !t.value
@@ -335,6 +486,158 @@ class DateUtilities {
335
486
  }
336
487
  return times;
337
488
  }
489
+ /**
490
+ * Checks if the time object has processable hours and minutes properties.
491
+ * Doesn't check custom validators like min/max from the metadata configuration.
492
+ *
493
+ * @param time - The time to check.
494
+ * @returns Whether or not the time object is unprocessable.
495
+ */
496
+ static timeIsUnprocessable(time) {
497
+ if (!time
498
+ || time.hours == null
499
+ || typeof time.hours !== 'number'
500
+ || Number.isNaN(time.hours)
501
+ || time.minutes == null
502
+ || typeof time.minutes !== 'number'
503
+ || Number.isNaN(time.minutes)) {
504
+ return true;
505
+ }
506
+ return false;
507
+ }
508
+ }
509
+ /**
510
+ * The default filter function to user when none was provided by the user.
511
+ */
512
+ DateUtilities.defaultDateFilter = () => true;
513
+
514
+ /**
515
+ * Provides functionality regarding files.
516
+ */
517
+ class FileUtilities {
518
+ /**
519
+ * Gets the accept value for the html input.
520
+ *
521
+ * @param mimeTypes - The mimeTypes to get the accept string from.
522
+ * @returns A comma separated string of all the provided mime types.
523
+ */
524
+ static getAcceptString(mimeTypes) {
525
+ if (!(mimeTypes === null || mimeTypes === void 0 ? void 0 : mimeTypes.length)) {
526
+ return '*';
527
+ }
528
+ return mimeTypes.join(', ');
529
+ }
530
+ // TODO: Find a way to use blobs with jest
531
+ /* istanbul ignore next */
532
+ /**
533
+ * Reads a url to display the given file.
534
+ *
535
+ * @param file - The file to get the url from.
536
+ * @returns A promise of the url. Undefined if no file was provided.
537
+ */
538
+ static getDataURLFromFile(file) {
539
+ return __awaiter(this, void 0, void 0, function* () {
540
+ if (!file) {
541
+ return undefined;
542
+ }
543
+ return new Promise((resolve, reject) => {
544
+ const reader = new FileReader();
545
+ reader.onload = e => { var _a; return resolve((_a = e.target) === null || _a === void 0 ? void 0 : _a.result); };
546
+ reader.onerror = e => reject(e);
547
+ reader.readAsDataURL(file);
548
+ });
549
+ });
550
+ }
551
+ // TODO: Find a way to use blobs with jest
552
+ /* istanbul ignore next */
553
+ /**
554
+ * Gets a file from the given url.
555
+ *
556
+ * @param url - The url to get the file from.
557
+ * @returns A promise of the File.
558
+ */
559
+ static getFileFromUrl(url) {
560
+ return __awaiter(this, void 0, void 0, function* () {
561
+ const res = yield fetch(url);
562
+ if (!res.ok) {
563
+ // TODO make error more robust
564
+ throw new Error(`Error fetching the file from the url ${url}`);
565
+ }
566
+ return yield res.blob();
567
+ });
568
+ }
569
+ // TODO: Find a way to use blobs with jest
570
+ /* istanbul ignore next */
571
+ /**
572
+ * Gets the file data with the blob from the given File Data.
573
+ *
574
+ * @param data - The File Data to get the file data with blob from.
575
+ * @returns FileDataWithFile.
576
+ */
577
+ static getFileData(data) {
578
+ return __awaiter(this, void 0, void 0, function* () {
579
+ if (data.file) {
580
+ return {
581
+ file: data.file,
582
+ name: data.name,
583
+ url: data.url,
584
+ type: data.type,
585
+ size: data.size
586
+ };
587
+ }
588
+ else {
589
+ return {
590
+ file: yield FileUtilities.getFileFromUrl(data.url),
591
+ name: data.name,
592
+ url: data.url,
593
+ type: data.type,
594
+ size: data.size
595
+ };
596
+ }
597
+ });
598
+ }
599
+ /**
600
+ * Checks if the given file has a valid mime type.
601
+ *
602
+ * @param type - The type of the file to check.
603
+ * @param allowedMimeTypes - The allowed mime types.
604
+ * @returns Whether or not the given file has a valid mime type.
605
+ */
606
+ static isMimeTypeValid(type, allowedMimeTypes) {
607
+ if (allowedMimeTypes.includes('*')) {
608
+ return true;
609
+ }
610
+ for (const t of allowedMimeTypes) {
611
+ if (t === type) {
612
+ return true;
613
+ }
614
+ if (t.endsWith('*') && type.startsWith(t.split('*')[0])) {
615
+ return true;
616
+ }
617
+ }
618
+ return false;
619
+ }
620
+ /**
621
+ * Transform the given value to Megabytes.
622
+ *
623
+ * @param value - The original value.
624
+ * @param unit - If the value is B, KB or GB.
625
+ * @returns The given value as bytes.
626
+ */
627
+ static transformToMegaBytes(value, unit) {
628
+ const bytes = this.transformToBytes(LodashUtilities.cloneDeep(value), unit);
629
+ return bytes / 1000000;
630
+ }
631
+ static transformToBytes(value, unit) {
632
+ switch (unit) {
633
+ case 'B':
634
+ return value;
635
+ case 'KB':
636
+ return value * 1000;
637
+ case 'GB':
638
+ return value * 1000000000;
639
+ }
640
+ }
338
641
  }
339
642
 
340
643
  /**
@@ -373,6 +676,26 @@ class EntityUtilities {
373
676
  }
374
677
  return res;
375
678
  }
679
+ /**
680
+ * Gets all properties on the given entity which are files.
681
+ *
682
+ * @param entity - The entity to check for file properties.
683
+ * @param omit - Whether to leave out values that are omitted for create or delete.
684
+ * @returns The keys of all file properties on the given entity.
685
+ */
686
+ static getFileProperties(entity, omit) {
687
+ const res = [];
688
+ for (const key of EntityUtilities.keysOf(entity)) {
689
+ const type = EntityUtilities.getPropertyType(entity, key);
690
+ if (type === DecoratorTypes.FILE_DEFAULT || type === DecoratorTypes.FILE_IMAGE) {
691
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
692
+ if (!(metadata.omitForCreate && omit === 'create') && !(metadata.omitForUpdate && omit === 'update')) {
693
+ res.push(key);
694
+ }
695
+ }
696
+ }
697
+ return res;
698
+ }
376
699
  /**
377
700
  * Gets the metadata included in an property.
378
701
  *
@@ -385,16 +708,11 @@ class EntityUtilities {
385
708
  static getPropertyMetadata(entity, propertyKey,
386
709
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
387
710
  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) {
711
+ const metadata = ReflectUtilities.getMetadata('metadata', entity, propertyKey);
712
+ if (metadata == null) {
396
713
  throw new Error(`Could not find metadata for property ${String(propertyKey)} on the entity ${JSON.stringify(entity)}`);
397
714
  }
715
+ return metadata;
398
716
  }
399
717
  /**
400
718
  * Gets the type of the property-metadata.
@@ -406,8 +724,8 @@ class EntityUtilities {
406
724
  */
407
725
  static getPropertyType(entity, propertyKey) {
408
726
  try {
409
- const propertyType = Reflect.getMetadata('type', entity, propertyKey);
410
- if (!propertyType) {
727
+ const propertyType = ReflectUtilities.getMetadata('type', entity, propertyKey);
728
+ if (propertyType == null) {
411
729
  throw new Error(`Could not find type metadata for property ${String(propertyKey)} on the entity ${JSON.stringify(entity)}`);
412
730
  }
413
731
  return propertyType;
@@ -428,12 +746,10 @@ class EntityUtilities {
428
746
  static new(target, entity) {
429
747
  for (const key in target) {
430
748
  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;
749
+ let value = entity ? ReflectUtilities.get(entity, key) : undefined;
433
750
  switch (type) {
434
751
  case DecoratorTypes.OBJECT:
435
752
  const objectMetadata = EntityUtilities.getPropertyMetadata(target, key, DecoratorTypes.OBJECT);
436
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
437
753
  value = new objectMetadata.EntityClass(value);
438
754
  break;
439
755
  case DecoratorTypes.ARRAY:
@@ -451,7 +767,7 @@ class EntityUtilities {
451
767
  default:
452
768
  break;
453
769
  }
454
- Reflect.set(target, key, value);
770
+ ReflectUtilities.set(target, key, value);
455
771
  }
456
772
  }
457
773
  /**
@@ -488,37 +804,52 @@ class EntityUtilities {
488
804
  if (metadata.omitForUpdate && omit === 'update') {
489
805
  return true;
490
806
  }
491
- if (metadata.required && !entity[key]) {
807
+ if (metadata.required && entity[key] == null) {
492
808
  return false;
493
809
  }
494
810
  switch (type) {
495
811
  case DecoratorTypes.BOOLEAN_DROPDOWN:
812
+ break;
496
813
  case DecoratorTypes.BOOLEAN_CHECKBOX:
497
814
  case DecoratorTypes.BOOLEAN_TOGGLE:
498
- return true;
815
+ const entityBoolean = entity[key];
816
+ const booleanMetadata = metadata;
817
+ if (!EntityUtilities.isBooleanValid(entityBoolean, booleanMetadata)) {
818
+ return false;
819
+ }
820
+ break;
499
821
  case DecoratorTypes.STRING_DROPDOWN:
500
- return true;
822
+ break;
501
823
  case DecoratorTypes.STRING:
502
824
  case DecoratorTypes.STRING_AUTOCOMPLETE:
503
825
  const entityString = entity[key];
504
826
  const stringMetadata = metadata;
505
- if (!this.isStringValid(entityString, stringMetadata)) {
827
+ if (!EntityUtilities.isStringValid(entityString, stringMetadata)) {
506
828
  return false;
507
829
  }
508
830
  break;
509
831
  case DecoratorTypes.STRING_TEXTBOX:
510
832
  const entityTextbox = entity[key];
511
833
  const textboxMetadata = metadata;
512
- if (!this.isTextboxValid(entityTextbox, textboxMetadata)) {
834
+ if (!EntityUtilities.isTextboxValid(entityTextbox, textboxMetadata)) {
835
+ return false;
836
+ }
837
+ break;
838
+ case DecoratorTypes.STRING_PASSWORD:
839
+ const entityPassword = entity[key];
840
+ const passwordMetadata = metadata;
841
+ const confirmPassword = ReflectUtilities.getMetadata('confirmPassword', entity, key);
842
+ if (!EntityUtilities.isPasswordValid(entityPassword, passwordMetadata, confirmPassword)) {
513
843
  return false;
514
844
  }
515
845
  break;
516
846
  case DecoratorTypes.NUMBER_DROPDOWN:
517
847
  return true;
518
848
  case DecoratorTypes.NUMBER:
849
+ case DecoratorTypes.NUMBER_SLIDER:
519
850
  const entityNumber = entity[key];
520
851
  const numberMetadata = metadata;
521
- if (!this.isNumberValid(entityNumber, numberMetadata)) {
852
+ if (!EntityUtilities.isNumberValid(entityNumber, numberMetadata)) {
522
853
  return false;
523
854
  }
524
855
  break;
@@ -532,6 +863,9 @@ class EntityUtilities {
532
863
  break;
533
864
  case DecoratorTypes.ARRAY_STRING_CHIPS:
534
865
  case DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS:
866
+ case DecoratorTypes.ARRAY_DATE:
867
+ case DecoratorTypes.ARRAY_DATE_TIME:
868
+ case DecoratorTypes.ARRAY_DATE_RANGE:
535
869
  case DecoratorTypes.ARRAY:
536
870
  const entityArray = entity[key];
537
871
  const arrayMetadata = metadata;
@@ -542,21 +876,36 @@ class EntityUtilities {
542
876
  case DecoratorTypes.DATE:
543
877
  const entityDate = new Date(entity[key]);
544
878
  const dateMetadata = metadata;
545
- if (!this.isDateValid(entityDate, dateMetadata)) {
879
+ if (!EntityUtilities.isDateValid(entityDate, dateMetadata)) {
546
880
  return false;
547
881
  }
548
882
  break;
549
883
  case DecoratorTypes.DATE_RANGE:
550
- const entityDateRange = cloneDeep(entity[key]);
884
+ const entityDateRange = LodashUtilities.cloneDeep(entity[key]);
551
885
  const dateRangeMetadata = metadata;
552
- if (!this.isDateRangeValid(entityDateRange, dateRangeMetadata)) {
886
+ if (!EntityUtilities.isDateRangeValid(entityDateRange, dateRangeMetadata)) {
553
887
  return false;
554
888
  }
555
889
  break;
556
890
  case DecoratorTypes.DATE_TIME:
557
891
  const entityDateTime = new Date(entity[key]);
558
892
  const dateTimeMetadata = metadata;
559
- if (!this.isDateTimeValid(entityDateTime, dateTimeMetadata)) {
893
+ if (!EntityUtilities.isDateTimeValid(entityDateTime, dateTimeMetadata)) {
894
+ return false;
895
+ }
896
+ break;
897
+ case DecoratorTypes.FILE_DEFAULT:
898
+ case DecoratorTypes.FILE_IMAGE:
899
+ const entityFile = entity[key];
900
+ const entityFileMetadata = metadata;
901
+ if (!EntityUtilities.isFileDataValid(entityFile, entityFileMetadata)) {
902
+ return false;
903
+ }
904
+ break;
905
+ case DecoratorTypes.CUSTOM:
906
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
907
+ const customMetadata = metadata;
908
+ if (!customMetadata.isValid(entity[key], omit)) {
560
909
  return false;
561
910
  }
562
911
  break;
@@ -565,6 +914,12 @@ class EntityUtilities {
565
914
  }
566
915
  return true;
567
916
  }
917
+ static isBooleanValid(value, metadata) {
918
+ if (metadata.required && !value) {
919
+ return false;
920
+ }
921
+ return true;
922
+ }
568
923
  static isStringValid(value, metadata) {
569
924
  if (metadata.maxLength && value.length > metadata.maxLength) {
570
925
  return false;
@@ -586,6 +941,21 @@ class EntityUtilities {
586
941
  }
587
942
  return true;
588
943
  }
944
+ static isPasswordValid(value, metadata, confirmPassword) {
945
+ if (value !== confirmPassword) {
946
+ return false;
947
+ }
948
+ if (metadata.maxLength && value.length > metadata.maxLength) {
949
+ return false;
950
+ }
951
+ if (metadata.minLength && value.length < metadata.minLength) {
952
+ return false;
953
+ }
954
+ if (metadata.regex && !value.match(metadata.regex)) {
955
+ return false;
956
+ }
957
+ return true;
958
+ }
589
959
  static isNumberValid(value, metadata) {
590
960
  if (metadata.max && value > metadata.max) {
591
961
  return false;
@@ -608,8 +978,13 @@ class EntityUtilities {
608
978
  return true;
609
979
  }
610
980
  static isDateRangeValid(value, metadata) {
611
- if (metadata.required && (!value.start || !value.end)) {
612
- return false;
981
+ if (metadata.required) {
982
+ if (!value.start) {
983
+ return false;
984
+ }
985
+ if (!value.end) {
986
+ return false;
987
+ }
613
988
  }
614
989
  value.start = new Date(value.start);
615
990
  value.end = new Date(value.end);
@@ -679,6 +1054,27 @@ class EntityUtilities {
679
1054
  }
680
1055
  return true;
681
1056
  }
1057
+ static isFileDataValid(value, metadata) {
1058
+ const files = metadata.multiple ? value : [value];
1059
+ let fileSizeTotal = 0;
1060
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
1061
+ for (let i = 0; i < files.length; i++) {
1062
+ if (!files[i].name || !files[i].file && !files[i].url) {
1063
+ return false;
1064
+ }
1065
+ if (!FileUtilities.isMimeTypeValid(files[i].type, metadata.allowedMimeTypes)) {
1066
+ return false;
1067
+ }
1068
+ if (FileUtilities.transformToMegaBytes(files[i].size, 'B') > metadata.maxSize) {
1069
+ return false;
1070
+ }
1071
+ fileSizeTotal += files[i].size;
1072
+ if (FileUtilities.transformToMegaBytes(fileSizeTotal, 'B') > metadata.maxSizeTotal) {
1073
+ return false;
1074
+ }
1075
+ }
1076
+ return true;
1077
+ }
682
1078
  /**
683
1079
  * Checks if an entity is "dirty" (if its values have changed).
684
1080
  *
@@ -686,27 +1082,33 @@ class EntityUtilities {
686
1082
  * @param entityPriorChanges - The entity before the changes.
687
1083
  * @returns Whether or not the entity is dirty.
688
1084
  */
689
- static dirty(entity, entityPriorChanges) {
690
- if (!entityPriorChanges) {
691
- return false;
692
- }
693
- else {
694
- const differences = this.differencesForDirty(entity, entityPriorChanges);
695
- return differences.length ? true : false;
696
- }
1085
+ static isDirty(entity, entityPriorChanges) {
1086
+ return __awaiter(this, void 0, void 0, function* () {
1087
+ if (!entityPriorChanges) {
1088
+ return false;
1089
+ }
1090
+ else {
1091
+ const differences = yield EntityUtilities.differencesForDirty(entity, entityPriorChanges);
1092
+ return differences.length ? true : false;
1093
+ }
1094
+ });
697
1095
  }
698
1096
  static differencesForDirty(entity, entityPriorChanges) {
699
- const res = [];
700
- for (const key in entity) {
701
- if (!this.isEqual(entity[key], entityPriorChanges[key], EntityUtilities.getPropertyMetadata(entity, key))) {
702
- res.push({
703
- key: key,
704
- before: entityPriorChanges[key],
705
- after: entity[key]
706
- });
1097
+ return __awaiter(this, void 0, void 0, function* () {
1098
+ const res = [];
1099
+ for (const key in entity) {
1100
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
1101
+ const type = EntityUtilities.getPropertyType(entity, key);
1102
+ if (!(yield EntityUtilities.isEqual(entity[key], entityPriorChanges[key], metadata, type))) {
1103
+ res.push({
1104
+ key: key,
1105
+ before: entityPriorChanges[key],
1106
+ after: entity[key]
1107
+ });
1108
+ }
707
1109
  }
708
- }
709
- return res;
1110
+ return res;
1111
+ });
710
1112
  }
711
1113
  /**
712
1114
  * Compares two Entities and returns their difference in an object.
@@ -716,60 +1118,140 @@ class EntityUtilities {
716
1118
  * @returns The difference between the two Entities in form of a Partial.
717
1119
  */
718
1120
  static difference(entity, entityPriorChanges) {
719
- const res = {};
720
- for (const key in entity) {
721
- if (!this.isEqual(entity[key], entityPriorChanges[key], EntityUtilities.getPropertyMetadata(entity, key))) {
722
- res[key] = entity[key];
723
- }
724
- }
725
- return res;
726
- }
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;
1121
+ return __awaiter(this, void 0, void 0, function* () {
1122
+ const res = {};
1123
+ for (const key in entity) {
1124
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
1125
+ const type = EntityUtilities.getPropertyType(entity, key);
1126
+ if (!(yield EntityUtilities.isEqual(entity[key], entityPriorChanges[key], metadata, type))) {
1127
+ res[key] = entity[key];
1128
+ }
755
1129
  }
756
- catch (error) { }
757
- ;
758
- }
759
- return false;
1130
+ return res;
1131
+ });
760
1132
  }
761
1133
  /**
762
- * Compare function for sorting entity keys by their order value.
1134
+ * Checks if two given values are equal.
1135
+ * It uses the isEqual method from LodashUtilities and extends it with functionality regarding Dates.
763
1136
  *
764
- * @param a - First key of entity.
765
- * @param b - Second key of entity.
766
- * @param entity - Current entity (used to get metadata of entity keys).
767
- * @returns 0 if both values have the same order, a negative value if 'a' comes before 'b', a positive value if 'a' comes behind 'b'.
1137
+ * @param value - The updated value.
1138
+ * @param valuePriorChanges - The value before any changes.
1139
+ * @param metadata - The metadata of the property.
1140
+ * @param type - The type of the property.
1141
+ * @returns Whether or not the given values are equal.
768
1142
  */
769
- static compareOrder(a, b, entity) {
770
- const metadataA = EntityUtilities.getPropertyMetadata(entity, a);
771
- const metadataB = EntityUtilities.getPropertyMetadata(entity, b);
772
- if (metadataA.position.order === -1) {
1143
+ static isEqual(value, valuePriorChanges, metadata, type) {
1144
+ return __awaiter(this, void 0, void 0, function* () {
1145
+ switch (type) {
1146
+ case DecoratorTypes.DATE_RANGE:
1147
+ return EntityUtilities.isEqualDateRange(value, valuePriorChanges, metadata.filter);
1148
+ case DecoratorTypes.DATE:
1149
+ return EntityUtilities.isEqualDate(value, valuePriorChanges);
1150
+ case DecoratorTypes.DATE_TIME:
1151
+ return EntityUtilities.isEqualDateTime(value, valuePriorChanges);
1152
+ case DecoratorTypes.ARRAY_DATE:
1153
+ case DecoratorTypes.ARRAY_DATE_TIME:
1154
+ return EntityUtilities.isEqualArrayDate(value, valuePriorChanges);
1155
+ case DecoratorTypes.ARRAY_DATE_RANGE:
1156
+ return EntityUtilities.isEqualArrayDateRange(value, valuePriorChanges, metadata.filter);
1157
+ case DecoratorTypes.FILE_IMAGE:
1158
+ case DecoratorTypes.FILE_DEFAULT:
1159
+ return EntityUtilities.isEqualFile(value, valuePriorChanges, metadata.multiple);
1160
+ case DecoratorTypes.CUSTOM:
1161
+ // eslint-disable-next-line max-len, @typescript-eslint/no-explicit-any
1162
+ return EntityUtilities.isEqualCustom(value, valuePriorChanges, metadata);
1163
+ default:
1164
+ return LodashUtilities.isEqual(value, valuePriorChanges);
1165
+ }
1166
+ });
1167
+ }
1168
+ static isEqualArrayDate(value, valuePriorChanges) {
1169
+ const newValue = value.map(v => new Date(v)).sort();
1170
+ const newValuePriorChanges = valuePriorChanges.map(v => new Date(v)).sort();
1171
+ return LodashUtilities.isEqual(newValue, newValuePriorChanges);
1172
+ }
1173
+ static isEqualArrayDateRange(value, valuePriorChanges, filter) {
1174
+ const dateRanges = value.sort();
1175
+ const dateRangesPriorChanges = valuePriorChanges.sort();
1176
+ if (dateRanges.length !== dateRangesPriorChanges.length) {
1177
+ return false;
1178
+ }
1179
+ for (let i = 0; i < dateRanges.length; i++) {
1180
+ if (!EntityUtilities.isEqualDateRange(dateRanges[i], dateRangesPriorChanges[i], filter)) {
1181
+ return false;
1182
+ }
1183
+ }
1184
+ return true;
1185
+ }
1186
+ static isEqualDateTime(value, valuePriorChanges) {
1187
+ const date = new Date(value);
1188
+ const datePriorChanges = new Date(valuePriorChanges);
1189
+ return LodashUtilities.isEqual(date, datePriorChanges);
1190
+ }
1191
+ static isEqualDate(value, valuePriorChanges) {
1192
+ const date = new Date(value);
1193
+ const datePriorChanges = new Date(valuePriorChanges);
1194
+ date.setHours(0, 0, 0, 0);
1195
+ datePriorChanges.setHours(0, 0, 0, 0);
1196
+ return LodashUtilities.isEqual(date, datePriorChanges);
1197
+ }
1198
+ static isEqualDateRange(value, valuePriorChanges, filter) {
1199
+ const dateRange = LodashUtilities.cloneDeep(value);
1200
+ dateRange.start = new Date(value.start);
1201
+ dateRange.end = new Date(value.end);
1202
+ dateRange.values = DateUtilities.getDatesBetween(dateRange.start, dateRange.end, filter);
1203
+ const dateRangePriorChanges = LodashUtilities.cloneDeep(valuePriorChanges);
1204
+ dateRangePriorChanges.start = new Date(valuePriorChanges.start);
1205
+ dateRangePriorChanges.end = new Date(valuePriorChanges.end);
1206
+ dateRangePriorChanges.values = DateUtilities.getDatesBetween(dateRangePriorChanges.start, dateRangePriorChanges.end, filter);
1207
+ return LodashUtilities.isEqual(dateRange, dateRangePriorChanges);
1208
+ }
1209
+ // TODO: Find a way to use blobs with jest
1210
+ /* istanbul ignore next */
1211
+ static isEqualFile(value, valuePriorChanges, multiple) {
1212
+ var _a, _b, _c, _d, _e, _f;
1213
+ return __awaiter(this, void 0, void 0, function* () {
1214
+ const files = multiple ? value.sort() : [value].sort();
1215
+ const filesPriorChanges = multiple ? valuePriorChanges.sort() : [valuePriorChanges].sort();
1216
+ if (files.length !== filesPriorChanges.length) {
1217
+ return false;
1218
+ }
1219
+ for (let i = 0; i < files.length; i++) {
1220
+ // checks this before actually getting any files due to performance reasons.
1221
+ if (!LodashUtilities.isEqual((_a = files[i]) === null || _a === void 0 ? void 0 : _a.name, (_b = filesPriorChanges[i]) === null || _b === void 0 ? void 0 : _b.name)
1222
+ || !LodashUtilities.isEqual((_c = files[i]) === null || _c === void 0 ? void 0 : _c.url, (_d = filesPriorChanges[i]) === null || _d === void 0 ? void 0 : _d.url)) {
1223
+ return false;
1224
+ }
1225
+ files[i] = filesPriorChanges[i].file && !files[i].file ? yield FileUtilities.getFileData(files[i]) : files[i];
1226
+ // eslint-disable-next-line max-len
1227
+ filesPriorChanges[i] = files[i].file && !filesPriorChanges[i].file ? yield FileUtilities.getFileData(filesPriorChanges[i]) : filesPriorChanges[i];
1228
+ if (!LodashUtilities.isEqual(yield ((_e = files[i].file) === null || _e === void 0 ? void 0 : _e.text()), yield ((_f = filesPriorChanges[i].file) === null || _f === void 0 ? void 0 : _f.text()))) {
1229
+ return false;
1230
+ }
1231
+ }
1232
+ return true;
1233
+ });
1234
+ }
1235
+ static isEqualCustom(value, valuePriorChanges,
1236
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1237
+ metadata) {
1238
+ if (!metadata.isEqual(value, valuePriorChanges, metadata)) {
1239
+ return false;
1240
+ }
1241
+ return true;
1242
+ }
1243
+ /**
1244
+ * Compare function for sorting entity keys by their order value.
1245
+ *
1246
+ * @param a - First key of entity.
1247
+ * @param b - Second key of entity.
1248
+ * @param entity - Current entity (used to get metadata of entity keys).
1249
+ * @returns 0 if both values have the same order, a negative value if 'a' comes before 'b', a positive value if 'a' comes behind 'b'.
1250
+ */
1251
+ static compareOrder(a, b, entity) {
1252
+ const metadataA = EntityUtilities.getPropertyMetadata(entity, a);
1253
+ const metadataB = EntityUtilities.getPropertyMetadata(entity, b);
1254
+ if (metadataA.position.order === -1) {
773
1255
  if (metadataB.position.order === -1) {
774
1256
  return 0;
775
1257
  }
@@ -778,7 +1260,7 @@ class EntityUtilities {
778
1260
  else if (metadataB.position.order === -1) {
779
1261
  return -1;
780
1262
  }
781
- return ((metadataA.position.order) - (metadataB.position.order));
1263
+ return metadataA.position.order - metadataB.position.order;
782
1264
  }
783
1265
  /**
784
1266
  * Gets the bootstrap column values for "lg", "md", "sm".
@@ -807,7 +1289,7 @@ class EntityUtilities {
807
1289
  */
808
1290
  static resetChangesOnEntity(entity, entityPriorChanges) {
809
1291
  for (const key in entityPriorChanges) {
810
- Reflect.set(entity, key, Reflect.get(entityPriorChanges, key));
1292
+ ReflectUtilities.set(entity, key, ReflectUtilities.get(entityPriorChanges, key));
811
1293
  }
812
1294
  }
813
1295
  /**
@@ -821,17 +1303,17 @@ class EntityUtilities {
821
1303
  static getEntityRows(entity, hideOmitForCreate = false, hideOmitForEdit = false) {
822
1304
  const res = [];
823
1305
  const keys = EntityUtilities.keysOf(entity, hideOmitForCreate, hideOmitForEdit);
824
- const numberOfRows = this.getNumberOfRows(keys, entity);
1306
+ const numberOfRows = EntityUtilities.getNumberOfRows(keys, entity);
825
1307
  for (let i = 1; i <= numberOfRows; i++) {
826
1308
  const row = {
827
1309
  row: i,
828
- keys: this.getKeysForRow(keys, entity, i)
1310
+ keys: EntityUtilities.getKeysForRow(keys, entity, i)
829
1311
  };
830
1312
  res.push(row);
831
1313
  }
832
1314
  const lastRow = {
833
1315
  row: numberOfRows + 1,
834
- keys: this.getKeysForRow(keys, entity, -1)
1316
+ keys: EntityUtilities.getKeysForRow(keys, entity, -1)
835
1317
  };
836
1318
  res.push(lastRow);
837
1319
  return res;
@@ -855,7 +1337,7 @@ class EntityUtilities {
855
1337
  * @returns An array of keys of the entity.
856
1338
  */
857
1339
  static keysOf(entity, hideOmitForCreate = false, hideOmitForEdit = false) {
858
- let keys = Reflect.ownKeys(entity);
1340
+ let keys = ReflectUtilities.ownKeys(entity);
859
1341
  if (hideOmitForCreate) {
860
1342
  const omitForCreateKeys = EntityUtilities.getOmitForCreate(entity);
861
1343
  keys = keys.filter(k => !omitForCreateKeys.includes(k));
@@ -872,6 +1354,26 @@ EntityUtilities.construct = EntityUtilities.new;
872
1354
  // eslint-disable-next-line @typescript-eslint/member-ordering, jsdoc/require-jsdoc
873
1355
  EntityUtilities.build = EntityUtilities.new;
874
1356
 
1357
+ /**
1358
+ * A base Entity class with a builtin id.
1359
+ */
1360
+ class Entity {
1361
+ constructor(entity) {
1362
+ EntityUtilities.new(this, entity);
1363
+ }
1364
+ }
1365
+ __decorate([
1366
+ string({
1367
+ omitForCreate: true,
1368
+ omitForUpdate: true,
1369
+ display: false,
1370
+ displayStyle: 'line',
1371
+ displayName: 'ID',
1372
+ required: true
1373
+ }),
1374
+ __metadata("design:type", String)
1375
+ ], Entity.prototype, "id", void 0);
1376
+
875
1377
  /**
876
1378
  * A generic EntityService class.
877
1379
  * Offers basic CRUD-functionality.
@@ -910,7 +1412,58 @@ class EntityService {
910
1412
  */
911
1413
  create(entity) {
912
1414
  return __awaiter(this, void 0, void 0, function* () {
913
- const body = omit(entity, EntityUtilities.getOmitForCreate(entity));
1415
+ const body = LodashUtilities.omit(entity, EntityUtilities.getOmitForCreate(entity));
1416
+ const filePropertyKeys = EntityUtilities.getFileProperties(entity);
1417
+ if (!filePropertyKeys.length) {
1418
+ return yield this.createWithJson(body);
1419
+ }
1420
+ else {
1421
+ return yield this.createWithFormData(body, filePropertyKeys, entity);
1422
+ }
1423
+ });
1424
+ }
1425
+ // TODO: Find a way to use blobs with jest
1426
+ /* istanbul ignore next */
1427
+ /**
1428
+ * Creates the entity with form data when the entity contains files in contrast to creating it with a normal json body.
1429
+ * All file values are stored inside their respective property key and their name.
1430
+ * Form data is able to handle setting multiple files to the same key.
1431
+ *
1432
+ * @param body - The body Of the request.
1433
+ * @param filePropertyKeys - All property keys that are files and need to be added to the form data.
1434
+ * @param entity - The entity to create. This is needed in addition to the body because the body doesn't contain any metadata.
1435
+ * @returns The created entity from the server.
1436
+ */
1437
+ createWithFormData(body, filePropertyKeys, entity) {
1438
+ return __awaiter(this, void 0, void 0, function* () {
1439
+ const formData = new FormData();
1440
+ formData.append('body', JSON.stringify(LodashUtilities.omit(body, filePropertyKeys)));
1441
+ for (const key of filePropertyKeys) {
1442
+ if (EntityUtilities.getPropertyMetadata(entity, key, DecoratorTypes.FILE_DEFAULT).multiple) {
1443
+ const fileDataValues = body[key];
1444
+ for (const value of fileDataValues) {
1445
+ formData.append(key, (yield FileUtilities.getFileData(value)).file, value.name);
1446
+ }
1447
+ }
1448
+ else {
1449
+ const fileData = body[key];
1450
+ formData.append(key, (yield FileUtilities.getFileData(fileData)).file, fileData.name);
1451
+ }
1452
+ }
1453
+ const e = yield firstValueFrom(this.http.post(this.baseUrl, formData));
1454
+ this.entities.push(e);
1455
+ this.entitiesSubject.next(this.entities);
1456
+ return e;
1457
+ });
1458
+ }
1459
+ /**
1460
+ * Creates the entity with a normal json body in contrast to creating it with form data when the entity contains files.
1461
+ *
1462
+ * @param body - The body Of the request.
1463
+ * @returns The created entity from the server.
1464
+ */
1465
+ createWithJson(body) {
1466
+ return __awaiter(this, void 0, void 0, function* () {
914
1467
  const e = yield firstValueFrom(this.http.post(this.baseUrl, body));
915
1468
  this.entities.push(e);
916
1469
  this.entitiesSubject.next(this.entities);
@@ -939,9 +1492,61 @@ class EntityService {
939
1492
  */
940
1493
  update(entity, entityPriorChanges) {
941
1494
  return __awaiter(this, void 0, void 0, function* () {
942
- const reqBody = omit(EntityUtilities.difference(entity, entityPriorChanges), EntityUtilities.getOmitForUpdate(entity));
943
- const updatedEntity = yield firstValueFrom(this.http.patch(`${this.baseUrl}/${entityPriorChanges[this.idKey]}`, omitBy(reqBody, isNil)));
944
- this.entities[this.entities.findIndex(e => e[this.idKey] === entityPriorChanges[this.idKey])] = updatedEntity;
1495
+ const body = LodashUtilities.omit(yield EntityUtilities.difference(entity, entityPriorChanges), EntityUtilities.getOmitForUpdate(entity));
1496
+ const filePropertyKeys = EntityUtilities.getFileProperties(entityPriorChanges);
1497
+ if (!filePropertyKeys.length) {
1498
+ yield this.updateWithJson(body, entityPriorChanges[this.idKey]);
1499
+ }
1500
+ else {
1501
+ yield this.updateWithFormData(body, filePropertyKeys, entity, entityPriorChanges[this.idKey]);
1502
+ }
1503
+ });
1504
+ }
1505
+ // TODO: Find a way to use blobs with jest
1506
+ /* istanbul ignore next */
1507
+ /**
1508
+ * Updates the entity with form data when the entity contains files in contrast to creating it with a normal json body.
1509
+ * All file values are stored inside their respective property key and their name.
1510
+ * Form data is able to handle setting multiple files to the same key.
1511
+ *
1512
+ * @param body - The request body. Already contains only properties that have changed.
1513
+ * @param filePropertyKeys - The keys of all properties which are files and need to separately be appended to the form data.
1514
+ * @param entity - The original entity. Is needed to get the metadata of all the files.
1515
+ * @param id - The id of the entity to update.
1516
+ */
1517
+ updateWithFormData(body, filePropertyKeys, entity, id) {
1518
+ return __awaiter(this, void 0, void 0, function* () {
1519
+ const formData = new FormData();
1520
+ formData.append('body', JSON.stringify(LodashUtilities.omitBy(body, LodashUtilities.isNil)));
1521
+ for (const key of filePropertyKeys) {
1522
+ if (EntityUtilities.getPropertyMetadata(entity, key, DecoratorTypes.FILE_DEFAULT).multiple) {
1523
+ // eslint-disable-next-line max-len
1524
+ const fileDataValues = body[key];
1525
+ for (const value of fileDataValues) {
1526
+ formData.append(key, (yield FileUtilities.getFileData(value)).file, value.name);
1527
+ }
1528
+ }
1529
+ else {
1530
+ // eslint-disable-next-line max-len
1531
+ const fileData = body[key];
1532
+ formData.append(key, (yield FileUtilities.getFileData(fileData)).file, fileData.name);
1533
+ }
1534
+ }
1535
+ const updatedEntity = yield firstValueFrom(this.http.patch(`${this.baseUrl}/${id}`, formData));
1536
+ this.entities[this.entities.findIndex(e => e[this.idKey] === id)] = updatedEntity;
1537
+ this.entitiesSubject.next(this.entities);
1538
+ });
1539
+ }
1540
+ /**
1541
+ * Updates the entity with a normal json body in contrast to updating it with form data when the entity contains files.
1542
+ *
1543
+ * @param body - The body of the Request. Has already removed all unnecessary values.
1544
+ * @param id - The id of the entity to update.
1545
+ */
1546
+ updateWithJson(body, id) {
1547
+ return __awaiter(this, void 0, void 0, function* () {
1548
+ const updatedEntity = yield firstValueFrom(this.http.patch(`${this.baseUrl}/${id}`, LodashUtilities.omitBy(body, LodashUtilities.isNil)));
1549
+ this.entities[this.entities.findIndex(e => e[this.idKey] === id)] = updatedEntity;
945
1550
  this.entitiesSubject.next(this.entities);
946
1551
  });
947
1552
  }
@@ -979,7 +1584,6 @@ class BaseBuilder {
979
1584
  validateInput(data) {
980
1585
  // By default, no validation is done
981
1586
  }
982
- ;
983
1587
  /**
984
1588
  * Sets the value for the given key if no user value was provided.
985
1589
  *
@@ -988,7 +1592,7 @@ class BaseBuilder {
988
1592
  * @returns The Builder.
989
1593
  */
990
1594
  withDefault(key, value) {
991
- if (!this.inputData || !this.inputData[key]) {
1595
+ if (this.inputData == null || this.inputData[key] == null) {
992
1596
  this.data[key] = value;
993
1597
  }
994
1598
  return this;
@@ -1026,18 +1630,19 @@ class ConfirmDialogDataBuilder extends BaseBuilder {
1026
1630
  }
1027
1631
  // eslint-disable-next-line jsdoc/require-jsdoc
1028
1632
  generateBaseData(data) {
1029
- return new ConfirmDialogDataInternal((data === null || data === void 0 ? void 0 : data.text) ? data.text : ['Do you really want to do this?'], (data === null || data === void 0 ? void 0 : data.type) ? data.type : 'default', (data === null || data === void 0 ? void 0 : data.confirmButtonLabel) ? data.confirmButtonLabel : 'Confirm', (data === null || data === void 0 ? void 0 : data.cancelButtonLabel) ? data.cancelButtonLabel : 'Cancel', (data === null || data === void 0 ? void 0 : data.title) ? data.title : 'Confirmation', (data === null || data === void 0 ? void 0 : data.requireConfirmation) ? data.requireConfirmation : false, data === null || data === void 0 ? void 0 : data.confirmationText);
1633
+ var _a, _b, _c, _d, _e, _f;
1634
+ return new ConfirmDialogDataInternal((_a = data === null || data === void 0 ? void 0 : data.text) !== null && _a !== void 0 ? _a : ['Do you really want to do this?'], (_b = data === null || data === void 0 ? void 0 : data.type) !== null && _b !== void 0 ? _b : 'default', (_c = data === null || data === void 0 ? void 0 : data.confirmButtonLabel) !== null && _c !== void 0 ? _c : 'Confirm', (_d = data === null || data === void 0 ? void 0 : data.cancelButtonLabel) !== null && _d !== void 0 ? _d : 'Cancel', (_e = data === null || data === void 0 ? void 0 : data.title) !== null && _e !== void 0 ? _e : 'Confirmation', (_f = data === null || data === void 0 ? void 0 : data.requireConfirmation) !== null && _f !== void 0 ? _f : false, data === null || data === void 0 ? void 0 : data.confirmationText);
1030
1635
  }
1031
1636
  // eslint-disable-next-line jsdoc/require-jsdoc
1032
1637
  validateInput(data) {
1033
1638
  if (!data) {
1034
1639
  return;
1035
1640
  }
1036
- if (data.requireConfirmation && !data.confirmationText) {
1641
+ if (data.requireConfirmation === true && !data.confirmationText) {
1037
1642
  throw new Error(`Missing required Input data "confirmationText".
1038
1643
  You can only omit this value when "requireConfirmation" is false.`);
1039
1644
  }
1040
- if (!data.requireConfirmation && data.confirmationText) {
1645
+ if (data.requireConfirmation !== true && data.confirmationText) {
1041
1646
  throw new Error('The "confirmationText" will never be shown because "requireConfirmation" is not set to true');
1042
1647
  }
1043
1648
  if (data.type === 'info-only' && data.cancelButtonLabel) {
@@ -1075,10 +1680,10 @@ class NgxMatEntityConfirmDialogComponent {
1075
1680
  }
1076
1681
  }
1077
1682
  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 });
1078
- 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]" }] });
1683
+ 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: i2.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: i6.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: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.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]" }] });
1079
1684
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityConfirmDialogComponent, decorators: [{
1080
1685
  type: Component,
1081
- 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"] }]
1686
+ 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"] }]
1082
1687
  }], ctorParameters: function () {
1083
1688
  return [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{
1084
1689
  type: Inject,
@@ -1158,12 +1763,13 @@ class CreateDialogDataBuilder extends BaseBuilder {
1158
1763
  }
1159
1764
  // eslint-disable-next-line jsdoc/require-jsdoc
1160
1765
  generateBaseData(data) {
1766
+ var _a, _b, _c, _d;
1161
1767
  const confirmCreateDialogData = new ConfirmDialogDataBuilder(data === null || data === void 0 ? void 0 : data.confirmCreateDialogData)
1162
1768
  .withDefault('confirmButtonLabel', 'create')
1163
1769
  .withDefault('text', ['Do you really want to create this entity?'])
1164
1770
  .withDefault('title', 'Create')
1165
1771
  .getResult();
1166
- return new CreateDialogDataInternal((data === null || data === void 0 ? void 0 : data.title) ? data.title : 'Create', (data === null || data === void 0 ? void 0 : data.createButtonLabel) ? data.createButtonLabel : 'Create', (data === null || data === void 0 ? void 0 : data.cancelButtonLabel) ? data.cancelButtonLabel : 'Cancel', (data === null || data === void 0 ? void 0 : data.createRequiresConfirmDialog) ? data.createRequiresConfirmDialog : false, confirmCreateDialogData);
1772
+ return new CreateDialogDataInternal((_a = data === null || data === void 0 ? void 0 : data.title) !== null && _a !== void 0 ? _a : 'Create', (_b = data === null || data === void 0 ? void 0 : data.createButtonLabel) !== null && _b !== void 0 ? _b : 'Create', (_c = data === null || data === void 0 ? void 0 : data.cancelButtonLabel) !== null && _c !== void 0 ? _c : 'Cancel', (_d = data === null || data === void 0 ? void 0 : data.createRequiresConfirmDialog) !== null && _d !== void 0 ? _d : false, confirmCreateDialogData);
1167
1773
  }
1168
1774
  }
1169
1775
 
@@ -1186,337 +1792,1254 @@ class AddArrayItemDialogDataBuilder extends BaseBuilder {
1186
1792
  }
1187
1793
  // eslint-disable-next-line jsdoc/require-jsdoc
1188
1794
  generateBaseData(data) {
1795
+ var _a;
1189
1796
  const createDialogData = new CreateDialogDataBuilder(data.createDialogData)
1190
1797
  .withDefault('createButtonLabel', 'Add')
1191
1798
  .withDefault('title', 'Add to array')
1192
1799
  .getResult();
1193
- return new AddArrayItemDialogDataInternal(data.entity, createDialogData, data.getValidationErrorMessage ? data.getValidationErrorMessage : getValidationErrorMessage);
1800
+ return new AddArrayItemDialogDataInternal(data.entity, createDialogData, (_a = data.getValidationErrorMessage) !== null && _a !== void 0 ? _a : getValidationErrorMessage);
1194
1801
  }
1195
1802
  }
1196
1803
 
1197
1804
  /**
1198
- * The default input component. It gets the metadata of the property from the given @Input "entity" and @Input "propertyKey"
1199
- * and displays the input field accordingly.
1805
+ * The abstract base class of any ngx-mat-entity input.
1806
+ * Extend from this when implementing your own custom decorator.
1200
1807
  *
1201
- * You can also define a method that generates error-messages and if the input should be hidden when its metadata says
1202
- * that it should be omitted for creating or updating.
1203
- * The last part being mostly relevant if you want to use this component inside an ngFor.
1808
+ * It already provides:
1809
+ *
1810
+ * - entity: The entity which the property is on. (type-safe due to the Generic "EntityType")
1811
+ * - key: The key of the property. (type-safe due to the Generic "EntityType")
1812
+ * - getValidationErrorMessage: The function that generates the error message when the input is invalid.
1813
+ * - isReadOnly: Whether or not the input is read only. Can be used to disable elements.
1814
+ * - propertyValue: Just the typed version of the property, its the same as entity[key].
1815
+ * - metadata: The metadata of the property. (type-safe due to the Generic "CustomMetadataType")
1816
+ * - ngOnInit: Gets the metadata for the property, be aware of this when overriding this method.
1817
+ * - emitChange: Should be called when the input has changed. This is needed to trigger validation and dirty checks.
1204
1818
  */
1205
- class NgxMatEntityInputComponent {
1206
- constructor(dialog) {
1207
- this.dialog = dialog;
1208
- this.chipsInput = '';
1209
- this.selection = new SelectionModel(true, []);
1210
- this.DecoratorTypes = DecoratorTypes;
1211
- this.EntityUtilities = EntityUtilities;
1212
- this.DateUtilities = DateUtilities;
1213
- this.defaultDateFilter = () => true;
1819
+ // eslint-disable-next-line max-len
1820
+ class NgxMatEntityBaseInputComponent {
1821
+ constructor() {
1822
+ this.inputChangeEvent = new EventEmitter();
1214
1823
  }
1824
+ // eslint-disable-next-line jsdoc/require-returns
1215
1825
  /**
1216
- * This is needed for the inputs to work inside an ngFor.
1217
- *
1218
- * @param index - The index of the element in the ngFor.
1219
- * @returns The index.
1826
+ * The property value of entity[key] correctly typed.
1827
+ * Uses getters and setters so that inputs are always linked to the original value.
1220
1828
  */
1221
- trackByFn(index) {
1222
- return index;
1829
+ get propertyValue() {
1830
+ return this.entity[this.key];
1831
+ }
1832
+ // eslint-disable-next-line jsdoc/require-jsdoc
1833
+ set propertyValue(value) {
1834
+ this.entity[this.key] = value;
1223
1835
  }
1224
1836
  ngOnInit() {
1225
- var _a;
1226
- if (!this.entity) {
1227
- throw new Error('Missing required Input data "entity"');
1228
- }
1229
- if (!this.propertyKey) {
1230
- throw new Error('Missing required Input data "propertyKey"');
1231
- }
1232
- this.type = EntityUtilities.getPropertyType(this.entity, this.propertyKey);
1233
- this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.propertyKey, this.type);
1234
- this.metadataDefaultString = this.metadata;
1235
- this.metadataTextboxString = this.metadata;
1236
- this.metadataAutocompleteString = this.metadata;
1237
- this.autocompleteStrings = this.metadataAutocompleteString.autocompleteValues;
1238
- this.filteredAutocompleteStrings = cloneDeep(this.autocompleteStrings);
1239
- this.metadataDropdownString = this.metadata;
1240
- this.metadataDropdownBoolean = this.metadata;
1241
- if ((this.type === DecoratorTypes.BOOLEAN_CHECKBOX || this.type === DecoratorTypes.BOOLEAN_TOGGLE)
1242
- && this.entity[this.propertyKey] === undefined) {
1243
- this.entity[this.propertyKey] = false;
1244
- }
1245
- this.metadataDefaultNumber = this.metadata;
1246
- this.metadataDropdownNumber = this.metadata;
1247
- this.metadataDefaultObject = this.metadata;
1248
- this.objectProperty = this.entity[this.propertyKey];
1249
- if (this.type === DecoratorTypes.OBJECT) {
1250
- this.objectPropertyRows = EntityUtilities.getEntityRows(this.objectProperty, this.hideOmitForCreate, this.hideOmitForEdit);
1251
- }
1252
- this.metadataEntityArray = this.metadata;
1253
- if (this.type === DecoratorTypes.ARRAY) {
1254
- if (!this.entity[this.propertyKey]) {
1255
- this.entity[this.propertyKey] = [];
1256
- }
1257
- this.entityArrayValues = this.entity[this.propertyKey];
1258
- if (this.metadataEntityArray.createInline === undefined) {
1259
- this.metadataEntityArray.createInline = true;
1260
- }
1261
- if (!this.metadataEntityArray.createInline && !this.metadataEntityArray.createDialogData) {
1262
- this.metadataEntityArray.createDialogData = {
1263
- title: 'Add'
1264
- };
1265
- }
1266
- const givenDisplayColumns = this.metadataEntityArray.displayColumns.map((v) => v.displayName);
1267
- if (givenDisplayColumns.find(s => s === 'select')) {
1268
- throw new Error(`The name "select" for a display column is reserved.
1269
- Please choose a different name.`);
1270
- }
1271
- this.displayedColumns = ['select'].concat(givenDisplayColumns);
1272
- this.dataSource = new MatTableDataSource();
1273
- this.dataSource.data = this.entityArrayValues;
1274
- this.arrayItem = new this.metadataEntityArray.EntityClass();
1275
- this.arrayItemInlineRows = EntityUtilities.getEntityRows(this.arrayItem, this.hideOmitForCreate === false ? false : true, this.hideOmitForEdit ? true : false);
1276
- this.arrayItemPriorChanges = cloneDeep(this.arrayItem);
1277
- this.dialogInputData = {
1278
- entity: this.arrayItem,
1279
- createDialogData: this.metadataEntityArray.createDialogData,
1280
- getValidationErrorMessage: this.getValidationErrorMessage
1281
- };
1282
- this.dialogData = new AddArrayItemDialogDataBuilder(this.dialogInputData).getResult();
1283
- this.arrayItemDialogRows = EntityUtilities.getEntityRows(this.dialogData.entity, true);
1284
- }
1285
- this.metadataStringChipsArray = this.metadata;
1286
- if ((this.type === DecoratorTypes.ARRAY_STRING_CHIPS || this.type === DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS)
1287
- && ((_a = this.entity[this.propertyKey]) === null || _a === void 0 ? void 0 : _a.length)) {
1288
- this.stringChipsArrayValues = this.entity[this.propertyKey];
1289
- }
1290
- this.metadataAutocompleteStringChipsArray = this.metadata;
1291
- if (!this.getValidationErrorMessage) {
1292
- this.getValidationErrorMessage = getValidationErrorMessage;
1293
- }
1294
- this.metadataDefaultDate = this.metadata;
1295
- this.metadataDateRangeDate = this.metadata;
1296
- this.metadataDateTimeDate = this.metadata;
1297
- if (this.type === DecoratorTypes.DATE_RANGE) {
1298
- this.dateRange = cloneDeep(this.entity[this.propertyKey]);
1299
- if (!this.dateRange) {
1300
- this.dateRange = {
1301
- start: undefined,
1302
- end: undefined,
1303
- values: undefined
1304
- };
1305
- }
1306
- this.dateRangeStart = new Date(this.dateRange.start);
1307
- this.dateRangeEnd = new Date(this.dateRange.end);
1308
- this.setDateRangeValues();
1309
- }
1310
- if (this.type === DecoratorTypes.DATE_TIME) {
1311
- this.time = DateUtilities.getTimeFromDate(DateUtilities.asDate(this.entity[this.propertyKey]));
1312
- this.timeDropdownValues = this.metadataDateTimeDate.times;
1313
- if (this.entity[this.propertyKey]) {
1314
- this.dateTime = new Date(this.entity[this.propertyKey]);
1315
- }
1316
- }
1837
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key);
1317
1838
  }
1318
1839
  /**
1319
- * Checks if two times are equal. Is needed for the dropdown.
1320
- *
1321
- * @param time1 - The first time to compare.
1322
- * @param time2 - The second time to compare.
1323
- * @returns Whether or not the time objects are the same.
1840
+ * Should emit when the input has changed. This is needed to trigger validation and dirty checks.
1324
1841
  */
1325
- compareTimes(time1, time2) {
1326
- return time1 && time2 && time1.hours === time2.hours && time1.minutes === time2.minutes;
1842
+ emitChange() {
1843
+ this.inputChangeEvent.emit();
1844
+ }
1845
+ }
1846
+ NgxMatEntityBaseInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityBaseInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1847
+ NgxMatEntityBaseInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityBaseInputComponent, selector: "ngx-mat-entity-base-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage", isReadOnly: "isReadOnly" }, outputs: { inputChangeEvent: "inputChangeEvent" }, ngImport: i0, template: '', isInline: true });
1848
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityBaseInputComponent, decorators: [{
1849
+ type: Component,
1850
+ args: [{
1851
+ selector: 'ngx-mat-entity-base-input',
1852
+ template: ''
1853
+ }]
1854
+ }], propDecorators: { entity: [{
1855
+ type: Input
1856
+ }], key: [{
1857
+ type: Input
1858
+ }], getValidationErrorMessage: [{
1859
+ type: Input
1860
+ }], isReadOnly: [{
1861
+ type: Input
1862
+ }], inputChangeEvent: [{
1863
+ type: Output
1864
+ }] } });
1865
+
1866
+ /* eslint-disable jsdoc/require-jsdoc */
1867
+ class StringInputComponent extends NgxMatEntityBaseInputComponent {
1868
+ }
1869
+ StringInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1870
+ StringInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: StringInputComponent, selector: "string-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"propertyValue\"\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 [disabled]=\"isReadOnly\"\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$1.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.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i4.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i4.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i4.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
1871
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringInputComponent, decorators: [{
1872
+ type: Component,
1873
+ args: [{ selector: 'string-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"propertyValue\"\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 [disabled]=\"isReadOnly\"\n >\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
1874
+ }] });
1875
+
1876
+ /* eslint-disable jsdoc/require-jsdoc */
1877
+ class StringTextboxInputComponent extends NgxMatEntityBaseInputComponent {
1878
+ }
1879
+ StringTextboxInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringTextboxInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1880
+ StringTextboxInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: StringTextboxInputComponent, selector: "string-textbox-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <textarea\n matInput\n [(ngModel)]=\"propertyValue\"\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 [disabled]=\"isReadOnly\"\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$1.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: i4.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i4.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i4.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
1881
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringTextboxInputComponent, decorators: [{
1882
+ type: Component,
1883
+ args: [{ selector: 'string-textbox-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <textarea\n matInput\n [(ngModel)]=\"propertyValue\"\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 [disabled]=\"isReadOnly\"\n >\n </textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
1884
+ }] });
1885
+
1886
+ /* eslint-disable jsdoc/require-jsdoc */
1887
+ class StringAutocompleteInputComponent extends NgxMatEntityBaseInputComponent {
1888
+ ngOnInit() {
1889
+ super.ngOnInit();
1890
+ this.autocompleteStrings = this.metadata.autocompleteValues;
1891
+ this.filteredAutocompleteStrings = LodashUtilities.cloneDeep(this.autocompleteStrings);
1327
1892
  }
1328
1893
  /**
1329
- * Updates the date range values based on the start and end date.
1894
+ * Dynamically filters the Autocomplete options when the user inputs something.
1895
+ *
1896
+ * @param input - The input of the user.
1330
1897
  */
1331
- setDateRangeValues() {
1332
- if (this.dateRangeStart && this.dateRangeEnd) {
1333
- this.dateRange.start = new Date(this.dateRangeStart);
1334
- this.dateRange.end = new Date(this.dateRangeEnd);
1335
- const values = DateUtilities.getDatesBetween(new Date(this.dateRange.start), new Date(this.dateRange.end), this.metadataDateRangeDate);
1336
- this.dateRange.values = values.length ? values : undefined;
1898
+ filterAutocompleteStrings(input) {
1899
+ if (input) {
1900
+ this.filteredAutocompleteStrings = this.autocompleteStrings.filter(s => s.toLowerCase().includes(input.toLowerCase()));
1337
1901
  }
1338
- else {
1339
- this.dateRange.values = undefined;
1902
+ }
1903
+ }
1904
+ StringAutocompleteInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringAutocompleteInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1905
+ StringAutocompleteInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: StringAutocompleteInputComponent, selector: "string-autocomplete-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matAutocomplete]=\"auto\"\n (keyup)=\"filterAutocompleteStrings(propertyValue)\"\n [required]=\"metadata.required\"\n [minlength]=\"metadata.minLength ?? null\"\n [maxlength]=\"metadata.maxLength ?? null\"\n [pattern]=\"metadata.regex ?? '[\\\\s\\\\S]*'\"\n (ngModelChange)=\"emitChange()\"\n [disabled]=\"isReadOnly\"\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$1.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$1.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.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$1.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", exportAs: ["matAutocompleteTrigger"] }, { type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i4.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i4.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i4.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
1906
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringAutocompleteInputComponent, decorators: [{
1907
+ type: Component,
1908
+ args: [{ selector: 'string-autocomplete-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matAutocomplete]=\"auto\"\n (keyup)=\"filterAutocompleteStrings(propertyValue)\"\n [required]=\"metadata.required\"\n [minlength]=\"metadata.minLength ?? null\"\n [maxlength]=\"metadata.maxLength ?? null\"\n [pattern]=\"metadata.regex ?? '[\\\\s\\\\S]*'\"\n (ngModelChange)=\"emitChange()\"\n [disabled]=\"isReadOnly\"\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"] }]
1909
+ }] });
1910
+
1911
+ /* eslint-disable jsdoc/require-jsdoc */
1912
+ class StringDropdownInputComponent extends NgxMatEntityBaseInputComponent {
1913
+ }
1914
+ StringDropdownInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringDropdownInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1915
+ StringDropdownInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: StringDropdownInputComponent, selector: "string-dropdown-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select (ngModelChange)=\"emitChange()\" [(ngModel)]=\"propertyValue\" [name]=\"key.toString()\" #model=\"ngModel\" [required]=\"metadata.required\" [disabled]=\"isReadOnly\">\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$2.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
1916
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringDropdownInputComponent, decorators: [{
1917
+ type: Component,
1918
+ args: [{ selector: 'string-dropdown-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select (ngModelChange)=\"emitChange()\" [(ngModel)]=\"propertyValue\" [name]=\"key.toString()\" #model=\"ngModel\" [required]=\"metadata.required\" [disabled]=\"isReadOnly\">\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"] }]
1919
+ }] });
1920
+
1921
+ /* eslint-disable jsdoc/require-jsdoc */
1922
+ class StringPasswordInputComponent extends NgxMatEntityBaseInputComponent {
1923
+ constructor() {
1924
+ super(...arguments);
1925
+ this.hide = true;
1926
+ this.hideConfirm = true;
1927
+ }
1928
+ ngOnInit() {
1929
+ super.ngOnInit();
1930
+ this.confirmRequired = this.metadata.required;
1931
+ this.confirmPassword = LodashUtilities.cloneDeep(this.propertyValue);
1932
+ ReflectUtilities.defineMetadata('confirmPassword', this.confirmPassword, this.entity, this.key);
1933
+ }
1934
+ passwordInput() {
1935
+ this.confirmRequired = Boolean(this.propertyValue);
1936
+ ReflectUtilities.defineMetadata('confirmPassword', this.confirmPassword, this.entity, this.key);
1937
+ this.emitChange();
1938
+ }
1939
+ }
1940
+ StringPasswordInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringPasswordInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1941
+ StringPasswordInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: StringPasswordInputComponent, selector: "string-password-input", usesInheritance: true, ngImport: i0, template: "<div class=\"password-row\">\n <mat-form-field [class.w-50]=\"metadata.needsConfirmation\" [class.w-100]=\"!metadata.needsConfirmation\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n [type]=\"hide ? 'password' : 'text'\"\n matInput\n [(ngModel)]=\"propertyValue\"\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)=\"passwordInput()\"\n [disabled]=\"isReadOnly\"\n >\n <button (click)=\"hide = !hide\" [disabled]=\"isReadOnly\" mat-icon-button matSuffix>\n <i *ngIf=\"hide\" class=\"fas fa-eye-slash\"></i>\n <i *ngIf=\"!hide\" class=\"fas fa-eye\"></i>\n </button>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n <div *ngIf=\"metadata.needsConfirmation\" style=\"margin-left: 5px;margin-right: 5px;\"></div>\n <mat-form-field class=\"w-50\" *ngIf=\"metadata.needsConfirmation\">\n <mat-label>{{metadata.confirmationDisplayName}}</mat-label>\n <input\n [type]=\"hideConfirm ? 'password' : 'text'\"\n matInput\n [(ngModel)]=\"confirmPassword\"\n [name]=\"key.toString() + 'confirmPassword'\"\n #confirmModel=\"ngModel\"\n [required]=\"metadata.required || confirmRequired\"\n (ngModelChange)=\"passwordInput()\"\n [disabled]=\"isReadOnly\"\n >\n <button (click)=\"hideConfirm = !hideConfirm\" [disabled]=\"isReadOnly\" mat-icon-button matSuffix>\n <i *ngIf=\"hideConfirm\" class=\"fas fa-eye-slash\"></i>\n <i *ngIf=\"!hideConfirm\" class=\"fas fa-eye\"></i>\n </button>\n <mat-error>{{getValidationErrorMessage(confirmModel)}}</mat-error>\n </mat-form-field>\n</div>\n\n<mat-error *ngIf=\"metadata.needsConfirmation && propertyValue && confirmPassword && (confirmPassword !== propertyValue)\">\n {{metadata.passwordsDontMatchErrorMessage}}\n</mat-error>", styles: [".password-row{display:flex;justify-content:space-between}.w-50{width:50%}.w-100{width:100%}\n"], components: [{ type: i1$1.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"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i4$1.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.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i4.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i4.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i4.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i1$1.MatSuffix, selector: "[matSuffix]" }, { type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
1942
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringPasswordInputComponent, decorators: [{
1943
+ type: Component,
1944
+ args: [{ selector: 'string-password-input', template: "<div class=\"password-row\">\n <mat-form-field [class.w-50]=\"metadata.needsConfirmation\" [class.w-100]=\"!metadata.needsConfirmation\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n [type]=\"hide ? 'password' : 'text'\"\n matInput\n [(ngModel)]=\"propertyValue\"\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)=\"passwordInput()\"\n [disabled]=\"isReadOnly\"\n >\n <button (click)=\"hide = !hide\" [disabled]=\"isReadOnly\" mat-icon-button matSuffix>\n <i *ngIf=\"hide\" class=\"fas fa-eye-slash\"></i>\n <i *ngIf=\"!hide\" class=\"fas fa-eye\"></i>\n </button>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n <div *ngIf=\"metadata.needsConfirmation\" style=\"margin-left: 5px;margin-right: 5px;\"></div>\n <mat-form-field class=\"w-50\" *ngIf=\"metadata.needsConfirmation\">\n <mat-label>{{metadata.confirmationDisplayName}}</mat-label>\n <input\n [type]=\"hideConfirm ? 'password' : 'text'\"\n matInput\n [(ngModel)]=\"confirmPassword\"\n [name]=\"key.toString() + 'confirmPassword'\"\n #confirmModel=\"ngModel\"\n [required]=\"metadata.required || confirmRequired\"\n (ngModelChange)=\"passwordInput()\"\n [disabled]=\"isReadOnly\"\n >\n <button (click)=\"hideConfirm = !hideConfirm\" [disabled]=\"isReadOnly\" mat-icon-button matSuffix>\n <i *ngIf=\"hideConfirm\" class=\"fas fa-eye-slash\"></i>\n <i *ngIf=\"!hideConfirm\" class=\"fas fa-eye\"></i>\n </button>\n <mat-error>{{getValidationErrorMessage(confirmModel)}}</mat-error>\n </mat-form-field>\n</div>\n\n<mat-error *ngIf=\"metadata.needsConfirmation && propertyValue && confirmPassword && (confirmPassword !== propertyValue)\">\n {{metadata.passwordsDontMatchErrorMessage}}\n</mat-error>", styles: [".password-row{display:flex;justify-content:space-between}.w-50{width:50%}.w-100{width:100%}\n"] }]
1945
+ }] });
1946
+
1947
+ /* eslint-disable jsdoc/require-jsdoc */
1948
+ class BooleanCheckboxInputComponent extends NgxMatEntityBaseInputComponent {
1949
+ ngOnInit() {
1950
+ var _a;
1951
+ super.ngOnInit();
1952
+ this.propertyValue = (_a = this.propertyValue) !== null && _a !== void 0 ? _a : false;
1953
+ }
1954
+ }
1955
+ BooleanCheckboxInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanCheckboxInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1956
+ BooleanCheckboxInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: BooleanCheckboxInputComponent, selector: "boolean-checkbox-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-checkbox\n color=\"primary\"\n (ngModelChange)=\"emitChange()\"\n (click)=\"model.control.markAsTouched()\"\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString()\"\n [disabled]=\"isReadOnly\"\n [class.disabled]=\"isReadOnly\"\n [class.mat-checkbox-disabled]=\"false\"\n >\n </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)]=\"propertyValue\"\n [name]=\"key.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\"\n [disabled]=\"isReadOnly\"\n >\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["::ng-deep .hideUnderline .mat-form-field-underline{opacity:0%}::ng-deep .disabled .mat-checkbox-ripple{display:none}::ng-deep .disabled:hover{cursor:default}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.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4$1.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.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: i4.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i4.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"] }] });
1957
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanCheckboxInputComponent, decorators: [{
1958
+ type: Component,
1959
+ args: [{ selector: 'boolean-checkbox-input', template: "<mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-checkbox\n color=\"primary\"\n (ngModelChange)=\"emitChange()\"\n (click)=\"model.control.markAsTouched()\"\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString()\"\n [disabled]=\"isReadOnly\"\n [class.disabled]=\"isReadOnly\"\n [class.mat-checkbox-disabled]=\"false\"\n >\n </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)]=\"propertyValue\"\n [name]=\"key.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\"\n [disabled]=\"isReadOnly\"\n >\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["::ng-deep .hideUnderline .mat-form-field-underline{opacity:0%}::ng-deep .disabled .mat-checkbox-ripple{display:none}::ng-deep .disabled:hover{cursor:default}mat-form-field{width:100%}\n"] }]
1960
+ }] });
1961
+
1962
+ /* eslint-disable jsdoc/require-jsdoc */
1963
+ class BooleanToggleInputComponent extends NgxMatEntityBaseInputComponent {
1964
+ ngOnInit() {
1965
+ var _a;
1966
+ super.ngOnInit();
1967
+ this.propertyValue = (_a = this.propertyValue) !== null && _a !== void 0 ? _a : false;
1968
+ }
1969
+ }
1970
+ BooleanToggleInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanToggleInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1971
+ BooleanToggleInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: BooleanToggleInputComponent, selector: "boolean-toggle-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-slide-toggle\n color=\"primary\"\n (click)=\"model.control.markAsTouched()\"\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString()\"\n [disabled]=\"isReadOnly\"\n >\n </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)]=\"propertyValue\"\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$3.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4$1.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.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: i4.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i4.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"] }] });
1972
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanToggleInputComponent, decorators: [{
1973
+ type: Component,
1974
+ args: [{ selector: 'boolean-toggle-input', template: "<mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-slide-toggle\n color=\"primary\"\n (click)=\"model.control.markAsTouched()\"\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString()\"\n [disabled]=\"isReadOnly\"\n >\n </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)]=\"propertyValue\"\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"] }]
1975
+ }] });
1976
+
1977
+ /* eslint-disable jsdoc/require-jsdoc */
1978
+ class BooleanDropdownInputComponent extends NgxMatEntityBaseInputComponent {
1979
+ }
1980
+ BooleanDropdownInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanDropdownInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1981
+ BooleanDropdownInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: BooleanDropdownInputComponent, selector: "boolean-dropdown-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select\n (ngModelChange)=\"emitChange()\"\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [disabled]=\"isReadOnly\"\n >\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$2.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.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"] }] });
1982
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanDropdownInputComponent, decorators: [{
1983
+ type: Component,
1984
+ args: [{ selector: 'boolean-dropdown-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select\n (ngModelChange)=\"emitChange()\"\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [disabled]=\"isReadOnly\"\n >\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"] }]
1985
+ }] });
1986
+
1987
+ /* eslint-disable jsdoc/require-jsdoc */
1988
+ class NumberInputComponent extends NgxMatEntityBaseInputComponent {
1989
+ }
1990
+ NumberInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1991
+ NumberInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NumberInputComponent, selector: "number-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n type=\"number\"\n [(ngModel)]=\"propertyValue\"\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 [disabled]=\"isReadOnly\"\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$1.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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { type: i4.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { type: i4.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { type: i4.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.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"] }] });
1992
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberInputComponent, decorators: [{
1993
+ type: Component,
1994
+ args: [{ selector: 'number-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n type=\"number\"\n [(ngModel)]=\"propertyValue\"\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 [disabled]=\"isReadOnly\"\n >\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
1995
+ }] });
1996
+
1997
+ /* eslint-disable jsdoc/require-jsdoc */
1998
+ class NumberDropdownInputComponent extends NgxMatEntityBaseInputComponent {
1999
+ }
2000
+ NumberDropdownInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberDropdownInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2001
+ NumberDropdownInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NumberDropdownInputComponent, selector: "number-dropdown-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select (ngModelChange)=\"emitChange()\" [(ngModel)]=\"propertyValue\" [name]=\"key.toString()\" #model=\"ngModel\" [required]=\"metadata.required\" [disabled]=\"isReadOnly\">\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$2.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
2002
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberDropdownInputComponent, decorators: [{
2003
+ type: Component,
2004
+ args: [{ selector: 'number-dropdown-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select (ngModelChange)=\"emitChange()\" [(ngModel)]=\"propertyValue\" [name]=\"key.toString()\" #model=\"ngModel\" [required]=\"metadata.required\" [disabled]=\"isReadOnly\">\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"] }]
2005
+ }] });
2006
+
2007
+ /* eslint-disable jsdoc/require-jsdoc */
2008
+ class NumberSliderInputComponent extends NgxMatEntityBaseInputComponent {
2009
+ }
2010
+ NumberSliderInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberSliderInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2011
+ NumberSliderInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NumberSliderInputComponent, selector: "number-slider-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field floatLabel=\"always\" class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <!-- hidden input is needed so that the slider can be used inside a mat-form-field -->\n <input matInput\n #hiddenInput\n type=\"number\"\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString() + 'Helper'\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadata.min ?? null\"\n [max]=\"metadata.max ?? null\"\n (ngModelChange)=\"emitChange()\"\n [disabled]=\"isReadOnly\"\n >\n <mat-slider\n id=\"slider\"\n color=\"primary\"\n (click)=\"model.control.markAsTouched()\"\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString()\"\n [min]=\"metadata.min ?? null\"\n [max]=\"metadata.max ?? null\"\n [step]=\"metadata.step\"\n [thumbLabel]=\"true\"\n [displayWith]=\"metadata.formatThumbLabelValue\"\n [tickInterval]=\"metadata.tickInterval\"\n [disabled]=\"isReadOnly\"\n >\n </mat-slider>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}input{opacity:0%}mat-slider{width:100%;position:absolute;top:-7px;left:0}::ng-deep .hideUnderline .mat-form-field-underline{opacity:0%}::ng-deep #slider .mat-slider-thumb-label{top:-15px;display:flex;transform:rotate(45deg) scale(1);border-radius:50%}::ng-deep #slider.mat-slider-min-value.cdk-focused .mat-slider-thumb-label{background-color:#000000de}::ng-deep #slider .mat-slider-thumb{transform:scale(0)}::ng-deep #slider .mat-slider-thumb-label-text{opacity:1}\n"], components: [{ type: i1$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2$4.MatSlider, selector: "mat-slider", inputs: ["disabled", "color", "tabIndex", "invert", "max", "min", "step", "thumbLabel", "tickInterval", "value", "displayWith", "valueText", "vertical"], outputs: ["change", "input", "valueChange"], exportAs: ["matSlider"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i4$1.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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { type: i4.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { type: i4.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { type: i4.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.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"] }] });
2012
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberSliderInputComponent, decorators: [{
2013
+ type: Component,
2014
+ args: [{ selector: 'number-slider-input', template: "<mat-form-field floatLabel=\"always\" class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <!-- hidden input is needed so that the slider can be used inside a mat-form-field -->\n <input matInput\n #hiddenInput\n type=\"number\"\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString() + 'Helper'\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadata.min ?? null\"\n [max]=\"metadata.max ?? null\"\n (ngModelChange)=\"emitChange()\"\n [disabled]=\"isReadOnly\"\n >\n <mat-slider\n id=\"slider\"\n color=\"primary\"\n (click)=\"model.control.markAsTouched()\"\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString()\"\n [min]=\"metadata.min ?? null\"\n [max]=\"metadata.max ?? null\"\n [step]=\"metadata.step\"\n [thumbLabel]=\"true\"\n [displayWith]=\"metadata.formatThumbLabelValue\"\n [tickInterval]=\"metadata.tickInterval\"\n [disabled]=\"isReadOnly\"\n >\n </mat-slider>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}input{opacity:0%}mat-slider{width:100%;position:absolute;top:-7px;left:0}::ng-deep .hideUnderline .mat-form-field-underline{opacity:0%}::ng-deep #slider .mat-slider-thumb-label{top:-15px;display:flex;transform:rotate(45deg) scale(1);border-radius:50%}::ng-deep #slider.mat-slider-min-value.cdk-focused .mat-slider-thumb-label{background-color:#000000de}::ng-deep #slider .mat-slider-thumb{transform:scale(0)}::ng-deep #slider .mat-slider-thumb-label-text{opacity:1}\n"] }]
2015
+ }] });
2016
+
2017
+ /**
2018
+ * The base data needed for all arrays that are displayed as a table.
2019
+ */
2020
+ class ArrayTableComponent extends NgxMatEntityBaseInputComponent {
2021
+ constructor(matDialog) {
2022
+ super();
2023
+ this.matDialog = matDialog;
2024
+ this.input = undefined;
2025
+ this.dataSource = new MatTableDataSource();
2026
+ this.selection = new SelectionModel(true, []);
2027
+ }
2028
+ ngOnInit() {
2029
+ var _a;
2030
+ super.ngOnInit();
2031
+ this.propertyValue = (_a = this.propertyValue) !== null && _a !== void 0 ? _a : [];
2032
+ const givenDisplayColumns = this.metadata.displayColumns.map((v) => v.displayName);
2033
+ if (givenDisplayColumns.find(s => s === 'select')) {
2034
+ throw new Error(`The name "select" for a display column is reserved.
2035
+ Please choose a different name.`);
1340
2036
  }
1341
- this.entity[this.propertyKey] = this.dateRange;
2037
+ this.displayedColumns = this.isReadOnly ? givenDisplayColumns : ['select'].concat(givenDisplayColumns);
2038
+ this.dataSource.data = this.propertyValue;
1342
2039
  }
1343
2040
  /**
1344
- * Sets the time on a datetime property.
2041
+ * Toggles all array-items in the table.
2042
+ *
1345
2043
  */
1346
- setTime() {
1347
- var _a, _b;
1348
- if (!this.dateTime) {
1349
- this.entity[this.propertyKey] = undefined;
1350
- return;
1351
- }
1352
- this.entity[this.propertyKey] = new Date(this.dateTime);
1353
- if (((_a = this.time) === null || _a === void 0 ? void 0 : _a.hours) != null && ((_b = this.time) === null || _b === void 0 ? void 0 : _b.minutes) != null) {
1354
- DateUtilities.asDate(this.entity[this.propertyKey]).setHours(this.time.hours, this.time.minutes, 0, 0);
2044
+ masterToggle() {
2045
+ if (this.isAllSelected()) {
2046
+ this.selection.clear();
1355
2047
  }
1356
2048
  else {
1357
- DateUtilities.asDate(this.entity[this.propertyKey]).setHours(0, 0, 0, 0);
2049
+ this.dataSource.data.forEach(row => this.selection.select(row));
1358
2050
  }
1359
2051
  }
1360
2052
  /**
1361
- * Tries to add an item to the array.
1362
- * Does this either inline if the "createInline"-metadata is set to true
1363
- * or in a separate dialog if it is set to false.
2053
+ * Checks if all array-items in the table have been selected.
2054
+ * This is needed to display the "masterToggle"-checkbox correctly.
2055
+ *
2056
+ * @returns Whether or not all array-items in the table have been selected.
1364
2057
  */
1365
- add() {
1366
- if (this.metadataEntityArray.createInline) {
1367
- this.entityArrayValues.push(cloneDeep(this.arrayItem));
1368
- this.dataSource.data = this.entityArrayValues;
1369
- EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
1370
- }
1371
- else {
1372
- this.addArrayItemDialogRef = this.dialog.open(this.addArrayItemDialog, {
1373
- data: this.dialogData,
1374
- autoFocus: false,
1375
- restoreFocus: false
1376
- });
1377
- }
2058
+ isAllSelected() {
2059
+ const numSelected = this.selection.selected.length;
2060
+ const numRows = this.dataSource.data.length;
2061
+ return numSelected === numRows;
1378
2062
  }
1379
2063
  /**
1380
- * Adds the array item defined in the dialog.
2064
+ * Tries to add an item to the array.
1381
2065
  */
1382
- addArrayItem() {
1383
- this.addArrayItemDialogRef.close();
1384
- this.entityArrayValues.push(cloneDeep(this.arrayItem));
1385
- this.dataSource.data = this.entityArrayValues;
1386
- EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
2066
+ add() {
2067
+ var _a, _b, _c;
2068
+ if (this.input != null) {
2069
+ if (!this.metadata.allowDuplicates
2070
+ && ((_a = this.propertyValue) === null || _a === void 0 ? void 0 : _a.find((v) => __awaiter(this, void 0, void 0, function* () { return yield EntityUtilities.isEqual(this.input, v, this.metadata, this.metadata.itemType); }))) != null) {
2071
+ this.matDialog.open(NgxMatEntityConfirmDialogComponent, {
2072
+ data: this.metadata.duplicatesErrorDialog,
2073
+ autoFocus: false,
2074
+ restoreFocus: false
2075
+ });
2076
+ return;
2077
+ }
2078
+ (_b = this.propertyValue) === null || _b === void 0 ? void 0 : _b.push(LodashUtilities.cloneDeep(this.input));
2079
+ this.dataSource.data = (_c = this.propertyValue) !== null && _c !== void 0 ? _c : [];
2080
+ this.resetInput();
2081
+ this.emitChange();
2082
+ }
1387
2083
  }
1388
2084
  /**
1389
- * Cancels adding the array item defined in the dialog.
2085
+ * Is split up from the add method to override this functionality more easily.
1390
2086
  */
1391
- cancelAddArrayItem() {
1392
- this.addArrayItemDialogRef.close();
1393
- EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
2087
+ resetInput() {
2088
+ this.input = undefined;
1394
2089
  }
1395
2090
  /**
1396
- * Removes all selected entries from the array.
2091
+ * Removes all selected entries from the entity array.
1397
2092
  */
1398
2093
  remove() {
2094
+ var _a;
1399
2095
  this.selection.selected.forEach(s => {
1400
- this.entityArrayValues.splice(this.entityArrayValues.indexOf(s), 1);
2096
+ var _a;
2097
+ (_a = this.propertyValue) === null || _a === void 0 ? void 0 : _a.splice(this.propertyValue.indexOf(s), 1);
1401
2098
  });
1402
- this.dataSource.data = this.entityArrayValues;
2099
+ this.dataSource.data = (_a = this.propertyValue) !== null && _a !== void 0 ? _a : [];
1403
2100
  this.selection.clear();
2101
+ this.emitChange();
2102
+ }
2103
+ }
2104
+ ArrayTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayTableComponent, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
2105
+ ArrayTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: ArrayTableComponent, selector: "ngx-mat-entity-array-table", usesInheritance: true, ngImport: i0, template: '', isInline: true });
2106
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayTableComponent, decorators: [{
2107
+ type: Component,
2108
+ args: [{
2109
+ selector: 'ngx-mat-entity-array-table',
2110
+ template: ''
2111
+ }]
2112
+ }], ctorParameters: function () { return [{ type: i1.MatDialog }]; } });
2113
+
2114
+ /* eslint-disable jsdoc/require-jsdoc */
2115
+ class ArrayDateInputComponent extends ArrayTableComponent {
2116
+ constructor() {
2117
+ super(...arguments);
2118
+ this.DateUtilities = DateUtilities;
2119
+ }
2120
+ }
2121
+ ArrayDateInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2122
+ ArrayDateInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: ArrayDateInputComponent, selector: "array-date-input", usesInheritance: true, ngImport: i0, template: "<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>{{metadata.displayName}}</b>\n </div>\n <div *ngIf=\"!isReadOnly\">\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 </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: i2$5.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i2$5.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { 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$2.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i2.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$2.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i4$2.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.MatLabel, selector: "mat-label" }, { type: i4$1.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.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$5.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.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$2.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i4$2.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i4$2.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i4$2.MatCellDef, selector: "[matCellDef]" }, { type: i4$2.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4$2.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i4$2.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }] });
2123
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateInputComponent, decorators: [{
2124
+ type: Component,
2125
+ args: [{ selector: 'array-date-input', template: "<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>{{metadata.displayName}}</b>\n </div>\n <div *ngIf=\"!isReadOnly\">\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 </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"] }]
2126
+ }] });
2127
+
2128
+ /* eslint-disable jsdoc/require-jsdoc */
2129
+ class ArrayDateTimeInputComponent extends ArrayTableComponent {
2130
+ constructor() {
2131
+ super(...arguments);
2132
+ this.DateUtilities = DateUtilities;
2133
+ }
2134
+ ngOnInit() {
2135
+ super.ngOnInit();
2136
+ this.time = DateUtilities.getTimeFromDate(this.entity[this.key]);
2137
+ this.timeDropdownValues = this.metadata.times;
2138
+ if (this.entity[this.key] != null) {
2139
+ this.dateTime = new Date(this.entity[this.key]);
2140
+ }
2141
+ }
2142
+ resetInput() {
2143
+ this.input = undefined;
2144
+ this.time = undefined;
1404
2145
  }
1405
2146
  /**
1406
- * Toggles all array-items in the table.
2147
+ * Adds a date time to the array.
1407
2148
  */
1408
- masterToggle() {
1409
- if (this.isAllSelected()) {
1410
- this.selection.clear();
2149
+ addDateTime() {
2150
+ if (this.input && this.time) {
2151
+ this.input = new Date(this.input);
2152
+ this.input.setHours(this.time.hours, this.time.minutes, 0, 0);
2153
+ this.add();
2154
+ }
2155
+ }
2156
+ }
2157
+ ArrayDateTimeInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateTimeInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2158
+ ArrayDateTimeInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: ArrayDateTimeInputComponent, selector: "array-date-time-input", usesInheritance: true, ngImport: i0, template: "<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>{{metadata.displayName}}</b>\n </div>\n <div *ngIf=\"!isReadOnly\">\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 metadata.times,\n input,\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 </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: i2$5.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i2$5.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { type: i2$2.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i3$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { 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$2.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i2.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$2.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i4$2.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.MatLabel, selector: "mat-label" }, { type: i4$1.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.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$5.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.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: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4$2.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i4$2.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i4$2.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i4$2.MatCellDef, selector: "[matCellDef]" }, { type: i4$2.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i4$2.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i4$2.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }] });
2159
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateTimeInputComponent, decorators: [{
2160
+ type: Component,
2161
+ 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 <div style=\"padding-bottom: 10px;\">\n <b>{{metadata.displayName}}</b>\n </div>\n <div *ngIf=\"!isReadOnly\">\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 metadata.times,\n input,\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 </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"] }]
2162
+ }] });
2163
+
2164
+ /* eslint-disable jsdoc/require-jsdoc */
2165
+ class ArrayDateRangeInputComponent extends ArrayTableComponent {
2166
+ constructor() {
2167
+ super(...arguments);
2168
+ this.DateUtilities = DateUtilities;
2169
+ }
2170
+ ngOnInit() {
2171
+ super.ngOnInit();
2172
+ this.input = {
2173
+ start: undefined,
2174
+ end: undefined,
2175
+ values: undefined
2176
+ };
2177
+ }
2178
+ /**
2179
+ * Adds a DateRange to the array.
2180
+ */
2181
+ addDateRange() {
2182
+ if (this.input && this.dateRangeStart && this.dateRangeEnd) {
2183
+ this.input.start = new Date(this.dateRangeStart);
2184
+ this.input.end = new Date(this.dateRangeEnd);
2185
+ const values = DateUtilities.getDatesBetween(this.input.start, this.input.end, this.metadata.filter);
2186
+ this.input.values = values.length ? values : undefined;
2187
+ this.add();
2188
+ }
2189
+ }
2190
+ resetInput() {
2191
+ this.input = undefined;
2192
+ this.dateRangeStart = undefined;
2193
+ this.dateRangeEnd = undefined;
2194
+ }
2195
+ }
2196
+ ArrayDateRangeInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateRangeInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2197
+ ArrayDateRangeInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: ArrayDateRangeInputComponent, selector: "array-date-range-input", usesInheritance: true, ngImport: i0, template: "<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>{{metadata.displayName}}</b>\n </div>\n <div *ngIf=\"!isReadOnly\">\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 </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: i2$5.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { type: i2$5.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i2$5.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { 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$2.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i2.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$2.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i4$2.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.MatLabel, selector: "mat-label" }, { type: i2$5.MatStartDate, selector: "input[matStartDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i4.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i2$5.MatEndDate, selector: "input[matEndDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i1$1.MatSuffix, selector: "[matSuffix]" }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }, { type: i4$2.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i4$2.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i4$2.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i4$2.MatCellDef, selector: "[matCellDef]" }, { type: i4$2.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4$2.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i4$2.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }] });
2198
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateRangeInputComponent, decorators: [{
2199
+ type: Component,
2200
+ 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 <div style=\"padding-bottom: 10px;\">\n <b>{{metadata.displayName}}</b>\n </div>\n <div *ngIf=\"!isReadOnly\">\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 </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"] }]
2201
+ }] });
2202
+
2203
+ /* eslint-disable jsdoc/require-jsdoc */
2204
+ class ArrayStringChipsInputComponent extends NgxMatEntityBaseInputComponent {
2205
+ constructor() {
2206
+ super(...arguments);
2207
+ this.chipsInput = '';
2208
+ }
2209
+ /**
2210
+ * Handles adding strings to the chipsArray.
2211
+ * Checks validation and also creates a new array if it is undefined.
2212
+ * This is needed because two things are validated: The array itself
2213
+ * and the contents of the array. And we need a way to display an
2214
+ * mat-error. As the only validation for the array is whether or not
2215
+ * it contains values, we can set it to undefined when the last element is removed
2216
+ * (removeStringChipArrayValue). That way we can use the "required" validator.
2217
+ *
2218
+ * @param event - The event that fires when a new chip is completed.
2219
+ */
2220
+ addStringChipArrayValue(event) {
2221
+ var _a, _b;
2222
+ const value = (event.value || '').trim();
2223
+ if (value) {
2224
+ if (this.metadata.minLength && value.length < this.metadata.minLength) {
2225
+ return;
2226
+ }
2227
+ if (this.metadata.maxLength && value.length > this.metadata.maxLength) {
2228
+ return;
2229
+ }
2230
+ if (this.metadata.regex && !value.match(this.metadata.regex)) {
2231
+ return;
2232
+ }
2233
+ this.propertyValue = (_a = this.propertyValue) !== null && _a !== void 0 ? _a : [];
2234
+ this.propertyValue.push(value);
2235
+ }
2236
+ (_b = event.chipInput) === null || _b === void 0 ? void 0 : _b.clear();
2237
+ }
2238
+ /**
2239
+ * Removes the given value from the array.
2240
+ * Sets the array to undefined if it is now empty.
2241
+ * This is needed because two things are validated: The array itself
2242
+ * and the contents of the array. And we need a way to display an
2243
+ * mat-error. As the only validation for the array is whether or not
2244
+ * it is empty, setting it to undefined here enables us to use the "required" validator.
2245
+ *
2246
+ * @param value - The string to remove from the array.
2247
+ */
2248
+ removeStringChipArrayValue(value) {
2249
+ var _a, _b;
2250
+ (_a = this.propertyValue) === null || _a === void 0 ? void 0 : _a.splice(this.propertyValue.indexOf(value), 1);
2251
+ this.propertyValue = ((_b = this.propertyValue) === null || _b === void 0 ? void 0 : _b.length) ? this.propertyValue : undefined;
2252
+ }
2253
+ /**
2254
+ * Handles adding a string to the array when an autocomplete value has been selected.
2255
+ *
2256
+ * @param event - The autocomplete selected event.
2257
+ * @param chipsInput - The element where the user typed the value.
2258
+ */
2259
+ selected(event, chipsInput) {
2260
+ var _a;
2261
+ const value = (event.option.viewValue || '').trim();
2262
+ if (this.metadata.minLength && value.length < this.metadata.minLength) {
2263
+ return;
2264
+ }
2265
+ if (this.metadata.maxLength && value.length > this.metadata.maxLength) {
2266
+ return;
2267
+ }
2268
+ if (this.metadata.regex && !value.match(this.metadata.regex)) {
2269
+ return;
2270
+ }
2271
+ this.propertyValue = (_a = this.propertyValue) !== null && _a !== void 0 ? _a : [];
2272
+ this.propertyValue.push(value);
2273
+ chipsInput.value = '';
2274
+ }
2275
+ }
2276
+ ArrayStringChipsInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayStringChipsInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2277
+ ArrayStringChipsInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: ArrayStringChipsInputComponent, selector: "array-string-chips-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n (ngModelChange)=\"emitChange()\"\n [(ngModel)]=\"propertyValue\" [name]=\"key.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n [disabled]=\"isReadOnly\"\n >\n <mat-chip *ngFor=\"let value of propertyValue\" (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$6.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2$6.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$6.MatChipRemove, selector: "[matChipRemove]" }, { type: i4$1.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$6.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { type: i4.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: i4.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i4.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i4.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
2278
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayStringChipsInputComponent, decorators: [{
2279
+ type: Component,
2280
+ 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)]=\"propertyValue\" [name]=\"key.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n [disabled]=\"isReadOnly\"\n >\n <mat-chip *ngFor=\"let value of propertyValue\" (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"] }]
2281
+ }] });
2282
+
2283
+ /* eslint-disable jsdoc/require-jsdoc */
2284
+ class ArrayStringAutocompleteChipsComponent extends NgxMatEntityBaseInputComponent {
2285
+ constructor() {
2286
+ super(...arguments);
2287
+ this.chipsInput = '';
2288
+ }
2289
+ ngOnInit() {
2290
+ super.ngOnInit();
2291
+ this.filteredAutocompleteStrings = LodashUtilities.cloneDeep(this.metadata.autocompleteValues);
2292
+ }
2293
+ /**
2294
+ * Handles adding strings to the chipsArray.
2295
+ * Checks validation and also creates a new array if it is undefined.
2296
+ * This is needed because two things are validated: The array itself
2297
+ * and the contents of the array. And we need a way to display an
2298
+ * mat-error. As the only validation for the array is whether or not
2299
+ * it contains values, we can set it to undefined when the last element is removed
2300
+ * (removeStringChipArrayValue). That way we can use the "required" validator.
2301
+ *
2302
+ * @param event - The event that fires when a new chip is completed.
2303
+ */
2304
+ addStringChipArrayValue(event) {
2305
+ var _a, _b;
2306
+ const value = (event.value || '').trim();
2307
+ if (value) {
2308
+ if (this.metadata.minLength && value.length < this.metadata.minLength) {
2309
+ return;
2310
+ }
2311
+ if (this.metadata.maxLength && value.length > this.metadata.maxLength) {
2312
+ return;
2313
+ }
2314
+ if (this.metadata.regex && !value.match(this.metadata.regex)) {
2315
+ return;
2316
+ }
2317
+ this.propertyValue = (_a = this.propertyValue) !== null && _a !== void 0 ? _a : [];
2318
+ this.propertyValue.push(value);
2319
+ }
2320
+ (_b = event.chipInput) === null || _b === void 0 ? void 0 : _b.clear();
2321
+ }
2322
+ /**
2323
+ * Removes the given value from the array.
2324
+ * Sets the array to undefined if it is now empty.
2325
+ * This is needed because two things are validated: The array itself
2326
+ * and the contents of the array. And we need a way to display an
2327
+ * mat-error. As the only validation for the array is whether or not
2328
+ * it is empty, setting it to undefined here enables us to use the "required" validator.
2329
+ *
2330
+ * @param value - The string to remove from the array.
2331
+ */
2332
+ removeStringChipArrayValue(value) {
2333
+ var _a, _b;
2334
+ (_a = this.propertyValue) === null || _a === void 0 ? void 0 : _a.splice(this.propertyValue.indexOf(value), 1);
2335
+ this.propertyValue = ((_b = this.propertyValue) === null || _b === void 0 ? void 0 : _b.length) ? this.propertyValue : undefined;
2336
+ }
2337
+ /**
2338
+ * Handles adding a string to the array when an autocomplete value has been selected.
2339
+ *
2340
+ * @param event - The autocomplete selected event.
2341
+ * @param chipsInput - The element where the user typed the value.
2342
+ */
2343
+ selected(event, chipsInput) {
2344
+ var _a;
2345
+ const value = (event.option.viewValue || '').trim();
2346
+ if (this.metadata.minLength && value.length < this.metadata.minLength) {
2347
+ return;
2348
+ }
2349
+ if (this.metadata.maxLength && value.length > this.metadata.maxLength) {
2350
+ return;
2351
+ }
2352
+ if (this.metadata.regex && !value.match(this.metadata.regex)) {
2353
+ return;
2354
+ }
2355
+ this.propertyValue = (_a = this.propertyValue) !== null && _a !== void 0 ? _a : [];
2356
+ this.propertyValue.push(value);
2357
+ chipsInput.value = '';
2358
+ }
2359
+ /**
2360
+ * Dynamically filters the Autocomplete options when the user inputs something.
2361
+ *
2362
+ * @param input - The input of the user.
2363
+ */
2364
+ filterAutocompleteStrings(input) {
2365
+ if (input != null) {
2366
+ const filterValue = input.toLowerCase();
2367
+ this.filteredAutocompleteStrings = this.metadata.autocompleteValues.filter(s => s.toLowerCase().includes(filterValue));
2368
+ }
2369
+ }
2370
+ }
2371
+ ArrayStringAutocompleteChipsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayStringAutocompleteChipsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2372
+ ArrayStringAutocompleteChipsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: ArrayStringAutocompleteChipsComponent, selector: "array-string-autocomplete-chips", usesInheritance: true, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n (ngModelChange)=\"emitChange()\"\n [(ngModel)]=\"propertyValue\" [name]=\"key.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n [disabled]=\"isReadOnly\"\n >\n <mat-chip *ngFor=\"let value of propertyValue\" (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$6.MatChipList, selector: "mat-chip-list", inputs: ["errorStateMatcher", "multiple", "compareWith", "value", "required", "placeholder", "disabled", "aria-orientation", "selectable", "tabIndex"], outputs: ["change", "valueChange"], exportAs: ["matChipList"] }, { type: i2$1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2$6.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$6.MatChipRemove, selector: "[matChipRemove]" }, { type: i4$1.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$6.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { type: i2$1.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", exportAs: ["matAutocompleteTrigger"] }, { type: i4.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: i4.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i4.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i4.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
2373
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayStringAutocompleteChipsComponent, decorators: [{
2374
+ type: Component,
2375
+ 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)]=\"propertyValue\" [name]=\"key.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n [disabled]=\"isReadOnly\"\n >\n <mat-chip *ngFor=\"let value of propertyValue\" (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"] }]
2376
+ }] });
2377
+
2378
+ /* eslint-disable jsdoc/require-jsdoc */
2379
+ class DateInputComponent extends NgxMatEntityBaseInputComponent {
2380
+ constructor() {
2381
+ super(...arguments);
2382
+ this.DateUtilities = DateUtilities;
2383
+ }
2384
+ }
2385
+ DateInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2386
+ DateInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: DateInputComponent, selector: "date-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n (ngModelChange)=\"emitChange()\"\n matInput\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadata.min ? metadata.min(propertyValue) : undefined\"\n [max]=\"metadata.max ? metadata.max(propertyValue) : undefined\"\n [matDatepickerFilter]=\"metadata.filter ?? DateUtilities.defaultDateFilter\"\n [disabled]=\"isReadOnly\"\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: i2$5.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i2$5.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i4$1.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.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$5.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.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"] }] });
2387
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateInputComponent, decorators: [{
2388
+ type: Component,
2389
+ 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)]=\"propertyValue\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadata.min ? metadata.min(propertyValue) : undefined\"\n [max]=\"metadata.max ? metadata.max(propertyValue) : undefined\"\n [matDatepickerFilter]=\"metadata.filter ?? DateUtilities.defaultDateFilter\"\n [disabled]=\"isReadOnly\"\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"] }]
2390
+ }] });
2391
+
2392
+ /* eslint-disable jsdoc/require-jsdoc */
2393
+ const EMPTY_DATERANGE = {
2394
+ start: undefined,
2395
+ end: undefined,
2396
+ values: undefined
2397
+ };
2398
+ class DateRangeInputComponent extends NgxMatEntityBaseInputComponent {
2399
+ constructor() {
2400
+ super(...arguments);
2401
+ this.defaultDateFilter = DateUtilities.defaultDateFilter;
2402
+ }
2403
+ ngOnInit() {
2404
+ var _a;
2405
+ super.ngOnInit();
2406
+ this.dateRange = (_a = LodashUtilities.cloneDeep(this.propertyValue)) !== null && _a !== void 0 ? _a : EMPTY_DATERANGE;
2407
+ this.dateRangeStart = new Date(this.dateRange.start);
2408
+ this.dateRangeEnd = new Date(this.dateRange.end);
2409
+ this.setDateRangeValues();
2410
+ }
2411
+ /**
2412
+ * Updates the date range values based on the start and end date.
2413
+ */
2414
+ setDateRangeValues() {
2415
+ if (this.dateRangeStart && this.dateRangeEnd) {
2416
+ this.dateRange.start = new Date(this.dateRangeStart);
2417
+ this.dateRange.end = new Date(this.dateRangeEnd);
2418
+ const values = DateUtilities.getDatesBetween(new Date(this.dateRange.start), new Date(this.dateRange.end), this.metadata.filter);
2419
+ this.dateRange.values = values.length ? values : undefined;
1411
2420
  }
1412
2421
  else {
1413
- this.dataSource.data.forEach(row => this.selection.select(row));
2422
+ this.dateRange.values = undefined;
2423
+ }
2424
+ this.propertyValue = this.dateRange;
2425
+ this.emitChange();
2426
+ }
2427
+ }
2428
+ DateRangeInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateRangeInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2429
+ DateRangeInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: DateRangeInputComponent, selector: "date-range-input", usesInheritance: true, 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\" [disabled]=\"isReadOnly\">\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: i2$5.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { type: i2$5.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i2$5.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }], directives: [{ type: i1$1.MatLabel, selector: "mat-label" }, { type: i2$5.MatStartDate, selector: "input[matStartDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i4.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: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i2$5.MatEndDate, selector: "input[matEndDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i1$1.MatSuffix, selector: "[matSuffix]" }, { type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.MatError, selector: "mat-error", inputs: ["id"] }] });
2430
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateRangeInputComponent, decorators: [{
2431
+ type: Component,
2432
+ 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\" [disabled]=\"isReadOnly\">\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"] }]
2433
+ }] });
2434
+
2435
+ /* eslint-disable jsdoc/require-jsdoc */
2436
+ class DateTimeInputComponent extends NgxMatEntityBaseInputComponent {
2437
+ constructor() {
2438
+ super(...arguments);
2439
+ this.DateUtilities = DateUtilities;
2440
+ this.defaultDateFilter = () => true;
2441
+ }
2442
+ ngOnInit() {
2443
+ super.ngOnInit();
2444
+ this.time = DateUtilities.getTimeFromDate(this.propertyValue);
2445
+ this.timeDropdownValues = this.metadata.times;
2446
+ if (this.propertyValue) {
2447
+ this.propertyValue = new Date(this.propertyValue);
1414
2448
  }
1415
2449
  }
1416
2450
  /**
1417
- * Checks if all array-items in the table have been selected.
1418
- * This is needed to display the "masterToggle"-checkbox correctly.
2451
+ * Checks if two times are equal. Is needed for the dropdown.
1419
2452
  *
1420
- * @returns Whether or not all array-items in the table have been selected.
2453
+ * @param time1 - The first time to compare.
2454
+ * @param time2 - The second time to compare.
2455
+ * @returns Whether or not the time objects are the same.
1421
2456
  */
1422
- isAllSelected() {
1423
- const numSelected = this.selection.selected.length;
1424
- const numRows = this.dataSource.data.length;
1425
- return numSelected === numRows;
2457
+ compareTimes(time1, time2) {
2458
+ if (time1 && time2 && time1.hours === time2.hours && time1.minutes === time2.minutes) {
2459
+ return true;
2460
+ }
2461
+ return false;
2462
+ }
2463
+ /**
2464
+ * Sets the time on a datetime property.
2465
+ */
2466
+ setTime() {
2467
+ var _a, _b;
2468
+ if (!this.propertyValue) {
2469
+ this.emitChange();
2470
+ return;
2471
+ }
2472
+ if (((_a = this.time) === null || _a === void 0 ? void 0 : _a.hours) != null && ((_b = this.time) === null || _b === void 0 ? void 0 : _b.minutes) != null) {
2473
+ this.propertyValue.setHours(this.time.hours, this.time.minutes, 0, 0);
2474
+ }
2475
+ else {
2476
+ this.propertyValue.setHours(0, 0, 0, 0);
2477
+ }
2478
+ this.emitChange();
2479
+ }
2480
+ }
2481
+ DateTimeInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateTimeInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2482
+ DateTimeInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: DateTimeInputComponent, selector: "date-time-input", usesInheritance: true, 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)]=\"propertyValue\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadata.minDate ? metadata.minDate(propertyValue) : undefined\"\n [max]=\"metadata.maxDate ? metadata.maxDate(propertyValue) : undefined\"\n [matDatepickerFilter]=\"metadata.filterDate ?? defaultDateFilter\"\n (dateInput)=\"setTime()\"\n [disabled]=\"isReadOnly\"\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 [disabled]=\"isReadOnly\"\n >\n <mat-option *ngFor=\"let validTime of DateUtilities.getValidTimesForDropdown(\n metadata.times,\n propertyValue,\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: i2$5.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i2$5.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { type: i2$2.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$1.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.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$5.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.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: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
2483
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateTimeInputComponent, decorators: [{
2484
+ type: Component,
2485
+ 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)]=\"propertyValue\"\n [name]=\"key.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadata.minDate ? metadata.minDate(propertyValue) : undefined\"\n [max]=\"metadata.maxDate ? metadata.maxDate(propertyValue) : undefined\"\n [matDatepickerFilter]=\"metadata.filterDate ?? defaultDateFilter\"\n (dateInput)=\"setTime()\"\n [disabled]=\"isReadOnly\"\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 [disabled]=\"isReadOnly\"\n >\n <mat-option *ngFor=\"let validTime of DateUtilities.getValidTimesForDropdown(\n metadata.times,\n propertyValue,\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"] }]
2486
+ }] });
2487
+
2488
+ /**
2489
+ * Adds drag and drop functionality to an element.
2490
+ */
2491
+ class DragDropDirective {
2492
+ constructor() {
2493
+ /**
2494
+ * Emits the dropped files to the parent.
2495
+ */
2496
+ this.files = new EventEmitter();
2497
+ }
2498
+ /**
2499
+ * Prevents the event default.
2500
+ *
2501
+ * @param evt - The Event when dragged files hover over the parent.
2502
+ */
2503
+ onDragOver(evt) {
2504
+ evt.preventDefault();
2505
+ evt.stopPropagation();
2506
+ }
2507
+ /**
2508
+ * Prevents the event default.
2509
+ *
2510
+ * @param evt - The Event when dragged files leave the parent.
2511
+ */
2512
+ onDragLeave(evt) {
2513
+ evt.preventDefault();
2514
+ evt.stopPropagation();
2515
+ }
2516
+ /**
2517
+ * Prevents the event default and emits the dropped files with the output.
2518
+ *
2519
+ * @param evt - The Event when files are dropped.
2520
+ */
2521
+ onDrop(evt) {
2522
+ evt.preventDefault();
2523
+ evt.stopPropagation();
2524
+ if (evt.dataTransfer && evt.dataTransfer.files.length > 0) {
2525
+ this.files.emit(Array.from(evt.dataTransfer.files));
2526
+ }
2527
+ }
2528
+ }
2529
+ DragDropDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DragDropDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2530
+ 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 });
2531
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DragDropDirective, decorators: [{
2532
+ type: Directive,
2533
+ args: [{
2534
+ // eslint-disable-next-line @angular-eslint/directive-selector
2535
+ selector: '[dragDrop]'
2536
+ }]
2537
+ }], ctorParameters: function () { return []; }, propDecorators: { files: [{
2538
+ type: Output
2539
+ }], onDragOver: [{
2540
+ type: HostListener,
2541
+ args: ['dragover', ['$event']]
2542
+ }], onDragLeave: [{
2543
+ type: HostListener,
2544
+ args: ['dragleave', ['$event']]
2545
+ }], onDrop: [{
2546
+ type: HostListener,
2547
+ args: ['drop', ['$event']]
2548
+ }] } });
2549
+
2550
+ class FileInputComponent {
2551
+ constructor(dialog) {
2552
+ this.dialog = dialog;
2553
+ this.FileUtilities = FileUtilities;
2554
+ this.fileDataChangeEvent = new EventEmitter();
2555
+ }
2556
+ ngOnInit() {
2557
+ var _a;
2558
+ return __awaiter(this, void 0, void 0, function* () {
2559
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.FILE_DEFAULT);
2560
+ if (this.metadata.multiple) {
2561
+ this.initMultiFile();
2562
+ }
2563
+ else {
2564
+ this.initSingleFile();
2565
+ }
2566
+ this.fileDataChangeEvent.emit((_a = this.singleFileData) !== null && _a !== void 0 ? _a : this.multiFileData);
2567
+ });
2568
+ }
2569
+ initMultiFile() {
2570
+ this.multiFileData = this.entity[this.key];
2571
+ if (this.multiFileData) {
2572
+ this.filenames = this.multiFileData.map(f => f.name);
2573
+ }
2574
+ }
2575
+ initSingleFile() {
2576
+ this.singleFileData = this.entity[this.key];
2577
+ if (this.singleFileData) {
2578
+ this.filenames = LodashUtilities.cloneDeep([this.singleFileData.name]);
2579
+ }
2580
+ }
2581
+ setFileFromInput(event) {
2582
+ var _a;
2583
+ return __awaiter(this, void 0, void 0, function* () {
2584
+ const files = (_a = event.target.files) !== null && _a !== void 0 ? _a : [];
2585
+ yield this.setFile(Array.from(files));
2586
+ });
2587
+ }
2588
+ setFile(files) {
2589
+ var _a;
2590
+ return __awaiter(this, void 0, void 0, function* () {
2591
+ // validation done inline
2592
+ if (files.find(f => !FileUtilities.isMimeTypeValid(f.type, this.metadata.allowedMimeTypes))) {
2593
+ this.dialog.open(NgxMatEntityConfirmDialogComponent, {
2594
+ data: this.metadata.mimeTypeErrorDialog,
2595
+ autoFocus: false,
2596
+ restoreFocus: false
2597
+ });
2598
+ this.resetFileInputs();
2599
+ return;
2600
+ }
2601
+ if (files.find(f => FileUtilities.transformToMegaBytes(f.size, 'B') > this.metadata.maxSize)) {
2602
+ this.dialog.open(NgxMatEntityConfirmDialogComponent, {
2603
+ data: this.metadata.maxSizeErrorDialog,
2604
+ autoFocus: false,
2605
+ restoreFocus: false
2606
+ });
2607
+ this.resetFileInputs();
2608
+ return;
2609
+ }
2610
+ let fileSizeTotal = 0;
2611
+ for (const file of files) {
2612
+ fileSizeTotal += file.size;
2613
+ }
2614
+ if (FileUtilities.transformToMegaBytes(fileSizeTotal, 'B') > this.metadata.maxSizeTotal) {
2615
+ this.dialog.open(NgxMatEntityConfirmDialogComponent, {
2616
+ data: this.metadata.maxSizeTotalErrorDialog,
2617
+ autoFocus: false,
2618
+ restoreFocus: false
2619
+ });
2620
+ this.resetFileInputs();
2621
+ return;
2622
+ }
2623
+ if (this.metadata.multiple) {
2624
+ yield this.setMultiFile(Array.from(files));
2625
+ }
2626
+ else {
2627
+ yield this.setSingleFile(files[0]);
2628
+ }
2629
+ this.fileDataChangeEvent.emit((_a = this.singleFileData) !== null && _a !== void 0 ? _a : this.multiFileData);
2630
+ });
2631
+ }
2632
+ resetFileInputs() {
2633
+ this.filenames = undefined;
2634
+ this.singleFileData = undefined;
2635
+ this.multiFileData = undefined;
2636
+ this.fileDataChangeEvent.emit();
2637
+ }
2638
+ setMultiFile(files) {
2639
+ return __awaiter(this, void 0, void 0, function* () {
2640
+ const data = [];
2641
+ for (const file of files) {
2642
+ const fileData = {
2643
+ file: file,
2644
+ name: file.name,
2645
+ type: file.type,
2646
+ size: file.size
2647
+ };
2648
+ data.push(fileData);
2649
+ }
2650
+ this.multiFileData = LodashUtilities.cloneDeep(data);
2651
+ this.filenames = this.multiFileData.map(f => f.name);
2652
+ });
2653
+ }
2654
+ setSingleFile(file) {
2655
+ return __awaiter(this, void 0, void 0, function* () {
2656
+ this.singleFileData = {
2657
+ file: file,
2658
+ name: file.name,
2659
+ type: file.type,
2660
+ size: file.size
2661
+ };
2662
+ this.filenames = LodashUtilities.cloneDeep([this.singleFileData.name]);
2663
+ });
2664
+ }
2665
+ removeFile(name) {
2666
+ var _a, _b, _c, _d, _e, _f;
2667
+ if (this.metadata.multiple) {
2668
+ (_a = this.filenames) === null || _a === void 0 ? void 0 : _a.splice(this.filenames.indexOf(name), 1);
2669
+ if (!((_b = this.filenames) === null || _b === void 0 ? void 0 : _b.length)) {
2670
+ this.filenames = undefined;
2671
+ }
2672
+ const fileDataToRemove = (_c = this.multiFileData) === null || _c === void 0 ? void 0 : _c.find(f => f.name === name);
2673
+ (_d = this.multiFileData) === null || _d === void 0 ? void 0 : _d.splice(this.multiFileData.indexOf(fileDataToRemove), 1);
2674
+ if (!((_e = this.multiFileData) === null || _e === void 0 ? void 0 : _e.length)) {
2675
+ this.multiFileData = undefined;
2676
+ }
2677
+ }
2678
+ else {
2679
+ this.filenames = undefined;
2680
+ this.singleFileData = undefined;
2681
+ }
2682
+ this.fileDataChangeEvent.emit((_f = this.singleFileData) !== null && _f !== void 0 ? _f : this.multiFileData);
2683
+ }
2684
+ }
2685
+ FileInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileInputComponent, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
2686
+ FileInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: FileInputComponent, selector: "file-input", inputs: { entity: "entity", key: "key", getValidationErrorMessage: "getValidationErrorMessage", isReadOnly: "isReadOnly" }, 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 [class.readOnly]=\"isReadOnly\" floatLabel=\"always\" (click)=\"!isReadOnly ? fileInput.click() : null\">\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 [disabled]=\"isReadOnly\"\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 [disabled]=\"isReadOnly\">\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 && !isReadOnly\" class=\"dropdown\" dragDrop (files)=\"setFile($event)\">\n <i class=\"fas fa-file-arrow-up\"></i>\n</div>", styles: ["mat-form-field{width:100%}.readOnly:hover,.readOnly:hover input:hover{cursor:default}input:hover,mat-form-field:hover{cursor:pointer}.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$6.MatChipList, selector: "mat-chip-list", inputs: ["errorStateMatcher", "multiple", "compareWith", "value", "required", "placeholder", "disabled", "aria-orientation", "selectable", "tabIndex"], outputs: ["change", "valueChange"], exportAs: ["matChipList"] }, { 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$1.MatLabel, selector: "mat-label" }, { type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2$6.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$6.MatChipRemove, selector: "[matChipRemove]" }, { type: i2$6.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: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: DragDropDirective, selector: "[dragDrop]", outputs: ["files"] }] });
2687
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileInputComponent, decorators: [{
2688
+ type: Component,
2689
+ 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 [class.readOnly]=\"isReadOnly\" floatLabel=\"always\" (click)=\"!isReadOnly ? fileInput.click() : null\">\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 [disabled]=\"isReadOnly\"\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 [disabled]=\"isReadOnly\">\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 && !isReadOnly\" class=\"dropdown\" dragDrop (files)=\"setFile($event)\">\n <i class=\"fas fa-file-arrow-up\"></i>\n</div>", styles: ["mat-form-field{width:100%}.readOnly:hover,.readOnly:hover input:hover{cursor:default}input:hover,mat-form-field:hover{cursor:pointer}.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"] }]
2690
+ }], ctorParameters: function () { return [{ type: i1.MatDialog }]; }, propDecorators: { entity: [{
2691
+ type: Input
2692
+ }], key: [{
2693
+ type: Input
2694
+ }], getValidationErrorMessage: [{
2695
+ type: Input
2696
+ }], isReadOnly: [{
2697
+ type: Input
2698
+ }], fileDataChangeEvent: [{
2699
+ type: Output
2700
+ }] } });
2701
+
2702
+ class FileDefaultInputComponent extends NgxMatEntityBaseInputComponent {
2703
+ constructor() {
2704
+ super(...arguments);
2705
+ this.FileUtilities = FileUtilities;
2706
+ }
2707
+ refreshFileData(fileData) {
2708
+ return __awaiter(this, void 0, void 0, function* () {
2709
+ this.propertyValue = fileData;
2710
+ this.emitChange();
2711
+ });
2712
+ }
2713
+ }
2714
+ FileDefaultInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileDefaultInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2715
+ FileDefaultInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: FileDefaultInputComponent, selector: "file-default-input", usesInheritance: true, ngImport: i0, template: "<div [class.file-input]=\"metadata.dragAndDrop\" [class.mat-elevation-z8]=\"metadata.dragAndDrop\">\n <file-input\n (fileDataChangeEvent)=\"refreshFileData($event)\"\n [entity]=\"entity\"\n [key]=\"key\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [isReadOnly]=\"isReadOnly\"\n >\n </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", "isReadOnly"], outputs: ["fileDataChangeEvent"] }] });
2716
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileDefaultInputComponent, decorators: [{
2717
+ type: Component,
2718
+ args: [{ selector: 'file-default-input', template: "<div [class.file-input]=\"metadata.dragAndDrop\" [class.mat-elevation-z8]=\"metadata.dragAndDrop\">\n <file-input\n (fileDataChangeEvent)=\"refreshFileData($event)\"\n [entity]=\"entity\"\n [key]=\"key\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [isReadOnly]=\"isReadOnly\"\n >\n </file-input>\n</div>", styles: [".file-input{margin-top:15px;margin-bottom:15px;padding:15px;border-radius:5px}\n"] }]
2719
+ }] });
2720
+
2721
+ // eslint-disable-next-line max-len
2722
+ 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=';
2723
+
2724
+ class FileImageInputComponent extends NgxMatEntityBaseInputComponent {
2725
+ constructor() {
2726
+ super(...arguments);
2727
+ this.FileUtilities = FileUtilities;
2728
+ this.imageIndex = 0;
2729
+ this.placeHolder = placeholder;
2730
+ }
2731
+ setSinglePreviewImage() {
2732
+ return __awaiter(this, void 0, void 0, function* () {
2733
+ if (this.propertyValue) {
2734
+ this.propertyValue = yield FileUtilities.getFileData(this.propertyValue);
2735
+ this.singlePreviewImage = yield FileUtilities.getDataURLFromFile(this.propertyValue.file);
2736
+ }
2737
+ else {
2738
+ this.singlePreviewImage = undefined;
2739
+ }
2740
+ });
2741
+ }
2742
+ setMultiPreviewImages(index) {
2743
+ return __awaiter(this, void 0, void 0, function* () {
2744
+ const multiFileData = this.propertyValue;
2745
+ const previewImages = [];
2746
+ if (multiFileData === null || multiFileData === void 0 ? void 0 : multiFileData.length) {
2747
+ for (let i = 0; i < multiFileData.length; i++) {
2748
+ if (i === index) {
2749
+ multiFileData[index] = yield FileUtilities.getFileData(multiFileData[index]);
2750
+ previewImages.push(yield FileUtilities.getDataURLFromFile(multiFileData[index].file));
2751
+ }
2752
+ else {
2753
+ previewImages.push('empty');
2754
+ }
2755
+ }
2756
+ }
2757
+ this.multiPreviewImages = previewImages;
2758
+ });
2759
+ }
2760
+ refreshFileData(fileData) {
2761
+ return __awaiter(this, void 0, void 0, function* () {
2762
+ this.propertyValue = fileData;
2763
+ this.emitChange();
2764
+ if (this.metadata.multiple) {
2765
+ fileData = fileData;
2766
+ if (!(fileData === null || fileData === void 0 ? void 0 : fileData[this.imageIndex])) {
2767
+ this.imageIndex = 0;
2768
+ }
2769
+ yield this.setMultiPreviewImages(this.imageIndex);
2770
+ }
2771
+ else {
2772
+ yield this.setSinglePreviewImage();
2773
+ }
2774
+ });
2775
+ }
2776
+ prev() {
2777
+ return __awaiter(this, void 0, void 0, function* () {
2778
+ if (this.imageIndex <= 0) {
2779
+ return;
2780
+ }
2781
+ yield this.setMultiPreviewImages(this.imageIndex - 1);
2782
+ this.imageIndex--;
2783
+ });
2784
+ }
2785
+ next() {
2786
+ var _a;
2787
+ return __awaiter(this, void 0, void 0, function* () {
2788
+ if (!((_a = this.multiPreviewImages) === null || _a === void 0 ? void 0 : _a.length)) {
2789
+ return;
2790
+ }
2791
+ if (this.imageIndex === (this.multiPreviewImages.length - 1)) {
2792
+ return;
2793
+ }
2794
+ yield this.setMultiPreviewImages(this.imageIndex + 1);
2795
+ this.imageIndex++;
2796
+ });
2797
+ }
2798
+ setIndex(index) {
2799
+ return __awaiter(this, void 0, void 0, function* () {
2800
+ yield this.setMultiPreviewImages(index);
2801
+ this.imageIndex = index;
2802
+ });
2803
+ }
2804
+ }
2805
+ FileImageInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileImageInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2806
+ FileImageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: FileImageInputComponent, selector: "file-image-input", usesInheritance: true, ngImport: i0, template: "<div *ngIf=\"!metadata.dragAndDrop && !metadata.preview\">\n <file-input\n (fileDataChangeEvent)=\"refreshFileData($event)\"\n [entity]=\"entity\"\n [key]=\"key\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [isReadOnly]=\"isReadOnly\"\n >\n </file-input>\n</div>\n\n<div *ngIf=\"metadata.dragAndDrop || metadata.preview\" class=\"file-input mat-elevation-z8\">\n <file-input\n (fileDataChangeEvent)=\"refreshFileData($event)\"\n [entity]=\"entity\"\n [key]=\"key\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [isReadOnly]=\"isReadOnly\"\n >\n </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()\"\n [class.disabled]=\"!multiPreviewImages || !multiPreviewImages.length || imageIndex === (multiPreviewImages.length - 1)\"\n class=\"next-button fa-solid fa-angle-right\"\n >\n </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:#00000042}.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", "isReadOnly"], outputs: ["fileDataChangeEvent"] }, { 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: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
2807
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileImageInputComponent, decorators: [{
2808
+ type: Component,
2809
+ args: [{ selector: 'file-image-input', template: "<div *ngIf=\"!metadata.dragAndDrop && !metadata.preview\">\n <file-input\n (fileDataChangeEvent)=\"refreshFileData($event)\"\n [entity]=\"entity\"\n [key]=\"key\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [isReadOnly]=\"isReadOnly\"\n >\n </file-input>\n</div>\n\n<div *ngIf=\"metadata.dragAndDrop || metadata.preview\" class=\"file-input mat-elevation-z8\">\n <file-input\n (fileDataChangeEvent)=\"refreshFileData($event)\"\n [entity]=\"entity\"\n [key]=\"key\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [isReadOnly]=\"isReadOnly\"\n >\n </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()\"\n [class.disabled]=\"!multiPreviewImages || !multiPreviewImages.length || imageIndex === (multiPreviewImages.length - 1)\"\n class=\"next-button fa-solid fa-angle-right\"\n >\n </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:#00000042}.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"] }]
2810
+ }] });
2811
+
2812
+ /* eslint-disable jsdoc/require-jsdoc */
2813
+ class CustomInputComponent extends NgxMatEntityBaseInputComponent {
2814
+ constructor(viewContainerRef) {
2815
+ super();
2816
+ this.viewContainerRef = viewContainerRef;
2817
+ }
2818
+ ngOnInit() {
2819
+ super.ngOnInit();
2820
+ this.component = this.viewContainerRef.createComponent(this.metadata.component);
2821
+ this.component.instance.entity = this.entity;
2822
+ this.component.instance.key = this.key;
2823
+ this.component.instance.getValidationErrorMessage = this.getValidationErrorMessage;
2824
+ this.component.instance.inputChangeEvent.subscribe(this.inputChangeEvent);
2825
+ this.component.instance.isReadOnly = this.isReadOnly;
2826
+ }
2827
+ }
2828
+ CustomInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: CustomInputComponent, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component });
2829
+ CustomInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: CustomInputComponent, selector: "custom-input", usesInheritance: true, ngImport: i0, template: "", styles: [""] });
2830
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: CustomInputComponent, decorators: [{
2831
+ type: Component,
2832
+ args: [{ selector: 'custom-input', template: "", styles: [""] }]
2833
+ }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }]; } });
2834
+
2835
+ /**
2836
+ * The default input component. It gets the metadata of the property from the given @Input "entity" and @Input "propertyKey"
2837
+ * and displays the input field accordingly.
2838
+ *
2839
+ * You can also define a method that generates error-messages and if the input should be hidden when its metadata says
2840
+ * that it should be omitted for creating or updating.
2841
+ * The last part being mostly relevant if you want to use this component inside an ngFor.
2842
+ */
2843
+ class NgxMatEntityInputComponent {
2844
+ constructor(dialog) {
2845
+ this.dialog = dialog;
2846
+ this.inputChangeEvent = new EventEmitter();
2847
+ this.selection = new SelectionModel(true, []);
2848
+ this.isArrayItemValid = false;
2849
+ this.isDialogArrayItemValid = false;
2850
+ this.DecoratorTypes = DecoratorTypes;
2851
+ this.EntityUtilities = EntityUtilities;
2852
+ this.DateUtilities = DateUtilities;
2853
+ }
2854
+ /**
2855
+ * This is needed for the inputs to work inside an ngFor.
2856
+ *
2857
+ * @param index - The index of the element in the ngFor.
2858
+ * @returns The index.
2859
+ */
2860
+ trackByFn(index) {
2861
+ return index;
2862
+ }
2863
+ ngOnInit() {
2864
+ var _a, _b;
2865
+ if (!this.entity) {
2866
+ throw new Error('Missing required Input data "entity"');
2867
+ }
2868
+ this.internalEntity = this.entity;
2869
+ if (this.propertyKey == null) {
2870
+ throw new Error('Missing required Input data "propertyKey"');
2871
+ }
2872
+ this.internalPropertyKey = this.propertyKey;
2873
+ this.internalGetValidationErrorMessage = (_a = this.getValidationErrorMessage) !== null && _a !== void 0 ? _a : getValidationErrorMessage;
2874
+ this.internalIsReadOnly = (_b = this.isReadOnly) !== null && _b !== void 0 ? _b : false;
2875
+ this.type = EntityUtilities.getPropertyType(this.internalEntity, this.internalPropertyKey);
2876
+ this.metadata = EntityUtilities.getPropertyMetadata(this.internalEntity, this.internalPropertyKey, this.type);
2877
+ if (this.type === DecoratorTypes.OBJECT) {
2878
+ this.initObjectInput();
2879
+ }
2880
+ if (this.type === DecoratorTypes.ARRAY) {
2881
+ this.initEntityArray();
2882
+ }
2883
+ }
2884
+ initEntityArray() {
2885
+ var _a;
2886
+ this.metadataEntityArray = this.metadata;
2887
+ if (this.internalEntity[this.internalPropertyKey] == null) {
2888
+ this.internalEntity[this.internalPropertyKey] = [];
2889
+ }
2890
+ this.entityArrayValues = this.internalEntity[this.internalPropertyKey];
2891
+ if (!this.metadataEntityArray.createInline && !this.metadataEntityArray.createDialogData) {
2892
+ this.metadataEntityArray.createDialogData = {
2893
+ title: 'Add'
2894
+ };
2895
+ }
2896
+ const givenDisplayColumns = this.metadataEntityArray.displayColumns.map((v) => v.displayName);
2897
+ if (givenDisplayColumns.find(s => s === 'select')) {
2898
+ throw new Error(`The name "select" for a display column is reserved.
2899
+ Please choose a different name.`);
2900
+ }
2901
+ this.displayedColumns = this.internalIsReadOnly ? givenDisplayColumns : ['select'].concat(givenDisplayColumns);
2902
+ this.dataSource = new MatTableDataSource();
2903
+ this.dataSource.data = this.entityArrayValues;
2904
+ this.arrayItem = new this.metadataEntityArray.EntityClass();
2905
+ this.arrayItemInlineRows = EntityUtilities.getEntityRows(this.arrayItem, (_a = this.hideOmitForCreate) !== null && _a !== void 0 ? _a : true, this.hideOmitForEdit);
2906
+ this.arrayItemPriorChanges = LodashUtilities.cloneDeep(this.arrayItem);
2907
+ this.dialogInputData = {
2908
+ entity: this.arrayItem,
2909
+ createDialogData: this.metadataEntityArray.createDialogData,
2910
+ getValidationErrorMessage: this.getValidationErrorMessage
2911
+ };
2912
+ this.dialogData = new AddArrayItemDialogDataBuilder(this.dialogInputData).getResult();
2913
+ this.arrayItemDialogRows = EntityUtilities.getEntityRows(this.dialogData.entity, true);
2914
+ }
2915
+ initObjectInput() {
2916
+ this.metadataDefaultObject = this.metadata;
2917
+ this.objectProperty = this.internalEntity[this.internalPropertyKey];
2918
+ this.objectPropertyRows = EntityUtilities.getEntityRows(this.objectProperty, this.hideOmitForCreate, this.hideOmitForEdit);
2919
+ }
2920
+ /**
2921
+ * Checks if the arrayItem is valid.
2922
+ */
2923
+ checkIsArrayItemValid() {
2924
+ this.isArrayItemValid = EntityUtilities.isEntityValid(this.arrayItem, 'create');
2925
+ }
2926
+ /**
2927
+ * Checks if the arrayItem inside the dialog is valid.
2928
+ */
2929
+ checkIsDialogArrayItemValid() {
2930
+ this.isDialogArrayItemValid = EntityUtilities.isEntityValid(this.dialogData.entity, 'create');
2931
+ }
2932
+ /**
2933
+ * Emits that a the value has been changed.
2934
+ */
2935
+ emitChange() {
2936
+ this.inputChangeEvent.emit();
2937
+ }
2938
+ /**
2939
+ * Tries to add an item to the entity array.
2940
+ * Does this either inline if the "createInline"-metadata is set to true
2941
+ * or in a separate dialog if it is set to false.
2942
+ */
2943
+ addEntity() {
2944
+ return __awaiter(this, void 0, void 0, function* () {
2945
+ if (this.metadataEntityArray.createInline) {
2946
+ if (!this.metadataEntityArray.allowDuplicates) {
2947
+ for (const v of this.entityArrayValues) {
2948
+ if ((yield EntityUtilities.isEqual(this.arrayItem, v, this.metadata, this.metadataEntityArray.itemType))) {
2949
+ this.dialog.open(NgxMatEntityConfirmDialogComponent, {
2950
+ data: this.metadataEntityArray.duplicatesErrorDialog,
2951
+ autoFocus: false,
2952
+ restoreFocus: false
2953
+ });
2954
+ return;
2955
+ }
2956
+ }
2957
+ }
2958
+ this.entityArrayValues.push(LodashUtilities.cloneDeep(this.arrayItem));
2959
+ this.dataSource.data = this.entityArrayValues;
2960
+ EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
2961
+ this.checkIsArrayItemValid();
2962
+ this.emitChange();
2963
+ }
2964
+ else {
2965
+ this.addArrayItemDialogRef = this.dialog.open(this.addArrayItemDialog, {
2966
+ data: this.dialogData,
2967
+ autoFocus: false,
2968
+ restoreFocus: false
2969
+ });
2970
+ }
2971
+ });
2972
+ }
2973
+ /**
2974
+ * Adds the array item defined in the dialog.
2975
+ */
2976
+ addArrayItem() {
2977
+ this.addArrayItemDialogRef.close();
2978
+ this.entityArrayValues.push(LodashUtilities.cloneDeep(this.arrayItem));
2979
+ this.dataSource.data = this.entityArrayValues;
2980
+ EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
2981
+ this.checkIsArrayItemValid();
2982
+ this.emitChange();
1426
2983
  }
1427
2984
  /**
1428
- * Handles adding strings to the chipsArray.
1429
- * Checks validation and also creates a new array if it is undefined.
1430
- * This is needed because two things are validated: The array itself
1431
- * and the contents of the array. And we need a way to display an
1432
- * mat-error. As the only validation for the array is whether or not
1433
- * it contains values, we can set it to undefined when the last element is removed
1434
- * (removeStringChipArrayValue). That way we can use the "required" validator.
1435
- *
1436
- * @param event - The event that fires when a new chip is completed.
2985
+ * Cancels adding the array item defined in the dialog.
1437
2986
  */
1438
- addStringChipArrayValue(event) {
1439
- const value = (event.value || '').trim();
1440
- if (value) {
1441
- if (this.metadataStringChipsArray.minLength && value.length < this.metadataStringChipsArray.minLength) {
1442
- return;
1443
- }
1444
- if (this.metadataStringChipsArray.maxLength && value.length > this.metadataStringChipsArray.maxLength) {
1445
- return;
1446
- }
1447
- if (this.metadataStringChipsArray.regex && !value.match(this.metadataStringChipsArray.regex)) {
1448
- return;
1449
- }
1450
- if (!this.stringChipsArrayValues) {
1451
- if (!this.entity[this.propertyKey]) {
1452
- this.entity[this.propertyKey] = [];
1453
- }
1454
- this.stringChipsArrayValues = this.entity[this.propertyKey];
1455
- }
1456
- this.stringChipsArrayValues.push(value);
1457
- }
1458
- event.chipInput.clear();
2987
+ cancelAddArrayItem() {
2988
+ this.addArrayItemDialogRef.close();
2989
+ EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
2990
+ this.emitChange();
1459
2991
  }
1460
2992
  /**
1461
- * Removes the given value from the array.
1462
- * Sets the array to undefined if it is now empty.
1463
- * This is needed because two things are validated: The array itself
1464
- * and the contents of the array. And we need a way to display an
1465
- * mat-error. As the only validation for the array is whether or not
1466
- * it is empty, setting it to undefined here enables us to use the "required" validator.
2993
+ * Removes all selected entries from the entity array.
1467
2994
  *
1468
- * @param value - The string to remove from the array.
2995
+ * @param selection - The selection containing the items to remove.
2996
+ * @param values - The values of the dataSource.
2997
+ * @param dataSource - The dataSource.
1469
2998
  */
1470
- removeStringChipArrayValue(value) {
1471
- this.stringChipsArrayValues.splice(this.stringChipsArrayValues.indexOf(value), 1);
1472
- if (!this.stringChipsArrayValues.length) {
1473
- this.entity[this.propertyKey] = undefined;
1474
- this.stringChipsArrayValues = this.entity[this.propertyKey];
1475
- }
2999
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3000
+ remove(selection, values, dataSource) {
3001
+ selection.selected.forEach(s => {
3002
+ values.splice(values.indexOf(s), 1);
3003
+ });
3004
+ dataSource.data = values;
3005
+ selection.clear();
3006
+ this.emitChange();
1476
3007
  }
1477
3008
  /**
1478
- * Handles adding a string to the array when an autocomplete value has been selected.
3009
+ * Toggles all array-items in the table.
1479
3010
  *
1480
- * @param event - The autocomplete selected event.
1481
- * @param chipsInput - The element where the user typed the value.
3011
+ * @param selection - The selection to toggle.
3012
+ * @param dataSource - The dataSource of the selection.
1482
3013
  */
1483
- selected(event, chipsInput) {
1484
- const value = (event.option.viewValue || '').trim();
1485
- if (this.metadataStringChipsArray.minLength && value.length < this.metadataStringChipsArray.minLength) {
1486
- return;
3014
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3015
+ masterToggle(selection, dataSource) {
3016
+ if (this.isAllSelected(selection, dataSource)) {
3017
+ selection.clear();
1487
3018
  }
1488
- if (this.metadataStringChipsArray.maxLength && value.length > this.metadataStringChipsArray.maxLength) {
1489
- return;
1490
- }
1491
- if (this.metadataStringChipsArray.regex && !value.match(this.metadataStringChipsArray.regex)) {
1492
- return;
1493
- }
1494
- if (!this.stringChipsArrayValues) {
1495
- if (!this.entity[this.propertyKey]) {
1496
- this.entity[this.propertyKey] = [];
1497
- }
1498
- this.stringChipsArrayValues = this.entity[this.propertyKey];
3019
+ else {
3020
+ dataSource.data.forEach(row => selection.select(row));
1499
3021
  }
1500
- this.stringChipsArrayValues.push(value);
1501
- chipsInput.value = '';
1502
3022
  }
1503
3023
  /**
1504
- * Dynamically filters the Autocomplete options when the user inputs something.
3024
+ * Checks if all array-items in the table have been selected.
3025
+ * This is needed to display the "masterToggle"-checkbox correctly.
1505
3026
  *
1506
- * @param input - The input of the user.
3027
+ * @param selection - The selection to check.
3028
+ * @param dataSource - The dataSource of the selection.
3029
+ * @returns Whether or not all array-items in the table have been selected.
1507
3030
  */
1508
- filterAutocompleteStrings(input) {
1509
- if (input) {
1510
- const filterValue = input.toLowerCase();
1511
- this.filteredAutocompleteStrings = this.autocompleteStrings.filter(s => s.toLowerCase().includes(filterValue));
1512
- }
3031
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3032
+ isAllSelected(selection, dataSource) {
3033
+ const numSelected = selection.selected.length;
3034
+ const numRows = dataSource.data.length;
3035
+ return numSelected === numRows;
1513
3036
  }
1514
3037
  }
1515
3038
  NgxMatEntityInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputComponent, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
1516
- 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]" }] });
3039
+ 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", isReadOnly: "isReadOnly" }, 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\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </string-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.STRING_TEXTBOX\">\n <string-textbox-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </string-textbox-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.STRING_AUTOCOMPLETE\">\n <string-autocomplete-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </string-autocomplete-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.STRING_DROPDOWN\">\n <string-dropdown-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </string-dropdown-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.STRING_PASSWORD\">\n <string-password-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </string-password-input>\n </div>\n\n <!-------------------------------------------->\n <!-----------------Booleans------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_CHECKBOX\">\n <boolean-checkbox-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </boolean-checkbox-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_TOGGLE\">\n <boolean-toggle-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </boolean-toggle-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_DROPDOWN\">\n <boolean-dropdown-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </boolean-dropdown-input>\n </div>\n\n <!-------------------------------------------->\n <!------------------Numbers------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER\">\n <number-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </number-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER_DROPDOWN\">\n <number-dropdown-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </number-dropdown-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER_SLIDER\">\n <number-slider-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </number-slider-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 [isReadOnly]=\"internalIsReadOnly\"\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 && !internalIsReadOnly\">\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\" *ngIf=\"!internalIsReadOnly\">\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\" *ngIf=\"!internalIsReadOnly\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox\n [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle(selection, dataSource) : null\"\n [checked]=\"selection.hasValue() && isAllSelected(selection, dataSource)\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected(selection, dataSource)\">\n </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\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </array-date-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_DATE_TIME\">\n <array-date-time-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </array-date-time-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_DATE_RANGE\">\n <array-date-range-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </array-date-range-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_CHIPS\">\n <array-string-chips-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </array-string-chips-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS\">\n <array-string-autocomplete-chips\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </array-string-autocomplete-chips>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Dates-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.DATE\">\n <date-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </date-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.DATE_RANGE\">\n <date-range-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </date-range-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.DATE_TIME\">\n <date-time-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </date-time-input>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Files-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.FILE_DEFAULT\">\n <file-default-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </file-default-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.FILE_IMAGE\">\n <file-image-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </file-image-input>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Custom------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.CUSTOM\">\n <custom-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </custom-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%}::ng-deep .mat-form-field.mat-form-field-disabled .mat-form-field-wrapper .mat-form-field-underline{background-image:none;height:1px;background-color:#0000006b}::ng-deep .mat-form-field.mat-form-field-disabled .mat-chip.mat-standard-chip.mat-chip-disabled{opacity:1}::ng-deep .mat-form-field.mat-form-field-disabled .mat-chip.mat-standard-chip.mat-chip-disabled button{opacity:.2}::ng-deep .mat-form-field.mat-form-field-disabled .mat-select-disabled .mat-select-value{color:#000}::ng-deep .mat-form-field.mat-form-field-disabled .mat-date-range-input-inner:disabled{color:#000}::ng-deep .mat-form-field .mat-slide-toggle.mat-disabled{opacity:1}::ng-deep .mat-input-element:disabled{color:#000}.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" }, { type: StringTextboxInputComponent, selector: "string-textbox-input" }, { type: StringAutocompleteInputComponent, selector: "string-autocomplete-input" }, { type: StringDropdownInputComponent, selector: "string-dropdown-input" }, { type: StringPasswordInputComponent, selector: "string-password-input" }, { type: BooleanCheckboxInputComponent, selector: "boolean-checkbox-input" }, { type: BooleanToggleInputComponent, selector: "boolean-toggle-input" }, { type: BooleanDropdownInputComponent, selector: "boolean-dropdown-input" }, { type: NumberInputComponent, selector: "number-input" }, { type: NumberDropdownInputComponent, selector: "number-dropdown-input" }, { type: NumberSliderInputComponent, selector: "number-slider-input" }, { type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit", "isReadOnly"], outputs: ["inputChangeEvent"] }, { 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$2.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i2.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$2.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i4$2.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { type: ArrayDateInputComponent, selector: "array-date-input" }, { type: ArrayDateTimeInputComponent, selector: "array-date-time-input" }, { type: ArrayDateRangeInputComponent, selector: "array-date-range-input" }, { type: ArrayStringChipsInputComponent, selector: "array-string-chips-input" }, { type: ArrayStringAutocompleteChipsComponent, selector: "array-string-autocomplete-chips" }, { type: DateInputComponent, selector: "date-input" }, { type: DateRangeInputComponent, selector: "date-range-input" }, { type: DateTimeInputComponent, selector: "date-time-input" }, { type: FileDefaultInputComponent, selector: "file-default-input" }, { type: FileImageInputComponent, selector: "file-image-input" }, { type: CustomInputComponent, selector: "custom-input" }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i6.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4$2.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i4$2.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i4$2.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i4$2.MatCellDef, selector: "[matCellDef]" }, { type: i4$2.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i4$2.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i4$2.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { type: i6.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: i4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i4.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]" }] });
1517
3040
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputComponent, decorators: [{
1518
3041
  type: Component,
1519
- 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"] }]
3042
+ 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\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </string-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.STRING_TEXTBOX\">\n <string-textbox-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </string-textbox-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.STRING_AUTOCOMPLETE\">\n <string-autocomplete-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </string-autocomplete-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.STRING_DROPDOWN\">\n <string-dropdown-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </string-dropdown-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.STRING_PASSWORD\">\n <string-password-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </string-password-input>\n </div>\n\n <!-------------------------------------------->\n <!-----------------Booleans------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_CHECKBOX\">\n <boolean-checkbox-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </boolean-checkbox-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_TOGGLE\">\n <boolean-toggle-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </boolean-toggle-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_DROPDOWN\">\n <boolean-dropdown-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </boolean-dropdown-input>\n </div>\n\n <!-------------------------------------------->\n <!------------------Numbers------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER\">\n <number-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </number-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER_DROPDOWN\">\n <number-dropdown-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </number-dropdown-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER_SLIDER\">\n <number-slider-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </number-slider-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 [isReadOnly]=\"internalIsReadOnly\"\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 && !internalIsReadOnly\">\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\" *ngIf=\"!internalIsReadOnly\">\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\" *ngIf=\"!internalIsReadOnly\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox\n [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle(selection, dataSource) : null\"\n [checked]=\"selection.hasValue() && isAllSelected(selection, dataSource)\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected(selection, dataSource)\">\n </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\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </array-date-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_DATE_TIME\">\n <array-date-time-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </array-date-time-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_DATE_RANGE\">\n <array-date-range-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </array-date-range-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_CHIPS\">\n <array-string-chips-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </array-string-chips-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS\">\n <array-string-autocomplete-chips\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </array-string-autocomplete-chips>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Dates-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.DATE\">\n <date-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </date-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.DATE_RANGE\">\n <date-range-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </date-range-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.DATE_TIME\">\n <date-time-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </date-time-input>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Files-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.FILE_DEFAULT\">\n <file-default-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </file-default-input>\n </div>\n <div *ngSwitchCase=\"DecoratorTypes.FILE_IMAGE\">\n <file-image-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </file-image-input>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Custom------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.CUSTOM\">\n <custom-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </custom-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%}::ng-deep .mat-form-field.mat-form-field-disabled .mat-form-field-wrapper .mat-form-field-underline{background-image:none;height:1px;background-color:#0000006b}::ng-deep .mat-form-field.mat-form-field-disabled .mat-chip.mat-standard-chip.mat-chip-disabled{opacity:1}::ng-deep .mat-form-field.mat-form-field-disabled .mat-chip.mat-standard-chip.mat-chip-disabled button{opacity:.2}::ng-deep .mat-form-field.mat-form-field-disabled .mat-select-disabled .mat-select-value{color:#000}::ng-deep .mat-form-field.mat-form-field-disabled .mat-date-range-input-inner:disabled{color:#000}::ng-deep .mat-form-field .mat-slide-toggle.mat-disabled{opacity:1}::ng-deep .mat-input-element:disabled{color:#000}.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"] }]
1520
3043
  }], ctorParameters: function () { return [{ type: i1.MatDialog }]; }, propDecorators: { entity: [{
1521
3044
  type: Input
1522
3045
  }], propertyKey: [{
@@ -1527,6 +3050,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1527
3050
  type: Input
1528
3051
  }], hideOmitForEdit: [{
1529
3052
  type: Input
3053
+ }], isReadOnly: [{
3054
+ type: Input
3055
+ }], inputChangeEvent: [{
3056
+ type: Output
1530
3057
  }], addArrayItemDialog: [{
1531
3058
  type: ViewChild,
1532
3059
  args: ['addArrayItemDialog']
@@ -1535,7 +3062,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1535
3062
  class NgxMatEntityInputModule {
1536
3063
  }
1537
3064
  NgxMatEntityInputModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1538
- NgxMatEntityInputModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputModule, declarations: [NgxMatEntityInputComponent], imports: [CommonModule,
3065
+ NgxMatEntityInputModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputModule, declarations: [StringInputComponent,
3066
+ StringTextboxInputComponent,
3067
+ StringAutocompleteInputComponent,
3068
+ StringDropdownInputComponent,
3069
+ StringPasswordInputComponent,
3070
+ BooleanCheckboxInputComponent,
3071
+ BooleanToggleInputComponent,
3072
+ BooleanDropdownInputComponent,
3073
+ NumberInputComponent,
3074
+ NumberDropdownInputComponent,
3075
+ NumberSliderInputComponent,
3076
+ ArrayStringChipsInputComponent,
3077
+ ArrayStringAutocompleteChipsComponent,
3078
+ DateInputComponent,
3079
+ DateRangeInputComponent,
3080
+ DateTimeInputComponent,
3081
+ ArrayDateInputComponent,
3082
+ ArrayDateTimeInputComponent,
3083
+ ArrayDateRangeInputComponent,
3084
+ FileInputComponent,
3085
+ FileImageInputComponent,
3086
+ FileDefaultInputComponent,
3087
+ DragDropDirective,
3088
+ CustomInputComponent,
3089
+ NgxMatEntityInputComponent], imports: [CommonModule,
1539
3090
  MatInputModule,
1540
3091
  FormsModule,
1541
3092
  MatFormFieldModule,
@@ -1548,7 +3099,8 @@ NgxMatEntityInputModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0",
1548
3099
  MatTableModule,
1549
3100
  MatDialogModule,
1550
3101
  MatButtonModule,
1551
- MatDatepickerModule], exports: [NgxMatEntityInputComponent] });
3102
+ MatDatepickerModule,
3103
+ MatSliderModule], exports: [NgxMatEntityInputComponent] });
1552
3104
  NgxMatEntityInputModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputModule, imports: [[
1553
3105
  CommonModule,
1554
3106
  MatInputModule,
@@ -1563,13 +3115,38 @@ NgxMatEntityInputModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0",
1563
3115
  MatTableModule,
1564
3116
  MatDialogModule,
1565
3117
  MatButtonModule,
1566
- MatDatepickerModule
3118
+ MatDatepickerModule,
3119
+ MatSliderModule
1567
3120
  ]] });
1568
3121
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputModule, decorators: [{
1569
3122
  type: NgModule,
1570
3123
  args: [{
1571
3124
  declarations: [
1572
- NgxMatEntityInputComponent,
3125
+ StringInputComponent,
3126
+ StringTextboxInputComponent,
3127
+ StringAutocompleteInputComponent,
3128
+ StringDropdownInputComponent,
3129
+ StringPasswordInputComponent,
3130
+ BooleanCheckboxInputComponent,
3131
+ BooleanToggleInputComponent,
3132
+ BooleanDropdownInputComponent,
3133
+ NumberInputComponent,
3134
+ NumberDropdownInputComponent,
3135
+ NumberSliderInputComponent,
3136
+ ArrayStringChipsInputComponent,
3137
+ ArrayStringAutocompleteChipsComponent,
3138
+ DateInputComponent,
3139
+ DateRangeInputComponent,
3140
+ DateTimeInputComponent,
3141
+ ArrayDateInputComponent,
3142
+ ArrayDateTimeInputComponent,
3143
+ ArrayDateRangeInputComponent,
3144
+ FileInputComponent,
3145
+ FileImageInputComponent,
3146
+ FileDefaultInputComponent,
3147
+ DragDropDirective,
3148
+ CustomInputComponent,
3149
+ NgxMatEntityInputComponent
1573
3150
  ],
1574
3151
  imports: [
1575
3152
  CommonModule,
@@ -1585,7 +3162,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1585
3162
  MatTableModule,
1586
3163
  MatDialogModule,
1587
3164
  MatButtonModule,
1588
- MatDatepickerModule
3165
+ MatDatepickerModule,
3166
+ MatSliderModule
1589
3167
  ],
1590
3168
  exports: [NgxMatEntityInputComponent]
1591
3169
  }]
@@ -1628,7 +3206,7 @@ class NgxMatEntityCreateDialogComponent {
1628
3206
  this.injector = injector;
1629
3207
  this.dialog = dialog;
1630
3208
  this.EntityUtilities = EntityUtilities;
1631
- this.getWidth = EntityUtilities.getWidth;
3209
+ this.isEntityValid = false;
1632
3210
  }
1633
3211
  ngOnInit() {
1634
3212
  this.data = new CreateEntityDialogDataBuilder(this.inputData).getResult();
@@ -1636,16 +3214,22 @@ class NgxMatEntityCreateDialogComponent {
1636
3214
  this.entityRows = EntityUtilities.getEntityRows(this.data.entity, true);
1637
3215
  this.entityService = this.injector.get(this.data.EntityServiceClass);
1638
3216
  }
3217
+ /**
3218
+ * Checks if the entity is valid.
3219
+ */
3220
+ checkIsEntityValid() {
3221
+ this.isEntityValid = EntityUtilities.isEntityValid(this.data.entity, 'create');
3222
+ }
1639
3223
  /**
1640
3224
  * Tries add the new entity and close the dialog afterwards.
1641
3225
  * Also handles the confirmation if required.
1642
3226
  */
1643
3227
  create() {
1644
- var _a, _b;
1645
- if (!((_a = this.data.createDialogData) === null || _a === void 0 ? void 0 : _a.createRequiresConfirmDialog)) {
1646
- return this.confirmCreate();
3228
+ if (!this.data.createDialogData.createRequiresConfirmDialog) {
3229
+ this.confirmCreate();
3230
+ return;
1647
3231
  }
1648
- const dialogData = new ConfirmDialogDataBuilder((_b = this.data.createDialogData) === null || _b === void 0 ? void 0 : _b.confirmCreateDialogData)
3232
+ const dialogData = new ConfirmDialogDataBuilder(this.data.createDialogData.confirmCreateDialogData)
1649
3233
  .withDefault('text', ['Do you really want to create this entity?'])
1650
3234
  .withDefault('confirmButtonLabel', 'Create')
1651
3235
  .withDefault('title', 'Create')
@@ -1662,7 +3246,7 @@ class NgxMatEntityCreateDialogComponent {
1662
3246
  });
1663
3247
  }
1664
3248
  confirmCreate() {
1665
- this.entityService.create(this.data.entity).then(() => this.dialogRef.close());
3249
+ void this.entityService.create(this.data.entity).then(() => this.dialogRef.close());
1666
3250
  }
1667
3251
  /**
1668
3252
  * Closes the dialog.
@@ -1672,10 +3256,10 @@ class NgxMatEntityCreateDialogComponent {
1672
3256
  }
1673
3257
  }
1674
3258
  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 });
1675
- 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]" }] });
3259
+ 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", "isReadOnly"], outputs: ["inputChangeEvent"] }, { 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: i4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i4.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }] });
1676
3260
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityCreateDialogComponent, decorators: [{
1677
3261
  type: Component,
1678
- 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"] }]
3262
+ 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"] }]
1679
3263
  }], ctorParameters: function () {
1680
3264
  return [{ type: undefined, decorators: [{
1681
3265
  type: Inject,
@@ -1707,6 +3291,7 @@ class EditDialogDataBuilder extends BaseBuilder {
1707
3291
  }
1708
3292
  // eslint-disable-next-line jsdoc/require-jsdoc
1709
3293
  generateBaseData(data) {
3294
+ var _a, _b, _c, _d, _e, _f;
1710
3295
  const confirmEditDialogData = new ConfirmDialogDataBuilder(data === null || data === void 0 ? void 0 : data.confirmEditDialogData)
1711
3296
  .withDefault('confirmButtonLabel', 'Save')
1712
3297
  .withDefault('text', ['Do you really want to save all changes?'])
@@ -1718,7 +3303,7 @@ class EditDialogDataBuilder extends BaseBuilder {
1718
3303
  .withDefault('text', ['Do you really want to delete this entity?'])
1719
3304
  .withDefault('title', 'Delete')
1720
3305
  .getResult();
1721
- return new EditDialogDataInternal((data === null || data === void 0 ? void 0 : data.title) ? data.title : () => 'Edit', (data === null || data === void 0 ? void 0 : data.confirmButtonLabel) ? data.confirmButtonLabel : 'Save', (data === null || data === void 0 ? void 0 : data.deleteButtonLabel) ? data.deleteButtonLabel : 'Delete', (data === null || data === void 0 ? void 0 : data.cancelButtonLabel) ? data.cancelButtonLabel : 'Cancel', (data === null || data === void 0 ? void 0 : data.deleteRequiresConfirmDialog) ? data.deleteRequiresConfirmDialog : true, (data === null || data === void 0 ? void 0 : data.editRequiresConfirmDialog) ? data.editRequiresConfirmDialog : false, confirmDeleteDialogData, confirmEditDialogData);
3306
+ return new EditDialogDataInternal((_a = data === null || data === void 0 ? void 0 : data.title) !== null && _a !== void 0 ? _a : (() => 'Edit'), (_b = data === null || data === void 0 ? void 0 : data.confirmButtonLabel) !== null && _b !== void 0 ? _b : 'Save', (_c = data === null || data === void 0 ? void 0 : data.deleteButtonLabel) !== null && _c !== void 0 ? _c : 'Delete', (_d = data === null || data === void 0 ? void 0 : data.cancelButtonLabel) !== null && _d !== void 0 ? _d : 'Cancel', (_e = data === null || data === void 0 ? void 0 : data.deleteRequiresConfirmDialog) !== null && _e !== void 0 ? _e : true, (_f = data === null || data === void 0 ? void 0 : data.editRequiresConfirmDialog) !== null && _f !== void 0 ? _f : false, confirmDeleteDialogData, confirmEditDialogData);
1722
3307
  }
1723
3308
  }
1724
3309
 
@@ -1726,11 +3311,12 @@ class EditDialogDataBuilder extends BaseBuilder {
1726
3311
  * The internal EditEntityDialogData. Requires all default values the user can leave out.
1727
3312
  */
1728
3313
  class EditEntityDialogDataInternal {
1729
- constructor(entity, EntityServiceClass, editDialogData, allowDelete) {
3314
+ constructor(entity, EntityServiceClass, editDialogData, allowUpdate, allowDelete) {
1730
3315
  this.entity = entity;
1731
3316
  this.EntityServiceClass = EntityServiceClass;
1732
3317
  this.editDialogData = editDialogData;
1733
3318
  this.allowDelete = allowDelete;
3319
+ this.allowUpdate = allowUpdate;
1734
3320
  }
1735
3321
  }
1736
3322
  /**
@@ -1742,8 +3328,9 @@ class EditEntityDialogDataBuilder extends BaseBuilder {
1742
3328
  }
1743
3329
  // eslint-disable-next-line jsdoc/require-jsdoc
1744
3330
  generateBaseData(data) {
3331
+ var _a, _b;
1745
3332
  const editDialogData = new EditDialogDataBuilder(data.editDialogData).getResult();
1746
- return new EditEntityDialogDataInternal(data.entity, data.EntityServiceClass, editDialogData, data.allowDelete ? data.allowDelete : () => true);
3333
+ return new EditEntityDialogDataInternal(data.entity, data.EntityServiceClass, editDialogData, (_a = data.allowUpdate) !== null && _a !== void 0 ? _a : (() => true), (_b = data.allowDelete) !== null && _b !== void 0 ? _b : (() => true));
1747
3334
  }
1748
3335
  }
1749
3336
 
@@ -1760,14 +3347,21 @@ class NgxMatEntityEditDialogComponent {
1760
3347
  this.injector = injector;
1761
3348
  this.dialog = dialog;
1762
3349
  this.EntityUtilities = EntityUtilities;
1763
- this.getWidth = EntityUtilities.getWidth;
3350
+ this.isEntityValid = true;
3351
+ this.isEntityDirty = (() => __awaiter(this, void 0, void 0, function* () { return false; })).call(this);
1764
3352
  }
1765
3353
  ngOnInit() {
1766
3354
  this.data = new EditEntityDialogDataBuilder(this.inputData).getResult();
3355
+ this.isReadOnly = !this.data.allowUpdate(this.entityPriorChanges);
1767
3356
  this.dialogRef.disableClose = true;
1768
3357
  this.entityRows = EntityUtilities.getEntityRows(this.data.entity, false, true);
1769
3358
  this.entityService = this.injector.get(this.data.EntityServiceClass);
1770
- this.entityPriorChanges = cloneDeep(this.data.entity);
3359
+ this.entityPriorChanges = LodashUtilities.cloneDeep(this.data.entity);
3360
+ }
3361
+ // eslint-disable-next-line jsdoc/require-jsdoc
3362
+ checkEntity() {
3363
+ this.isEntityValid = EntityUtilities.isEntityValid(this.data.entity, 'update');
3364
+ this.isEntityDirty = EntityUtilities.isDirty(this.data.entity, this.entityPriorChanges);
1771
3365
  }
1772
3366
  /**
1773
3367
  * Tries to save the changes and close the dialog afterwards.
@@ -1775,7 +3369,8 @@ class NgxMatEntityEditDialogComponent {
1775
3369
  */
1776
3370
  edit() {
1777
3371
  if (!this.data.editDialogData.editRequiresConfirmDialog) {
1778
- return this.confirmEdit();
3372
+ this.confirmEdit();
3373
+ return;
1779
3374
  }
1780
3375
  const dialogData = new ConfirmDialogDataBuilder(this.data.editDialogData.confirmEditDialogData)
1781
3376
  .withDefault('text', ['Do you really want to save all changes?'])
@@ -1794,7 +3389,7 @@ class NgxMatEntityEditDialogComponent {
1794
3389
  });
1795
3390
  }
1796
3391
  confirmEdit() {
1797
- this.entityService.update(this.data.entity, this.entityPriorChanges).then(() => this.dialogRef.close(1));
3392
+ void this.entityService.update(this.data.entity, this.entityPriorChanges).then(() => this.dialogRef.close(1));
1798
3393
  }
1799
3394
  /**
1800
3395
  * Tries to delete the entity and close the dialog afterwards.
@@ -1802,7 +3397,8 @@ class NgxMatEntityEditDialogComponent {
1802
3397
  */
1803
3398
  delete() {
1804
3399
  if (!this.data.editDialogData.deleteRequiresConfirmDialog) {
1805
- return this.confirmDelete();
3400
+ this.confirmDelete();
3401
+ return;
1806
3402
  }
1807
3403
  const dialogData = new ConfirmDialogDataBuilder(this.data.editDialogData.confirmDeleteDialogData)
1808
3404
  .withDefault('text', ['Do you really want to delete this entity?'])
@@ -1822,7 +3418,7 @@ class NgxMatEntityEditDialogComponent {
1822
3418
  });
1823
3419
  }
1824
3420
  confirmDelete() {
1825
- this.entityService.delete(this.entityPriorChanges).then(() => this.dialogRef.close(2));
3421
+ void this.entityService.delete(this.entityPriorChanges).then(() => this.dialogRef.close(2));
1826
3422
  }
1827
3423
  /**
1828
3424
  * Reverts all changes made and closes the dialog.
@@ -1833,10 +3429,10 @@ class NgxMatEntityEditDialogComponent {
1833
3429
  }
1834
3430
  }
1835
3431
  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 });
1836
- 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]" }] });
3432
+ 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 [isReadOnly]=\"isReadOnly\"\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]=\"isReadOnly || !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: 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", "isReadOnly"], outputs: ["inputChangeEvent"] }], directives: [{ type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i4.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }], pipes: { "async": i6.AsyncPipe } });
1837
3433
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityEditDialogComponent, decorators: [{
1838
3434
  type: Component,
1839
- 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"] }]
3435
+ 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 [isReadOnly]=\"isReadOnly\"\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]=\"isReadOnly || !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"] }]
1840
3436
  }], ctorParameters: function () {
1841
3437
  return [{ type: undefined, decorators: [{
1842
3438
  type: Inject,
@@ -1863,14 +3459,15 @@ class BaseDataBuilder extends BaseBuilder {
1863
3459
  }
1864
3460
  // eslint-disable-next-line jsdoc/require-jsdoc
1865
3461
  generateBaseData(data) {
1866
- 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);
3462
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
3463
+ return new BaseDataInternal(data.title, data.displayColumns, data.EntityServiceClass, (_a = data.searchLabel) !== null && _a !== void 0 ? _a : 'Search', (_b = data.createButtonLabel) !== null && _b !== void 0 ? _b : 'Create', (_c = data.searchString) !== null && _c !== void 0 ? _c : defaultSearchFunction, (_d = data.allowCreate) !== null && _d !== void 0 ? _d : (() => true), (_e = data.allowRead) !== null && _e !== void 0 ? _e : (() => true), (_f = data.allowUpdate) !== null && _f !== void 0 ? _f : (() => true), (_g = data.allowDelete) !== null && _g !== void 0 ? _g : (() => true), (_h = data.multiSelectActions) !== null && _h !== void 0 ? _h : [], (_j = data.multiSelectLabel) !== null && _j !== void 0 ? _j : 'Actions', data.EntityClass, data.edit, data.create);
1867
3464
  }
1868
3465
  }
1869
3466
  /**
1870
3467
  * The internal TableData. Requires all default values the user can leave out.
1871
3468
  */
1872
3469
  class BaseDataInternal {
1873
- constructor(title, displayColumns, EntityServiceClass, searchLabel, createButtonLabel, searchString, allowCreate, allowEdit, allowDelete, multiSelectActions, multiSelectLabel, EntityClass, edit, create) {
3470
+ constructor(title, displayColumns, EntityServiceClass, searchLabel, createButtonLabel, searchString, allowCreate, allowRead, allowUpdate, allowDelete, multiSelectActions, multiSelectLabel, EntityClass, edit, create) {
1874
3471
  this.title = title;
1875
3472
  this.displayColumns = displayColumns;
1876
3473
  this.EntityServiceClass = EntityServiceClass;
@@ -1879,7 +3476,8 @@ class BaseDataInternal {
1879
3476
  this.createButtonLabel = createButtonLabel;
1880
3477
  this.searchString = searchString;
1881
3478
  this.allowCreate = allowCreate;
1882
- this.allowEdit = allowEdit;
3479
+ this.allowRead = allowRead;
3480
+ this.allowUpdate = allowUpdate;
1883
3481
  this.allowDelete = allowDelete;
1884
3482
  this.multiSelectActions = multiSelectActions;
1885
3483
  this.multiSelectLabel = multiSelectLabel;
@@ -1908,24 +3506,26 @@ class TableDataBuilder extends BaseBuilder {
1908
3506
  throw new Error(`The name "select" for a display column is reserved for the multi-select action functionality.
1909
3507
  Please choose a different name.`);
1910
3508
  }
1911
- if ((data.baseData.allowEdit && data.baseData.allowEdit !== (() => false)
1912
- || data.baseData.allowDelete && data.baseData.allowDelete !== (() => false)
1913
- || data.baseData.allowCreate)
3509
+ if ((data.baseData.allowCreate !== (() => false)
3510
+ || data.baseData.allowRead !== (() => false)
3511
+ || data.baseData.allowUpdate !== (() => false)
3512
+ || data.baseData.allowDelete !== (() => false))
1914
3513
  && !data.baseData.EntityClass) {
1915
3514
  throw new Error(`
1916
3515
  Missing required Input data "EntityClass".
1917
3516
  You can only omit this value if you can neither create or update entities.`);
1918
3517
  }
1919
- if (data.baseData.allowCreate !== false && !data.baseData.create && !data.createDialogData) {
3518
+ if (data.baseData.allowCreate !== (() => false) && !data.baseData.create && !data.createDialogData) {
1920
3519
  throw new Error(`Missing required Input data "createDialogData".
1921
3520
  You can only omit this value when creation is disallowed or done with a custom create method.`);
1922
3521
  }
1923
- if ((data.baseData.allowEdit !== (() => false)
3522
+ if ((data.baseData.allowRead !== (() => false)
3523
+ || data.baseData.allowUpdate !== (() => false)
1924
3524
  || data.baseData.allowDelete !== (() => false))
1925
3525
  && !data.baseData.edit
1926
3526
  && !data.editDialogData) {
1927
3527
  throw new Error(`Missing required Input data "editDialogData".
1928
- You can only omit this value when editing and deleting is disallowed or done with a custom edit method.`);
3528
+ You can only omit this value when viewing, editing and deleting is disallowed or done with a custom edit method.`);
1929
3529
  }
1930
3530
  }
1931
3531
  }
@@ -1979,21 +3579,19 @@ class NgxMatEntityTableComponent {
1979
3579
  return (_a = this.data.baseData.displayColumns.find((dp) => dp.displayName === header)) === null || _a === void 0 ? void 0 : _a.value(entity);
1980
3580
  };
1981
3581
  this.dataSource.sort = this.sort;
1982
- if (this.data.baseData.searchString) {
1983
- this.dataSource.filterPredicate = (entity, filter) => {
1984
- const searchStr = this.data.baseData.searchString(entity);
1985
- const formattedSearchString = searchStr.toLowerCase();
1986
- const formattedFilterString = filter.toLowerCase();
1987
- return formattedSearchString.includes(formattedFilterString);
1988
- };
1989
- }
3582
+ this.dataSource.filterPredicate = (entity, filter) => {
3583
+ const searchStr = this.data.baseData.searchString(entity);
3584
+ const formattedSearchString = searchStr.toLowerCase();
3585
+ const formattedFilterString = filter.toLowerCase();
3586
+ return formattedSearchString.includes(formattedFilterString);
3587
+ };
1990
3588
  this.dataSource.filter = this.filter;
1991
3589
  this.dataSource.paginator = this.paginator;
1992
3590
  this.entityService.entitiesSubject.pipe(takeUntil(this.onDestroy)).subscribe((entities) => {
1993
3591
  this.dataSource.data = entities;
1994
3592
  this.selection.clear();
1995
3593
  });
1996
- this.entityService.read();
3594
+ void this.entityService.read();
1997
3595
  }
1998
3596
  /**
1999
3597
  * Edits an entity. This either calls the edit-Method provided by the user or uses a default edit-dialog.
@@ -2002,32 +3600,35 @@ class NgxMatEntityTableComponent {
2002
3600
  * @throws When no EntityClass was provided, as a new call is needed to initialize metadata.
2003
3601
  */
2004
3602
  editEntity(entity) {
2005
- if (this.data.baseData.allowEdit(entity)) {
2006
- if (!this.data.baseData.EntityClass) {
2007
- throw new Error('No "EntityClass" specified for this table');
2008
- }
2009
- if (this.data.baseData.edit) {
2010
- this.data.baseData.edit(new this.data.baseData.EntityClass(entity));
2011
- }
2012
- else {
2013
- this.editDefault(new this.data.baseData.EntityClass(entity));
2014
- }
3603
+ if (!(this.data.baseData.allowUpdate(entity) || this.data.baseData.allowRead(entity))) {
3604
+ return;
3605
+ }
3606
+ if (!this.data.baseData.EntityClass) {
3607
+ throw new Error('No "EntityClass" specified for this table');
3608
+ }
3609
+ if (this.data.baseData.edit) {
3610
+ this.data.baseData.edit(new this.data.baseData.EntityClass(entity));
3611
+ }
3612
+ else {
3613
+ void this.editDefault(new this.data.baseData.EntityClass(entity));
2015
3614
  }
2016
3615
  }
2017
3616
  editDefault(entity) {
2018
- const inputDialogData = {
2019
- entity: entity,
2020
- EntityServiceClass: this.data.baseData.EntityServiceClass,
2021
- allowDelete: this.data.baseData.allowDelete,
2022
- editDialogData: this.data.editDialogData
2023
- };
2024
- const dialogData = new EditEntityDialogDataBuilder(inputDialogData).getResult();
2025
- firstValueFrom(this.dialog.open(NgxMatEntityEditDialogComponent, {
2026
- data: dialogData,
2027
- minWidth: '60%',
2028
- autoFocus: false,
2029
- restoreFocus: false
2030
- }).afterClosed()).then((res) => {
3617
+ return __awaiter(this, void 0, void 0, function* () {
3618
+ const inputDialogData = {
3619
+ entity: entity,
3620
+ EntityServiceClass: this.data.baseData.EntityServiceClass,
3621
+ allowUpdate: this.data.baseData.allowUpdate,
3622
+ allowDelete: this.data.baseData.allowDelete,
3623
+ editDialogData: this.data.editDialogData
3624
+ };
3625
+ const dialogData = new EditEntityDialogDataBuilder(inputDialogData).getResult();
3626
+ const res = yield firstValueFrom(this.dialog.open(NgxMatEntityEditDialogComponent, {
3627
+ data: dialogData,
3628
+ minWidth: '60%',
3629
+ autoFocus: false,
3630
+ restoreFocus: false
3631
+ }).afterClosed());
2031
3632
  if (res === 0) {
2032
3633
  const data = this.dataSource.data;
2033
3634
  data[this.dataSource.data.findIndex((e) => e[this.entityService.idKey] === entity[this.entityService.idKey])] = entity;
@@ -2042,7 +3643,7 @@ class NgxMatEntityTableComponent {
2042
3643
  * @throws When no EntityClass was provided, as a new call is needed to initialize metadata.
2043
3644
  */
2044
3645
  createEntity() {
2045
- if (this.data.baseData.allowCreate) {
3646
+ if (this.data.baseData.allowCreate()) {
2046
3647
  if (!this.data.baseData.EntityClass) {
2047
3648
  throw new Error('No "EntityClass" specified for this table');
2048
3649
  }
@@ -2075,7 +3676,8 @@ class NgxMatEntityTableComponent {
2075
3676
  */
2076
3677
  runMultiAction(action) {
2077
3678
  if (!action.requireConfirmDialog || !action.requireConfirmDialog(this.selection.selected)) {
2078
- return this.confirmRunMultiAction(action);
3679
+ this.confirmRunMultiAction(action);
3680
+ return;
2079
3681
  }
2080
3682
  const dialogData = new ConfirmDialogDataBuilder(action.confirmDialogData)
2081
3683
  .withDefault('text', [`Do you really want to run this action on ${this.selection.selected.length} entries?`])
@@ -2119,7 +3721,7 @@ class NgxMatEntityTableComponent {
2119
3721
  this.selection.clear();
2120
3722
  }
2121
3723
  else {
2122
- this.dataSource.data.forEach((row) => this.selection.select(row));
3724
+ this.dataSource.data.forEach(row => this.selection.select(row));
2123
3725
  }
2124
3726
  }
2125
3727
  /**
@@ -2148,10 +3750,10 @@ class NgxMatEntityTableComponent {
2148
3750
  }
2149
3751
  }
2150
3752
  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 });
2151
- 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"] }] });
3753
+ 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.allowUpdate(entity) || data.baseData.allowRead(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: 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$3.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { type: i4$3.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { type: i4$2.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i2.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$2.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i4$2.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$1.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: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4$3.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4$2.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i4$2.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i4$2.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i4$2.MatCellDef, selector: "[matCellDef]" }, { type: i4$2.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i4$2.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i4$2.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }] });
2152
3754
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityTableComponent, decorators: [{
2153
3755
  type: Component,
2154
- 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"] }]
3756
+ 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.allowUpdate(entity) || data.baseData.allowRead(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"] }]
2155
3757
  }], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i0.Injector }]; }, propDecorators: { tableData: [{
2156
3758
  type: Input
2157
3759
  }], paginator: [{
@@ -2284,17 +3886,88 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
2284
3886
  */
2285
3887
  class EntityArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2286
3888
  constructor(data) {
3889
+ var _a, _b, _c, _d, _e, _f, _g;
2287
3890
  super(data);
2288
- this.createInline = data.createInline != undefined ? data.createInline : true;
2289
- this.displayStyle = data.displayStyle;
3891
+ this.createInline = (_a = data.createInline) !== null && _a !== void 0 ? _a : true;
2290
3892
  this.itemType = data.itemType;
3893
+ this.allowDuplicates = (_b = data.allowDuplicates) !== null && _b !== void 0 ? _b : false;
3894
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
2291
3895
  this.EntityClass = data.EntityClass;
2292
3896
  this.displayColumns = data.displayColumns;
2293
- this.createInline = data.createInline != undefined ? data.createInline : true;
2294
- this.missingErrorMessage = data.missingErrorMessage ? data.missingErrorMessage : 'Needs to contain at least one value';
2295
- this.defaultWidths = data.defaultWidths ? data.defaultWidths : [12, 12, 12];
2296
- this.addButtonLabel = data.addButtonLabel ? data.addButtonLabel : 'Add';
2297
- this.removeButtonLabel = data.removeButtonLabel ? data.removeButtonLabel : 'Remove';
3897
+ this.createInline = (_c = data.createInline) !== null && _c !== void 0 ? _c : true;
3898
+ this.missingErrorMessage = (_d = data.missingErrorMessage) !== null && _d !== void 0 ? _d : 'Needs to contain at least one value';
3899
+ this.defaultWidths = (_e = data.defaultWidths) !== null && _e !== void 0 ? _e : [12, 12, 12];
3900
+ this.addButtonLabel = (_f = data.addButtonLabel) !== null && _f !== void 0 ? _f : 'Add';
3901
+ this.removeButtonLabel = (_g = data.removeButtonLabel) !== null && _g !== void 0 ? _g : 'Remove';
3902
+ }
3903
+ }
3904
+ /**
3905
+ * The internal DateArrayDecoratorConfig. Sets default values.
3906
+ */
3907
+ class DateArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
3908
+ constructor(data) {
3909
+ var _a, _b, _c, _d, _e;
3910
+ super(data);
3911
+ this.itemType = data.itemType;
3912
+ this.allowDuplicates = (_a = data.allowDuplicates) !== null && _a !== void 0 ? _a : false;
3913
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
3914
+ this.displayColumns = data.displayColumns;
3915
+ this.defaultWidths = (_b = data.defaultWidths) !== null && _b !== void 0 ? _b : [12, 12, 12];
3916
+ this.addButtonLabel = (_c = data.addButtonLabel) !== null && _c !== void 0 ? _c : 'Add';
3917
+ this.removeButtonLabel = (_d = data.removeButtonLabel) !== null && _d !== void 0 ? _d : 'Remove';
3918
+ this.missingErrorMessage = (_e = data.missingErrorMessage) !== null && _e !== void 0 ? _e : 'Needs to contain at least one value';
3919
+ this.min = data.min;
3920
+ this.max = data.max;
3921
+ this.filter = data.filter;
3922
+ }
3923
+ }
3924
+ /**
3925
+ * The internal DateTimeArrayDecoratorConfig. Sets default values.
3926
+ */
3927
+ class DateTimeArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
3928
+ constructor(data) {
3929
+ var _a, _b, _c, _d, _e, _f, _g;
3930
+ super(data);
3931
+ this.itemType = data.itemType;
3932
+ this.allowDuplicates = (_a = data.allowDuplicates) !== null && _a !== void 0 ? _a : false;
3933
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
3934
+ this.displayColumns = data.displayColumns;
3935
+ this.defaultWidths = (_b = data.defaultWidths) !== null && _b !== void 0 ? _b : [12, 12, 12];
3936
+ this.addButtonLabel = (_c = data.addButtonLabel) !== null && _c !== void 0 ? _c : 'Add';
3937
+ this.removeButtonLabel = (_d = data.removeButtonLabel) !== null && _d !== void 0 ? _d : 'Remove';
3938
+ this.missingErrorMessage = (_e = data.missingErrorMessage) !== null && _e !== void 0 ? _e : 'Needs to contain at least one value';
3939
+ this.times = (_f = data.times) !== null && _f !== void 0 ? _f : DateUtilities.getDefaultTimes();
3940
+ this.timeDisplayName = (_g = data.timeDisplayName) !== null && _g !== void 0 ? _g : 'Time';
3941
+ this.minDate = data.minDate;
3942
+ this.maxDate = data.maxDate;
3943
+ this.filterDate = data.filterDate;
3944
+ this.minTime = data.minTime;
3945
+ this.maxTime = data.maxTime;
3946
+ this.filterTime = data.filterTime;
3947
+ }
3948
+ }
3949
+ /**
3950
+ * The internal DateRangeArrayDecoratorConfig. Sets default values.
3951
+ */
3952
+ class DateRangeArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
3953
+ constructor(data) {
3954
+ var _a, _b, _c, _d, _e, _f, _g;
3955
+ super(data);
3956
+ this.itemType = data.itemType;
3957
+ this.allowDuplicates = (_a = data.allowDuplicates) !== null && _a !== void 0 ? _a : false;
3958
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
3959
+ this.displayColumns = data.displayColumns;
3960
+ this.defaultWidths = (_b = data.defaultWidths) !== null && _b !== void 0 ? _b : [12, 12, 12];
3961
+ this.addButtonLabel = (_c = data.addButtonLabel) !== null && _c !== void 0 ? _c : 'Add';
3962
+ this.removeButtonLabel = (_d = data.removeButtonLabel) !== null && _d !== void 0 ? _d : 'Remove';
3963
+ this.missingErrorMessage = (_e = data.missingErrorMessage) !== null && _e !== void 0 ? _e : 'Needs to contain at least one value';
3964
+ this.placeholderStart = (_f = data.placeholderStart) !== null && _f !== void 0 ? _f : 'Start';
3965
+ this.placeholderEnd = (_g = data.placeholderEnd) !== null && _g !== void 0 ? _g : 'End';
3966
+ this.minStart = data.minStart;
3967
+ this.maxStart = data.maxStart;
3968
+ this.minEnd = data.minEnd;
3969
+ this.maxEnd = data.maxEnd;
3970
+ this.filter = data.filter;
2298
3971
  }
2299
3972
  }
2300
3973
  /**
@@ -2302,14 +3975,16 @@ class EntityArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal
2302
3975
  */
2303
3976
  class StringChipsArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2304
3977
  constructor(data) {
3978
+ var _a, _b, _c;
2305
3979
  super(data);
2306
- this.deleteIcon = data.deleteIcon ? data.deleteIcon : 'fas fa-circle-minus';
2307
- this.displayStyle = data.displayStyle;
3980
+ this.deleteIcon = (_a = data.deleteIcon) !== null && _a !== void 0 ? _a : 'fas fa-circle-minus';
2308
3981
  this.itemType = data.itemType;
3982
+ this.allowDuplicates = (_b = data.allowDuplicates) !== null && _b !== void 0 ? _b : false;
3983
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
2309
3984
  this.maxLength = data.maxLength;
2310
3985
  this.minLength = data.minLength;
2311
3986
  this.regex = data.regex;
2312
- this.defaultWidths = data.defaultWidths ? data.defaultWidths : [6, 12, 12];
3987
+ this.defaultWidths = (_c = data.defaultWidths) !== null && _c !== void 0 ? _c : [6, 12, 12];
2313
3988
  }
2314
3989
  }
2315
3990
  /**
@@ -2317,17 +3992,38 @@ class StringChipsArrayDecoratorConfigInternal extends PropertyDecoratorConfigInt
2317
3992
  */
2318
3993
  class AutocompleteStringChipsArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2319
3994
  constructor(data) {
3995
+ var _a, _b, _c;
2320
3996
  super(data);
2321
3997
  this.autocompleteValues = data.autocompleteValues;
2322
- this.deleteIcon = data.deleteIcon ? data.deleteIcon : 'fas fa-circle-minus';
2323
- this.displayStyle = data.displayStyle;
3998
+ this.deleteIcon = (_a = data.deleteIcon) !== null && _a !== void 0 ? _a : 'fas fa-circle-minus';
2324
3999
  this.itemType = data.itemType;
4000
+ this.allowDuplicates = (_b = data.allowDuplicates) !== null && _b !== void 0 ? _b : false;
4001
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
2325
4002
  this.maxLength = data.maxLength;
2326
4003
  this.minLength = data.minLength;
2327
4004
  this.regex = data.regex;
2328
- this.defaultWidths = data.defaultWidths ? data.defaultWidths : [6, 12, 12];
4005
+ this.defaultWidths = (_c = data.defaultWidths) !== null && _c !== void 0 ? _c : [6, 12, 12];
2329
4006
  }
2330
4007
  }
4008
+ /**
4009
+ * Gets the default dialog data for the error dialog to display when the user tries to add a duplicate value.
4010
+ *
4011
+ * @param data - The Array Decorator data.
4012
+ * @returns The dialog data with set default values.
4013
+ */
4014
+ function getDefaultDuplicateErrorDialogData(data) {
4015
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
4016
+ return {
4017
+ type: (_b = (_a = data.duplicatesErrorDialog) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : 'info-only',
4018
+ // eslint-disable-next-line max-len
4019
+ text: (_d = (_c = data.duplicatesErrorDialog) === null || _c === void 0 ? void 0 : _c.text) !== null && _d !== void 0 ? _d : ['Adding duplicate entries to the array is not allowed.'],
4020
+ title: (_f = (_e = data.duplicatesErrorDialog) === null || _e === void 0 ? void 0 : _e.title) !== null && _f !== void 0 ? _f : 'Error adding duplicate item',
4021
+ confirmButtonLabel: (_g = data.duplicatesErrorDialog) === null || _g === void 0 ? void 0 : _g.confirmButtonLabel,
4022
+ cancelButtonLabel: (_h = data.duplicatesErrorDialog) === null || _h === void 0 ? void 0 : _h.cancelButtonLabel,
4023
+ requireConfirmation: (_j = data.duplicatesErrorDialog) === null || _j === void 0 ? void 0 : _j.requireConfirmation,
4024
+ confirmationText: (_k = data.duplicatesErrorDialog) === null || _k === void 0 ? void 0 : _k.confirmationText
4025
+ };
4026
+ }
2331
4027
 
2332
4028
  /**
2333
4029
  * Decorator for setting and getting array property metadata.
@@ -2340,6 +4036,12 @@ function array(metadata) {
2340
4036
  switch (metadata.itemType) {
2341
4037
  case DecoratorTypes.OBJECT:
2342
4038
  return baseProperty(new EntityArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY);
4039
+ case DecoratorTypes.DATE:
4040
+ return baseProperty(new DateArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY_DATE);
4041
+ case DecoratorTypes.DATE_TIME:
4042
+ return baseProperty(new DateTimeArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY_DATE_TIME);
4043
+ case DecoratorTypes.DATE_RANGE:
4044
+ return baseProperty(new DateRangeArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY_DATE_RANGE);
2343
4045
  case DecoratorTypes.STRING:
2344
4046
  return baseProperty(new StringChipsArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY_STRING_CHIPS);
2345
4047
  case DecoratorTypes.STRING_AUTOCOMPLETE:
@@ -2378,9 +4080,10 @@ class DropdownBooleanDecoratorConfigInternal extends PropertyDecoratorConfigInte
2378
4080
  */
2379
4081
  class CheckboxBooleanDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2380
4082
  constructor(data) {
4083
+ var _a;
2381
4084
  super(data);
2382
4085
  this.displayStyle = data.displayStyle;
2383
- this.required = data.required === undefined ? false : data.required;
4086
+ this.required = (_a = data.required) !== null && _a !== void 0 ? _a : false;
2384
4087
  }
2385
4088
  }
2386
4089
  /**
@@ -2388,9 +4091,10 @@ class CheckboxBooleanDecoratorConfigInternal extends PropertyDecoratorConfigInte
2388
4091
  */
2389
4092
  class ToggleBooleanDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2390
4093
  constructor(data) {
4094
+ var _a;
2391
4095
  super(data);
2392
4096
  this.displayStyle = data.displayStyle;
2393
- this.required = data.required === undefined ? false : data.required;
4097
+ this.required = (_a = data.required) !== null && _a !== void 0 ? _a : false;
2394
4098
  }
2395
4099
  }
2396
4100
 
@@ -2418,6 +4122,78 @@ function boolean(metadata) {
2418
4122
  class BooleanDecoratorConfig extends PropertyDecoratorConfig {
2419
4123
  }
2420
4124
 
4125
+ /**
4126
+ * The internal DefaultDateDecoratorConfig. Sets default values.
4127
+ */
4128
+ class DefaultDateDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4129
+ constructor(data) {
4130
+ super(data);
4131
+ this.displayStyle = data.displayStyle;
4132
+ this.max = data.max;
4133
+ this.min = data.min;
4134
+ this.filter = data.filter;
4135
+ }
4136
+ }
4137
+ /**
4138
+ * The internal DateRangeDateDecoratorConfig. Sets default values.
4139
+ */
4140
+ class DateRangeDateDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4141
+ constructor(data) {
4142
+ var _a, _b;
4143
+ super(data);
4144
+ this.displayStyle = data.displayStyle;
4145
+ this.minStart = data.minStart;
4146
+ this.maxStart = data.maxStart;
4147
+ this.minEnd = data.minEnd;
4148
+ this.maxEnd = data.maxEnd;
4149
+ this.filter = data.filter;
4150
+ this.placeholderStart = (_a = data.placeholderStart) !== null && _a !== void 0 ? _a : 'Start';
4151
+ this.placeholderEnd = (_b = data.placeholderEnd) !== null && _b !== void 0 ? _b : 'End';
4152
+ }
4153
+ }
4154
+ /**
4155
+ * The internal DateTimeDateDecoratorConfig. Sets default values.
4156
+ */
4157
+ class DateTimeDateDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4158
+ constructor(data) {
4159
+ var _a, _b;
4160
+ super(data);
4161
+ this.displayStyle = data.displayStyle;
4162
+ this.times = (_a = data.times) !== null && _a !== void 0 ? _a : DateUtilities.getDefaultTimes();
4163
+ this.timeDisplayName = (_b = data.timeDisplayName) !== null && _b !== void 0 ? _b : 'Time';
4164
+ this.minDate = data.minDate;
4165
+ this.maxDate = data.maxDate;
4166
+ this.filterDate = data.filterDate;
4167
+ this.minTime = data.minTime;
4168
+ this.maxTime = data.maxTime;
4169
+ this.filterTime = data.filterTime;
4170
+ }
4171
+ }
4172
+
4173
+ /**
4174
+ * Decorator for setting and getting date property metadata.
4175
+ *
4176
+ * @param metadata - The metadata of the date property.
4177
+ * @returns The method that defines the metadata.
4178
+ */
4179
+ function date(metadata) {
4180
+ if (metadata.displayStyle === 'date') {
4181
+ return baseProperty(new DefaultDateDecoratorConfigInternal(metadata), DecoratorTypes.DATE);
4182
+ }
4183
+ else if (metadata.displayStyle === 'datetime') {
4184
+ return baseProperty(new DateTimeDateDecoratorConfigInternal(metadata), DecoratorTypes.DATE_TIME);
4185
+ }
4186
+ else {
4187
+ return baseProperty(new DateRangeDateDecoratorConfigInternal(metadata), DecoratorTypes.DATE_RANGE);
4188
+ }
4189
+ }
4190
+
4191
+ /**
4192
+ * Definition for the @date metadata.
4193
+ */
4194
+ class DateDecoratorConfig extends PropertyDecoratorConfig {
4195
+ }
4196
+
2421
4197
  /**
2422
4198
  * The internal DefaultNumberDecoratorConfig. Sets default values.
2423
4199
  */
@@ -2439,6 +4215,30 @@ class DropdownNumberDecoratorConfigInternal extends PropertyDecoratorConfigInter
2439
4215
  this.dropdownValues = data.dropdownValues;
2440
4216
  }
2441
4217
  }
4218
+ /**
4219
+ * The internal SliderNumberDecoratorConfig. Sets default values.
4220
+ */
4221
+ class SliderNumberDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4222
+ constructor(data) {
4223
+ var _a;
4224
+ super(data);
4225
+ this.displayStyle = data.displayStyle;
4226
+ this.max = data.max;
4227
+ this.min = data.min;
4228
+ this.step = data.step;
4229
+ this.formatThumbLabelValue = (_a = data.formatThumbLabelValue) !== null && _a !== void 0 ? _a : defaultFormatThumbLabelValue;
4230
+ this.tickInterval = data.tickInterval;
4231
+ }
4232
+ }
4233
+ /**
4234
+ * The default function to format values for the number slider thumb label.
4235
+ *
4236
+ * @param value - The value of the slider.
4237
+ * @returns Just the value without any formatting done.
4238
+ */
4239
+ function defaultFormatThumbLabelValue(value) {
4240
+ return value;
4241
+ }
2442
4242
 
2443
4243
  /**
2444
4244
  * Decorator for setting and getting number property metadata.
@@ -2447,11 +4247,13 @@ class DropdownNumberDecoratorConfigInternal extends PropertyDecoratorConfigInter
2447
4247
  * @returns The method that defines the metadata.
2448
4248
  */
2449
4249
  function number(metadata) {
2450
- if (metadata.displayStyle === 'dropdown') {
2451
- return baseProperty(new DropdownNumberDecoratorConfigInternal(metadata), DecoratorTypes.NUMBER_DROPDOWN);
2452
- }
2453
- else {
2454
- return baseProperty(new DefaultNumberDecoratorConfigInternal(metadata), DecoratorTypes.NUMBER);
4250
+ switch (metadata.displayStyle) {
4251
+ case 'dropdown':
4252
+ return baseProperty(new DropdownNumberDecoratorConfigInternal(metadata), DecoratorTypes.NUMBER_DROPDOWN);
4253
+ case 'slider':
4254
+ return baseProperty(new SliderNumberDecoratorConfigInternal(metadata), DecoratorTypes.NUMBER_SLIDER);
4255
+ default:
4256
+ return baseProperty(new DefaultNumberDecoratorConfigInternal(metadata), DecoratorTypes.NUMBER);
2455
4257
  }
2456
4258
  }
2457
4259
 
@@ -2494,6 +4296,168 @@ class ObjectDecoratorConfig extends PropertyDecoratorConfig {
2494
4296
  class StringDecoratorConfig extends PropertyDecoratorConfig {
2495
4297
  }
2496
4298
 
4299
+ /**
4300
+ * The internal DefaultFileDecoratorConfig. Sets default values.
4301
+ */
4302
+ class DefaultFileDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4303
+ constructor(data) {
4304
+ var _a, _b, _c, _d, _e, _f, _g, _h;
4305
+ super(data);
4306
+ this.type = data.type;
4307
+ this.preview = false;
4308
+ this.multiple = data.multiple;
4309
+ this.deleteIcon = (_a = data.deleteIcon) !== null && _a !== void 0 ? _a : 'fas fa-circle-minus';
4310
+ this.allowedMimeTypes = (_b = data.allowedMimeTypes) !== null && _b !== void 0 ? _b : ['*'];
4311
+ this.maxSize = (_c = data.maxSize) !== null && _c !== void 0 ? _c : 10;
4312
+ this.maxSizeTotal = (_d = data.maxSizeTotal) !== null && _d !== void 0 ? _d : 100;
4313
+ this.mimeTypeErrorDialog = (_e = data.mimeTypeErrorDialog) !== null && _e !== void 0 ? _e : getDefaultMimeTypeErrorDialogData(data);
4314
+ this.maxSizeErrorDialog = (_f = data.maxSizeErrorDialog) !== null && _f !== void 0 ? _f : getDefaultMaxSizeErrorDialogData(data);
4315
+ this.maxSizeTotalErrorDialog = (_g = data.maxSizeTotalErrorDialog) !== null && _g !== void 0 ? _g : getDefaultMaxSizeTotalErrorDialogData(data);
4316
+ this.dragAndDrop = (_h = data.dragAndDrop) !== null && _h !== void 0 ? _h : data.multiple;
4317
+ }
4318
+ }
4319
+ /**
4320
+ * The internal ImageFileDecoratorConfig. Sets default values.
4321
+ */
4322
+ class ImageFileDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4323
+ constructor(data) {
4324
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
4325
+ super(data);
4326
+ this.type = data.type;
4327
+ this.allowedMimeTypes = (_a = data.allowedMimeTypes) !== null && _a !== void 0 ? _a : ['image/*'];
4328
+ this.multiple = data.multiple;
4329
+ this.preview = (_b = data.preview) !== null && _b !== void 0 ? _b : true;
4330
+ this.deleteIcon = (_c = data.deleteIcon) !== null && _c !== void 0 ? _c : 'fas fa-circle-minus';
4331
+ this.maxSize = (_d = data.maxSize) !== null && _d !== void 0 ? _d : 10;
4332
+ this.maxSizeTotal = (_e = data.maxSizeTotal) !== null && _e !== void 0 ? _e : 100;
4333
+ this.mimeTypeErrorDialog = (_f = data.mimeTypeErrorDialog) !== null && _f !== void 0 ? _f : getDefaultMimeTypeErrorDialogData(data);
4334
+ this.maxSizeErrorDialog = (_g = data.maxSizeErrorDialog) !== null && _g !== void 0 ? _g : getDefaultMaxSizeErrorDialogData(data);
4335
+ this.maxSizeTotalErrorDialog = (_h = data.maxSizeTotalErrorDialog) !== null && _h !== void 0 ? _h : getDefaultMaxSizeTotalErrorDialogData(data);
4336
+ this.previewPlaceholderUrl = data.previewPlaceholderUrl;
4337
+ this.dragAndDrop = (_j = data.dragAndDrop) !== null && _j !== void 0 ? _j : data.multiple;
4338
+ }
4339
+ }
4340
+ /**
4341
+ * Gets the default dialog data for the error dialog to display
4342
+ * when the user tries to add a file with a wrong type.
4343
+ *
4344
+ * @param data - The File Decorator data.
4345
+ * @returns The dialog data with set default values.
4346
+ */
4347
+ function getDefaultMimeTypeErrorDialogData(data) {
4348
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
4349
+ return {
4350
+ type: (_b = (_a = data.mimeTypeErrorDialog) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : 'info-only',
4351
+ // eslint-disable-next-line max-len
4352
+ text: (_d = (_c = data.mimeTypeErrorDialog) === null || _c === void 0 ? void 0 : _c.text) !== null && _d !== void 0 ? _d : (data.multiple ? ['One of the uploaded files has the wrong type.'] : ['The uploaded file has the wrong type.']),
4353
+ title: (_f = (_e = data.mimeTypeErrorDialog) === null || _e === void 0 ? void 0 : _e.title) !== null && _f !== void 0 ? _f : (data.multiple ? 'Error adding files' : 'Error adding file'),
4354
+ confirmButtonLabel: (_g = data.mimeTypeErrorDialog) === null || _g === void 0 ? void 0 : _g.confirmButtonLabel,
4355
+ cancelButtonLabel: (_h = data.mimeTypeErrorDialog) === null || _h === void 0 ? void 0 : _h.cancelButtonLabel,
4356
+ requireConfirmation: (_j = data.mimeTypeErrorDialog) === null || _j === void 0 ? void 0 : _j.requireConfirmation,
4357
+ confirmationText: (_k = data.mimeTypeErrorDialog) === null || _k === void 0 ? void 0 : _k.confirmationText
4358
+ };
4359
+ }
4360
+ /**
4361
+ * Gets the default dialog data for the error dialog to display
4362
+ * when the user tries to add a single file that is bigger than the allowed maxSize.
4363
+ *
4364
+ * @param data - The File Decorator data.
4365
+ * @returns The dialog data with set default values.
4366
+ */
4367
+ function getDefaultMaxSizeErrorDialogData(data) {
4368
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
4369
+ return {
4370
+ type: (_b = (_a = data.mimeTypeErrorDialog) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : 'info-only',
4371
+ // eslint-disable-next-line max-len
4372
+ text: (_d = (_c = data.mimeTypeErrorDialog) === null || _c === void 0 ? void 0 : _c.text) !== null && _d !== void 0 ? _d : (data.multiple ? ['One of the uploaded files is too big'] : ['The uploaded files is too big']),
4373
+ title: (_f = (_e = data.mimeTypeErrorDialog) === null || _e === void 0 ? void 0 : _e.title) !== null && _f !== void 0 ? _f : (data.multiple ? 'Error adding files' : 'Error adding file'),
4374
+ confirmButtonLabel: (_g = data.mimeTypeErrorDialog) === null || _g === void 0 ? void 0 : _g.confirmButtonLabel,
4375
+ cancelButtonLabel: (_h = data.mimeTypeErrorDialog) === null || _h === void 0 ? void 0 : _h.cancelButtonLabel,
4376
+ requireConfirmation: (_j = data.mimeTypeErrorDialog) === null || _j === void 0 ? void 0 : _j.requireConfirmation,
4377
+ confirmationText: (_k = data.mimeTypeErrorDialog) === null || _k === void 0 ? void 0 : _k.confirmationText
4378
+ };
4379
+ }
4380
+ /**
4381
+ * Gets the default dialog data for the error dialog to display
4382
+ * when the user tries to add a single file that is bigger than the allowed maxSize.
4383
+ *
4384
+ * @param data - The File Decorator data.
4385
+ * @returns The dialog data with set default values.
4386
+ */
4387
+ function getDefaultMaxSizeTotalErrorDialogData(data) {
4388
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
4389
+ return {
4390
+ type: (_b = (_a = data.mimeTypeErrorDialog) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : 'info-only',
4391
+ // eslint-disable-next-line max-len
4392
+ text: (_d = (_c = data.mimeTypeErrorDialog) === null || _c === void 0 ? void 0 : _c.text) !== null && _d !== void 0 ? _d : ['The size of all files combined is too big'],
4393
+ title: (_f = (_e = data.mimeTypeErrorDialog) === null || _e === void 0 ? void 0 : _e.title) !== null && _f !== void 0 ? _f : (data.multiple ? 'Error adding files' : 'Error adding file'),
4394
+ confirmButtonLabel: (_g = data.mimeTypeErrorDialog) === null || _g === void 0 ? void 0 : _g.confirmButtonLabel,
4395
+ cancelButtonLabel: (_h = data.mimeTypeErrorDialog) === null || _h === void 0 ? void 0 : _h.cancelButtonLabel,
4396
+ requireConfirmation: (_j = data.mimeTypeErrorDialog) === null || _j === void 0 ? void 0 : _j.requireConfirmation,
4397
+ confirmationText: (_k = data.mimeTypeErrorDialog) === null || _k === void 0 ? void 0 : _k.confirmationText
4398
+ };
4399
+ }
4400
+
4401
+ /**
4402
+ * Decorator for setting and getting file property metadata.
4403
+ *
4404
+ * @param metadata - The metadata of the file property.
4405
+ * @returns The method that defines the metadata.
4406
+ * @throws When an unknown metadata type was provided.
4407
+ */
4408
+ function file(metadata) {
4409
+ switch (metadata.type) {
4410
+ case 'other':
4411
+ return baseProperty(new DefaultFileDecoratorConfigInternal(metadata), DecoratorTypes.FILE_DEFAULT);
4412
+ case 'image':
4413
+ return baseProperty(new ImageFileDecoratorConfigInternal(metadata), DecoratorTypes.FILE_IMAGE);
4414
+ default:
4415
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
4416
+ throw new Error(`Unknown metadata type ${metadata.type}`);
4417
+ }
4418
+ }
4419
+
4420
+ /**
4421
+ * Definition for the @file metadata.
4422
+ */
4423
+ class FileDecoratorConfig extends PropertyDecoratorConfig {
4424
+ }
4425
+
4426
+ /**
4427
+ * The default function to use for checking if the value is dirty.
4428
+ *
4429
+ * @param value - The current value.
4430
+ * @param valuePriorChanges - The value before any changes.
4431
+ * @returns Whether or not the provided value has been changed.
4432
+ */
4433
+ function defaultIsEqual(value, valuePriorChanges) {
4434
+ return LodashUtilities.isEqual(value, valuePriorChanges);
4435
+ }
4436
+ /**
4437
+ * The internal config for the @custom decorator.
4438
+ * Sets default values.
4439
+ */
4440
+ class CustomDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4441
+ constructor(data) {
4442
+ var _a, _b;
4443
+ super(data);
4444
+ this.component = data.component;
4445
+ this.isValid = (_a = data.isValid) !== null && _a !== void 0 ? _a : (() => true);
4446
+ this.isEqual = (_b = data.isEqual) !== null && _b !== void 0 ? _b : defaultIsEqual;
4447
+ this.customMetadata = data.customMetadata;
4448
+ }
4449
+ }
4450
+
4451
+ /**
4452
+ * Decorator for setting and getting custom property metadata.
4453
+ *
4454
+ * @param metadata - The metadata of the custom property.
4455
+ * @returns The method that defines the metadata.
4456
+ */
4457
+ function custom(metadata) {
4458
+ return baseProperty(new CustomDecoratorConfigInternal(metadata), DecoratorTypes.CUSTOM);
4459
+ }
4460
+
2497
4461
  /**
2498
4462
  * Public API Surface of ngx-material-entity.
2499
4463
  */
@@ -2502,5 +4466,5 @@ class StringDecoratorConfig extends PropertyDecoratorConfig {
2502
4466
  * Generated bundle index. Do not edit.
2503
4467
  */
2504
4468
 
2505
- export { DateUtilities, DecoratorTypes, Entity, EntityService, EntityUtilities, NgxMatEntityConfirmDialogComponent, NgxMatEntityConfirmDialogModule, NgxMatEntityCreateDialogComponent, NgxMatEntityCreateDialogModule, NgxMatEntityEditDialogComponent, NgxMatEntityEditDialogModule, NgxMatEntityInputComponent, NgxMatEntityInputModule, NgxMatEntityTableComponent, NgxMatEntityTableModule, array, boolean, getValidationErrorMessage, number, object, string };
4469
+ export { ArrayDecoratorConfig, DateUtilities, DecoratorTypes, Entity, EntityService, EntityUtilities, FileUtilities, NgxMatEntityBaseInputComponent, NgxMatEntityConfirmDialogComponent, NgxMatEntityConfirmDialogModule, NgxMatEntityCreateDialogComponent, NgxMatEntityCreateDialogModule, NgxMatEntityEditDialogComponent, NgxMatEntityEditDialogModule, NgxMatEntityInputComponent, NgxMatEntityInputModule, NgxMatEntityTableComponent, NgxMatEntityTableModule, array, boolean, custom, date, file, getValidationErrorMessage, number, object, string };
2506
4470
  //# sourceMappingURL=ngx-material-entity.mjs.map