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
2
  import { __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
  /**
@@ -83,11 +162,11 @@ var DecoratorTypes;
83
162
  class PositionInternal {
84
163
  constructor(data) {
85
164
  this.validateInput(data);
86
- this.row = data?.row ? data.row : -1;
87
- this.order = data?.order ? data.order : -1;
165
+ this.row = data?.row ?? -1;
166
+ this.order = data?.order ?? -1;
88
167
  }
89
168
  validateInput(data) {
90
- if (data?.order) {
169
+ if (data?.order != null) {
91
170
  if (data.order < 1) {
92
171
  throw new Error('order must be at least 1');
93
172
  }
@@ -95,7 +174,7 @@ class PositionInternal {
95
174
  throw new Error('order cannot be bigger than 12 (the minimum value for a bootstrap column)');
96
175
  }
97
176
  }
98
- if (data?.row && (data.row < 1)) {
177
+ if (data?.row != null && data.row < 1) {
99
178
  throw new Error('row must be at least 1');
100
179
  }
101
180
  }
@@ -105,12 +184,12 @@ class PositionInternal {
105
184
  */
106
185
  class PropertyDecoratorConfigInternal {
107
186
  constructor(data) {
108
- this.display = data.display != undefined ? data.display : true;
187
+ this.display = data.display ?? true;
109
188
  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];
189
+ this.required = data.required ?? true;
190
+ this.omitForCreate = data.omitForCreate ?? false;
191
+ this.omitForUpdate = data.omitForUpdate ?? false;
192
+ this.defaultWidths = data.defaultWidths ?? [6, 6, 12];
114
193
  this.position = new PositionInternal(data.position);
115
194
  }
116
195
  }
@@ -161,6 +240,21 @@ class AutocompleteStringDecoratorConfigInternal extends PropertyDecoratorConfigI
161
240
  this.regex = data.regex;
162
241
  }
163
242
  }
243
+ /**
244
+ * The internal PasswordStringDecoratorConfig. Sets default values.
245
+ */
246
+ class PasswordStringDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
247
+ constructor(data) {
248
+ super(data);
249
+ this.displayStyle = data.displayStyle;
250
+ this.minLength = data.minLength;
251
+ this.maxLength = data.maxLength;
252
+ this.regex = data.regex;
253
+ this.needsConfirmation = data.needsConfirmation ?? true;
254
+ this.confirmationDisplayName = data.confirmationDisplayName ?? 'Confirm Password';
255
+ this.passwordsDontMatchErrorMessage = data.passwordsDontMatchErrorMessage ?? 'Passwords need to match!';
256
+ }
257
+ }
164
258
 
165
259
  /**
166
260
  * Decorator for setting and getting string Property metadata.
@@ -169,36 +263,93 @@ class AutocompleteStringDecoratorConfigInternal extends PropertyDecoratorConfigI
169
263
  * @returns The method that defines the metadata.
170
264
  */
171
265
  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);
266
+ switch (metadata.displayStyle) {
267
+ case 'dropdown':
268
+ return baseProperty(new DropdownStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_DROPDOWN);
269
+ case 'autocomplete':
270
+ return baseProperty(new AutocompleteStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_AUTOCOMPLETE);
271
+ case 'textbox':
272
+ return baseProperty(new TextboxStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_TEXTBOX);
273
+ case 'password':
274
+ return baseProperty(new PasswordStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_PASSWORD);
275
+ default:
276
+ return baseProperty(new DefaultStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING);
183
277
  }
184
278
  }
185
279
 
186
280
  /**
187
- * A base Entity class with a builtin id.
281
+ * Encapsulates all functionality of lodash.
188
282
  */
189
- class Entity {
283
+ class LodashUtilities {
284
+ /**
285
+ * Performs a deep comparison between two values to determine if they are
286
+ * equivalent.
287
+ *
288
+ * **Note:** This method supports comparing arrays, array buffers, booleans,
289
+ * date objects, error objects, maps, numbers, `Object` objects, regexps,
290
+ * sets, strings, symbols, and typed arrays. `Object` objects are compared
291
+ * by their own, not inherited, enumerable properties. Functions and DOM
292
+ * nodes are **not** supported.
293
+ *
294
+ * @param value - The value to compare.
295
+ * @param other - The other value to compare.
296
+ * @returns Returns `true` if the values are equivalent, else `false`.
297
+ */
298
+ static isEqual(value, other) {
299
+ return isEqual(value, other);
300
+ }
301
+ /**
302
+ * This method is like _.clone except that it recursively clones value.
303
+ *
304
+ * @param value - The value to recursively clone.
305
+ * @returns Returns the deep cloned value.
306
+ */
307
+ static cloneDeep(value) {
308
+ return cloneDeep(value);
309
+ }
310
+ /**
311
+ * The opposite of `_.pick`; this method creates an object composed of the
312
+ * own and inherited enumerable properties of `object` that are not omitted.
313
+ *
314
+ * @param object - The source object.
315
+ * @param paths - The property names to omit, specified
316
+ * individually or in arrays.
317
+ * @returns Returns the new object.
318
+ */
319
+ static omit(object, ...paths) {
320
+ return omit(object, ...paths);
321
+ }
322
+ /**
323
+ * Checks if `value` is `null` or `undefined`.
324
+ *
325
+ * @param value - The value to check.
326
+ * @returns Returns `true` if `value` is nullish, else `false`.
327
+ */
328
+ static isNil(value) {
329
+ return isNil(value);
330
+ }
331
+ /**
332
+ * The opposite of `_.pickBy`; this method creates an object composed of the
333
+ * own and inherited enumerable properties of `object` that `predicate`
334
+ * doesn't return truthy for.
335
+ *
336
+ * @param object - The source object.
337
+ * @param predicate - The function invoked per property.
338
+ * @returns Returns the new object.
339
+ */
340
+ static omitBy(object, predicate) {
341
+ return omitBy(object, predicate);
342
+ }
343
+ /**
344
+ * Checks if value is classified as an Array object.
345
+ *
346
+ * @param value - The value to check.
347
+ * @returns Returns true if value is correctly classified, else false.
348
+ */
349
+ static isArray(value) {
350
+ return isArray(value);
351
+ }
190
352
  }
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
353
 
203
354
  const DAY_IN_MS = 1000 * 60 * 60 * 24;
204
355
  /**
@@ -225,14 +376,14 @@ class DateUtilities {
225
376
  const res = [{ displayName: '-', value: undefined }];
226
377
  for (let hour = 0; hour < 24; hour++) {
227
378
  for (let minute = 0; minute < 60; minute += minuteSteps) {
228
- res.push(this.getTimeDropdownValue(format, hour, minute));
379
+ res.push(DateUtilities.getTimeDropdownValue(format, hour, minute));
229
380
  }
230
381
  }
231
382
  return res;
232
383
  }
233
384
  static getTimeDropdownValue(format, hour, minute) {
234
- const displayHour = this.getFormattedHour(format, cloneDeep(hour));
235
- const displayMinute = this.getFormattedMinute(format, hour, minute);
385
+ const displayHour = DateUtilities.getFormattedHour(format, LodashUtilities.cloneDeep(hour));
386
+ const displayMinute = DateUtilities.getFormattedMinute(format, hour, minute);
236
387
  return {
237
388
  displayName: `${displayHour}:${displayMinute}`,
238
389
  value: {
@@ -270,10 +421,7 @@ class DateUtilities {
270
421
  */
271
422
  static getTimeFromDate(value) {
272
423
  if (!value) {
273
- return {
274
- hours: undefined,
275
- minutes: undefined
276
- };
424
+ return undefined;
277
425
  }
278
426
  else {
279
427
  return {
@@ -287,10 +435,10 @@ class DateUtilities {
287
435
  *
288
436
  * @param startDate - The start date.
289
437
  * @param endDate - The end date.
290
- * @param metadataDateRangeDate - The metadata.
438
+ * @param filter - The custom filter from the metadata.
291
439
  * @returns All dates between the two provided dates. Includes start and end date.
292
440
  */
293
- static getDatesBetween(startDate, endDate, metadataDateRangeDate) {
441
+ static getDatesBetween(startDate, endDate, filter) {
294
442
  const res = [];
295
443
  while (startDate.getFullYear() < endDate.getFullYear()
296
444
  || startDate.getMonth() < endDate.getMonth()
@@ -298,8 +446,8 @@ class DateUtilities {
298
446
  res.push(new Date(startDate));
299
447
  startDate.setTime(startDate.getTime() + DAY_IN_MS);
300
448
  }
301
- if (metadataDateRangeDate.filter) {
302
- return res.filter(d => metadataDateRangeDate.filter?.(d));
449
+ if (filter) {
450
+ return res.filter(d => filter(d));
303
451
  }
304
452
  else {
305
453
  return res;
@@ -308,14 +456,14 @@ class DateUtilities {
308
456
  /**
309
457
  * Get all valid times for the dropdown of a datetime property.
310
458
  *
311
- * @param date - The date of the datetime.
312
459
  * @param times - All given times to filter.
460
+ * @param date - The date of the datetime.
313
461
  * @param min - The function that defines the minimum time.
314
462
  * @param max - The function that defines the maximum time.
315
463
  * @param filter - A filter function to do more specific time filtering. This could be e.g. The removal of lunch breaks.
316
464
  * @returns All valid dropdown values for the datetime property.
317
465
  */
318
- static getValidTimesForDropdown(date, times, min, max, filter) {
466
+ static getValidTimesForDropdown(times, date, min, max, filter) {
319
467
  if (min) {
320
468
  const minTime = min(date);
321
469
  times = times.filter(t => !t.value
@@ -335,6 +483,152 @@ class DateUtilities {
335
483
  }
336
484
  return times;
337
485
  }
486
+ /**
487
+ * Checks if the time object has processable hours and minutes properties.
488
+ * Doesn't check custom validators like min/max from the metadata configuration.
489
+ *
490
+ * @param time - The time to check.
491
+ * @returns Whether or not the time object is unprocessable.
492
+ */
493
+ static timeIsUnprocessable(time) {
494
+ if (!time
495
+ || time.hours == null
496
+ || typeof time.hours !== 'number'
497
+ || Number.isNaN(time.hours)
498
+ || time.minutes == null
499
+ || typeof time.minutes !== 'number'
500
+ || Number.isNaN(time.minutes)) {
501
+ return true;
502
+ }
503
+ return false;
504
+ }
505
+ }
506
+ /**
507
+ * The default filter function to user when none was provided by the user.
508
+ */
509
+ DateUtilities.defaultDateFilter = () => true;
510
+
511
+ /**
512
+ * Provides functionality regarding files.
513
+ */
514
+ class FileUtilities {
515
+ /**
516
+ * Gets the accept value for the html input.
517
+ *
518
+ * @param mimeTypes - The mimeTypes to get the accept string from.
519
+ * @returns A comma separated string of all the provided mime types.
520
+ */
521
+ static getAcceptString(mimeTypes) {
522
+ if (!mimeTypes?.length) {
523
+ return '*';
524
+ }
525
+ return mimeTypes.join(', ');
526
+ }
527
+ // TODO: Find a way to use blobs with jest
528
+ /* istanbul ignore next */
529
+ /**
530
+ * Reads a url to display the given file.
531
+ *
532
+ * @param file - The file to get the url from.
533
+ * @returns A promise of the url. Undefined if no file was provided.
534
+ */
535
+ static async getDataURLFromFile(file) {
536
+ if (!file) {
537
+ return undefined;
538
+ }
539
+ return new Promise((resolve, reject) => {
540
+ const reader = new FileReader();
541
+ reader.onload = e => resolve(e.target?.result);
542
+ reader.onerror = e => reject(e);
543
+ reader.readAsDataURL(file);
544
+ });
545
+ }
546
+ // TODO: Find a way to use blobs with jest
547
+ /* istanbul ignore next */
548
+ /**
549
+ * Gets a file from the given url.
550
+ *
551
+ * @param url - The url to get the file from.
552
+ * @returns A promise of the File.
553
+ */
554
+ static async getFileFromUrl(url) {
555
+ const res = await fetch(url);
556
+ if (!res.ok) {
557
+ // TODO make error more robust
558
+ throw new Error(`Error fetching the file from the url ${url}`);
559
+ }
560
+ return await res.blob();
561
+ }
562
+ // TODO: Find a way to use blobs with jest
563
+ /* istanbul ignore next */
564
+ /**
565
+ * Gets the file data with the blob from the given File Data.
566
+ *
567
+ * @param data - The File Data to get the file data with blob from.
568
+ * @returns FileDataWithFile.
569
+ */
570
+ static async getFileData(data) {
571
+ if (data.file) {
572
+ return {
573
+ file: data.file,
574
+ name: data.name,
575
+ url: data.url,
576
+ type: data.type,
577
+ size: data.size
578
+ };
579
+ }
580
+ else {
581
+ return {
582
+ file: await FileUtilities.getFileFromUrl(data.url),
583
+ name: data.name,
584
+ url: data.url,
585
+ type: data.type,
586
+ size: data.size
587
+ };
588
+ }
589
+ }
590
+ /**
591
+ * Checks if the given file has a valid mime type.
592
+ *
593
+ * @param type - The type of the file to check.
594
+ * @param allowedMimeTypes - The allowed mime types.
595
+ * @returns Whether or not the given file has a valid mime type.
596
+ */
597
+ static isMimeTypeValid(type, allowedMimeTypes) {
598
+ if (allowedMimeTypes.includes('*')) {
599
+ return true;
600
+ }
601
+ for (const t of allowedMimeTypes) {
602
+ if (t === type) {
603
+ return true;
604
+ }
605
+ if (t.endsWith('*') && type.startsWith(t.split('*')[0])) {
606
+ return true;
607
+ }
608
+ }
609
+ return false;
610
+ }
611
+ /**
612
+ * Transform the given value to Megabytes.
613
+ *
614
+ * @param value - The original value.
615
+ * @param unit - If the value is B, KB or GB.
616
+ * @returns The given value as bytes.
617
+ */
618
+ static transformToMegaBytes(value, unit) {
619
+ const bytes = this.transformToBytes(LodashUtilities.cloneDeep(value), unit);
620
+ return bytes / 1000000;
621
+ }
622
+ static transformToBytes(value, unit) {
623
+ switch (unit) {
624
+ case 'B':
625
+ return value;
626
+ case 'KB':
627
+ return value * 1000;
628
+ case 'GB':
629
+ return value * 1000000000;
630
+ }
631
+ }
338
632
  }
339
633
 
340
634
  /**
@@ -373,6 +667,26 @@ class EntityUtilities {
373
667
  }
374
668
  return res;
375
669
  }
670
+ /**
671
+ * Gets all properties on the given entity which are files.
672
+ *
673
+ * @param entity - The entity to check for file properties.
674
+ * @param omit - Whether to leave out values that are omitted for create or delete.
675
+ * @returns The keys of all file properties on the given entity.
676
+ */
677
+ static getFileProperties(entity, omit) {
678
+ const res = [];
679
+ for (const key of EntityUtilities.keysOf(entity)) {
680
+ const type = EntityUtilities.getPropertyType(entity, key);
681
+ if (type === DecoratorTypes.FILE_DEFAULT || type === DecoratorTypes.FILE_IMAGE) {
682
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
683
+ if (!(metadata.omitForCreate && omit === 'create') && !(metadata.omitForUpdate && omit === 'update')) {
684
+ res.push(key);
685
+ }
686
+ }
687
+ }
688
+ return res;
689
+ }
376
690
  /**
377
691
  * Gets the metadata included in an property.
378
692
  *
@@ -385,16 +699,11 @@ class EntityUtilities {
385
699
  static getPropertyMetadata(entity, propertyKey,
386
700
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
387
701
  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) {
702
+ const metadata = ReflectUtilities.getMetadata('metadata', entity, propertyKey);
703
+ if (metadata == null) {
396
704
  throw new Error(`Could not find metadata for property ${String(propertyKey)} on the entity ${JSON.stringify(entity)}`);
397
705
  }
706
+ return metadata;
398
707
  }
399
708
  /**
400
709
  * Gets the type of the property-metadata.
@@ -406,8 +715,8 @@ class EntityUtilities {
406
715
  */
407
716
  static getPropertyType(entity, propertyKey) {
408
717
  try {
409
- const propertyType = Reflect.getMetadata('type', entity, propertyKey);
410
- if (!propertyType) {
718
+ const propertyType = ReflectUtilities.getMetadata('type', entity, propertyKey);
719
+ if (propertyType == null) {
411
720
  throw new Error(`Could not find type metadata for property ${String(propertyKey)} on the entity ${JSON.stringify(entity)}`);
412
721
  }
413
722
  return propertyType;
@@ -428,12 +737,10 @@ class EntityUtilities {
428
737
  static new(target, entity) {
429
738
  for (const key in target) {
430
739
  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;
740
+ let value = entity ? ReflectUtilities.get(entity, key) : undefined;
433
741
  switch (type) {
434
742
  case DecoratorTypes.OBJECT:
435
743
  const objectMetadata = EntityUtilities.getPropertyMetadata(target, key, DecoratorTypes.OBJECT);
436
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
437
744
  value = new objectMetadata.EntityClass(value);
438
745
  break;
439
746
  case DecoratorTypes.ARRAY:
@@ -451,7 +758,7 @@ class EntityUtilities {
451
758
  default:
452
759
  break;
453
760
  }
454
- Reflect.set(target, key, value);
761
+ ReflectUtilities.set(target, key, value);
455
762
  }
456
763
  }
457
764
  /**
@@ -488,37 +795,52 @@ class EntityUtilities {
488
795
  if (metadata.omitForUpdate && omit === 'update') {
489
796
  return true;
490
797
  }
491
- if (metadata.required && !entity[key]) {
798
+ if (metadata.required && entity[key] == null) {
492
799
  return false;
493
800
  }
494
801
  switch (type) {
495
802
  case DecoratorTypes.BOOLEAN_DROPDOWN:
803
+ break;
496
804
  case DecoratorTypes.BOOLEAN_CHECKBOX:
497
805
  case DecoratorTypes.BOOLEAN_TOGGLE:
498
- return true;
806
+ const entityBoolean = entity[key];
807
+ const booleanMetadata = metadata;
808
+ if (!EntityUtilities.isBooleanValid(entityBoolean, booleanMetadata)) {
809
+ return false;
810
+ }
811
+ break;
499
812
  case DecoratorTypes.STRING_DROPDOWN:
500
- return true;
813
+ break;
501
814
  case DecoratorTypes.STRING:
502
815
  case DecoratorTypes.STRING_AUTOCOMPLETE:
503
816
  const entityString = entity[key];
504
817
  const stringMetadata = metadata;
505
- if (!this.isStringValid(entityString, stringMetadata)) {
818
+ if (!EntityUtilities.isStringValid(entityString, stringMetadata)) {
506
819
  return false;
507
820
  }
508
821
  break;
509
822
  case DecoratorTypes.STRING_TEXTBOX:
510
823
  const entityTextbox = entity[key];
511
824
  const textboxMetadata = metadata;
512
- if (!this.isTextboxValid(entityTextbox, textboxMetadata)) {
825
+ if (!EntityUtilities.isTextboxValid(entityTextbox, textboxMetadata)) {
826
+ return false;
827
+ }
828
+ break;
829
+ case DecoratorTypes.STRING_PASSWORD:
830
+ const entityPassword = entity[key];
831
+ const passwordMetadata = metadata;
832
+ const confirmPassword = ReflectUtilities.getMetadata('confirmPassword', entity, key);
833
+ if (!EntityUtilities.isPasswordValid(entityPassword, passwordMetadata, confirmPassword)) {
513
834
  return false;
514
835
  }
515
836
  break;
516
837
  case DecoratorTypes.NUMBER_DROPDOWN:
517
838
  return true;
518
839
  case DecoratorTypes.NUMBER:
840
+ case DecoratorTypes.NUMBER_SLIDER:
519
841
  const entityNumber = entity[key];
520
842
  const numberMetadata = metadata;
521
- if (!this.isNumberValid(entityNumber, numberMetadata)) {
843
+ if (!EntityUtilities.isNumberValid(entityNumber, numberMetadata)) {
522
844
  return false;
523
845
  }
524
846
  break;
@@ -532,6 +854,9 @@ class EntityUtilities {
532
854
  break;
533
855
  case DecoratorTypes.ARRAY_STRING_CHIPS:
534
856
  case DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS:
857
+ case DecoratorTypes.ARRAY_DATE:
858
+ case DecoratorTypes.ARRAY_DATE_TIME:
859
+ case DecoratorTypes.ARRAY_DATE_RANGE:
535
860
  case DecoratorTypes.ARRAY:
536
861
  const entityArray = entity[key];
537
862
  const arrayMetadata = metadata;
@@ -542,21 +867,36 @@ class EntityUtilities {
542
867
  case DecoratorTypes.DATE:
543
868
  const entityDate = new Date(entity[key]);
544
869
  const dateMetadata = metadata;
545
- if (!this.isDateValid(entityDate, dateMetadata)) {
870
+ if (!EntityUtilities.isDateValid(entityDate, dateMetadata)) {
546
871
  return false;
547
872
  }
548
873
  break;
549
874
  case DecoratorTypes.DATE_RANGE:
550
- const entityDateRange = cloneDeep(entity[key]);
875
+ const entityDateRange = LodashUtilities.cloneDeep(entity[key]);
551
876
  const dateRangeMetadata = metadata;
552
- if (!this.isDateRangeValid(entityDateRange, dateRangeMetadata)) {
877
+ if (!EntityUtilities.isDateRangeValid(entityDateRange, dateRangeMetadata)) {
553
878
  return false;
554
879
  }
555
880
  break;
556
881
  case DecoratorTypes.DATE_TIME:
557
882
  const entityDateTime = new Date(entity[key]);
558
883
  const dateTimeMetadata = metadata;
559
- if (!this.isDateTimeValid(entityDateTime, dateTimeMetadata)) {
884
+ if (!EntityUtilities.isDateTimeValid(entityDateTime, dateTimeMetadata)) {
885
+ return false;
886
+ }
887
+ break;
888
+ case DecoratorTypes.FILE_DEFAULT:
889
+ case DecoratorTypes.FILE_IMAGE:
890
+ const entityFile = entity[key];
891
+ const entityFileMetadata = metadata;
892
+ if (!EntityUtilities.isFileDataValid(entityFile, entityFileMetadata)) {
893
+ return false;
894
+ }
895
+ break;
896
+ case DecoratorTypes.CUSTOM:
897
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
898
+ const customMetadata = metadata;
899
+ if (!customMetadata.isValid(entity[key], omit)) {
560
900
  return false;
561
901
  }
562
902
  break;
@@ -565,6 +905,12 @@ class EntityUtilities {
565
905
  }
566
906
  return true;
567
907
  }
908
+ static isBooleanValid(value, metadata) {
909
+ if (metadata.required && !value) {
910
+ return false;
911
+ }
912
+ return true;
913
+ }
568
914
  static isStringValid(value, metadata) {
569
915
  if (metadata.maxLength && value.length > metadata.maxLength) {
570
916
  return false;
@@ -586,6 +932,21 @@ class EntityUtilities {
586
932
  }
587
933
  return true;
588
934
  }
935
+ static isPasswordValid(value, metadata, confirmPassword) {
936
+ if (value !== confirmPassword) {
937
+ return false;
938
+ }
939
+ if (metadata.maxLength && value.length > metadata.maxLength) {
940
+ return false;
941
+ }
942
+ if (metadata.minLength && value.length < metadata.minLength) {
943
+ return false;
944
+ }
945
+ if (metadata.regex && !value.match(metadata.regex)) {
946
+ return false;
947
+ }
948
+ return true;
949
+ }
589
950
  static isNumberValid(value, metadata) {
590
951
  if (metadata.max && value > metadata.max) {
591
952
  return false;
@@ -608,8 +969,13 @@ class EntityUtilities {
608
969
  return true;
609
970
  }
610
971
  static isDateRangeValid(value, metadata) {
611
- if (metadata.required && (!value.start || !value.end)) {
612
- return false;
972
+ if (metadata.required) {
973
+ if (!value.start) {
974
+ return false;
975
+ }
976
+ if (!value.end) {
977
+ return false;
978
+ }
613
979
  }
614
980
  value.start = new Date(value.start);
615
981
  value.end = new Date(value.end);
@@ -679,6 +1045,27 @@ class EntityUtilities {
679
1045
  }
680
1046
  return true;
681
1047
  }
1048
+ static isFileDataValid(value, metadata) {
1049
+ const files = metadata.multiple ? value : [value];
1050
+ let fileSizeTotal = 0;
1051
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
1052
+ for (let i = 0; i < files.length; i++) {
1053
+ if (!files[i].name || !files[i].file && !files[i].url) {
1054
+ return false;
1055
+ }
1056
+ if (!FileUtilities.isMimeTypeValid(files[i].type, metadata.allowedMimeTypes)) {
1057
+ return false;
1058
+ }
1059
+ if (FileUtilities.transformToMegaBytes(files[i].size, 'B') > metadata.maxSize) {
1060
+ return false;
1061
+ }
1062
+ fileSizeTotal += files[i].size;
1063
+ if (FileUtilities.transformToMegaBytes(fileSizeTotal, 'B') > metadata.maxSizeTotal) {
1064
+ return false;
1065
+ }
1066
+ }
1067
+ return true;
1068
+ }
682
1069
  /**
683
1070
  * Checks if an entity is "dirty" (if its values have changed).
684
1071
  *
@@ -686,19 +1073,21 @@ class EntityUtilities {
686
1073
  * @param entityPriorChanges - The entity before the changes.
687
1074
  * @returns Whether or not the entity is dirty.
688
1075
  */
689
- static dirty(entity, entityPriorChanges) {
1076
+ static async isDirty(entity, entityPriorChanges) {
690
1077
  if (!entityPriorChanges) {
691
1078
  return false;
692
1079
  }
693
1080
  else {
694
- const differences = this.differencesForDirty(entity, entityPriorChanges);
1081
+ const differences = await EntityUtilities.differencesForDirty(entity, entityPriorChanges);
695
1082
  return differences.length ? true : false;
696
1083
  }
697
1084
  }
698
- static differencesForDirty(entity, entityPriorChanges) {
1085
+ static async differencesForDirty(entity, entityPriorChanges) {
699
1086
  const res = [];
700
1087
  for (const key in entity) {
701
- if (!this.isEqual(entity[key], entityPriorChanges[key], EntityUtilities.getPropertyMetadata(entity, key))) {
1088
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
1089
+ const type = EntityUtilities.getPropertyType(entity, key);
1090
+ if (!(await EntityUtilities.isEqual(entity[key], entityPriorChanges[key], metadata, type))) {
702
1091
  res.push({
703
1092
  key: key,
704
1093
  before: entityPriorChanges[key],
@@ -715,48 +1104,121 @@ class EntityUtilities {
715
1104
  * @param entityPriorChanges - The second entity to compare.
716
1105
  * @returns The difference between the two Entities in form of a Partial.
717
1106
  */
718
- static difference(entity, entityPriorChanges) {
1107
+ static async difference(entity, entityPriorChanges) {
719
1108
  const res = {};
720
1109
  for (const key in entity) {
721
- if (!this.isEqual(entity[key], entityPriorChanges[key], EntityUtilities.getPropertyMetadata(entity, key))) {
1110
+ const metadata = EntityUtilities.getPropertyMetadata(entity, key);
1111
+ const type = EntityUtilities.getPropertyType(entity, key);
1112
+ if (!(await EntityUtilities.isEqual(entity[key], entityPriorChanges[key], metadata, type))) {
722
1113
  res[key] = entity[key];
723
1114
  }
724
1115
  }
725
1116
  return res;
726
1117
  }
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;
1118
+ /**
1119
+ * Checks if two given values are equal.
1120
+ * It uses the isEqual method from LodashUtilities and extends it with functionality regarding Dates.
1121
+ *
1122
+ * @param value - The updated value.
1123
+ * @param valuePriorChanges - The value before any changes.
1124
+ * @param metadata - The metadata of the property.
1125
+ * @param type - The type of the property.
1126
+ * @returns Whether or not the given values are equal.
1127
+ */
1128
+ static async isEqual(value, valuePriorChanges, metadata, type) {
1129
+ switch (type) {
1130
+ case DecoratorTypes.DATE_RANGE:
1131
+ return EntityUtilities.isEqualDateRange(value, valuePriorChanges, metadata.filter);
1132
+ case DecoratorTypes.DATE:
1133
+ return EntityUtilities.isEqualDate(value, valuePriorChanges);
1134
+ case DecoratorTypes.DATE_TIME:
1135
+ return EntityUtilities.isEqualDateTime(value, valuePriorChanges);
1136
+ case DecoratorTypes.ARRAY_DATE:
1137
+ case DecoratorTypes.ARRAY_DATE_TIME:
1138
+ return EntityUtilities.isEqualArrayDate(value, valuePriorChanges);
1139
+ case DecoratorTypes.ARRAY_DATE_RANGE:
1140
+ return EntityUtilities.isEqualArrayDateRange(value, valuePriorChanges, metadata.filter);
1141
+ case DecoratorTypes.FILE_IMAGE:
1142
+ case DecoratorTypes.FILE_DEFAULT:
1143
+ return EntityUtilities.isEqualFile(value, valuePriorChanges, metadata.multiple);
1144
+ case DecoratorTypes.CUSTOM:
1145
+ // eslint-disable-next-line max-len, @typescript-eslint/no-explicit-any
1146
+ return EntityUtilities.isEqualCustom(value, valuePriorChanges, metadata);
1147
+ default:
1148
+ return LodashUtilities.isEqual(value, valuePriorChanges);
1149
+ }
1150
+ }
1151
+ static isEqualArrayDate(value, valuePriorChanges) {
1152
+ const newValue = value.map(v => new Date(v)).sort();
1153
+ const newValuePriorChanges = valuePriorChanges.map(v => new Date(v)).sort();
1154
+ return LodashUtilities.isEqual(newValue, newValuePriorChanges);
1155
+ }
1156
+ static isEqualArrayDateRange(value, valuePriorChanges, filter) {
1157
+ const dateRanges = value.sort();
1158
+ const dateRangesPriorChanges = valuePriorChanges.sort();
1159
+ if (dateRanges.length !== dateRangesPriorChanges.length) {
1160
+ return false;
1161
+ }
1162
+ for (let i = 0; i < dateRanges.length; i++) {
1163
+ if (!EntityUtilities.isEqualDateRange(dateRanges[i], dateRangesPriorChanges[i], filter)) {
1164
+ return false;
755
1165
  }
756
- catch (error) { }
757
- ;
758
1166
  }
759
- return false;
1167
+ return true;
1168
+ }
1169
+ static isEqualDateTime(value, valuePriorChanges) {
1170
+ const date = new Date(value);
1171
+ const datePriorChanges = new Date(valuePriorChanges);
1172
+ return LodashUtilities.isEqual(date, datePriorChanges);
1173
+ }
1174
+ static isEqualDate(value, valuePriorChanges) {
1175
+ const date = new Date(value);
1176
+ const datePriorChanges = new Date(valuePriorChanges);
1177
+ date.setHours(0, 0, 0, 0);
1178
+ datePriorChanges.setHours(0, 0, 0, 0);
1179
+ return LodashUtilities.isEqual(date, datePriorChanges);
1180
+ }
1181
+ static isEqualDateRange(value, valuePriorChanges, filter) {
1182
+ const dateRange = LodashUtilities.cloneDeep(value);
1183
+ dateRange.start = new Date(value.start);
1184
+ dateRange.end = new Date(value.end);
1185
+ dateRange.values = DateUtilities.getDatesBetween(dateRange.start, dateRange.end, filter);
1186
+ const dateRangePriorChanges = LodashUtilities.cloneDeep(valuePriorChanges);
1187
+ dateRangePriorChanges.start = new Date(valuePriorChanges.start);
1188
+ dateRangePriorChanges.end = new Date(valuePriorChanges.end);
1189
+ dateRangePriorChanges.values = DateUtilities.getDatesBetween(dateRangePriorChanges.start, dateRangePriorChanges.end, filter);
1190
+ return LodashUtilities.isEqual(dateRange, dateRangePriorChanges);
1191
+ }
1192
+ // TODO: Find a way to use blobs with jest
1193
+ /* istanbul ignore next */
1194
+ static async isEqualFile(value, valuePriorChanges, multiple) {
1195
+ const files = multiple ? value.sort() : [value].sort();
1196
+ const filesPriorChanges = multiple ? valuePriorChanges.sort() : [valuePriorChanges].sort();
1197
+ if (files.length !== filesPriorChanges.length) {
1198
+ return false;
1199
+ }
1200
+ for (let i = 0; i < files.length; i++) {
1201
+ // checks this before actually getting any files due to performance reasons.
1202
+ if (!LodashUtilities.isEqual(files[i]?.name, filesPriorChanges[i]?.name)
1203
+ || !LodashUtilities.isEqual(files[i]?.url, filesPriorChanges[i]?.url)) {
1204
+ return false;
1205
+ }
1206
+ files[i] = filesPriorChanges[i].file && !files[i].file ? await FileUtilities.getFileData(files[i]) : files[i];
1207
+ // eslint-disable-next-line max-len
1208
+ filesPriorChanges[i] = files[i].file && !filesPriorChanges[i].file ? await FileUtilities.getFileData(filesPriorChanges[i]) : filesPriorChanges[i];
1209
+ if (!LodashUtilities.isEqual(await files[i].file?.text(), await filesPriorChanges[i].file?.text())) {
1210
+ return false;
1211
+ }
1212
+ }
1213
+ return true;
1214
+ }
1215
+ static isEqualCustom(value, valuePriorChanges,
1216
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1217
+ metadata) {
1218
+ if (!metadata.isEqual(value, valuePriorChanges, metadata)) {
1219
+ return false;
1220
+ }
1221
+ return true;
760
1222
  }
761
1223
  /**
762
1224
  * Compare function for sorting entity keys by their order value.
@@ -778,7 +1240,7 @@ class EntityUtilities {
778
1240
  else if (metadataB.position.order === -1) {
779
1241
  return -1;
780
1242
  }
781
- return ((metadataA.position.order) - (metadataB.position.order));
1243
+ return metadataA.position.order - metadataB.position.order;
782
1244
  }
783
1245
  /**
784
1246
  * Gets the bootstrap column values for "lg", "md", "sm".
@@ -807,7 +1269,7 @@ class EntityUtilities {
807
1269
  */
808
1270
  static resetChangesOnEntity(entity, entityPriorChanges) {
809
1271
  for (const key in entityPriorChanges) {
810
- Reflect.set(entity, key, Reflect.get(entityPriorChanges, key));
1272
+ ReflectUtilities.set(entity, key, ReflectUtilities.get(entityPriorChanges, key));
811
1273
  }
812
1274
  }
813
1275
  /**
@@ -821,17 +1283,17 @@ class EntityUtilities {
821
1283
  static getEntityRows(entity, hideOmitForCreate = false, hideOmitForEdit = false) {
822
1284
  const res = [];
823
1285
  const keys = EntityUtilities.keysOf(entity, hideOmitForCreate, hideOmitForEdit);
824
- const numberOfRows = this.getNumberOfRows(keys, entity);
1286
+ const numberOfRows = EntityUtilities.getNumberOfRows(keys, entity);
825
1287
  for (let i = 1; i <= numberOfRows; i++) {
826
1288
  const row = {
827
1289
  row: i,
828
- keys: this.getKeysForRow(keys, entity, i)
1290
+ keys: EntityUtilities.getKeysForRow(keys, entity, i)
829
1291
  };
830
1292
  res.push(row);
831
1293
  }
832
1294
  const lastRow = {
833
1295
  row: numberOfRows + 1,
834
- keys: this.getKeysForRow(keys, entity, -1)
1296
+ keys: EntityUtilities.getKeysForRow(keys, entity, -1)
835
1297
  };
836
1298
  res.push(lastRow);
837
1299
  return res;
@@ -855,7 +1317,7 @@ class EntityUtilities {
855
1317
  * @returns An array of keys of the entity.
856
1318
  */
857
1319
  static keysOf(entity, hideOmitForCreate = false, hideOmitForEdit = false) {
858
- let keys = Reflect.ownKeys(entity);
1320
+ let keys = ReflectUtilities.ownKeys(entity);
859
1321
  if (hideOmitForCreate) {
860
1322
  const omitForCreateKeys = EntityUtilities.getOmitForCreate(entity);
861
1323
  keys = keys.filter(k => !omitForCreateKeys.includes(k));
@@ -873,19 +1335,39 @@ EntityUtilities.construct = EntityUtilities.new;
873
1335
  EntityUtilities.build = EntityUtilities.new;
874
1336
 
875
1337
  /**
876
- * A generic EntityService class.
877
- * Offers basic CRUD-functionality.
878
- * You should create a service for every Entity you have.
879
- * If you extend from this you need to make sure that the extended Service can be injected.
1338
+ * A base Entity class with a builtin id.
880
1339
  */
881
- class EntityService {
882
- constructor(http) {
883
- this.http = http;
884
- /**
885
- * The key which holds the id value.
886
- *
887
- * @default 'id'
888
- */
1340
+ class Entity {
1341
+ constructor(entity) {
1342
+ EntityUtilities.new(this, entity);
1343
+ }
1344
+ }
1345
+ __decorate([
1346
+ string({
1347
+ omitForCreate: true,
1348
+ omitForUpdate: true,
1349
+ display: false,
1350
+ displayStyle: 'line',
1351
+ displayName: 'ID',
1352
+ required: true
1353
+ }),
1354
+ __metadata("design:type", String)
1355
+ ], Entity.prototype, "id", void 0);
1356
+
1357
+ /**
1358
+ * A generic EntityService class.
1359
+ * Offers basic CRUD-functionality.
1360
+ * You should create a service for every Entity you have.
1361
+ * If you extend from this you need to make sure that the extended Service can be injected.
1362
+ */
1363
+ class EntityService {
1364
+ constructor(http) {
1365
+ this.http = http;
1366
+ /**
1367
+ * The key which holds the id value.
1368
+ *
1369
+ * @default 'id'
1370
+ */
889
1371
  this.idKey = 'id';
890
1372
  /**
891
1373
  * A subject of all the entity values.
@@ -909,7 +1391,54 @@ class EntityService {
909
1391
  * @returns A Promise of the created entity.
910
1392
  */
911
1393
  async create(entity) {
912
- const body = omit(entity, EntityUtilities.getOmitForCreate(entity));
1394
+ const body = LodashUtilities.omit(entity, EntityUtilities.getOmitForCreate(entity));
1395
+ const filePropertyKeys = EntityUtilities.getFileProperties(entity);
1396
+ if (!filePropertyKeys.length) {
1397
+ return await this.createWithJson(body);
1398
+ }
1399
+ else {
1400
+ return await this.createWithFormData(body, filePropertyKeys, entity);
1401
+ }
1402
+ }
1403
+ // TODO: Find a way to use blobs with jest
1404
+ /* istanbul ignore next */
1405
+ /**
1406
+ * Creates the entity with form data when the entity contains files in contrast to creating it with a normal json body.
1407
+ * All file values are stored inside their respective property key and their name.
1408
+ * Form data is able to handle setting multiple files to the same key.
1409
+ *
1410
+ * @param body - The body Of the request.
1411
+ * @param filePropertyKeys - All property keys that are files and need to be added to the form data.
1412
+ * @param entity - The entity to create. This is needed in addition to the body because the body doesn't contain any metadata.
1413
+ * @returns The created entity from the server.
1414
+ */
1415
+ async createWithFormData(body, filePropertyKeys, entity) {
1416
+ const formData = new FormData();
1417
+ formData.append('body', JSON.stringify(LodashUtilities.omit(body, filePropertyKeys)));
1418
+ for (const key of filePropertyKeys) {
1419
+ if (EntityUtilities.getPropertyMetadata(entity, key, DecoratorTypes.FILE_DEFAULT).multiple) {
1420
+ const fileDataValues = body[key];
1421
+ for (const value of fileDataValues) {
1422
+ formData.append(key, (await FileUtilities.getFileData(value)).file, value.name);
1423
+ }
1424
+ }
1425
+ else {
1426
+ const fileData = body[key];
1427
+ formData.append(key, (await FileUtilities.getFileData(fileData)).file, fileData.name);
1428
+ }
1429
+ }
1430
+ const e = await firstValueFrom(this.http.post(this.baseUrl, formData));
1431
+ this.entities.push(e);
1432
+ this.entitiesSubject.next(this.entities);
1433
+ return e;
1434
+ }
1435
+ /**
1436
+ * Creates the entity with a normal json body in contrast to creating it with form data when the entity contains files.
1437
+ *
1438
+ * @param body - The body Of the request.
1439
+ * @returns The created entity from the server.
1440
+ */
1441
+ async createWithJson(body) {
913
1442
  const e = await firstValueFrom(this.http.post(this.baseUrl, body));
914
1443
  this.entities.push(e);
915
1444
  this.entitiesSubject.next(this.entities);
@@ -934,9 +1463,57 @@ class EntityService {
934
1463
  * It Is used to get changed values and only update them instead of sending the whole entity data.
935
1464
  */
936
1465
  async update(entity, entityPriorChanges) {
937
- const reqBody = omit(EntityUtilities.difference(entity, entityPriorChanges), EntityUtilities.getOmitForUpdate(entity));
938
- const updatedEntity = await firstValueFrom(this.http.patch(`${this.baseUrl}/${entityPriorChanges[this.idKey]}`, omitBy(reqBody, isNil)));
939
- this.entities[this.entities.findIndex(e => e[this.idKey] === entityPriorChanges[this.idKey])] = updatedEntity;
1466
+ const body = LodashUtilities.omit(await EntityUtilities.difference(entity, entityPriorChanges), EntityUtilities.getOmitForUpdate(entity));
1467
+ const filePropertyKeys = EntityUtilities.getFileProperties(entityPriorChanges);
1468
+ if (!filePropertyKeys.length) {
1469
+ await this.updateWithJson(body, entityPriorChanges[this.idKey]);
1470
+ }
1471
+ else {
1472
+ await this.updateWithFormData(body, filePropertyKeys, entity, entityPriorChanges[this.idKey]);
1473
+ }
1474
+ }
1475
+ // TODO: Find a way to use blobs with jest
1476
+ /* istanbul ignore next */
1477
+ /**
1478
+ * Updates the entity with form data when the entity contains files in contrast to creating it with a normal json body.
1479
+ * All file values are stored inside their respective property key and their name.
1480
+ * Form data is able to handle setting multiple files to the same key.
1481
+ *
1482
+ * @param body - The request body. Already contains only properties that have changed.
1483
+ * @param filePropertyKeys - The keys of all properties which are files and need to separately be appended to the form data.
1484
+ * @param entity - The original entity. Is needed to get the metadata of all the files.
1485
+ * @param id - The id of the entity to update.
1486
+ */
1487
+ async updateWithFormData(body, filePropertyKeys, entity, id) {
1488
+ const formData = new FormData();
1489
+ formData.append('body', JSON.stringify(LodashUtilities.omitBy(body, LodashUtilities.isNil)));
1490
+ for (const key of filePropertyKeys) {
1491
+ if (EntityUtilities.getPropertyMetadata(entity, key, DecoratorTypes.FILE_DEFAULT).multiple) {
1492
+ // eslint-disable-next-line max-len
1493
+ const fileDataValues = body[key];
1494
+ for (const value of fileDataValues) {
1495
+ formData.append(key, (await FileUtilities.getFileData(value)).file, value.name);
1496
+ }
1497
+ }
1498
+ else {
1499
+ // eslint-disable-next-line max-len
1500
+ const fileData = body[key];
1501
+ formData.append(key, (await FileUtilities.getFileData(fileData)).file, fileData.name);
1502
+ }
1503
+ }
1504
+ const updatedEntity = await firstValueFrom(this.http.patch(`${this.baseUrl}/${id}`, formData));
1505
+ this.entities[this.entities.findIndex(e => e[this.idKey] === id)] = updatedEntity;
1506
+ this.entitiesSubject.next(this.entities);
1507
+ }
1508
+ /**
1509
+ * Updates the entity with a normal json body in contrast to updating it with form data when the entity contains files.
1510
+ *
1511
+ * @param body - The body of the Request. Has already removed all unnecessary values.
1512
+ * @param id - The id of the entity to update.
1513
+ */
1514
+ async updateWithJson(body, id) {
1515
+ const updatedEntity = await firstValueFrom(this.http.patch(`${this.baseUrl}/${id}`, LodashUtilities.omitBy(body, LodashUtilities.isNil)));
1516
+ this.entities[this.entities.findIndex(e => e[this.idKey] === id)] = updatedEntity;
940
1517
  this.entitiesSubject.next(this.entities);
941
1518
  }
942
1519
  /**
@@ -971,7 +1548,6 @@ class BaseBuilder {
971
1548
  validateInput(data) {
972
1549
  // By default, no validation is done
973
1550
  }
974
- ;
975
1551
  /**
976
1552
  * Sets the value for the given key if no user value was provided.
977
1553
  *
@@ -980,7 +1556,7 @@ class BaseBuilder {
980
1556
  * @returns The Builder.
981
1557
  */
982
1558
  withDefault(key, value) {
983
- if (!this.inputData || !this.inputData[key]) {
1559
+ if (this.inputData == null || this.inputData[key] == null) {
984
1560
  this.data[key] = value;
985
1561
  }
986
1562
  return this;
@@ -1018,18 +1594,18 @@ class ConfirmDialogDataBuilder extends BaseBuilder {
1018
1594
  }
1019
1595
  // eslint-disable-next-line jsdoc/require-jsdoc
1020
1596
  generateBaseData(data) {
1021
- return new ConfirmDialogDataInternal(data?.text ? data.text : ['Do you really want to do this?'], data?.type ? data.type : 'default', data?.confirmButtonLabel ? data.confirmButtonLabel : 'Confirm', data?.cancelButtonLabel ? data.cancelButtonLabel : 'Cancel', data?.title ? data.title : 'Confirmation', data?.requireConfirmation ? data.requireConfirmation : false, data?.confirmationText);
1597
+ return new ConfirmDialogDataInternal(data?.text ?? ['Do you really want to do this?'], data?.type ?? 'default', data?.confirmButtonLabel ?? 'Confirm', data?.cancelButtonLabel ?? 'Cancel', data?.title ?? 'Confirmation', data?.requireConfirmation ?? false, data?.confirmationText);
1022
1598
  }
1023
1599
  // eslint-disable-next-line jsdoc/require-jsdoc
1024
1600
  validateInput(data) {
1025
1601
  if (!data) {
1026
1602
  return;
1027
1603
  }
1028
- if (data.requireConfirmation && !data.confirmationText) {
1604
+ if (data.requireConfirmation === true && !data.confirmationText) {
1029
1605
  throw new Error(`Missing required Input data "confirmationText".
1030
1606
  You can only omit this value when "requireConfirmation" is false.`);
1031
1607
  }
1032
- if (!data.requireConfirmation && data.confirmationText) {
1608
+ if (data.requireConfirmation !== true && data.confirmationText) {
1033
1609
  throw new Error('The "confirmationText" will never be shown because "requireConfirmation" is not set to true');
1034
1610
  }
1035
1611
  if (data.type === 'info-only' && data.cancelButtonLabel) {
@@ -1067,10 +1643,10 @@ class NgxMatEntityConfirmDialogComponent {
1067
1643
  }
1068
1644
  }
1069
1645
  NgxMatEntityConfirmDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityConfirmDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
1070
- NgxMatEntityConfirmDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityConfirmDialogComponent, selector: "ngx-mat-entity-confirm-dialog", ngImport: i0, template: "<h2 mat-dialog-title *ngIf=\"data.title\">{{data.title}}</h2>\n\n<mat-dialog-content>\n <p *ngFor=\"let paragraph of data.text\">{{paragraph}}</p>\n <div *ngIf=\"data.requireConfirmation\" class=\"checkbox-wrapper\">\n <mat-checkbox [(ngModel)]=\"confirm\" name=\"confirm\">\n {{data.confirmationText}}\n </mat-checkbox>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button *ngIf=\"data.type === 'delete'\" mat-raised-button color=\"warn\" (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button *ngIf=\"data.type !== 'delete'\" mat-raised-button (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: [".checkbox-wrapper{min-height:50px;display:flex}.checkbox-wrapper>mat-checkbox{align-self:center}mat-dialog-actions{display:flex;justify-content:space-between}\n"], components: [{ type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i3.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i12.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i12.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }] });
1646
+ 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]" }] });
1071
1647
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityConfirmDialogComponent, decorators: [{
1072
1648
  type: Component,
1073
- args: [{ selector: 'ngx-mat-entity-confirm-dialog', template: "<h2 mat-dialog-title *ngIf=\"data.title\">{{data.title}}</h2>\n\n<mat-dialog-content>\n <p *ngFor=\"let paragraph of data.text\">{{paragraph}}</p>\n <div *ngIf=\"data.requireConfirmation\" class=\"checkbox-wrapper\">\n <mat-checkbox [(ngModel)]=\"confirm\" name=\"confirm\">\n {{data.confirmationText}}\n </mat-checkbox>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button *ngIf=\"data.type === 'delete'\" mat-raised-button color=\"warn\" (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button *ngIf=\"data.type !== 'delete'\" mat-raised-button (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: [".checkbox-wrapper{min-height:50px;display:flex}.checkbox-wrapper>mat-checkbox{align-self:center}mat-dialog-actions{display:flex;justify-content:space-between}\n"] }]
1649
+ args: [{ selector: 'ngx-mat-entity-confirm-dialog', template: "<h2 mat-dialog-title *ngIf=\"data.title\">{{data.title}}</h2>\n\n<mat-dialog-content>\n <p *ngFor=\"let paragraph of data.text\">{{paragraph}}</p>\n <div *ngIf=\"data.requireConfirmation\" class=\"checkbox-wrapper\">\n <mat-checkbox [(ngModel)]=\"confirm\" name=\"confirm\">\n {{data.confirmationText}}\n </mat-checkbox>\n </div>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button *ngIf=\"data.type === 'delete'\" mat-raised-button color=\"warn\" (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button *ngIf=\"data.type !== 'delete'\" mat-raised-button (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button *ngIf=\"data.type !== 'info-only'\" mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: [".checkbox-wrapper{min-height:50px;display:flex}.checkbox-wrapper>mat-checkbox{align-self:center}mat-dialog-actions{display:flex;justify-content:space-between}\n"] }]
1074
1650
  }], ctorParameters: function () { return [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{
1075
1651
  type: Inject,
1076
1652
  args: [MAT_DIALOG_DATA]
@@ -1153,7 +1729,7 @@ class CreateDialogDataBuilder extends BaseBuilder {
1153
1729
  .withDefault('text', ['Do you really want to create this entity?'])
1154
1730
  .withDefault('title', 'Create')
1155
1731
  .getResult();
1156
- return new CreateDialogDataInternal(data?.title ? data.title : 'Create', data?.createButtonLabel ? data.createButtonLabel : 'Create', data?.cancelButtonLabel ? data.cancelButtonLabel : 'Cancel', data?.createRequiresConfirmDialog ? data.createRequiresConfirmDialog : false, confirmCreateDialogData);
1732
+ return new CreateDialogDataInternal(data?.title ?? 'Create', data?.createButtonLabel ?? 'Create', data?.cancelButtonLabel ?? 'Cancel', data?.createRequiresConfirmDialog ?? false, confirmCreateDialogData);
1157
1733
  }
1158
1734
  }
1159
1735
 
@@ -1180,181 +1756,1127 @@ class AddArrayItemDialogDataBuilder extends BaseBuilder {
1180
1756
  .withDefault('createButtonLabel', 'Add')
1181
1757
  .withDefault('title', 'Add to array')
1182
1758
  .getResult();
1183
- return new AddArrayItemDialogDataInternal(data.entity, createDialogData, data.getValidationErrorMessage ? data.getValidationErrorMessage : getValidationErrorMessage);
1759
+ return new AddArrayItemDialogDataInternal(data.entity, createDialogData, data.getValidationErrorMessage ?? getValidationErrorMessage);
1184
1760
  }
1185
1761
  }
1186
1762
 
1187
1763
  /**
1188
- * The default input component. It gets the metadata of the property from the given @Input "entity" and @Input "propertyKey"
1189
- * and displays the input field accordingly.
1764
+ * The abstract base class of any ngx-mat-entity input.
1765
+ * Extend from this when implementing your own custom decorator.
1190
1766
  *
1191
- * You can also define a method that generates error-messages and if the input should be hidden when its metadata says
1192
- * that it should be omitted for creating or updating.
1193
- * The last part being mostly relevant if you want to use this component inside an ngFor.
1767
+ * It already provides:
1768
+ *
1769
+ * - entity: The entity which the property is on. (type-safe due to the Generic "EntityType")
1770
+ * - key: The key of the property. (type-safe due to the Generic "EntityType")
1771
+ * - getValidationErrorMessage: The function that generates the error message when the input is invalid.
1772
+ * - isReadOnly: Whether or not the input is read only. Can be used to disable elements.
1773
+ * - propertyValue: Just the typed version of the property, its the same as entity[key].
1774
+ * - metadata: The metadata of the property. (type-safe due to the Generic "CustomMetadataType")
1775
+ * - ngOnInit: Gets the metadata for the property, be aware of this when overriding this method.
1776
+ * - emitChange: Should be called when the input has changed. This is needed to trigger validation and dirty checks.
1194
1777
  */
1195
- class NgxMatEntityInputComponent {
1196
- constructor(dialog) {
1197
- this.dialog = dialog;
1198
- this.chipsInput = '';
1199
- this.selection = new SelectionModel(true, []);
1200
- this.DecoratorTypes = DecoratorTypes;
1201
- this.EntityUtilities = EntityUtilities;
1202
- this.DateUtilities = DateUtilities;
1203
- this.defaultDateFilter = () => true;
1778
+ // eslint-disable-next-line max-len
1779
+ class NgxMatEntityBaseInputComponent {
1780
+ constructor() {
1781
+ this.inputChangeEvent = new EventEmitter();
1204
1782
  }
1783
+ // eslint-disable-next-line jsdoc/require-returns
1205
1784
  /**
1206
- * This is needed for the inputs to work inside an ngFor.
1207
- *
1208
- * @param index - The index of the element in the ngFor.
1209
- * @returns The index.
1785
+ * The property value of entity[key] correctly typed.
1786
+ * Uses getters and setters so that inputs are always linked to the original value.
1210
1787
  */
1211
- trackByFn(index) {
1212
- return index;
1788
+ get propertyValue() {
1789
+ return this.entity[this.key];
1790
+ }
1791
+ // eslint-disable-next-line jsdoc/require-jsdoc
1792
+ set propertyValue(value) {
1793
+ this.entity[this.key] = value;
1213
1794
  }
1214
1795
  ngOnInit() {
1215
- if (!this.entity) {
1216
- throw new Error('Missing required Input data "entity"');
1217
- }
1218
- if (!this.propertyKey) {
1219
- throw new Error('Missing required Input data "propertyKey"');
1220
- }
1221
- this.type = EntityUtilities.getPropertyType(this.entity, this.propertyKey);
1222
- this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.propertyKey, this.type);
1223
- this.metadataDefaultString = this.metadata;
1224
- this.metadataTextboxString = this.metadata;
1225
- this.metadataAutocompleteString = this.metadata;
1226
- this.autocompleteStrings = this.metadataAutocompleteString.autocompleteValues;
1227
- this.filteredAutocompleteStrings = cloneDeep(this.autocompleteStrings);
1228
- this.metadataDropdownString = this.metadata;
1229
- this.metadataDropdownBoolean = this.metadata;
1230
- if ((this.type === DecoratorTypes.BOOLEAN_CHECKBOX || this.type === DecoratorTypes.BOOLEAN_TOGGLE)
1231
- && this.entity[this.propertyKey] === undefined) {
1232
- this.entity[this.propertyKey] = false;
1233
- }
1234
- this.metadataDefaultNumber = this.metadata;
1235
- this.metadataDropdownNumber = this.metadata;
1236
- this.metadataDefaultObject = this.metadata;
1237
- this.objectProperty = this.entity[this.propertyKey];
1238
- if (this.type === DecoratorTypes.OBJECT) {
1239
- this.objectPropertyRows = EntityUtilities.getEntityRows(this.objectProperty, this.hideOmitForCreate, this.hideOmitForEdit);
1240
- }
1241
- this.metadataEntityArray = this.metadata;
1242
- if (this.type === DecoratorTypes.ARRAY) {
1243
- if (!this.entity[this.propertyKey]) {
1244
- this.entity[this.propertyKey] = [];
1245
- }
1246
- this.entityArrayValues = this.entity[this.propertyKey];
1247
- if (this.metadataEntityArray.createInline === undefined) {
1248
- this.metadataEntityArray.createInline = true;
1249
- }
1250
- if (!this.metadataEntityArray.createInline && !this.metadataEntityArray.createDialogData) {
1251
- this.metadataEntityArray.createDialogData = {
1252
- title: 'Add'
1253
- };
1254
- }
1255
- const givenDisplayColumns = this.metadataEntityArray.displayColumns.map((v) => v.displayName);
1256
- if (givenDisplayColumns.find(s => s === 'select')) {
1257
- throw new Error(`The name "select" for a display column is reserved.
1258
- Please choose a different name.`);
1259
- }
1260
- this.displayedColumns = ['select'].concat(givenDisplayColumns);
1261
- this.dataSource = new MatTableDataSource();
1262
- this.dataSource.data = this.entityArrayValues;
1263
- this.arrayItem = new this.metadataEntityArray.EntityClass();
1264
- this.arrayItemInlineRows = EntityUtilities.getEntityRows(this.arrayItem, this.hideOmitForCreate === false ? false : true, this.hideOmitForEdit ? true : false);
1265
- this.arrayItemPriorChanges = cloneDeep(this.arrayItem);
1266
- this.dialogInputData = {
1267
- entity: this.arrayItem,
1268
- createDialogData: this.metadataEntityArray.createDialogData,
1269
- getValidationErrorMessage: this.getValidationErrorMessage
1270
- };
1271
- this.dialogData = new AddArrayItemDialogDataBuilder(this.dialogInputData).getResult();
1272
- this.arrayItemDialogRows = EntityUtilities.getEntityRows(this.dialogData.entity, true);
1273
- }
1274
- this.metadataStringChipsArray = this.metadata;
1275
- if ((this.type === DecoratorTypes.ARRAY_STRING_CHIPS || this.type === DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS)
1276
- && this.entity[this.propertyKey]?.length) {
1277
- this.stringChipsArrayValues = this.entity[this.propertyKey];
1278
- }
1279
- this.metadataAutocompleteStringChipsArray = this.metadata;
1280
- if (!this.getValidationErrorMessage) {
1281
- this.getValidationErrorMessage = getValidationErrorMessage;
1282
- }
1283
- this.metadataDefaultDate = this.metadata;
1284
- this.metadataDateRangeDate = this.metadata;
1285
- this.metadataDateTimeDate = this.metadata;
1286
- if (this.type === DecoratorTypes.DATE_RANGE) {
1287
- this.dateRange = cloneDeep(this.entity[this.propertyKey]);
1288
- if (!this.dateRange) {
1289
- this.dateRange = {
1290
- start: undefined,
1291
- end: undefined,
1292
- values: undefined
1293
- };
1294
- }
1295
- this.dateRangeStart = new Date(this.dateRange.start);
1296
- this.dateRangeEnd = new Date(this.dateRange.end);
1297
- this.setDateRangeValues();
1298
- }
1299
- if (this.type === DecoratorTypes.DATE_TIME) {
1300
- this.time = DateUtilities.getTimeFromDate(DateUtilities.asDate(this.entity[this.propertyKey]));
1301
- this.timeDropdownValues = this.metadataDateTimeDate.times;
1302
- if (this.entity[this.propertyKey]) {
1303
- this.dateTime = new Date(this.entity[this.propertyKey]);
1304
- }
1305
- }
1796
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key);
1306
1797
  }
1307
1798
  /**
1308
- * Checks if two times are equal. Is needed for the dropdown.
1309
- *
1310
- * @param time1 - The first time to compare.
1311
- * @param time2 - The second time to compare.
1312
- * @returns Whether or not the time objects are the same.
1799
+ * Should emit when the input has changed. This is needed to trigger validation and dirty checks.
1313
1800
  */
1314
- compareTimes(time1, time2) {
1315
- return time1 && time2 && time1.hours === time2.hours && time1.minutes === time2.minutes;
1801
+ emitChange() {
1802
+ this.inputChangeEvent.emit();
1803
+ }
1804
+ }
1805
+ NgxMatEntityBaseInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityBaseInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1806
+ 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 });
1807
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityBaseInputComponent, decorators: [{
1808
+ type: Component,
1809
+ args: [{
1810
+ selector: 'ngx-mat-entity-base-input',
1811
+ template: ''
1812
+ }]
1813
+ }], propDecorators: { entity: [{
1814
+ type: Input
1815
+ }], key: [{
1816
+ type: Input
1817
+ }], getValidationErrorMessage: [{
1818
+ type: Input
1819
+ }], isReadOnly: [{
1820
+ type: Input
1821
+ }], inputChangeEvent: [{
1822
+ type: Output
1823
+ }] } });
1824
+
1825
+ /* eslint-disable jsdoc/require-jsdoc */
1826
+ class StringInputComponent extends NgxMatEntityBaseInputComponent {
1827
+ }
1828
+ StringInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1829
+ 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"] }] });
1830
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringInputComponent, decorators: [{
1831
+ type: Component,
1832
+ 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"] }]
1833
+ }] });
1834
+
1835
+ /* eslint-disable jsdoc/require-jsdoc */
1836
+ class StringTextboxInputComponent extends NgxMatEntityBaseInputComponent {
1837
+ }
1838
+ StringTextboxInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringTextboxInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1839
+ 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"] }] });
1840
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringTextboxInputComponent, decorators: [{
1841
+ type: Component,
1842
+ 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"] }]
1843
+ }] });
1844
+
1845
+ /* eslint-disable jsdoc/require-jsdoc */
1846
+ class StringAutocompleteInputComponent extends NgxMatEntityBaseInputComponent {
1847
+ ngOnInit() {
1848
+ super.ngOnInit();
1849
+ this.autocompleteStrings = this.metadata.autocompleteValues;
1850
+ this.filteredAutocompleteStrings = LodashUtilities.cloneDeep(this.autocompleteStrings);
1316
1851
  }
1317
1852
  /**
1318
- * Updates the date range values based on the start and end date.
1853
+ * Dynamically filters the Autocomplete options when the user inputs something.
1854
+ *
1855
+ * @param input - The input of the user.
1319
1856
  */
1320
- setDateRangeValues() {
1321
- if (this.dateRangeStart && this.dateRangeEnd) {
1322
- this.dateRange.start = new Date(this.dateRangeStart);
1323
- this.dateRange.end = new Date(this.dateRangeEnd);
1324
- const values = DateUtilities.getDatesBetween(new Date(this.dateRange.start), new Date(this.dateRange.end), this.metadataDateRangeDate);
1325
- this.dateRange.values = values.length ? values : undefined;
1857
+ filterAutocompleteStrings(input) {
1858
+ if (input) {
1859
+ this.filteredAutocompleteStrings = this.autocompleteStrings.filter(s => s.toLowerCase().includes(input.toLowerCase()));
1326
1860
  }
1327
- else {
1328
- this.dateRange.values = undefined;
1861
+ }
1862
+ }
1863
+ StringAutocompleteInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringAutocompleteInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1864
+ 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"] }] });
1865
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringAutocompleteInputComponent, decorators: [{
1866
+ type: Component,
1867
+ 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"] }]
1868
+ }] });
1869
+
1870
+ /* eslint-disable jsdoc/require-jsdoc */
1871
+ class StringDropdownInputComponent extends NgxMatEntityBaseInputComponent {
1872
+ }
1873
+ StringDropdownInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringDropdownInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1874
+ 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"] }] });
1875
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringDropdownInputComponent, decorators: [{
1876
+ type: Component,
1877
+ 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"] }]
1878
+ }] });
1879
+
1880
+ /* eslint-disable jsdoc/require-jsdoc */
1881
+ class StringPasswordInputComponent extends NgxMatEntityBaseInputComponent {
1882
+ constructor() {
1883
+ super(...arguments);
1884
+ this.hide = true;
1885
+ this.hideConfirm = true;
1886
+ }
1887
+ ngOnInit() {
1888
+ super.ngOnInit();
1889
+ this.confirmRequired = this.metadata.required;
1890
+ this.confirmPassword = LodashUtilities.cloneDeep(this.propertyValue);
1891
+ ReflectUtilities.defineMetadata('confirmPassword', this.confirmPassword, this.entity, this.key);
1892
+ }
1893
+ passwordInput() {
1894
+ this.confirmRequired = Boolean(this.propertyValue);
1895
+ ReflectUtilities.defineMetadata('confirmPassword', this.confirmPassword, this.entity, this.key);
1896
+ this.emitChange();
1897
+ }
1898
+ }
1899
+ StringPasswordInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringPasswordInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1900
+ 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"] }] });
1901
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: StringPasswordInputComponent, decorators: [{
1902
+ type: Component,
1903
+ 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"] }]
1904
+ }] });
1905
+
1906
+ /* eslint-disable jsdoc/require-jsdoc */
1907
+ class BooleanCheckboxInputComponent extends NgxMatEntityBaseInputComponent {
1908
+ ngOnInit() {
1909
+ super.ngOnInit();
1910
+ this.propertyValue = this.propertyValue ?? false;
1911
+ }
1912
+ }
1913
+ BooleanCheckboxInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanCheckboxInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1914
+ 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"] }] });
1915
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanCheckboxInputComponent, decorators: [{
1916
+ type: Component,
1917
+ 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"] }]
1918
+ }] });
1919
+
1920
+ /* eslint-disable jsdoc/require-jsdoc */
1921
+ class BooleanToggleInputComponent extends NgxMatEntityBaseInputComponent {
1922
+ ngOnInit() {
1923
+ super.ngOnInit();
1924
+ this.propertyValue = this.propertyValue ?? false;
1925
+ }
1926
+ }
1927
+ BooleanToggleInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanToggleInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1928
+ 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"] }] });
1929
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanToggleInputComponent, decorators: [{
1930
+ type: Component,
1931
+ 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"] }]
1932
+ }] });
1933
+
1934
+ /* eslint-disable jsdoc/require-jsdoc */
1935
+ class BooleanDropdownInputComponent extends NgxMatEntityBaseInputComponent {
1936
+ }
1937
+ BooleanDropdownInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanDropdownInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1938
+ 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"] }] });
1939
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: BooleanDropdownInputComponent, decorators: [{
1940
+ type: Component,
1941
+ 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"] }]
1942
+ }] });
1943
+
1944
+ /* eslint-disable jsdoc/require-jsdoc */
1945
+ class NumberInputComponent extends NgxMatEntityBaseInputComponent {
1946
+ }
1947
+ NumberInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1948
+ 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"] }] });
1949
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberInputComponent, decorators: [{
1950
+ type: Component,
1951
+ 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"] }]
1952
+ }] });
1953
+
1954
+ /* eslint-disable jsdoc/require-jsdoc */
1955
+ class NumberDropdownInputComponent extends NgxMatEntityBaseInputComponent {
1956
+ }
1957
+ NumberDropdownInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberDropdownInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1958
+ 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"] }] });
1959
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberDropdownInputComponent, decorators: [{
1960
+ type: Component,
1961
+ 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"] }]
1962
+ }] });
1963
+
1964
+ /* eslint-disable jsdoc/require-jsdoc */
1965
+ class NumberSliderInputComponent extends NgxMatEntityBaseInputComponent {
1966
+ }
1967
+ NumberSliderInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberSliderInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1968
+ 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"] }] });
1969
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NumberSliderInputComponent, decorators: [{
1970
+ type: Component,
1971
+ 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"] }]
1972
+ }] });
1973
+
1974
+ /* eslint-disable jsdoc/require-jsdoc */
1975
+ /**
1976
+ * The base data needed for all arrays that are displayed as a table.
1977
+ */
1978
+ class ArrayTableComponent extends NgxMatEntityBaseInputComponent {
1979
+ constructor(matDialog) {
1980
+ super();
1981
+ this.matDialog = matDialog;
1982
+ this.input = undefined;
1983
+ this.dataSource = new MatTableDataSource();
1984
+ this.selection = new SelectionModel(true, []);
1985
+ }
1986
+ ngOnInit() {
1987
+ super.ngOnInit();
1988
+ this.propertyValue = this.propertyValue ?? [];
1989
+ const givenDisplayColumns = this.metadata.displayColumns.map((v) => v.displayName);
1990
+ if (givenDisplayColumns.find(s => s === 'select')) {
1991
+ throw new Error(`The name "select" for a display column is reserved.
1992
+ Please choose a different name.`);
1329
1993
  }
1330
- this.entity[this.propertyKey] = this.dateRange;
1994
+ this.displayedColumns = this.isReadOnly ? givenDisplayColumns : ['select'].concat(givenDisplayColumns);
1995
+ this.dataSource.data = this.propertyValue;
1331
1996
  }
1332
1997
  /**
1333
- * Sets the time on a datetime property.
1998
+ * Toggles all array-items in the table.
1999
+ *
1334
2000
  */
1335
- setTime() {
1336
- if (!this.dateTime) {
1337
- this.entity[this.propertyKey] = undefined;
1338
- return;
1339
- }
1340
- this.entity[this.propertyKey] = new Date(this.dateTime);
1341
- if (this.time?.hours != null && this.time?.minutes != null) {
1342
- DateUtilities.asDate(this.entity[this.propertyKey]).setHours(this.time.hours, this.time.minutes, 0, 0);
2001
+ masterToggle() {
2002
+ if (this.isAllSelected()) {
2003
+ this.selection.clear();
1343
2004
  }
1344
2005
  else {
1345
- DateUtilities.asDate(this.entity[this.propertyKey]).setHours(0, 0, 0, 0);
2006
+ this.dataSource.data.forEach(row => this.selection.select(row));
1346
2007
  }
1347
2008
  }
2009
+ /**
2010
+ * Checks if all array-items in the table have been selected.
2011
+ * This is needed to display the "masterToggle"-checkbox correctly.
2012
+ *
2013
+ * @returns Whether or not all array-items in the table have been selected.
2014
+ */
2015
+ isAllSelected() {
2016
+ const numSelected = this.selection.selected.length;
2017
+ const numRows = this.dataSource.data.length;
2018
+ return numSelected === numRows;
2019
+ }
1348
2020
  /**
1349
2021
  * Tries to add an item to the array.
1350
- * Does this either inline if the "createInline"-metadata is set to true
1351
- * or in a separate dialog if it is set to false.
1352
2022
  */
1353
2023
  add() {
1354
- if (this.metadataEntityArray.createInline) {
1355
- this.entityArrayValues.push(cloneDeep(this.arrayItem));
2024
+ if (this.input != null) {
2025
+ if (!this.metadata.allowDuplicates
2026
+ && this.propertyValue?.find(async (v) => await EntityUtilities.isEqual(this.input, v, this.metadata, this.metadata.itemType)) != null) {
2027
+ this.matDialog.open(NgxMatEntityConfirmDialogComponent, {
2028
+ data: this.metadata.duplicatesErrorDialog,
2029
+ autoFocus: false,
2030
+ restoreFocus: false
2031
+ });
2032
+ return;
2033
+ }
2034
+ this.propertyValue?.push(LodashUtilities.cloneDeep(this.input));
2035
+ this.dataSource.data = this.propertyValue ?? [];
2036
+ this.resetInput();
2037
+ this.emitChange();
2038
+ }
2039
+ }
2040
+ /**
2041
+ * Is split up from the add method to override this functionality more easily.
2042
+ */
2043
+ resetInput() {
2044
+ this.input = undefined;
2045
+ }
2046
+ /**
2047
+ * Removes all selected entries from the entity array.
2048
+ */
2049
+ remove() {
2050
+ this.selection.selected.forEach(s => {
2051
+ this.propertyValue?.splice(this.propertyValue.indexOf(s), 1);
2052
+ });
2053
+ this.dataSource.data = this.propertyValue ?? [];
2054
+ this.selection.clear();
2055
+ this.emitChange();
2056
+ }
2057
+ }
2058
+ ArrayTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayTableComponent, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
2059
+ 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 });
2060
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayTableComponent, decorators: [{
2061
+ type: Component,
2062
+ args: [{
2063
+ selector: 'ngx-mat-entity-array-table',
2064
+ template: ''
2065
+ }]
2066
+ }], ctorParameters: function () { return [{ type: i1.MatDialog }]; } });
2067
+
2068
+ /* eslint-disable jsdoc/require-jsdoc */
2069
+ class ArrayDateInputComponent extends ArrayTableComponent {
2070
+ constructor() {
2071
+ super(...arguments);
2072
+ this.DateUtilities = DateUtilities;
2073
+ }
2074
+ }
2075
+ ArrayDateInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2076
+ 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"] }] });
2077
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateInputComponent, decorators: [{
2078
+ type: Component,
2079
+ 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"] }]
2080
+ }] });
2081
+
2082
+ /* eslint-disable jsdoc/require-jsdoc */
2083
+ class ArrayDateTimeInputComponent extends ArrayTableComponent {
2084
+ constructor() {
2085
+ super(...arguments);
2086
+ this.DateUtilities = DateUtilities;
2087
+ }
2088
+ ngOnInit() {
2089
+ super.ngOnInit();
2090
+ this.time = DateUtilities.getTimeFromDate(this.entity[this.key]);
2091
+ this.timeDropdownValues = this.metadata.times;
2092
+ if (this.entity[this.key] != null) {
2093
+ this.dateTime = new Date(this.entity[this.key]);
2094
+ }
2095
+ }
2096
+ resetInput() {
2097
+ this.input = undefined;
2098
+ this.time = undefined;
2099
+ }
2100
+ /**
2101
+ * Adds a date time to the array.
2102
+ */
2103
+ addDateTime() {
2104
+ if (this.input && this.time) {
2105
+ this.input = new Date(this.input);
2106
+ this.input.setHours(this.time.hours, this.time.minutes, 0, 0);
2107
+ this.add();
2108
+ }
2109
+ }
2110
+ }
2111
+ ArrayDateTimeInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateTimeInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2112
+ 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"] }] });
2113
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateTimeInputComponent, decorators: [{
2114
+ type: Component,
2115
+ 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"] }]
2116
+ }] });
2117
+
2118
+ /* eslint-disable jsdoc/require-jsdoc */
2119
+ class ArrayDateRangeInputComponent extends ArrayTableComponent {
2120
+ constructor() {
2121
+ super(...arguments);
2122
+ this.DateUtilities = DateUtilities;
2123
+ }
2124
+ ngOnInit() {
2125
+ super.ngOnInit();
2126
+ this.input = {
2127
+ start: undefined,
2128
+ end: undefined,
2129
+ values: undefined
2130
+ };
2131
+ }
2132
+ /**
2133
+ * Adds a DateRange to the array.
2134
+ */
2135
+ addDateRange() {
2136
+ if (this.input && this.dateRangeStart && this.dateRangeEnd) {
2137
+ this.input.start = new Date(this.dateRangeStart);
2138
+ this.input.end = new Date(this.dateRangeEnd);
2139
+ const values = DateUtilities.getDatesBetween(this.input.start, this.input.end, this.metadata.filter);
2140
+ this.input.values = values.length ? values : undefined;
2141
+ this.add();
2142
+ }
2143
+ }
2144
+ resetInput() {
2145
+ this.input = undefined;
2146
+ this.dateRangeStart = undefined;
2147
+ this.dateRangeEnd = undefined;
2148
+ }
2149
+ }
2150
+ ArrayDateRangeInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateRangeInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2151
+ 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"] }] });
2152
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayDateRangeInputComponent, decorators: [{
2153
+ type: Component,
2154
+ 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"] }]
2155
+ }] });
2156
+
2157
+ /* eslint-disable jsdoc/require-jsdoc */
2158
+ class ArrayStringChipsInputComponent extends NgxMatEntityBaseInputComponent {
2159
+ constructor() {
2160
+ super(...arguments);
2161
+ this.chipsInput = '';
2162
+ }
2163
+ /**
2164
+ * Handles adding strings to the chipsArray.
2165
+ * Checks validation and also creates a new array if it is undefined.
2166
+ * This is needed because two things are validated: The array itself
2167
+ * and the contents of the array. And we need a way to display an
2168
+ * mat-error. As the only validation for the array is whether or not
2169
+ * it contains values, we can set it to undefined when the last element is removed
2170
+ * (removeStringChipArrayValue). That way we can use the "required" validator.
2171
+ *
2172
+ * @param event - The event that fires when a new chip is completed.
2173
+ */
2174
+ addStringChipArrayValue(event) {
2175
+ const value = (event.value || '').trim();
2176
+ if (value) {
2177
+ if (this.metadata.minLength && value.length < this.metadata.minLength) {
2178
+ return;
2179
+ }
2180
+ if (this.metadata.maxLength && value.length > this.metadata.maxLength) {
2181
+ return;
2182
+ }
2183
+ if (this.metadata.regex && !value.match(this.metadata.regex)) {
2184
+ return;
2185
+ }
2186
+ this.propertyValue = this.propertyValue ?? [];
2187
+ this.propertyValue.push(value);
2188
+ }
2189
+ event.chipInput?.clear();
2190
+ }
2191
+ /**
2192
+ * Removes the given value from the array.
2193
+ * Sets the array to undefined if it is now empty.
2194
+ * This is needed because two things are validated: The array itself
2195
+ * and the contents of the array. And we need a way to display an
2196
+ * mat-error. As the only validation for the array is whether or not
2197
+ * it is empty, setting it to undefined here enables us to use the "required" validator.
2198
+ *
2199
+ * @param value - The string to remove from the array.
2200
+ */
2201
+ removeStringChipArrayValue(value) {
2202
+ this.propertyValue?.splice(this.propertyValue.indexOf(value), 1);
2203
+ this.propertyValue = this.propertyValue?.length ? this.propertyValue : undefined;
2204
+ }
2205
+ /**
2206
+ * Handles adding a string to the array when an autocomplete value has been selected.
2207
+ *
2208
+ * @param event - The autocomplete selected event.
2209
+ * @param chipsInput - The element where the user typed the value.
2210
+ */
2211
+ selected(event, chipsInput) {
2212
+ const value = (event.option.viewValue || '').trim();
2213
+ if (this.metadata.minLength && value.length < this.metadata.minLength) {
2214
+ return;
2215
+ }
2216
+ if (this.metadata.maxLength && value.length > this.metadata.maxLength) {
2217
+ return;
2218
+ }
2219
+ if (this.metadata.regex && !value.match(this.metadata.regex)) {
2220
+ return;
2221
+ }
2222
+ this.propertyValue = this.propertyValue ?? [];
2223
+ this.propertyValue.push(value);
2224
+ chipsInput.value = '';
2225
+ }
2226
+ }
2227
+ ArrayStringChipsInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayStringChipsInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2228
+ 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"] }] });
2229
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayStringChipsInputComponent, decorators: [{
2230
+ type: Component,
2231
+ 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"] }]
2232
+ }] });
2233
+
2234
+ /* eslint-disable jsdoc/require-jsdoc */
2235
+ class ArrayStringAutocompleteChipsComponent extends NgxMatEntityBaseInputComponent {
2236
+ constructor() {
2237
+ super(...arguments);
2238
+ this.chipsInput = '';
2239
+ }
2240
+ ngOnInit() {
2241
+ super.ngOnInit();
2242
+ this.filteredAutocompleteStrings = LodashUtilities.cloneDeep(this.metadata.autocompleteValues);
2243
+ }
2244
+ /**
2245
+ * Handles adding strings to the chipsArray.
2246
+ * Checks validation and also creates a new array if it is undefined.
2247
+ * This is needed because two things are validated: The array itself
2248
+ * and the contents of the array. And we need a way to display an
2249
+ * mat-error. As the only validation for the array is whether or not
2250
+ * it contains values, we can set it to undefined when the last element is removed
2251
+ * (removeStringChipArrayValue). That way we can use the "required" validator.
2252
+ *
2253
+ * @param event - The event that fires when a new chip is completed.
2254
+ */
2255
+ addStringChipArrayValue(event) {
2256
+ const value = (event.value || '').trim();
2257
+ if (value) {
2258
+ if (this.metadata.minLength && value.length < this.metadata.minLength) {
2259
+ return;
2260
+ }
2261
+ if (this.metadata.maxLength && value.length > this.metadata.maxLength) {
2262
+ return;
2263
+ }
2264
+ if (this.metadata.regex && !value.match(this.metadata.regex)) {
2265
+ return;
2266
+ }
2267
+ this.propertyValue = this.propertyValue ?? [];
2268
+ this.propertyValue.push(value);
2269
+ }
2270
+ event.chipInput?.clear();
2271
+ }
2272
+ /**
2273
+ * Removes the given value from the array.
2274
+ * Sets the array to undefined if it is now empty.
2275
+ * This is needed because two things are validated: The array itself
2276
+ * and the contents of the array. And we need a way to display an
2277
+ * mat-error. As the only validation for the array is whether or not
2278
+ * it is empty, setting it to undefined here enables us to use the "required" validator.
2279
+ *
2280
+ * @param value - The string to remove from the array.
2281
+ */
2282
+ removeStringChipArrayValue(value) {
2283
+ this.propertyValue?.splice(this.propertyValue.indexOf(value), 1);
2284
+ this.propertyValue = this.propertyValue?.length ? this.propertyValue : undefined;
2285
+ }
2286
+ /**
2287
+ * Handles adding a string to the array when an autocomplete value has been selected.
2288
+ *
2289
+ * @param event - The autocomplete selected event.
2290
+ * @param chipsInput - The element where the user typed the value.
2291
+ */
2292
+ selected(event, chipsInput) {
2293
+ const value = (event.option.viewValue || '').trim();
2294
+ if (this.metadata.minLength && value.length < this.metadata.minLength) {
2295
+ return;
2296
+ }
2297
+ if (this.metadata.maxLength && value.length > this.metadata.maxLength) {
2298
+ return;
2299
+ }
2300
+ if (this.metadata.regex && !value.match(this.metadata.regex)) {
2301
+ return;
2302
+ }
2303
+ this.propertyValue = this.propertyValue ?? [];
2304
+ this.propertyValue.push(value);
2305
+ chipsInput.value = '';
2306
+ }
2307
+ /**
2308
+ * Dynamically filters the Autocomplete options when the user inputs something.
2309
+ *
2310
+ * @param input - The input of the user.
2311
+ */
2312
+ filterAutocompleteStrings(input) {
2313
+ if (input != null) {
2314
+ const filterValue = input.toLowerCase();
2315
+ this.filteredAutocompleteStrings = this.metadata.autocompleteValues.filter(s => s.toLowerCase().includes(filterValue));
2316
+ }
2317
+ }
2318
+ }
2319
+ ArrayStringAutocompleteChipsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayStringAutocompleteChipsComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2320
+ 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"] }] });
2321
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: ArrayStringAutocompleteChipsComponent, decorators: [{
2322
+ type: Component,
2323
+ 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"] }]
2324
+ }] });
2325
+
2326
+ /* eslint-disable jsdoc/require-jsdoc */
2327
+ class DateInputComponent extends NgxMatEntityBaseInputComponent {
2328
+ constructor() {
2329
+ super(...arguments);
2330
+ this.DateUtilities = DateUtilities;
2331
+ }
2332
+ }
2333
+ DateInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2334
+ 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"] }] });
2335
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateInputComponent, decorators: [{
2336
+ type: Component,
2337
+ 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"] }]
2338
+ }] });
2339
+
2340
+ /* eslint-disable jsdoc/require-jsdoc */
2341
+ const EMPTY_DATERANGE = {
2342
+ start: undefined,
2343
+ end: undefined,
2344
+ values: undefined
2345
+ };
2346
+ class DateRangeInputComponent extends NgxMatEntityBaseInputComponent {
2347
+ constructor() {
2348
+ super(...arguments);
2349
+ this.defaultDateFilter = DateUtilities.defaultDateFilter;
2350
+ }
2351
+ ngOnInit() {
2352
+ super.ngOnInit();
2353
+ this.dateRange = LodashUtilities.cloneDeep(this.propertyValue) ?? EMPTY_DATERANGE;
2354
+ this.dateRangeStart = new Date(this.dateRange.start);
2355
+ this.dateRangeEnd = new Date(this.dateRange.end);
2356
+ this.setDateRangeValues();
2357
+ }
2358
+ /**
2359
+ * Updates the date range values based on the start and end date.
2360
+ */
2361
+ setDateRangeValues() {
2362
+ if (this.dateRangeStart && this.dateRangeEnd) {
2363
+ this.dateRange.start = new Date(this.dateRangeStart);
2364
+ this.dateRange.end = new Date(this.dateRangeEnd);
2365
+ const values = DateUtilities.getDatesBetween(new Date(this.dateRange.start), new Date(this.dateRange.end), this.metadata.filter);
2366
+ this.dateRange.values = values.length ? values : undefined;
2367
+ }
2368
+ else {
2369
+ this.dateRange.values = undefined;
2370
+ }
2371
+ this.propertyValue = this.dateRange;
2372
+ this.emitChange();
2373
+ }
2374
+ }
2375
+ DateRangeInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateRangeInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2376
+ 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"] }] });
2377
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateRangeInputComponent, decorators: [{
2378
+ type: Component,
2379
+ 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"] }]
2380
+ }] });
2381
+
2382
+ /* eslint-disable jsdoc/require-jsdoc */
2383
+ class DateTimeInputComponent extends NgxMatEntityBaseInputComponent {
2384
+ constructor() {
2385
+ super(...arguments);
2386
+ this.DateUtilities = DateUtilities;
2387
+ this.defaultDateFilter = () => true;
2388
+ }
2389
+ ngOnInit() {
2390
+ super.ngOnInit();
2391
+ this.time = DateUtilities.getTimeFromDate(this.propertyValue);
2392
+ this.timeDropdownValues = this.metadata.times;
2393
+ if (this.propertyValue) {
2394
+ this.propertyValue = new Date(this.propertyValue);
2395
+ }
2396
+ }
2397
+ /**
2398
+ * Checks if two times are equal. Is needed for the dropdown.
2399
+ *
2400
+ * @param time1 - The first time to compare.
2401
+ * @param time2 - The second time to compare.
2402
+ * @returns Whether or not the time objects are the same.
2403
+ */
2404
+ compareTimes(time1, time2) {
2405
+ if (time1 && time2 && time1.hours === time2.hours && time1.minutes === time2.minutes) {
2406
+ return true;
2407
+ }
2408
+ return false;
2409
+ }
2410
+ /**
2411
+ * Sets the time on a datetime property.
2412
+ */
2413
+ setTime() {
2414
+ if (!this.propertyValue) {
2415
+ this.emitChange();
2416
+ return;
2417
+ }
2418
+ if (this.time?.hours != null && this.time?.minutes != null) {
2419
+ this.propertyValue.setHours(this.time.hours, this.time.minutes, 0, 0);
2420
+ }
2421
+ else {
2422
+ this.propertyValue.setHours(0, 0, 0, 0);
2423
+ }
2424
+ this.emitChange();
2425
+ }
2426
+ }
2427
+ DateTimeInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateTimeInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2428
+ 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"] }] });
2429
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DateTimeInputComponent, decorators: [{
2430
+ type: Component,
2431
+ 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"] }]
2432
+ }] });
2433
+
2434
+ /**
2435
+ * Adds drag and drop functionality to an element.
2436
+ */
2437
+ class DragDropDirective {
2438
+ constructor() {
2439
+ /**
2440
+ * Emits the dropped files to the parent.
2441
+ */
2442
+ this.files = new EventEmitter();
2443
+ }
2444
+ /**
2445
+ * Prevents the event default.
2446
+ *
2447
+ * @param evt - The Event when dragged files hover over the parent.
2448
+ */
2449
+ onDragOver(evt) {
2450
+ evt.preventDefault();
2451
+ evt.stopPropagation();
2452
+ }
2453
+ /**
2454
+ * Prevents the event default.
2455
+ *
2456
+ * @param evt - The Event when dragged files leave the parent.
2457
+ */
2458
+ onDragLeave(evt) {
2459
+ evt.preventDefault();
2460
+ evt.stopPropagation();
2461
+ }
2462
+ /**
2463
+ * Prevents the event default and emits the dropped files with the output.
2464
+ *
2465
+ * @param evt - The Event when files are dropped.
2466
+ */
2467
+ onDrop(evt) {
2468
+ evt.preventDefault();
2469
+ evt.stopPropagation();
2470
+ if (evt.dataTransfer && evt.dataTransfer.files.length > 0) {
2471
+ this.files.emit(Array.from(evt.dataTransfer.files));
2472
+ }
2473
+ }
2474
+ }
2475
+ DragDropDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DragDropDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2476
+ 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 });
2477
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: DragDropDirective, decorators: [{
2478
+ type: Directive,
2479
+ args: [{
2480
+ // eslint-disable-next-line @angular-eslint/directive-selector
2481
+ selector: '[dragDrop]'
2482
+ }]
2483
+ }], ctorParameters: function () { return []; }, propDecorators: { files: [{
2484
+ type: Output
2485
+ }], onDragOver: [{
2486
+ type: HostListener,
2487
+ args: ['dragover', ['$event']]
2488
+ }], onDragLeave: [{
2489
+ type: HostListener,
2490
+ args: ['dragleave', ['$event']]
2491
+ }], onDrop: [{
2492
+ type: HostListener,
2493
+ args: ['drop', ['$event']]
2494
+ }] } });
2495
+
2496
+ /* eslint-disable jsdoc/require-jsdoc */
2497
+ class FileInputComponent {
2498
+ constructor(dialog) {
2499
+ this.dialog = dialog;
2500
+ this.FileUtilities = FileUtilities;
2501
+ this.fileDataChangeEvent = new EventEmitter();
2502
+ }
2503
+ async ngOnInit() {
2504
+ this.metadata = EntityUtilities.getPropertyMetadata(this.entity, this.key, DecoratorTypes.FILE_DEFAULT);
2505
+ if (this.metadata.multiple) {
2506
+ this.initMultiFile();
2507
+ }
2508
+ else {
2509
+ this.initSingleFile();
2510
+ }
2511
+ this.fileDataChangeEvent.emit(this.singleFileData ?? this.multiFileData);
2512
+ }
2513
+ initMultiFile() {
2514
+ this.multiFileData = this.entity[this.key];
2515
+ if (this.multiFileData) {
2516
+ this.filenames = this.multiFileData.map(f => f.name);
2517
+ }
2518
+ }
2519
+ initSingleFile() {
2520
+ this.singleFileData = this.entity[this.key];
2521
+ if (this.singleFileData) {
2522
+ this.filenames = LodashUtilities.cloneDeep([this.singleFileData.name]);
2523
+ }
2524
+ }
2525
+ async setFileFromInput(event) {
2526
+ const files = event.target.files ?? [];
2527
+ await this.setFile(Array.from(files));
2528
+ }
2529
+ async setFile(files) {
2530
+ // validation done inline
2531
+ if (files.find(f => !FileUtilities.isMimeTypeValid(f.type, this.metadata.allowedMimeTypes))) {
2532
+ this.dialog.open(NgxMatEntityConfirmDialogComponent, {
2533
+ data: this.metadata.mimeTypeErrorDialog,
2534
+ autoFocus: false,
2535
+ restoreFocus: false
2536
+ });
2537
+ this.resetFileInputs();
2538
+ return;
2539
+ }
2540
+ if (files.find(f => FileUtilities.transformToMegaBytes(f.size, 'B') > this.metadata.maxSize)) {
2541
+ this.dialog.open(NgxMatEntityConfirmDialogComponent, {
2542
+ data: this.metadata.maxSizeErrorDialog,
2543
+ autoFocus: false,
2544
+ restoreFocus: false
2545
+ });
2546
+ this.resetFileInputs();
2547
+ return;
2548
+ }
2549
+ let fileSizeTotal = 0;
2550
+ for (const file of files) {
2551
+ fileSizeTotal += file.size;
2552
+ }
2553
+ if (FileUtilities.transformToMegaBytes(fileSizeTotal, 'B') > this.metadata.maxSizeTotal) {
2554
+ this.dialog.open(NgxMatEntityConfirmDialogComponent, {
2555
+ data: this.metadata.maxSizeTotalErrorDialog,
2556
+ autoFocus: false,
2557
+ restoreFocus: false
2558
+ });
2559
+ this.resetFileInputs();
2560
+ return;
2561
+ }
2562
+ if (this.metadata.multiple) {
2563
+ await this.setMultiFile(Array.from(files));
2564
+ }
2565
+ else {
2566
+ await this.setSingleFile(files[0]);
2567
+ }
2568
+ this.fileDataChangeEvent.emit(this.singleFileData ?? this.multiFileData);
2569
+ }
2570
+ resetFileInputs() {
2571
+ this.filenames = undefined;
2572
+ this.singleFileData = undefined;
2573
+ this.multiFileData = undefined;
2574
+ this.fileDataChangeEvent.emit();
2575
+ }
2576
+ async setMultiFile(files) {
2577
+ const data = [];
2578
+ for (const file of files) {
2579
+ const fileData = {
2580
+ file: file,
2581
+ name: file.name,
2582
+ type: file.type,
2583
+ size: file.size
2584
+ };
2585
+ data.push(fileData);
2586
+ }
2587
+ this.multiFileData = LodashUtilities.cloneDeep(data);
2588
+ this.filenames = this.multiFileData.map(f => f.name);
2589
+ }
2590
+ async setSingleFile(file) {
2591
+ this.singleFileData = {
2592
+ file: file,
2593
+ name: file.name,
2594
+ type: file.type,
2595
+ size: file.size
2596
+ };
2597
+ this.filenames = LodashUtilities.cloneDeep([this.singleFileData.name]);
2598
+ }
2599
+ removeFile(name) {
2600
+ if (this.metadata.multiple) {
2601
+ this.filenames?.splice(this.filenames.indexOf(name), 1);
2602
+ if (!this.filenames?.length) {
2603
+ this.filenames = undefined;
2604
+ }
2605
+ const fileDataToRemove = this.multiFileData?.find(f => f.name === name);
2606
+ this.multiFileData?.splice(this.multiFileData.indexOf(fileDataToRemove), 1);
2607
+ if (!this.multiFileData?.length) {
2608
+ this.multiFileData = undefined;
2609
+ }
2610
+ }
2611
+ else {
2612
+ this.filenames = undefined;
2613
+ this.singleFileData = undefined;
2614
+ }
2615
+ this.fileDataChangeEvent.emit(this.singleFileData ?? this.multiFileData);
2616
+ }
2617
+ }
2618
+ FileInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileInputComponent, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
2619
+ 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"] }] });
2620
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileInputComponent, decorators: [{
2621
+ type: Component,
2622
+ 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"] }]
2623
+ }], ctorParameters: function () { return [{ type: i1.MatDialog }]; }, propDecorators: { entity: [{
2624
+ type: Input
2625
+ }], key: [{
2626
+ type: Input
2627
+ }], getValidationErrorMessage: [{
2628
+ type: Input
2629
+ }], isReadOnly: [{
2630
+ type: Input
2631
+ }], fileDataChangeEvent: [{
2632
+ type: Output
2633
+ }] } });
2634
+
2635
+ /* eslint-disable jsdoc/require-jsdoc */
2636
+ class FileDefaultInputComponent extends NgxMatEntityBaseInputComponent {
2637
+ constructor() {
2638
+ super(...arguments);
2639
+ this.FileUtilities = FileUtilities;
2640
+ }
2641
+ async refreshFileData(fileData) {
2642
+ this.propertyValue = fileData;
2643
+ this.emitChange();
2644
+ }
2645
+ }
2646
+ FileDefaultInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileDefaultInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2647
+ 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"] }] });
2648
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileDefaultInputComponent, decorators: [{
2649
+ type: Component,
2650
+ 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"] }]
2651
+ }] });
2652
+
2653
+ // eslint-disable-next-line max-len
2654
+ 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=';
2655
+
2656
+ /* eslint-disable jsdoc/require-jsdoc */
2657
+ class FileImageInputComponent extends NgxMatEntityBaseInputComponent {
2658
+ constructor() {
2659
+ super(...arguments);
2660
+ this.FileUtilities = FileUtilities;
2661
+ this.imageIndex = 0;
2662
+ this.placeHolder = placeholder;
2663
+ }
2664
+ async setSinglePreviewImage() {
2665
+ if (this.propertyValue) {
2666
+ this.propertyValue = await FileUtilities.getFileData(this.propertyValue);
2667
+ this.singlePreviewImage = await FileUtilities.getDataURLFromFile(this.propertyValue.file);
2668
+ }
2669
+ else {
2670
+ this.singlePreviewImage = undefined;
2671
+ }
2672
+ }
2673
+ async setMultiPreviewImages(index) {
2674
+ const multiFileData = this.propertyValue;
2675
+ const previewImages = [];
2676
+ if (multiFileData?.length) {
2677
+ for (let i = 0; i < multiFileData.length; i++) {
2678
+ if (i === index) {
2679
+ multiFileData[index] = await FileUtilities.getFileData(multiFileData[index]);
2680
+ previewImages.push(await FileUtilities.getDataURLFromFile(multiFileData[index].file));
2681
+ }
2682
+ else {
2683
+ previewImages.push('empty');
2684
+ }
2685
+ }
2686
+ }
2687
+ this.multiPreviewImages = previewImages;
2688
+ }
2689
+ async refreshFileData(fileData) {
2690
+ this.propertyValue = fileData;
2691
+ this.emitChange();
2692
+ if (this.metadata.multiple) {
2693
+ fileData = fileData;
2694
+ if (!fileData?.[this.imageIndex]) {
2695
+ this.imageIndex = 0;
2696
+ }
2697
+ await this.setMultiPreviewImages(this.imageIndex);
2698
+ }
2699
+ else {
2700
+ await this.setSinglePreviewImage();
2701
+ }
2702
+ }
2703
+ async prev() {
2704
+ if (this.imageIndex <= 0) {
2705
+ return;
2706
+ }
2707
+ await this.setMultiPreviewImages(this.imageIndex - 1);
2708
+ this.imageIndex--;
2709
+ }
2710
+ async next() {
2711
+ if (!this.multiPreviewImages?.length) {
2712
+ return;
2713
+ }
2714
+ if (this.imageIndex === (this.multiPreviewImages.length - 1)) {
2715
+ return;
2716
+ }
2717
+ await this.setMultiPreviewImages(this.imageIndex + 1);
2718
+ this.imageIndex++;
2719
+ }
2720
+ async setIndex(index) {
2721
+ await this.setMultiPreviewImages(index);
2722
+ this.imageIndex = index;
2723
+ }
2724
+ }
2725
+ FileImageInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileImageInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2726
+ 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"] }] });
2727
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: FileImageInputComponent, decorators: [{
2728
+ type: Component,
2729
+ 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"] }]
2730
+ }] });
2731
+
2732
+ /* eslint-disable jsdoc/require-jsdoc */
2733
+ class CustomInputComponent extends NgxMatEntityBaseInputComponent {
2734
+ constructor(viewContainerRef) {
2735
+ super();
2736
+ this.viewContainerRef = viewContainerRef;
2737
+ }
2738
+ ngOnInit() {
2739
+ super.ngOnInit();
2740
+ this.component = this.viewContainerRef.createComponent(this.metadata.component);
2741
+ this.component.instance.entity = this.entity;
2742
+ this.component.instance.key = this.key;
2743
+ this.component.instance.getValidationErrorMessage = this.getValidationErrorMessage;
2744
+ this.component.instance.inputChangeEvent.subscribe(this.inputChangeEvent);
2745
+ this.component.instance.isReadOnly = this.isReadOnly;
2746
+ }
2747
+ }
2748
+ CustomInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: CustomInputComponent, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component });
2749
+ CustomInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: CustomInputComponent, selector: "custom-input", usesInheritance: true, ngImport: i0, template: "", styles: [""] });
2750
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: CustomInputComponent, decorators: [{
2751
+ type: Component,
2752
+ args: [{ selector: 'custom-input', template: "", styles: [""] }]
2753
+ }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }]; } });
2754
+
2755
+ /**
2756
+ * The default input component. It gets the metadata of the property from the given @Input "entity" and @Input "propertyKey"
2757
+ * and displays the input field accordingly.
2758
+ *
2759
+ * You can also define a method that generates error-messages and if the input should be hidden when its metadata says
2760
+ * that it should be omitted for creating or updating.
2761
+ * The last part being mostly relevant if you want to use this component inside an ngFor.
2762
+ */
2763
+ class NgxMatEntityInputComponent {
2764
+ constructor(dialog) {
2765
+ this.dialog = dialog;
2766
+ this.inputChangeEvent = new EventEmitter();
2767
+ this.selection = new SelectionModel(true, []);
2768
+ this.isArrayItemValid = false;
2769
+ this.isDialogArrayItemValid = false;
2770
+ this.DecoratorTypes = DecoratorTypes;
2771
+ this.EntityUtilities = EntityUtilities;
2772
+ this.DateUtilities = DateUtilities;
2773
+ }
2774
+ /**
2775
+ * This is needed for the inputs to work inside an ngFor.
2776
+ *
2777
+ * @param index - The index of the element in the ngFor.
2778
+ * @returns The index.
2779
+ */
2780
+ trackByFn(index) {
2781
+ return index;
2782
+ }
2783
+ ngOnInit() {
2784
+ if (!this.entity) {
2785
+ throw new Error('Missing required Input data "entity"');
2786
+ }
2787
+ this.internalEntity = this.entity;
2788
+ if (this.propertyKey == null) {
2789
+ throw new Error('Missing required Input data "propertyKey"');
2790
+ }
2791
+ this.internalPropertyKey = this.propertyKey;
2792
+ this.internalGetValidationErrorMessage = this.getValidationErrorMessage ?? getValidationErrorMessage;
2793
+ this.internalIsReadOnly = this.isReadOnly ?? false;
2794
+ this.type = EntityUtilities.getPropertyType(this.internalEntity, this.internalPropertyKey);
2795
+ this.metadata = EntityUtilities.getPropertyMetadata(this.internalEntity, this.internalPropertyKey, this.type);
2796
+ if (this.type === DecoratorTypes.OBJECT) {
2797
+ this.initObjectInput();
2798
+ }
2799
+ if (this.type === DecoratorTypes.ARRAY) {
2800
+ this.initEntityArray();
2801
+ }
2802
+ }
2803
+ initEntityArray() {
2804
+ this.metadataEntityArray = this.metadata;
2805
+ if (this.internalEntity[this.internalPropertyKey] == null) {
2806
+ this.internalEntity[this.internalPropertyKey] = [];
2807
+ }
2808
+ this.entityArrayValues = this.internalEntity[this.internalPropertyKey];
2809
+ if (!this.metadataEntityArray.createInline && !this.metadataEntityArray.createDialogData) {
2810
+ this.metadataEntityArray.createDialogData = {
2811
+ title: 'Add'
2812
+ };
2813
+ }
2814
+ const givenDisplayColumns = this.metadataEntityArray.displayColumns.map((v) => v.displayName);
2815
+ if (givenDisplayColumns.find(s => s === 'select')) {
2816
+ throw new Error(`The name "select" for a display column is reserved.
2817
+ Please choose a different name.`);
2818
+ }
2819
+ this.displayedColumns = this.internalIsReadOnly ? givenDisplayColumns : ['select'].concat(givenDisplayColumns);
2820
+ this.dataSource = new MatTableDataSource();
2821
+ this.dataSource.data = this.entityArrayValues;
2822
+ this.arrayItem = new this.metadataEntityArray.EntityClass();
2823
+ this.arrayItemInlineRows = EntityUtilities.getEntityRows(this.arrayItem, this.hideOmitForCreate ?? true, this.hideOmitForEdit);
2824
+ this.arrayItemPriorChanges = LodashUtilities.cloneDeep(this.arrayItem);
2825
+ this.dialogInputData = {
2826
+ entity: this.arrayItem,
2827
+ createDialogData: this.metadataEntityArray.createDialogData,
2828
+ getValidationErrorMessage: this.getValidationErrorMessage
2829
+ };
2830
+ this.dialogData = new AddArrayItemDialogDataBuilder(this.dialogInputData).getResult();
2831
+ this.arrayItemDialogRows = EntityUtilities.getEntityRows(this.dialogData.entity, true);
2832
+ }
2833
+ initObjectInput() {
2834
+ this.metadataDefaultObject = this.metadata;
2835
+ this.objectProperty = this.internalEntity[this.internalPropertyKey];
2836
+ this.objectPropertyRows = EntityUtilities.getEntityRows(this.objectProperty, this.hideOmitForCreate, this.hideOmitForEdit);
2837
+ }
2838
+ /**
2839
+ * Checks if the arrayItem is valid.
2840
+ */
2841
+ checkIsArrayItemValid() {
2842
+ this.isArrayItemValid = EntityUtilities.isEntityValid(this.arrayItem, 'create');
2843
+ }
2844
+ /**
2845
+ * Checks if the arrayItem inside the dialog is valid.
2846
+ */
2847
+ checkIsDialogArrayItemValid() {
2848
+ this.isDialogArrayItemValid = EntityUtilities.isEntityValid(this.dialogData.entity, 'create');
2849
+ }
2850
+ /**
2851
+ * Emits that a the value has been changed.
2852
+ */
2853
+ emitChange() {
2854
+ this.inputChangeEvent.emit();
2855
+ }
2856
+ /**
2857
+ * Tries to add an item to the entity array.
2858
+ * Does this either inline if the "createInline"-metadata is set to true
2859
+ * or in a separate dialog if it is set to false.
2860
+ */
2861
+ async addEntity() {
2862
+ if (this.metadataEntityArray.createInline) {
2863
+ if (!this.metadataEntityArray.allowDuplicates) {
2864
+ for (const v of this.entityArrayValues) {
2865
+ if ((await EntityUtilities.isEqual(this.arrayItem, v, this.metadata, this.metadataEntityArray.itemType))) {
2866
+ this.dialog.open(NgxMatEntityConfirmDialogComponent, {
2867
+ data: this.metadataEntityArray.duplicatesErrorDialog,
2868
+ autoFocus: false,
2869
+ restoreFocus: false
2870
+ });
2871
+ return;
2872
+ }
2873
+ }
2874
+ }
2875
+ this.entityArrayValues.push(LodashUtilities.cloneDeep(this.arrayItem));
1356
2876
  this.dataSource.data = this.entityArrayValues;
1357
2877
  EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
2878
+ this.checkIsArrayItemValid();
2879
+ this.emitChange();
1358
2880
  }
1359
2881
  else {
1360
2882
  this.addArrayItemDialogRef = this.dialog.open(this.addArrayItemDialog, {
@@ -1369,9 +2891,11 @@ class NgxMatEntityInputComponent {
1369
2891
  */
1370
2892
  addArrayItem() {
1371
2893
  this.addArrayItemDialogRef.close();
1372
- this.entityArrayValues.push(cloneDeep(this.arrayItem));
2894
+ this.entityArrayValues.push(LodashUtilities.cloneDeep(this.arrayItem));
1373
2895
  this.dataSource.data = this.entityArrayValues;
1374
2896
  EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
2897
+ this.checkIsArrayItemValid();
2898
+ this.emitChange();
1375
2899
  }
1376
2900
  /**
1377
2901
  * Cancels adding the array item defined in the dialog.
@@ -1379,132 +2903,59 @@ class NgxMatEntityInputComponent {
1379
2903
  cancelAddArrayItem() {
1380
2904
  this.addArrayItemDialogRef.close();
1381
2905
  EntityUtilities.resetChangesOnEntity(this.arrayItem, this.arrayItemPriorChanges);
2906
+ this.emitChange();
1382
2907
  }
1383
2908
  /**
1384
- * Removes all selected entries from the array.
2909
+ * Removes all selected entries from the entity array.
2910
+ *
2911
+ * @param selection - The selection containing the items to remove.
2912
+ * @param values - The values of the dataSource.
2913
+ * @param dataSource - The dataSource.
1385
2914
  */
1386
- remove() {
1387
- this.selection.selected.forEach(s => {
1388
- this.entityArrayValues.splice(this.entityArrayValues.indexOf(s), 1);
2915
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2916
+ remove(selection, values, dataSource) {
2917
+ selection.selected.forEach(s => {
2918
+ values.splice(values.indexOf(s), 1);
1389
2919
  });
1390
- this.dataSource.data = this.entityArrayValues;
1391
- this.selection.clear();
2920
+ dataSource.data = values;
2921
+ selection.clear();
2922
+ this.emitChange();
1392
2923
  }
1393
2924
  /**
1394
2925
  * Toggles all array-items in the table.
2926
+ *
2927
+ * @param selection - The selection to toggle.
2928
+ * @param dataSource - The dataSource of the selection.
1395
2929
  */
1396
- masterToggle() {
1397
- if (this.isAllSelected()) {
1398
- this.selection.clear();
2930
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2931
+ masterToggle(selection, dataSource) {
2932
+ if (this.isAllSelected(selection, dataSource)) {
2933
+ selection.clear();
1399
2934
  }
1400
2935
  else {
1401
- this.dataSource.data.forEach(row => this.selection.select(row));
2936
+ dataSource.data.forEach(row => selection.select(row));
1402
2937
  }
1403
2938
  }
1404
2939
  /**
1405
2940
  * Checks if all array-items in the table have been selected.
1406
2941
  * This is needed to display the "masterToggle"-checkbox correctly.
1407
2942
  *
2943
+ * @param selection - The selection to check.
2944
+ * @param dataSource - The dataSource of the selection.
1408
2945
  * @returns Whether or not all array-items in the table have been selected.
1409
2946
  */
1410
- isAllSelected() {
1411
- const numSelected = this.selection.selected.length;
1412
- const numRows = this.dataSource.data.length;
2947
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2948
+ isAllSelected(selection, dataSource) {
2949
+ const numSelected = selection.selected.length;
2950
+ const numRows = dataSource.data.length;
1413
2951
  return numSelected === numRows;
1414
2952
  }
1415
- /**
1416
- * Handles adding strings to the chipsArray.
1417
- * Checks validation and also creates a new array if it is undefined.
1418
- * This is needed because two things are validated: The array itself
1419
- * and the contents of the array. And we need a way to display an
1420
- * mat-error. As the only validation for the array is whether or not
1421
- * it contains values, we can set it to undefined when the last element is removed
1422
- * (removeStringChipArrayValue). That way we can use the "required" validator.
1423
- *
1424
- * @param event - The event that fires when a new chip is completed.
1425
- */
1426
- addStringChipArrayValue(event) {
1427
- const value = (event.value || '').trim();
1428
- if (value) {
1429
- if (this.metadataStringChipsArray.minLength && value.length < this.metadataStringChipsArray.minLength) {
1430
- return;
1431
- }
1432
- if (this.metadataStringChipsArray.maxLength && value.length > this.metadataStringChipsArray.maxLength) {
1433
- return;
1434
- }
1435
- if (this.metadataStringChipsArray.regex && !value.match(this.metadataStringChipsArray.regex)) {
1436
- return;
1437
- }
1438
- if (!this.stringChipsArrayValues) {
1439
- if (!this.entity[this.propertyKey]) {
1440
- this.entity[this.propertyKey] = [];
1441
- }
1442
- this.stringChipsArrayValues = this.entity[this.propertyKey];
1443
- }
1444
- this.stringChipsArrayValues.push(value);
1445
- }
1446
- event.chipInput.clear();
1447
- }
1448
- /**
1449
- * Removes the given value from the array.
1450
- * Sets the array to undefined if it is now empty.
1451
- * This is needed because two things are validated: The array itself
1452
- * and the contents of the array. And we need a way to display an
1453
- * mat-error. As the only validation for the array is whether or not
1454
- * it is empty, setting it to undefined here enables us to use the "required" validator.
1455
- *
1456
- * @param value - The string to remove from the array.
1457
- */
1458
- removeStringChipArrayValue(value) {
1459
- this.stringChipsArrayValues.splice(this.stringChipsArrayValues.indexOf(value), 1);
1460
- if (!this.stringChipsArrayValues.length) {
1461
- this.entity[this.propertyKey] = undefined;
1462
- this.stringChipsArrayValues = this.entity[this.propertyKey];
1463
- }
1464
- }
1465
- /**
1466
- * Handles adding a string to the array when an autocomplete value has been selected.
1467
- *
1468
- * @param event - The autocomplete selected event.
1469
- * @param chipsInput - The element where the user typed the value.
1470
- */
1471
- selected(event, chipsInput) {
1472
- const value = (event.option.viewValue || '').trim();
1473
- if (this.metadataStringChipsArray.minLength && value.length < this.metadataStringChipsArray.minLength) {
1474
- return;
1475
- }
1476
- if (this.metadataStringChipsArray.maxLength && value.length > this.metadataStringChipsArray.maxLength) {
1477
- return;
1478
- }
1479
- if (this.metadataStringChipsArray.regex && !value.match(this.metadataStringChipsArray.regex)) {
1480
- return;
1481
- }
1482
- if (!this.stringChipsArrayValues) {
1483
- if (!this.entity[this.propertyKey]) {
1484
- this.entity[this.propertyKey] = [];
1485
- }
1486
- this.stringChipsArrayValues = this.entity[this.propertyKey];
1487
- }
1488
- this.stringChipsArrayValues.push(value);
1489
- chipsInput.value = '';
1490
- }
1491
- /**
1492
- * Dynamically filters the Autocomplete options when the user inputs something.
1493
- *
1494
- * @param input - The input of the user.
1495
- */
1496
- filterAutocompleteStrings(input) {
1497
- if (input) {
1498
- const filterValue = input.toLowerCase();
1499
- this.filteredAutocompleteStrings = this.autocompleteStrings.filter(s => s.toLowerCase().includes(filterValue));
1500
- }
1501
- }
1502
2953
  }
1503
2954
  NgxMatEntityInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputComponent, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
1504
- NgxMatEntityInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: { entity: "entity", propertyKey: "propertyKey", getValidationErrorMessage: "getValidationErrorMessage", hideOmitForCreate: "hideOmitForCreate", hideOmitForEdit: "hideOmitForEdit" }, viewQueries: [{ propertyName: "addArrayItemDialog", first: true, predicate: ["addArrayItemDialog"], descendants: true }], ngImport: i0, template: "<div [ngSwitch]=\"type\" *ngIf=\"!(hideOmitForCreate && metadata.omitForCreate) && !(hideOmitForEdit && metadata.omitForUpdate)\">\n <!-------------------------------------------->\n <!-----------------Strings-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.STRING\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [pattern]=\"metadataDefaultString.regex ? metadataDefaultString.regex : '[\\\\s\\\\S]*'\"\n [minlength]=\"metadataDefaultString.minLength ? metadataDefaultString.minLength : null\"\n [maxlength]=\"metadataDefaultString.maxLength ? metadataDefaultString.maxLength : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_TEXTBOX\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <textarea\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"10\"\n [required]=\"metadata.required\"\n [minlength]=\"metadataTextboxString.minLength ? metadataTextboxString.minLength : null\"\n [maxlength]=\"metadataTextboxString.maxLength ? metadataTextboxString.maxLength : null\"\n >\n </textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_AUTOCOMPLETE\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matAutocomplete]=\"auto\"\n (keyup)=\"filterAutocompleteStrings(entity[propertyKey])\"\n [required]=\"metadata.required\"\n [minlength]=\"metadataAutocompleteString.minLength ? metadataAutocompleteString.minLength : null\"\n [maxlength]=\"metadataAutocompleteString.maxLength ? metadataAutocompleteString.maxLength : null\"\n [pattern]=\"metadataAutocompleteString.regex ? metadataAutocompleteString.regex : '[\\\\s\\\\S]*'\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadataDropdownString.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-----------------Booleans------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_CHECKBOX\">\n <mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-checkbox (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\"></mat-checkbox>\n <!-- hidden input is needed so that the checkbox can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\">\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_TOGGLE\">\n <mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-slide-toggle (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\"></mat-slide-toggle>\n <!-- hidden input is needed so that the toggle can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\">\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option [value]=\"undefined\">-</mat-option>\n <mat-option [value]=\"true\">{{metadataDropdownBoolean.dropdownTrue}}</mat-option>\n <mat-option [value]=\"false\">{{metadataDropdownBoolean.dropdownFalse}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!------------------Numbers------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n type=\"number\"\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDefaultNumber.min ? metadataDefaultNumber.min : null\"\n [max]=\"metadataDefaultNumber.max ? metadataDefaultNumber.max : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadataDropdownNumber.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Object------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.OBJECT\">\n <b>{{metadataDefaultObject.displayName}}</b>\n <!-- iterates over the object properties -->\n\n <div class=\"row\" *ngFor=\"let row of objectPropertyRows\">\n <!--\n displays another ngx-material-entity with the:\n object as the entity,\n the current key in the loop received by the keyvalue direction as the propertyKey\n and the getValidationErrorMessage of the current component\n -->\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"objectProperty\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n class=\"col-lg-{{EntityUtilities.getWidth(objectProperty, key, 'lg')}} col-md-{{EntityUtilities.getWidth(objectProperty, key, 'md')}} col-sm-{{EntityUtilities.getWidth(objectProperty, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Array-------------------->\n <!-------------------------------------------->\n <div class=\"entityArray\" *ngSwitchCase=\"DecoratorTypes.ARRAY\">\n <div class=\"mat-elevation-z8\" style=\"border-radius: 5px;padding: 15px;margin-bottom: 15px;margin-top: 15px;\">\n\n <div style=\"padding-bottom: 10px\">\n <b>{{metadataEntityArray.displayName}}</b>\n </div>\n <div *ngIf=\"metadataEntityArray.createInline\">\n <div class=\"row\" *ngFor=\"let row of arrayItemInlineRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(arrayItem, key, 'lg')}} col-md-{{EntityUtilities.getWidth(arrayItem, key, 'md')}} col-sm-{{EntityUtilities.getWidth(arrayItem, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n \n <div class=\"buttons\">\n <button mat-raised-button\n [disabled]=\"metadataEntityArray.createInline && !EntityUtilities.isEntityValid(arrayItem, 'create')\"\n (click)=\"add()\">\n {{metadataEntityArray.addButtonLabel}}\n </button>\n <button mat-raised-button\n [disabled]=\"!selection.selected.length\"\n (click)=\"remove()\">\n {{metadataEntityArray.removeButtonLabel}}\n </button>\n </div>\n \n <mat-table [dataSource]=\"dataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"></mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\" class=\"module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"></mat-checkbox>\n </mat-cell>\n </ng-container>\n \n <ng-container *ngFor=\"let dCol of metadataEntityArray.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n \n <div class=\"array-error\" *ngIf=\"metadataEntityArray.required && !dataSource.data.length\">\n {{metadataEntityArray.missingErrorMessage}}\n </div>\n </div>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadataStringChipsArray.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadataStringChipsArray.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matAutocomplete]=\"auto\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n (keyup)=\"filterAutocompleteStrings(chipsInput)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n #chipsElement\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event, chipsElement)\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Dates-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.DATE\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadataDefaultDate.min ? metadataDefaultDate.min(DateUtilities.asDate(entity[propertyKey])) : undefined\"\n [max]=\"metadataDefaultDate.max ? metadataDefaultDate.max(DateUtilities.asDate(entity[propertyKey])) : undefined\"\n [matDatepickerFilter]=\"metadataDefaultDate.filter ? metadataDefaultDate.filter : defaultDateFilter\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.DATE_RANGE\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n \n <mat-date-range-input [rangePicker]=\"picker\" [required]=\"metadata.required\" [dateFilter]=\"metadataDateRangeDate.filter ? metadataDateRangeDate.filter : defaultDateFilter\">\n <input matStartDate\n [(ngModel)]=\"dateRangeStart\"\n [name]=\"propertyKey.toString() + 'start'\"\n #startModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateRangeDate.minStart ? metadataDateRangeDate.minStart(dateRange.start) : undefined\"\n [max]=\"metadataDateRangeDate.maxStart ? metadataDateRangeDate.maxStart(dateRange.start) : undefined\"\n [placeholder]=\"metadataDateRangeDate.placeholderStart ? metadataDateRangeDate.placeholderStart : 'Start'\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n <input matEndDate\n [(ngModel)]=\"dateRangeEnd\"\n [name]=\"propertyKey.toString() + 'end'\"\n #endModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateRangeDate.minEnd ? metadataDateRangeDate.minEnd(dateRange.end) : undefined\"\n [max]=\"metadataDateRangeDate.maxEnd ? metadataDateRangeDate.maxEnd(dateRange.end) : undefined\"\n [placeholder]=\"metadataDateRangeDate.placeholderEnd ? metadataDateRangeDate.placeholderEnd : 'End'\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n </mat-date-range-input>\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-date-range-picker #picker></mat-date-range-picker>\n\n <mat-error *ngIf=\"startModel.errors\">{{getValidationErrorMessage(startModel)}}</mat-error>\n <mat-error *ngIf=\"!startModel.errors && endModel.errors\">{{getValidationErrorMessage(endModel)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.DATE_TIME\" class=\"date-time\">\n <mat-form-field appearance=\"standard\" class=\"datepicker\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"dateTime\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateTimeDate.minDate ? metadataDateTimeDate.minDate(dateTime) : undefined\"\n [max]=\"metadataDateTimeDate.maxDate ? metadataDateTimeDate.maxDate(dateTime) : undefined\"\n [matDatepickerFilter]=\"metadataDateTimeDate.filterDate ? metadataDateTimeDate.filterDate : defaultDateFilter\"\n (dateInput)=\"setTime()\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n <mat-form-field class=\"timepicker\">\n <mat-label>{{metadataDateTimeDate.timeDisplayName}}</mat-label>\n <mat-select\n [(ngModel)]=\"time\"\n [name]=\"propertyKey.toString() + 'time'\"\n #timeModel=\"ngModel\"\n [required]=\"metadata.required\"\n [compareWith]=\"compareTimes\"\n (ngModelChange)=\"setTime()\"\n >\n <mat-option *ngFor=\"let validTime of DateUtilities.getValidTimesForDropdown(\n DateUtilities.asDate(entity[propertyKey]),\n metadataDateTimeDate.times,\n metadataDateTimeDate.minTime,\n metadataDateTimeDate.maxTime,\n metadataDateTimeDate.filterTime\n )\"\n [value]=\"validTime.value\"\n >\n {{validTime.displayName}}\n </mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(timeModel)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchDefault>ERROR: The type {{type}} is not known.</div>\n</div>\n\n<!--------------------------------------------------------->\n<!--------------------Add Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #addArrayItemDialog>\n <h2 mat-dialog-title>{{dialogData.createDialogData.title}}</h2>\n\n <mat-dialog-content>\n <form #form=\"ngForm\" class=\"row\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"dialogData.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"dialogData.getValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(dialogData.entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(dialogData.entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(dialogData.entity, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n </mat-dialog-content>\n\n <mat-dialog-actions>\n <button mat-raised-button (click)=\"addArrayItem()\" [disabled]=\"!EntityUtilities.isEntityValid(dialogData.entity, 'create')\">\n {{dialogData.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancelAddArrayItem()\" class=\"cancel-button\">\n {{dialogData.createDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n\n</ng-template>", styles: ["mat-form-field{width:100%}::ng-deep .hideUnderline .mat-form-field-underline{opacity:0%}.entityArray .buttons{display:flex;justify-content:space-between;margin-bottom:10px;margin-top:5px}.entityArray mat-table{border:1px solid #E0E0E0;border-radius:5px;padding-top:5px;padding-bottom:25px}.entityArray .mat-column-select{flex:0 0 75px}.entityArray .array-error{display:flex;align-items:center;justify-content:center;margin-top:-25.8px;border:1px solid #E0E0E0;background-color:#f8d3d7;color:#721c24;height:25.8px;border-bottom-left-radius:5px;border-bottom-right-radius:5px}.date-time{display:flex;align-items:baseline}.date-time .timepicker{margin-left:10px}\n"], components: [{ type: i2.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i3$1.MatAutocomplete, selector: "mat-autocomplete", inputs: ["disableRipple"], exportAs: ["matAutocomplete"] }, { type: i4.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { type: i5.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex", "name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "checked"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit"] }, { type: i3.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { type: i10.MatChipList, selector: "mat-chip-list", inputs: ["errorStateMatcher", "multiple", "compareWith", "value", "required", "placeholder", "disabled", "aria-orientation", "selectable", "tabIndex"], outputs: ["change", "valueChange"], exportAs: ["matChipList"] }, { type: i11.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { type: i11.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { type: i11.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { type: i11.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }], directives: [{ type: i12.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i12.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i12.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i2.MatLabel, selector: "mat-label" }, { type: i13.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i14.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i14.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i14.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i14.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i14.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { type: i14.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { type: i14.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { type: i2.MatError, selector: "mat-error", inputs: ["id"] }, { type: i15.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { type: i3$1.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", exportAs: ["matAutocompleteTrigger"] }, { type: i12.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i14.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { type: i14.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { type: i14.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i9.MatCellDef, selector: "[matCellDef]" }, { type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { type: i10.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["color", "disableRipple", "tabIndex", "selected", "value", "selectable", "disabled", "removable"], outputs: ["selectionChange", "destroyed", "removed"], exportAs: ["matChip"] }, { type: i10.MatChipRemove, selector: "[matChipRemove]" }, { type: i10.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { type: i11.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { type: i2.MatSuffix, selector: "[matSuffix]" }, { type: i11.MatStartDate, selector: "input[matStartDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i11.MatEndDate, selector: "input[matEndDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i12.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i14.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i14.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i14.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }] });
2955
+ 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]" }] });
1505
2956
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputComponent, decorators: [{
1506
2957
  type: Component,
1507
- args: [{ selector: 'ngx-mat-entity-input', template: "<div [ngSwitch]=\"type\" *ngIf=\"!(hideOmitForCreate && metadata.omitForCreate) && !(hideOmitForEdit && metadata.omitForUpdate)\">\n <!-------------------------------------------->\n <!-----------------Strings-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.STRING\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [pattern]=\"metadataDefaultString.regex ? metadataDefaultString.regex : '[\\\\s\\\\S]*'\"\n [minlength]=\"metadataDefaultString.minLength ? metadataDefaultString.minLength : null\"\n [maxlength]=\"metadataDefaultString.maxLength ? metadataDefaultString.maxLength : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_TEXTBOX\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <textarea\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"10\"\n [required]=\"metadata.required\"\n [minlength]=\"metadataTextboxString.minLength ? metadataTextboxString.minLength : null\"\n [maxlength]=\"metadataTextboxString.maxLength ? metadataTextboxString.maxLength : null\"\n >\n </textarea>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_AUTOCOMPLETE\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matAutocomplete]=\"auto\"\n (keyup)=\"filterAutocompleteStrings(entity[propertyKey])\"\n [required]=\"metadata.required\"\n [minlength]=\"metadataAutocompleteString.minLength ? metadataAutocompleteString.minLength : null\"\n [maxlength]=\"metadataAutocompleteString.maxLength ? metadataAutocompleteString.maxLength : null\"\n [pattern]=\"metadataAutocompleteString.regex ? metadataAutocompleteString.regex : '[\\\\s\\\\S]*'\"\n />\n <mat-autocomplete #auto=\"matAutocomplete\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.STRING_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadataDropdownString.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-----------------Booleans------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_CHECKBOX\">\n <mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-checkbox (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\"></mat-checkbox>\n <!-- hidden input is needed so that the checkbox can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\">\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_TOGGLE\">\n <mat-form-field class=\"hideUnderline\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-slide-toggle (click)=\"model.control.markAsTouched()\" [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\"></mat-slide-toggle>\n <!-- hidden input is needed so that the toggle can be used inside a mat-form-field -->\n <input matInput hidden\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString() + 'Helper'\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required\">\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.BOOLEAN_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option [value]=\"undefined\">-</mat-option>\n <mat-option [value]=\"true\">{{metadataDropdownBoolean.dropdownTrue}}</mat-option>\n <mat-option [value]=\"false\">{{metadataDropdownBoolean.dropdownFalse}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!------------------Numbers------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n type=\"number\"\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDefaultNumber.min ? metadataDefaultNumber.min : null\"\n [max]=\"metadataDefaultNumber.max ? metadataDefaultNumber.max : null\"\n />\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.NUMBER_DROPDOWN\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\" [required]=\"metadata.required\">\n <mat-option *ngFor=\"let value of metadataDropdownNumber.dropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Object------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.OBJECT\">\n <b>{{metadataDefaultObject.displayName}}</b>\n <!-- iterates over the object properties -->\n\n <div class=\"row\" *ngFor=\"let row of objectPropertyRows\">\n <!--\n displays another ngx-material-entity with the:\n object as the entity,\n the current key in the loop received by the keyvalue direction as the propertyKey\n and the getValidationErrorMessage of the current component\n -->\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"objectProperty\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n class=\"col-lg-{{EntityUtilities.getWidth(objectProperty, key, 'lg')}} col-md-{{EntityUtilities.getWidth(objectProperty, key, 'md')}} col-sm-{{EntityUtilities.getWidth(objectProperty, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Array-------------------->\n <!-------------------------------------------->\n <div class=\"entityArray\" *ngSwitchCase=\"DecoratorTypes.ARRAY\">\n <div class=\"mat-elevation-z8\" style=\"border-radius: 5px;padding: 15px;margin-bottom: 15px;margin-top: 15px;\">\n\n <div style=\"padding-bottom: 10px\">\n <b>{{metadataEntityArray.displayName}}</b>\n </div>\n <div *ngIf=\"metadataEntityArray.createInline\">\n <div class=\"row\" *ngFor=\"let row of arrayItemInlineRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(arrayItem, key, 'lg')}} col-md-{{EntityUtilities.getWidth(arrayItem, key, 'md')}} col-sm-{{EntityUtilities.getWidth(arrayItem, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n \n <div class=\"buttons\">\n <button mat-raised-button\n [disabled]=\"metadataEntityArray.createInline && !EntityUtilities.isEntityValid(arrayItem, 'create')\"\n (click)=\"add()\">\n {{metadataEntityArray.addButtonLabel}}\n </button>\n <button mat-raised-button\n [disabled]=\"!selection.selected.length\"\n (click)=\"remove()\">\n {{metadataEntityArray.removeButtonLabel}}\n </button>\n </div>\n \n <mat-table [dataSource]=\"dataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox [disabled]=\"!dataSource.data.length\" (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"></mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\" class=\"module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"></mat-checkbox>\n </mat-cell>\n </ng-container>\n \n <ng-container *ngFor=\"let dCol of metadataEntityArray.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n \n <div class=\"array-error\" *ngIf=\"metadataEntityArray.required && !dataSource.data.length\">\n {{metadataEntityArray.missingErrorMessage}}\n </div>\n </div>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadataStringChipsArray.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-chip-list #chipList\n [(ngModel)]=\"entity[propertyKey]\" [name]=\"propertyKey.toString()\" #model=\"ngModel\"\n [required]=\"metadata.required\"\n >\n <mat-chip *ngFor=\"let value of stringChipsArrayValues\" (removed)=\"removeStringChipArrayValue(value)\">\n {{value}}\n <button matChipRemove>\n <i class=\"{{metadataStringChipsArray.deleteIcon}}\"></i>\n </button>\n </mat-chip>\n <input matInput\n [matChipInputFor]=\"chipList\"\n [matAutocomplete]=\"auto\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addStringChipArrayValue($event)\"\n (keyup)=\"filterAutocompleteStrings(chipsInput)\"\n [(ngModel)]=\"chipsInput\" [name]=\"propertyKey.toString()\" #chipsModel=\"ngModel\"\n #chipsElement\n [minlength]='metadataStringChipsArray.minLength ? metadataStringChipsArray.minLength : null'\n [maxlength]='metadataStringChipsArray.maxLength ? metadataStringChipsArray.maxLength : null'\n [pattern]=\"metadataStringChipsArray.regex ? metadataStringChipsArray.regex : '[\\\\s\\\\S]*'\"\n >\n <mat-error *ngIf=\"chipsModel.errors\">{{getValidationErrorMessage(chipsModel)}}</mat-error>\n </mat-chip-list>\n <mat-autocomplete #auto=\"matAutocomplete\" (optionSelected)=\"selected($event, chipsElement)\">\n <mat-option *ngFor=\"let value of filteredAutocompleteStrings\" [value]=\"value\">\n {{value}}\n </mat-option>\n </mat-autocomplete>\n <mat-error *ngIf=\"!chipsModel.errors\">{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Dates-------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.DATE\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"entity[propertyKey]\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadataDefaultDate.min ? metadataDefaultDate.min(DateUtilities.asDate(entity[propertyKey])) : undefined\"\n [max]=\"metadataDefaultDate.max ? metadataDefaultDate.max(DateUtilities.asDate(entity[propertyKey])) : undefined\"\n [matDatepickerFilter]=\"metadataDefaultDate.filter ? metadataDefaultDate.filter : defaultDateFilter\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.DATE_RANGE\">\n <mat-form-field appearance=\"standard\">\n <mat-label>{{metadata.displayName}}</mat-label>\n \n <mat-date-range-input [rangePicker]=\"picker\" [required]=\"metadata.required\" [dateFilter]=\"metadataDateRangeDate.filter ? metadataDateRangeDate.filter : defaultDateFilter\">\n <input matStartDate\n [(ngModel)]=\"dateRangeStart\"\n [name]=\"propertyKey.toString() + 'start'\"\n #startModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateRangeDate.minStart ? metadataDateRangeDate.minStart(dateRange.start) : undefined\"\n [max]=\"metadataDateRangeDate.maxStart ? metadataDateRangeDate.maxStart(dateRange.start) : undefined\"\n [placeholder]=\"metadataDateRangeDate.placeholderStart ? metadataDateRangeDate.placeholderStart : 'Start'\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n <input matEndDate\n [(ngModel)]=\"dateRangeEnd\"\n [name]=\"propertyKey.toString() + 'end'\"\n #endModel=\"ngModel\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateRangeDate.minEnd ? metadataDateRangeDate.minEnd(dateRange.end) : undefined\"\n [max]=\"metadataDateRangeDate.maxEnd ? metadataDateRangeDate.maxEnd(dateRange.end) : undefined\"\n [placeholder]=\"metadataDateRangeDate.placeholderEnd ? metadataDateRangeDate.placeholderEnd : 'End'\"\n (ngModelChange)=\"setDateRangeValues()\"\n >\n </mat-date-range-input>\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-date-range-picker #picker></mat-date-range-picker>\n\n <mat-error *ngIf=\"startModel.errors\">{{getValidationErrorMessage(startModel)}}</mat-error>\n <mat-error *ngIf=\"!startModel.errors && endModel.errors\">{{getValidationErrorMessage(endModel)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchCase=\"DecoratorTypes.DATE_TIME\" class=\"date-time\">\n <mat-form-field appearance=\"standard\" class=\"datepicker\">\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"dateTime\"\n [name]=\"propertyKey.toString()\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required\"\n [min]=\"metadataDateTimeDate.minDate ? metadataDateTimeDate.minDate(dateTime) : undefined\"\n [max]=\"metadataDateTimeDate.maxDate ? metadataDateTimeDate.maxDate(dateTime) : undefined\"\n [matDatepickerFilter]=\"metadataDateTimeDate.filterDate ? metadataDateTimeDate.filterDate : defaultDateFilter\"\n (dateInput)=\"setTime()\"\n >\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n <mat-form-field class=\"timepicker\">\n <mat-label>{{metadataDateTimeDate.timeDisplayName}}</mat-label>\n <mat-select\n [(ngModel)]=\"time\"\n [name]=\"propertyKey.toString() + 'time'\"\n #timeModel=\"ngModel\"\n [required]=\"metadata.required\"\n [compareWith]=\"compareTimes\"\n (ngModelChange)=\"setTime()\"\n >\n <mat-option *ngFor=\"let validTime of DateUtilities.getValidTimesForDropdown(\n DateUtilities.asDate(entity[propertyKey]),\n metadataDateTimeDate.times,\n metadataDateTimeDate.minTime,\n metadataDateTimeDate.maxTime,\n metadataDateTimeDate.filterTime\n )\"\n [value]=\"validTime.value\"\n >\n {{validTime.displayName}}\n </mat-option>\n </mat-select>\n <mat-error>{{getValidationErrorMessage(timeModel)}}</mat-error>\n </mat-form-field>\n </div>\n\n <div *ngSwitchDefault>ERROR: The type {{type}} is not known.</div>\n</div>\n\n<!--------------------------------------------------------->\n<!--------------------Add Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #addArrayItemDialog>\n <h2 mat-dialog-title>{{dialogData.createDialogData.title}}</h2>\n\n <mat-dialog-content>\n <form #form=\"ngForm\" class=\"row\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"dialogData.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n [getValidationErrorMessage]=\"dialogData.getValidationErrorMessage\"\n class=\"col-lg-{{EntityUtilities.getWidth(dialogData.entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(dialogData.entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(dialogData.entity, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n </mat-dialog-content>\n\n <mat-dialog-actions>\n <button mat-raised-button (click)=\"addArrayItem()\" [disabled]=\"!EntityUtilities.isEntityValid(dialogData.entity, 'create')\">\n {{dialogData.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancelAddArrayItem()\" class=\"cancel-button\">\n {{dialogData.createDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n\n</ng-template>", styles: ["mat-form-field{width:100%}::ng-deep .hideUnderline .mat-form-field-underline{opacity:0%}.entityArray .buttons{display:flex;justify-content:space-between;margin-bottom:10px;margin-top:5px}.entityArray mat-table{border:1px solid #E0E0E0;border-radius:5px;padding-top:5px;padding-bottom:25px}.entityArray .mat-column-select{flex:0 0 75px}.entityArray .array-error{display:flex;align-items:center;justify-content:center;margin-top:-25.8px;border:1px solid #E0E0E0;background-color:#f8d3d7;color:#721c24;height:25.8px;border-bottom-left-radius:5px;border-bottom-right-radius:5px}.date-time{display:flex;align-items:baseline}.date-time .timepicker{margin-left:10px}\n"] }]
2958
+ 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"] }]
1508
2959
  }], ctorParameters: function () { return [{ type: i1.MatDialog }]; }, propDecorators: { entity: [{
1509
2960
  type: Input
1510
2961
  }], propertyKey: [{
@@ -1515,6 +2966,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1515
2966
  type: Input
1516
2967
  }], hideOmitForEdit: [{
1517
2968
  type: Input
2969
+ }], isReadOnly: [{
2970
+ type: Input
2971
+ }], inputChangeEvent: [{
2972
+ type: Output
1518
2973
  }], addArrayItemDialog: [{
1519
2974
  type: ViewChild,
1520
2975
  args: ['addArrayItemDialog']
@@ -1523,7 +2978,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1523
2978
  class NgxMatEntityInputModule {
1524
2979
  }
1525
2980
  NgxMatEntityInputModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1526
- NgxMatEntityInputModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputModule, declarations: [NgxMatEntityInputComponent], imports: [CommonModule,
2981
+ NgxMatEntityInputModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputModule, declarations: [StringInputComponent,
2982
+ StringTextboxInputComponent,
2983
+ StringAutocompleteInputComponent,
2984
+ StringDropdownInputComponent,
2985
+ StringPasswordInputComponent,
2986
+ BooleanCheckboxInputComponent,
2987
+ BooleanToggleInputComponent,
2988
+ BooleanDropdownInputComponent,
2989
+ NumberInputComponent,
2990
+ NumberDropdownInputComponent,
2991
+ NumberSliderInputComponent,
2992
+ ArrayStringChipsInputComponent,
2993
+ ArrayStringAutocompleteChipsComponent,
2994
+ DateInputComponent,
2995
+ DateRangeInputComponent,
2996
+ DateTimeInputComponent,
2997
+ ArrayDateInputComponent,
2998
+ ArrayDateTimeInputComponent,
2999
+ ArrayDateRangeInputComponent,
3000
+ FileInputComponent,
3001
+ FileImageInputComponent,
3002
+ FileDefaultInputComponent,
3003
+ DragDropDirective,
3004
+ CustomInputComponent,
3005
+ NgxMatEntityInputComponent], imports: [CommonModule,
1527
3006
  MatInputModule,
1528
3007
  FormsModule,
1529
3008
  MatFormFieldModule,
@@ -1536,7 +3015,8 @@ NgxMatEntityInputModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0",
1536
3015
  MatTableModule,
1537
3016
  MatDialogModule,
1538
3017
  MatButtonModule,
1539
- MatDatepickerModule], exports: [NgxMatEntityInputComponent] });
3018
+ MatDatepickerModule,
3019
+ MatSliderModule], exports: [NgxMatEntityInputComponent] });
1540
3020
  NgxMatEntityInputModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputModule, imports: [[
1541
3021
  CommonModule,
1542
3022
  MatInputModule,
@@ -1551,13 +3031,38 @@ NgxMatEntityInputModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0",
1551
3031
  MatTableModule,
1552
3032
  MatDialogModule,
1553
3033
  MatButtonModule,
1554
- MatDatepickerModule
3034
+ MatDatepickerModule,
3035
+ MatSliderModule
1555
3036
  ]] });
1556
3037
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityInputModule, decorators: [{
1557
3038
  type: NgModule,
1558
3039
  args: [{
1559
3040
  declarations: [
1560
- NgxMatEntityInputComponent,
3041
+ StringInputComponent,
3042
+ StringTextboxInputComponent,
3043
+ StringAutocompleteInputComponent,
3044
+ StringDropdownInputComponent,
3045
+ StringPasswordInputComponent,
3046
+ BooleanCheckboxInputComponent,
3047
+ BooleanToggleInputComponent,
3048
+ BooleanDropdownInputComponent,
3049
+ NumberInputComponent,
3050
+ NumberDropdownInputComponent,
3051
+ NumberSliderInputComponent,
3052
+ ArrayStringChipsInputComponent,
3053
+ ArrayStringAutocompleteChipsComponent,
3054
+ DateInputComponent,
3055
+ DateRangeInputComponent,
3056
+ DateTimeInputComponent,
3057
+ ArrayDateInputComponent,
3058
+ ArrayDateTimeInputComponent,
3059
+ ArrayDateRangeInputComponent,
3060
+ FileInputComponent,
3061
+ FileImageInputComponent,
3062
+ FileDefaultInputComponent,
3063
+ DragDropDirective,
3064
+ CustomInputComponent,
3065
+ NgxMatEntityInputComponent
1561
3066
  ],
1562
3067
  imports: [
1563
3068
  CommonModule,
@@ -1573,7 +3078,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
1573
3078
  MatTableModule,
1574
3079
  MatDialogModule,
1575
3080
  MatButtonModule,
1576
- MatDatepickerModule
3081
+ MatDatepickerModule,
3082
+ MatSliderModule
1577
3083
  ],
1578
3084
  exports: [NgxMatEntityInputComponent]
1579
3085
  }]
@@ -1616,7 +3122,7 @@ class NgxMatEntityCreateDialogComponent {
1616
3122
  this.injector = injector;
1617
3123
  this.dialog = dialog;
1618
3124
  this.EntityUtilities = EntityUtilities;
1619
- this.getWidth = EntityUtilities.getWidth;
3125
+ this.isEntityValid = false;
1620
3126
  }
1621
3127
  ngOnInit() {
1622
3128
  this.data = new CreateEntityDialogDataBuilder(this.inputData).getResult();
@@ -1624,15 +3130,22 @@ class NgxMatEntityCreateDialogComponent {
1624
3130
  this.entityRows = EntityUtilities.getEntityRows(this.data.entity, true);
1625
3131
  this.entityService = this.injector.get(this.data.EntityServiceClass);
1626
3132
  }
3133
+ /**
3134
+ * Checks if the entity is valid.
3135
+ */
3136
+ checkIsEntityValid() {
3137
+ this.isEntityValid = EntityUtilities.isEntityValid(this.data.entity, 'create');
3138
+ }
1627
3139
  /**
1628
3140
  * Tries add the new entity and close the dialog afterwards.
1629
3141
  * Also handles the confirmation if required.
1630
3142
  */
1631
3143
  create() {
1632
- if (!this.data.createDialogData?.createRequiresConfirmDialog) {
1633
- return this.confirmCreate();
3144
+ if (!this.data.createDialogData.createRequiresConfirmDialog) {
3145
+ this.confirmCreate();
3146
+ return;
1634
3147
  }
1635
- const dialogData = new ConfirmDialogDataBuilder(this.data.createDialogData?.confirmCreateDialogData)
3148
+ const dialogData = new ConfirmDialogDataBuilder(this.data.createDialogData.confirmCreateDialogData)
1636
3149
  .withDefault('text', ['Do you really want to create this entity?'])
1637
3150
  .withDefault('confirmButtonLabel', 'Create')
1638
3151
  .withDefault('title', 'Create')
@@ -1649,7 +3162,7 @@ class NgxMatEntityCreateDialogComponent {
1649
3162
  });
1650
3163
  }
1651
3164
  confirmCreate() {
1652
- this.entityService.create(this.data.entity).then(() => this.dialogRef.close());
3165
+ void this.entityService.create(this.data.entity).then(() => this.dialogRef.close());
1653
3166
  }
1654
3167
  /**
1655
3168
  * Closes the dialog.
@@ -1659,10 +3172,10 @@ class NgxMatEntityCreateDialogComponent {
1659
3172
  }
1660
3173
  }
1661
3174
  NgxMatEntityCreateDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityCreateDialogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1.MatDialogRef }, { token: i0.Injector }, { token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
1662
- NgxMatEntityCreateDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityCreateDialogComponent, selector: "ngx-mat-entity-create-dialog", ngImport: i0, template: "<h2 mat-dialog-title>{{data.createDialogData.title}}</h2>\n\n<mat-dialog-content>\n <form #form=\"ngForm\">\n <div class=\"row\" *ngFor=\"let row of entityRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"data.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{getWidth(data.entity, key, 'lg')}} col-md-{{getWidth(data.entity, key, 'md')}} col-sm-{{getWidth(data.entity, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button mat-raised-button (click)=\"create()\" [disabled]=\"!EntityUtilities.isEntityValid(data.entity, 'create')\">\n {{data.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.createDialogData.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: ["mat-dialog-actions{display:flex;justify-content:space-between}\n"], components: [{ type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit"] }, { type: i3.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i14.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i14.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i14.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i12.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }] });
3175
+ 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]" }] });
1663
3176
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityCreateDialogComponent, decorators: [{
1664
3177
  type: Component,
1665
- args: [{ selector: 'ngx-mat-entity-create-dialog', template: "<h2 mat-dialog-title>{{data.createDialogData.title}}</h2>\n\n<mat-dialog-content>\n <form #form=\"ngForm\">\n <div class=\"row\" *ngFor=\"let row of entityRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"data.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{getWidth(data.entity, key, 'lg')}} col-md-{{getWidth(data.entity, key, 'md')}} col-sm-{{getWidth(data.entity, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button mat-raised-button (click)=\"create()\" [disabled]=\"!EntityUtilities.isEntityValid(data.entity, 'create')\">\n {{data.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.createDialogData.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: ["mat-dialog-actions{display:flex;justify-content:space-between}\n"] }]
3178
+ args: [{ selector: 'ngx-mat-entity-create-dialog', template: "<h2 mat-dialog-title>{{data.createDialogData.title}}</h2>\n\n<mat-dialog-content>\n <form #form=\"ngForm\">\n <div class=\"row\" *ngFor=\"let row of entityRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"data.entity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(data.entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(data.entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(data.entity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsEntityValid()\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button mat-raised-button (click)=\"create()\" [disabled]=\"!isEntityValid\">\n {{data.createDialogData.createButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.createDialogData.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: ["mat-dialog-actions{display:flex;justify-content:space-between}\n"] }]
1666
3179
  }], ctorParameters: function () { return [{ type: undefined, decorators: [{
1667
3180
  type: Inject,
1668
3181
  args: [MAT_DIALOG_DATA]
@@ -1703,7 +3216,7 @@ class EditDialogDataBuilder extends BaseBuilder {
1703
3216
  .withDefault('text', ['Do you really want to delete this entity?'])
1704
3217
  .withDefault('title', 'Delete')
1705
3218
  .getResult();
1706
- return new EditDialogDataInternal(data?.title ? data.title : () => 'Edit', data?.confirmButtonLabel ? data.confirmButtonLabel : 'Save', data?.deleteButtonLabel ? data.deleteButtonLabel : 'Delete', data?.cancelButtonLabel ? data.cancelButtonLabel : 'Cancel', data?.deleteRequiresConfirmDialog ? data.deleteRequiresConfirmDialog : true, data?.editRequiresConfirmDialog ? data.editRequiresConfirmDialog : false, confirmDeleteDialogData, confirmEditDialogData);
3219
+ return new EditDialogDataInternal(data?.title ?? (() => 'Edit'), data?.confirmButtonLabel ?? 'Save', data?.deleteButtonLabel ?? 'Delete', data?.cancelButtonLabel ?? 'Cancel', data?.deleteRequiresConfirmDialog ?? true, data?.editRequiresConfirmDialog ?? false, confirmDeleteDialogData, confirmEditDialogData);
1707
3220
  }
1708
3221
  }
1709
3222
 
@@ -1711,11 +3224,12 @@ class EditDialogDataBuilder extends BaseBuilder {
1711
3224
  * The internal EditEntityDialogData. Requires all default values the user can leave out.
1712
3225
  */
1713
3226
  class EditEntityDialogDataInternal {
1714
- constructor(entity, EntityServiceClass, editDialogData, allowDelete) {
3227
+ constructor(entity, EntityServiceClass, editDialogData, allowUpdate, allowDelete) {
1715
3228
  this.entity = entity;
1716
3229
  this.EntityServiceClass = EntityServiceClass;
1717
3230
  this.editDialogData = editDialogData;
1718
3231
  this.allowDelete = allowDelete;
3232
+ this.allowUpdate = allowUpdate;
1719
3233
  }
1720
3234
  }
1721
3235
  /**
@@ -1728,7 +3242,7 @@ class EditEntityDialogDataBuilder extends BaseBuilder {
1728
3242
  // eslint-disable-next-line jsdoc/require-jsdoc
1729
3243
  generateBaseData(data) {
1730
3244
  const editDialogData = new EditDialogDataBuilder(data.editDialogData).getResult();
1731
- return new EditEntityDialogDataInternal(data.entity, data.EntityServiceClass, editDialogData, data.allowDelete ? data.allowDelete : () => true);
3245
+ return new EditEntityDialogDataInternal(data.entity, data.EntityServiceClass, editDialogData, data.allowUpdate ?? (() => true), data.allowDelete ?? (() => true));
1732
3246
  }
1733
3247
  }
1734
3248
 
@@ -1745,14 +3259,21 @@ class NgxMatEntityEditDialogComponent {
1745
3259
  this.injector = injector;
1746
3260
  this.dialog = dialog;
1747
3261
  this.EntityUtilities = EntityUtilities;
1748
- this.getWidth = EntityUtilities.getWidth;
3262
+ this.isEntityValid = true;
3263
+ this.isEntityDirty = (async () => false).call(this);
1749
3264
  }
1750
3265
  ngOnInit() {
1751
3266
  this.data = new EditEntityDialogDataBuilder(this.inputData).getResult();
3267
+ this.isReadOnly = !this.data.allowUpdate(this.entityPriorChanges);
1752
3268
  this.dialogRef.disableClose = true;
1753
3269
  this.entityRows = EntityUtilities.getEntityRows(this.data.entity, false, true);
1754
3270
  this.entityService = this.injector.get(this.data.EntityServiceClass);
1755
- this.entityPriorChanges = cloneDeep(this.data.entity);
3271
+ this.entityPriorChanges = LodashUtilities.cloneDeep(this.data.entity);
3272
+ }
3273
+ // eslint-disable-next-line jsdoc/require-jsdoc
3274
+ checkEntity() {
3275
+ this.isEntityValid = EntityUtilities.isEntityValid(this.data.entity, 'update');
3276
+ this.isEntityDirty = EntityUtilities.isDirty(this.data.entity, this.entityPriorChanges);
1756
3277
  }
1757
3278
  /**
1758
3279
  * Tries to save the changes and close the dialog afterwards.
@@ -1760,7 +3281,8 @@ class NgxMatEntityEditDialogComponent {
1760
3281
  */
1761
3282
  edit() {
1762
3283
  if (!this.data.editDialogData.editRequiresConfirmDialog) {
1763
- return this.confirmEdit();
3284
+ this.confirmEdit();
3285
+ return;
1764
3286
  }
1765
3287
  const dialogData = new ConfirmDialogDataBuilder(this.data.editDialogData.confirmEditDialogData)
1766
3288
  .withDefault('text', ['Do you really want to save all changes?'])
@@ -1779,7 +3301,7 @@ class NgxMatEntityEditDialogComponent {
1779
3301
  });
1780
3302
  }
1781
3303
  confirmEdit() {
1782
- this.entityService.update(this.data.entity, this.entityPriorChanges).then(() => this.dialogRef.close(1));
3304
+ void this.entityService.update(this.data.entity, this.entityPriorChanges).then(() => this.dialogRef.close(1));
1783
3305
  }
1784
3306
  /**
1785
3307
  * Tries to delete the entity and close the dialog afterwards.
@@ -1787,7 +3309,8 @@ class NgxMatEntityEditDialogComponent {
1787
3309
  */
1788
3310
  delete() {
1789
3311
  if (!this.data.editDialogData.deleteRequiresConfirmDialog) {
1790
- return this.confirmDelete();
3312
+ this.confirmDelete();
3313
+ return;
1791
3314
  }
1792
3315
  const dialogData = new ConfirmDialogDataBuilder(this.data.editDialogData.confirmDeleteDialogData)
1793
3316
  .withDefault('text', ['Do you really want to delete this entity?'])
@@ -1807,7 +3330,7 @@ class NgxMatEntityEditDialogComponent {
1807
3330
  });
1808
3331
  }
1809
3332
  confirmDelete() {
1810
- this.entityService.delete(this.entityPriorChanges).then(() => this.dialogRef.close(2));
3333
+ void this.entityService.delete(this.entityPriorChanges).then(() => this.dialogRef.close(2));
1811
3334
  }
1812
3335
  /**
1813
3336
  * Reverts all changes made and closes the dialog.
@@ -1818,10 +3341,10 @@ class NgxMatEntityEditDialogComponent {
1818
3341
  }
1819
3342
  }
1820
3343
  NgxMatEntityEditDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityEditDialogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1.MatDialogRef }, { token: i0.Injector }, { token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
1821
- NgxMatEntityEditDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityEditDialogComponent, selector: "ngx-mat-entity-edit-dialog", ngImport: i0, template: "<h2 mat-dialog-title>\n {{data.editDialogData.title(data.entity)}}\n <button *ngIf=\"data.allowDelete(data.entity)\" mat-raised-button (click)=\"delete()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{data.editDialogData.deleteButtonLabel}}\n </button>\n</h2>\n\n<mat-dialog-content>\n <form #form=\"ngForm\" class=\"row\">\n <div class=\"row\" *ngFor=\"let row of entityRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"data.entity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{getWidth(data.entity, key, 'lg')}} col-md-{{getWidth(data.entity, key, 'md')}} col-sm-{{getWidth(data.entity, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button mat-raised-button (click)=\"edit()\" [disabled]=\"!EntityUtilities.isEntityValid(data.entity, 'update') || !EntityUtilities.dirty(data.entity, entityPriorChanges)\">\n {{data.editDialogData.confirmButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.editDialogData.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: ["mat-dialog-actions{display:flex;justify-content:space-between}.delete-button{float:right}\n"], components: [{ type: i3.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit"] }], directives: [{ type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i12.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i14.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i14.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i14.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i12.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }] });
3344
+ 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 } });
1822
3345
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityEditDialogComponent, decorators: [{
1823
3346
  type: Component,
1824
- args: [{ selector: 'ngx-mat-entity-edit-dialog', template: "<h2 mat-dialog-title>\n {{data.editDialogData.title(data.entity)}}\n <button *ngIf=\"data.allowDelete(data.entity)\" mat-raised-button (click)=\"delete()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{data.editDialogData.deleteButtonLabel}}\n </button>\n</h2>\n\n<mat-dialog-content>\n <form #form=\"ngForm\" class=\"row\">\n <div class=\"row\" *ngFor=\"let row of entityRows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"data.entity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{getWidth(data.entity, key, 'lg')}} col-md-{{getWidth(data.entity, key, 'md')}} col-sm-{{getWidth(data.entity, key, 'sm')}}\"\n >\n </ngx-mat-entity-input>\n </div>\n </form>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <button mat-raised-button (click)=\"edit()\" [disabled]=\"!EntityUtilities.isEntityValid(data.entity, 'update') || !EntityUtilities.dirty(data.entity, entityPriorChanges)\">\n {{data.editDialogData.confirmButtonLabel}}\n </button>\n <button mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.editDialogData.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>\n", styles: ["mat-dialog-actions{display:flex;justify-content:space-between}.delete-button{float:right}\n"] }]
3347
+ 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"] }]
1825
3348
  }], ctorParameters: function () { return [{ type: undefined, decorators: [{
1826
3349
  type: Inject,
1827
3350
  args: [MAT_DIALOG_DATA]
@@ -1846,14 +3369,14 @@ class BaseDataBuilder extends BaseBuilder {
1846
3369
  }
1847
3370
  // eslint-disable-next-line jsdoc/require-jsdoc
1848
3371
  generateBaseData(data) {
1849
- return new BaseDataInternal(data.title, data.displayColumns, data.EntityServiceClass, data.searchLabel ? data.searchLabel : 'Search', data.createButtonLabel ? data.createButtonLabel : 'Create', data.searchString ? data.searchString : defaultSearchFunction, data.allowCreate === false ? data.allowCreate : true, data.allowEdit ? data.allowEdit : () => true, data.allowDelete ? data.allowDelete : () => true, data.multiSelectActions ? data.multiSelectActions : [], data.multiSelectLabel ? data.multiSelectLabel : 'Actions', data.EntityClass, data.edit, data.create);
3372
+ return new BaseDataInternal(data.title, data.displayColumns, data.EntityServiceClass, data.searchLabel ?? 'Search', data.createButtonLabel ?? 'Create', data.searchString ?? defaultSearchFunction, data.allowCreate ?? (() => true), data.allowRead ?? (() => true), data.allowUpdate ?? (() => true), data.allowDelete ?? (() => true), data.multiSelectActions ?? [], data.multiSelectLabel ?? 'Actions', data.EntityClass, data.edit, data.create);
1850
3373
  }
1851
3374
  }
1852
3375
  /**
1853
3376
  * The internal TableData. Requires all default values the user can leave out.
1854
3377
  */
1855
3378
  class BaseDataInternal {
1856
- constructor(title, displayColumns, EntityServiceClass, searchLabel, createButtonLabel, searchString, allowCreate, allowEdit, allowDelete, multiSelectActions, multiSelectLabel, EntityClass, edit, create) {
3379
+ constructor(title, displayColumns, EntityServiceClass, searchLabel, createButtonLabel, searchString, allowCreate, allowRead, allowUpdate, allowDelete, multiSelectActions, multiSelectLabel, EntityClass, edit, create) {
1857
3380
  this.title = title;
1858
3381
  this.displayColumns = displayColumns;
1859
3382
  this.EntityServiceClass = EntityServiceClass;
@@ -1862,7 +3385,8 @@ class BaseDataInternal {
1862
3385
  this.createButtonLabel = createButtonLabel;
1863
3386
  this.searchString = searchString;
1864
3387
  this.allowCreate = allowCreate;
1865
- this.allowEdit = allowEdit;
3388
+ this.allowRead = allowRead;
3389
+ this.allowUpdate = allowUpdate;
1866
3390
  this.allowDelete = allowDelete;
1867
3391
  this.multiSelectActions = multiSelectActions;
1868
3392
  this.multiSelectLabel = multiSelectLabel;
@@ -1890,24 +3414,26 @@ class TableDataBuilder extends BaseBuilder {
1890
3414
  throw new Error(`The name "select" for a display column is reserved for the multi-select action functionality.
1891
3415
  Please choose a different name.`);
1892
3416
  }
1893
- if ((data.baseData.allowEdit && data.baseData.allowEdit !== (() => false)
1894
- || data.baseData.allowDelete && data.baseData.allowDelete !== (() => false)
1895
- || data.baseData.allowCreate)
3417
+ if ((data.baseData.allowCreate !== (() => false)
3418
+ || data.baseData.allowRead !== (() => false)
3419
+ || data.baseData.allowUpdate !== (() => false)
3420
+ || data.baseData.allowDelete !== (() => false))
1896
3421
  && !data.baseData.EntityClass) {
1897
3422
  throw new Error(`
1898
3423
  Missing required Input data "EntityClass".
1899
3424
  You can only omit this value if you can neither create or update entities.`);
1900
3425
  }
1901
- if (data.baseData.allowCreate !== false && !data.baseData.create && !data.createDialogData) {
3426
+ if (data.baseData.allowCreate !== (() => false) && !data.baseData.create && !data.createDialogData) {
1902
3427
  throw new Error(`Missing required Input data "createDialogData".
1903
3428
  You can only omit this value when creation is disallowed or done with a custom create method.`);
1904
3429
  }
1905
- if ((data.baseData.allowEdit !== (() => false)
3430
+ if ((data.baseData.allowRead !== (() => false)
3431
+ || data.baseData.allowUpdate !== (() => false)
1906
3432
  || data.baseData.allowDelete !== (() => false))
1907
3433
  && !data.baseData.edit
1908
3434
  && !data.editDialogData) {
1909
3435
  throw new Error(`Missing required Input data "editDialogData".
1910
- You can only omit this value when editing and deleting is disallowed or done with a custom edit method.`);
3436
+ You can only omit this value when viewing, editing and deleting is disallowed or done with a custom edit method.`);
1911
3437
  }
1912
3438
  }
1913
3439
  }
@@ -1960,21 +3486,19 @@ class NgxMatEntityTableComponent {
1960
3486
  return this.data.baseData.displayColumns.find((dp) => dp.displayName === header)?.value(entity);
1961
3487
  };
1962
3488
  this.dataSource.sort = this.sort;
1963
- if (this.data.baseData.searchString) {
1964
- this.dataSource.filterPredicate = (entity, filter) => {
1965
- const searchStr = this.data.baseData.searchString(entity);
1966
- const formattedSearchString = searchStr.toLowerCase();
1967
- const formattedFilterString = filter.toLowerCase();
1968
- return formattedSearchString.includes(formattedFilterString);
1969
- };
1970
- }
3489
+ this.dataSource.filterPredicate = (entity, filter) => {
3490
+ const searchStr = this.data.baseData.searchString(entity);
3491
+ const formattedSearchString = searchStr.toLowerCase();
3492
+ const formattedFilterString = filter.toLowerCase();
3493
+ return formattedSearchString.includes(formattedFilterString);
3494
+ };
1971
3495
  this.dataSource.filter = this.filter;
1972
3496
  this.dataSource.paginator = this.paginator;
1973
3497
  this.entityService.entitiesSubject.pipe(takeUntil(this.onDestroy)).subscribe((entities) => {
1974
3498
  this.dataSource.data = entities;
1975
3499
  this.selection.clear();
1976
3500
  });
1977
- this.entityService.read();
3501
+ void this.entityService.read();
1978
3502
  }
1979
3503
  /**
1980
3504
  * Edits an entity. This either calls the edit-Method provided by the user or uses a default edit-dialog.
@@ -1983,39 +3507,40 @@ class NgxMatEntityTableComponent {
1983
3507
  * @throws When no EntityClass was provided, as a new call is needed to initialize metadata.
1984
3508
  */
1985
3509
  editEntity(entity) {
1986
- if (this.data.baseData.allowEdit(entity)) {
1987
- if (!this.data.baseData.EntityClass) {
1988
- throw new Error('No "EntityClass" specified for this table');
1989
- }
1990
- if (this.data.baseData.edit) {
1991
- this.data.baseData.edit(new this.data.baseData.EntityClass(entity));
1992
- }
1993
- else {
1994
- this.editDefault(new this.data.baseData.EntityClass(entity));
1995
- }
3510
+ if (!(this.data.baseData.allowUpdate(entity) || this.data.baseData.allowRead(entity))) {
3511
+ return;
3512
+ }
3513
+ if (!this.data.baseData.EntityClass) {
3514
+ throw new Error('No "EntityClass" specified for this table');
3515
+ }
3516
+ if (this.data.baseData.edit) {
3517
+ this.data.baseData.edit(new this.data.baseData.EntityClass(entity));
3518
+ }
3519
+ else {
3520
+ void this.editDefault(new this.data.baseData.EntityClass(entity));
1996
3521
  }
1997
3522
  }
1998
- editDefault(entity) {
3523
+ async editDefault(entity) {
1999
3524
  const inputDialogData = {
2000
3525
  entity: entity,
2001
3526
  EntityServiceClass: this.data.baseData.EntityServiceClass,
3527
+ allowUpdate: this.data.baseData.allowUpdate,
2002
3528
  allowDelete: this.data.baseData.allowDelete,
2003
3529
  editDialogData: this.data.editDialogData
2004
3530
  };
2005
3531
  const dialogData = new EditEntityDialogDataBuilder(inputDialogData).getResult();
2006
- firstValueFrom(this.dialog.open(NgxMatEntityEditDialogComponent, {
3532
+ const res = await firstValueFrom(this.dialog.open(NgxMatEntityEditDialogComponent, {
2007
3533
  data: dialogData,
2008
3534
  minWidth: '60%',
2009
3535
  autoFocus: false,
2010
3536
  restoreFocus: false
2011
- }).afterClosed()).then((res) => {
2012
- if (res === 0) {
2013
- const data = this.dataSource.data;
2014
- data[this.dataSource.data.findIndex((e) => e[this.entityService.idKey] === entity[this.entityService.idKey])] = entity;
2015
- this.dataSource.data = data;
2016
- this.selection.clear();
2017
- }
2018
- });
3537
+ }).afterClosed());
3538
+ if (res === 0) {
3539
+ const data = this.dataSource.data;
3540
+ data[this.dataSource.data.findIndex((e) => e[this.entityService.idKey] === entity[this.entityService.idKey])] = entity;
3541
+ this.dataSource.data = data;
3542
+ this.selection.clear();
3543
+ }
2019
3544
  }
2020
3545
  /**
2021
3546
  * Creates a new Entity. This either calls the create-Method provided by the user or uses a default create-dialog.
@@ -2023,7 +3548,7 @@ class NgxMatEntityTableComponent {
2023
3548
  * @throws When no EntityClass was provided, as a new call is needed to initialize metadata.
2024
3549
  */
2025
3550
  createEntity() {
2026
- if (this.data.baseData.allowCreate) {
3551
+ if (this.data.baseData.allowCreate()) {
2027
3552
  if (!this.data.baseData.EntityClass) {
2028
3553
  throw new Error('No "EntityClass" specified for this table');
2029
3554
  }
@@ -2056,7 +3581,8 @@ class NgxMatEntityTableComponent {
2056
3581
  */
2057
3582
  runMultiAction(action) {
2058
3583
  if (!action.requireConfirmDialog || !action.requireConfirmDialog(this.selection.selected)) {
2059
- return this.confirmRunMultiAction(action);
3584
+ this.confirmRunMultiAction(action);
3585
+ return;
2060
3586
  }
2061
3587
  const dialogData = new ConfirmDialogDataBuilder(action.confirmDialogData)
2062
3588
  .withDefault('text', [`Do you really want to run this action on ${this.selection.selected.length} entries?`])
@@ -2099,7 +3625,7 @@ class NgxMatEntityTableComponent {
2099
3625
  this.selection.clear();
2100
3626
  }
2101
3627
  else {
2102
- this.dataSource.data.forEach((row) => this.selection.select(row));
3628
+ this.dataSource.data.forEach(row => this.selection.select(row));
2103
3629
  }
2104
3630
  }
2105
3631
  /**
@@ -2128,10 +3654,10 @@ class NgxMatEntityTableComponent {
2128
3654
  }
2129
3655
  }
2130
3656
  NgxMatEntityTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityTableComponent, deps: [{ token: i1.MatDialog }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
2131
- NgxMatEntityTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxMatEntityTableComponent, selector: "ngx-mat-entity-table", inputs: { tableData: "tableData" }, viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, static: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true, static: true }, { propertyName: "filter", first: true, predicate: ["filter"], descendants: true, static: true }], ngImport: i0, template: "<h1 class=\"title\">{{data.baseData.title}}</h1>\n\n<div class=\"row\">\n <mat-form-field class=\"col-lg-8 col-md-6 col-sm-12\">\n <mat-label>{{data.baseData.searchLabel}}</mat-label>\n <input matInput (keyup)=\"applyFilter($event)\" />\n </mat-form-field>\n <div\n *ngIf=\"data.baseData.multiSelectActions.length\"\n [class.col-lg-2]=\"data.baseData.allowCreate\"\n [class.col-lg-4]=\"!data.baseData.allowCreate\"\n [class.col-md-3]=\"data.baseData.allowCreate\"\n [class.col-md-6]=\"!data.baseData.allowCreate\"\n [class.col-sm-6]=\"data.baseData.allowCreate\"\n [class.col-sm-12]=\"!data.baseData.allowCreate\"\n >\n <button class=\"actions-button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{data.baseData.multiSelectLabel}}\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button *ngFor=\"let action of data.baseData.multiSelectActions\" [disabled]=\"multiActionDisabled(action)\" (click)=\"runMultiAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n\n <div\n *ngIf=\"data.baseData.allowCreate\"\n [class.col-lg-2]=\"data.baseData.multiSelectActions.length\"\n [class.col-lg-4]=\"!data.baseData.multiSelectActions.length\"\n [class.col-md-3]=\"data.baseData.multiSelectActions.length\"\n [class.col-md-6]=\"!data.baseData.multiSelectActions.length\"\n [class.col-sm-6]=\"data.baseData.multiSelectActions.length\"\n [class.col-sm-12]=\"!data.baseData.multiSelectActions.length\"\n >\n <button class=\"create-button\" (click)=\"createEntity()\" mat-raised-button>\n {{data.baseData.createButtonLabel}}\n </button>\n </div>\n</div>\n\n<div class=\"mat-elevation-z8\">\n <mat-table *ngIf=\"dataSource\" [dataSource]=\"dataSource\" matSort>\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\" [indeterminate]=\"selection.hasValue() && !isAllSelected()\"> </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let module\" class=\"module\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(module) : null\" [checked]=\"selection.isSelected(module)\"> </mat-checkbox>\n </mat-cell>\n </ng-container>\n\n <ng-container *ngFor=\"let dCol of data.baseData.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell class=\"entity\" [class.enabled]=\"data.baseData.allowEdit(entity)\" (click)=\"editEntity(entity)\" *matCellDef=\"let entity\">\n {{dCol.value(entity)}}\n </mat-cell>\n </ng-container>\n\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns\"></mat-row>\n </mat-table>\n\n <mat-paginator *ngIf=\"dataSource\" id=\"paginator\" [length]=\"dataSource.filteredData.length\" [pageIndex]=\"0\" [pageSize]=\"10\" [pageSizeOptions]=\"[5, 10, 25, 50]\"> </mat-paginator>\n</div>\n", styles: [".title{text-align:center}button{width:100%}.mat-column-select{flex:0 0 75px}.enabled:hover{cursor:pointer}@media (max-width: 767px){.actions-button,.create-button{margin-bottom:15px}}\n"], components: [{ type: i2.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i3.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i4$1.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { type: i4$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { type: i7$1.MatPaginator, selector: "mat-paginator", inputs: ["disabled"], exportAs: ["matPaginator"] }], directives: [{ type: i2.MatLabel, selector: "mat-label" }, { type: i13.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i12.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { type: i12.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i9.MatCellDef, selector: "[matCellDef]" }, { type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }] });
3657
+ 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"] }] });
2132
3658
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxMatEntityTableComponent, decorators: [{
2133
3659
  type: Component,
2134
- 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"] }]
3660
+ 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"] }]
2135
3661
  }], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i0.Injector }]; }, propDecorators: { tableData: [{
2136
3662
  type: Input
2137
3663
  }], paginator: [{
@@ -2265,16 +3791,83 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
2265
3791
  class EntityArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2266
3792
  constructor(data) {
2267
3793
  super(data);
2268
- this.createInline = data.createInline != undefined ? data.createInline : true;
2269
- this.displayStyle = data.displayStyle;
3794
+ this.createInline = data.createInline ?? true;
2270
3795
  this.itemType = data.itemType;
3796
+ this.allowDuplicates = data.allowDuplicates ?? false;
3797
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
2271
3798
  this.EntityClass = data.EntityClass;
2272
3799
  this.displayColumns = data.displayColumns;
2273
- this.createInline = data.createInline != undefined ? data.createInline : true;
2274
- this.missingErrorMessage = data.missingErrorMessage ? data.missingErrorMessage : 'Needs to contain at least one value';
2275
- this.defaultWidths = data.defaultWidths ? data.defaultWidths : [12, 12, 12];
2276
- this.addButtonLabel = data.addButtonLabel ? data.addButtonLabel : 'Add';
2277
- this.removeButtonLabel = data.removeButtonLabel ? data.removeButtonLabel : 'Remove';
3800
+ this.createInline = data.createInline ?? true;
3801
+ this.missingErrorMessage = data.missingErrorMessage ?? 'Needs to contain at least one value';
3802
+ this.defaultWidths = data.defaultWidths ?? [12, 12, 12];
3803
+ this.addButtonLabel = data.addButtonLabel ?? 'Add';
3804
+ this.removeButtonLabel = data.removeButtonLabel ?? 'Remove';
3805
+ }
3806
+ }
3807
+ /**
3808
+ * The internal DateArrayDecoratorConfig. Sets default values.
3809
+ */
3810
+ class DateArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
3811
+ constructor(data) {
3812
+ super(data);
3813
+ this.itemType = data.itemType;
3814
+ this.allowDuplicates = data.allowDuplicates ?? false;
3815
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
3816
+ this.displayColumns = data.displayColumns;
3817
+ this.defaultWidths = data.defaultWidths ?? [12, 12, 12];
3818
+ this.addButtonLabel = data.addButtonLabel ?? 'Add';
3819
+ this.removeButtonLabel = data.removeButtonLabel ?? 'Remove';
3820
+ this.missingErrorMessage = data.missingErrorMessage ?? 'Needs to contain at least one value';
3821
+ this.min = data.min;
3822
+ this.max = data.max;
3823
+ this.filter = data.filter;
3824
+ }
3825
+ }
3826
+ /**
3827
+ * The internal DateTimeArrayDecoratorConfig. Sets default values.
3828
+ */
3829
+ class DateTimeArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
3830
+ constructor(data) {
3831
+ super(data);
3832
+ this.itemType = data.itemType;
3833
+ this.allowDuplicates = data.allowDuplicates ?? false;
3834
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
3835
+ this.displayColumns = data.displayColumns;
3836
+ this.defaultWidths = data.defaultWidths ?? [12, 12, 12];
3837
+ this.addButtonLabel = data.addButtonLabel ?? 'Add';
3838
+ this.removeButtonLabel = data.removeButtonLabel ?? 'Remove';
3839
+ this.missingErrorMessage = data.missingErrorMessage ?? 'Needs to contain at least one value';
3840
+ this.times = data.times ?? DateUtilities.getDefaultTimes();
3841
+ this.timeDisplayName = data.timeDisplayName ?? 'Time';
3842
+ this.minDate = data.minDate;
3843
+ this.maxDate = data.maxDate;
3844
+ this.filterDate = data.filterDate;
3845
+ this.minTime = data.minTime;
3846
+ this.maxTime = data.maxTime;
3847
+ this.filterTime = data.filterTime;
3848
+ }
3849
+ }
3850
+ /**
3851
+ * The internal DateRangeArrayDecoratorConfig. Sets default values.
3852
+ */
3853
+ class DateRangeArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
3854
+ constructor(data) {
3855
+ super(data);
3856
+ this.itemType = data.itemType;
3857
+ this.allowDuplicates = data.allowDuplicates ?? false;
3858
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
3859
+ this.displayColumns = data.displayColumns;
3860
+ this.defaultWidths = data.defaultWidths ?? [12, 12, 12];
3861
+ this.addButtonLabel = data.addButtonLabel ?? 'Add';
3862
+ this.removeButtonLabel = data.removeButtonLabel ?? 'Remove';
3863
+ this.missingErrorMessage = data.missingErrorMessage ?? 'Needs to contain at least one value';
3864
+ this.placeholderStart = data.placeholderStart ?? 'Start';
3865
+ this.placeholderEnd = data.placeholderEnd ?? 'End';
3866
+ this.minStart = data.minStart;
3867
+ this.maxStart = data.maxStart;
3868
+ this.minEnd = data.minEnd;
3869
+ this.maxEnd = data.maxEnd;
3870
+ this.filter = data.filter;
2278
3871
  }
2279
3872
  }
2280
3873
  /**
@@ -2283,13 +3876,14 @@ class EntityArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal
2283
3876
  class StringChipsArrayDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
2284
3877
  constructor(data) {
2285
3878
  super(data);
2286
- this.deleteIcon = data.deleteIcon ? data.deleteIcon : 'fas fa-circle-minus';
2287
- this.displayStyle = data.displayStyle;
3879
+ this.deleteIcon = data.deleteIcon ?? 'fas fa-circle-minus';
2288
3880
  this.itemType = data.itemType;
3881
+ this.allowDuplicates = data.allowDuplicates ?? false;
3882
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
2289
3883
  this.maxLength = data.maxLength;
2290
3884
  this.minLength = data.minLength;
2291
3885
  this.regex = data.regex;
2292
- this.defaultWidths = data.defaultWidths ? data.defaultWidths : [6, 12, 12];
3886
+ this.defaultWidths = data.defaultWidths ?? [6, 12, 12];
2293
3887
  }
2294
3888
  }
2295
3889
  /**
@@ -2299,15 +3893,34 @@ class AutocompleteStringChipsArrayDecoratorConfigInternal extends PropertyDecora
2299
3893
  constructor(data) {
2300
3894
  super(data);
2301
3895
  this.autocompleteValues = data.autocompleteValues;
2302
- this.deleteIcon = data.deleteIcon ? data.deleteIcon : 'fas fa-circle-minus';
2303
- this.displayStyle = data.displayStyle;
3896
+ this.deleteIcon = data.deleteIcon ?? 'fas fa-circle-minus';
2304
3897
  this.itemType = data.itemType;
3898
+ this.allowDuplicates = data.allowDuplicates ?? false;
3899
+ this.duplicatesErrorDialog = getDefaultDuplicateErrorDialogData(data);
2305
3900
  this.maxLength = data.maxLength;
2306
3901
  this.minLength = data.minLength;
2307
3902
  this.regex = data.regex;
2308
- this.defaultWidths = data.defaultWidths ? data.defaultWidths : [6, 12, 12];
3903
+ this.defaultWidths = data.defaultWidths ?? [6, 12, 12];
2309
3904
  }
2310
3905
  }
3906
+ /**
3907
+ * Gets the default dialog data for the error dialog to display when the user tries to add a duplicate value.
3908
+ *
3909
+ * @param data - The Array Decorator data.
3910
+ * @returns The dialog data with set default values.
3911
+ */
3912
+ function getDefaultDuplicateErrorDialogData(data) {
3913
+ return {
3914
+ type: data.duplicatesErrorDialog?.type ?? 'info-only',
3915
+ // eslint-disable-next-line max-len
3916
+ text: data.duplicatesErrorDialog?.text ?? ['Adding duplicate entries to the array is not allowed.'],
3917
+ title: data.duplicatesErrorDialog?.title ?? 'Error adding duplicate item',
3918
+ confirmButtonLabel: data.duplicatesErrorDialog?.confirmButtonLabel,
3919
+ cancelButtonLabel: data.duplicatesErrorDialog?.cancelButtonLabel,
3920
+ requireConfirmation: data.duplicatesErrorDialog?.requireConfirmation,
3921
+ confirmationText: data.duplicatesErrorDialog?.confirmationText
3922
+ };
3923
+ }
2311
3924
 
2312
3925
  /**
2313
3926
  * Decorator for setting and getting array property metadata.
@@ -2320,6 +3933,12 @@ function array(metadata) {
2320
3933
  switch (metadata.itemType) {
2321
3934
  case DecoratorTypes.OBJECT:
2322
3935
  return baseProperty(new EntityArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY);
3936
+ case DecoratorTypes.DATE:
3937
+ return baseProperty(new DateArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY_DATE);
3938
+ case DecoratorTypes.DATE_TIME:
3939
+ return baseProperty(new DateTimeArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY_DATE_TIME);
3940
+ case DecoratorTypes.DATE_RANGE:
3941
+ return baseProperty(new DateRangeArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY_DATE_RANGE);
2323
3942
  case DecoratorTypes.STRING:
2324
3943
  return baseProperty(new StringChipsArrayDecoratorConfigInternal(metadata), DecoratorTypes.ARRAY_STRING_CHIPS);
2325
3944
  case DecoratorTypes.STRING_AUTOCOMPLETE:
@@ -2360,7 +3979,7 @@ class CheckboxBooleanDecoratorConfigInternal extends PropertyDecoratorConfigInte
2360
3979
  constructor(data) {
2361
3980
  super(data);
2362
3981
  this.displayStyle = data.displayStyle;
2363
- this.required = data.required === undefined ? false : data.required;
3982
+ this.required = data.required ?? false;
2364
3983
  }
2365
3984
  }
2366
3985
  /**
@@ -2370,7 +3989,7 @@ class ToggleBooleanDecoratorConfigInternal extends PropertyDecoratorConfigIntern
2370
3989
  constructor(data) {
2371
3990
  super(data);
2372
3991
  this.displayStyle = data.displayStyle;
2373
- this.required = data.required === undefined ? false : data.required;
3992
+ this.required = data.required ?? false;
2374
3993
  }
2375
3994
  }
2376
3995
 
@@ -2398,6 +4017,76 @@ function boolean(metadata) {
2398
4017
  class BooleanDecoratorConfig extends PropertyDecoratorConfig {
2399
4018
  }
2400
4019
 
4020
+ /**
4021
+ * The internal DefaultDateDecoratorConfig. Sets default values.
4022
+ */
4023
+ class DefaultDateDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4024
+ constructor(data) {
4025
+ super(data);
4026
+ this.displayStyle = data.displayStyle;
4027
+ this.max = data.max;
4028
+ this.min = data.min;
4029
+ this.filter = data.filter;
4030
+ }
4031
+ }
4032
+ /**
4033
+ * The internal DateRangeDateDecoratorConfig. Sets default values.
4034
+ */
4035
+ class DateRangeDateDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4036
+ constructor(data) {
4037
+ super(data);
4038
+ this.displayStyle = data.displayStyle;
4039
+ this.minStart = data.minStart;
4040
+ this.maxStart = data.maxStart;
4041
+ this.minEnd = data.minEnd;
4042
+ this.maxEnd = data.maxEnd;
4043
+ this.filter = data.filter;
4044
+ this.placeholderStart = data.placeholderStart ?? 'Start';
4045
+ this.placeholderEnd = data.placeholderEnd ?? 'End';
4046
+ }
4047
+ }
4048
+ /**
4049
+ * The internal DateTimeDateDecoratorConfig. Sets default values.
4050
+ */
4051
+ class DateTimeDateDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4052
+ constructor(data) {
4053
+ super(data);
4054
+ this.displayStyle = data.displayStyle;
4055
+ this.times = data.times ?? DateUtilities.getDefaultTimes();
4056
+ this.timeDisplayName = data.timeDisplayName ?? 'Time';
4057
+ this.minDate = data.minDate;
4058
+ this.maxDate = data.maxDate;
4059
+ this.filterDate = data.filterDate;
4060
+ this.minTime = data.minTime;
4061
+ this.maxTime = data.maxTime;
4062
+ this.filterTime = data.filterTime;
4063
+ }
4064
+ }
4065
+
4066
+ /**
4067
+ * Decorator for setting and getting date property metadata.
4068
+ *
4069
+ * @param metadata - The metadata of the date property.
4070
+ * @returns The method that defines the metadata.
4071
+ */
4072
+ function date(metadata) {
4073
+ if (metadata.displayStyle === 'date') {
4074
+ return baseProperty(new DefaultDateDecoratorConfigInternal(metadata), DecoratorTypes.DATE);
4075
+ }
4076
+ else if (metadata.displayStyle === 'datetime') {
4077
+ return baseProperty(new DateTimeDateDecoratorConfigInternal(metadata), DecoratorTypes.DATE_TIME);
4078
+ }
4079
+ else {
4080
+ return baseProperty(new DateRangeDateDecoratorConfigInternal(metadata), DecoratorTypes.DATE_RANGE);
4081
+ }
4082
+ }
4083
+
4084
+ /**
4085
+ * Definition for the @date metadata.
4086
+ */
4087
+ class DateDecoratorConfig extends PropertyDecoratorConfig {
4088
+ }
4089
+
2401
4090
  /**
2402
4091
  * The internal DefaultNumberDecoratorConfig. Sets default values.
2403
4092
  */
@@ -2419,6 +4108,29 @@ class DropdownNumberDecoratorConfigInternal extends PropertyDecoratorConfigInter
2419
4108
  this.dropdownValues = data.dropdownValues;
2420
4109
  }
2421
4110
  }
4111
+ /**
4112
+ * The internal SliderNumberDecoratorConfig. Sets default values.
4113
+ */
4114
+ class SliderNumberDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4115
+ constructor(data) {
4116
+ super(data);
4117
+ this.displayStyle = data.displayStyle;
4118
+ this.max = data.max;
4119
+ this.min = data.min;
4120
+ this.step = data.step;
4121
+ this.formatThumbLabelValue = data.formatThumbLabelValue ?? defaultFormatThumbLabelValue;
4122
+ this.tickInterval = data.tickInterval;
4123
+ }
4124
+ }
4125
+ /**
4126
+ * The default function to format values for the number slider thumb label.
4127
+ *
4128
+ * @param value - The value of the slider.
4129
+ * @returns Just the value without any formatting done.
4130
+ */
4131
+ function defaultFormatThumbLabelValue(value) {
4132
+ return value;
4133
+ }
2422
4134
 
2423
4135
  /**
2424
4136
  * Decorator for setting and getting number property metadata.
@@ -2427,11 +4139,13 @@ class DropdownNumberDecoratorConfigInternal extends PropertyDecoratorConfigInter
2427
4139
  * @returns The method that defines the metadata.
2428
4140
  */
2429
4141
  function number(metadata) {
2430
- if (metadata.displayStyle === 'dropdown') {
2431
- return baseProperty(new DropdownNumberDecoratorConfigInternal(metadata), DecoratorTypes.NUMBER_DROPDOWN);
2432
- }
2433
- else {
2434
- return baseProperty(new DefaultNumberDecoratorConfigInternal(metadata), DecoratorTypes.NUMBER);
4142
+ switch (metadata.displayStyle) {
4143
+ case 'dropdown':
4144
+ return baseProperty(new DropdownNumberDecoratorConfigInternal(metadata), DecoratorTypes.NUMBER_DROPDOWN);
4145
+ case 'slider':
4146
+ return baseProperty(new SliderNumberDecoratorConfigInternal(metadata), DecoratorTypes.NUMBER_SLIDER);
4147
+ default:
4148
+ return baseProperty(new DefaultNumberDecoratorConfigInternal(metadata), DecoratorTypes.NUMBER);
2435
4149
  }
2436
4150
  }
2437
4151
 
@@ -2474,6 +4188,162 @@ class ObjectDecoratorConfig extends PropertyDecoratorConfig {
2474
4188
  class StringDecoratorConfig extends PropertyDecoratorConfig {
2475
4189
  }
2476
4190
 
4191
+ /**
4192
+ * The internal DefaultFileDecoratorConfig. Sets default values.
4193
+ */
4194
+ class DefaultFileDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4195
+ constructor(data) {
4196
+ super(data);
4197
+ this.type = data.type;
4198
+ this.preview = false;
4199
+ this.multiple = data.multiple;
4200
+ this.deleteIcon = data.deleteIcon ?? 'fas fa-circle-minus';
4201
+ this.allowedMimeTypes = data.allowedMimeTypes ?? ['*'];
4202
+ this.maxSize = data.maxSize ?? 10;
4203
+ this.maxSizeTotal = data.maxSizeTotal ?? 100;
4204
+ this.mimeTypeErrorDialog = data.mimeTypeErrorDialog ?? getDefaultMimeTypeErrorDialogData(data);
4205
+ this.maxSizeErrorDialog = data.maxSizeErrorDialog ?? getDefaultMaxSizeErrorDialogData(data);
4206
+ this.maxSizeTotalErrorDialog = data.maxSizeTotalErrorDialog ?? getDefaultMaxSizeTotalErrorDialogData(data);
4207
+ this.dragAndDrop = data.dragAndDrop ?? data.multiple;
4208
+ }
4209
+ }
4210
+ /**
4211
+ * The internal ImageFileDecoratorConfig. Sets default values.
4212
+ */
4213
+ class ImageFileDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4214
+ constructor(data) {
4215
+ super(data);
4216
+ this.type = data.type;
4217
+ this.allowedMimeTypes = data.allowedMimeTypes ?? ['image/*'];
4218
+ this.multiple = data.multiple;
4219
+ this.preview = data.preview ?? true;
4220
+ this.deleteIcon = data.deleteIcon ?? 'fas fa-circle-minus';
4221
+ this.maxSize = data.maxSize ?? 10;
4222
+ this.maxSizeTotal = data.maxSizeTotal ?? 100;
4223
+ this.mimeTypeErrorDialog = data.mimeTypeErrorDialog ?? getDefaultMimeTypeErrorDialogData(data);
4224
+ this.maxSizeErrorDialog = data.maxSizeErrorDialog ?? getDefaultMaxSizeErrorDialogData(data);
4225
+ this.maxSizeTotalErrorDialog = data.maxSizeTotalErrorDialog ?? getDefaultMaxSizeTotalErrorDialogData(data);
4226
+ this.previewPlaceholderUrl = data.previewPlaceholderUrl;
4227
+ this.dragAndDrop = data.dragAndDrop ?? data.multiple;
4228
+ }
4229
+ }
4230
+ /**
4231
+ * Gets the default dialog data for the error dialog to display
4232
+ * when the user tries to add a file with a wrong type.
4233
+ *
4234
+ * @param data - The File Decorator data.
4235
+ * @returns The dialog data with set default values.
4236
+ */
4237
+ function getDefaultMimeTypeErrorDialogData(data) {
4238
+ return {
4239
+ type: data.mimeTypeErrorDialog?.type ?? 'info-only',
4240
+ // eslint-disable-next-line max-len
4241
+ text: data.mimeTypeErrorDialog?.text ?? (data.multiple ? ['One of the uploaded files has the wrong type.'] : ['The uploaded file has the wrong type.']),
4242
+ title: data.mimeTypeErrorDialog?.title ?? (data.multiple ? 'Error adding files' : 'Error adding file'),
4243
+ confirmButtonLabel: data.mimeTypeErrorDialog?.confirmButtonLabel,
4244
+ cancelButtonLabel: data.mimeTypeErrorDialog?.cancelButtonLabel,
4245
+ requireConfirmation: data.mimeTypeErrorDialog?.requireConfirmation,
4246
+ confirmationText: data.mimeTypeErrorDialog?.confirmationText
4247
+ };
4248
+ }
4249
+ /**
4250
+ * Gets the default dialog data for the error dialog to display
4251
+ * when the user tries to add a single file that is bigger than the allowed maxSize.
4252
+ *
4253
+ * @param data - The File Decorator data.
4254
+ * @returns The dialog data with set default values.
4255
+ */
4256
+ function getDefaultMaxSizeErrorDialogData(data) {
4257
+ return {
4258
+ type: data.mimeTypeErrorDialog?.type ?? 'info-only',
4259
+ // eslint-disable-next-line max-len
4260
+ text: data.mimeTypeErrorDialog?.text ?? (data.multiple ? ['One of the uploaded files is too big'] : ['The uploaded files is too big']),
4261
+ title: data.mimeTypeErrorDialog?.title ?? (data.multiple ? 'Error adding files' : 'Error adding file'),
4262
+ confirmButtonLabel: data.mimeTypeErrorDialog?.confirmButtonLabel,
4263
+ cancelButtonLabel: data.mimeTypeErrorDialog?.cancelButtonLabel,
4264
+ requireConfirmation: data.mimeTypeErrorDialog?.requireConfirmation,
4265
+ confirmationText: data.mimeTypeErrorDialog?.confirmationText
4266
+ };
4267
+ }
4268
+ /**
4269
+ * Gets the default dialog data for the error dialog to display
4270
+ * when the user tries to add a single file that is bigger than the allowed maxSize.
4271
+ *
4272
+ * @param data - The File Decorator data.
4273
+ * @returns The dialog data with set default values.
4274
+ */
4275
+ function getDefaultMaxSizeTotalErrorDialogData(data) {
4276
+ return {
4277
+ type: data.mimeTypeErrorDialog?.type ?? 'info-only',
4278
+ // eslint-disable-next-line max-len
4279
+ text: data.mimeTypeErrorDialog?.text ?? ['The size of all files combined is too big'],
4280
+ title: data.mimeTypeErrorDialog?.title ?? (data.multiple ? 'Error adding files' : 'Error adding file'),
4281
+ confirmButtonLabel: data.mimeTypeErrorDialog?.confirmButtonLabel,
4282
+ cancelButtonLabel: data.mimeTypeErrorDialog?.cancelButtonLabel,
4283
+ requireConfirmation: data.mimeTypeErrorDialog?.requireConfirmation,
4284
+ confirmationText: data.mimeTypeErrorDialog?.confirmationText
4285
+ };
4286
+ }
4287
+
4288
+ /**
4289
+ * Decorator for setting and getting file property metadata.
4290
+ *
4291
+ * @param metadata - The metadata of the file property.
4292
+ * @returns The method that defines the metadata.
4293
+ * @throws When an unknown metadata type was provided.
4294
+ */
4295
+ function file(metadata) {
4296
+ switch (metadata.type) {
4297
+ case 'other':
4298
+ return baseProperty(new DefaultFileDecoratorConfigInternal(metadata), DecoratorTypes.FILE_DEFAULT);
4299
+ case 'image':
4300
+ return baseProperty(new ImageFileDecoratorConfigInternal(metadata), DecoratorTypes.FILE_IMAGE);
4301
+ default:
4302
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
4303
+ throw new Error(`Unknown metadata type ${metadata.type}`);
4304
+ }
4305
+ }
4306
+
4307
+ /**
4308
+ * Definition for the @file metadata.
4309
+ */
4310
+ class FileDecoratorConfig extends PropertyDecoratorConfig {
4311
+ }
4312
+
4313
+ /**
4314
+ * The default function to use for checking if the value is dirty.
4315
+ *
4316
+ * @param value - The current value.
4317
+ * @param valuePriorChanges - The value before any changes.
4318
+ * @returns Whether or not the provided value has been changed.
4319
+ */
4320
+ function defaultIsEqual(value, valuePriorChanges) {
4321
+ return LodashUtilities.isEqual(value, valuePriorChanges);
4322
+ }
4323
+ /**
4324
+ * The internal config for the @custom decorator.
4325
+ * Sets default values.
4326
+ */
4327
+ class CustomDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
4328
+ constructor(data) {
4329
+ super(data);
4330
+ this.component = data.component;
4331
+ this.isValid = data.isValid ?? (() => true);
4332
+ this.isEqual = data.isEqual ?? defaultIsEqual;
4333
+ this.customMetadata = data.customMetadata;
4334
+ }
4335
+ }
4336
+
4337
+ /**
4338
+ * Decorator for setting and getting custom property metadata.
4339
+ *
4340
+ * @param metadata - The metadata of the custom property.
4341
+ * @returns The method that defines the metadata.
4342
+ */
4343
+ function custom(metadata) {
4344
+ return baseProperty(new CustomDecoratorConfigInternal(metadata), DecoratorTypes.CUSTOM);
4345
+ }
4346
+
2477
4347
  /**
2478
4348
  * Public API Surface of ngx-material-entity.
2479
4349
  */
@@ -2482,5 +4352,5 @@ class StringDecoratorConfig extends PropertyDecoratorConfig {
2482
4352
  * Generated bundle index. Do not edit.
2483
4353
  */
2484
4354
 
2485
- export { DateUtilities, DecoratorTypes, Entity, EntityService, EntityUtilities, NgxMatEntityConfirmDialogComponent, NgxMatEntityConfirmDialogModule, NgxMatEntityCreateDialogComponent, NgxMatEntityCreateDialogModule, NgxMatEntityEditDialogComponent, NgxMatEntityEditDialogModule, NgxMatEntityInputComponent, NgxMatEntityInputModule, NgxMatEntityTableComponent, NgxMatEntityTableModule, array, boolean, getValidationErrorMessage, number, object, string };
4355
+ 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 };
2486
4356
  //# sourceMappingURL=ngx-material-entity.mjs.map