ngx-material-entity 16.0.1 → 16.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/edit-page/edit-page.component.d.ts +13 -2
- package/components/input/boolean/boolean-checkbox-input/boolean-checkbox-input.component.d.ts +1 -0
- package/components/input/boolean/boolean-toggle-input/boolean-toggle-input.component.d.ts +2 -1
- package/components/input/input.component.d.ts +28 -3
- package/components/input/input.module.d.ts +5 -2
- package/components/input/number/number-slider-input/number-slider-input.component.d.ts +2 -1
- package/components/table/create-dialog/create-entity-dialog.component.d.ts +3 -0
- package/components/table/edit-dialog/edit-entity-dialog.component.d.ts +4 -0
- package/components/tooltip/tooltip.component.d.ts +9 -0
- package/decorators/array/array-decorator-internal.data.d.ts +6 -6
- package/decorators/array/array-decorator.data.d.ts +7 -7
- package/decorators/base/property-decorator-internal.data.d.ts +11 -2
- package/decorators/base/property-decorator.data.d.ts +9 -1
- package/decorators/boolean/boolean-decorator-internal.data.d.ts +3 -3
- package/decorators/boolean/boolean-decorator.data.d.ts +1 -1
- package/decorators/custom/custom-decorator-internal.data.d.ts +2 -2
- package/decorators/custom/custom-decorator.data.d.ts +4 -4
- package/decorators/date/date-decorator-internal.data.d.ts +4 -4
- package/decorators/date/date-decorator.data.d.ts +5 -5
- package/decorators/file/file-decorator-internal.data.d.ts +3 -3
- package/decorators/file/file-decorator.data.d.ts +1 -1
- package/decorators/has-many/has-many-decorator-internal.data.d.ts +1 -1
- package/decorators/has-many/has-many-decorator.data.d.ts +1 -1
- package/decorators/number/number-decorator-internal.data.d.ts +3 -3
- package/decorators/number/number-decorator.data.d.ts +1 -1
- package/decorators/object/object-decorator-internal.data.d.ts +1 -1
- package/decorators/object/object-decorator.data.d.ts +1 -1
- package/decorators/references-many/references-many-decorator-internal.data.d.ts +1 -1
- package/decorators/references-many/references-many-decorator.data.d.ts +1 -1
- package/decorators/references-one/references-one-decorator-internal.data.d.ts +1 -1
- package/decorators/references-one/references-one-decorator.data.d.ts +1 -1
- package/decorators/string/string-decorator-internal.data.d.ts +5 -6
- package/decorators/string/string-decorator.data.d.ts +1 -7
- package/directives/number.directive.d.ts +17 -0
- package/directives/password-match.directive.d.ts +14 -0
- package/directives/tooltip.directive.d.ts +33 -0
- package/esm2022/components/edit-page/edit-page.component.mjs +57 -13
- package/esm2022/components/input/array/array-date-range-input/array-date-range-input.component.mjs +1 -1
- package/esm2022/components/input/array/array-string-chips-input/array-string-chips-input.component.mjs +2 -2
- package/esm2022/components/input/base-input.component.mjs +2 -1
- package/esm2022/components/input/boolean/boolean-checkbox-input/boolean-checkbox-input.component.mjs +6 -3
- package/esm2022/components/input/boolean/boolean-toggle-input/boolean-toggle-input.component.mjs +6 -3
- package/esm2022/components/input/date/date-range-input/date-range-input.component.mjs +3 -1
- package/esm2022/components/input/file/file-image-input/file-image-input.component.mjs +3 -3
- package/esm2022/components/input/file/file-input/file-input.component.mjs +1 -1
- package/esm2022/components/input/input.component.mjs +94 -35
- package/esm2022/components/input/input.module.mjs +15 -5
- package/esm2022/components/input/number/number-input/number-input.component.mjs +4 -3
- package/esm2022/components/input/number/number-slider-input/number-slider-input.component.mjs +6 -3
- package/esm2022/components/input/string/string-password-input/string-password-input.component.mjs +4 -3
- package/esm2022/components/table/create-dialog/create-entity-dialog.component.mjs +18 -6
- package/esm2022/components/table/edit-dialog/edit-entity-dialog.component.mjs +26 -13
- package/esm2022/components/table/table.component.mjs +14 -9
- package/esm2022/components/tooltip/tooltip.component.mjs +20 -0
- package/esm2022/decorators/array/array-decorator-internal.data.mjs +1 -1
- package/esm2022/decorators/array/array-decorator.data.mjs +1 -1
- package/esm2022/decorators/base/property-decorator-internal.data.mjs +22 -1
- package/esm2022/decorators/base/property-decorator.data.mjs +10 -1
- package/esm2022/decorators/boolean/boolean-decorator-internal.data.mjs +1 -1
- package/esm2022/decorators/boolean/boolean-decorator.data.mjs +1 -1
- package/esm2022/decorators/custom/custom-decorator-internal.data.mjs +2 -2
- package/esm2022/decorators/custom/custom-decorator.data.mjs +1 -1
- package/esm2022/decorators/date/date-decorator-internal.data.mjs +2 -1
- package/esm2022/decorators/date/date-decorator.data.mjs +1 -1
- package/esm2022/decorators/file/file-decorator-internal.data.mjs +1 -1
- package/esm2022/decorators/file/file-decorator.data.mjs +1 -1
- package/esm2022/decorators/has-many/has-many-decorator-internal.data.mjs +1 -1
- package/esm2022/decorators/has-many/has-many-decorator.data.mjs +1 -1
- package/esm2022/decorators/number/number-decorator-internal.data.mjs +1 -1
- package/esm2022/decorators/number/number-decorator.data.mjs +1 -1
- package/esm2022/decorators/object/object-decorator-internal.data.mjs +1 -1
- package/esm2022/decorators/object/object-decorator.data.mjs +1 -1
- package/esm2022/decorators/references-many/references-many-decorator-internal.data.mjs +1 -1
- package/esm2022/decorators/references-many/references-many-decorator.data.mjs +1 -1
- package/esm2022/decorators/references-one/references-one-decorator-internal.data.mjs +1 -1
- package/esm2022/decorators/references-one/references-one-decorator.data.mjs +1 -1
- package/esm2022/decorators/string/string-decorator-internal.data.mjs +1 -4
- package/esm2022/decorators/string/string-decorator.data.mjs +1 -1
- package/esm2022/directives/drag-drop.directive.mjs +62 -0
- package/esm2022/directives/number.directive.mjs +38 -0
- package/esm2022/directives/password-match.directive.mjs +30 -0
- package/esm2022/directives/tooltip.directive.mjs +112 -0
- package/esm2022/functions/get-validation-error-message.function.mjs +49 -0
- package/esm2022/functions/get-validation-errors-tooltip-content.function.ts.mjs +25 -0
- package/esm2022/public-api.mjs +6 -2
- package/esm2022/utilities/entity.utilities.mjs +83 -386
- package/esm2022/utilities/validation.utilities.mjs +455 -0
- package/fesm2022/ngx-material-entity.mjs +1713 -1183
- package/fesm2022/ngx-material-entity.mjs.map +1 -1
- package/functions/get-validation-errors-tooltip-content.function.ts.d.ts +10 -0
- package/package.json +1 -1
- package/public-api.d.ts +4 -1
- package/utilities/entity.utilities.d.ts +33 -30
- package/utilities/validation.utilities.d.ts +56 -0
- package/esm2022/components/get-validation-error-message.function.mjs +0 -42
- package/esm2022/components/input/file/file-input/dragDrop.directive.mjs +0 -62
- /package/{components/input/file/file-input/dragDrop.directive.d.ts → directives/drag-drop.directive.d.ts} +0 -0
- /package/{components → functions}/get-validation-error-message.function.d.ts +0 -0
|
@@ -4,11 +4,11 @@ import 'reflect-metadata';
|
|
|
4
4
|
import { firstValueFrom, Observable, BehaviorSubject, first, map, Subject, takeUntil } from 'rxjs';
|
|
5
5
|
import JSZip from 'jszip';
|
|
6
6
|
import * as i0 from '@angular/core';
|
|
7
|
-
import { Component, Inject,
|
|
7
|
+
import { Component, Inject, InjectionToken, inject, EventEmitter, Directive, Output, HostListener, Input, ViewChild, NgModule, runInInjectionContext } from '@angular/core';
|
|
8
8
|
import * as i1 from '@angular/material/dialog';
|
|
9
9
|
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
|
10
10
|
import * as i3 from '@angular/forms';
|
|
11
|
-
import { FormsModule } from '@angular/forms';
|
|
11
|
+
import { FormsModule, NG_VALIDATORS } from '@angular/forms';
|
|
12
12
|
import * as i5 from '@angular/material/button';
|
|
13
13
|
import { MatButtonModule } from '@angular/material/button';
|
|
14
14
|
import * as i4 from '@angular/material/checkbox';
|
|
@@ -16,7 +16,9 @@ import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
|
16
16
|
import * as i1$1 from '@angular/common';
|
|
17
17
|
import { NgIf, NgFor, CommonModule } from '@angular/common';
|
|
18
18
|
import * as i2 from '@angular/common/http';
|
|
19
|
-
import * as
|
|
19
|
+
import * as i10 from '@angular/material/badge';
|
|
20
|
+
import { MatBadgeModule } from '@angular/material/badge';
|
|
21
|
+
import * as i14 from '@angular/material/menu';
|
|
20
22
|
import { MatMenuModule } from '@angular/material/menu';
|
|
21
23
|
import * as i15 from '@angular/material/progress-spinner';
|
|
22
24
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
@@ -42,13 +44,13 @@ import * as i4$3 from '@angular/material/slide-toggle';
|
|
|
42
44
|
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
|
43
45
|
import * as i4$4 from '@angular/material/slider';
|
|
44
46
|
import { MatSliderModule } from '@angular/material/slider';
|
|
47
|
+
import * as i18 from '@angular/material/sort';
|
|
48
|
+
import { MatSort, MatSortModule } from '@angular/material/sort';
|
|
45
49
|
import * as i6 from '@angular/material/table';
|
|
46
50
|
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
|
47
51
|
import { SelectionModel } from '@angular/cdk/collections';
|
|
48
52
|
import * as uuid from 'uuid';
|
|
49
53
|
import * as i5$1 from '@angular/material/core';
|
|
50
|
-
import { UUIDUtilities as UUIDUtilities$1 } from 'projects/ngx-material-entity/src/encapsulation/uuid.utilities';
|
|
51
|
-
import { MatSort } from '@angular/material/sort';
|
|
52
54
|
import * as i3$1 from '@angular/cdk/text-field';
|
|
53
55
|
import * as js2xml from 'js2xmlparser';
|
|
54
56
|
|
|
@@ -661,7 +663,7 @@ class EntityUtilities {
|
|
|
661
663
|
static getOmitForUpdate(entity) {
|
|
662
664
|
const res = [];
|
|
663
665
|
for (const key of ReflectUtilities.ownKeys(entity)) {
|
|
664
|
-
const metadata =
|
|
666
|
+
const metadata = this.getPropertyMetadata(entity, key);
|
|
665
667
|
if (metadata.omitForUpdate) {
|
|
666
668
|
res.push(key);
|
|
667
669
|
}
|
|
@@ -677,7 +679,7 @@ class EntityUtilities {
|
|
|
677
679
|
static getOmitForCreate(entity) {
|
|
678
680
|
const res = [];
|
|
679
681
|
for (const key of ReflectUtilities.ownKeys(entity)) {
|
|
680
|
-
const metadata =
|
|
682
|
+
const metadata = this.getPropertyMetadata(entity, key);
|
|
681
683
|
if (metadata.omitForCreate) {
|
|
682
684
|
res.push(key);
|
|
683
685
|
}
|
|
@@ -691,7 +693,7 @@ class EntityUtilities {
|
|
|
691
693
|
* @returns The reduced entity object.
|
|
692
694
|
*/
|
|
693
695
|
static getWithoutOmitCreateValues(entity) {
|
|
694
|
-
return LodashUtilities.omit(entity,
|
|
696
|
+
return LodashUtilities.omit(entity, this.getOmitForCreate(entity));
|
|
695
697
|
}
|
|
696
698
|
/**
|
|
697
699
|
* Returns the given entity without the values that should be omitted for updating.
|
|
@@ -704,18 +706,18 @@ class EntityUtilities {
|
|
|
704
706
|
*/
|
|
705
707
|
static async getWithoutOmitUpdateValues(entity, entityPriorChanges, http) {
|
|
706
708
|
const res = {};
|
|
707
|
-
for (const key of
|
|
708
|
-
const metadata =
|
|
709
|
-
const type =
|
|
710
|
-
if (!(await
|
|
709
|
+
for (const key of this.keysOf(entity, false, true)) {
|
|
710
|
+
const metadata = this.getPropertyMetadata(entity, key);
|
|
711
|
+
const type = this.getPropertyType(entity, key);
|
|
712
|
+
if (!(await this.isEqual(entity[key], entityPriorChanges[key], metadata, type, http))) {
|
|
711
713
|
switch (type) {
|
|
712
714
|
case DecoratorTypes.OBJECT:
|
|
713
715
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
714
|
-
res[key] = LodashUtilities.omit(entity[key],
|
|
716
|
+
res[key] = LodashUtilities.omit(entity[key], this.getOmitForCreate(entity[key]));
|
|
715
717
|
break;
|
|
716
718
|
case DecoratorTypes.ARRAY:
|
|
717
719
|
res[key] = entity[key]
|
|
718
|
-
.map(value => LodashUtilities.omit(value,
|
|
720
|
+
.map(value => LodashUtilities.omit(value, this.getOmitForCreate(value)));
|
|
719
721
|
break;
|
|
720
722
|
default:
|
|
721
723
|
res[key] = entity[key];
|
|
@@ -725,6 +727,20 @@ class EntityUtilities {
|
|
|
725
727
|
}
|
|
726
728
|
return res;
|
|
727
729
|
}
|
|
730
|
+
/**
|
|
731
|
+
* Sets all default values on the given entity.
|
|
732
|
+
*
|
|
733
|
+
* @param entity - The entity to set the default values on.
|
|
734
|
+
*/
|
|
735
|
+
static setDefaultValues(entity) {
|
|
736
|
+
for (const key in entity) {
|
|
737
|
+
const metadata = this.getPropertyMetadata(entity, key);
|
|
738
|
+
if (metadata.default) {
|
|
739
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
|
|
740
|
+
entity[key] = metadata.default();
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
728
744
|
/**
|
|
729
745
|
* Gets all properties on the given entity which are files.
|
|
730
746
|
*
|
|
@@ -735,9 +751,9 @@ class EntityUtilities {
|
|
|
735
751
|
static getFileProperties(entity, omit) {
|
|
736
752
|
const res = [];
|
|
737
753
|
for (const key of ReflectUtilities.ownKeys(entity)) {
|
|
738
|
-
const type =
|
|
754
|
+
const type = this.getPropertyType(entity, key);
|
|
739
755
|
if (type === DecoratorTypes.FILE_DEFAULT || type === DecoratorTypes.FILE_IMAGE) {
|
|
740
|
-
const metadata =
|
|
756
|
+
const metadata = this.getPropertyMetadata(entity, key);
|
|
741
757
|
if (!(metadata.omitForCreate && omit === 'create') && !(metadata.omitForUpdate && omit === 'update')) {
|
|
742
758
|
res.push(key);
|
|
743
759
|
}
|
|
@@ -794,12 +810,12 @@ class EntityUtilities {
|
|
|
794
810
|
*/
|
|
795
811
|
static new(target, entity) {
|
|
796
812
|
for (const key in target) {
|
|
797
|
-
const type =
|
|
813
|
+
const type = this.getPropertyType(target, key);
|
|
798
814
|
let value = entity ? ReflectUtilities.get(entity, key) : undefined;
|
|
799
815
|
switch (type) {
|
|
800
816
|
case DecoratorTypes.OBJECT:
|
|
801
817
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
802
|
-
const objectMetadata =
|
|
818
|
+
const objectMetadata = this.getPropertyMetadata(target, key, DecoratorTypes.OBJECT);
|
|
803
819
|
value = new objectMetadata.EntityClass(value);
|
|
804
820
|
break;
|
|
805
821
|
case DecoratorTypes.ARRAY:
|
|
@@ -807,7 +823,7 @@ class EntityUtilities {
|
|
|
807
823
|
const resArray = [];
|
|
808
824
|
if (inputArray) {
|
|
809
825
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
810
|
-
const arrayMetadata =
|
|
826
|
+
const arrayMetadata = this.getPropertyMetadata(target, key, DecoratorTypes.ARRAY);
|
|
811
827
|
for (const item of inputArray) {
|
|
812
828
|
const itemWithMetadata = new arrayMetadata.EntityClass(item);
|
|
813
829
|
resArray.push(itemWithMetadata);
|
|
@@ -822,690 +838,373 @@ class EntityUtilities {
|
|
|
822
838
|
}
|
|
823
839
|
}
|
|
824
840
|
// eslint-disable-next-line @typescript-eslint/member-ordering, jsdoc/require-jsdoc, @typescript-eslint/typedef
|
|
825
|
-
static construct =
|
|
841
|
+
static construct = this.new;
|
|
826
842
|
// eslint-disable-next-line @typescript-eslint/member-ordering, jsdoc/require-jsdoc, @typescript-eslint/typedef
|
|
827
|
-
static build =
|
|
843
|
+
static build = this.new;
|
|
828
844
|
/**
|
|
829
|
-
* Checks if
|
|
830
|
-
* Also checks all the validators given by the metadata ("required", "maxLength" etc.).
|
|
845
|
+
* Checks if an entity is "dirty" (if its values have changed).
|
|
831
846
|
*
|
|
832
|
-
* @param entity - The entity
|
|
833
|
-
* @param
|
|
834
|
-
* @
|
|
847
|
+
* @param entity - The entity after all changes.
|
|
848
|
+
* @param entityPriorChanges - The entity before the changes.
|
|
849
|
+
* @param http - The angular HttpClient. Used to fetch files.
|
|
850
|
+
* @returns Whether or not the entity is dirty.
|
|
835
851
|
*/
|
|
836
|
-
static
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
return false;
|
|
840
|
-
}
|
|
852
|
+
static async isDirty(entity, entityPriorChanges, http) {
|
|
853
|
+
if (!entityPriorChanges) {
|
|
854
|
+
return false;
|
|
841
855
|
}
|
|
842
|
-
|
|
856
|
+
const differences = await this.getDifferencesBetweenEntities(entity, entityPriorChanges, http);
|
|
857
|
+
return differences.length ? true : false;
|
|
843
858
|
}
|
|
844
859
|
/**
|
|
845
|
-
*
|
|
860
|
+
* Gets the differences between the two given entities.
|
|
846
861
|
*
|
|
847
|
-
* @param entity - The entity
|
|
848
|
-
* @param
|
|
849
|
-
* @param
|
|
850
|
-
* @returns
|
|
851
|
-
* @throws Throws when it extracts an unknown metadata type.
|
|
862
|
+
* @param entity - The entity as is.
|
|
863
|
+
* @param entityPriorChanges - The entity before any changes have been made.
|
|
864
|
+
* @param http - The angular http client, is needed to check if files are equal.
|
|
865
|
+
* @returns The differences as an array consisting of key, before and after.
|
|
852
866
|
*/
|
|
853
|
-
static
|
|
854
|
-
const
|
|
855
|
-
const
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
return false;
|
|
867
|
+
static async getDifferencesBetweenEntities(entity, entityPriorChanges, http) {
|
|
868
|
+
const res = [];
|
|
869
|
+
for (const key of ReflectUtilities.ownKeys(entity)) {
|
|
870
|
+
const metadata = this.getPropertyMetadata(entity, key);
|
|
871
|
+
const type = this.getPropertyType(entity, key);
|
|
872
|
+
if (!(await this.isEqual(entity[key], entityPriorChanges[key], metadata, type, http))) {
|
|
873
|
+
res.push({
|
|
874
|
+
key: key,
|
|
875
|
+
before: entityPriorChanges[key],
|
|
876
|
+
after: entity[key]
|
|
877
|
+
});
|
|
865
878
|
}
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
return true;
|
|
879
|
+
else {
|
|
880
|
+
// This is needed to set blob file data so that it is only requested once.
|
|
881
|
+
entityPriorChanges[key] = LodashUtilities.cloneDeep(entity[key]);
|
|
870
882
|
}
|
|
871
883
|
}
|
|
884
|
+
return res;
|
|
885
|
+
}
|
|
886
|
+
// TODO Remove
|
|
887
|
+
/**
|
|
888
|
+
* Compares two Entities and returns their difference in an object.
|
|
889
|
+
*
|
|
890
|
+
* @param entity - The first entity to compare.
|
|
891
|
+
* @param entityPriorChanges - The second entity to compare.
|
|
892
|
+
* @returns The difference between the two Entities in form of a Partial.
|
|
893
|
+
*/
|
|
894
|
+
// static async difference<EntityType extends BaseEntityType<EntityType>>(
|
|
895
|
+
// entity: EntityType,
|
|
896
|
+
// entityPriorChanges: EntityType
|
|
897
|
+
// ): Promise<Partial<EntityType>> {
|
|
898
|
+
// const res: Partial<EntityType> = {};
|
|
899
|
+
// for (const key in entity) {
|
|
900
|
+
// const metadata: PropertyDecoratorConfigInternal = this.getPropertyMetadata(entity, key);
|
|
901
|
+
// const type: DecoratorTypes = this.getPropertyType(entity, key);
|
|
902
|
+
// if (!(await this.isEqual(entity[key], entityPriorChanges[key], metadata, type))) {
|
|
903
|
+
// res[key] = entity[key];
|
|
904
|
+
// }
|
|
905
|
+
// }
|
|
906
|
+
// return res;
|
|
907
|
+
// }
|
|
908
|
+
/**
|
|
909
|
+
* Checks if two given values are equal.
|
|
910
|
+
* It uses the isEqual method from LodashUtilities and extends it with functionality regarding Dates.
|
|
911
|
+
*
|
|
912
|
+
* @param value - The updated value.
|
|
913
|
+
* @param valuePriorChanges - The value before any changes.
|
|
914
|
+
* @param metadata - The metadata of the property.
|
|
915
|
+
* @param type - The type of the property.
|
|
916
|
+
* @param http - The angular HttpClient. Used to fetch files.
|
|
917
|
+
* @returns Whether or not the given values are equal.
|
|
918
|
+
*/
|
|
919
|
+
static async isEqual(value, valuePriorChanges, metadata, type, http) {
|
|
872
920
|
switch (type) {
|
|
873
|
-
case DecoratorTypes.
|
|
874
|
-
|
|
875
|
-
case DecoratorTypes.
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
if (!EntityUtilities.isBooleanValid(entity, entityBoolean, booleanMetadata)) {
|
|
880
|
-
return false;
|
|
881
|
-
}
|
|
882
|
-
break;
|
|
883
|
-
case DecoratorTypes.STRING_DROPDOWN:
|
|
884
|
-
break;
|
|
885
|
-
case DecoratorTypes.STRING:
|
|
886
|
-
case DecoratorTypes.STRING_AUTOCOMPLETE:
|
|
887
|
-
const entityString = entity[key];
|
|
888
|
-
const stringMetadata = metadata;
|
|
889
|
-
if (!EntityUtilities.isStringValid(entityString, stringMetadata)) {
|
|
890
|
-
return false;
|
|
891
|
-
}
|
|
892
|
-
break;
|
|
893
|
-
case DecoratorTypes.STRING_TEXTBOX:
|
|
894
|
-
const entityTextbox = entity[key];
|
|
895
|
-
const textboxMetadata = metadata;
|
|
896
|
-
if (!EntityUtilities.isTextboxValid(entityTextbox, textboxMetadata)) {
|
|
897
|
-
return false;
|
|
898
|
-
}
|
|
899
|
-
break;
|
|
900
|
-
case DecoratorTypes.STRING_PASSWORD:
|
|
901
|
-
const entityPassword = entity[key];
|
|
902
|
-
const passwordMetadata = metadata;
|
|
903
|
-
const confirmPassword = ReflectUtilities.getMetadata(this.CONFIRM_PASSWORD_KEY, entity, key);
|
|
904
|
-
if (!EntityUtilities.isPasswordValid(entityPassword, passwordMetadata, confirmPassword)) {
|
|
905
|
-
return false;
|
|
906
|
-
}
|
|
907
|
-
break;
|
|
908
|
-
case DecoratorTypes.NUMBER_DROPDOWN:
|
|
909
|
-
return true;
|
|
910
|
-
case DecoratorTypes.NUMBER:
|
|
911
|
-
case DecoratorTypes.NUMBER_SLIDER:
|
|
912
|
-
const entityNumber = entity[key];
|
|
913
|
-
const numberMetadata = metadata;
|
|
914
|
-
if (!EntityUtilities.isNumberValid(entityNumber, numberMetadata)) {
|
|
915
|
-
return false;
|
|
916
|
-
}
|
|
917
|
-
break;
|
|
918
|
-
case DecoratorTypes.OBJECT:
|
|
919
|
-
const entityObject = entity[key];
|
|
920
|
-
for (const parameterKey in entityObject) {
|
|
921
|
-
const value = entityObject[parameterKey];
|
|
922
|
-
if (!metadata.omit.includes(parameterKey)
|
|
923
|
-
&& !(!metadata.required(entity) && (value == null || value == ''))) {
|
|
924
|
-
if (!EntityUtilities.isPropertyValid(entityObject, parameterKey, omit)) {
|
|
925
|
-
return false;
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
break;
|
|
930
|
-
case DecoratorTypes.ARRAY_STRING_CHIPS:
|
|
931
|
-
case DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS:
|
|
921
|
+
case DecoratorTypes.DATE_RANGE:
|
|
922
|
+
return this.isEqualDateRange(value, valuePriorChanges, metadata.filter);
|
|
923
|
+
case DecoratorTypes.DATE:
|
|
924
|
+
return this.isEqualDate(value, valuePriorChanges);
|
|
925
|
+
case DecoratorTypes.DATE_TIME:
|
|
926
|
+
return this.isEqualDateTime(value, valuePriorChanges);
|
|
932
927
|
case DecoratorTypes.ARRAY_DATE:
|
|
933
928
|
case DecoratorTypes.ARRAY_DATE_TIME:
|
|
929
|
+
return this.isEqualArrayDate(value, valuePriorChanges);
|
|
934
930
|
case DecoratorTypes.ARRAY_DATE_RANGE:
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
if (arrayMetadata.required(entity) && !entityArray.length) {
|
|
940
|
-
return false;
|
|
941
|
-
}
|
|
942
|
-
break;
|
|
943
|
-
case DecoratorTypes.DATE:
|
|
944
|
-
const entityDate = new Date(entity[key]);
|
|
945
|
-
const dateMetadata = metadata;
|
|
946
|
-
if (!EntityUtilities.isDateValid(entityDate, dateMetadata)) {
|
|
947
|
-
return false;
|
|
948
|
-
}
|
|
949
|
-
break;
|
|
950
|
-
case DecoratorTypes.DATE_RANGE:
|
|
951
|
-
const entityDateRange = LodashUtilities.cloneDeep(entity[key]);
|
|
952
|
-
const dateRangeMetadata = metadata;
|
|
953
|
-
if (!EntityUtilities.isDateRangeValid(entity, entityDateRange, dateRangeMetadata)) {
|
|
954
|
-
return false;
|
|
955
|
-
}
|
|
956
|
-
break;
|
|
957
|
-
case DecoratorTypes.DATE_TIME:
|
|
958
|
-
const entityDateTime = new Date(entity[key]);
|
|
959
|
-
const dateTimeMetadata = metadata;
|
|
960
|
-
const hasTime = ReflectUtilities.hasMetadata(this.TIME_KEY, entity, key);
|
|
961
|
-
if (!EntityUtilities.isDateTimeValid(entityDateTime, dateTimeMetadata, hasTime)) {
|
|
962
|
-
return false;
|
|
963
|
-
}
|
|
964
|
-
break;
|
|
965
|
-
case DecoratorTypes.FILE_DEFAULT:
|
|
931
|
+
return this.isEqualArrayDateRange(value, valuePriorChanges, metadata.filter);
|
|
932
|
+
case DecoratorTypes.ARRAY_STRING_CHIPS:
|
|
933
|
+
case DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS:
|
|
934
|
+
return this.isEqualArrayString(value, valuePriorChanges);
|
|
966
935
|
case DecoratorTypes.FILE_IMAGE:
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
if (!EntityUtilities.isFileDataValid(entityFile, entityFileMetadata)) {
|
|
970
|
-
return false;
|
|
971
|
-
}
|
|
972
|
-
break;
|
|
973
|
-
case DecoratorTypes.REFERENCES_MANY:
|
|
974
|
-
case DecoratorTypes.REFERENCES_ONE:
|
|
975
|
-
case DecoratorTypes.HAS_MANY:
|
|
976
|
-
break;
|
|
936
|
+
case DecoratorTypes.FILE_DEFAULT:
|
|
937
|
+
return this.isEqualFile(value, valuePriorChanges, metadata.multiple, http);
|
|
977
938
|
case DecoratorTypes.CUSTOM:
|
|
978
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
979
|
-
|
|
980
|
-
if (!customMetadata.isValid(entity[key], omit)) {
|
|
981
|
-
return false;
|
|
982
|
-
}
|
|
983
|
-
break;
|
|
939
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
940
|
+
return this.isEqualCustom(value, valuePriorChanges, metadata);
|
|
984
941
|
default:
|
|
985
|
-
|
|
942
|
+
return LodashUtilities.isEqual(value, valuePriorChanges);
|
|
986
943
|
}
|
|
987
|
-
return true;
|
|
988
944
|
}
|
|
989
|
-
static
|
|
990
|
-
|
|
945
|
+
static isEqualArrayString(value, valuePriorChanges) {
|
|
946
|
+
const stringArray = LodashUtilities.cloneDeep(value).sort();
|
|
947
|
+
const stringArrayPriorChanges = LodashUtilities.cloneDeep(valuePriorChanges).sort();
|
|
948
|
+
return LodashUtilities.isEqual(stringArray, stringArrayPriorChanges);
|
|
949
|
+
}
|
|
950
|
+
static isEqualArrayDate(value, valuePriorChanges) {
|
|
951
|
+
const newValue = value.map(v => new Date(v)).sort();
|
|
952
|
+
const newValuePriorChanges = valuePriorChanges.map(v => new Date(v)).sort();
|
|
953
|
+
return LodashUtilities.isEqual(newValue, newValuePriorChanges);
|
|
954
|
+
}
|
|
955
|
+
static isEqualArrayDateRange(value, valuePriorChanges, filter) {
|
|
956
|
+
const dateRanges = value.sort();
|
|
957
|
+
const dateRangesPriorChanges = valuePriorChanges.sort();
|
|
958
|
+
if (dateRanges.length !== dateRangesPriorChanges.length) {
|
|
991
959
|
return false;
|
|
992
960
|
}
|
|
961
|
+
for (let i = 0; i < dateRanges.length; i++) {
|
|
962
|
+
if (!this.isEqualDateRange(dateRanges[i], dateRangesPriorChanges[i], filter)) {
|
|
963
|
+
return false;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
993
966
|
return true;
|
|
994
967
|
}
|
|
995
|
-
static
|
|
996
|
-
|
|
997
|
-
|
|
968
|
+
static isEqualDateTime(value, valuePriorChanges) {
|
|
969
|
+
const date = new Date(value);
|
|
970
|
+
const datePriorChanges = new Date(valuePriorChanges);
|
|
971
|
+
return LodashUtilities.isEqual(date, datePriorChanges);
|
|
972
|
+
}
|
|
973
|
+
static isEqualDate(value, valuePriorChanges) {
|
|
974
|
+
const date = new Date(value);
|
|
975
|
+
const datePriorChanges = new Date(valuePriorChanges);
|
|
976
|
+
date.setHours(0, 0, 0, 0);
|
|
977
|
+
datePriorChanges.setHours(0, 0, 0, 0);
|
|
978
|
+
return LodashUtilities.isEqual(date, datePriorChanges);
|
|
979
|
+
}
|
|
980
|
+
static isEqualDateRange(value, valuePriorChanges, filter) {
|
|
981
|
+
const dateRange = LodashUtilities.cloneDeep(value);
|
|
982
|
+
dateRange.start = new Date(value.start);
|
|
983
|
+
dateRange.end = new Date(value.end);
|
|
984
|
+
dateRange.values = DateUtilities.getDatesBetween(dateRange.start, dateRange.end, filter);
|
|
985
|
+
const dateRangePriorChanges = LodashUtilities.cloneDeep(valuePriorChanges);
|
|
986
|
+
dateRangePriorChanges.start = new Date(valuePriorChanges.start);
|
|
987
|
+
dateRangePriorChanges.end = new Date(valuePriorChanges.end);
|
|
988
|
+
dateRangePriorChanges.values = DateUtilities.getDatesBetween(dateRangePriorChanges.start, dateRangePriorChanges.end, filter);
|
|
989
|
+
return LodashUtilities.isEqual(dateRange, dateRangePriorChanges);
|
|
990
|
+
}
|
|
991
|
+
// TODO: Find a way to use blobs with jest
|
|
992
|
+
/* istanbul ignore next */
|
|
993
|
+
static async isEqualFile(value, valuePriorChanges, multiple, http) {
|
|
994
|
+
if (value == null) {
|
|
995
|
+
if (valuePriorChanges == null) {
|
|
996
|
+
return true;
|
|
997
|
+
}
|
|
998
|
+
else {
|
|
999
|
+
return false;
|
|
1000
|
+
}
|
|
998
1001
|
}
|
|
999
|
-
|
|
1002
|
+
const files = multiple ? value.sort() : [value].sort();
|
|
1003
|
+
const filesPriorChanges = multiple ? valuePriorChanges.sort() : [valuePriorChanges].sort();
|
|
1004
|
+
if (files.length !== filesPriorChanges.length) {
|
|
1000
1005
|
return false;
|
|
1001
1006
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1007
|
+
for (let i = 0; i < files.length; i++) {
|
|
1008
|
+
// checks this before actually getting any files due to performance reasons.
|
|
1009
|
+
if (!LodashUtilities.isEqual(LodashUtilities.omit(files[i], 'file'), LodashUtilities.omit(filesPriorChanges[i], 'file'))) {
|
|
1010
|
+
return false;
|
|
1011
|
+
}
|
|
1012
|
+
if (filesPriorChanges[i].file && !files[i].file) {
|
|
1013
|
+
files[i] = await FileUtilities.getFileData(files[i], http);
|
|
1014
|
+
value = files[i];
|
|
1015
|
+
}
|
|
1016
|
+
if (files[i].file && !filesPriorChanges[i].file) {
|
|
1017
|
+
filesPriorChanges[i] = await FileUtilities.getFileData(filesPriorChanges[i], http);
|
|
1018
|
+
valuePriorChanges = filesPriorChanges[i];
|
|
1019
|
+
}
|
|
1020
|
+
if (!LodashUtilities.isEqual(await files[i].file?.text(), await filesPriorChanges[i].file?.text())) {
|
|
1021
|
+
return false;
|
|
1022
|
+
}
|
|
1004
1023
|
}
|
|
1005
1024
|
return true;
|
|
1006
1025
|
}
|
|
1007
|
-
static
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
if (metadata.minLength && value.length < metadata.minLength) {
|
|
1012
|
-
return false;
|
|
1013
|
-
}
|
|
1014
|
-
return true;
|
|
1015
|
-
}
|
|
1016
|
-
static isPasswordValid(value, metadata, confirmPassword) {
|
|
1017
|
-
if (value !== confirmPassword) {
|
|
1018
|
-
return false;
|
|
1019
|
-
}
|
|
1020
|
-
if (metadata.maxLength && value.length > metadata.maxLength) {
|
|
1021
|
-
return false;
|
|
1022
|
-
}
|
|
1023
|
-
if (metadata.minLength && value.length < metadata.minLength) {
|
|
1024
|
-
return false;
|
|
1025
|
-
}
|
|
1026
|
-
if (metadata.regex && !value.match(metadata.regex)) {
|
|
1026
|
+
static isEqualCustom(value, valuePriorChanges,
|
|
1027
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1028
|
+
metadata) {
|
|
1029
|
+
if (!metadata.isEqual(value, valuePriorChanges, metadata)) {
|
|
1027
1030
|
return false;
|
|
1028
1031
|
}
|
|
1029
1032
|
return true;
|
|
1030
1033
|
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
+
/**
|
|
1035
|
+
* Compare function for sorting entity keys by their order value.
|
|
1036
|
+
*
|
|
1037
|
+
* @param a - First key of entity.
|
|
1038
|
+
* @param b - Second key of entity.
|
|
1039
|
+
* @param entity - Current entity (used to get metadata of entity keys).
|
|
1040
|
+
* @returns 0 if both values have the same order, a negative value if 'a' comes before 'b', a positive value if 'a' comes behind 'b'.
|
|
1041
|
+
*/
|
|
1042
|
+
static compareOrder(a, b, entity) {
|
|
1043
|
+
const metadataA = this.getPropertyMetadata(entity, a);
|
|
1044
|
+
const metadataB = this.getPropertyMetadata(entity, b);
|
|
1045
|
+
if (metadataA.position.order === -1) {
|
|
1046
|
+
if (metadataB.position.order === -1) {
|
|
1047
|
+
return 0;
|
|
1048
|
+
}
|
|
1049
|
+
return 1;
|
|
1034
1050
|
}
|
|
1035
|
-
if (
|
|
1036
|
-
return
|
|
1051
|
+
else if (metadataB.position.order === -1) {
|
|
1052
|
+
return -1;
|
|
1037
1053
|
}
|
|
1038
|
-
return
|
|
1054
|
+
return metadataA.position.order - metadataB.position.order;
|
|
1039
1055
|
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1056
|
+
/**
|
|
1057
|
+
* Gets the bootstrap column values for "lg", "md", "sm".
|
|
1058
|
+
*
|
|
1059
|
+
* @param entity - Entity to get the bootstrap column values of the key.
|
|
1060
|
+
* @param key - Key of the property to get bootstrap column values from.
|
|
1061
|
+
* @param type - Defines for which screen size the column values should be returned.
|
|
1062
|
+
* @returns Bootstrap column value.
|
|
1063
|
+
*/
|
|
1064
|
+
static getWidth(entity, key, type) {
|
|
1065
|
+
const metadata = this.getPropertyMetadata(entity, key);
|
|
1066
|
+
switch (type) {
|
|
1067
|
+
case 'lg':
|
|
1068
|
+
return metadata.defaultWidths[0];
|
|
1069
|
+
case 'md':
|
|
1070
|
+
return metadata.defaultWidths[1];
|
|
1071
|
+
case 'sm':
|
|
1072
|
+
return metadata.defaultWidths[2];
|
|
1049
1073
|
}
|
|
1050
|
-
return true;
|
|
1051
1074
|
}
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
}
|
|
1066
|
-
if (metadata.maxStart && value.start.getTime() > metadata.maxStart(value.start).getTime()) {
|
|
1067
|
-
return false;
|
|
1068
|
-
}
|
|
1069
|
-
if (metadata.minEnd && value.end.getTime() < metadata.minEnd(value.end).getTime()) {
|
|
1070
|
-
return false;
|
|
1071
|
-
}
|
|
1072
|
-
if (metadata.maxEnd && value.end.getTime() > metadata.maxEnd(value.end).getTime()) {
|
|
1073
|
-
return false;
|
|
1074
|
-
}
|
|
1075
|
-
if (metadata.filter) {
|
|
1076
|
-
if (!metadata.filter(value.start)) {
|
|
1077
|
-
return false;
|
|
1078
|
-
}
|
|
1079
|
-
if (!metadata.filter(value.end)) {
|
|
1080
|
-
return false;
|
|
1081
|
-
}
|
|
1082
|
-
if (value.values) {
|
|
1083
|
-
for (const date of value.values) {
|
|
1084
|
-
if (!metadata.filter(date)) {
|
|
1085
|
-
return false;
|
|
1075
|
+
/**
|
|
1076
|
+
* Resets all changes on an entity.
|
|
1077
|
+
*
|
|
1078
|
+
* @param entity - The entity to reset.
|
|
1079
|
+
* @param entityPriorChanges - The entity before any changes.
|
|
1080
|
+
*/
|
|
1081
|
+
static resetChangesOnEntity(entity, entityPriorChanges) {
|
|
1082
|
+
for (const key in entityPriorChanges) {
|
|
1083
|
+
ReflectUtilities.set(entity, key, ReflectUtilities.get(entityPriorChanges, key));
|
|
1084
|
+
if (ReflectUtilities.hasMetadata(this.METADATA_KEYS_TO_RESET_KEY, entity, key)) {
|
|
1085
|
+
for (const k of ReflectUtilities.getMetadata(this.METADATA_KEYS_TO_RESET_KEY, entity, key)) {
|
|
1086
|
+
if (ReflectUtilities.hasMetadata(k, entity, key)) {
|
|
1087
|
+
ReflectUtilities.defineMetadata(k, undefined, entity, key);
|
|
1086
1088
|
}
|
|
1087
1089
|
}
|
|
1088
1090
|
}
|
|
1089
1091
|
}
|
|
1090
|
-
return true;
|
|
1091
1092
|
}
|
|
1092
|
-
static
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
return false;
|
|
1093
|
+
static getEntityRows(entity, tab, hideOmitForCreate, hideOmitForEdit, additionalOmitValues) {
|
|
1094
|
+
const res = [];
|
|
1095
|
+
const keys = this.keysOf(entity, hideOmitForCreate, hideOmitForEdit)
|
|
1096
|
+
.filter(k => !additionalOmitValues.includes(k));
|
|
1097
|
+
const numberOfRows = this.getNumberOfRows(keys, entity, tab);
|
|
1098
|
+
for (let i = 1; i <= numberOfRows; i++) {
|
|
1099
|
+
const row = {
|
|
1100
|
+
row: i,
|
|
1101
|
+
keys: this.getKeysForRow(keys, entity, i, tab)
|
|
1102
|
+
};
|
|
1103
|
+
res.push(row);
|
|
1104
1104
|
}
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
if (!(time.hours > minTime.hours
|
|
1112
|
-
|| (time.hours === minTime.hours
|
|
1113
|
-
&& time.minutes >= minTime.minutes))) {
|
|
1114
|
-
return false;
|
|
1115
|
-
}
|
|
1105
|
+
if (this.getKeysForRow(keys, entity, -1, tab).length) {
|
|
1106
|
+
const lastRow = {
|
|
1107
|
+
row: numberOfRows + 1,
|
|
1108
|
+
keys: this.getKeysForRow(keys, entity, -1, tab)
|
|
1109
|
+
};
|
|
1110
|
+
res.push(lastRow);
|
|
1116
1111
|
}
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1112
|
+
return res;
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* Gets the tabs that are used to display the given entity.
|
|
1116
|
+
*
|
|
1117
|
+
* @param entity - The entity to get the rows from.
|
|
1118
|
+
* @param hideOmitForCreate - Whether or not keys with the metadata omitForCreate should be filtered out.
|
|
1119
|
+
* @param hideOmitForEdit - Whether or not keys with the metadata omitForUpdate should be filtered out.
|
|
1120
|
+
* @param additionalOmitValues - Additional omit values.
|
|
1121
|
+
* @returns The sorted Tabs containing the rows and the keys to display in that row.
|
|
1122
|
+
*/
|
|
1123
|
+
static getEntityTabs(entity, hideOmitForCreate = false, hideOmitForEdit = false, additionalOmitValues = []) {
|
|
1124
|
+
const res = [];
|
|
1125
|
+
const keys = this.keysOf(entity, hideOmitForCreate, hideOmitForEdit)
|
|
1126
|
+
.filter(k => !additionalOmitValues.includes(k));
|
|
1127
|
+
const numberOfTabs = this.getNumberOfTabs(keys, entity);
|
|
1128
|
+
// eslint-disable-next-line max-len
|
|
1129
|
+
const firstTabRows = this.getEntityRows(entity, -1, hideOmitForCreate, hideOmitForEdit, additionalOmitValues);
|
|
1130
|
+
if (firstTabRows.length) {
|
|
1131
|
+
const firstTab = {
|
|
1132
|
+
tabName: this.getFirstTabName(entity),
|
|
1133
|
+
tab: -1,
|
|
1134
|
+
rows: firstTabRows
|
|
1135
|
+
};
|
|
1136
|
+
res.push(firstTab);
|
|
1124
1137
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1138
|
+
for (let i = 2; i <= numberOfTabs; i++) {
|
|
1139
|
+
const rows = this.getEntityRows(entity, i, hideOmitForCreate, hideOmitForEdit, additionalOmitValues);
|
|
1140
|
+
if (rows.length) {
|
|
1141
|
+
const tab = {
|
|
1142
|
+
tabName: this.getTabName(entity, i),
|
|
1143
|
+
tab: i,
|
|
1144
|
+
rows: rows
|
|
1145
|
+
};
|
|
1146
|
+
res.push(tab);
|
|
1128
1147
|
}
|
|
1129
1148
|
}
|
|
1130
|
-
return
|
|
1149
|
+
return res;
|
|
1131
1150
|
}
|
|
1132
|
-
static
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
+
static getKeysForRow(keys, entity, row, tab) {
|
|
1152
|
+
return keys
|
|
1153
|
+
.filter(k => this.getPropertyMetadata(entity, k).position.row === row)
|
|
1154
|
+
.filter(k => this.getPropertyMetadata(entity, k).position.tab === tab)
|
|
1155
|
+
.sort((a, b) => this.compareOrder(a, b, entity));
|
|
1156
|
+
}
|
|
1157
|
+
static getNumberOfRows(keys, entity, tab) {
|
|
1158
|
+
return keys
|
|
1159
|
+
.filter(k => this.getPropertyMetadata(entity, k).position.tab === tab)
|
|
1160
|
+
.map(k => this.getPropertyMetadata(entity, k).position.row)
|
|
1161
|
+
.sort((a, b) => (a > b ? -1 : 1))[0];
|
|
1162
|
+
}
|
|
1163
|
+
static getNumberOfTabs(keys, entity) {
|
|
1164
|
+
return keys
|
|
1165
|
+
.map(k => this.getPropertyMetadata(entity, k).position.tab)
|
|
1166
|
+
.sort((a, b) => (a > b ? -1 : 1))[0];
|
|
1167
|
+
}
|
|
1168
|
+
static getTabName(entity, tab) {
|
|
1169
|
+
const providedTabName = ReflectUtilities.ownKeys(entity)
|
|
1170
|
+
.map(k => this.getPropertyMetadata(entity, k))
|
|
1171
|
+
.find(m => m.position.tab === tab && m.position.tabName)?.position.tabName;
|
|
1172
|
+
return providedTabName ?? `Tab ${tab}`;
|
|
1173
|
+
}
|
|
1174
|
+
static getFirstTabName(entity) {
|
|
1175
|
+
const providedTabName = ReflectUtilities.ownKeys(entity)
|
|
1176
|
+
.map(k => this.getPropertyMetadata(entity, k))
|
|
1177
|
+
.find(m => m.position.tabName && m.position.tab === -1)?.position.tabName;
|
|
1178
|
+
return providedTabName ?? 'Tab 1';
|
|
1151
1179
|
}
|
|
1152
1180
|
/**
|
|
1153
|
-
*
|
|
1181
|
+
* Gets the keys of the provided entity correctly typed.
|
|
1154
1182
|
*
|
|
1155
|
-
* @param entity - The entity
|
|
1156
|
-
* @param
|
|
1157
|
-
* @param
|
|
1158
|
-
* @returns
|
|
1183
|
+
* @param entity - The entity to get the keys of.
|
|
1184
|
+
* @param hideOmitForCreate - Whether or not keys with the metadata omitForCreate should be filtered out.
|
|
1185
|
+
* @param hideOmitForEdit - Whether or not keys with the metadata omitForUpdate should be filtered out.
|
|
1186
|
+
* @returns An array of keys of the entity.
|
|
1159
1187
|
*/
|
|
1160
|
-
static
|
|
1161
|
-
|
|
1162
|
-
|
|
1188
|
+
static keysOf(entity, hideOmitForCreate = false, hideOmitForEdit = false) {
|
|
1189
|
+
let keys = ReflectUtilities.ownKeys(entity);
|
|
1190
|
+
const dontDisplayKeys = this.getDontDisplayKeys(entity);
|
|
1191
|
+
keys = keys.filter(k => !dontDisplayKeys.includes(k));
|
|
1192
|
+
if (hideOmitForCreate) {
|
|
1193
|
+
const omitForCreateKeys = this.getOmitForCreate(entity);
|
|
1194
|
+
keys = keys.filter(k => !omitForCreateKeys.includes(k));
|
|
1163
1195
|
}
|
|
1164
|
-
|
|
1165
|
-
|
|
1196
|
+
if (hideOmitForEdit) {
|
|
1197
|
+
const omitForUpdateKeys = this.getOmitForUpdate(entity);
|
|
1198
|
+
keys = keys.filter(k => !omitForUpdateKeys.includes(k));
|
|
1199
|
+
}
|
|
1200
|
+
return keys;
|
|
1166
1201
|
}
|
|
1167
|
-
static
|
|
1202
|
+
static getDontDisplayKeys(entity) {
|
|
1168
1203
|
const res = [];
|
|
1169
1204
|
for (const key of ReflectUtilities.ownKeys(entity)) {
|
|
1170
|
-
const metadata =
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
res.push({
|
|
1174
|
-
key: key,
|
|
1175
|
-
before: entityPriorChanges[key],
|
|
1176
|
-
after: entity[key]
|
|
1177
|
-
});
|
|
1178
|
-
}
|
|
1179
|
-
else {
|
|
1180
|
-
// This is needed to set blob file data so that it is only requested once.
|
|
1181
|
-
entityPriorChanges[key] = LodashUtilities.cloneDeep(entity[key]);
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
return res;
|
|
1185
|
-
}
|
|
1186
|
-
// TODO Remove
|
|
1187
|
-
/**
|
|
1188
|
-
* Compares two Entities and returns their difference in an object.
|
|
1189
|
-
*
|
|
1190
|
-
* @param entity - The first entity to compare.
|
|
1191
|
-
* @param entityPriorChanges - The second entity to compare.
|
|
1192
|
-
* @returns The difference between the two Entities in form of a Partial.
|
|
1193
|
-
*/
|
|
1194
|
-
// static async difference<EntityType extends BaseEntityType<EntityType>>(
|
|
1195
|
-
// entity: EntityType,
|
|
1196
|
-
// entityPriorChanges: EntityType
|
|
1197
|
-
// ): Promise<Partial<EntityType>> {
|
|
1198
|
-
// const res: Partial<EntityType> = {};
|
|
1199
|
-
// for (const key in entity) {
|
|
1200
|
-
// const metadata: PropertyDecoratorConfigInternal = EntityUtilities.getPropertyMetadata(entity, key);
|
|
1201
|
-
// const type: DecoratorTypes = EntityUtilities.getPropertyType(entity, key);
|
|
1202
|
-
// if (!(await EntityUtilities.isEqual(entity[key], entityPriorChanges[key], metadata, type))) {
|
|
1203
|
-
// res[key] = entity[key];
|
|
1204
|
-
// }
|
|
1205
|
-
// }
|
|
1206
|
-
// return res;
|
|
1207
|
-
// }
|
|
1208
|
-
/**
|
|
1209
|
-
* Checks if two given values are equal.
|
|
1210
|
-
* It uses the isEqual method from LodashUtilities and extends it with functionality regarding Dates.
|
|
1211
|
-
*
|
|
1212
|
-
* @param value - The updated value.
|
|
1213
|
-
* @param valuePriorChanges - The value before any changes.
|
|
1214
|
-
* @param metadata - The metadata of the property.
|
|
1215
|
-
* @param type - The type of the property.
|
|
1216
|
-
* @param http - The angular HttpClient. Used to fetch files.
|
|
1217
|
-
* @returns Whether or not the given values are equal.
|
|
1218
|
-
*/
|
|
1219
|
-
static async isEqual(value, valuePriorChanges, metadata, type, http) {
|
|
1220
|
-
switch (type) {
|
|
1221
|
-
case DecoratorTypes.DATE_RANGE:
|
|
1222
|
-
return EntityUtilities.isEqualDateRange(value, valuePriorChanges, metadata.filter);
|
|
1223
|
-
case DecoratorTypes.DATE:
|
|
1224
|
-
return EntityUtilities.isEqualDate(value, valuePriorChanges);
|
|
1225
|
-
case DecoratorTypes.DATE_TIME:
|
|
1226
|
-
return EntityUtilities.isEqualDateTime(value, valuePriorChanges);
|
|
1227
|
-
case DecoratorTypes.ARRAY_DATE:
|
|
1228
|
-
case DecoratorTypes.ARRAY_DATE_TIME:
|
|
1229
|
-
return EntityUtilities.isEqualArrayDate(value, valuePriorChanges);
|
|
1230
|
-
case DecoratorTypes.ARRAY_DATE_RANGE:
|
|
1231
|
-
return EntityUtilities.isEqualArrayDateRange(value, valuePriorChanges, metadata.filter);
|
|
1232
|
-
case DecoratorTypes.ARRAY_STRING_CHIPS:
|
|
1233
|
-
case DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS:
|
|
1234
|
-
return EntityUtilities.isEqualArrayString(value, valuePriorChanges);
|
|
1235
|
-
case DecoratorTypes.FILE_IMAGE:
|
|
1236
|
-
case DecoratorTypes.FILE_DEFAULT:
|
|
1237
|
-
// eslint-disable-next-line max-len
|
|
1238
|
-
return EntityUtilities.isEqualFile(value, valuePriorChanges, metadata.multiple, http);
|
|
1239
|
-
case DecoratorTypes.CUSTOM:
|
|
1240
|
-
// eslint-disable-next-line max-len, @typescript-eslint/no-explicit-any
|
|
1241
|
-
return EntityUtilities.isEqualCustom(value, valuePriorChanges, metadata);
|
|
1242
|
-
default:
|
|
1243
|
-
return LodashUtilities.isEqual(value, valuePriorChanges);
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
static isEqualArrayString(value, valuePriorChanges) {
|
|
1247
|
-
const stringArray = LodashUtilities.cloneDeep(value).sort();
|
|
1248
|
-
const stringArrayPriorChanges = LodashUtilities.cloneDeep(valuePriorChanges).sort();
|
|
1249
|
-
return LodashUtilities.isEqual(stringArray, stringArrayPriorChanges);
|
|
1250
|
-
}
|
|
1251
|
-
static isEqualArrayDate(value, valuePriorChanges) {
|
|
1252
|
-
const newValue = value.map(v => new Date(v)).sort();
|
|
1253
|
-
const newValuePriorChanges = valuePriorChanges.map(v => new Date(v)).sort();
|
|
1254
|
-
return LodashUtilities.isEqual(newValue, newValuePriorChanges);
|
|
1255
|
-
}
|
|
1256
|
-
static isEqualArrayDateRange(value, valuePriorChanges, filter) {
|
|
1257
|
-
const dateRanges = value.sort();
|
|
1258
|
-
const dateRangesPriorChanges = valuePriorChanges.sort();
|
|
1259
|
-
if (dateRanges.length !== dateRangesPriorChanges.length) {
|
|
1260
|
-
return false;
|
|
1261
|
-
}
|
|
1262
|
-
for (let i = 0; i < dateRanges.length; i++) {
|
|
1263
|
-
if (!EntityUtilities.isEqualDateRange(dateRanges[i], dateRangesPriorChanges[i], filter)) {
|
|
1264
|
-
return false;
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
|
-
return true;
|
|
1268
|
-
}
|
|
1269
|
-
static isEqualDateTime(value, valuePriorChanges) {
|
|
1270
|
-
const date = new Date(value);
|
|
1271
|
-
const datePriorChanges = new Date(valuePriorChanges);
|
|
1272
|
-
return LodashUtilities.isEqual(date, datePriorChanges);
|
|
1273
|
-
}
|
|
1274
|
-
static isEqualDate(value, valuePriorChanges) {
|
|
1275
|
-
const date = new Date(value);
|
|
1276
|
-
const datePriorChanges = new Date(valuePriorChanges);
|
|
1277
|
-
date.setHours(0, 0, 0, 0);
|
|
1278
|
-
datePriorChanges.setHours(0, 0, 0, 0);
|
|
1279
|
-
return LodashUtilities.isEqual(date, datePriorChanges);
|
|
1280
|
-
}
|
|
1281
|
-
static isEqualDateRange(value, valuePriorChanges, filter) {
|
|
1282
|
-
const dateRange = LodashUtilities.cloneDeep(value);
|
|
1283
|
-
dateRange.start = new Date(value.start);
|
|
1284
|
-
dateRange.end = new Date(value.end);
|
|
1285
|
-
dateRange.values = DateUtilities.getDatesBetween(dateRange.start, dateRange.end, filter);
|
|
1286
|
-
const dateRangePriorChanges = LodashUtilities.cloneDeep(valuePriorChanges);
|
|
1287
|
-
dateRangePriorChanges.start = new Date(valuePriorChanges.start);
|
|
1288
|
-
dateRangePriorChanges.end = new Date(valuePriorChanges.end);
|
|
1289
|
-
dateRangePriorChanges.values = DateUtilities.getDatesBetween(dateRangePriorChanges.start, dateRangePriorChanges.end, filter);
|
|
1290
|
-
return LodashUtilities.isEqual(dateRange, dateRangePriorChanges);
|
|
1291
|
-
}
|
|
1292
|
-
// TODO: Find a way to use blobs with jest
|
|
1293
|
-
/* istanbul ignore next */
|
|
1294
|
-
static async isEqualFile(value, valuePriorChanges, multiple, http) {
|
|
1295
|
-
if (value == null) {
|
|
1296
|
-
if (valuePriorChanges == null) {
|
|
1297
|
-
return true;
|
|
1298
|
-
}
|
|
1299
|
-
else {
|
|
1300
|
-
return false;
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
const files = multiple ? value.sort() : [value].sort();
|
|
1304
|
-
const filesPriorChanges = multiple ? valuePriorChanges.sort() : [valuePriorChanges].sort();
|
|
1305
|
-
if (files.length !== filesPriorChanges.length) {
|
|
1306
|
-
return false;
|
|
1307
|
-
}
|
|
1308
|
-
for (let i = 0; i < files.length; i++) {
|
|
1309
|
-
// checks this before actually getting any files due to performance reasons.
|
|
1310
|
-
if (!LodashUtilities.isEqual(LodashUtilities.omit(files[i], 'file'), LodashUtilities.omit(filesPriorChanges[i], 'file'))) {
|
|
1311
|
-
return false;
|
|
1312
|
-
}
|
|
1313
|
-
if (filesPriorChanges[i].file && !files[i].file) {
|
|
1314
|
-
files[i] = await FileUtilities.getFileData(files[i], http);
|
|
1315
|
-
value = files[i];
|
|
1316
|
-
}
|
|
1317
|
-
if (files[i].file && !filesPriorChanges[i].file) {
|
|
1318
|
-
filesPriorChanges[i] = await FileUtilities.getFileData(filesPriorChanges[i], http);
|
|
1319
|
-
valuePriorChanges = filesPriorChanges[i];
|
|
1320
|
-
}
|
|
1321
|
-
if (!LodashUtilities.isEqual(await files[i].file?.text(), await filesPriorChanges[i].file?.text())) {
|
|
1322
|
-
return false;
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
return true;
|
|
1326
|
-
}
|
|
1327
|
-
static isEqualCustom(value, valuePriorChanges,
|
|
1328
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1329
|
-
metadata) {
|
|
1330
|
-
if (!metadata.isEqual(value, valuePriorChanges, metadata)) {
|
|
1331
|
-
return false;
|
|
1332
|
-
}
|
|
1333
|
-
return true;
|
|
1334
|
-
}
|
|
1335
|
-
/**
|
|
1336
|
-
* Compare function for sorting entity keys by their order value.
|
|
1337
|
-
*
|
|
1338
|
-
* @param a - First key of entity.
|
|
1339
|
-
* @param b - Second key of entity.
|
|
1340
|
-
* @param entity - Current entity (used to get metadata of entity keys).
|
|
1341
|
-
* @returns 0 if both values have the same order, a negative value if 'a' comes before 'b', a positive value if 'a' comes behind 'b'.
|
|
1342
|
-
*/
|
|
1343
|
-
static compareOrder(a, b, entity) {
|
|
1344
|
-
const metadataA = EntityUtilities.getPropertyMetadata(entity, a);
|
|
1345
|
-
const metadataB = EntityUtilities.getPropertyMetadata(entity, b);
|
|
1346
|
-
if (metadataA.position.order === -1) {
|
|
1347
|
-
if (metadataB.position.order === -1) {
|
|
1348
|
-
return 0;
|
|
1349
|
-
}
|
|
1350
|
-
return 1;
|
|
1351
|
-
}
|
|
1352
|
-
else if (metadataB.position.order === -1) {
|
|
1353
|
-
return -1;
|
|
1354
|
-
}
|
|
1355
|
-
return metadataA.position.order - metadataB.position.order;
|
|
1356
|
-
}
|
|
1357
|
-
/**
|
|
1358
|
-
* Gets the bootstrap column values for "lg", "md", "sm".
|
|
1359
|
-
*
|
|
1360
|
-
* @param entity - Entity to get the bootstrap column values of the key.
|
|
1361
|
-
* @param key - Key of the property to get bootstrap column values from.
|
|
1362
|
-
* @param type - Defines for which screen size the column values should be returned.
|
|
1363
|
-
* @returns Bootstrap column value.
|
|
1364
|
-
*/
|
|
1365
|
-
static getWidth(entity, key, type) {
|
|
1366
|
-
const metadata = EntityUtilities.getPropertyMetadata(entity, key);
|
|
1367
|
-
switch (type) {
|
|
1368
|
-
case 'lg':
|
|
1369
|
-
return metadata.defaultWidths[0];
|
|
1370
|
-
case 'md':
|
|
1371
|
-
return metadata.defaultWidths[1];
|
|
1372
|
-
case 'sm':
|
|
1373
|
-
return metadata.defaultWidths[2];
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
1376
|
-
/**
|
|
1377
|
-
* Resets all changes on an entity.
|
|
1378
|
-
*
|
|
1379
|
-
* @param entity - The entity to reset.
|
|
1380
|
-
* @param entityPriorChanges - The entity before any changes.
|
|
1381
|
-
*/
|
|
1382
|
-
static resetChangesOnEntity(entity, entityPriorChanges) {
|
|
1383
|
-
for (const key in entityPriorChanges) {
|
|
1384
|
-
ReflectUtilities.set(entity, key, ReflectUtilities.get(entityPriorChanges, key));
|
|
1385
|
-
if (ReflectUtilities.hasMetadata(this.METADATA_KEYS_TO_RESET_KEY, entity, key)) {
|
|
1386
|
-
for (const k of ReflectUtilities.getMetadata(this.METADATA_KEYS_TO_RESET_KEY, entity, key)) {
|
|
1387
|
-
if (ReflectUtilities.hasMetadata(k, entity, key)) {
|
|
1388
|
-
ReflectUtilities.defineMetadata(k, undefined, entity, key);
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
static getEntityRows(entity, tab, hideOmitForCreate, hideOmitForEdit, additionalOmitValues) {
|
|
1395
|
-
const res = [];
|
|
1396
|
-
const keys = EntityUtilities.keysOf(entity, hideOmitForCreate, hideOmitForEdit)
|
|
1397
|
-
.filter(k => !additionalOmitValues.includes(k));
|
|
1398
|
-
const numberOfRows = EntityUtilities.getNumberOfRows(keys, entity, tab);
|
|
1399
|
-
for (let i = 1; i <= numberOfRows; i++) {
|
|
1400
|
-
const row = {
|
|
1401
|
-
row: i,
|
|
1402
|
-
keys: EntityUtilities.getKeysForRow(keys, entity, i, tab)
|
|
1403
|
-
};
|
|
1404
|
-
res.push(row);
|
|
1405
|
-
}
|
|
1406
|
-
if (EntityUtilities.getKeysForRow(keys, entity, -1, tab).length) {
|
|
1407
|
-
const lastRow = {
|
|
1408
|
-
row: numberOfRows + 1,
|
|
1409
|
-
keys: EntityUtilities.getKeysForRow(keys, entity, -1, tab)
|
|
1410
|
-
};
|
|
1411
|
-
res.push(lastRow);
|
|
1412
|
-
}
|
|
1413
|
-
return res;
|
|
1414
|
-
}
|
|
1415
|
-
/**
|
|
1416
|
-
* Gets the tabs that are used to display the given entity.
|
|
1417
|
-
*
|
|
1418
|
-
* @param entity - The entity to get the rows from.
|
|
1419
|
-
* @param hideOmitForCreate - Whether or not keys with the metadata omitForCreate should be filtered out.
|
|
1420
|
-
* @param hideOmitForEdit - Whether or not keys with the metadata omitForUpdate should be filtered out.
|
|
1421
|
-
* @param additionalOmitValues - Additional omit values.
|
|
1422
|
-
* @returns The sorted Tabs containing the rows and the keys to display in that row.
|
|
1423
|
-
*/
|
|
1424
|
-
static getEntityTabs(entity, hideOmitForCreate = false, hideOmitForEdit = false, additionalOmitValues = []) {
|
|
1425
|
-
const res = [];
|
|
1426
|
-
const keys = EntityUtilities.keysOf(entity, hideOmitForCreate, hideOmitForEdit)
|
|
1427
|
-
.filter(k => !additionalOmitValues.includes(k));
|
|
1428
|
-
const numberOfTabs = EntityUtilities.getNumberOfTabs(keys, entity);
|
|
1429
|
-
// eslint-disable-next-line max-len
|
|
1430
|
-
const firstTabRows = EntityUtilities.getEntityRows(entity, -1, hideOmitForCreate, hideOmitForEdit, additionalOmitValues);
|
|
1431
|
-
if (firstTabRows.length) {
|
|
1432
|
-
const firstTab = {
|
|
1433
|
-
tabName: EntityUtilities.getFirstTabName(entity),
|
|
1434
|
-
tab: -1,
|
|
1435
|
-
rows: firstTabRows
|
|
1436
|
-
};
|
|
1437
|
-
res.push(firstTab);
|
|
1438
|
-
}
|
|
1439
|
-
for (let i = 2; i <= numberOfTabs; i++) {
|
|
1440
|
-
const rows = EntityUtilities.getEntityRows(entity, i, hideOmitForCreate, hideOmitForEdit, additionalOmitValues);
|
|
1441
|
-
if (rows.length) {
|
|
1442
|
-
const tab = {
|
|
1443
|
-
tabName: EntityUtilities.getTabName(entity, i),
|
|
1444
|
-
tab: i,
|
|
1445
|
-
rows: rows
|
|
1446
|
-
};
|
|
1447
|
-
res.push(tab);
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
return res;
|
|
1451
|
-
}
|
|
1452
|
-
static getKeysForRow(keys, entity, row, tab) {
|
|
1453
|
-
return keys
|
|
1454
|
-
.filter(k => EntityUtilities.getPropertyMetadata(entity, k).position.row === row)
|
|
1455
|
-
.filter(k => EntityUtilities.getPropertyMetadata(entity, k).position.tab === tab)
|
|
1456
|
-
.sort((a, b) => EntityUtilities.compareOrder(a, b, entity));
|
|
1457
|
-
}
|
|
1458
|
-
static getNumberOfRows(keys, entity, tab) {
|
|
1459
|
-
return keys
|
|
1460
|
-
.filter(k => EntityUtilities.getPropertyMetadata(entity, k).position.tab === tab)
|
|
1461
|
-
.map(k => EntityUtilities.getPropertyMetadata(entity, k).position.row)
|
|
1462
|
-
.sort((a, b) => (a > b ? -1 : 1))[0];
|
|
1463
|
-
}
|
|
1464
|
-
static getNumberOfTabs(keys, entity) {
|
|
1465
|
-
return keys
|
|
1466
|
-
.map(k => EntityUtilities.getPropertyMetadata(entity, k).position.tab)
|
|
1467
|
-
.sort((a, b) => (a > b ? -1 : 1))[0];
|
|
1468
|
-
}
|
|
1469
|
-
static getTabName(entity, tab) {
|
|
1470
|
-
const providedTabName = ReflectUtilities.ownKeys(entity)
|
|
1471
|
-
.map(k => EntityUtilities.getPropertyMetadata(entity, k))
|
|
1472
|
-
.find(m => m.position.tab === tab && m.position.tabName)?.position.tabName;
|
|
1473
|
-
return providedTabName ?? `Tab ${tab}`;
|
|
1474
|
-
}
|
|
1475
|
-
static getFirstTabName(entity) {
|
|
1476
|
-
const providedTabName = ReflectUtilities.ownKeys(entity)
|
|
1477
|
-
.map(k => EntityUtilities.getPropertyMetadata(entity, k))
|
|
1478
|
-
.find(m => m.position.tabName && m.position.tab === -1)?.position.tabName;
|
|
1479
|
-
return providedTabName ?? 'Tab 1';
|
|
1480
|
-
}
|
|
1481
|
-
/**
|
|
1482
|
-
* Gets the keys of the provided entity correctly typed.
|
|
1483
|
-
*
|
|
1484
|
-
* @param entity - The entity to get the keys of.
|
|
1485
|
-
* @param hideOmitForCreate - Whether or not keys with the metadata omitForCreate should be filtered out.
|
|
1486
|
-
* @param hideOmitForEdit - Whether or not keys with the metadata omitForUpdate should be filtered out.
|
|
1487
|
-
* @returns An array of keys of the entity.
|
|
1488
|
-
*/
|
|
1489
|
-
static keysOf(entity, hideOmitForCreate = false, hideOmitForEdit = false) {
|
|
1490
|
-
let keys = ReflectUtilities.ownKeys(entity);
|
|
1491
|
-
const dontDisplayKeys = EntityUtilities.getDontDisplayKeys(entity);
|
|
1492
|
-
keys = keys.filter(k => !dontDisplayKeys.includes(k));
|
|
1493
|
-
if (hideOmitForCreate) {
|
|
1494
|
-
const omitForCreateKeys = EntityUtilities.getOmitForCreate(entity);
|
|
1495
|
-
keys = keys.filter(k => !omitForCreateKeys.includes(k));
|
|
1496
|
-
}
|
|
1497
|
-
if (hideOmitForEdit) {
|
|
1498
|
-
const omitForUpdateKeys = EntityUtilities.getOmitForUpdate(entity);
|
|
1499
|
-
keys = keys.filter(k => !omitForUpdateKeys.includes(k));
|
|
1500
|
-
}
|
|
1501
|
-
return keys;
|
|
1502
|
-
}
|
|
1503
|
-
static getDontDisplayKeys(entity) {
|
|
1504
|
-
const res = [];
|
|
1505
|
-
for (const key of ReflectUtilities.ownKeys(entity)) {
|
|
1506
|
-
const metadata = EntityUtilities.getPropertyMetadata(entity, key);
|
|
1507
|
-
if (!metadata.display(entity)) {
|
|
1508
|
-
res.push(key);
|
|
1205
|
+
const metadata = this.getPropertyMetadata(entity, key);
|
|
1206
|
+
if (!metadata.display(entity)) {
|
|
1207
|
+
res.push(key);
|
|
1509
1208
|
}
|
|
1510
1209
|
}
|
|
1511
1210
|
return res;
|
|
@@ -1595,6 +1294,10 @@ class PropertyDecoratorConfigInternal {
|
|
|
1595
1294
|
position;
|
|
1596
1295
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1597
1296
|
isReadOnly;
|
|
1297
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1298
|
+
default;
|
|
1299
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1300
|
+
change;
|
|
1598
1301
|
constructor(data) {
|
|
1599
1302
|
this.display = this.booleanToFunction(data.display ?? true);
|
|
1600
1303
|
this.displayName = data.displayName;
|
|
@@ -1604,6 +1307,23 @@ class PropertyDecoratorConfigInternal {
|
|
|
1604
1307
|
this.defaultWidths = data.defaultWidths ?? [6, 6, 12];
|
|
1605
1308
|
this.position = new PositionInternal(data.position);
|
|
1606
1309
|
this.isReadOnly = this.booleanToFunction(data.isReadOnly ?? false);
|
|
1310
|
+
this.default = this.defaultToFunction(data.default);
|
|
1311
|
+
this.change = data.change;
|
|
1312
|
+
}
|
|
1313
|
+
/**
|
|
1314
|
+
* Converts the default value to a function or undefined.
|
|
1315
|
+
*
|
|
1316
|
+
* @param value - The default value provided by the metadata.
|
|
1317
|
+
* @returns A function that returns a default value or undefined.
|
|
1318
|
+
*/
|
|
1319
|
+
defaultToFunction(value) {
|
|
1320
|
+
if (value == null) {
|
|
1321
|
+
return undefined;
|
|
1322
|
+
}
|
|
1323
|
+
if (typeof value == 'function') {
|
|
1324
|
+
return value;
|
|
1325
|
+
}
|
|
1326
|
+
return (() => value);
|
|
1607
1327
|
}
|
|
1608
1328
|
/**
|
|
1609
1329
|
* Converts the given boolean or boolean function to a boolean function.
|
|
@@ -1702,520 +1422,1113 @@ class AutocompleteStringDecoratorConfigInternal extends PropertyDecoratorConfigI
|
|
|
1702
1422
|
}
|
|
1703
1423
|
}
|
|
1704
1424
|
/**
|
|
1705
|
-
* The internal PasswordStringDecoratorConfig. Sets default values.
|
|
1425
|
+
* The internal PasswordStringDecoratorConfig. Sets default values.
|
|
1426
|
+
*/
|
|
1427
|
+
class PasswordStringDecoratorConfigInternal extends PropertyDecoratorConfigInternal {
|
|
1428
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1429
|
+
displayStyle;
|
|
1430
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1431
|
+
minLength;
|
|
1432
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1433
|
+
maxLength;
|
|
1434
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1435
|
+
regex;
|
|
1436
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1437
|
+
needsConfirmation;
|
|
1438
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1439
|
+
confirmationDisplayName;
|
|
1440
|
+
constructor(data) {
|
|
1441
|
+
super(data);
|
|
1442
|
+
this.displayStyle = data.displayStyle;
|
|
1443
|
+
this.minLength = data.minLength;
|
|
1444
|
+
this.maxLength = data.maxLength;
|
|
1445
|
+
this.regex = data.regex;
|
|
1446
|
+
this.needsConfirmation = data.needsConfirmation ?? true;
|
|
1447
|
+
this.confirmationDisplayName = data.confirmationDisplayName ?? 'Confirm Password';
|
|
1448
|
+
this.defaultWidths = data.defaultWidths ?? [12, 12, 12];
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
/**
|
|
1453
|
+
* Decorator for setting and getting string Property metadata.
|
|
1454
|
+
*
|
|
1455
|
+
* @param metadata - The metadata of the string property.
|
|
1456
|
+
* @returns The method that defines the metadata.
|
|
1457
|
+
*/
|
|
1458
|
+
function string(metadata) {
|
|
1459
|
+
switch (metadata.displayStyle) {
|
|
1460
|
+
case 'dropdown':
|
|
1461
|
+
return baseProperty(new DropdownStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_DROPDOWN);
|
|
1462
|
+
case 'autocomplete':
|
|
1463
|
+
return baseProperty(new AutocompleteStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_AUTOCOMPLETE);
|
|
1464
|
+
case 'textbox':
|
|
1465
|
+
return baseProperty(new TextboxStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_TEXTBOX);
|
|
1466
|
+
case 'password':
|
|
1467
|
+
return baseProperty(new PasswordStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING_PASSWORD, [EntityUtilities.CONFIRM_PASSWORD_KEY]);
|
|
1468
|
+
default:
|
|
1469
|
+
return baseProperty(new DefaultStringDecoratorConfigInternal(metadata), DecoratorTypes.STRING);
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
/**
|
|
1474
|
+
* A base Entity class with a builtin id.
|
|
1475
|
+
*/
|
|
1476
|
+
class Entity {
|
|
1477
|
+
/**
|
|
1478
|
+
* A unique identifier for the Entity.
|
|
1479
|
+
*/
|
|
1480
|
+
id;
|
|
1481
|
+
constructor(entity) {
|
|
1482
|
+
this.id = entity?.id;
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
__decorate([
|
|
1486
|
+
string({
|
|
1487
|
+
omitForCreate: true,
|
|
1488
|
+
omitForUpdate: true,
|
|
1489
|
+
display: false,
|
|
1490
|
+
displayStyle: 'line',
|
|
1491
|
+
displayName: 'ID',
|
|
1492
|
+
required: true
|
|
1493
|
+
}),
|
|
1494
|
+
__metadata("design:type", String)
|
|
1495
|
+
], Entity.prototype, "id", void 0);
|
|
1496
|
+
|
|
1497
|
+
/**
|
|
1498
|
+
* The abstract BaseBuilder class.
|
|
1499
|
+
*/
|
|
1500
|
+
class BaseBuilder {
|
|
1501
|
+
data;
|
|
1502
|
+
inputData;
|
|
1503
|
+
constructor(data) {
|
|
1504
|
+
this.validateInput(data);
|
|
1505
|
+
this.inputData = data;
|
|
1506
|
+
this.data = this.generateBaseData(data);
|
|
1507
|
+
return this;
|
|
1508
|
+
}
|
|
1509
|
+
/**
|
|
1510
|
+
* Used to validate the user input in the constructor.
|
|
1511
|
+
*
|
|
1512
|
+
* @param data - The user input.
|
|
1513
|
+
*/
|
|
1514
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1515
|
+
validateInput(data) {
|
|
1516
|
+
// By default, no validation is done
|
|
1517
|
+
}
|
|
1518
|
+
/**
|
|
1519
|
+
* Sets the value for the given key if no user value was provided.
|
|
1520
|
+
*
|
|
1521
|
+
* @param key - The key to set the default value for.
|
|
1522
|
+
* @param value - The value to set when nothing was provided.
|
|
1523
|
+
* @returns The Builder.
|
|
1524
|
+
*/
|
|
1525
|
+
withDefault(key, value) {
|
|
1526
|
+
if (this.inputData == null || this.inputData[key] == null) {
|
|
1527
|
+
this.data[key] = value;
|
|
1528
|
+
}
|
|
1529
|
+
return this;
|
|
1530
|
+
}
|
|
1531
|
+
/**
|
|
1532
|
+
* Method used to get the final build value after applying all chaining.
|
|
1533
|
+
*
|
|
1534
|
+
* @returns The build value.
|
|
1535
|
+
*/
|
|
1536
|
+
getResult() {
|
|
1537
|
+
return this.data;
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
/**
|
|
1542
|
+
* The internal ConfirmDialogData. Requires all default values the user can leave out.
|
|
1706
1543
|
*/
|
|
1707
|
-
class
|
|
1544
|
+
class ConfirmDialogDataInternal {
|
|
1708
1545
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1709
|
-
|
|
1546
|
+
text;
|
|
1710
1547
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1711
|
-
|
|
1548
|
+
type;
|
|
1712
1549
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1713
|
-
|
|
1550
|
+
confirmButtonLabel;
|
|
1714
1551
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1715
|
-
|
|
1552
|
+
cancelButtonLabel;
|
|
1716
1553
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1717
|
-
|
|
1554
|
+
title;
|
|
1718
1555
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1719
|
-
|
|
1556
|
+
requireConfirmation;
|
|
1720
1557
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1721
|
-
|
|
1558
|
+
confirmationText;
|
|
1559
|
+
constructor(text, type, confirmButtonLabel, cancelButtonLabel, title, requireConfirmation, confirmationText) {
|
|
1560
|
+
this.text = text;
|
|
1561
|
+
this.type = type;
|
|
1562
|
+
this.confirmButtonLabel = confirmButtonLabel;
|
|
1563
|
+
this.cancelButtonLabel = cancelButtonLabel;
|
|
1564
|
+
this.title = title;
|
|
1565
|
+
this.requireConfirmation = requireConfirmation;
|
|
1566
|
+
this.confirmationText = confirmationText;
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
/**
|
|
1570
|
+
* The Builder for the ConfirmDialogData. Sets default values.
|
|
1571
|
+
*/
|
|
1572
|
+
class ConfirmDialogDataBuilder extends BaseBuilder {
|
|
1722
1573
|
constructor(data) {
|
|
1723
1574
|
super(data);
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
this
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1575
|
+
}
|
|
1576
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1577
|
+
generateBaseData(data) {
|
|
1578
|
+
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);
|
|
1579
|
+
}
|
|
1580
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1581
|
+
validateInput(data) {
|
|
1582
|
+
if (!data) {
|
|
1583
|
+
return;
|
|
1584
|
+
}
|
|
1585
|
+
if (data.requireConfirmation === true && !data.confirmationText) {
|
|
1586
|
+
// eslint-disable-next-line max-len
|
|
1587
|
+
throw new Error('Missing required Input data "confirmationText". You can only omit this value when "requireConfirmation" is false.');
|
|
1588
|
+
}
|
|
1589
|
+
if (data.requireConfirmation !== true && data.confirmationText) {
|
|
1590
|
+
throw new Error('The "confirmationText" will never be shown because "requireConfirmation" is not set to true');
|
|
1591
|
+
}
|
|
1592
|
+
if (data.type === 'info-only' && data.cancelButtonLabel) {
|
|
1593
|
+
throw new Error('The "cancelButtonLabel" will never be shown because "type" is set to "info-only"');
|
|
1594
|
+
}
|
|
1732
1595
|
}
|
|
1733
1596
|
}
|
|
1734
1597
|
|
|
1735
1598
|
/**
|
|
1736
|
-
*
|
|
1599
|
+
* The Dialog used whenever confirmation by the user is required (e.g. When the user tries to delete an entity).
|
|
1737
1600
|
*
|
|
1738
|
-
*
|
|
1739
|
-
* @returns The method that defines the metadata.
|
|
1601
|
+
* Can be customized with the MAT_DIALOG_DATA "inputData". Customization options are defined in "ConfirmDialogData".
|
|
1740
1602
|
*/
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1603
|
+
class NgxMatEntityConfirmDialogComponent {
|
|
1604
|
+
dialogRef;
|
|
1605
|
+
inputData;
|
|
1606
|
+
confirm = false;
|
|
1607
|
+
data;
|
|
1608
|
+
constructor(dialogRef, inputData) {
|
|
1609
|
+
this.dialogRef = dialogRef;
|
|
1610
|
+
this.inputData = inputData;
|
|
1611
|
+
}
|
|
1612
|
+
ngOnInit() {
|
|
1613
|
+
this.data = new ConfirmDialogDataBuilder(this.inputData).getResult();
|
|
1614
|
+
this.dialogRef.disableClose = true;
|
|
1615
|
+
}
|
|
1616
|
+
/**
|
|
1617
|
+
* Closes the dialog with true to signal that the action should be run.
|
|
1618
|
+
*/
|
|
1619
|
+
confirmAction() {
|
|
1620
|
+
this.dialogRef.close(true);
|
|
1621
|
+
}
|
|
1622
|
+
/**
|
|
1623
|
+
* Closes the dialog.
|
|
1624
|
+
*/
|
|
1625
|
+
cancel() {
|
|
1626
|
+
this.dialogRef.close(false);
|
|
1627
|
+
}
|
|
1628
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityConfirmDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
1629
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: NgxMatEntityConfirmDialogComponent, isStandalone: true, 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 type=\"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 type=\"button\" *ngIf=\"data.type !== 'delete'\" mat-raised-button (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button type=\"button\" *ngIf=\"data.type !== 'info-only'\" mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>", styles: [".checkbox-wrapper{min-height:50px;display:flex}.checkbox-wrapper>mat-checkbox{align-self:center}mat-dialog-actions{justify-content:space-between}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i4.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }] });
|
|
1630
|
+
}
|
|
1631
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityConfirmDialogComponent, decorators: [{
|
|
1632
|
+
type: Component,
|
|
1633
|
+
args: [{ selector: 'ngx-mat-entity-confirm-dialog', standalone: true, imports: [
|
|
1634
|
+
NgIf,
|
|
1635
|
+
NgFor,
|
|
1636
|
+
MatDialogModule,
|
|
1637
|
+
FormsModule,
|
|
1638
|
+
MatCheckboxModule,
|
|
1639
|
+
MatButtonModule
|
|
1640
|
+
], 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 type=\"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 type=\"button\" *ngIf=\"data.type !== 'delete'\" mat-raised-button (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button type=\"button\" *ngIf=\"data.type !== 'info-only'\" mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>", styles: [".checkbox-wrapper{min-height:50px;display:flex}.checkbox-wrapper>mat-checkbox{align-self:center}mat-dialog-actions{justify-content:space-between}\n"] }]
|
|
1641
|
+
}], ctorParameters: function () { return [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{
|
|
1642
|
+
type: Inject,
|
|
1643
|
+
args: [MAT_DIALOG_DATA]
|
|
1644
|
+
}] }]; } });
|
|
1645
|
+
|
|
1646
|
+
// eslint-disable-next-line jsdoc/require-jsdoc, @typescript-eslint/no-explicit-any
|
|
1647
|
+
function UnsavedChangesGuard(component) {
|
|
1648
|
+
return new Observable((obs) => {
|
|
1649
|
+
if (component.canDeactivate()) {
|
|
1650
|
+
obs.next(true);
|
|
1651
|
+
return;
|
|
1652
|
+
}
|
|
1653
|
+
component.openConfirmNavigationDialog().subscribe(v => {
|
|
1654
|
+
obs.next(v);
|
|
1655
|
+
});
|
|
1656
|
+
});
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
const defaultEditDataRoute = {
|
|
1660
|
+
loadComponent: () => Promise.resolve().then(function () { return editPage_component; }).then(m => m.NgxMatEntityEditPageComponent),
|
|
1661
|
+
title: 'Edit',
|
|
1662
|
+
path: 'entities:id',
|
|
1663
|
+
canDeactivate: [UnsavedChangesGuard]
|
|
1664
|
+
};
|
|
1665
|
+
|
|
1666
|
+
const NGX_VALIDATION_ERRORS_TOOLTIP_TITLE = new InjectionToken('Provider for the validation errors tooltip title.', {
|
|
1667
|
+
providedIn: 'root',
|
|
1668
|
+
factory: () => 'Validation Errors:'
|
|
1669
|
+
});
|
|
1670
|
+
/**
|
|
1671
|
+
* The default function that gets the validation errors tooltip content.
|
|
1672
|
+
*
|
|
1673
|
+
* @param validationErrors - All validation errors for which the tooltip content should be generated.
|
|
1674
|
+
* @returns A html string, containing a list of the name of each invalid property.
|
|
1675
|
+
*/
|
|
1676
|
+
function getValidationErrorsTooltipContent(validationErrors) {
|
|
1677
|
+
const title = inject(NGX_VALIDATION_ERRORS_TOOLTIP_TITLE);
|
|
1678
|
+
let res = `
|
|
1679
|
+
${title}
|
|
1680
|
+
<br>
|
|
1681
|
+
<ul style="margin-bottom: 0px; padding-left: 16px;">
|
|
1682
|
+
`;
|
|
1683
|
+
for (const error of validationErrors) {
|
|
1684
|
+
res = res.concat(`<li>${error.property}</li>`);
|
|
1685
|
+
}
|
|
1686
|
+
res = res.concat('</ul>');
|
|
1687
|
+
return res;
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
/**
|
|
1691
|
+
* A generic EntityService class.
|
|
1692
|
+
* Offers basic CRUD-functionality.
|
|
1693
|
+
* You should create a service for every Entity you have.
|
|
1694
|
+
* If you extend from this you need to make sure that the extended Service can be injected.
|
|
1695
|
+
*/
|
|
1696
|
+
class EntityService {
|
|
1697
|
+
http;
|
|
1698
|
+
/**
|
|
1699
|
+
* The route segment that comes before the id when editing an entity in a separate page.
|
|
1700
|
+
*/
|
|
1701
|
+
editBaseRoute = 'entities';
|
|
1702
|
+
/**
|
|
1703
|
+
* The key which holds the id value.
|
|
1704
|
+
*
|
|
1705
|
+
* @default 'id'
|
|
1706
|
+
*/
|
|
1707
|
+
idKey = 'id';
|
|
1708
|
+
/**
|
|
1709
|
+
* A subject of all the entity values.
|
|
1710
|
+
* Can be subscribed to when you want to do a specific thing whenever the entities change.
|
|
1711
|
+
*/
|
|
1712
|
+
entitiesSubject = new BehaviorSubject([]);
|
|
1713
|
+
/**
|
|
1714
|
+
* When frequently trying to find a single entity by an id (eg. When nesting relations)
|
|
1715
|
+
* you might send a lot of unnecessary requests.
|
|
1716
|
+
* Therefore the findById method tries to look in the already existing entities first,
|
|
1717
|
+
* IF the entities have been requested in the last READ_EXPIRATION_IN_MS milliseconds.
|
|
1718
|
+
*
|
|
1719
|
+
* @default 900000 (5 minutes)
|
|
1720
|
+
*/
|
|
1721
|
+
READ_EXPIRATION_IN_MS = 900000;
|
|
1722
|
+
/**
|
|
1723
|
+
* Gets the entities in an array from the internal entitiesSubject.
|
|
1724
|
+
*
|
|
1725
|
+
* @returns The current entities in form of an array.
|
|
1726
|
+
*/
|
|
1727
|
+
get entities() {
|
|
1728
|
+
return this.entitiesSubject.value;
|
|
1729
|
+
}
|
|
1730
|
+
lastRead;
|
|
1731
|
+
constructor(http) {
|
|
1732
|
+
this.http = http;
|
|
1733
|
+
}
|
|
1734
|
+
/**
|
|
1735
|
+
* Creates a new Entity and pushes it to the entities array.
|
|
1736
|
+
*
|
|
1737
|
+
* @param entity - The data of the entity to create.
|
|
1738
|
+
* All values that should be omitted will be removed from it inside this method.
|
|
1739
|
+
* @param baseUrl - The base url to send the post request to.
|
|
1740
|
+
* This can be used if you want to create an entity belonging to another, like "customers/{id}/invoices".
|
|
1741
|
+
* @returns A Promise of the created entity.
|
|
1742
|
+
*/
|
|
1743
|
+
async create(entity, baseUrl = this.baseUrl) {
|
|
1744
|
+
const body = EntityUtilities.getWithoutOmitCreateValues(entity);
|
|
1745
|
+
const filePropertyKeys = EntityUtilities.getFileProperties(entity);
|
|
1746
|
+
if (!filePropertyKeys.length) {
|
|
1747
|
+
return await this.createWithJson(body, baseUrl);
|
|
1748
|
+
}
|
|
1749
|
+
else {
|
|
1750
|
+
return await this.createWithFormData(body, filePropertyKeys, entity, baseUrl);
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
// TODO: Find a way to use blobs with jest
|
|
1754
|
+
/* istanbul ignore next */
|
|
1755
|
+
/**
|
|
1756
|
+
* Imports everything from the provided json file.
|
|
1757
|
+
*
|
|
1758
|
+
* @param file - The json file to import from.
|
|
1759
|
+
* @returns All entities that have been imported.
|
|
1760
|
+
*/
|
|
1761
|
+
async import(file) {
|
|
1762
|
+
const formData = new FormData();
|
|
1763
|
+
formData.append('import', file);
|
|
1764
|
+
const result = await firstValueFrom(this.http.post(`${this.baseUrl}/import`, formData));
|
|
1765
|
+
this.entities.push(...result);
|
|
1766
|
+
this.entitiesSubject.next(this.entities);
|
|
1767
|
+
return result;
|
|
1768
|
+
}
|
|
1769
|
+
// TODO: Find a way to use blobs with jest
|
|
1770
|
+
/* istanbul ignore next */
|
|
1771
|
+
/**
|
|
1772
|
+
* Creates the entity with form data when the entity contains files in contrast to creating it with a normal json body.
|
|
1773
|
+
* All file values are stored inside their respective property key and their name.
|
|
1774
|
+
* Form data is able to handle setting multiple files to the same key.
|
|
1775
|
+
*
|
|
1776
|
+
* @param body - The body Of the request.
|
|
1777
|
+
* @param filePropertyKeys - All property keys that are files and need to be added to the form data.
|
|
1778
|
+
* @param entity - The entity to create. This is needed in addition to the body because the body doesn't contain any metadata.
|
|
1779
|
+
* @param baseUrl - The base url to send the post request to.
|
|
1780
|
+
* This can be used if you want to create an entity belonging to another, like "customers/{id}/invoices".
|
|
1781
|
+
* @returns The created entity from the server.
|
|
1782
|
+
*/
|
|
1783
|
+
async createWithFormData(body, filePropertyKeys, entity, baseUrl = this.baseUrl) {
|
|
1784
|
+
const formData = new FormData();
|
|
1785
|
+
formData.append('body', JSON.stringify(LodashUtilities.omit(body, filePropertyKeys)));
|
|
1786
|
+
for (const key of filePropertyKeys) {
|
|
1787
|
+
if (EntityUtilities.getPropertyMetadata(entity, key, DecoratorTypes.FILE_DEFAULT).multiple) {
|
|
1788
|
+
const fileDataValues = body[key];
|
|
1789
|
+
for (const value of fileDataValues) {
|
|
1790
|
+
formData.append(key, (await FileUtilities.getFileData(value, this.http)).file, value.name);
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
else {
|
|
1794
|
+
const fileData = body[key];
|
|
1795
|
+
formData.append(key, (await FileUtilities.getFileData(fileData, this.http)).file, fileData.name);
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
const e = await firstValueFrom(this.http.post(baseUrl, formData));
|
|
1799
|
+
if (!e) {
|
|
1800
|
+
throw new Error(`
|
|
1801
|
+
The created entity was not returned in the response.
|
|
1802
|
+
If you want to provide a logic that allows that
|
|
1803
|
+
you need to override the create methods of this class.
|
|
1804
|
+
`);
|
|
1805
|
+
}
|
|
1806
|
+
this.entities.push(e);
|
|
1807
|
+
this.entitiesSubject.next(this.entities);
|
|
1808
|
+
return e;
|
|
1753
1809
|
}
|
|
1754
|
-
}
|
|
1755
|
-
|
|
1756
|
-
/**
|
|
1757
|
-
* A base Entity class with a builtin id.
|
|
1758
|
-
*/
|
|
1759
|
-
class Entity {
|
|
1760
1810
|
/**
|
|
1761
|
-
*
|
|
1811
|
+
* Creates the entity with a normal json body in contrast to creating it with form data when the entity contains files.
|
|
1812
|
+
*
|
|
1813
|
+
* @param body - The body Of the request.
|
|
1814
|
+
* @param baseUrl - The base url to send the post request to.
|
|
1815
|
+
* This can be used if you want to create an entity belonging to another, like "customers/{id}/invoices".
|
|
1816
|
+
* @returns The created entity from the server.
|
|
1762
1817
|
*/
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
required: true
|
|
1776
|
-
}),
|
|
1777
|
-
__metadata("design:type", String)
|
|
1778
|
-
], Entity.prototype, "id", void 0);
|
|
1779
|
-
|
|
1780
|
-
/**
|
|
1781
|
-
* The abstract BaseBuilder class.
|
|
1782
|
-
*/
|
|
1783
|
-
class BaseBuilder {
|
|
1784
|
-
data;
|
|
1785
|
-
inputData;
|
|
1786
|
-
constructor(data) {
|
|
1787
|
-
this.validateInput(data);
|
|
1788
|
-
this.inputData = data;
|
|
1789
|
-
this.data = this.generateBaseData(data);
|
|
1790
|
-
return this;
|
|
1818
|
+
async createWithJson(body, baseUrl = this.baseUrl) {
|
|
1819
|
+
const e = await firstValueFrom(this.http.post(baseUrl, body));
|
|
1820
|
+
if (!e) {
|
|
1821
|
+
throw new Error(`
|
|
1822
|
+
The created entity was not returned in the response.
|
|
1823
|
+
If you want to provide a logic that allows that
|
|
1824
|
+
you need to override the create methods of this class.
|
|
1825
|
+
`);
|
|
1826
|
+
}
|
|
1827
|
+
this.entities.push(e);
|
|
1828
|
+
this.entitiesSubject.next(this.entities);
|
|
1829
|
+
return e;
|
|
1791
1830
|
}
|
|
1792
1831
|
/**
|
|
1793
|
-
*
|
|
1832
|
+
* Gets all existing entities and pushes them to the entities array.
|
|
1794
1833
|
*
|
|
1795
|
-
* @param
|
|
1834
|
+
* @param baseUrl - The base url for the request. Defaults to the baseUrl on the service.
|
|
1835
|
+
* @returns A Promise of all received Entities.
|
|
1796
1836
|
*/
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1837
|
+
async read(baseUrl = this.baseUrl) {
|
|
1838
|
+
const e = await firstValueFrom(this.http.get(baseUrl));
|
|
1839
|
+
this.entitiesSubject.next(e);
|
|
1840
|
+
this.lastRead = new Date();
|
|
1841
|
+
return e;
|
|
1800
1842
|
}
|
|
1801
1843
|
/**
|
|
1802
|
-
*
|
|
1844
|
+
* Tries to find an entity with the given id.
|
|
1803
1845
|
*
|
|
1804
|
-
* @param
|
|
1805
|
-
* @
|
|
1806
|
-
* @returns The Builder.
|
|
1846
|
+
* @param id - The id of the entity to find.
|
|
1847
|
+
* @returns The found entity.
|
|
1807
1848
|
*/
|
|
1808
|
-
|
|
1809
|
-
if (this.
|
|
1810
|
-
this.
|
|
1849
|
+
async findById(id) {
|
|
1850
|
+
if (this.lastRead == null
|
|
1851
|
+
|| (new Date().getTime() - this.lastRead.getTime()) > this.READ_EXPIRATION_IN_MS) {
|
|
1852
|
+
return firstValueFrom(this.http.get(`${this.baseUrl}/${id}`));
|
|
1811
1853
|
}
|
|
1812
|
-
return this;
|
|
1854
|
+
return this.entities.find(e => e[this.idKey] === id) ?? firstValueFrom(this.http.get(`${this.baseUrl}/${id}`));
|
|
1813
1855
|
}
|
|
1814
1856
|
/**
|
|
1815
|
-
*
|
|
1857
|
+
* Updates a specific Entity.
|
|
1816
1858
|
*
|
|
1817
|
-
* @
|
|
1859
|
+
* @param entity - The updated Entity
|
|
1860
|
+
* All values that should be omitted will be removed from it inside this method.
|
|
1861
|
+
* @param entityPriorChanges - The current Entity.
|
|
1862
|
+
* It Is used to get changed values and only update them instead of sending the whole entity data.
|
|
1818
1863
|
*/
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
/**
|
|
1825
|
-
* The internal ConfirmDialogData. Requires all default values the user can leave out.
|
|
1826
|
-
*/
|
|
1827
|
-
class ConfirmDialogDataInternal {
|
|
1828
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1829
|
-
text;
|
|
1830
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1831
|
-
type;
|
|
1832
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1833
|
-
confirmButtonLabel;
|
|
1834
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1835
|
-
cancelButtonLabel;
|
|
1836
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1837
|
-
title;
|
|
1838
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1839
|
-
requireConfirmation;
|
|
1840
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1841
|
-
confirmationText;
|
|
1842
|
-
constructor(text, type, confirmButtonLabel, cancelButtonLabel, title, requireConfirmation, confirmationText) {
|
|
1843
|
-
this.text = text;
|
|
1844
|
-
this.type = type;
|
|
1845
|
-
this.confirmButtonLabel = confirmButtonLabel;
|
|
1846
|
-
this.cancelButtonLabel = cancelButtonLabel;
|
|
1847
|
-
this.title = title;
|
|
1848
|
-
this.requireConfirmation = requireConfirmation;
|
|
1849
|
-
this.confirmationText = confirmationText;
|
|
1850
|
-
}
|
|
1851
|
-
}
|
|
1852
|
-
/**
|
|
1853
|
-
* The Builder for the ConfirmDialogData. Sets default values.
|
|
1854
|
-
*/
|
|
1855
|
-
class ConfirmDialogDataBuilder extends BaseBuilder {
|
|
1856
|
-
constructor(data) {
|
|
1857
|
-
super(data);
|
|
1858
|
-
}
|
|
1859
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1860
|
-
generateBaseData(data) {
|
|
1861
|
-
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);
|
|
1862
|
-
}
|
|
1863
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1864
|
-
validateInput(data) {
|
|
1865
|
-
if (!data) {
|
|
1866
|
-
return;
|
|
1867
|
-
}
|
|
1868
|
-
if (data.requireConfirmation === true && !data.confirmationText) {
|
|
1869
|
-
// eslint-disable-next-line max-len
|
|
1870
|
-
throw new Error('Missing required Input data "confirmationText". You can only omit this value when "requireConfirmation" is false.');
|
|
1871
|
-
}
|
|
1872
|
-
if (data.requireConfirmation !== true && data.confirmationText) {
|
|
1873
|
-
throw new Error('The "confirmationText" will never be shown because "requireConfirmation" is not set to true');
|
|
1864
|
+
async update(entity, entityPriorChanges) {
|
|
1865
|
+
const filePropertyKeys = EntityUtilities.getFileProperties(entityPriorChanges);
|
|
1866
|
+
const body = await this.entityToUpdateRequestBody(entity, entityPriorChanges);
|
|
1867
|
+
if (!filePropertyKeys.length) {
|
|
1868
|
+
await this.updateWithJson(body, entityPriorChanges[this.idKey]);
|
|
1874
1869
|
}
|
|
1875
|
-
|
|
1876
|
-
|
|
1870
|
+
else {
|
|
1871
|
+
await this.updateWithFormData(body, filePropertyKeys, entity, entityPriorChanges[this.idKey]);
|
|
1877
1872
|
}
|
|
1878
1873
|
}
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
confirm = false;
|
|
1890
|
-
data;
|
|
1891
|
-
constructor(dialogRef, inputData) {
|
|
1892
|
-
this.dialogRef = dialogRef;
|
|
1893
|
-
this.inputData = inputData;
|
|
1874
|
+
/**
|
|
1875
|
+
* Builds the update request body from the given entity before and after its changes.
|
|
1876
|
+
*
|
|
1877
|
+
* @param entity - The entity with changed values.
|
|
1878
|
+
* @param entityPriorChanges - The entity before any changes.
|
|
1879
|
+
* @returns A partial of only the changed values.
|
|
1880
|
+
*/
|
|
1881
|
+
async entityToUpdateRequestBody(entity, entityPriorChanges) {
|
|
1882
|
+
const body = await EntityUtilities.getWithoutOmitUpdateValues(entity, entityPriorChanges, this.http);
|
|
1883
|
+
return LodashUtilities.omitBy(body, LodashUtilities.isNil);
|
|
1894
1884
|
}
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1885
|
+
// TODO: Find a way to use blobs with jest
|
|
1886
|
+
/* istanbul ignore next */
|
|
1887
|
+
/**
|
|
1888
|
+
* Updates the entity with form data when the entity contains files in contrast to creating it with a normal json body.
|
|
1889
|
+
* All file values are stored inside their respective property key and their name.
|
|
1890
|
+
* Form data is able to handle setting multiple files to the same key.
|
|
1891
|
+
*
|
|
1892
|
+
* @param body - The request body. Already contains only properties that have changed.
|
|
1893
|
+
* @param filePropertyKeys - The keys of all properties which are files and need to separately be appended to the form data.
|
|
1894
|
+
* @param entity - The original entity. Is needed to get the metadata of all the files.
|
|
1895
|
+
* @param id - The id of the entity to update.
|
|
1896
|
+
*/
|
|
1897
|
+
async updateWithFormData(body, filePropertyKeys, entity, id) {
|
|
1898
|
+
const formData = new FormData();
|
|
1899
|
+
formData.append('body', JSON.stringify(body));
|
|
1900
|
+
for (const key of filePropertyKeys) {
|
|
1901
|
+
if (EntityUtilities.getPropertyMetadata(entity, key, DecoratorTypes.FILE_DEFAULT).multiple) {
|
|
1902
|
+
const fileDataValues = body[key];
|
|
1903
|
+
for (const value of fileDataValues) {
|
|
1904
|
+
formData.append(key, (await FileUtilities.getFileData(value, this.http)).file, value.name);
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
else {
|
|
1908
|
+
const fileData = body[key];
|
|
1909
|
+
formData.append(key, (await FileUtilities.getFileData(fileData, this.http)).file, fileData.name);
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
const updatedEntity = await firstValueFrom(this.http.patch(`${this.baseUrl}/${id}`, formData));
|
|
1913
|
+
if (!updatedEntity) {
|
|
1914
|
+
// eslint-disable-next-line no-console
|
|
1915
|
+
console.warn('The updated entity was not returned in the response. Applying the changes from the request body.');
|
|
1916
|
+
for (const key in body) {
|
|
1917
|
+
this.entities[this.entities.findIndex(e => e[this.idKey] === id)][key]
|
|
1918
|
+
= body[key];
|
|
1919
|
+
}
|
|
1920
|
+
this.entitiesSubject.next(this.entities);
|
|
1921
|
+
return;
|
|
1922
|
+
}
|
|
1923
|
+
this.entities[this.entities.findIndex(e => e[this.idKey] === id)] = updatedEntity;
|
|
1924
|
+
this.entitiesSubject.next(this.entities);
|
|
1898
1925
|
}
|
|
1899
1926
|
/**
|
|
1900
|
-
*
|
|
1927
|
+
* Updates the entity with a normal json body in contrast to updating it with form data when the entity contains files.
|
|
1928
|
+
*
|
|
1929
|
+
* @param body - The body of the Request. Has already removed all unnecessary values.
|
|
1930
|
+
* @param id - The id of the entity to update.
|
|
1901
1931
|
*/
|
|
1902
|
-
|
|
1903
|
-
this.
|
|
1932
|
+
async updateWithJson(body, id) {
|
|
1933
|
+
const updatedEntity = await firstValueFrom(this.http.patch(`${this.baseUrl}/${id}`, LodashUtilities.omitBy(body, LodashUtilities.isNil)));
|
|
1934
|
+
if (!updatedEntity) {
|
|
1935
|
+
// eslint-disable-next-line no-console
|
|
1936
|
+
console.warn('The updated entity was not returned in the response. Applying the changes from the request body.');
|
|
1937
|
+
const foundEntity = this.entities[this.entities.findIndex(e => e[this.idKey] === id)];
|
|
1938
|
+
for (const key in body) {
|
|
1939
|
+
foundEntity[key]
|
|
1940
|
+
= body[key];
|
|
1941
|
+
}
|
|
1942
|
+
this.entitiesSubject.next(this.entities);
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
this.entities[this.entities.findIndex(e => e[this.idKey] === id)] = updatedEntity;
|
|
1946
|
+
this.entitiesSubject.next(this.entities);
|
|
1904
1947
|
}
|
|
1905
1948
|
/**
|
|
1906
|
-
*
|
|
1949
|
+
* Deletes a specific Entity.
|
|
1950
|
+
*
|
|
1951
|
+
* @param entity - The entity to delete.
|
|
1907
1952
|
*/
|
|
1908
|
-
|
|
1909
|
-
this.
|
|
1953
|
+
async delete(entity) {
|
|
1954
|
+
await firstValueFrom(this.http.delete(`${this.baseUrl}/${entity[this.idKey]}`));
|
|
1955
|
+
// the == comparison instead of === is to catch ids that are numbers.
|
|
1956
|
+
this.entities.splice(this.entities.findIndex(e => e[this.idKey] === entity[this.idKey]), 1);
|
|
1957
|
+
this.entitiesSubject.next(this.entities);
|
|
1910
1958
|
}
|
|
1911
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityConfirmDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
1912
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: NgxMatEntityConfirmDialogComponent, isStandalone: true, 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 type=\"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 type=\"button\" *ngIf=\"data.type !== 'delete'\" mat-raised-button (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button type=\"button\" *ngIf=\"data.type !== 'info-only'\" mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>", styles: [".checkbox-wrapper{min-height:50px;display:flex}.checkbox-wrapper>mat-checkbox{align-self:center}mat-dialog-actions{justify-content:space-between}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i4.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }] });
|
|
1913
|
-
}
|
|
1914
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityConfirmDialogComponent, decorators: [{
|
|
1915
|
-
type: Component,
|
|
1916
|
-
args: [{ selector: 'ngx-mat-entity-confirm-dialog', standalone: true, imports: [
|
|
1917
|
-
NgIf,
|
|
1918
|
-
NgFor,
|
|
1919
|
-
MatDialogModule,
|
|
1920
|
-
FormsModule,
|
|
1921
|
-
MatCheckboxModule,
|
|
1922
|
-
MatButtonModule
|
|
1923
|
-
], 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 type=\"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 type=\"button\" *ngIf=\"data.type !== 'delete'\" mat-raised-button (click)=\"confirmAction()\" [disabled]=\"data.requireConfirmation && !confirm\" class=\"confirm-button\">\n {{data.confirmButtonLabel}}\n </button>\n <button type=\"button\" *ngIf=\"data.type !== 'info-only'\" mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.cancelButtonLabel}}\n </button>\n</mat-dialog-actions>", styles: [".checkbox-wrapper{min-height:50px;display:flex}.checkbox-wrapper>mat-checkbox{align-self:center}mat-dialog-actions{justify-content:space-between}\n"] }]
|
|
1924
|
-
}], ctorParameters: function () { return [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{
|
|
1925
|
-
type: Inject,
|
|
1926
|
-
args: [MAT_DIALOG_DATA]
|
|
1927
|
-
}] }]; } });
|
|
1928
|
-
|
|
1929
|
-
// eslint-disable-next-line jsdoc/require-jsdoc, @typescript-eslint/no-explicit-any
|
|
1930
|
-
function UnsavedChangesGuard(component) {
|
|
1931
|
-
return new Observable((obs) => {
|
|
1932
|
-
if (component.canDeactivate()) {
|
|
1933
|
-
obs.next(true);
|
|
1934
|
-
return;
|
|
1935
|
-
}
|
|
1936
|
-
component.openConfirmNavigationDialog().subscribe(v => {
|
|
1937
|
-
obs.next(v);
|
|
1938
|
-
});
|
|
1939
|
-
});
|
|
1940
1959
|
}
|
|
1941
1960
|
|
|
1942
|
-
const defaultEditDataRoute = {
|
|
1943
|
-
loadComponent: () => Promise.resolve().then(function () { return editPage_component; }).then(m => m.NgxMatEntityEditPageComponent),
|
|
1944
|
-
title: 'Edit',
|
|
1945
|
-
path: 'entities:id',
|
|
1946
|
-
canDeactivate: [UnsavedChangesGuard]
|
|
1947
|
-
};
|
|
1948
|
-
|
|
1949
1961
|
/**
|
|
1950
|
-
*
|
|
1951
|
-
* Offers basic CRUD-functionality.
|
|
1952
|
-
* You should create a service for every Entity you have.
|
|
1953
|
-
* If you extend from this you need to make sure that the extended Service can be injected.
|
|
1962
|
+
* Contains HelperMethods around handling Validation of entities and properties.
|
|
1954
1963
|
*/
|
|
1955
|
-
class
|
|
1956
|
-
http;
|
|
1957
|
-
/**
|
|
1958
|
-
* The route segment that comes before the id when editing an entity in a separate page.
|
|
1959
|
-
*/
|
|
1960
|
-
editBaseRoute = 'entities';
|
|
1964
|
+
class ValidationUtilities {
|
|
1961
1965
|
/**
|
|
1962
|
-
*
|
|
1966
|
+
* Checks if the values on an entity are valid.
|
|
1967
|
+
* Also checks all the validators given by the metadata ("required", "maxLength" etc.).
|
|
1963
1968
|
*
|
|
1964
|
-
* @
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
/**
|
|
1968
|
-
* A subject of all the entity values.
|
|
1969
|
-
* Can be subscribed to when you want to do a specific thing whenever the entities change.
|
|
1969
|
+
* @param entity - The entity to validate.
|
|
1970
|
+
* @param omit - Whether to check for creating or editing validity.
|
|
1971
|
+
* @returns Whether or not the entity is valid.
|
|
1970
1972
|
*/
|
|
1971
|
-
|
|
1973
|
+
static isEntityValid(entity, omit) {
|
|
1974
|
+
return this.getEntityValidationErrors(entity, omit).length === 0;
|
|
1975
|
+
}
|
|
1972
1976
|
/**
|
|
1973
|
-
*
|
|
1974
|
-
* you might send a lot of unnecessary requests.
|
|
1975
|
-
* Therefore the findById method tries to look in the already existing entities first,
|
|
1976
|
-
* IF the entities have been requested in the last READ_EXPIRATION_IN_MS milliseconds.
|
|
1977
|
+
* Gets all validation errors on the given entity.
|
|
1977
1978
|
*
|
|
1978
|
-
* @
|
|
1979
|
+
* @param entity - The entity to validate.
|
|
1980
|
+
* @param omit - What keys not to check. An empty value means no keys are omitted.
|
|
1981
|
+
* @returns An array of validation errors on the provided entity.
|
|
1979
1982
|
*/
|
|
1980
|
-
|
|
1983
|
+
static getEntityValidationErrors(entity, omit) {
|
|
1984
|
+
const res = [];
|
|
1985
|
+
for (const key in entity) {
|
|
1986
|
+
const err = this.getPropertyValidationError(entity, key, omit);
|
|
1987
|
+
if (err) {
|
|
1988
|
+
res.push(err);
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
return res;
|
|
1992
|
+
}
|
|
1993
|
+
// /**
|
|
1994
|
+
// * Checks if a single property value is valid.
|
|
1995
|
+
// *
|
|
1996
|
+
// * @param entity - The entity where the property is from.
|
|
1997
|
+
// * @param key - The name of the property.
|
|
1998
|
+
// * @param omit - Whether to check if the given entity is valid for creation or updating.
|
|
1999
|
+
// * @returns Whether or not the property value is valid.
|
|
2000
|
+
// * @throws Throws when it extracts an unknown metadata type.
|
|
2001
|
+
// */
|
|
2002
|
+
// static isPropertyValid<EntityType extends BaseEntityType<EntityType>>(
|
|
2003
|
+
// entity: EntityType,
|
|
2004
|
+
// key: keyof EntityType,
|
|
2005
|
+
// omit?: 'create' | 'update'
|
|
2006
|
+
// ): boolean {
|
|
2007
|
+
// return this.getPropertyValidationError(entity, key, omit) == null;
|
|
2008
|
+
// }
|
|
1981
2009
|
/**
|
|
1982
|
-
*
|
|
2010
|
+
* Validates the property on the given entity with the given key.
|
|
1983
2011
|
*
|
|
1984
|
-
* @
|
|
2012
|
+
* @param entity - The entity on which the property to check is.
|
|
2013
|
+
* @param key - The key of the property to validate.
|
|
2014
|
+
* @param omit - What keys not to check. An empty value means no keys are omitted.
|
|
2015
|
+
* @returns A validation error when the property is not valid, undefined otherwise.
|
|
2016
|
+
* @throws When the type of the property is not known.
|
|
1985
2017
|
*/
|
|
1986
|
-
|
|
1987
|
-
|
|
2018
|
+
static getPropertyValidationError(entity, key, omit) {
|
|
2019
|
+
const type = EntityUtilities.getPropertyType(entity, key);
|
|
2020
|
+
const metadata = EntityUtilities.getPropertyMetadata(entity, key, type);
|
|
2021
|
+
if (metadata.omitForCreate && omit === 'create') {
|
|
2022
|
+
return undefined;
|
|
2023
|
+
}
|
|
2024
|
+
if (metadata.omitForUpdate && omit === 'update') {
|
|
2025
|
+
return undefined;
|
|
2026
|
+
}
|
|
2027
|
+
if (metadata.required(entity) && type !== DecoratorTypes.HAS_MANY) {
|
|
2028
|
+
if (entity[key] == null || entity[key] === '') {
|
|
2029
|
+
return {
|
|
2030
|
+
property: metadata.displayName,
|
|
2031
|
+
message: 'required'
|
|
2032
|
+
};
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
if (!metadata.required(entity)) {
|
|
2036
|
+
if (entity[key] == null || entity[key] === '') {
|
|
2037
|
+
return undefined;
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
switch (type) {
|
|
2041
|
+
case DecoratorTypes.BOOLEAN_DROPDOWN:
|
|
2042
|
+
break;
|
|
2043
|
+
case DecoratorTypes.BOOLEAN_CHECKBOX:
|
|
2044
|
+
case DecoratorTypes.BOOLEAN_TOGGLE:
|
|
2045
|
+
const entityBoolean = entity[key];
|
|
2046
|
+
const booleanMetadata = metadata;
|
|
2047
|
+
return this.getBooleanValidationError(entity, entityBoolean, booleanMetadata);
|
|
2048
|
+
case DecoratorTypes.STRING_DROPDOWN:
|
|
2049
|
+
break;
|
|
2050
|
+
case DecoratorTypes.STRING:
|
|
2051
|
+
case DecoratorTypes.STRING_AUTOCOMPLETE:
|
|
2052
|
+
const entityString = entity[key];
|
|
2053
|
+
const stringMetadata = metadata;
|
|
2054
|
+
return this.getStringValidationError(entityString, stringMetadata);
|
|
2055
|
+
case DecoratorTypes.STRING_TEXTBOX:
|
|
2056
|
+
const entityTextbox = entity[key];
|
|
2057
|
+
const textboxMetadata = metadata;
|
|
2058
|
+
return this.getTextboxValidationError(entityTextbox, textboxMetadata);
|
|
2059
|
+
case DecoratorTypes.STRING_PASSWORD:
|
|
2060
|
+
const entityPassword = entity[key];
|
|
2061
|
+
const passwordMetadata = metadata;
|
|
2062
|
+
const confirmPassword = ReflectUtilities.getMetadata(EntityUtilities.CONFIRM_PASSWORD_KEY, entity, key);
|
|
2063
|
+
return this.getPasswordValidationError(entityPassword, passwordMetadata, confirmPassword);
|
|
2064
|
+
case DecoratorTypes.NUMBER_DROPDOWN:
|
|
2065
|
+
// Because only valid values can be selected, this is always true when it has a value
|
|
2066
|
+
return undefined;
|
|
2067
|
+
case DecoratorTypes.NUMBER:
|
|
2068
|
+
case DecoratorTypes.NUMBER_SLIDER:
|
|
2069
|
+
const entityNumber = entity[key];
|
|
2070
|
+
const numberMetadata = metadata;
|
|
2071
|
+
return this.getNumberValidationError(entityNumber, numberMetadata);
|
|
2072
|
+
case DecoratorTypes.OBJECT:
|
|
2073
|
+
const entityObject = entity[key];
|
|
2074
|
+
for (const parameterKey in entityObject) {
|
|
2075
|
+
const value = entityObject[parameterKey];
|
|
2076
|
+
if (!metadata.omit.includes(parameterKey)
|
|
2077
|
+
&& !(!metadata.required(entity) && (value == null || value == ''))) {
|
|
2078
|
+
const err = this.getPropertyValidationError(entityObject, parameterKey, omit);
|
|
2079
|
+
if (err) {
|
|
2080
|
+
return {
|
|
2081
|
+
property: metadata.displayName,
|
|
2082
|
+
message: `${err.property} is invalid: ${err.message}`
|
|
2083
|
+
};
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
break;
|
|
2088
|
+
case DecoratorTypes.ARRAY_STRING_CHIPS:
|
|
2089
|
+
case DecoratorTypes.ARRAY_STRING_AUTOCOMPLETE_CHIPS:
|
|
2090
|
+
case DecoratorTypes.ARRAY_DATE:
|
|
2091
|
+
case DecoratorTypes.ARRAY_DATE_TIME:
|
|
2092
|
+
case DecoratorTypes.ARRAY_DATE_RANGE:
|
|
2093
|
+
case DecoratorTypes.ARRAY:
|
|
2094
|
+
const entityArray = entity[key];
|
|
2095
|
+
// eslint-disable-next-line max-len
|
|
2096
|
+
const arrayMetadata = metadata;
|
|
2097
|
+
if (arrayMetadata.required(entity) && !entityArray.length) {
|
|
2098
|
+
return {
|
|
2099
|
+
property: metadata.displayName,
|
|
2100
|
+
message: 'no items in array'
|
|
2101
|
+
};
|
|
2102
|
+
}
|
|
2103
|
+
break;
|
|
2104
|
+
case DecoratorTypes.DATE:
|
|
2105
|
+
const entityDate = new Date(entity[key]);
|
|
2106
|
+
const dateMetadata = metadata;
|
|
2107
|
+
return this.getDateValidationError(entityDate, dateMetadata);
|
|
2108
|
+
case DecoratorTypes.DATE_RANGE:
|
|
2109
|
+
const entityDateRange = LodashUtilities.cloneDeep(entity[key]);
|
|
2110
|
+
const dateRangeMetadata = metadata;
|
|
2111
|
+
return this.getDateRangeValidationError(entity, entityDateRange, dateRangeMetadata);
|
|
2112
|
+
case DecoratorTypes.DATE_TIME:
|
|
2113
|
+
const entityDateTime = new Date(entity[key]);
|
|
2114
|
+
const dateTimeMetadata = metadata;
|
|
2115
|
+
const hasTime = ReflectUtilities.hasMetadata(EntityUtilities.TIME_KEY, entity, key);
|
|
2116
|
+
return this.getDateTimeValidationError(entityDateTime, dateTimeMetadata, hasTime);
|
|
2117
|
+
case DecoratorTypes.FILE_DEFAULT:
|
|
2118
|
+
case DecoratorTypes.FILE_IMAGE:
|
|
2119
|
+
const entityFile = entity[key];
|
|
2120
|
+
const entityFileMetadata = metadata;
|
|
2121
|
+
return this.getFileDataValidationError(entityFile, entityFileMetadata);
|
|
2122
|
+
case DecoratorTypes.REFERENCES_MANY:
|
|
2123
|
+
case DecoratorTypes.REFERENCES_ONE:
|
|
2124
|
+
case DecoratorTypes.HAS_MANY:
|
|
2125
|
+
break;
|
|
2126
|
+
case DecoratorTypes.CUSTOM:
|
|
2127
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, max-len
|
|
2128
|
+
const customMetadata = metadata;
|
|
2129
|
+
if (!customMetadata.isValid(entity[key], omit)) {
|
|
2130
|
+
return {
|
|
2131
|
+
property: metadata.displayName,
|
|
2132
|
+
message: 'invalid'
|
|
2133
|
+
};
|
|
2134
|
+
}
|
|
2135
|
+
break;
|
|
2136
|
+
default:
|
|
2137
|
+
throw new Error(`Could not validate the input because the DecoratorType ${type} is not known`);
|
|
2138
|
+
}
|
|
2139
|
+
return undefined;
|
|
1988
2140
|
}
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
2141
|
+
static getBooleanValidationError(entity, value, metadata) {
|
|
2142
|
+
if (metadata.required(entity) && !value) {
|
|
2143
|
+
return {
|
|
2144
|
+
property: metadata.displayName,
|
|
2145
|
+
message: 'not selected'
|
|
2146
|
+
};
|
|
2147
|
+
}
|
|
2148
|
+
return undefined;
|
|
1992
2149
|
}
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2150
|
+
static getStringValidationError(value, metadata) {
|
|
2151
|
+
if (metadata.maxLength && value.length > metadata.maxLength) {
|
|
2152
|
+
return {
|
|
2153
|
+
property: metadata.displayName,
|
|
2154
|
+
message: `needs to be smaller than ${metadata.maxLength} characters`
|
|
2155
|
+
};
|
|
2156
|
+
}
|
|
2157
|
+
if (metadata.minLength && value.length < metadata.minLength) {
|
|
2158
|
+
return {
|
|
2159
|
+
property: metadata.displayName,
|
|
2160
|
+
message: `needs to be bigger than ${metadata.minLength} characters`
|
|
2161
|
+
};
|
|
2162
|
+
}
|
|
2163
|
+
if (metadata.regex && !value.match(metadata.regex)) {
|
|
2164
|
+
return {
|
|
2165
|
+
property: metadata.displayName,
|
|
2166
|
+
message: 'invalid'
|
|
2167
|
+
};
|
|
2168
|
+
}
|
|
2169
|
+
return undefined;
|
|
2170
|
+
}
|
|
2171
|
+
static getTextboxValidationError(value, metadata) {
|
|
2172
|
+
if (metadata.maxLength && value.length > metadata.maxLength) {
|
|
2173
|
+
return {
|
|
2174
|
+
property: metadata.displayName,
|
|
2175
|
+
message: `needs to be smaller than ${metadata.maxLength} characters`
|
|
2176
|
+
};
|
|
2177
|
+
}
|
|
2178
|
+
if (metadata.minLength && value.length < metadata.minLength) {
|
|
2179
|
+
return {
|
|
2180
|
+
property: metadata.displayName,
|
|
2181
|
+
message: `needs to be bigger than ${metadata.minLength} characters`
|
|
2182
|
+
};
|
|
2183
|
+
}
|
|
2184
|
+
return undefined;
|
|
2185
|
+
}
|
|
2186
|
+
static getPasswordValidationError(value, metadata, confirmPassword) {
|
|
2187
|
+
if (value !== confirmPassword) {
|
|
2188
|
+
return {
|
|
2189
|
+
property: metadata.displayName,
|
|
2190
|
+
message: 'passwords need to match'
|
|
2191
|
+
};
|
|
2192
|
+
}
|
|
2193
|
+
if (metadata.maxLength && value.length > metadata.maxLength) {
|
|
2194
|
+
return {
|
|
2195
|
+
property: metadata.displayName,
|
|
2196
|
+
message: `needs to be smaller than ${metadata.maxLength} characters`
|
|
2197
|
+
};
|
|
2198
|
+
}
|
|
2199
|
+
if (metadata.minLength && value.length < metadata.minLength) {
|
|
2200
|
+
return {
|
|
2201
|
+
property: metadata.displayName,
|
|
2202
|
+
message: `needs to be bigger than ${metadata.minLength} characters`
|
|
2203
|
+
};
|
|
2204
|
+
}
|
|
2205
|
+
if (metadata.regex && !value.match(metadata.regex)) {
|
|
2206
|
+
return {
|
|
2207
|
+
property: metadata.displayName,
|
|
2208
|
+
message: 'invalid'
|
|
2209
|
+
};
|
|
2210
|
+
}
|
|
2211
|
+
return undefined;
|
|
2212
|
+
}
|
|
2213
|
+
static getNumberValidationError(value, metadata) {
|
|
2214
|
+
if (metadata.max && value > metadata.max) {
|
|
2215
|
+
return {
|
|
2216
|
+
property: metadata.displayName,
|
|
2217
|
+
message: `needs to be smaller than ${metadata.max}`
|
|
2218
|
+
};
|
|
2219
|
+
}
|
|
2220
|
+
if (metadata.min && value < metadata.min) {
|
|
2221
|
+
return {
|
|
2222
|
+
property: metadata.displayName,
|
|
2223
|
+
message: `needs to be bigger than ${metadata.min}`
|
|
2224
|
+
};
|
|
2225
|
+
}
|
|
2226
|
+
return undefined;
|
|
2227
|
+
}
|
|
2228
|
+
static getDateValidationError(value, metadata) {
|
|
2229
|
+
if (metadata.min && value.getTime() < metadata.min(value).getTime()) {
|
|
2230
|
+
return {
|
|
2231
|
+
property: metadata.displayName,
|
|
2232
|
+
message: `needs to be after ${formatDate(metadata.min(value))}`
|
|
2233
|
+
};
|
|
2234
|
+
}
|
|
2235
|
+
if (metadata.max && value.getTime() > metadata.max(value).getTime()) {
|
|
2236
|
+
return {
|
|
2237
|
+
property: metadata.displayName,
|
|
2238
|
+
message: `needs to be before ${formatDate(metadata.max(value))}`
|
|
2239
|
+
};
|
|
2007
2240
|
}
|
|
2008
|
-
|
|
2009
|
-
return
|
|
2241
|
+
if (metadata.filter && !metadata.filter(value)) {
|
|
2242
|
+
return {
|
|
2243
|
+
property: metadata.displayName,
|
|
2244
|
+
message: 'invalid'
|
|
2245
|
+
};
|
|
2010
2246
|
}
|
|
2247
|
+
return undefined;
|
|
2011
2248
|
}
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2249
|
+
static getDateRangeValidationError(entity, value, metadata) {
|
|
2250
|
+
if (metadata.required(entity)) {
|
|
2251
|
+
if (value.start == null || value.end == null || value.values == null) {
|
|
2252
|
+
return {
|
|
2253
|
+
property: metadata.displayName,
|
|
2254
|
+
message: 'required'
|
|
2255
|
+
};
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
value.start = new Date(value.start);
|
|
2259
|
+
value.end = new Date(value.end);
|
|
2260
|
+
if (metadata.minStart && value.start.getTime() < metadata.minStart(value.start).getTime()) {
|
|
2261
|
+
return {
|
|
2262
|
+
property: metadata.displayName,
|
|
2263
|
+
message: `start date needs to be after ${formatDate(metadata.minStart(value.start))}`
|
|
2264
|
+
};
|
|
2265
|
+
}
|
|
2266
|
+
if (metadata.maxStart && value.start.getTime() > metadata.maxStart(value.start).getTime()) {
|
|
2267
|
+
return {
|
|
2268
|
+
property: metadata.displayName,
|
|
2269
|
+
message: `start date needs to be before ${formatDate(metadata.maxStart(value.start))}`
|
|
2270
|
+
};
|
|
2271
|
+
}
|
|
2272
|
+
if (metadata.minEnd && value.end.getTime() < metadata.minEnd(value.end).getTime()) {
|
|
2273
|
+
return {
|
|
2274
|
+
property: metadata.displayName,
|
|
2275
|
+
message: `end date needs to be after ${formatDate(metadata.minEnd(value.end))}`
|
|
2276
|
+
};
|
|
2277
|
+
}
|
|
2278
|
+
if (metadata.maxEnd && value.end.getTime() > metadata.maxEnd(value.end).getTime()) {
|
|
2279
|
+
return {
|
|
2280
|
+
property: metadata.displayName,
|
|
2281
|
+
message: `end date needs to be before ${formatDate(metadata.maxEnd(value.end))}`
|
|
2282
|
+
};
|
|
2283
|
+
}
|
|
2284
|
+
if (metadata.filter) {
|
|
2285
|
+
if (!metadata.filter(value.start)) {
|
|
2286
|
+
return {
|
|
2287
|
+
property: metadata.displayName,
|
|
2288
|
+
message: 'start date invalid'
|
|
2289
|
+
};
|
|
2290
|
+
}
|
|
2291
|
+
if (!metadata.filter(value.end)) {
|
|
2292
|
+
return {
|
|
2293
|
+
property: metadata.displayName,
|
|
2294
|
+
message: 'end date invalid'
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
for (const date of value.values) {
|
|
2298
|
+
if (!metadata.filter(date)) {
|
|
2299
|
+
return {
|
|
2300
|
+
property: metadata.displayName,
|
|
2301
|
+
message: `value ${formatDate(date)} invalid`
|
|
2302
|
+
};
|
|
2050
2303
|
}
|
|
2051
2304
|
}
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2305
|
+
}
|
|
2306
|
+
return undefined;
|
|
2307
|
+
}
|
|
2308
|
+
static getDateTimeValidationError(value, metadata, hasTime) {
|
|
2309
|
+
if (!hasTime) {
|
|
2310
|
+
return {
|
|
2311
|
+
property: metadata.displayName,
|
|
2312
|
+
message: 'no time'
|
|
2313
|
+
};
|
|
2314
|
+
}
|
|
2315
|
+
if (metadata.minDate && value.getTime() < metadata.minDate(value).getTime()) {
|
|
2316
|
+
return {
|
|
2317
|
+
property: metadata.displayName,
|
|
2318
|
+
message: `date needs to be after ${formatDate(metadata.minDate(value))}`
|
|
2319
|
+
};
|
|
2320
|
+
}
|
|
2321
|
+
if (metadata.maxDate && value.getTime() > metadata.maxDate(value).getTime()) {
|
|
2322
|
+
return {
|
|
2323
|
+
property: metadata.displayName,
|
|
2324
|
+
message: `date needs to be before ${formatDate(metadata.maxDate(value))}`
|
|
2325
|
+
};
|
|
2326
|
+
}
|
|
2327
|
+
if (metadata.filterDate && !metadata.filterDate(value)) {
|
|
2328
|
+
return {
|
|
2329
|
+
property: metadata.displayName,
|
|
2330
|
+
message: 'invalid date'
|
|
2331
|
+
};
|
|
2332
|
+
}
|
|
2333
|
+
const time = DateUtilities.getTimeFromDate(value);
|
|
2334
|
+
if (metadata.minTime) {
|
|
2335
|
+
const minTime = metadata.minTime(value);
|
|
2336
|
+
if (!(time.hours > minTime.hours
|
|
2337
|
+
|| (time.hours === minTime.hours
|
|
2338
|
+
&& time.minutes >= minTime.minutes))) {
|
|
2339
|
+
return {
|
|
2340
|
+
property: metadata.displayName,
|
|
2341
|
+
message: `time needs to be after ${minTime.hours}:${minTime.minutes}`
|
|
2342
|
+
};
|
|
2055
2343
|
}
|
|
2056
2344
|
}
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2345
|
+
if (metadata.maxTime) {
|
|
2346
|
+
const maxTime = metadata.maxTime(value);
|
|
2347
|
+
if (!(time.hours < maxTime.hours
|
|
2348
|
+
|| (time.hours === maxTime.hours
|
|
2349
|
+
&& time.minutes <= maxTime.minutes))) {
|
|
2350
|
+
return {
|
|
2351
|
+
property: metadata.displayName,
|
|
2352
|
+
message: `time needs to be before ${maxTime.hours}:${maxTime.minutes}`
|
|
2353
|
+
};
|
|
2354
|
+
}
|
|
2064
2355
|
}
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
* Creates the entity with a normal json body in contrast to creating it with form data when the entity contains files.
|
|
2071
|
-
*
|
|
2072
|
-
* @param body - The body Of the request.
|
|
2073
|
-
* @param baseUrl - The base url to send the post request to.
|
|
2074
|
-
* This can be used if you want to create an entity belonging to another, like "customers/{id}/invoices".
|
|
2075
|
-
* @returns The created entity from the server.
|
|
2076
|
-
*/
|
|
2077
|
-
async createWithJson(body, baseUrl = this.baseUrl) {
|
|
2078
|
-
const e = await firstValueFrom(this.http.post(baseUrl, body));
|
|
2079
|
-
if (!e) {
|
|
2080
|
-
throw new Error(`
|
|
2081
|
-
The created entity was not returned in the response.
|
|
2082
|
-
If you want to provide a logic that allows that
|
|
2083
|
-
you need to override the create methods of this class.
|
|
2084
|
-
`);
|
|
2356
|
+
if (metadata.filterTime && !metadata.filterTime(time)) {
|
|
2357
|
+
return {
|
|
2358
|
+
property: metadata.displayName,
|
|
2359
|
+
message: 'invalid time'
|
|
2360
|
+
};
|
|
2085
2361
|
}
|
|
2086
|
-
|
|
2087
|
-
this.entitiesSubject.next(this.entities);
|
|
2088
|
-
return e;
|
|
2089
|
-
}
|
|
2090
|
-
/**
|
|
2091
|
-
* Gets all existing entities and pushes them to the entities array.
|
|
2092
|
-
*
|
|
2093
|
-
* @param baseUrl - The base url for the request. Defaults to the baseUrl on the service.
|
|
2094
|
-
* @returns A Promise of all received Entities.
|
|
2095
|
-
*/
|
|
2096
|
-
async read(baseUrl = this.baseUrl) {
|
|
2097
|
-
const e = await firstValueFrom(this.http.get(baseUrl));
|
|
2098
|
-
this.entitiesSubject.next(e);
|
|
2099
|
-
this.lastRead = new Date();
|
|
2100
|
-
return e;
|
|
2362
|
+
return undefined;
|
|
2101
2363
|
}
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2364
|
+
static getFileDataValidationError(value, metadata) {
|
|
2365
|
+
const files = metadata.multiple ? value : [value];
|
|
2366
|
+
let fileSizeTotal = 0;
|
|
2367
|
+
for (const file of files) {
|
|
2368
|
+
if (!file.name || !file.file && !file.url) {
|
|
2369
|
+
return {
|
|
2370
|
+
property: metadata.displayName,
|
|
2371
|
+
message: 'invalid'
|
|
2372
|
+
};
|
|
2373
|
+
}
|
|
2374
|
+
if (!FileUtilities.isMimeTypeValid(file.type, metadata.allowedMimeTypes)) {
|
|
2375
|
+
return {
|
|
2376
|
+
property: metadata.displayName,
|
|
2377
|
+
message: `mimetype needs to be one of ${metadata.allowedMimeTypes}`
|
|
2378
|
+
};
|
|
2379
|
+
}
|
|
2380
|
+
if (FileUtilities.transformToMegaBytes(file.size, 'B') > metadata.maxSize) {
|
|
2381
|
+
return {
|
|
2382
|
+
property: metadata.displayName,
|
|
2383
|
+
message: `file needs to be smaller than ${metadata.maxSize} MB`
|
|
2384
|
+
};
|
|
2385
|
+
}
|
|
2386
|
+
fileSizeTotal += file.size;
|
|
2387
|
+
if (FileUtilities.transformToMegaBytes(fileSizeTotal, 'B') > metadata.maxSizeTotal) {
|
|
2388
|
+
return {
|
|
2389
|
+
property: metadata.displayName,
|
|
2390
|
+
message: `The size of all files combined needs to be smaller than ${metadata.maxSizeTotal}`
|
|
2391
|
+
};
|
|
2392
|
+
}
|
|
2112
2393
|
}
|
|
2113
|
-
return
|
|
2394
|
+
return undefined;
|
|
2114
2395
|
}
|
|
2396
|
+
}
|
|
2397
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
2398
|
+
function padTo2Digits(num) {
|
|
2399
|
+
return num.toString().padStart(2, '0');
|
|
2400
|
+
}
|
|
2401
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
2402
|
+
function formatDate(date) {
|
|
2403
|
+
return [
|
|
2404
|
+
padTo2Digits(date.getDate()),
|
|
2405
|
+
padTo2Digits(date.getMonth() + 1),
|
|
2406
|
+
date.getFullYear()
|
|
2407
|
+
].join('/');
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
/**
|
|
2411
|
+
* Adds drag and drop functionality to an element.
|
|
2412
|
+
*/
|
|
2413
|
+
class DragDropDirective {
|
|
2115
2414
|
/**
|
|
2116
|
-
*
|
|
2117
|
-
*
|
|
2118
|
-
* @param entity - The updated Entity
|
|
2119
|
-
* All values that should be omitted will be removed from it inside this method.
|
|
2120
|
-
* @param entityPriorChanges - The current Entity.
|
|
2121
|
-
* It Is used to get changed values and only update them instead of sending the whole entity data.
|
|
2415
|
+
* Emits the dropped files to the parent.
|
|
2122
2416
|
*/
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
const body = await this.entityToUpdateRequestBody(entity, entityPriorChanges);
|
|
2126
|
-
if (!filePropertyKeys.length) {
|
|
2127
|
-
await this.updateWithJson(body, entityPriorChanges[this.idKey]);
|
|
2128
|
-
}
|
|
2129
|
-
else {
|
|
2130
|
-
await this.updateWithFormData(body, filePropertyKeys, entity, entityPriorChanges[this.idKey]);
|
|
2131
|
-
}
|
|
2132
|
-
}
|
|
2417
|
+
files = new EventEmitter();
|
|
2418
|
+
constructor() { }
|
|
2133
2419
|
/**
|
|
2134
|
-
*
|
|
2420
|
+
* Prevents the event default.
|
|
2135
2421
|
*
|
|
2136
|
-
* @param
|
|
2137
|
-
* @param entityPriorChanges - The entity before any changes.
|
|
2138
|
-
* @returns A partial of only the changed values.
|
|
2422
|
+
* @param evt - The Event when dragged files hover over the parent.
|
|
2139
2423
|
*/
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2424
|
+
onDragOver(evt) {
|
|
2425
|
+
evt.preventDefault();
|
|
2426
|
+
evt.stopPropagation();
|
|
2143
2427
|
}
|
|
2144
|
-
// TODO: Find a way to use blobs with jest
|
|
2145
|
-
/* istanbul ignore next */
|
|
2146
2428
|
/**
|
|
2147
|
-
*
|
|
2148
|
-
* All file values are stored inside their respective property key and their name.
|
|
2149
|
-
* Form data is able to handle setting multiple files to the same key.
|
|
2429
|
+
* Prevents the event default.
|
|
2150
2430
|
*
|
|
2151
|
-
* @param
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
const fileData = body[key];
|
|
2168
|
-
formData.append(key, (await FileUtilities.getFileData(fileData, this.http)).file, fileData.name);
|
|
2169
|
-
}
|
|
2170
|
-
}
|
|
2171
|
-
const updatedEntity = await firstValueFrom(this.http.patch(`${this.baseUrl}/${id}`, formData));
|
|
2172
|
-
if (!updatedEntity) {
|
|
2173
|
-
// eslint-disable-next-line no-console
|
|
2174
|
-
console.warn('The updated entity was not returned in the response. Applying the changes from the request body.');
|
|
2175
|
-
for (const key in body) {
|
|
2176
|
-
this.entities[this.entities.findIndex(e => e[this.idKey] === id)][key]
|
|
2177
|
-
= body[key];
|
|
2178
|
-
}
|
|
2179
|
-
this.entitiesSubject.next(this.entities);
|
|
2180
|
-
return;
|
|
2431
|
+
* @param evt - The Event when dragged files leave the parent.
|
|
2432
|
+
*/
|
|
2433
|
+
onDragLeave(evt) {
|
|
2434
|
+
evt.preventDefault();
|
|
2435
|
+
evt.stopPropagation();
|
|
2436
|
+
}
|
|
2437
|
+
/**
|
|
2438
|
+
* Prevents the event default and emits the dropped files with the output.
|
|
2439
|
+
*
|
|
2440
|
+
* @param evt - The Event when files are dropped.
|
|
2441
|
+
*/
|
|
2442
|
+
onDrop(evt) {
|
|
2443
|
+
evt.preventDefault();
|
|
2444
|
+
evt.stopPropagation();
|
|
2445
|
+
if (evt.dataTransfer && evt.dataTransfer.files.length > 0) {
|
|
2446
|
+
this.files.emit(Array.from(evt.dataTransfer.files));
|
|
2181
2447
|
}
|
|
2182
|
-
|
|
2183
|
-
|
|
2448
|
+
}
|
|
2449
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: DragDropDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2450
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.0", type: DragDropDirective, selector: "[dragDrop]", outputs: { files: "files" }, host: { listeners: { "dragover": "onDragOver($event)", "dragleave": "onDragLeave($event)", "drop": "onDrop($event)" } }, ngImport: i0 });
|
|
2451
|
+
}
|
|
2452
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: DragDropDirective, decorators: [{
|
|
2453
|
+
type: Directive,
|
|
2454
|
+
args: [{
|
|
2455
|
+
selector: '[dragDrop]'
|
|
2456
|
+
}]
|
|
2457
|
+
}], ctorParameters: function () { return []; }, propDecorators: { files: [{
|
|
2458
|
+
type: Output
|
|
2459
|
+
}], onDragOver: [{
|
|
2460
|
+
type: HostListener,
|
|
2461
|
+
args: ['dragover', ['$event']]
|
|
2462
|
+
}], onDragLeave: [{
|
|
2463
|
+
type: HostListener,
|
|
2464
|
+
args: ['dragleave', ['$event']]
|
|
2465
|
+
}], onDrop: [{
|
|
2466
|
+
type: HostListener,
|
|
2467
|
+
args: ['drop', ['$event']]
|
|
2468
|
+
}] } });
|
|
2469
|
+
|
|
2470
|
+
/**
|
|
2471
|
+
* A directive that only allows number inputs.
|
|
2472
|
+
*/
|
|
2473
|
+
class NumberDirective {
|
|
2474
|
+
el;
|
|
2475
|
+
constructor(el) {
|
|
2476
|
+
this.el = el;
|
|
2184
2477
|
}
|
|
2185
2478
|
/**
|
|
2186
|
-
*
|
|
2479
|
+
* Prevents the default event when a key is pressed that is not a valid number, eg. 'A', 'B', 'C', 'D' etc.
|
|
2187
2480
|
*
|
|
2188
|
-
* @param
|
|
2189
|
-
* @param id - The id of the entity to update.
|
|
2481
|
+
* @param e - The keydown event from the user.
|
|
2190
2482
|
*/
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
//
|
|
2195
|
-
|
|
2196
|
-
const foundEntity = this.entities[this.entities.findIndex(e => e[this.idKey] === id)];
|
|
2197
|
-
for (const key in body) {
|
|
2198
|
-
foundEntity[key]
|
|
2199
|
-
= body[key];
|
|
2200
|
-
}
|
|
2201
|
-
this.entitiesSubject.next(this.entities);
|
|
2483
|
+
onKeyDown(e) {
|
|
2484
|
+
if (!isNaN(parseInt(e.key))
|
|
2485
|
+
|| ['.', ',', 'Escape', 'Enter', 'Delete', 'Backspace', 'Home', 'End', 'Left', 'Right', 'Tab'].includes(e.key)
|
|
2486
|
+
|| (e.ctrlKey || e.metaKey) // && ['a', 'c', 'v', 'x', 'z'].includes(e.key)
|
|
2487
|
+
) {
|
|
2202
2488
|
return;
|
|
2203
2489
|
}
|
|
2204
|
-
|
|
2205
|
-
this.entitiesSubject.next(this.entities);
|
|
2490
|
+
e.preventDefault();
|
|
2206
2491
|
}
|
|
2492
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NumberDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
2493
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.0", type: NumberDirective, isStandalone: true, selector: "[number]", host: { listeners: { "keydown": "onKeyDown($event)" } }, ngImport: i0 });
|
|
2494
|
+
}
|
|
2495
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NumberDirective, decorators: [{
|
|
2496
|
+
type: Directive,
|
|
2497
|
+
args: [{
|
|
2498
|
+
selector: '[number]',
|
|
2499
|
+
standalone: true
|
|
2500
|
+
}]
|
|
2501
|
+
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { onKeyDown: [{
|
|
2502
|
+
type: HostListener,
|
|
2503
|
+
args: ['keydown', ['$event']]
|
|
2504
|
+
}] } });
|
|
2505
|
+
|
|
2506
|
+
/**
|
|
2507
|
+
* A directive that validates if a given password matches the control value.
|
|
2508
|
+
*/
|
|
2509
|
+
class PasswordMatchValidatorDirective {
|
|
2207
2510
|
/**
|
|
2208
|
-
*
|
|
2209
|
-
*
|
|
2210
|
-
* @param entity - The entity to delete.
|
|
2511
|
+
* The password that the control value should be matched against.
|
|
2211
2512
|
*/
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
this.
|
|
2513
|
+
passwordMatch;
|
|
2514
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
2515
|
+
validate(control) {
|
|
2516
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
2517
|
+
return this.passwordMatch == control.value ? null : { passwordMatch: { value: control.value } };
|
|
2217
2518
|
}
|
|
2519
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: PasswordMatchValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2520
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.0", type: PasswordMatchValidatorDirective, isStandalone: true, selector: "[passwordMatch]", inputs: { passwordMatch: "passwordMatch" }, providers: [{ provide: NG_VALIDATORS, useExisting: PasswordMatchValidatorDirective, multi: true }], ngImport: i0 });
|
|
2218
2521
|
}
|
|
2522
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: PasswordMatchValidatorDirective, decorators: [{
|
|
2523
|
+
type: Directive,
|
|
2524
|
+
args: [{
|
|
2525
|
+
selector: '[passwordMatch]',
|
|
2526
|
+
providers: [{ provide: NG_VALIDATORS, useExisting: PasswordMatchValidatorDirective, multi: true }],
|
|
2527
|
+
standalone: true
|
|
2528
|
+
}]
|
|
2529
|
+
}], propDecorators: { passwordMatch: [{
|
|
2530
|
+
type: Input
|
|
2531
|
+
}] } });
|
|
2219
2532
|
|
|
2220
2533
|
/* eslint-disable @angular-eslint/component-selector */
|
|
2221
2534
|
/**
|
|
@@ -2361,6 +2674,7 @@ class NgxMatEntityBaseInputComponent {
|
|
|
2361
2674
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
2362
2675
|
set propertyValue(value) {
|
|
2363
2676
|
this.entity[this.key] = value;
|
|
2677
|
+
this.metadata.change?.(this.entity);
|
|
2364
2678
|
}
|
|
2365
2679
|
/**
|
|
2366
2680
|
* The metadata of the property.
|
|
@@ -2573,7 +2887,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
2573
2887
|
|
|
2574
2888
|
/* eslint-disable jsdoc/require-jsdoc */
|
|
2575
2889
|
class ArrayStringChipsInputComponent extends NgxMatEntityBaseInputComponent {
|
|
2576
|
-
uuid2 = UUIDUtilities
|
|
2890
|
+
uuid2 = UUIDUtilities.create();
|
|
2577
2891
|
chipsInput = '';
|
|
2578
2892
|
/**
|
|
2579
2893
|
* Handles adding strings to the chipsArray.
|
|
@@ -2676,12 +2990,15 @@ class BooleanCheckboxInputComponent extends NgxMatEntityBaseInputComponent {
|
|
|
2676
2990
|
super.ngOnInit();
|
|
2677
2991
|
this.propertyValue = this.propertyValue ?? false;
|
|
2678
2992
|
}
|
|
2993
|
+
updatePropertyValue() {
|
|
2994
|
+
this.propertyValue = this.propertyValue != null ? !this.propertyValue : true;
|
|
2995
|
+
}
|
|
2679
2996
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: BooleanCheckboxInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2680
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: BooleanCheckboxInputComponent, selector: "boolean-checkbox-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-checkbox\n color=\"primary\"\n (
|
|
2997
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: BooleanCheckboxInputComponent, selector: "boolean-checkbox-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-checkbox\n color=\"primary\"\n (click)=\"model.control.markAsTouched(); updatePropertyValue(); emitChange();\"\n [disabled]=\"isReadOnly\"\n [class.disabled]=\"isReadOnly\"\n [class.mat-checkbox-disabled]=\"false\"\n [checked]=\"propertyValue\"\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() + uuid\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required(entity) ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required(entity)\"\n [disabled]=\"isReadOnly\"\n >\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-checkbox{margin-top:-10px;margin-bottom:-10px}mat-form-field{width:100%}\n"], dependencies: [{ kind: "directive", type: i2$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"] }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }] });
|
|
2681
2998
|
}
|
|
2682
2999
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: BooleanCheckboxInputComponent, decorators: [{
|
|
2683
3000
|
type: Component,
|
|
2684
|
-
args: [{ selector: 'boolean-checkbox-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-checkbox\n color=\"primary\"\n (
|
|
3001
|
+
args: [{ selector: 'boolean-checkbox-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-checkbox\n color=\"primary\"\n (click)=\"model.control.markAsTouched(); updatePropertyValue(); emitChange();\"\n [disabled]=\"isReadOnly\"\n [class.disabled]=\"isReadOnly\"\n [class.mat-checkbox-disabled]=\"false\"\n [checked]=\"propertyValue\"\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() + uuid\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required(entity) ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required(entity)\"\n [disabled]=\"isReadOnly\"\n >\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-checkbox{margin-top:-10px;margin-bottom:-10px}mat-form-field{width:100%}\n"] }]
|
|
2685
3002
|
}] });
|
|
2686
3003
|
|
|
2687
3004
|
/* eslint-disable jsdoc/require-jsdoc */
|
|
@@ -2700,12 +3017,15 @@ class BooleanToggleInputComponent extends NgxMatEntityBaseInputComponent {
|
|
|
2700
3017
|
super.ngOnInit();
|
|
2701
3018
|
this.propertyValue = this.propertyValue ?? false;
|
|
2702
3019
|
}
|
|
3020
|
+
updatePropertyValue() {
|
|
3021
|
+
this.propertyValue = this.propertyValue != null ? !this.propertyValue : true;
|
|
3022
|
+
}
|
|
2703
3023
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: BooleanToggleInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2704
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: BooleanToggleInputComponent, selector: "boolean-toggle-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-slide-toggle\n color=\"primary\"\n (click)=\"model.control.markAsTouched()
|
|
3024
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: BooleanToggleInputComponent, selector: "boolean-toggle-input", usesInheritance: true, ngImport: i0, template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-slide-toggle\n color=\"primary\"\n (click)=\"model.control.markAsTouched(); updatePropertyValue(); emitChange();\"\n [disabled]=\"isReadOnly\"\n [checked]=\"propertyValue\"\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() + uuid\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required(entity) ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required(entity)\"\n [disabled]=\"isReadOnly\"\n (ngModelChange)=\"emitChange()\"\n >\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "directive", type: i2$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"] }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4$3.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex"], exportAs: ["matSlideToggle"] }] });
|
|
2705
3025
|
}
|
|
2706
3026
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: BooleanToggleInputComponent, decorators: [{
|
|
2707
3027
|
type: Component,
|
|
2708
|
-
args: [{ selector: 'boolean-toggle-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-slide-toggle\n color=\"primary\"\n (click)=\"model.control.markAsTouched()
|
|
3028
|
+
args: [{ selector: 'boolean-toggle-input', template: "<mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-slide-toggle\n color=\"primary\"\n (click)=\"model.control.markAsTouched(); updatePropertyValue(); emitChange();\"\n [disabled]=\"isReadOnly\"\n [checked]=\"propertyValue\"\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() + uuid\"\n #model=\"ngModel\"\n [pattern]=\"metadata.required(entity) ? 'true' : '[\\\\s\\\\S]*'\"\n [required]=\"metadata.required(entity)\"\n [disabled]=\"isReadOnly\"\n (ngModelChange)=\"emitChange()\"\n >\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
|
|
2709
3029
|
}] });
|
|
2710
3030
|
|
|
2711
3031
|
/* eslint-disable jsdoc/require-jsdoc */
|
|
@@ -2788,6 +3108,8 @@ class DateRangeInputComponent extends NgxMatEntityBaseInputComponent {
|
|
|
2788
3108
|
this.dateRange.values = values.length ? values : undefined;
|
|
2789
3109
|
}
|
|
2790
3110
|
else {
|
|
3111
|
+
this.dateRange.start = undefined;
|
|
3112
|
+
this.dateRange.end = undefined;
|
|
2791
3113
|
this.dateRange.values = undefined;
|
|
2792
3114
|
}
|
|
2793
3115
|
this.propertyValue = this.dateRange;
|
|
@@ -2857,66 +3179,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
2857
3179
|
args: [{ selector: 'date-time-input', template: "<div class=\"date-time\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n matInput\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString() + uuid\"\n #model=\"ngModel\"\n [matDatepicker]=\"picker\"\n [required]=\"metadata.required(entity)\"\n [min]=\"metadata.minDate ? metadata.minDate(propertyValue) : undefined\"\n [max]=\"metadata.maxDate ? metadata.maxDate(propertyValue) : undefined\"\n [matDatepickerFilter]=\"metadata.filterDate ?? defaultDateFilter\"\n (dateChange)=\"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' + uuid\"\n #timeModel=\"ngModel\"\n [required]=\"metadata.required(entity)\"\n [compareWith]=\"compareTimes\"\n [disabled]=\"isReadOnly\"\n (selectionChange)=\"setTime()\"\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"] }]
|
|
2858
3180
|
}] });
|
|
2859
3181
|
|
|
2860
|
-
/**
|
|
2861
|
-
* Adds drag and drop functionality to an element.
|
|
2862
|
-
*/
|
|
2863
|
-
class DragDropDirective {
|
|
2864
|
-
/**
|
|
2865
|
-
* Emits the dropped files to the parent.
|
|
2866
|
-
*/
|
|
2867
|
-
files = new EventEmitter();
|
|
2868
|
-
constructor() { }
|
|
2869
|
-
/**
|
|
2870
|
-
* Prevents the event default.
|
|
2871
|
-
*
|
|
2872
|
-
* @param evt - The Event when dragged files hover over the parent.
|
|
2873
|
-
*/
|
|
2874
|
-
onDragOver(evt) {
|
|
2875
|
-
evt.preventDefault();
|
|
2876
|
-
evt.stopPropagation();
|
|
2877
|
-
}
|
|
2878
|
-
/**
|
|
2879
|
-
* Prevents the event default.
|
|
2880
|
-
*
|
|
2881
|
-
* @param evt - The Event when dragged files leave the parent.
|
|
2882
|
-
*/
|
|
2883
|
-
onDragLeave(evt) {
|
|
2884
|
-
evt.preventDefault();
|
|
2885
|
-
evt.stopPropagation();
|
|
2886
|
-
}
|
|
2887
|
-
/**
|
|
2888
|
-
* Prevents the event default and emits the dropped files with the output.
|
|
2889
|
-
*
|
|
2890
|
-
* @param evt - The Event when files are dropped.
|
|
2891
|
-
*/
|
|
2892
|
-
onDrop(evt) {
|
|
2893
|
-
evt.preventDefault();
|
|
2894
|
-
evt.stopPropagation();
|
|
2895
|
-
if (evt.dataTransfer && evt.dataTransfer.files.length > 0) {
|
|
2896
|
-
this.files.emit(Array.from(evt.dataTransfer.files));
|
|
2897
|
-
}
|
|
2898
|
-
}
|
|
2899
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: DragDropDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2900
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.0", type: DragDropDirective, selector: "[dragDrop]", outputs: { files: "files" }, host: { listeners: { "dragover": "onDragOver($event)", "dragleave": "onDragLeave($event)", "drop": "onDrop($event)" } }, ngImport: i0 });
|
|
2901
|
-
}
|
|
2902
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: DragDropDirective, decorators: [{
|
|
2903
|
-
type: Directive,
|
|
2904
|
-
args: [{
|
|
2905
|
-
selector: '[dragDrop]'
|
|
2906
|
-
}]
|
|
2907
|
-
}], ctorParameters: function () { return []; }, propDecorators: { files: [{
|
|
2908
|
-
type: Output
|
|
2909
|
-
}], onDragOver: [{
|
|
2910
|
-
type: HostListener,
|
|
2911
|
-
args: ['dragover', ['$event']]
|
|
2912
|
-
}], onDragLeave: [{
|
|
2913
|
-
type: HostListener,
|
|
2914
|
-
args: ['dragleave', ['$event']]
|
|
2915
|
-
}], onDrop: [{
|
|
2916
|
-
type: HostListener,
|
|
2917
|
-
args: ['drop', ['$event']]
|
|
2918
|
-
}] } });
|
|
2919
|
-
|
|
2920
3182
|
/* eslint-disable jsdoc/require-jsdoc */
|
|
2921
3183
|
class FileInputComponent {
|
|
2922
3184
|
dialog;
|
|
@@ -3205,11 +3467,11 @@ class FileImageInputComponent extends NgxMatEntityBaseInputComponent {
|
|
|
3205
3467
|
this.imageIndex = index;
|
|
3206
3468
|
}
|
|
3207
3469
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: FileImageInputComponent, deps: [{ token: i2.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
|
|
3208
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", 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 [propertyValue]=\"propertyValue\"\n [metadata]=\"metadata\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [isReadOnly]=\"isReadOnly\"\n [entity]=\"entity\"\n [key]=\"key\"\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 [propertyValue]=\"propertyValue\"\n [metadata]=\"metadata\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [isReadOnly]=\"isReadOnly\"\n [entity]=\"entity\"\n [key]=\"key\"\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 type=\"button\" (click)=\"setIndex(imageIndex-4)\" mat-icon-button *ngIf=\"\n this.multiPreviewImages\n && multiPreviewImages[imageIndex-4]\n && imageIndex === (this.multiPreviewImages.length - 1)\"\n >\n <
|
|
3470
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", 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 [propertyValue]=\"propertyValue\"\n [metadata]=\"metadata\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [isReadOnly]=\"isReadOnly\"\n [entity]=\"entity\"\n [key]=\"key\"\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 [propertyValue]=\"propertyValue\"\n [metadata]=\"metadata\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [isReadOnly]=\"isReadOnly\"\n [entity]=\"entity\"\n [key]=\"key\"\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\n <div class=\"preview-nav\" *ngIf=\"metadata.preview && metadata.multiple\">\n <button type=\"button\" (click)=\"setIndex(imageIndex-4)\" mat-icon-button *ngIf=\"\n this.multiPreviewImages\n && multiPreviewImages[imageIndex-4]\n && imageIndex === (this.multiPreviewImages.length - 1)\"\n >\n <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex - 3}}</div>\n </div>\n </button>\n <!-- eslint-disable-next-line @angular-eslint/template/conditional-complexity -->\n <button type=\"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 <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex - 2}}</div>\n </div>\n </button>\n <button type=\"button\" (click)=\"setIndex(imageIndex-2)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex-2]\">\n <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex - 1}}</div>\n </div>\n </button>\n <button type=\"button\" (click)=\"setIndex(imageIndex-1)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex-1]\">\n <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex}}</div>\n </div>\n </button>\n <button type=\"button\" mat-icon-button disabled>\n <div class=\"dot selected\">\n <div class=\"image-index\">{{imageIndex + 1}}</div>\n </div>\n </button>\n <button type=\"button\" (click)=\"setIndex(imageIndex+1)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+1]\">\n <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex + 2}}</div>\n </div>\n </button>\n <button type=\"button\" (click)=\"setIndex(imageIndex+2)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+2]\">\n <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex + 3}}</div>\n </div>\n </button>\n <button type=\"button\" (click)=\"setIndex(imageIndex+3)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+3] && imageIndex <= 1\">\n <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex + 4}}</div>\n </div>\n </button>\n <button type=\"button\" (click)=\"setIndex(imageIndex+4)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+4] && imageIndex === 0\">\n <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex + 5}}</div>\n </div>\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\n <div class=\"preview-nav\" *ngIf=\"metadata.preview && !metadata.multiple\">\n <button type=\"button\" disabled mat-icon-button>\n <div class=\"dot selected\">\n <div class=\"image-index\">1</div>\n </div>\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;color:#0000008a}.image-preview .next-button{font-size:100px;margin-right:5px;color:#0000008a}.image-preview .prev-button:hover,.image-preview .next-button:hover{cursor:pointer;color:#000000b3;transition:all .5s ease}.image-preview .prev-button.disabled,.image-preview .next-button.disabled{color:#00000042}.image-preview .prev-button.disabled:hover,.image-preview .next-button.disabled:hover{color:#00000042;transition:none;cursor:default}.image-preview img{max-width:calc(100% - 100px);max-height:100%;margin-left:auto;margin-right:auto;border-radius:3px}.preview-nav{display:flex;align-items:center;justify-content:center;column-gap:5px}.preview-nav button{display:flex;align-items:center;justify-content:center;padding:0;height:auto;width:auto}.preview-nav button .dot{display:flex;align-items:center;justify-content:center;height:25px;width:25px;min-width:25px;background-color:#00000061;border-radius:50%}.preview-nav button .dot .image-index{color:#fff;font-size:20px;font-weight:600}.preview-nav button .dot.selected{background-color:#0000008a}.preview-nav button:hover .dot{background-color:#0000008a;transition:all .3s ease}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i5.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: FileInputComponent, selector: "file-input", inputs: ["propertyValue", "entity", "key", "metadata", "getValidationErrorMessage", "isReadOnly"], outputs: ["fileDataChangeEvent"] }] });
|
|
3209
3471
|
}
|
|
3210
3472
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: FileImageInputComponent, decorators: [{
|
|
3211
3473
|
type: Component,
|
|
3212
|
-
args: [{ selector: 'file-image-input', template: "<div *ngIf=\"!metadata.dragAndDrop && !metadata.preview\">\n <file-input\n (fileDataChangeEvent)=\"refreshFileData($event)\"\n [propertyValue]=\"propertyValue\"\n [metadata]=\"metadata\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [isReadOnly]=\"isReadOnly\"\n [entity]=\"entity\"\n [key]=\"key\"\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 [propertyValue]=\"propertyValue\"\n [metadata]=\"metadata\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [isReadOnly]=\"isReadOnly\"\n [entity]=\"entity\"\n [key]=\"key\"\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 type=\"button\" (click)=\"setIndex(imageIndex-4)\" mat-icon-button *ngIf=\"\n this.multiPreviewImages\n && multiPreviewImages[imageIndex-4]\n && imageIndex === (this.multiPreviewImages.length - 1)\"\n >\n <
|
|
3474
|
+
args: [{ selector: 'file-image-input', template: "<div *ngIf=\"!metadata.dragAndDrop && !metadata.preview\">\n <file-input\n (fileDataChangeEvent)=\"refreshFileData($event)\"\n [propertyValue]=\"propertyValue\"\n [metadata]=\"metadata\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [isReadOnly]=\"isReadOnly\"\n [entity]=\"entity\"\n [key]=\"key\"\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 [propertyValue]=\"propertyValue\"\n [metadata]=\"metadata\"\n [getValidationErrorMessage]=\"getValidationErrorMessage\"\n [isReadOnly]=\"isReadOnly\"\n [entity]=\"entity\"\n [key]=\"key\"\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\n <div class=\"preview-nav\" *ngIf=\"metadata.preview && metadata.multiple\">\n <button type=\"button\" (click)=\"setIndex(imageIndex-4)\" mat-icon-button *ngIf=\"\n this.multiPreviewImages\n && multiPreviewImages[imageIndex-4]\n && imageIndex === (this.multiPreviewImages.length - 1)\"\n >\n <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex - 3}}</div>\n </div>\n </button>\n <!-- eslint-disable-next-line @angular-eslint/template/conditional-complexity -->\n <button type=\"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 <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex - 2}}</div>\n </div>\n </button>\n <button type=\"button\" (click)=\"setIndex(imageIndex-2)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex-2]\">\n <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex - 1}}</div>\n </div>\n </button>\n <button type=\"button\" (click)=\"setIndex(imageIndex-1)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex-1]\">\n <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex}}</div>\n </div>\n </button>\n <button type=\"button\" mat-icon-button disabled>\n <div class=\"dot selected\">\n <div class=\"image-index\">{{imageIndex + 1}}</div>\n </div>\n </button>\n <button type=\"button\" (click)=\"setIndex(imageIndex+1)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+1]\">\n <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex + 2}}</div>\n </div>\n </button>\n <button type=\"button\" (click)=\"setIndex(imageIndex+2)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+2]\">\n <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex + 3}}</div>\n </div>\n </button>\n <button type=\"button\" (click)=\"setIndex(imageIndex+3)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+3] && imageIndex <= 1\">\n <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex + 4}}</div>\n </div>\n </button>\n <button type=\"button\" (click)=\"setIndex(imageIndex+4)\" mat-icon-button *ngIf=\"multiPreviewImages?.[imageIndex+4] && imageIndex === 0\">\n <div class=\"dot\">\n <div class=\"image-index\">{{imageIndex + 5}}</div>\n </div>\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\n <div class=\"preview-nav\" *ngIf=\"metadata.preview && !metadata.multiple\">\n <button type=\"button\" disabled mat-icon-button>\n <div class=\"dot selected\">\n <div class=\"image-index\">1</div>\n </div>\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;color:#0000008a}.image-preview .next-button{font-size:100px;margin-right:5px;color:#0000008a}.image-preview .prev-button:hover,.image-preview .next-button:hover{cursor:pointer;color:#000000b3;transition:all .5s ease}.image-preview .prev-button.disabled,.image-preview .next-button.disabled{color:#00000042}.image-preview .prev-button.disabled:hover,.image-preview .next-button.disabled:hover{color:#00000042;transition:none;cursor:default}.image-preview img{max-width:calc(100% - 100px);max-height:100%;margin-left:auto;margin-right:auto;border-radius:3px}.preview-nav{display:flex;align-items:center;justify-content:center;column-gap:5px}.preview-nav button{display:flex;align-items:center;justify-content:center;padding:0;height:auto;width:auto}.preview-nav button .dot{display:flex;align-items:center;justify-content:center;height:25px;width:25px;min-width:25px;background-color:#00000061;border-radius:50%}.preview-nav button .dot .image-index{color:#fff;font-size:20px;font-weight:600}.preview-nav button .dot.selected{background-color:#0000008a}.preview-nav button:hover .dot{background-color:#0000008a;transition:all .3s ease}\n"] }]
|
|
3213
3475
|
}], ctorParameters: function () { return [{ type: i2.HttpClient }]; } });
|
|
3214
3476
|
|
|
3215
3477
|
const NGX_GET_VALIDATION_ERROR_MESSAGE = new InjectionToken('Provider for the default getValidationErrorMessage.', {
|
|
@@ -3233,6 +3495,10 @@ function getValidationErrorMessage(model) {
|
|
|
3233
3495
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
3234
3496
|
return `needs to be at least ${model.getError('minlength').requiredLength} characters long`;
|
|
3235
3497
|
}
|
|
3498
|
+
else if (model.hasError('maxlength')) {
|
|
3499
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
3500
|
+
return `needs to be at most ${model.getError('maxlength').requiredLength} characters long`;
|
|
3501
|
+
}
|
|
3236
3502
|
else if (model.hasError('min')) {
|
|
3237
3503
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
3238
3504
|
return `needs to be equal or bigger than ${model.getError('min').min}`;
|
|
@@ -3241,6 +3507,9 @@ function getValidationErrorMessage(model) {
|
|
|
3241
3507
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
3242
3508
|
return `needs to be equal or smaller than ${model.getError('max').max}`;
|
|
3243
3509
|
}
|
|
3510
|
+
else if (model.hasError('passwordMatch')) {
|
|
3511
|
+
return 'Passwords need to match!';
|
|
3512
|
+
}
|
|
3244
3513
|
else if (model.hasError('required')) {
|
|
3245
3514
|
return 'required';
|
|
3246
3515
|
}
|
|
@@ -3748,21 +4017,21 @@ class StringPasswordInputComponent extends NgxMatEntityBaseInputComponent {
|
|
|
3748
4017
|
this.emitChange();
|
|
3749
4018
|
}
|
|
3750
4019
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: StringPasswordInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3751
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: StringPasswordInputComponent, selector: "string-password-input", usesInheritance: true, ngImport: i0, template: "<div class=\"password-row\">\n <mat-form-field
|
|
4020
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: StringPasswordInputComponent, selector: "string-password-input", usesInheritance: true, ngImport: i0, template: "<div class=\"password-row\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n [type]=\"hide ? 'password' : 'text'\"\n matInput\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString() + uuid\"\n #model=\"ngModel\"\n [required]=\"metadata.required(entity)\"\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 type=\"button\" (click)=\"hide = !hide\" mat-icon-button matSuffix>\n <div class=\"d-flex justify-content-center align-items-center\">\n <i *ngIf=\"hide\" class=\"fas fa-eye-slash\"></i>\n <i *ngIf=\"!hide\" class=\"fas fa-eye\"></i>\n </div>\n </button>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n <mat-form-field *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' + uuid\"\n #confirmModel=\"ngModel\"\n [required]=\"confirmRequired\"\n (ngModelChange)=\"passwordInput()\"\n [disabled]=\"isReadOnly\"\n [passwordMatch]=\"propertyValue\"\n >\n <button type=\"button\" (click)=\"hideConfirm = !hideConfirm\" mat-icon-button matSuffix>\n <div class=\"d-flex justify-content-center align-items-center\">\n <i *ngIf=\"hideConfirm\" class=\"fas fa-eye-slash\"></i>\n <i *ngIf=\"!hideConfirm\" class=\"fas fa-eye\"></i>\n </div>\n </button>\n <mat-error>{{getValidationErrorMessage(confirmModel)}}</mat-error>\n </mat-form-field>\n</div>", styles: [".password-row{display:flex;justify-content:space-evenly;column-gap:24px}.password-row mat-form-field{flex:1 1 0}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$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"] }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i3.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i3.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: PasswordMatchValidatorDirective, selector: "[passwordMatch]", inputs: ["passwordMatch"] }] });
|
|
3752
4021
|
}
|
|
3753
4022
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: StringPasswordInputComponent, decorators: [{
|
|
3754
4023
|
type: Component,
|
|
3755
|
-
args: [{ selector: 'string-password-input', template: "<div class=\"password-row\">\n <mat-form-field
|
|
4024
|
+
args: [{ selector: 'string-password-input', template: "<div class=\"password-row\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <input\n [type]=\"hide ? 'password' : 'text'\"\n matInput\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString() + uuid\"\n #model=\"ngModel\"\n [required]=\"metadata.required(entity)\"\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 type=\"button\" (click)=\"hide = !hide\" mat-icon-button matSuffix>\n <div class=\"d-flex justify-content-center align-items-center\">\n <i *ngIf=\"hide\" class=\"fas fa-eye-slash\"></i>\n <i *ngIf=\"!hide\" class=\"fas fa-eye\"></i>\n </div>\n </button>\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n </mat-form-field>\n <mat-form-field *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' + uuid\"\n #confirmModel=\"ngModel\"\n [required]=\"confirmRequired\"\n (ngModelChange)=\"passwordInput()\"\n [disabled]=\"isReadOnly\"\n [passwordMatch]=\"propertyValue\"\n >\n <button type=\"button\" (click)=\"hideConfirm = !hideConfirm\" mat-icon-button matSuffix>\n <div class=\"d-flex justify-content-center align-items-center\">\n <i *ngIf=\"hideConfirm\" class=\"fas fa-eye-slash\"></i>\n <i *ngIf=\"!hideConfirm\" class=\"fas fa-eye\"></i>\n </div>\n </button>\n <mat-error>{{getValidationErrorMessage(confirmModel)}}</mat-error>\n </mat-form-field>\n</div>", styles: [".password-row{display:flex;justify-content:space-evenly;column-gap:24px}.password-row mat-form-field{flex:1 1 0}\n"] }]
|
|
3756
4025
|
}] });
|
|
3757
4026
|
|
|
3758
4027
|
/* eslint-disable jsdoc/require-jsdoc */
|
|
3759
4028
|
class NumberInputComponent extends NgxMatEntityBaseInputComponent {
|
|
3760
4029
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NumberInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3761
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", 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() + uuid\"\n #model=\"ngModel\"\n [required]=\"metadata.required(entity)\"\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"], dependencies: [{ kind: "directive", type: i2$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"] }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i3.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
4030
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", 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() + uuid\"\n #model=\"ngModel\"\n [required]=\"metadata.required(entity)\"\n [min]=\"metadata.min ?? null\"\n [max]=\"metadata.max ?? null\"\n (ngModelChange)=\"emitChange()\"\n [disabled]=\"isReadOnly\"\n number\n >\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "directive", type: i2$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"] }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i3.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NumberDirective, selector: "[number]" }] });
|
|
3762
4031
|
}
|
|
3763
4032
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NumberInputComponent, decorators: [{
|
|
3764
4033
|
type: Component,
|
|
3765
|
-
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() + uuid\"\n #model=\"ngModel\"\n [required]=\"metadata.required(entity)\"\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"] }]
|
|
4034
|
+
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() + uuid\"\n #model=\"ngModel\"\n [required]=\"metadata.required(entity)\"\n [min]=\"metadata.min ?? null\"\n [max]=\"metadata.max ?? null\"\n (ngModelChange)=\"emitChange()\"\n [disabled]=\"isReadOnly\"\n number\n >\n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%}\n"] }]
|
|
3766
4035
|
}] });
|
|
3767
4036
|
|
|
3768
4037
|
/* eslint-disable jsdoc/require-jsdoc */
|
|
@@ -3782,12 +4051,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
3782
4051
|
|
|
3783
4052
|
/* eslint-disable jsdoc/require-jsdoc */
|
|
3784
4053
|
class NumberSliderInputComponent extends NgxMatEntityBaseInputComponent {
|
|
4054
|
+
updatePropertyValue(value) {
|
|
4055
|
+
this.propertyValue = value;
|
|
4056
|
+
}
|
|
3785
4057
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NumberSliderInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3786
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: NumberSliderInputComponent, selector: "number-slider-input", usesInheritance: true, ngImport: i0, template: "<mat-slider\n id=\"slider\"\n color=\"primary\"\n (click)=\"model.control.markAsTouched()\"\n [min]=\"metadata.min ?? null\"\n [max]=\"metadata.max ?? null\"\n [step]=\"metadata.step\"\n [discrete]=\"true\"\n [displayWith]=\"metadata.formatThumbLabelValue\"\n [showTickMarks]=\"metadata.showTickMarks\"\n [disabled]=\"isReadOnly\"\n>\n <input matSliderThumb\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString() +
|
|
4058
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: NumberSliderInputComponent, selector: "number-slider-input", usesInheritance: true, ngImport: i0, template: "<mat-slider\n id=\"slider\"\n color=\"primary\"\n (click)=\"model.control.markAsTouched()\"\n [min]=\"metadata.min ?? null\"\n [max]=\"metadata.max ?? null\"\n [step]=\"metadata.step\"\n [discrete]=\"true\"\n [displayWith]=\"metadata.formatThumbLabelValue\"\n [showTickMarks]=\"metadata.showTickMarks\"\n [disabled]=\"isReadOnly\"\n>\n <input matSliderThumb\n (valueChange)=\"updatePropertyValue($event)\"\n [disabled]=\"isReadOnly\"\n >\n</mat-slider>\n\n<mat-form-field floatLabel=\"always\">\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 style=\"opacity: 0%;\"\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString() + uuid\"\n #model=\"ngModel\"\n [required]=\"metadata.required(entity)\"\n [min]=\"metadata.min ?? null\"\n [max]=\"metadata.max ?? null\"\n (ngModelChange)=\"emitChange()\"\n [disabled]=\"isReadOnly\"\n >\n \n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%;margin-top:-40px}mat-slider{width:calc(100% - 40px);margin-left:20px;margin-right:20px;margin-bottom:-40px;z-index:999}::ng-deep #slider .mdc-slider__value-indicator-container{top:23px;left:57px;display:flex;transform:rotate(90deg) scale(1);border-radius:50%;pointer-events:auto}::ng-deep #slider .mdc-slider__value-indicator{padding-right:5px;padding-left:5px;transition:transform .1s 0ms cubic-bezier(0,0,.2,1);transform:scale(1)}::ng-deep #slider .mdc-slider__value-indicator-text{transform:rotate(270deg)}\n"], dependencies: [{ kind: "directive", type: i2$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"] }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4$4.MatSlider, selector: "mat-slider", inputs: ["color", "disableRipple", "disabled", "discrete", "showTickMarks", "min", "max", "step", "displayWith"], exportAs: ["matSlider"] }, { kind: "directive", type: i4$4.MatSliderThumb, selector: "input[matSliderThumb]", inputs: ["value"], outputs: ["valueChange", "dragStart", "dragEnd"], exportAs: ["matSliderThumb"] }] });
|
|
3787
4059
|
}
|
|
3788
4060
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NumberSliderInputComponent, decorators: [{
|
|
3789
4061
|
type: Component,
|
|
3790
|
-
args: [{ selector: 'number-slider-input', template: "<mat-slider\n id=\"slider\"\n color=\"primary\"\n (click)=\"model.control.markAsTouched()\"\n [min]=\"metadata.min ?? null\"\n [max]=\"metadata.max ?? null\"\n [step]=\"metadata.step\"\n [discrete]=\"true\"\n [displayWith]=\"metadata.formatThumbLabelValue\"\n [showTickMarks]=\"metadata.showTickMarks\"\n [disabled]=\"isReadOnly\"\n>\n <input matSliderThumb\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString() +
|
|
4062
|
+
args: [{ selector: 'number-slider-input', template: "<mat-slider\n id=\"slider\"\n color=\"primary\"\n (click)=\"model.control.markAsTouched()\"\n [min]=\"metadata.min ?? null\"\n [max]=\"metadata.max ?? null\"\n [step]=\"metadata.step\"\n [discrete]=\"true\"\n [displayWith]=\"metadata.formatThumbLabelValue\"\n [showTickMarks]=\"metadata.showTickMarks\"\n [disabled]=\"isReadOnly\"\n>\n <input matSliderThumb\n (valueChange)=\"updatePropertyValue($event)\"\n [disabled]=\"isReadOnly\"\n >\n</mat-slider>\n\n<mat-form-field floatLabel=\"always\">\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 style=\"opacity: 0%;\"\n [(ngModel)]=\"propertyValue\"\n [name]=\"key.toString() + uuid\"\n #model=\"ngModel\"\n [required]=\"metadata.required(entity)\"\n [min]=\"metadata.min ?? null\"\n [max]=\"metadata.max ?? null\"\n (ngModelChange)=\"emitChange()\"\n [disabled]=\"isReadOnly\"\n >\n \n <mat-error>{{getValidationErrorMessage(model)}}</mat-error>\n</mat-form-field>", styles: ["mat-form-field{width:100%;margin-top:-40px}mat-slider{width:calc(100% - 40px);margin-left:20px;margin-right:20px;margin-bottom:-40px;z-index:999}::ng-deep #slider .mdc-slider__value-indicator-container{top:23px;left:57px;display:flex;transform:rotate(90deg) scale(1);border-radius:50%;pointer-events:auto}::ng-deep #slider .mdc-slider__value-indicator{padding-right:5px;padding-left:5px;transition:transform .1s 0ms cubic-bezier(0,0,.2,1);transform:scale(1)}::ng-deep #slider .mdc-slider__value-indicator-text{transform:rotate(270deg)}\n"] }]
|
|
3791
4063
|
}] });
|
|
3792
4064
|
|
|
3793
4065
|
/* eslint-disable jsdoc/require-jsdoc */
|
|
@@ -3962,8 +4234,26 @@ class NgxMatEntityInputComponent {
|
|
|
3962
4234
|
editArrayItemDialogData;
|
|
3963
4235
|
metadataHasMany;
|
|
3964
4236
|
hasManyIsLoading = true;
|
|
3965
|
-
|
|
3966
|
-
|
|
4237
|
+
/**
|
|
4238
|
+
* A setter for the has many paginator.
|
|
4239
|
+
* Is needed because the paginator is inside a switch case,
|
|
4240
|
+
* which means that at ngOnInit it can't be initialized.
|
|
4241
|
+
*/
|
|
4242
|
+
set hasManyPaginator(paginator) {
|
|
4243
|
+
if (!this.hasManyDataSource.paginator) {
|
|
4244
|
+
this.hasManyDataSource.paginator = paginator;
|
|
4245
|
+
}
|
|
4246
|
+
}
|
|
4247
|
+
/**
|
|
4248
|
+
* A setter for the has many sort.
|
|
4249
|
+
* Is needed because the sort is inside a switch case,
|
|
4250
|
+
* which means that at ngOnInit it can't be initialized.
|
|
4251
|
+
*/
|
|
4252
|
+
set hasManySort(sort) {
|
|
4253
|
+
if (!this.hasManyDataSource.sort) {
|
|
4254
|
+
this.hasManyDataSource.sort = sort;
|
|
4255
|
+
}
|
|
4256
|
+
}
|
|
3967
4257
|
hasManyFilter;
|
|
3968
4258
|
displayedHasManyColumns;
|
|
3969
4259
|
hasManyDataSource = new MatTableDataSource();
|
|
@@ -4106,7 +4396,6 @@ class NgxMatEntityInputComponent {
|
|
|
4106
4396
|
return this.metadataHasMany.tableData.baseData.displayColumns.find((dp) => dp.displayName === header)?.value(entity);
|
|
4107
4397
|
});
|
|
4108
4398
|
};
|
|
4109
|
-
this.hasManyDataSource.sort = this.hasManySort;
|
|
4110
4399
|
this.hasManyDataSource.filterPredicate = (entity, filter) => {
|
|
4111
4400
|
const searchStr = this.metadataHasMany.tableData.baseData.searchString(entity);
|
|
4112
4401
|
const formattedSearchString = searchStr.toLowerCase();
|
|
@@ -4114,7 +4403,6 @@ class NgxMatEntityInputComponent {
|
|
|
4114
4403
|
return formattedSearchString.includes(formattedFilterString);
|
|
4115
4404
|
};
|
|
4116
4405
|
this.hasManyDataSource.filter = this.hasManyFilter;
|
|
4117
|
-
this.hasManyDataSource.paginator = this.hasManyPaginator;
|
|
4118
4406
|
this.hasManyEntityService.entitiesSubject.subscribe((entities) => {
|
|
4119
4407
|
this.hasManyDataSource.data = entities;
|
|
4120
4408
|
this.hasManySelection.clear();
|
|
@@ -4254,6 +4542,47 @@ class NgxMatEntityInputComponent {
|
|
|
4254
4542
|
return this.metadataHasMany.tableData.baseData.allowDelete(entity);
|
|
4255
4543
|
});
|
|
4256
4544
|
}
|
|
4545
|
+
/**
|
|
4546
|
+
* Checks if an EditAction is disabled (e.g. Because the current entry doesn't fullfil the requirements).
|
|
4547
|
+
*
|
|
4548
|
+
* @param action - The EditAction to check.
|
|
4549
|
+
* @returns Whether or not the Action can be used.
|
|
4550
|
+
*/
|
|
4551
|
+
hasManyEditActionDisabled(action) {
|
|
4552
|
+
return this.injector.runInContext(() => {
|
|
4553
|
+
return !action.enabled(this.hasManyEntityPriorChanges);
|
|
4554
|
+
});
|
|
4555
|
+
}
|
|
4556
|
+
/**
|
|
4557
|
+
* Runs the edit action on the entity.
|
|
4558
|
+
*
|
|
4559
|
+
* @param action - The action to run.
|
|
4560
|
+
*/
|
|
4561
|
+
hasManyRunEditAction(action) {
|
|
4562
|
+
const requireConfirmDialog = this.injector.runInContext(() => {
|
|
4563
|
+
return action.requireConfirmDialog(this.hasManyEntityPriorChanges);
|
|
4564
|
+
});
|
|
4565
|
+
if (!requireConfirmDialog) {
|
|
4566
|
+
this.confirmHasManyRunEditAction(action);
|
|
4567
|
+
return;
|
|
4568
|
+
}
|
|
4569
|
+
const dialogRef = this.dialog.open(NgxMatEntityConfirmDialogComponent, {
|
|
4570
|
+
data: action.confirmDialogData,
|
|
4571
|
+
autoFocus: false,
|
|
4572
|
+
restoreFocus: false
|
|
4573
|
+
});
|
|
4574
|
+
dialogRef.afterClosed().subscribe(res => {
|
|
4575
|
+
if (res == true) {
|
|
4576
|
+
this.confirmHasManyRunEditAction(action);
|
|
4577
|
+
}
|
|
4578
|
+
});
|
|
4579
|
+
}
|
|
4580
|
+
confirmHasManyRunEditAction(action) {
|
|
4581
|
+
void this.injector.runInContext(async () => {
|
|
4582
|
+
await action.action(this.hasManyEntity, this.hasManyEntityPriorChanges);
|
|
4583
|
+
await this.checkHasManyEntity();
|
|
4584
|
+
});
|
|
4585
|
+
}
|
|
4257
4586
|
editHasManyDefaultPage(entity) {
|
|
4258
4587
|
void this.router.navigate(['', this.hasManyEntityService.editBaseRoute, entity[this.hasManyEntityService.idKey]]);
|
|
4259
4588
|
}
|
|
@@ -4490,7 +4819,7 @@ class NgxMatEntityInputComponent {
|
|
|
4490
4819
|
* @param omit - Whether values omitted for create or update should be left out.
|
|
4491
4820
|
*/
|
|
4492
4821
|
checkIsHasManyEntityValid(omit) {
|
|
4493
|
-
this.isHasManyEntityValid =
|
|
4822
|
+
this.isHasManyEntityValid = ValidationUtilities.isEntityValid(this.hasManyEntity, omit);
|
|
4494
4823
|
}
|
|
4495
4824
|
/**
|
|
4496
4825
|
* Checks whether the array item is valid and if the array item is dirty.
|
|
@@ -4509,7 +4838,7 @@ class NgxMatEntityInputComponent {
|
|
|
4509
4838
|
* Checks if the arrayItem is valid.
|
|
4510
4839
|
*/
|
|
4511
4840
|
checkIsArrayItemValid() {
|
|
4512
|
-
this.isArrayItemValid =
|
|
4841
|
+
this.isArrayItemValid = ValidationUtilities.isEntityValid(this.arrayItem, 'create');
|
|
4513
4842
|
}
|
|
4514
4843
|
/**
|
|
4515
4844
|
* Emits that a the value has been changed.
|
|
@@ -4616,11 +4945,11 @@ class NgxMatEntityInputComponent {
|
|
|
4616
4945
|
this.emitChange();
|
|
4617
4946
|
}
|
|
4618
4947
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityInputComponent, deps: [{ token: i1.MatDialog }, { token: i0.EnvironmentInjector }, { token: i2$3.Router }, { token: NGX_GET_VALIDATION_ERROR_MESSAGE }, { token: i2.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
|
|
4619
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: { entity: "entity", propertyKey: "propertyKey", getValidationErrorMessage: "getValidationErrorMessage", hideOmitForCreate: "hideOmitForCreate", hideOmitForEdit: "hideOmitForEdit", validEmpty: "validEmpty", isReadOnly: "isReadOnly" }, outputs: { inputChangeEvent: "inputChangeEvent" }, viewQueries: [{ propertyName: "addArrayItemDialog", first: true, predicate: ["addArrayItemDialog"], descendants: true }, { propertyName: "editArrayItemDialog", first: true, predicate: ["editArrayItemDialog"], descendants: true }, { propertyName: "hasManyPaginator", first: true, predicate: MatPaginator, descendants: true, static: true }, { propertyName: "hasManySort", first: true, predicate: MatSort, descendants: true, static: true }, { propertyName: "hasManyFilter", first: true, predicate: ["filter"], descendants: true, static: true }, { propertyName: "createHasManyDialog", first: true, predicate: ["createHasManyDialog"], descendants: true }, { propertyName: "editHasManyDialog", first: true, predicate: ["editHasManyDialog"], 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 <!-------------------Array-------------------->\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 <!-------------- references many ------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.REFERENCES_MANY\">\n <references-many-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </references-many-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 <!-------------------------------------------->\n <!-------------------Object------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.OBJECT\">\n <b>{{metadataDefaultObject.displayName}}</b>\n <!-- iterates over the object properties -->\n <mat-tab-group *ngIf=\"objectPropertyTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of objectPropertyTabs; let tI = index; trackBy: trackByFn\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows;\">\n <ngx-mat-entity-input *ngFor=\"let key of row.keys; let rI = index; trackBy: trackByFn\"\n [entity]=\"objectProperty\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"isPropertyReadOnly(objectProperty, key)\"\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 </mat-tab>\n </mat-tab-group>\n\n <div *ngIf=\"objectPropertyTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of objectPropertyTabs[0].rows\">\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 [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"isPropertyReadOnly(objectProperty, key)\"\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 </div>\n\n <!-------------------------------------------->\n <!-------------- references one ------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.REFERENCES_ONE\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"internalEntity[internalPropertyKey]\"\n [name]=\"internalPropertyKey.toString() + 'input' + referencesOneUUID\"\n #inputModel=\"ngModel\"\n [disabled]=\"internalIsReadOnly\"\n [required]=\"metadata.required(entity)\"\n (ngModelChange)=\"setReferencesOneObject()\"\n >\n <mat-option *ngIf=\"!metadata.required(entity)\">-</mat-option>\n <mat-option *ngFor=\"let value of referencesOneDropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{internalGetValidationErrorMessage(inputModel)}}</mat-error>\n </mat-form-field>\n <!-- iterates over the references one properties -->\n <mat-tab-group *ngIf=\"referencesOnePropertyTabs && referencesOnePropertyTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of referencesOnePropertyTabs; let tI = index; trackBy: trackByFn\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows;\">\n <ngx-mat-entity-input *ngFor=\"let key of row.keys; let rI = index; trackBy: trackByFn\"\n [entity]=\"referencesOneObject\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(referencesOneObject, key, 'lg')}} col-md-{{EntityUtilities.getWidth(referencesOneObject, key, 'md')}} col-sm-{{EntityUtilities.getWidth(referencesOneObject, key, 'sm')}}\"\n (inputChangeEvent)=\"emitChange()\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n\n <div *ngIf=\"referencesOnePropertyTabs && referencesOnePropertyTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of referencesOnePropertyTabs[0].rows\">\n <ngx-mat-entity-input *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"referencesOneObject\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(referencesOneObject, key, 'lg')}} col-md-{{EntityUtilities.getWidth(referencesOneObject, key, 'md')}} col-sm-{{EntityUtilities.getWidth(referencesOneObject, key, 'sm')}}\"\n (inputChangeEvent)=\"emitChange()\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Array-------------------->\n <!-------------------------------------------->\n <div class=\"entityArray\" *ngSwitchCase=\"DecoratorTypes.ARRAY\">\n <div class=\"mat-elevation-z8 elevation-container\">\n <div class=\"array-headline\">\n <b>{{metadataEntityArray.displayName}}</b>\n </div>\n <div *ngIf=\"metadataEntityArray.createInline && !internalIsReadOnly\">\n <mat-tab-group *ngIf=\"arrayItemInlineTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of arrayItemInlineTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\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 </mat-tab>\n </mat-tab-group>\n\n <div *ngIf=\"arrayItemInlineTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of arrayItemInlineTabs[0].rows\">\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 </div>\n\n <div class=\"buttons\" *ngIf=\"!internalIsReadOnly\">\n <button type=\"button\" mat-raised-button\n [disabled]=\"metadataEntityArray.createInline && !isArrayItemValid\"\n (click)=\"addEntity()\">\n {{metadataEntityArray.addButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button\n [disabled]=\"!entityArraySelection.selected.length\"\n (click)=\"removeFromEntityArray()\">\n {{metadataEntityArray.removeButtonLabel}}\n </button>\n </div>\n \n <mat-table [dataSource]=\"entityArrayDataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\" *ngIf=\"!internalIsReadOnly\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox\n [disabled]=\"!entityArrayDataSource.data.length\" (change)=\"$event ? SelectionUtilities.masterToggle(entityArraySelection, entityArrayDataSource) : null\"\n [checked]=\"entityArraySelection.hasValue() && SelectionUtilities.isAllSelected(entityArraySelection, entityArrayDataSource)\"\n [indeterminate]=\"entityArraySelection.hasValue() && !SelectionUtilities.isAllSelected(entityArraySelection, entityArrayDataSource)\">\n </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let entity\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? entityArraySelection.toggle(entity) : null\" [checked]=\"entityArraySelection.isSelected(entity)\"></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.enabled]=\"!dCol.disableClick\" (click)=\"editArrayItem(entity, dCol)\" *matCellDef=\"let entity\">\n <ng-container *ngIf=\"dCol.Component\">\n <display-column-value [entity]=\"entity\" [ComponentClass]=\"dCol.Component\"></display-column-value>\n </ng-container>\n <ng-container *ngIf=\"!dCol.Component\">\n {{getDisplayColumnValue(entity, dCol)}}\n </ng-container>\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"entityArrayDisplayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: entityArrayDisplayedColumns\"></mat-row>\n </mat-table>\n \n <div class=\"array-error\" *ngIf=\"metadataEntityArray.required(entity) && !entityArrayDataSource.data.length\">\n {{metadataEntityArray.missingErrorMessage}}\n </div>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!------------------ has many ---------------->\n <!-------------------------------------------->\n <div class=\"hasMany\" *ngSwitchCase=\"DecoratorTypes.HAS_MANY\">\n <h2 class=\"title\">{{metadataHasMany.tableData.baseData.title}}</h2>\n\n <div class=\"row\">\n <mat-form-field class=\"col-lg-8 col-md-6 col-sm-12\">\n <mat-label>{{metadataHasMany.tableData.baseData.searchLabel}}</mat-label>\n <input matInput (keyup)=\"applyHasManyFilter($event)\">\n </mat-form-field>\n <div\n *ngIf=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-lg-2]=\"hasManyAllowCreate\"\n [class.col-lg-4]=\"!hasManyAllowCreate\"\n [class.col-md-3]=\"hasManyAllowCreate\"\n [class.col-md-6]=\"!hasManyAllowCreate\"\n [class.col-sm-6]=\"hasManyAllowCreate\"\n [class.col-sm-12]=\"!hasManyAllowCreate\"\n >\n <button type=\"button\" class=\"actions-button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{metadataHasMany.tableData.baseData.tableActionsLabel}}\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button *ngIf=\"metadataHasMany.tableData.baseData.allowJsonImport\" type=\"button\" [disabled]=\"hasManyTableActionDisabled(hasManyImportAction)\" (click)=\"runHasManyTableAction(hasManyImportAction)\" mat-menu-item>\n {{hasManyImportAction.displayName}}\n </button>\n <button type=\"button\" *ngFor=\"let action of metadataHasMany.tableData.baseData.tableActions\" [disabled]=\"hasManyTableActionDisabled(action)\" (click)=\"runHasManyTableAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n\n <div\n *ngIf=\"hasManyAllowCreate\"\n [class.col-lg-2]=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-lg-4]=\"!metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-md-3]=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-md-6]=\"!metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-sm-6]=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-sm-12]=\"!metadataHasMany.tableData.baseData.tableActions.length\"\n >\n <button type=\"button\" class=\"create-button\" (click)=\"createHasManyEntity()\" mat-raised-button>\n {{metadataHasMany.tableData.baseData.createButtonLabel}}\n </button>\n </div>\n </div>\n\n <div class=\"mat-elevation-z8 elevation-container\">\n <mat-table [dataSource]=\"hasManyDataSource\" matSort>\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox (change)=\"$event ? SelectionUtilities.masterToggle(hasManySelection, hasManyDataSource) : null\" [checked]=\"hasManySelection.hasValue() && SelectionUtilities.isAllSelected(hasManySelection, hasManyDataSource)\" [indeterminate]=\"hasManySelection.hasValue() && !SelectionUtilities.isAllSelected(hasManySelection, hasManyDataSource)\"> </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let entity\" class=\"enabled\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? hasManySelection.toggle(entity) : null\" [checked]=\"hasManySelection.isSelected(entity)\"> </mat-checkbox>\n </mat-cell>\n </ng-container>\n\n <ng-container *ngFor=\"let dCol of metadataHasMany.tableData.baseData.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell [class.enabled]=\"!dCol.disableClick && (hasManyAllowUpdate(entity) || hasManyAllowRead(entity))\" (click)=\"editHasManyEntity(entity, dCol)\" *matCellDef=\"let entity\">\n <ng-container *ngIf=\"dCol.Component\">\n <display-column-value [entity]=\"entity\" [ComponentClass]=\"dCol.Component\"></display-column-value>\n </ng-container>\n <ng-container *ngIf=\"!dCol.Component\">\n {{getDisplayColumnValue(entity, dCol)}}\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <mat-header-row *matHeaderRowDef=\"displayedHasManyColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedHasManyColumns\"></mat-row>\n </mat-table>\n\n <mat-spinner *ngIf=\"hasManyIsLoading && metadataHasMany.tableData.baseData.displayLoadingSpinner\">\n </mat-spinner>\n\n <mat-paginator [length]=\"hasManyDataSource.filteredData.length\" [pageIndex]=\"0\" [pageSize]=\"10\" [pageSizeOptions]=\"[5, 10, 25, 50]\"></mat-paginator>\n </div>\n </div>\n\n <div *ngSwitchDefault>ERROR: The type {{type}} is not known.</div>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<!--------------------------------------------------------->\n<!--------------------Add Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #addArrayItemDialog>\n <div class=\"mat-dialog-title\">\n <div>{{addArrayItemDialogData.title}}</div>\n </div>\n\n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"arrayItemDialogTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of arrayItemDialogTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\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 </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"arrayItemDialogTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\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 </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" mat-raised-button (click)=\"addArrayItem()\" [disabled]=\"!isArrayItemValid\">\n {{addArrayItemDialogData.createButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"closeAddArrayItemDialog()\" class=\"cancel-button\">\n {{addArrayItemDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form>\n\n</ng-template>\n\n<!--------------------------------------------------------->\n<!--------------------Edit Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #editArrayItemDialog>\n <div class=\"mat-dialog-title\">\n <div>{{editArrayItemDialogData.title(arrayItemPriorChanges)}}</div>\n </div>\n \n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"arrayItemDialogTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of arrayItemDialogTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\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)=\"checkArrayItem()\"\n [isReadOnly]=\"isPropertyReadOnly(arrayItem, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"arrayItemDialogTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\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)=\"checkArrayItem()\"\n [isReadOnly]=\"isPropertyReadOnly(arrayItem, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" (click)=\"saveArrayItem()\" mat-raised-button [disabled]=\"internalIsReadOnly || !isArrayItemValid || !isArrayItemDirty\">\n {{editArrayItemDialogData.confirmButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"closeEditArrayItemDialog()\" class=\"cancel-button\">\n {{editArrayItemDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form>\n</ng-template>\n\n<!--------------------------------------------------------->\n<!--------------------Create Has Many Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #createHasManyDialog>\n <div class=\"mat-dialog-title\">\n <div>{{metadataHasMany.tableData.createDialogData.title}}</div>\n </div>\n \n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"hasManyCreateTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of hasManyCreateTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsHasManyEntityValid('create')\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"hasManyCreateTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of hasManyCreateTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsHasManyEntityValid('create')\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" (click)=\"dialogCreateHasMany()\" mat-raised-button [disabled]=\"!isHasManyEntityValid\">\n {{metadataHasMany.tableData.createDialogData.createButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"dialogCancelCreateHasMany()\" class=\"cancel-button\">\n {{metadataHasMany.tableData.createDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form>\n \n</ng-template>\n\n<ng-template #editHasManyDialog>\n <div class=\"mat-dialog-title\">\n <div>{{metadataHasMany.tableData.editData.title(hasManyEntityPriorChanges)}}</div>\n <button type=\"button\" *ngIf=\"hasManyAllowDelete(hasManyEntity)\" mat-raised-button (click)=\"deleteHasManyEntity()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{metadataHasMany.tableData.editData.deleteButtonLabel}}\n </button>\n </div>\n \n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"hasManyUpdateTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of hasManyUpdateTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkHasManyEntity()\"\n [isReadOnly]=\"isPropertyReadOnly(hasManyEntity, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"hasManyUpdateTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of hasManyUpdateTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkHasManyEntity()\"\n [isReadOnly]=\"isPropertyReadOnly(hasManyEntity, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" (click)=\"dialogEditHasMany()\" mat-raised-button [disabled]=\"internalIsReadOnly || !isHasManyEntityValid || !isHasManyEntityDirty\">\n {{metadataHasMany.tableData.editData.confirmButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"dialogCancelEditHasMany()\" class=\"cancel-button\">\n {{metadataHasMany.tableData.editData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form> \n</ng-template>", styles: [".mdc-data-table__row:last-child .mdc-data-table__cell{border-bottom:1px solid rgba(0,0,0,.12)}.mat-dialog-title{padding:12px 20px;display:flex;justify-content:space-between;align-items:center}.mat-dialog-title div{font-size:var(--mdc-dialog-subhead-size, 14px);font-weight:var(--mdc-dialog-subhead-weight, 500)}::ng-deep .mdc-dialog .mdc-dialog__content{padding:6px 20px!important}mat-dialog-actions{justify-content:space-between;align-items:center;padding-left:20px;padding-right:20px}mat-spinner{margin:10px auto}::ng-deep .mat-mdc-tab-body-wrapper{margin-left:-12px;margin-right:-12px}::ng-deep mat-tab-body{padding-top:10px;padding-left:12px;padding-right:12px}::ng-deep mat-tab-body .mat-mdc-tab-body-content{overflow:initial}::ng-deep .mat-mdc-form-field.mat-form-field-disabled label{color:#0009}::ng-deep .mat-mdc-form-field.mat-form-field-disabled input,::ng-deep .mat-mdc-form-field.mat-form-field-disabled textarea,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-select-disabled,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-select-value{color:#000}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-chip.mat-mdc-standard-chip.mat-mdc-chip-disabled{opacity:1}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-chip.mat-mdc-standard-chip.mat-mdc-chip-disabled button{opacity:.2}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-date-range-input-inner:disabled{color:#000}::ng-deep .mat-mdc-form-field .mat-mdc-slide-toggle{opacity:1}.entityArray .elevation-container{border-radius:5px;padding:15px;margin-bottom:15px;margin-top:15px}.entityArray .array-headline{padding-bottom:10px}.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 .enabled:hover{cursor:pointer}.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}.hasMany button{width:100%;height:56px;line-height:24px;font-size:16px}.hasMany .title{text-align:center}.hasMany .elevation-container{border-radius:5px;padding:5px;margin-bottom:15px}.hasMany .mat-column-select{flex:0 0 75px}.hasMany .enabled:hover{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i2$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"] }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i4$2.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "panelWidth", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "component", type: i5$1.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i4.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }, { kind: "component", type: i6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i6$2.MatTab, selector: "mat-tab", inputs: ["disabled"], exportAs: ["matTab"] }, { kind: "component", type: i6$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "disableRipple", "fitInkBarToContent", "mat-stretch-tabs"], exportAs: ["matTabGroup"] }, { kind: "component", type: i9.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { kind: "component", type: i9.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i9.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { kind: "component", type: i15.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i16.MatPaginator, selector: "mat-paginator", inputs: ["disabled"], exportAs: ["matPaginator"] }, { kind: "component", type: DisplayColumnValueComponent, selector: "display-column-value", inputs: ["entity", "ComponentClass"] }, { kind: "component", type: StringInputComponent, selector: "string-input" }, { kind: "component", type: StringTextboxInputComponent, selector: "string-textbox-input" }, { kind: "component", type: StringAutocompleteInputComponent, selector: "string-autocomplete-input" }, { kind: "component", type: StringDropdownInputComponent, selector: "string-dropdown-input" }, { kind: "component", type: StringPasswordInputComponent, selector: "string-password-input" }, { kind: "component", type: BooleanCheckboxInputComponent, selector: "boolean-checkbox-input" }, { kind: "component", type: BooleanToggleInputComponent, selector: "boolean-toggle-input" }, { kind: "component", type: BooleanDropdownInputComponent, selector: "boolean-dropdown-input" }, { kind: "component", type: NumberInputComponent, selector: "number-input" }, { kind: "component", type: NumberDropdownInputComponent, selector: "number-dropdown-input" }, { kind: "component", type: NumberSliderInputComponent, selector: "number-slider-input" }, { kind: "component", type: ArrayStringChipsInputComponent, selector: "array-string-chips-input" }, { kind: "component", type: ArrayStringAutocompleteChipsComponent, selector: "array-string-autocomplete-chips" }, { kind: "component", type: DateInputComponent, selector: "date-input" }, { kind: "component", type: DateRangeInputComponent, selector: "date-range-input" }, { kind: "component", type: DateTimeInputComponent, selector: "date-time-input" }, { kind: "component", type: ArrayDateInputComponent, selector: "array-date-input" }, { kind: "component", type: ArrayDateTimeInputComponent, selector: "array-date-time-input" }, { kind: "component", type: ArrayDateRangeInputComponent, selector: "array-date-range-input" }, { kind: "component", type: FileImageInputComponent, selector: "file-image-input" }, { kind: "component", type: FileDefaultInputComponent, selector: "file-default-input" }, { kind: "component", type: ReferencesManyInputComponent, selector: "references-many-input" }, { kind: "component", type: CustomInputComponent, selector: "custom-input" }, { kind: "component", type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit", "validEmpty", "isReadOnly"], outputs: ["inputChangeEvent"] }] });
|
|
4948
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: { entity: "entity", propertyKey: "propertyKey", getValidationErrorMessage: "getValidationErrorMessage", hideOmitForCreate: "hideOmitForCreate", hideOmitForEdit: "hideOmitForEdit", validEmpty: "validEmpty", isReadOnly: "isReadOnly" }, outputs: { inputChangeEvent: "inputChangeEvent" }, viewQueries: [{ propertyName: "addArrayItemDialog", first: true, predicate: ["addArrayItemDialog"], descendants: true }, { propertyName: "editArrayItemDialog", first: true, predicate: ["editArrayItemDialog"], descendants: true }, { propertyName: "hasManyPaginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "hasManySort", first: true, predicate: MatSort, descendants: true }, { propertyName: "hasManyFilter", first: true, predicate: ["filter"], descendants: true, static: true }, { propertyName: "createHasManyDialog", first: true, predicate: ["createHasManyDialog"], descendants: true }, { propertyName: "editHasManyDialog", first: true, predicate: ["editHasManyDialog"], 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 <!-------------------Array-------------------->\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 <!-------------- references many ------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.REFERENCES_MANY\">\n <references-many-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </references-many-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 <!-------------------------------------------->\n <!-------------------Object------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.OBJECT\">\n <b>{{metadataDefaultObject.displayName}}</b>\n <!-- iterates over the object properties -->\n <mat-tab-group *ngIf=\"objectPropertyTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of objectPropertyTabs; let tI = index; trackBy: trackByFn\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows;\">\n <ngx-mat-entity-input *ngFor=\"let key of row.keys; let rI = index; trackBy: trackByFn\"\n [entity]=\"objectProperty\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"isPropertyReadOnly(objectProperty, key)\"\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 </mat-tab>\n </mat-tab-group>\n\n <div *ngIf=\"objectPropertyTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of objectPropertyTabs[0].rows\">\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 [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"isPropertyReadOnly(objectProperty, key)\"\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 </div>\n\n <!-------------------------------------------->\n <!-------------- references one ------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.REFERENCES_ONE\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"internalEntity[internalPropertyKey]\"\n [name]=\"internalPropertyKey.toString() + 'input' + referencesOneUUID\"\n #inputModel=\"ngModel\"\n [disabled]=\"internalIsReadOnly\"\n [required]=\"metadata.required(entity)\"\n (ngModelChange)=\"setReferencesOneObject()\"\n >\n <mat-option *ngIf=\"!metadata.required(entity)\">-</mat-option>\n <mat-option *ngFor=\"let value of referencesOneDropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{internalGetValidationErrorMessage(inputModel)}}</mat-error>\n </mat-form-field>\n <!-- iterates over the references one properties -->\n <mat-tab-group *ngIf=\"referencesOnePropertyTabs && referencesOnePropertyTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of referencesOnePropertyTabs; let tI = index; trackBy: trackByFn\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows;\">\n <ngx-mat-entity-input *ngFor=\"let key of row.keys; let rI = index; trackBy: trackByFn\"\n [entity]=\"referencesOneObject\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(referencesOneObject, key, 'lg')}} col-md-{{EntityUtilities.getWidth(referencesOneObject, key, 'md')}} col-sm-{{EntityUtilities.getWidth(referencesOneObject, key, 'sm')}}\"\n (inputChangeEvent)=\"emitChange()\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n\n <div *ngIf=\"referencesOnePropertyTabs && referencesOnePropertyTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of referencesOnePropertyTabs[0].rows\">\n <ngx-mat-entity-input *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"referencesOneObject\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(referencesOneObject, key, 'lg')}} col-md-{{EntityUtilities.getWidth(referencesOneObject, key, 'md')}} col-sm-{{EntityUtilities.getWidth(referencesOneObject, key, 'sm')}}\"\n (inputChangeEvent)=\"emitChange()\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Array-------------------->\n <!-------------------------------------------->\n <div class=\"entityArray\" *ngSwitchCase=\"DecoratorTypes.ARRAY\">\n <div class=\"mat-elevation-z8 elevation-container\">\n <div class=\"array-headline\">\n <b>{{metadataEntityArray.displayName}}</b>\n </div>\n <div *ngIf=\"metadataEntityArray.createInline && !internalIsReadOnly\">\n <mat-tab-group *ngIf=\"arrayItemInlineTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of arrayItemInlineTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\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 </mat-tab>\n </mat-tab-group>\n\n <div *ngIf=\"arrayItemInlineTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of arrayItemInlineTabs[0].rows\">\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 </div>\n\n <div class=\"buttons\" *ngIf=\"!internalIsReadOnly\">\n <button type=\"button\" mat-raised-button\n [disabled]=\"metadataEntityArray.createInline && !isArrayItemValid\"\n (click)=\"addEntity()\">\n {{metadataEntityArray.addButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button\n [disabled]=\"!entityArraySelection.selected.length\"\n (click)=\"removeFromEntityArray()\">\n {{metadataEntityArray.removeButtonLabel}}\n </button>\n </div>\n \n <mat-table [dataSource]=\"entityArrayDataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\" *ngIf=\"!internalIsReadOnly\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox\n [disabled]=\"!entityArrayDataSource.data.length\" (change)=\"$event ? SelectionUtilities.masterToggle(entityArraySelection, entityArrayDataSource) : null\"\n [checked]=\"entityArraySelection.hasValue() && SelectionUtilities.isAllSelected(entityArraySelection, entityArrayDataSource)\"\n [indeterminate]=\"entityArraySelection.hasValue() && !SelectionUtilities.isAllSelected(entityArraySelection, entityArrayDataSource)\">\n </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let entity\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? entityArraySelection.toggle(entity) : null\" [checked]=\"entityArraySelection.isSelected(entity)\"></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.enabled]=\"!dCol.disableClick\" (click)=\"editArrayItem(entity, dCol)\" *matCellDef=\"let entity\">\n <ng-container *ngIf=\"dCol.Component\">\n <display-column-value [entity]=\"entity\" [ComponentClass]=\"dCol.Component\"></display-column-value>\n </ng-container>\n <ng-container *ngIf=\"!dCol.Component\">\n {{getDisplayColumnValue(entity, dCol)}}\n </ng-container>\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"entityArrayDisplayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: entityArrayDisplayedColumns\"></mat-row>\n </mat-table>\n \n <div class=\"array-error\" *ngIf=\"metadataEntityArray.required(entity) && !entityArrayDataSource.data.length\">\n {{metadataEntityArray.missingErrorMessage}}\n </div>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!------------------ has many ---------------->\n <!-------------------------------------------->\n <div class=\"hasMany\" *ngSwitchCase=\"DecoratorTypes.HAS_MANY\">\n <h2 class=\"title\">{{metadataHasMany.tableData.baseData.title}}</h2>\n\n <div class=\"row\">\n <mat-form-field class=\"col-lg-8 col-md-6 col-sm-12\">\n <mat-label>{{metadataHasMany.tableData.baseData.searchLabel}}</mat-label>\n <input matInput (keyup)=\"applyHasManyFilter($event)\">\n </mat-form-field>\n <div\n *ngIf=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-lg-2]=\"hasManyAllowCreate\"\n [class.col-lg-4]=\"!hasManyAllowCreate\"\n [class.col-md-3]=\"hasManyAllowCreate\"\n [class.col-md-6]=\"!hasManyAllowCreate\"\n [class.col-sm-6]=\"hasManyAllowCreate\"\n [class.col-sm-12]=\"!hasManyAllowCreate\"\n >\n <button type=\"button\" class=\"actions-button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{metadataHasMany.tableData.baseData.tableActionsLabel}}\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button *ngIf=\"metadataHasMany.tableData.baseData.allowJsonImport\" type=\"button\" [disabled]=\"hasManyTableActionDisabled(hasManyImportAction)\" (click)=\"runHasManyTableAction(hasManyImportAction)\" mat-menu-item>\n {{hasManyImportAction.displayName}}\n </button>\n <button type=\"button\" *ngFor=\"let action of metadataHasMany.tableData.baseData.tableActions\" [disabled]=\"hasManyTableActionDisabled(action)\" (click)=\"runHasManyTableAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n\n <div\n *ngIf=\"hasManyAllowCreate\"\n [class.col-lg-2]=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-lg-4]=\"!metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-md-3]=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-md-6]=\"!metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-sm-6]=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-sm-12]=\"!metadataHasMany.tableData.baseData.tableActions.length\"\n >\n <button type=\"button\" class=\"create-button\" (click)=\"createHasManyEntity()\" mat-raised-button>\n {{metadataHasMany.tableData.baseData.createButtonLabel}}\n </button>\n </div>\n </div>\n\n <div class=\"mat-elevation-z8 elevation-container\">\n <mat-table [dataSource]=\"hasManyDataSource\" matSort>\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox (change)=\"$event ? SelectionUtilities.masterToggle(hasManySelection, hasManyDataSource) : null\"\n [checked]=\"hasManySelection.hasValue() && SelectionUtilities.isAllSelected(hasManySelection, hasManyDataSource)\"\n [indeterminate]=\"hasManySelection.hasValue() && !SelectionUtilities.isAllSelected(hasManySelection, hasManyDataSource)\">\n </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let entity\" class=\"enabled\">\n <mat-checkbox (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? hasManySelection.toggle(entity) : null\"\n [checked]=\"hasManySelection.isSelected(entity)\">\n </mat-checkbox>\n </mat-cell>\n </ng-container>\n\n <ng-container *ngFor=\"let dCol of metadataHasMany.tableData.baseData.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell [class.enabled]=\"!dCol.disableClick && (hasManyAllowUpdate(entity) || hasManyAllowRead(entity))\"\n (click)=\"editHasManyEntity(entity, dCol)\"\n *matCellDef=\"let entity\"\n >\n <ng-container *ngIf=\"dCol.Component\">\n <display-column-value [entity]=\"entity\" [ComponentClass]=\"dCol.Component\"></display-column-value>\n </ng-container>\n <ng-container *ngIf=\"!dCol.Component\">\n {{getDisplayColumnValue(entity, dCol)}}\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <mat-header-row *matHeaderRowDef=\"displayedHasManyColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedHasManyColumns\"></mat-row>\n </mat-table>\n\n <mat-spinner *ngIf=\"hasManyIsLoading && metadataHasMany.tableData.baseData.displayLoadingSpinner\">\n </mat-spinner>\n\n <mat-paginator [length]=\"hasManyDataSource.filteredData.length\" [pageIndex]=\"0\" [pageSize]=\"10\" [pageSizeOptions]=\"[5, 10, 25, 50]\"></mat-paginator>\n </div>\n </div>\n\n <div *ngSwitchDefault>ERROR: The type {{type}} is not known.</div>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<!--------------------------------------------------------->\n<!--------------------Add Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #addArrayItemDialog>\n <div class=\"mat-dialog-title\">\n <div>{{addArrayItemDialogData.title}}</div>\n </div>\n\n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"arrayItemDialogTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of arrayItemDialogTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\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 </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"arrayItemDialogTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\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 </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" mat-raised-button (click)=\"addArrayItem()\" [disabled]=\"!isArrayItemValid\">\n {{addArrayItemDialogData.createButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"closeAddArrayItemDialog()\" class=\"cancel-button\">\n {{addArrayItemDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form>\n\n</ng-template>\n\n<!--------------------------------------------------------->\n<!--------------------Edit Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #editArrayItemDialog>\n <div class=\"mat-dialog-title\">\n <div>{{editArrayItemDialogData.title(arrayItemPriorChanges)}}</div>\n </div>\n \n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"arrayItemDialogTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of arrayItemDialogTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\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)=\"checkArrayItem()\"\n [isReadOnly]=\"isPropertyReadOnly(arrayItem, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"arrayItemDialogTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\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)=\"checkArrayItem()\"\n [isReadOnly]=\"isPropertyReadOnly(arrayItem, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" (click)=\"saveArrayItem()\" mat-raised-button [disabled]=\"internalIsReadOnly || !isArrayItemValid || !isArrayItemDirty\">\n {{editArrayItemDialogData.confirmButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"closeEditArrayItemDialog()\" class=\"cancel-button\">\n {{editArrayItemDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form>\n</ng-template>\n\n<!--------------------------------------------------------->\n<!--------------------Create Has Many Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #createHasManyDialog>\n <div class=\"mat-dialog-title\">\n <div>{{metadataHasMany.tableData.createDialogData.title}}</div>\n </div>\n \n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"hasManyCreateTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of hasManyCreateTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsHasManyEntityValid('create')\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"hasManyCreateTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of hasManyCreateTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsHasManyEntityValid('create')\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" (click)=\"dialogCreateHasMany()\" mat-raised-button [disabled]=\"!isHasManyEntityValid\">\n {{metadataHasMany.tableData.createDialogData.createButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"dialogCancelCreateHasMany()\" class=\"cancel-button\">\n {{metadataHasMany.tableData.createDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form>\n \n</ng-template>\n\n<ng-template #editHasManyDialog>\n <div class=\"mat-dialog-title\">\n <div>{{metadataHasMany.tableData.editData.title(hasManyEntityPriorChanges)}}</div>\n\n <div class=\"actions-container\">\n <button *ngIf=\"metadataHasMany.tableData.editData.actions.length\" type=\"button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{metadataHasMany.tableData.editData.actionsLabel}}\n </button>\n <mat-menu #menu=\"matMenu\">\n <button type=\"button\" *ngFor=\"let action of metadataHasMany.tableData.editData.actions\" [disabled]=\"hasManyEditActionDisabled(action)\" (click)=\"hasManyRunEditAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n \n <button type=\"button\" *ngIf=\"hasManyAllowDelete(hasManyEntity)\" mat-raised-button (click)=\"deleteHasManyEntity()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{metadataHasMany.tableData.editData.deleteButtonLabel}}\n </button>\n </div>\n </div>\n \n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"hasManyUpdateTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of hasManyUpdateTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkHasManyEntity()\"\n [isReadOnly]=\"isPropertyReadOnly(hasManyEntity, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"hasManyUpdateTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of hasManyUpdateTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkHasManyEntity()\"\n [isReadOnly]=\"isPropertyReadOnly(hasManyEntity, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" (click)=\"dialogEditHasMany()\" mat-raised-button [disabled]=\"internalIsReadOnly || !isHasManyEntityValid || !isHasManyEntityDirty\">\n {{metadataHasMany.tableData.editData.confirmButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"dialogCancelEditHasMany()\" class=\"cancel-button\">\n {{metadataHasMany.tableData.editData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form> \n</ng-template>", styles: [".mdc-data-table__row:last-child .mdc-data-table__cell{border-bottom:1px solid rgba(0,0,0,.12)}.mat-dialog-title{padding:12px 20px;display:flex;justify-content:space-between;align-items:center}.mat-dialog-title div{font-size:var(--mdc-dialog-subhead-size, 14px);font-weight:var(--mdc-dialog-subhead-weight, 500)}::ng-deep .mdc-dialog .mdc-dialog__content{padding:6px 20px!important}mat-dialog-actions{justify-content:space-between;align-items:center;padding-left:20px;padding-right:20px}mat-spinner{margin:10px auto}::ng-deep .mat-mdc-tab-body-wrapper{margin-left:-12px;margin-right:-12px}::ng-deep mat-tab-body{padding-top:10px;padding-left:12px;padding-right:12px}::ng-deep mat-tab-body .mat-mdc-tab-body-content{overflow:initial}::ng-deep .mat-mdc-form-field.mat-form-field-disabled label{color:#0009}::ng-deep .mat-mdc-form-field.mat-form-field-disabled input,::ng-deep .mat-mdc-form-field.mat-form-field-disabled textarea,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-select-disabled,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-select-value{color:#000!important}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-checkbox .mdc-checkbox__native-control[disabled]:not(:checked):not(:indeterminate):not([data-indeterminate=true])~.mdc-checkbox__background{border-color:#707070}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-checkbox .mdc-checkbox__native-control[disabled]:checked~.mdc-checkbox__background,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-checkbox .mdc-checkbox__native-control[disabled]:indeterminate~.mdc-checkbox__background,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-checkbox .mdc-checkbox__native-control[data-indeterminate=true][disabled]~.mdc-checkbox__background{background-color:#000}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-chip.mat-mdc-standard-chip.mat-mdc-chip-disabled{opacity:1}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-chip.mat-mdc-standard-chip.mat-mdc-chip-disabled button{opacity:.2}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-switch.mdc-switch--selected:disabled .mdc-switch__icons,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-switch.mdc-switch--unselected:disabled .mdc-switch__icons{opacity:1}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-switch.mdc-switch--selected:disabled .mdc-switch__handle:after,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-switch.mdc-switch--unselected:disabled .mdc-switch__handle:after{opacity:1;background:black}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-switch.mdc-switch--selected:disabled .mdc-switch__track,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-switch.mdc-switch--unselected:disabled .mdc-switch__track{opacity:.3}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-date-range-input-inner:disabled{color:#000}::ng-deep #slider.mat-mdc-slider.mdc-slider--disabled{opacity:1}::ng-deep #slider.mat-mdc-slider.mdc-slider--disabled .mdc-slider__input{cursor:default}::ng-deep #slider.mat-mdc-slider.mdc-slider--disabled mat-slider-visual-thumb .mat-mdc-slider,::ng-deep #slider.mat-mdc-slider.mdc-slider--disabled mat-slider-visual-thumb .mdc-slider__thumb:hover,::ng-deep #slider.mat-mdc-slider.mdc-slider--disabled mat-slider-visual-thumb .mdc-slider__thumb-knob{background-color:#000;border-color:#000}::ng-deep .mat-mdc-form-field .mat-mdc-slide-toggle{opacity:1}.entityArray .elevation-container{border-radius:5px;padding:15px;margin-bottom:15px;margin-top:15px}.entityArray .array-headline{padding-bottom:10px}.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 .enabled:hover{cursor:pointer}.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}.hasMany button{width:100%;height:56px;line-height:24px;font-size:16px}.hasMany .title{text-align:center}.hasMany .elevation-container{border-radius:5px;padding:5px;margin-bottom:15px}.hasMany .mat-column-select{flex:0 0 75px}.hasMany .enabled:hover{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i2$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"] }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i4$2.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "panelWidth", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "component", type: i5$1.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i4.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }, { kind: "component", type: i6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i6$2.MatTab, selector: "mat-tab", inputs: ["disabled"], exportAs: ["matTab"] }, { kind: "component", type: i6$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "disableRipple", "fitInkBarToContent", "mat-stretch-tabs"], exportAs: ["matTabGroup"] }, { kind: "component", type: i14.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { kind: "component", type: i14.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i14.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { kind: "component", type: i15.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i16.MatPaginator, selector: "mat-paginator", inputs: ["disabled"], exportAs: ["matPaginator"] }, { kind: "component", type: DisplayColumnValueComponent, selector: "display-column-value", inputs: ["entity", "ComponentClass"] }, { kind: "directive", type: i18.MatSort, selector: "[matSort]", inputs: ["matSortDisabled", "matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i18.MatSortHeader, selector: "[mat-sort-header]", inputs: ["disabled", "mat-sort-header", "arrowPosition", "start", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: StringInputComponent, selector: "string-input" }, { kind: "component", type: StringTextboxInputComponent, selector: "string-textbox-input" }, { kind: "component", type: StringAutocompleteInputComponent, selector: "string-autocomplete-input" }, { kind: "component", type: StringDropdownInputComponent, selector: "string-dropdown-input" }, { kind: "component", type: StringPasswordInputComponent, selector: "string-password-input" }, { kind: "component", type: BooleanCheckboxInputComponent, selector: "boolean-checkbox-input" }, { kind: "component", type: BooleanToggleInputComponent, selector: "boolean-toggle-input" }, { kind: "component", type: BooleanDropdownInputComponent, selector: "boolean-dropdown-input" }, { kind: "component", type: NumberInputComponent, selector: "number-input" }, { kind: "component", type: NumberDropdownInputComponent, selector: "number-dropdown-input" }, { kind: "component", type: NumberSliderInputComponent, selector: "number-slider-input" }, { kind: "component", type: ArrayStringChipsInputComponent, selector: "array-string-chips-input" }, { kind: "component", type: ArrayStringAutocompleteChipsComponent, selector: "array-string-autocomplete-chips" }, { kind: "component", type: DateInputComponent, selector: "date-input" }, { kind: "component", type: DateRangeInputComponent, selector: "date-range-input" }, { kind: "component", type: DateTimeInputComponent, selector: "date-time-input" }, { kind: "component", type: ArrayDateInputComponent, selector: "array-date-input" }, { kind: "component", type: ArrayDateTimeInputComponent, selector: "array-date-time-input" }, { kind: "component", type: ArrayDateRangeInputComponent, selector: "array-date-range-input" }, { kind: "component", type: FileImageInputComponent, selector: "file-image-input" }, { kind: "component", type: FileDefaultInputComponent, selector: "file-default-input" }, { kind: "component", type: ReferencesManyInputComponent, selector: "references-many-input" }, { kind: "component", type: CustomInputComponent, selector: "custom-input" }, { kind: "component", type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit", "validEmpty", "isReadOnly"], outputs: ["inputChangeEvent"] }] });
|
|
4620
4949
|
}
|
|
4621
4950
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityInputComponent, decorators: [{
|
|
4622
4951
|
type: Component,
|
|
4623
|
-
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 <!-------------------Array-------------------->\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 <!-------------- references many ------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.REFERENCES_MANY\">\n <references-many-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </references-many-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 <!-------------------------------------------->\n <!-------------------Object------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.OBJECT\">\n <b>{{metadataDefaultObject.displayName}}</b>\n <!-- iterates over the object properties -->\n <mat-tab-group *ngIf=\"objectPropertyTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of objectPropertyTabs; let tI = index; trackBy: trackByFn\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows;\">\n <ngx-mat-entity-input *ngFor=\"let key of row.keys; let rI = index; trackBy: trackByFn\"\n [entity]=\"objectProperty\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"isPropertyReadOnly(objectProperty, key)\"\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 </mat-tab>\n </mat-tab-group>\n\n <div *ngIf=\"objectPropertyTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of objectPropertyTabs[0].rows\">\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 [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"isPropertyReadOnly(objectProperty, key)\"\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 </div>\n\n <!-------------------------------------------->\n <!-------------- references one ------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.REFERENCES_ONE\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"internalEntity[internalPropertyKey]\"\n [name]=\"internalPropertyKey.toString() + 'input' + referencesOneUUID\"\n #inputModel=\"ngModel\"\n [disabled]=\"internalIsReadOnly\"\n [required]=\"metadata.required(entity)\"\n (ngModelChange)=\"setReferencesOneObject()\"\n >\n <mat-option *ngIf=\"!metadata.required(entity)\">-</mat-option>\n <mat-option *ngFor=\"let value of referencesOneDropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{internalGetValidationErrorMessage(inputModel)}}</mat-error>\n </mat-form-field>\n <!-- iterates over the references one properties -->\n <mat-tab-group *ngIf=\"referencesOnePropertyTabs && referencesOnePropertyTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of referencesOnePropertyTabs; let tI = index; trackBy: trackByFn\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows;\">\n <ngx-mat-entity-input *ngFor=\"let key of row.keys; let rI = index; trackBy: trackByFn\"\n [entity]=\"referencesOneObject\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(referencesOneObject, key, 'lg')}} col-md-{{EntityUtilities.getWidth(referencesOneObject, key, 'md')}} col-sm-{{EntityUtilities.getWidth(referencesOneObject, key, 'sm')}}\"\n (inputChangeEvent)=\"emitChange()\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n\n <div *ngIf=\"referencesOnePropertyTabs && referencesOnePropertyTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of referencesOnePropertyTabs[0].rows\">\n <ngx-mat-entity-input *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"referencesOneObject\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(referencesOneObject, key, 'lg')}} col-md-{{EntityUtilities.getWidth(referencesOneObject, key, 'md')}} col-sm-{{EntityUtilities.getWidth(referencesOneObject, key, 'sm')}}\"\n (inputChangeEvent)=\"emitChange()\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Array-------------------->\n <!-------------------------------------------->\n <div class=\"entityArray\" *ngSwitchCase=\"DecoratorTypes.ARRAY\">\n <div class=\"mat-elevation-z8 elevation-container\">\n <div class=\"array-headline\">\n <b>{{metadataEntityArray.displayName}}</b>\n </div>\n <div *ngIf=\"metadataEntityArray.createInline && !internalIsReadOnly\">\n <mat-tab-group *ngIf=\"arrayItemInlineTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of arrayItemInlineTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\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 </mat-tab>\n </mat-tab-group>\n\n <div *ngIf=\"arrayItemInlineTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of arrayItemInlineTabs[0].rows\">\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 </div>\n\n <div class=\"buttons\" *ngIf=\"!internalIsReadOnly\">\n <button type=\"button\" mat-raised-button\n [disabled]=\"metadataEntityArray.createInline && !isArrayItemValid\"\n (click)=\"addEntity()\">\n {{metadataEntityArray.addButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button\n [disabled]=\"!entityArraySelection.selected.length\"\n (click)=\"removeFromEntityArray()\">\n {{metadataEntityArray.removeButtonLabel}}\n </button>\n </div>\n \n <mat-table [dataSource]=\"entityArrayDataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\" *ngIf=\"!internalIsReadOnly\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox\n [disabled]=\"!entityArrayDataSource.data.length\" (change)=\"$event ? SelectionUtilities.masterToggle(entityArraySelection, entityArrayDataSource) : null\"\n [checked]=\"entityArraySelection.hasValue() && SelectionUtilities.isAllSelected(entityArraySelection, entityArrayDataSource)\"\n [indeterminate]=\"entityArraySelection.hasValue() && !SelectionUtilities.isAllSelected(entityArraySelection, entityArrayDataSource)\">\n </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let entity\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? entityArraySelection.toggle(entity) : null\" [checked]=\"entityArraySelection.isSelected(entity)\"></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.enabled]=\"!dCol.disableClick\" (click)=\"editArrayItem(entity, dCol)\" *matCellDef=\"let entity\">\n <ng-container *ngIf=\"dCol.Component\">\n <display-column-value [entity]=\"entity\" [ComponentClass]=\"dCol.Component\"></display-column-value>\n </ng-container>\n <ng-container *ngIf=\"!dCol.Component\">\n {{getDisplayColumnValue(entity, dCol)}}\n </ng-container>\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"entityArrayDisplayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: entityArrayDisplayedColumns\"></mat-row>\n </mat-table>\n \n <div class=\"array-error\" *ngIf=\"metadataEntityArray.required(entity) && !entityArrayDataSource.data.length\">\n {{metadataEntityArray.missingErrorMessage}}\n </div>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!------------------ has many ---------------->\n <!-------------------------------------------->\n <div class=\"hasMany\" *ngSwitchCase=\"DecoratorTypes.HAS_MANY\">\n <h2 class=\"title\">{{metadataHasMany.tableData.baseData.title}}</h2>\n\n <div class=\"row\">\n <mat-form-field class=\"col-lg-8 col-md-6 col-sm-12\">\n <mat-label>{{metadataHasMany.tableData.baseData.searchLabel}}</mat-label>\n <input matInput (keyup)=\"applyHasManyFilter($event)\">\n </mat-form-field>\n <div\n *ngIf=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-lg-2]=\"hasManyAllowCreate\"\n [class.col-lg-4]=\"!hasManyAllowCreate\"\n [class.col-md-3]=\"hasManyAllowCreate\"\n [class.col-md-6]=\"!hasManyAllowCreate\"\n [class.col-sm-6]=\"hasManyAllowCreate\"\n [class.col-sm-12]=\"!hasManyAllowCreate\"\n >\n <button type=\"button\" class=\"actions-button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{metadataHasMany.tableData.baseData.tableActionsLabel}}\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button *ngIf=\"metadataHasMany.tableData.baseData.allowJsonImport\" type=\"button\" [disabled]=\"hasManyTableActionDisabled(hasManyImportAction)\" (click)=\"runHasManyTableAction(hasManyImportAction)\" mat-menu-item>\n {{hasManyImportAction.displayName}}\n </button>\n <button type=\"button\" *ngFor=\"let action of metadataHasMany.tableData.baseData.tableActions\" [disabled]=\"hasManyTableActionDisabled(action)\" (click)=\"runHasManyTableAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n\n <div\n *ngIf=\"hasManyAllowCreate\"\n [class.col-lg-2]=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-lg-4]=\"!metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-md-3]=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-md-6]=\"!metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-sm-6]=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-sm-12]=\"!metadataHasMany.tableData.baseData.tableActions.length\"\n >\n <button type=\"button\" class=\"create-button\" (click)=\"createHasManyEntity()\" mat-raised-button>\n {{metadataHasMany.tableData.baseData.createButtonLabel}}\n </button>\n </div>\n </div>\n\n <div class=\"mat-elevation-z8 elevation-container\">\n <mat-table [dataSource]=\"hasManyDataSource\" matSort>\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox (change)=\"$event ? SelectionUtilities.masterToggle(hasManySelection, hasManyDataSource) : null\" [checked]=\"hasManySelection.hasValue() && SelectionUtilities.isAllSelected(hasManySelection, hasManyDataSource)\" [indeterminate]=\"hasManySelection.hasValue() && !SelectionUtilities.isAllSelected(hasManySelection, hasManyDataSource)\"> </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let entity\" class=\"enabled\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? hasManySelection.toggle(entity) : null\" [checked]=\"hasManySelection.isSelected(entity)\"> </mat-checkbox>\n </mat-cell>\n </ng-container>\n\n <ng-container *ngFor=\"let dCol of metadataHasMany.tableData.baseData.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell [class.enabled]=\"!dCol.disableClick && (hasManyAllowUpdate(entity) || hasManyAllowRead(entity))\" (click)=\"editHasManyEntity(entity, dCol)\" *matCellDef=\"let entity\">\n <ng-container *ngIf=\"dCol.Component\">\n <display-column-value [entity]=\"entity\" [ComponentClass]=\"dCol.Component\"></display-column-value>\n </ng-container>\n <ng-container *ngIf=\"!dCol.Component\">\n {{getDisplayColumnValue(entity, dCol)}}\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <mat-header-row *matHeaderRowDef=\"displayedHasManyColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedHasManyColumns\"></mat-row>\n </mat-table>\n\n <mat-spinner *ngIf=\"hasManyIsLoading && metadataHasMany.tableData.baseData.displayLoadingSpinner\">\n </mat-spinner>\n\n <mat-paginator [length]=\"hasManyDataSource.filteredData.length\" [pageIndex]=\"0\" [pageSize]=\"10\" [pageSizeOptions]=\"[5, 10, 25, 50]\"></mat-paginator>\n </div>\n </div>\n\n <div *ngSwitchDefault>ERROR: The type {{type}} is not known.</div>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<!--------------------------------------------------------->\n<!--------------------Add Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #addArrayItemDialog>\n <div class=\"mat-dialog-title\">\n <div>{{addArrayItemDialogData.title}}</div>\n </div>\n\n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"arrayItemDialogTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of arrayItemDialogTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\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 </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"arrayItemDialogTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\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 </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" mat-raised-button (click)=\"addArrayItem()\" [disabled]=\"!isArrayItemValid\">\n {{addArrayItemDialogData.createButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"closeAddArrayItemDialog()\" class=\"cancel-button\">\n {{addArrayItemDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form>\n\n</ng-template>\n\n<!--------------------------------------------------------->\n<!--------------------Edit Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #editArrayItemDialog>\n <div class=\"mat-dialog-title\">\n <div>{{editArrayItemDialogData.title(arrayItemPriorChanges)}}</div>\n </div>\n \n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"arrayItemDialogTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of arrayItemDialogTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\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)=\"checkArrayItem()\"\n [isReadOnly]=\"isPropertyReadOnly(arrayItem, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"arrayItemDialogTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\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)=\"checkArrayItem()\"\n [isReadOnly]=\"isPropertyReadOnly(arrayItem, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" (click)=\"saveArrayItem()\" mat-raised-button [disabled]=\"internalIsReadOnly || !isArrayItemValid || !isArrayItemDirty\">\n {{editArrayItemDialogData.confirmButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"closeEditArrayItemDialog()\" class=\"cancel-button\">\n {{editArrayItemDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form>\n</ng-template>\n\n<!--------------------------------------------------------->\n<!--------------------Create Has Many Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #createHasManyDialog>\n <div class=\"mat-dialog-title\">\n <div>{{metadataHasMany.tableData.createDialogData.title}}</div>\n </div>\n \n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"hasManyCreateTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of hasManyCreateTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsHasManyEntityValid('create')\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"hasManyCreateTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of hasManyCreateTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsHasManyEntityValid('create')\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" (click)=\"dialogCreateHasMany()\" mat-raised-button [disabled]=\"!isHasManyEntityValid\">\n {{metadataHasMany.tableData.createDialogData.createButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"dialogCancelCreateHasMany()\" class=\"cancel-button\">\n {{metadataHasMany.tableData.createDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form>\n \n</ng-template>\n\n<ng-template #editHasManyDialog>\n <div class=\"mat-dialog-title\">\n <div>{{metadataHasMany.tableData.editData.title(hasManyEntityPriorChanges)}}</div>\n <button type=\"button\" *ngIf=\"hasManyAllowDelete(hasManyEntity)\" mat-raised-button (click)=\"deleteHasManyEntity()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{metadataHasMany.tableData.editData.deleteButtonLabel}}\n </button>\n </div>\n \n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"hasManyUpdateTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of hasManyUpdateTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkHasManyEntity()\"\n [isReadOnly]=\"isPropertyReadOnly(hasManyEntity, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"hasManyUpdateTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of hasManyUpdateTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkHasManyEntity()\"\n [isReadOnly]=\"isPropertyReadOnly(hasManyEntity, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" (click)=\"dialogEditHasMany()\" mat-raised-button [disabled]=\"internalIsReadOnly || !isHasManyEntityValid || !isHasManyEntityDirty\">\n {{metadataHasMany.tableData.editData.confirmButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"dialogCancelEditHasMany()\" class=\"cancel-button\">\n {{metadataHasMany.tableData.editData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form> \n</ng-template>", styles: [".mdc-data-table__row:last-child .mdc-data-table__cell{border-bottom:1px solid rgba(0,0,0,.12)}.mat-dialog-title{padding:12px 20px;display:flex;justify-content:space-between;align-items:center}.mat-dialog-title div{font-size:var(--mdc-dialog-subhead-size, 14px);font-weight:var(--mdc-dialog-subhead-weight, 500)}::ng-deep .mdc-dialog .mdc-dialog__content{padding:6px 20px!important}mat-dialog-actions{justify-content:space-between;align-items:center;padding-left:20px;padding-right:20px}mat-spinner{margin:10px auto}::ng-deep .mat-mdc-tab-body-wrapper{margin-left:-12px;margin-right:-12px}::ng-deep mat-tab-body{padding-top:10px;padding-left:12px;padding-right:12px}::ng-deep mat-tab-body .mat-mdc-tab-body-content{overflow:initial}::ng-deep .mat-mdc-form-field.mat-form-field-disabled label{color:#0009}::ng-deep .mat-mdc-form-field.mat-form-field-disabled input,::ng-deep .mat-mdc-form-field.mat-form-field-disabled textarea,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-select-disabled,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-select-value{color:#000}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-chip.mat-mdc-standard-chip.mat-mdc-chip-disabled{opacity:1}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-chip.mat-mdc-standard-chip.mat-mdc-chip-disabled button{opacity:.2}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-date-range-input-inner:disabled{color:#000}::ng-deep .mat-mdc-form-field .mat-mdc-slide-toggle{opacity:1}.entityArray .elevation-container{border-radius:5px;padding:15px;margin-bottom:15px;margin-top:15px}.entityArray .array-headline{padding-bottom:10px}.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 .enabled:hover{cursor:pointer}.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}.hasMany button{width:100%;height:56px;line-height:24px;font-size:16px}.hasMany .title{text-align:center}.hasMany .elevation-container{border-radius:5px;padding:5px;margin-bottom:15px}.hasMany .mat-column-select{flex:0 0 75px}.hasMany .enabled:hover{cursor:pointer}\n"] }]
|
|
4952
|
+
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 <!-------------------Array-------------------->\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 <!-------------- references many ------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.REFERENCES_MANY\">\n <references-many-input\n (inputChangeEvent)=\"emitChange()\"\n [entity]=\"internalEntity\"\n [key]=\"internalPropertyKey\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [isReadOnly]=\"internalIsReadOnly\"\n >\n </references-many-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 <!-------------------------------------------->\n <!-------------------Object------------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.OBJECT\">\n <b>{{metadataDefaultObject.displayName}}</b>\n <!-- iterates over the object properties -->\n <mat-tab-group *ngIf=\"objectPropertyTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of objectPropertyTabs; let tI = index; trackBy: trackByFn\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows;\">\n <ngx-mat-entity-input *ngFor=\"let key of row.keys; let rI = index; trackBy: trackByFn\"\n [entity]=\"objectProperty\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"isPropertyReadOnly(objectProperty, key)\"\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 </mat-tab>\n </mat-tab-group>\n\n <div *ngIf=\"objectPropertyTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of objectPropertyTabs[0].rows\">\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 [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"isPropertyReadOnly(objectProperty, key)\"\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 </div>\n\n <!-------------------------------------------->\n <!-------------- references one ------------->\n <!-------------------------------------------->\n <div *ngSwitchCase=\"DecoratorTypes.REFERENCES_ONE\">\n <mat-form-field>\n <mat-label>{{metadata.displayName}}</mat-label>\n <mat-select [(ngModel)]=\"internalEntity[internalPropertyKey]\"\n [name]=\"internalPropertyKey.toString() + 'input' + referencesOneUUID\"\n #inputModel=\"ngModel\"\n [disabled]=\"internalIsReadOnly\"\n [required]=\"metadata.required(entity)\"\n (ngModelChange)=\"setReferencesOneObject()\"\n >\n <mat-option *ngIf=\"!metadata.required(entity)\">-</mat-option>\n <mat-option *ngFor=\"let value of referencesOneDropdownValues\" [value]=\"value.value\">{{value.displayName}}</mat-option>\n </mat-select>\n <mat-error>{{internalGetValidationErrorMessage(inputModel)}}</mat-error>\n </mat-form-field>\n <!-- iterates over the references one properties -->\n <mat-tab-group *ngIf=\"referencesOnePropertyTabs && referencesOnePropertyTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of referencesOnePropertyTabs; let tI = index; trackBy: trackByFn\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows;\">\n <ngx-mat-entity-input *ngFor=\"let key of row.keys; let rI = index; trackBy: trackByFn\"\n [entity]=\"referencesOneObject\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(referencesOneObject, key, 'lg')}} col-md-{{EntityUtilities.getWidth(referencesOneObject, key, 'md')}} col-sm-{{EntityUtilities.getWidth(referencesOneObject, key, 'sm')}}\"\n (inputChangeEvent)=\"emitChange()\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n\n <div *ngIf=\"referencesOnePropertyTabs && referencesOnePropertyTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of referencesOnePropertyTabs[0].rows\">\n <ngx-mat-entity-input *ngFor=\"let key of row.keys; let i = index; trackBy: trackByFn\"\n [entity]=\"referencesOneObject\"\n [propertyKey]=\"key\"\n [getValidationErrorMessage]=\"internalGetValidationErrorMessage\"\n [hideOmitForCreate]=\"hideOmitForCreate\"\n [hideOmitForEdit]=\"hideOmitForEdit\"\n [validEmpty]=\"!metadata.required(entity)\"\n [isReadOnly]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(referencesOneObject, key, 'lg')}} col-md-{{EntityUtilities.getWidth(referencesOneObject, key, 'md')}} col-sm-{{EntityUtilities.getWidth(referencesOneObject, key, 'sm')}}\"\n (inputChangeEvent)=\"emitChange()\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!-------------------Array-------------------->\n <!-------------------------------------------->\n <div class=\"entityArray\" *ngSwitchCase=\"DecoratorTypes.ARRAY\">\n <div class=\"mat-elevation-z8 elevation-container\">\n <div class=\"array-headline\">\n <b>{{metadataEntityArray.displayName}}</b>\n </div>\n <div *ngIf=\"metadataEntityArray.createInline && !internalIsReadOnly\">\n <mat-tab-group *ngIf=\"arrayItemInlineTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of arrayItemInlineTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\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 </mat-tab>\n </mat-tab-group>\n\n <div *ngIf=\"arrayItemInlineTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of arrayItemInlineTabs[0].rows\">\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 </div>\n\n <div class=\"buttons\" *ngIf=\"!internalIsReadOnly\">\n <button type=\"button\" mat-raised-button\n [disabled]=\"metadataEntityArray.createInline && !isArrayItemValid\"\n (click)=\"addEntity()\">\n {{metadataEntityArray.addButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button\n [disabled]=\"!entityArraySelection.selected.length\"\n (click)=\"removeFromEntityArray()\">\n {{metadataEntityArray.removeButtonLabel}}\n </button>\n </div>\n \n <mat-table [dataSource]=\"entityArrayDataSource\">\n <!-- select Column -->\n <ng-container matColumnDef=\"select\" *ngIf=\"!internalIsReadOnly\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox\n [disabled]=\"!entityArrayDataSource.data.length\" (change)=\"$event ? SelectionUtilities.masterToggle(entityArraySelection, entityArrayDataSource) : null\"\n [checked]=\"entityArraySelection.hasValue() && SelectionUtilities.isAllSelected(entityArraySelection, entityArrayDataSource)\"\n [indeterminate]=\"entityArraySelection.hasValue() && !SelectionUtilities.isAllSelected(entityArraySelection, entityArrayDataSource)\">\n </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let entity\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? entityArraySelection.toggle(entity) : null\" [checked]=\"entityArraySelection.isSelected(entity)\"></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.enabled]=\"!dCol.disableClick\" (click)=\"editArrayItem(entity, dCol)\" *matCellDef=\"let entity\">\n <ng-container *ngIf=\"dCol.Component\">\n <display-column-value [entity]=\"entity\" [ComponentClass]=\"dCol.Component\"></display-column-value>\n </ng-container>\n <ng-container *ngIf=\"!dCol.Component\">\n {{getDisplayColumnValue(entity, dCol)}}\n </ng-container>\n </mat-cell>\n </ng-container>\n \n <mat-header-row *matHeaderRowDef=\"entityArrayDisplayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: entityArrayDisplayedColumns\"></mat-row>\n </mat-table>\n \n <div class=\"array-error\" *ngIf=\"metadataEntityArray.required(entity) && !entityArrayDataSource.data.length\">\n {{metadataEntityArray.missingErrorMessage}}\n </div>\n </div>\n </div>\n\n <!-------------------------------------------->\n <!------------------ has many ---------------->\n <!-------------------------------------------->\n <div class=\"hasMany\" *ngSwitchCase=\"DecoratorTypes.HAS_MANY\">\n <h2 class=\"title\">{{metadataHasMany.tableData.baseData.title}}</h2>\n\n <div class=\"row\">\n <mat-form-field class=\"col-lg-8 col-md-6 col-sm-12\">\n <mat-label>{{metadataHasMany.tableData.baseData.searchLabel}}</mat-label>\n <input matInput (keyup)=\"applyHasManyFilter($event)\">\n </mat-form-field>\n <div\n *ngIf=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-lg-2]=\"hasManyAllowCreate\"\n [class.col-lg-4]=\"!hasManyAllowCreate\"\n [class.col-md-3]=\"hasManyAllowCreate\"\n [class.col-md-6]=\"!hasManyAllowCreate\"\n [class.col-sm-6]=\"hasManyAllowCreate\"\n [class.col-sm-12]=\"!hasManyAllowCreate\"\n >\n <button type=\"button\" class=\"actions-button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{metadataHasMany.tableData.baseData.tableActionsLabel}}\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button *ngIf=\"metadataHasMany.tableData.baseData.allowJsonImport\" type=\"button\" [disabled]=\"hasManyTableActionDisabled(hasManyImportAction)\" (click)=\"runHasManyTableAction(hasManyImportAction)\" mat-menu-item>\n {{hasManyImportAction.displayName}}\n </button>\n <button type=\"button\" *ngFor=\"let action of metadataHasMany.tableData.baseData.tableActions\" [disabled]=\"hasManyTableActionDisabled(action)\" (click)=\"runHasManyTableAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n\n <div\n *ngIf=\"hasManyAllowCreate\"\n [class.col-lg-2]=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-lg-4]=\"!metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-md-3]=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-md-6]=\"!metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-sm-6]=\"metadataHasMany.tableData.baseData.tableActions.length\"\n [class.col-sm-12]=\"!metadataHasMany.tableData.baseData.tableActions.length\"\n >\n <button type=\"button\" class=\"create-button\" (click)=\"createHasManyEntity()\" mat-raised-button>\n {{metadataHasMany.tableData.baseData.createButtonLabel}}\n </button>\n </div>\n </div>\n\n <div class=\"mat-elevation-z8 elevation-container\">\n <mat-table [dataSource]=\"hasManyDataSource\" matSort>\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox (change)=\"$event ? SelectionUtilities.masterToggle(hasManySelection, hasManyDataSource) : null\"\n [checked]=\"hasManySelection.hasValue() && SelectionUtilities.isAllSelected(hasManySelection, hasManyDataSource)\"\n [indeterminate]=\"hasManySelection.hasValue() && !SelectionUtilities.isAllSelected(hasManySelection, hasManyDataSource)\">\n </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let entity\" class=\"enabled\">\n <mat-checkbox (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? hasManySelection.toggle(entity) : null\"\n [checked]=\"hasManySelection.isSelected(entity)\">\n </mat-checkbox>\n </mat-cell>\n </ng-container>\n\n <ng-container *ngFor=\"let dCol of metadataHasMany.tableData.baseData.displayColumns\" [matColumnDef]=\"dCol.displayName\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n {{dCol.displayName}}\n </mat-header-cell>\n <mat-cell [class.enabled]=\"!dCol.disableClick && (hasManyAllowUpdate(entity) || hasManyAllowRead(entity))\"\n (click)=\"editHasManyEntity(entity, dCol)\"\n *matCellDef=\"let entity\"\n >\n <ng-container *ngIf=\"dCol.Component\">\n <display-column-value [entity]=\"entity\" [ComponentClass]=\"dCol.Component\"></display-column-value>\n </ng-container>\n <ng-container *ngIf=\"!dCol.Component\">\n {{getDisplayColumnValue(entity, dCol)}}\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <mat-header-row *matHeaderRowDef=\"displayedHasManyColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedHasManyColumns\"></mat-row>\n </mat-table>\n\n <mat-spinner *ngIf=\"hasManyIsLoading && metadataHasMany.tableData.baseData.displayLoadingSpinner\">\n </mat-spinner>\n\n <mat-paginator [length]=\"hasManyDataSource.filteredData.length\" [pageIndex]=\"0\" [pageSize]=\"10\" [pageSizeOptions]=\"[5, 10, 25, 50]\"></mat-paginator>\n </div>\n </div>\n\n <div *ngSwitchDefault>ERROR: The type {{type}} is not known.</div>\n</div>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<!--------------------------------------------------------->\n<!--------------------Add Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #addArrayItemDialog>\n <div class=\"mat-dialog-title\">\n <div>{{addArrayItemDialogData.title}}</div>\n </div>\n\n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"arrayItemDialogTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of arrayItemDialogTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\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 </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"arrayItemDialogTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\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 </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" mat-raised-button (click)=\"addArrayItem()\" [disabled]=\"!isArrayItemValid\">\n {{addArrayItemDialogData.createButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"closeAddArrayItemDialog()\" class=\"cancel-button\">\n {{addArrayItemDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form>\n\n</ng-template>\n\n<!--------------------------------------------------------->\n<!--------------------Edit Array Item Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #editArrayItemDialog>\n <div class=\"mat-dialog-title\">\n <div>{{editArrayItemDialogData.title(arrayItemPriorChanges)}}</div>\n </div>\n \n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"arrayItemDialogTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of arrayItemDialogTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\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)=\"checkArrayItem()\"\n [isReadOnly]=\"isPropertyReadOnly(arrayItem, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"arrayItemDialogTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of arrayItemDialogTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"arrayItem\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\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)=\"checkArrayItem()\"\n [isReadOnly]=\"isPropertyReadOnly(arrayItem, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" (click)=\"saveArrayItem()\" mat-raised-button [disabled]=\"internalIsReadOnly || !isArrayItemValid || !isArrayItemDirty\">\n {{editArrayItemDialogData.confirmButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"closeEditArrayItemDialog()\" class=\"cancel-button\">\n {{editArrayItemDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form>\n</ng-template>\n\n<!--------------------------------------------------------->\n<!--------------------Create Has Many Dialog---------------->\n<!--------------------------------------------------------->\n<ng-template #createHasManyDialog>\n <div class=\"mat-dialog-title\">\n <div>{{metadataHasMany.tableData.createDialogData.title}}</div>\n </div>\n \n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"hasManyCreateTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of hasManyCreateTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsHasManyEntityValid('create')\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"hasManyCreateTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of hasManyCreateTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForCreate]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkIsHasManyEntityValid('create')\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" (click)=\"dialogCreateHasMany()\" mat-raised-button [disabled]=\"!isHasManyEntityValid\">\n {{metadataHasMany.tableData.createDialogData.createButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"dialogCancelCreateHasMany()\" class=\"cancel-button\">\n {{metadataHasMany.tableData.createDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form>\n \n</ng-template>\n\n<ng-template #editHasManyDialog>\n <div class=\"mat-dialog-title\">\n <div>{{metadataHasMany.tableData.editData.title(hasManyEntityPriorChanges)}}</div>\n\n <div class=\"actions-container\">\n <button *ngIf=\"metadataHasMany.tableData.editData.actions.length\" type=\"button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{metadataHasMany.tableData.editData.actionsLabel}}\n </button>\n <mat-menu #menu=\"matMenu\">\n <button type=\"button\" *ngFor=\"let action of metadataHasMany.tableData.editData.actions\" [disabled]=\"hasManyEditActionDisabled(action)\" (click)=\"hasManyRunEditAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n \n <button type=\"button\" *ngIf=\"hasManyAllowDelete(hasManyEntity)\" mat-raised-button (click)=\"deleteHasManyEntity()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{metadataHasMany.tableData.editData.deleteButtonLabel}}\n </button>\n </div>\n </div>\n \n <form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"hasManyUpdateTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of hasManyUpdateTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkHasManyEntity()\"\n [isReadOnly]=\"isPropertyReadOnly(hasManyEntity, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"hasManyUpdateTabs.length <= 1\">\n <div class=\"row\" *ngFor=\"let row of hasManyUpdateTabs[0].rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"hasManyEntity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(hasManyEntity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(hasManyEntity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(hasManyEntity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkHasManyEntity()\"\n [isReadOnly]=\"isPropertyReadOnly(hasManyEntity, key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" (click)=\"dialogEditHasMany()\" mat-raised-button [disabled]=\"internalIsReadOnly || !isHasManyEntityValid || !isHasManyEntityDirty\">\n {{metadataHasMany.tableData.editData.confirmButtonLabel}}\n </button>\n <button type=\"button\" mat-raised-button (click)=\"dialogCancelEditHasMany()\" class=\"cancel-button\">\n {{metadataHasMany.tableData.editData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n </form> \n</ng-template>", styles: [".mdc-data-table__row:last-child .mdc-data-table__cell{border-bottom:1px solid rgba(0,0,0,.12)}.mat-dialog-title{padding:12px 20px;display:flex;justify-content:space-between;align-items:center}.mat-dialog-title div{font-size:var(--mdc-dialog-subhead-size, 14px);font-weight:var(--mdc-dialog-subhead-weight, 500)}::ng-deep .mdc-dialog .mdc-dialog__content{padding:6px 20px!important}mat-dialog-actions{justify-content:space-between;align-items:center;padding-left:20px;padding-right:20px}mat-spinner{margin:10px auto}::ng-deep .mat-mdc-tab-body-wrapper{margin-left:-12px;margin-right:-12px}::ng-deep mat-tab-body{padding-top:10px;padding-left:12px;padding-right:12px}::ng-deep mat-tab-body .mat-mdc-tab-body-content{overflow:initial}::ng-deep .mat-mdc-form-field.mat-form-field-disabled label{color:#0009}::ng-deep .mat-mdc-form-field.mat-form-field-disabled input,::ng-deep .mat-mdc-form-field.mat-form-field-disabled textarea,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-select-disabled,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-select-value{color:#000!important}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-checkbox .mdc-checkbox__native-control[disabled]:not(:checked):not(:indeterminate):not([data-indeterminate=true])~.mdc-checkbox__background{border-color:#707070}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-checkbox .mdc-checkbox__native-control[disabled]:checked~.mdc-checkbox__background,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-checkbox .mdc-checkbox__native-control[disabled]:indeterminate~.mdc-checkbox__background,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-checkbox .mdc-checkbox__native-control[data-indeterminate=true][disabled]~.mdc-checkbox__background{background-color:#000}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-chip.mat-mdc-standard-chip.mat-mdc-chip-disabled{opacity:1}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-mdc-chip.mat-mdc-standard-chip.mat-mdc-chip-disabled button{opacity:.2}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-switch.mdc-switch--selected:disabled .mdc-switch__icons,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-switch.mdc-switch--unselected:disabled .mdc-switch__icons{opacity:1}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-switch.mdc-switch--selected:disabled .mdc-switch__handle:after,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-switch.mdc-switch--unselected:disabled .mdc-switch__handle:after{opacity:1;background:black}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-switch.mdc-switch--selected:disabled .mdc-switch__track,::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mdc-switch.mdc-switch--unselected:disabled .mdc-switch__track{opacity:.3}::ng-deep .mat-mdc-form-field.mat-form-field-disabled .mat-date-range-input-inner:disabled{color:#000}::ng-deep #slider.mat-mdc-slider.mdc-slider--disabled{opacity:1}::ng-deep #slider.mat-mdc-slider.mdc-slider--disabled .mdc-slider__input{cursor:default}::ng-deep #slider.mat-mdc-slider.mdc-slider--disabled mat-slider-visual-thumb .mat-mdc-slider,::ng-deep #slider.mat-mdc-slider.mdc-slider--disabled mat-slider-visual-thumb .mdc-slider__thumb:hover,::ng-deep #slider.mat-mdc-slider.mdc-slider--disabled mat-slider-visual-thumb .mdc-slider__thumb-knob{background-color:#000;border-color:#000}::ng-deep .mat-mdc-form-field .mat-mdc-slide-toggle{opacity:1}.entityArray .elevation-container{border-radius:5px;padding:15px;margin-bottom:15px;margin-top:15px}.entityArray .array-headline{padding-bottom:10px}.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 .enabled:hover{cursor:pointer}.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}.hasMany button{width:100%;height:56px;line-height:24px;font-size:16px}.hasMany .title{text-align:center}.hasMany .elevation-container{border-radius:5px;padding:5px;margin-bottom:15px}.hasMany .mat-column-select{flex:0 0 75px}.hasMany .enabled:hover{cursor:pointer}\n"] }]
|
|
4624
4953
|
}], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i0.EnvironmentInjector }, { type: i2$3.Router }, { type: undefined, decorators: [{
|
|
4625
4954
|
type: Inject,
|
|
4626
4955
|
args: [NGX_GET_VALIDATION_ERROR_MESSAGE]
|
|
@@ -4648,10 +4977,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
4648
4977
|
args: ['editArrayItemDialog']
|
|
4649
4978
|
}], hasManyPaginator: [{
|
|
4650
4979
|
type: ViewChild,
|
|
4651
|
-
args: [MatPaginator
|
|
4980
|
+
args: [MatPaginator]
|
|
4652
4981
|
}], hasManySort: [{
|
|
4653
4982
|
type: ViewChild,
|
|
4654
|
-
args: [MatSort
|
|
4983
|
+
args: [MatSort]
|
|
4655
4984
|
}], hasManyFilter: [{
|
|
4656
4985
|
type: ViewChild,
|
|
4657
4986
|
args: ['filter', { static: true }]
|
|
@@ -4709,7 +5038,10 @@ class NgxMatEntityInputModule {
|
|
|
4709
5038
|
MatMenuModule,
|
|
4710
5039
|
MatProgressSpinnerModule,
|
|
4711
5040
|
MatPaginatorModule,
|
|
4712
|
-
DisplayColumnValueComponent
|
|
5041
|
+
DisplayColumnValueComponent,
|
|
5042
|
+
MatSortModule,
|
|
5043
|
+
PasswordMatchValidatorDirective,
|
|
5044
|
+
NumberDirective], exports: [NgxMatEntityInputComponent] });
|
|
4713
5045
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityInputModule, imports: [CommonModule,
|
|
4714
5046
|
MatInputModule,
|
|
4715
5047
|
FormsModule,
|
|
@@ -4728,7 +5060,8 @@ class NgxMatEntityInputModule {
|
|
|
4728
5060
|
MatTabsModule,
|
|
4729
5061
|
MatMenuModule,
|
|
4730
5062
|
MatProgressSpinnerModule,
|
|
4731
|
-
MatPaginatorModule
|
|
5063
|
+
MatPaginatorModule,
|
|
5064
|
+
MatSortModule] });
|
|
4732
5065
|
}
|
|
4733
5066
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityInputModule, decorators: [{
|
|
4734
5067
|
type: NgModule,
|
|
@@ -4781,12 +5114,142 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
4781
5114
|
MatMenuModule,
|
|
4782
5115
|
MatProgressSpinnerModule,
|
|
4783
5116
|
MatPaginatorModule,
|
|
4784
|
-
DisplayColumnValueComponent
|
|
5117
|
+
DisplayColumnValueComponent,
|
|
5118
|
+
MatSortModule,
|
|
5119
|
+
PasswordMatchValidatorDirective,
|
|
5120
|
+
NumberDirective
|
|
4785
5121
|
],
|
|
4786
5122
|
exports: [NgxMatEntityInputComponent]
|
|
4787
5123
|
}]
|
|
4788
5124
|
}] });
|
|
4789
5125
|
|
|
5126
|
+
/**
|
|
5127
|
+
* A directive that displays a tooltip on hover.
|
|
5128
|
+
*/
|
|
5129
|
+
class TooltipDirective {
|
|
5130
|
+
el;
|
|
5131
|
+
renderer;
|
|
5132
|
+
/**
|
|
5133
|
+
* The content to display inside the tooltip.
|
|
5134
|
+
*/
|
|
5135
|
+
tooltip;
|
|
5136
|
+
tooltipElement;
|
|
5137
|
+
isTooltipVisible = false;
|
|
5138
|
+
closeListeners = [];
|
|
5139
|
+
constructor(el, renderer) {
|
|
5140
|
+
this.el = el;
|
|
5141
|
+
this.renderer = renderer;
|
|
5142
|
+
}
|
|
5143
|
+
/**
|
|
5144
|
+
* Shows the tooltip.
|
|
5145
|
+
*/
|
|
5146
|
+
onMouseEnter() {
|
|
5147
|
+
if (!this.isTooltipVisible) {
|
|
5148
|
+
this.showTooltip();
|
|
5149
|
+
this.registerCloseListeners();
|
|
5150
|
+
}
|
|
5151
|
+
else {
|
|
5152
|
+
this.hideTooltip();
|
|
5153
|
+
this.removeCloseListeners();
|
|
5154
|
+
}
|
|
5155
|
+
}
|
|
5156
|
+
/**
|
|
5157
|
+
* Hides the tooltip.
|
|
5158
|
+
*/
|
|
5159
|
+
onMouseLeave() {
|
|
5160
|
+
this.hideTooltip();
|
|
5161
|
+
this.removeCloseListeners();
|
|
5162
|
+
}
|
|
5163
|
+
showTooltip() {
|
|
5164
|
+
if (!this.tooltipElement) {
|
|
5165
|
+
this.tooltipElement = this.renderer.createElement('div');
|
|
5166
|
+
this.tooltipElement.innerHTML = this.tooltip;
|
|
5167
|
+
const rect = this.el.nativeElement.getBoundingClientRect();
|
|
5168
|
+
this.renderer.setStyle(this.tooltipElement, 'z-index', '1000');
|
|
5169
|
+
this.renderer.setStyle(this.tooltipElement, 'position', 'absolute');
|
|
5170
|
+
this.renderer.setStyle(this.tooltipElement, 'padding', '4px 8px 4px 8px');
|
|
5171
|
+
this.renderer.setStyle(this.tooltipElement, 'border-radius', '5px');
|
|
5172
|
+
this.renderer.setStyle(this.tooltipElement, 'background-color', '#616161');
|
|
5173
|
+
this.renderer.setStyle(this.tooltipElement, 'color', 'white');
|
|
5174
|
+
this.renderer.setStyle(this.tooltipElement, 'max-height', '30vh');
|
|
5175
|
+
this.renderer.setStyle(this.tooltipElement, 'overflow', 'scroll');
|
|
5176
|
+
this.renderer.appendChild(document.body, this.tooltipElement);
|
|
5177
|
+
const left = window.scrollX + rect.left - (this.tooltipElement.clientWidth / 2) + 18;
|
|
5178
|
+
this.renderer.setStyle(this.tooltipElement, 'left', `${left}px`);
|
|
5179
|
+
const top = window.scrollY + rect.top - this.tooltipElement.clientHeight - 5;
|
|
5180
|
+
this.renderer.setStyle(this.tooltipElement, 'top', `${top}px`);
|
|
5181
|
+
this.isTooltipVisible = true;
|
|
5182
|
+
}
|
|
5183
|
+
}
|
|
5184
|
+
registerCloseListeners() {
|
|
5185
|
+
setTimeout(() => {
|
|
5186
|
+
this.closeListeners.push(this.getCloseListener('click'), this.getCloseListener('touchmove'), this.getCloseListener('resize'));
|
|
5187
|
+
}, 100);
|
|
5188
|
+
}
|
|
5189
|
+
getCloseListener(event) {
|
|
5190
|
+
return this.renderer.listen('document', event, () => {
|
|
5191
|
+
this.hideTooltip();
|
|
5192
|
+
this.removeCloseListeners();
|
|
5193
|
+
});
|
|
5194
|
+
}
|
|
5195
|
+
hideTooltip() {
|
|
5196
|
+
if (this.tooltipElement) {
|
|
5197
|
+
this.renderer.removeChild(this.el.nativeElement, this.tooltipElement);
|
|
5198
|
+
this.tooltipElement = undefined;
|
|
5199
|
+
this.isTooltipVisible = false;
|
|
5200
|
+
}
|
|
5201
|
+
}
|
|
5202
|
+
removeCloseListeners() {
|
|
5203
|
+
for (const listener of this.closeListeners) {
|
|
5204
|
+
listener();
|
|
5205
|
+
}
|
|
5206
|
+
this.closeListeners = [];
|
|
5207
|
+
}
|
|
5208
|
+
ngOnDestroy() {
|
|
5209
|
+
this.removeCloseListeners();
|
|
5210
|
+
}
|
|
5211
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: TooltipDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
|
|
5212
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.0", type: TooltipDirective, isStandalone: true, selector: "[tooltip]", inputs: { tooltip: "tooltip" }, host: { listeners: { "mouseenter": "onMouseEnter()", "click": "onMouseEnter()", "mouseleave": "onMouseLeave()", "window:resize": "onMouseLeave()" } }, ngImport: i0 });
|
|
5213
|
+
}
|
|
5214
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: TooltipDirective, decorators: [{
|
|
5215
|
+
type: Directive,
|
|
5216
|
+
args: [{
|
|
5217
|
+
selector: '[tooltip]',
|
|
5218
|
+
standalone: true
|
|
5219
|
+
}]
|
|
5220
|
+
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }]; }, propDecorators: { tooltip: [{
|
|
5221
|
+
type: Input
|
|
5222
|
+
}], onMouseEnter: [{
|
|
5223
|
+
type: HostListener,
|
|
5224
|
+
args: ['mouseenter']
|
|
5225
|
+
}, {
|
|
5226
|
+
type: HostListener,
|
|
5227
|
+
args: ['click']
|
|
5228
|
+
}], onMouseLeave: [{
|
|
5229
|
+
type: HostListener,
|
|
5230
|
+
args: ['mouseleave']
|
|
5231
|
+
}, {
|
|
5232
|
+
type: HostListener,
|
|
5233
|
+
args: ['window:resize']
|
|
5234
|
+
}] } });
|
|
5235
|
+
|
|
5236
|
+
/**
|
|
5237
|
+
* A component that displays an info-symbol and a tooltip when it is hovered/clicked.
|
|
5238
|
+
*/
|
|
5239
|
+
class TooltipComponent {
|
|
5240
|
+
tooltipContent;
|
|
5241
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: TooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5242
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: TooltipComponent, isStandalone: true, selector: "ngx-mat-entity-tooltip", inputs: { tooltipContent: "tooltipContent" }, ngImport: i0, template: "<div [tooltip]=\"tooltipContent\" class=\"info\">\n <i class=\"fas fa-info\"></i>\n</div>", styles: [".info{display:flex;align-items:center;justify-content:center;height:25px;min-height:25px;width:25px;min-width:25px;border:2px solid black;border-radius:50%}.info:hover{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: TooltipDirective, selector: "[tooltip]", inputs: ["tooltip"] }] });
|
|
5243
|
+
}
|
|
5244
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: TooltipComponent, decorators: [{
|
|
5245
|
+
type: Component,
|
|
5246
|
+
args: [{ selector: 'ngx-mat-entity-tooltip', standalone: true, imports: [
|
|
5247
|
+
TooltipDirective
|
|
5248
|
+
], template: "<div [tooltip]=\"tooltipContent\" class=\"info\">\n <i class=\"fas fa-info\"></i>\n</div>", styles: [".info{display:flex;align-items:center;justify-content:center;height:25px;min-height:25px;width:25px;min-width:25px;border:2px solid black;border-radius:50%}.info:hover{cursor:pointer}\n"] }]
|
|
5249
|
+
}], propDecorators: { tooltipContent: [{
|
|
5250
|
+
type: Input
|
|
5251
|
+
}] } });
|
|
5252
|
+
|
|
4790
5253
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
4791
5254
|
class PageEditDataBuilder extends BaseBuilder {
|
|
4792
5255
|
constructor(data) {
|
|
@@ -4844,13 +5307,17 @@ class NgxMatEntityEditPageComponent {
|
|
|
4844
5307
|
EntityClass;
|
|
4845
5308
|
inputData;
|
|
4846
5309
|
http;
|
|
5310
|
+
el;
|
|
5311
|
+
renderer;
|
|
4847
5312
|
EntityUtilities = EntityUtilities;
|
|
4848
5313
|
entityTabs;
|
|
4849
5314
|
entity;
|
|
4850
5315
|
entityPriorChanges;
|
|
4851
5316
|
data;
|
|
5317
|
+
validationErrors = [];
|
|
4852
5318
|
isEntityValid = true;
|
|
4853
5319
|
isEntityDirty = false;
|
|
5320
|
+
tooltipContent = '';
|
|
4854
5321
|
isEntityReadOnly;
|
|
4855
5322
|
allowDelete;
|
|
4856
5323
|
inConfirmNavigation = false;
|
|
@@ -4858,7 +5325,7 @@ class NgxMatEntityEditPageComponent {
|
|
|
4858
5325
|
get hasUnsavedChanges() {
|
|
4859
5326
|
return this.isEntityDirty && this.data.editData.unsavedChangesRequireConfirmDialog;
|
|
4860
5327
|
}
|
|
4861
|
-
constructor(dialog, location, route, injector, entityService, EntityClass, inputData, http) {
|
|
5328
|
+
constructor(dialog, location, route, injector, entityService, EntityClass, inputData, http, el, renderer) {
|
|
4862
5329
|
this.dialog = dialog;
|
|
4863
5330
|
this.location = location;
|
|
4864
5331
|
this.route = route;
|
|
@@ -4867,6 +5334,8 @@ class NgxMatEntityEditPageComponent {
|
|
|
4867
5334
|
this.EntityClass = EntityClass;
|
|
4868
5335
|
this.inputData = inputData;
|
|
4869
5336
|
this.http = http;
|
|
5337
|
+
this.el = el;
|
|
5338
|
+
this.renderer = renderer;
|
|
4870
5339
|
}
|
|
4871
5340
|
/**
|
|
4872
5341
|
* Checks if the input with the given key is readonly.
|
|
@@ -4875,7 +5344,7 @@ class NgxMatEntityEditPageComponent {
|
|
|
4875
5344
|
* @returns Whether or not the input for the key is read only.
|
|
4876
5345
|
*/
|
|
4877
5346
|
isReadOnly(key) {
|
|
4878
|
-
return this.injector
|
|
5347
|
+
return runInInjectionContext(this.injector, () => {
|
|
4879
5348
|
const metadata = EntityUtilities.getPropertyMetadata(this.entity, key);
|
|
4880
5349
|
return this.isEntityReadOnly || metadata.isReadOnly(this.entity);
|
|
4881
5350
|
});
|
|
@@ -4894,11 +5363,34 @@ class NgxMatEntityEditPageComponent {
|
|
|
4894
5363
|
}
|
|
4895
5364
|
this.entity = new this.EntityClass(foundEntity);
|
|
4896
5365
|
this.entityPriorChanges = LodashUtilities.cloneDeep(this.entity);
|
|
4897
|
-
this.injector
|
|
5366
|
+
runInInjectionContext(this.injector, () => {
|
|
4898
5367
|
this.isEntityReadOnly = !this.data.allowUpdate(this.entityPriorChanges);
|
|
4899
5368
|
this.allowDelete = this.data.allowDelete(this.entityPriorChanges);
|
|
4900
5369
|
});
|
|
4901
5370
|
this.entityTabs = EntityUtilities.getEntityTabs(this.entity, false, true);
|
|
5371
|
+
setTimeout(() => this.checkOffset(), 1);
|
|
5372
|
+
setTimeout(() => this.checkIsEntityValid(), 1);
|
|
5373
|
+
}
|
|
5374
|
+
/**
|
|
5375
|
+
* Checks if the bottom row should be displayed as fixed.
|
|
5376
|
+
*/
|
|
5377
|
+
onScroll() {
|
|
5378
|
+
this.checkOffset();
|
|
5379
|
+
}
|
|
5380
|
+
checkOffset() {
|
|
5381
|
+
const scrollY = window.scrollY;
|
|
5382
|
+
const bottomRow = this.el.nativeElement.querySelector('.bottom-row');
|
|
5383
|
+
const bottomRowContainer = this.el.nativeElement.querySelector('.bottom-row-container');
|
|
5384
|
+
if (bottomRow && bottomRowContainer) {
|
|
5385
|
+
const bottomRowContainerOffset = bottomRowContainer.offsetTop;
|
|
5386
|
+
const windowHeight = window.innerHeight;
|
|
5387
|
+
if (scrollY + windowHeight >= bottomRowContainerOffset) {
|
|
5388
|
+
this.renderer.removeClass(bottomRow, 'fixed');
|
|
5389
|
+
}
|
|
5390
|
+
else {
|
|
5391
|
+
this.renderer.addClass(bottomRow, 'fixed');
|
|
5392
|
+
}
|
|
5393
|
+
}
|
|
4902
5394
|
}
|
|
4903
5395
|
/**
|
|
4904
5396
|
* Whether the page can be left without confirmation (of unsaved changes).
|
|
@@ -4912,9 +5404,14 @@ class NgxMatEntityEditPageComponent {
|
|
|
4912
5404
|
* Checks if the entity has become invalid or dirty.
|
|
4913
5405
|
*/
|
|
4914
5406
|
async checkEntity() {
|
|
4915
|
-
this.
|
|
5407
|
+
this.checkIsEntityValid();
|
|
4916
5408
|
this.isEntityDirty = await EntityUtilities.isDirty(this.entity, this.entityPriorChanges, this.http);
|
|
4917
5409
|
}
|
|
5410
|
+
checkIsEntityValid() {
|
|
5411
|
+
this.validationErrors = ValidationUtilities.getEntityValidationErrors(this.entity, 'update');
|
|
5412
|
+
this.tooltipContent = runInInjectionContext(this.injector, () => getValidationErrorsTooltipContent(this.validationErrors));
|
|
5413
|
+
this.isEntityValid = this.validationErrors.length === 0;
|
|
5414
|
+
}
|
|
4918
5415
|
/**
|
|
4919
5416
|
* Tries to save the changes and close the dialog afterwards.
|
|
4920
5417
|
* Also handles the confirmation if required.
|
|
@@ -5051,8 +5548,8 @@ class NgxMatEntityEditPageComponent {
|
|
|
5051
5548
|
return !action.enabled(this.entityPriorChanges);
|
|
5052
5549
|
});
|
|
5053
5550
|
}
|
|
5054
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityEditPageComponent, deps: [{ token: i1.MatDialog }, { token: i1$1.Location }, { token: i2$3.ActivatedRoute }, { token: i0.EnvironmentInjector }, { token: NGX_EDIT_DATA_ENTITY_SERVICE }, { token: NGX_EDIT_DATA_ENTITY }, { token: NGX_EDIT_DATA }, { token: i2.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
|
|
5055
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: NgxMatEntityEditPageComponent, isStandalone: true, selector: "ngx-mat-entity-edit-page", host: { listeners: { "window:beforeunload": "canDeactivate()" } }, ngImport: i0, template: "<div *ngIf=\"!entityTabs && data.displayLoadingSpinner\" class=\"container\">\n <br>\n <mat-spinner></mat-spinner>\n <br>\n</div>\n\n<div *ngIf=\"entityTabs\" class=\"container\">\n <br>\n\n <!------------>\n <!-- Header -->\n <!------------>\n <div class=\"header\">\n <div class=\"save-cancel-container\">\n <button type=\"button\" [class.unsavedChanges]=\"hasUnsavedChanges\" mat-raised-button (click)=\"navigateBack()\" class=\"back-button\" tabindex=\"-1\">\n <i class=\"fas fa-chevron-left\"></i>\n {{data.editData.cancelButtonLabel}}\n <i class=\"fas fa-warning\" *ngIf=\"hasUnsavedChanges\"></i>\n </button>\n
|
|
5551
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityEditPageComponent, deps: [{ token: i1.MatDialog }, { token: i1$1.Location }, { token: i2$3.ActivatedRoute }, { token: i0.EnvironmentInjector }, { token: NGX_EDIT_DATA_ENTITY_SERVICE }, { token: NGX_EDIT_DATA_ENTITY }, { token: NGX_EDIT_DATA }, { token: i2.HttpClient }, { token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
|
|
5552
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: NgxMatEntityEditPageComponent, isStandalone: true, selector: "ngx-mat-entity-edit-page", host: { listeners: { "window:scroll": "onScroll()", "window:beforeunload": "canDeactivate()" } }, ngImport: i0, template: "<div *ngIf=\"!entityTabs && data.displayLoadingSpinner\" class=\"container\">\n <br>\n <mat-spinner></mat-spinner>\n <br>\n</div>\n\n<div *ngIf=\"entityTabs\" class=\"container\">\n <br>\n\n <!------------>\n <!-- Header -->\n <!------------>\n <div class=\"header\">\n <div class=\"save-cancel-container\">\n <button type=\"button\" [class.unsavedChanges]=\"hasUnsavedChanges\" mat-raised-button (click)=\"navigateBack()\" class=\"back-button\" tabindex=\"-1\">\n <i class=\"fas fa-chevron-left\"></i>\n {{data.editData.cancelButtonLabel}}\n <i class=\"fas fa-warning\" *ngIf=\"hasUnsavedChanges\"></i>\n </button>\n </div>\n <div class=\"actions-container\">\n <button *ngIf=\"data.editData.actions.length\" type=\"button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{data.editData.actionsLabel}}\n </button>\n <mat-menu #menu=\"matMenu\">\n <button type=\"button\" *ngFor=\"let action of data.editData.actions\" [disabled]=\"editActionDisabled(action)\" (click)=\"runEditAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n \n <button type=\"button\" *ngIf=\"allowDelete\" mat-raised-button (click)=\"delete()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{data.editData.deleteButtonLabel}}\n </button>\n </div>\n </div>\n\n <h1>{{data.editData.title(entityPriorChanges)}}</h1>\n\n <!----------->\n <!-- Input -->\n <!----------->\n <form>\n <mat-tab-group *ngIf=\"entityTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of entityTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"entity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(entity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkEntity()\"\n [isReadOnly]=\"isReadOnly(key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"entityTabs.length <= 1\">\n <span class=\"no-entity-tabs\" *ngIf=\"!entityTabs.length\">\n ERROR: No Inputs. Did you correctly assign all values in the model constructor?\n </span>\n <div class=\"row\" *ngFor=\"let row of entityTabs[0]?.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"entity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(entity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkEntity()\"\n [isReadOnly]=\"isReadOnly(key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n\n <div class=\"bottom-row-container\">\n <div class=\"bottom-row container\" style=\"margin-top: 10px;\">\n <button type=\"submit\" (click)=\"edit()\" mat-raised-button\n [disabled]=\"isEntityReadOnly || !isEntityValid || !isEntityDirty\"\n [matBadge]=\"validationErrors.length\"\n [matBadgeHidden]=\"!validationErrors.length\"\n matBadgeColor=\"warn\"\n >\n {{data.editData.confirmButtonLabel}}\n </button>\n <ngx-mat-entity-tooltip *ngIf=\"validationErrors.length\" [tooltipContent]=\"tooltipContent\"></ngx-mat-entity-tooltip>\n </div>\n </div>\n </form>\n\n <br>\n</div>", styles: ["h1{text-align:center}mat-spinner{margin:10px auto}.fa-warning{color:orange}.bottom-row{display:flex;align-items:center;column-gap:10px}.fixed{position:fixed;bottom:0;left:0;right:0;width:100%;z-index:1000;padding:8px 20px;background-color:#fff}.no-entity-tabs{padding:10px;background-color:red;color:#f5f5f5}.header{display:flex;margin-bottom:5px;gap:10px;flex-wrap:wrap}.header button{min-width:150px}.header .save-cancel-container{display:flex;justify-content:flex-start;align-items:center;column-gap:10px;width:calc(50% - 10px)}.header .actions-container{display:flex;justify-content:flex-end;gap:10px;width:calc(50% - 10px)}.unsavedChanges{background-color:#ffe48d}@media (max-width: 800px){.header{margin-bottom:10px;gap:15px}.header button{min-width:0px;width:50%}.header .save-cancel-container,.header .actions-container{width:100%;gap:15px}}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i6$2.MatTab, selector: "mat-tab", inputs: ["disabled"], exportAs: ["matTab"] }, { kind: "component", type: i6$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "disableRipple", "fitInkBarToContent", "mat-stretch-tabs"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: NgxMatEntityInputModule }, { kind: "component", type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit", "validEmpty", "isReadOnly"], outputs: ["inputChangeEvent"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i15.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i14.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { kind: "component", type: i14.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i14.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i10.MatBadge, selector: "[matBadge]", inputs: ["matBadgeDisabled", "matBadgeColor", "matBadgeOverlap", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "component", type: TooltipComponent, selector: "ngx-mat-entity-tooltip", inputs: ["tooltipContent"] }] });
|
|
5056
5553
|
}
|
|
5057
5554
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityEditPageComponent, decorators: [{
|
|
5058
5555
|
type: Component,
|
|
@@ -5063,8 +5560,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
5063
5560
|
MatTabsModule,
|
|
5064
5561
|
NgxMatEntityInputModule,
|
|
5065
5562
|
MatProgressSpinnerModule,
|
|
5066
|
-
MatMenuModule
|
|
5067
|
-
|
|
5563
|
+
MatMenuModule,
|
|
5564
|
+
MatBadgeModule,
|
|
5565
|
+
TooltipComponent
|
|
5566
|
+
], template: "<div *ngIf=\"!entityTabs && data.displayLoadingSpinner\" class=\"container\">\n <br>\n <mat-spinner></mat-spinner>\n <br>\n</div>\n\n<div *ngIf=\"entityTabs\" class=\"container\">\n <br>\n\n <!------------>\n <!-- Header -->\n <!------------>\n <div class=\"header\">\n <div class=\"save-cancel-container\">\n <button type=\"button\" [class.unsavedChanges]=\"hasUnsavedChanges\" mat-raised-button (click)=\"navigateBack()\" class=\"back-button\" tabindex=\"-1\">\n <i class=\"fas fa-chevron-left\"></i>\n {{data.editData.cancelButtonLabel}}\n <i class=\"fas fa-warning\" *ngIf=\"hasUnsavedChanges\"></i>\n </button>\n </div>\n <div class=\"actions-container\">\n <button *ngIf=\"data.editData.actions.length\" type=\"button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{data.editData.actionsLabel}}\n </button>\n <mat-menu #menu=\"matMenu\">\n <button type=\"button\" *ngFor=\"let action of data.editData.actions\" [disabled]=\"editActionDisabled(action)\" (click)=\"runEditAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n \n <button type=\"button\" *ngIf=\"allowDelete\" mat-raised-button (click)=\"delete()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{data.editData.deleteButtonLabel}}\n </button>\n </div>\n </div>\n\n <h1>{{data.editData.title(entityPriorChanges)}}</h1>\n\n <!----------->\n <!-- Input -->\n <!----------->\n <form>\n <mat-tab-group *ngIf=\"entityTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of entityTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"entity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(entity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkEntity()\"\n [isReadOnly]=\"isReadOnly(key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"entityTabs.length <= 1\">\n <span class=\"no-entity-tabs\" *ngIf=\"!entityTabs.length\">\n ERROR: No Inputs. Did you correctly assign all values in the model constructor?\n </span>\n <div class=\"row\" *ngFor=\"let row of entityTabs[0]?.rows\">\n <ngx-mat-entity-input\n *ngFor=\"let key of row.keys\"\n [entity]=\"entity\"\n [propertyKey]=\"key\"\n [hideOmitForEdit]=\"true\"\n class=\"col-lg-{{EntityUtilities.getWidth(entity, key, 'lg')}} col-md-{{EntityUtilities.getWidth(entity, key, 'md')}} col-sm-{{EntityUtilities.getWidth(entity, key, 'sm')}}\"\n (inputChangeEvent)=\"checkEntity()\"\n [isReadOnly]=\"isReadOnly(key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n\n <div class=\"bottom-row-container\">\n <div class=\"bottom-row container\" style=\"margin-top: 10px;\">\n <button type=\"submit\" (click)=\"edit()\" mat-raised-button\n [disabled]=\"isEntityReadOnly || !isEntityValid || !isEntityDirty\"\n [matBadge]=\"validationErrors.length\"\n [matBadgeHidden]=\"!validationErrors.length\"\n matBadgeColor=\"warn\"\n >\n {{data.editData.confirmButtonLabel}}\n </button>\n <ngx-mat-entity-tooltip *ngIf=\"validationErrors.length\" [tooltipContent]=\"tooltipContent\"></ngx-mat-entity-tooltip>\n </div>\n </div>\n </form>\n\n <br>\n</div>", styles: ["h1{text-align:center}mat-spinner{margin:10px auto}.fa-warning{color:orange}.bottom-row{display:flex;align-items:center;column-gap:10px}.fixed{position:fixed;bottom:0;left:0;right:0;width:100%;z-index:1000;padding:8px 20px;background-color:#fff}.no-entity-tabs{padding:10px;background-color:red;color:#f5f5f5}.header{display:flex;margin-bottom:5px;gap:10px;flex-wrap:wrap}.header button{min-width:150px}.header .save-cancel-container{display:flex;justify-content:flex-start;align-items:center;column-gap:10px;width:calc(50% - 10px)}.header .actions-container{display:flex;justify-content:flex-end;gap:10px;width:calc(50% - 10px)}.unsavedChanges{background-color:#ffe48d}@media (max-width: 800px){.header{margin-bottom:10px;gap:15px}.header button{min-width:0px;width:50%}.header .save-cancel-container,.header .actions-container{width:100%;gap:15px}}\n"] }]
|
|
5068
5567
|
}], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i1$1.Location }, { type: i2$3.ActivatedRoute }, { type: i0.EnvironmentInjector }, { type: EntityService, decorators: [{
|
|
5069
5568
|
type: Inject,
|
|
5070
5569
|
args: [NGX_EDIT_DATA_ENTITY_SERVICE]
|
|
@@ -5074,7 +5573,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
5074
5573
|
}] }, { type: undefined, decorators: [{
|
|
5075
5574
|
type: Inject,
|
|
5076
5575
|
args: [NGX_EDIT_DATA]
|
|
5077
|
-
}] }, { type: i2.HttpClient }]; }, propDecorators: {
|
|
5576
|
+
}] }, { type: i2.HttpClient }, { type: i0.ElementRef }, { type: i0.Renderer2 }]; }, propDecorators: { onScroll: [{
|
|
5577
|
+
type: HostListener,
|
|
5578
|
+
args: ['window:scroll']
|
|
5579
|
+
}], canDeactivate: [{
|
|
5078
5580
|
type: HostListener,
|
|
5079
5581
|
args: ['window:beforeunload']
|
|
5080
5582
|
}] } });
|
|
@@ -5133,6 +5635,8 @@ class NgxMatEntityCreateDialogComponent {
|
|
|
5133
5635
|
entityService;
|
|
5134
5636
|
data;
|
|
5135
5637
|
isEntityValid = false;
|
|
5638
|
+
validationErrors = [];
|
|
5639
|
+
tooltipContent = '';
|
|
5136
5640
|
constructor(inputData, dialogRef, injector, dialog) {
|
|
5137
5641
|
this.inputData = inputData;
|
|
5138
5642
|
this.dialogRef = dialogRef;
|
|
@@ -5144,12 +5648,15 @@ class NgxMatEntityCreateDialogComponent {
|
|
|
5144
5648
|
this.dialogRef.disableClose = true;
|
|
5145
5649
|
this.entityTabs = EntityUtilities.getEntityTabs(this.data.entity, true);
|
|
5146
5650
|
this.entityService = this.injector.get(this.data.EntityServiceClass);
|
|
5651
|
+
setTimeout(() => this.checkIsEntityValid(), 1);
|
|
5147
5652
|
}
|
|
5148
5653
|
/**
|
|
5149
5654
|
* Checks if the entity is valid.
|
|
5150
5655
|
*/
|
|
5151
5656
|
checkIsEntityValid() {
|
|
5152
|
-
this.
|
|
5657
|
+
this.validationErrors = ValidationUtilities.getEntityValidationErrors(this.data.entity, 'create');
|
|
5658
|
+
this.tooltipContent = runInInjectionContext(this.injector, () => getValidationErrorsTooltipContent(this.validationErrors));
|
|
5659
|
+
this.isEntityValid = this.validationErrors.length === 0;
|
|
5153
5660
|
}
|
|
5154
5661
|
/**
|
|
5155
5662
|
* Tries add the new entity and close the dialog afterwards.
|
|
@@ -5189,7 +5696,7 @@ class NgxMatEntityCreateDialogComponent {
|
|
|
5189
5696
|
this.dialogRef.close();
|
|
5190
5697
|
}
|
|
5191
5698
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityCreateDialogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1.MatDialogRef }, { token: i0.Injector }, { token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
|
|
5192
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: NgxMatEntityCreateDialogComponent, isStandalone: true, selector: "ngx-mat-entity-create-dialog", ngImport: i0, template: "<div class=\"mat-dialog-title\">\n <div>{{data.createDialogData.title}}</div>\n</div>\n\n<form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"entityTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of entityTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\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 </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"entityTabs.length <= 1\">\n <span class=\"no-entity-tabs\" *ngIf=\"!entityTabs.length\">\n ERROR: No Inputs. Did you correctly assign all values in the model constructor?\n </span>\n <div class=\"row\" *ngFor=\"let row of entityTabs[0]?.rows\">\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 </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" (click)=\"create()\" mat-raised-button
|
|
5699
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: NgxMatEntityCreateDialogComponent, isStandalone: true, selector: "ngx-mat-entity-create-dialog", ngImport: i0, template: "<div class=\"mat-dialog-title\">\n <div>{{data.createDialogData.title}}</div>\n</div>\n\n<form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"entityTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of entityTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\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 </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"entityTabs.length <= 1\">\n <span class=\"no-entity-tabs\" *ngIf=\"!entityTabs.length\">\n ERROR: No Inputs. Did you correctly assign all values in the model constructor?\n </span>\n <div class=\"row\" *ngFor=\"let row of entityTabs[0]?.rows\">\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 </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n\n <div class=\"d-flex align-items-center gap-3\" style=\"margin-top: 10px;\">\n <button type=\"submit\" (click)=\"create()\" mat-raised-button\n [disabled]=\"!isEntityValid\"\n [matBadge]=\"validationErrors.length\"\n [matBadgeHidden]=\"!validationErrors.length\"\n matBadgeColor=\"warn\"\n >\n {{data.createDialogData.createButtonLabel}}\n </button>\n <ngx-mat-entity-tooltip *ngIf=\"validationErrors.length\" [tooltipContent]=\"tooltipContent\"></ngx-mat-entity-tooltip>\n </div>\n\n <button type=\"button\" mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.createDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n</form>\n", styles: [".mat-dialog-title{padding:20px;display:flex;justify-content:space-between;align-items:center}.mat-dialog-title div{font-size:var(--mdc-dialog-subhead-size, 14px);font-weight:var(--mdc-dialog-subhead-weight, 500)}.no-entity-tabs{padding:10px;background-color:red;color:#f5f5f5}::ng-deep .mdc-dialog .mdc-dialog__content{padding:6px 20px!important}mat-dialog-actions{justify-content:space-between;align-items:center;padding-left:20px;padding-right:20px}\n"], dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: NgxMatEntityInputModule }, { kind: "component", type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit", "validEmpty", "isReadOnly"], outputs: ["inputChangeEvent"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i6$2.MatTab, selector: "mat-tab", inputs: ["disabled"], exportAs: ["matTab"] }, { kind: "component", type: i6$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "disableRipple", "fitInkBarToContent", "mat-stretch-tabs"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i10.MatBadge, selector: "[matBadge]", inputs: ["matBadgeDisabled", "matBadgeColor", "matBadgeOverlap", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "component", type: TooltipComponent, selector: "ngx-mat-entity-tooltip", inputs: ["tooltipContent"] }] });
|
|
5193
5700
|
}
|
|
5194
5701
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityCreateDialogComponent, decorators: [{
|
|
5195
5702
|
type: Component,
|
|
@@ -5200,8 +5707,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
5200
5707
|
MatDialogModule,
|
|
5201
5708
|
FormsModule,
|
|
5202
5709
|
MatButtonModule,
|
|
5203
|
-
MatTabsModule
|
|
5204
|
-
|
|
5710
|
+
MatTabsModule,
|
|
5711
|
+
MatBadgeModule,
|
|
5712
|
+
TooltipComponent
|
|
5713
|
+
], template: "<div class=\"mat-dialog-title\">\n <div>{{data.createDialogData.title}}</div>\n</div>\n\n<form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"entityTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of entityTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\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 </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"entityTabs.length <= 1\">\n <span class=\"no-entity-tabs\" *ngIf=\"!entityTabs.length\">\n ERROR: No Inputs. Did you correctly assign all values in the model constructor?\n </span>\n <div class=\"row\" *ngFor=\"let row of entityTabs[0]?.rows\">\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 </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n\n <div class=\"d-flex align-items-center gap-3\" style=\"margin-top: 10px;\">\n <button type=\"submit\" (click)=\"create()\" mat-raised-button\n [disabled]=\"!isEntityValid\"\n [matBadge]=\"validationErrors.length\"\n [matBadgeHidden]=\"!validationErrors.length\"\n matBadgeColor=\"warn\"\n >\n {{data.createDialogData.createButtonLabel}}\n </button>\n <ngx-mat-entity-tooltip *ngIf=\"validationErrors.length\" [tooltipContent]=\"tooltipContent\"></ngx-mat-entity-tooltip>\n </div>\n\n <button type=\"button\" mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.createDialogData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n</form>\n", styles: [".mat-dialog-title{padding:20px;display:flex;justify-content:space-between;align-items:center}.mat-dialog-title div{font-size:var(--mdc-dialog-subhead-size, 14px);font-weight:var(--mdc-dialog-subhead-weight, 500)}.no-entity-tabs{padding:10px;background-color:red;color:#f5f5f5}::ng-deep .mdc-dialog .mdc-dialog__content{padding:6px 20px!important}mat-dialog-actions{justify-content:space-between;align-items:center;padding-left:20px;padding-right:20px}\n"] }]
|
|
5205
5714
|
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
5206
5715
|
type: Inject,
|
|
5207
5716
|
args: [MAT_DIALOG_DATA]
|
|
@@ -5386,6 +5895,8 @@ class NgxMatEntityEditDialogComponent {
|
|
|
5386
5895
|
data;
|
|
5387
5896
|
isEntityValid = true;
|
|
5388
5897
|
isEntityDirty = false;
|
|
5898
|
+
validationErrors = [];
|
|
5899
|
+
tooltipContent = '';
|
|
5389
5900
|
isEntityReadOnly;
|
|
5390
5901
|
allowDelete;
|
|
5391
5902
|
constructor(inputData, dialogRef, injector, dialog, http) {
|
|
@@ -5398,13 +5909,14 @@ class NgxMatEntityEditDialogComponent {
|
|
|
5398
5909
|
ngOnInit() {
|
|
5399
5910
|
this.data = new EditEntityDataBuilder(this.inputData).getResult();
|
|
5400
5911
|
this.entityPriorChanges = LodashUtilities.cloneDeep(this.data.entity);
|
|
5401
|
-
this.injector
|
|
5912
|
+
runInInjectionContext(this.injector, () => {
|
|
5402
5913
|
this.isEntityReadOnly = !this.data.allowUpdate(this.entityPriorChanges);
|
|
5403
5914
|
this.allowDelete = this.data.allowDelete(this.entityPriorChanges);
|
|
5404
5915
|
});
|
|
5405
5916
|
this.dialogRef.disableClose = true;
|
|
5406
5917
|
this.entityTabs = EntityUtilities.getEntityTabs(this.data.entity, false, true);
|
|
5407
5918
|
this.entityService = this.injector.get(this.data.EntityServiceClass);
|
|
5919
|
+
setTimeout(() => this.checkIsEntityValid(), 1);
|
|
5408
5920
|
}
|
|
5409
5921
|
/**
|
|
5410
5922
|
* Checks if the input with the given key is readonly.
|
|
@@ -5413,7 +5925,7 @@ class NgxMatEntityEditDialogComponent {
|
|
|
5413
5925
|
* @returns Whether or not the input for the key is read only.
|
|
5414
5926
|
*/
|
|
5415
5927
|
isReadOnly(key) {
|
|
5416
|
-
return this.injector
|
|
5928
|
+
return runInInjectionContext(this.injector, () => {
|
|
5417
5929
|
const metadata = EntityUtilities.getPropertyMetadata(this.data.entity, key);
|
|
5418
5930
|
return this.isEntityReadOnly || metadata.isReadOnly(this.data.entity);
|
|
5419
5931
|
});
|
|
@@ -5422,9 +5934,14 @@ class NgxMatEntityEditDialogComponent {
|
|
|
5422
5934
|
* Checks if the entity has become invalid or dirty.
|
|
5423
5935
|
*/
|
|
5424
5936
|
async checkEntity() {
|
|
5425
|
-
this.
|
|
5937
|
+
this.checkIsEntityValid();
|
|
5426
5938
|
this.isEntityDirty = await EntityUtilities.isDirty(this.data.entity, this.entityPriorChanges, this.http);
|
|
5427
5939
|
}
|
|
5940
|
+
checkIsEntityValid() {
|
|
5941
|
+
this.validationErrors = ValidationUtilities.getEntityValidationErrors(this.data.entity, 'update');
|
|
5942
|
+
this.tooltipContent = runInInjectionContext(this.injector, () => getValidationErrorsTooltipContent(this.validationErrors));
|
|
5943
|
+
this.isEntityValid = this.validationErrors.length === 0;
|
|
5944
|
+
}
|
|
5428
5945
|
/**
|
|
5429
5946
|
* Tries to save the changes and close the dialog afterwards.
|
|
5430
5947
|
* Also handles the confirmation if required.
|
|
@@ -5498,7 +6015,7 @@ class NgxMatEntityEditDialogComponent {
|
|
|
5498
6015
|
* @param action - The action to run.
|
|
5499
6016
|
*/
|
|
5500
6017
|
runEditAction(action) {
|
|
5501
|
-
const requireConfirmDialog = this.injector
|
|
6018
|
+
const requireConfirmDialog = runInInjectionContext(this.injector, () => {
|
|
5502
6019
|
return action.requireConfirmDialog(this.entityPriorChanges);
|
|
5503
6020
|
});
|
|
5504
6021
|
if (!requireConfirmDialog) {
|
|
@@ -5517,7 +6034,7 @@ class NgxMatEntityEditDialogComponent {
|
|
|
5517
6034
|
});
|
|
5518
6035
|
}
|
|
5519
6036
|
confirmRunEditAction(action) {
|
|
5520
|
-
void this.injector
|
|
6037
|
+
void runInInjectionContext(this.injector, async () => {
|
|
5521
6038
|
await action.action(this.data.entity, this.entityPriorChanges);
|
|
5522
6039
|
await this.checkEntity();
|
|
5523
6040
|
});
|
|
@@ -5529,12 +6046,10 @@ class NgxMatEntityEditDialogComponent {
|
|
|
5529
6046
|
* @returns Whether or not the Action can be used.
|
|
5530
6047
|
*/
|
|
5531
6048
|
editActionDisabled(action) {
|
|
5532
|
-
return this.injector
|
|
5533
|
-
return !action.enabled(this.entityPriorChanges);
|
|
5534
|
-
});
|
|
6049
|
+
return runInInjectionContext(this.injector, () => !action.enabled(this.entityPriorChanges));
|
|
5535
6050
|
}
|
|
5536
6051
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityEditDialogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1.MatDialogRef }, { token: i0.EnvironmentInjector }, { token: i1.MatDialog }, { token: i2.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
|
|
5537
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: NgxMatEntityEditDialogComponent, isStandalone: true, selector: "ngx-mat-entity-edit-dialog", ngImport: i0, template: "<div class=\"mat-dialog-title\">\n <div>{{data.editData.title(entityPriorChanges)}}</div>\n\n <div class=\"actions-container\">\n <button *ngIf=\"data.editData.actions.length\" type=\"button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{data.editData.actionsLabel}}\n </button>\n <mat-menu #menu=\"matMenu\">\n <button type=\"button\" *ngFor=\"let action of data.editData.actions\" [disabled]=\"editActionDisabled(action)\" (click)=\"runEditAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n \n <button type=\"button\" *ngIf=\"allowDelete\" mat-raised-button (click)=\"delete()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{data.editData.deleteButtonLabel}}\n </button>\n </div>\n</div>\n\n<form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"entityTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of entityTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\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(key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"entityTabs.length <= 1\">\n <span class=\"no-entity-tabs\" *ngIf=\"!entityTabs.length\">\n ERROR: No Inputs. Did you correctly assign all values in the model constructor?\n </span>\n <div class=\"row\" *ngFor=\"let row of entityTabs[0].rows\">\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(key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <button type=\"submit\" (click)=\"edit()\" mat-raised-button
|
|
6052
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: NgxMatEntityEditDialogComponent, isStandalone: true, selector: "ngx-mat-entity-edit-dialog", ngImport: i0, template: "<div class=\"mat-dialog-title\">\n <div>{{data.editData.title(entityPriorChanges)}}</div>\n\n <div class=\"actions-container\">\n <button *ngIf=\"data.editData.actions.length\" type=\"button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{data.editData.actionsLabel}}\n </button>\n <mat-menu #menu=\"matMenu\">\n <button type=\"button\" *ngFor=\"let action of data.editData.actions\" [disabled]=\"editActionDisabled(action)\" (click)=\"runEditAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n \n <button type=\"button\" *ngIf=\"allowDelete\" mat-raised-button (click)=\"delete()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{data.editData.deleteButtonLabel}}\n </button>\n </div>\n</div>\n\n<form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"entityTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of entityTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\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(key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"entityTabs.length <= 1\">\n <span class=\"no-entity-tabs\" *ngIf=\"!entityTabs.length\">\n ERROR: No Inputs. Did you correctly assign all values in the model constructor?\n </span>\n <div class=\"row\" *ngFor=\"let row of entityTabs[0].rows\">\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(key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <div class=\"d-flex align-items-center gap-3\" style=\"margin-top: 10px;\">\n <button type=\"submit\" (click)=\"edit()\" mat-raised-button\n [disabled]=\"isEntityReadOnly || !isEntityValid || !isEntityDirty\"\n [matBadge]=\"validationErrors.length\"\n [matBadgeHidden]=\"!validationErrors.length\"\n matBadgeColor=\"warn\"\n >\n {{data.editData.confirmButtonLabel}}\n </button>\n <ngx-mat-entity-tooltip *ngIf=\"validationErrors.length\" [tooltipContent]=\"tooltipContent\"></ngx-mat-entity-tooltip>\n </div>\n\n\n <button type=\"button\" mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.editData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n</form>\n", styles: [".mat-dialog-title{padding:12px 20px;display:flex;justify-content:space-between;align-items:center}.mat-dialog-title div{font-size:var(--mdc-dialog-subhead-size, 14px);font-weight:var(--mdc-dialog-subhead-weight, 500)}.actions-container{display:flex;gap:10px}.no-entity-tabs{padding:10px;background-color:red;color:#f5f5f5}::ng-deep .mdc-dialog .mdc-dialog__content{padding:6px 20px!important}mat-dialog-actions{justify-content:space-between;align-items:center;padding-left:20px;padding-right:20px}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: NgxMatEntityInputModule }, { kind: "component", type: NgxMatEntityInputComponent, selector: "ngx-mat-entity-input", inputs: ["entity", "propertyKey", "getValidationErrorMessage", "hideOmitForCreate", "hideOmitForEdit", "validEmpty", "isReadOnly"], outputs: ["inputChangeEvent"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i6$2.MatTab, selector: "mat-tab", inputs: ["disabled"], exportAs: ["matTab"] }, { kind: "component", type: i6$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "disableRipple", "fitInkBarToContent", "mat-stretch-tabs"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i14.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { kind: "component", type: i14.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i14.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i10.MatBadge, selector: "[matBadge]", inputs: ["matBadgeDisabled", "matBadgeColor", "matBadgeOverlap", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "component", type: TooltipComponent, selector: "ngx-mat-entity-tooltip", inputs: ["tooltipContent"] }] });
|
|
5538
6053
|
}
|
|
5539
6054
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityEditDialogComponent, decorators: [{
|
|
5540
6055
|
type: Component,
|
|
@@ -5547,8 +6062,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
5547
6062
|
MatButtonModule,
|
|
5548
6063
|
MatTabsModule,
|
|
5549
6064
|
NgxMatEntityConfirmDialogComponent,
|
|
5550
|
-
MatMenuModule
|
|
5551
|
-
|
|
6065
|
+
MatMenuModule,
|
|
6066
|
+
MatBadgeModule,
|
|
6067
|
+
TooltipComponent
|
|
6068
|
+
], template: "<div class=\"mat-dialog-title\">\n <div>{{data.editData.title(entityPriorChanges)}}</div>\n\n <div class=\"actions-container\">\n <button *ngIf=\"data.editData.actions.length\" type=\"button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{data.editData.actionsLabel}}\n </button>\n <mat-menu #menu=\"matMenu\">\n <button type=\"button\" *ngFor=\"let action of data.editData.actions\" [disabled]=\"editActionDisabled(action)\" (click)=\"runEditAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n \n <button type=\"button\" *ngIf=\"allowDelete\" mat-raised-button (click)=\"delete()\" color=\"warn\" class=\"delete-button\" tabindex=\"-1\">\n {{data.editData.deleteButtonLabel}}\n </button>\n </div>\n</div>\n\n<form>\n <mat-dialog-content>\n <mat-tab-group *ngIf=\"entityTabs.length > 1\" preserveContent>\n <mat-tab *ngFor=\"let tab of entityTabs\" [label]=\"tab.tabName\">\n <div class=\"row\" *ngFor=\"let row of tab.rows\">\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(key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </mat-tab>\n </mat-tab-group>\n \n <div *ngIf=\"entityTabs.length <= 1\">\n <span class=\"no-entity-tabs\" *ngIf=\"!entityTabs.length\">\n ERROR: No Inputs. Did you correctly assign all values in the model constructor?\n </span>\n <div class=\"row\" *ngFor=\"let row of entityTabs[0].rows\">\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(key)\"\n >\n </ngx-mat-entity-input>\n </div>\n </div>\n </mat-dialog-content>\n \n <mat-dialog-actions>\n <div class=\"d-flex align-items-center gap-3\" style=\"margin-top: 10px;\">\n <button type=\"submit\" (click)=\"edit()\" mat-raised-button\n [disabled]=\"isEntityReadOnly || !isEntityValid || !isEntityDirty\"\n [matBadge]=\"validationErrors.length\"\n [matBadgeHidden]=\"!validationErrors.length\"\n matBadgeColor=\"warn\"\n >\n {{data.editData.confirmButtonLabel}}\n </button>\n <ngx-mat-entity-tooltip *ngIf=\"validationErrors.length\" [tooltipContent]=\"tooltipContent\"></ngx-mat-entity-tooltip>\n </div>\n\n\n <button type=\"button\" mat-raised-button (click)=\"cancel()\" class=\"cancel-button\">\n {{data.editData.cancelButtonLabel}}\n </button>\n </mat-dialog-actions>\n</form>\n", styles: [".mat-dialog-title{padding:12px 20px;display:flex;justify-content:space-between;align-items:center}.mat-dialog-title div{font-size:var(--mdc-dialog-subhead-size, 14px);font-weight:var(--mdc-dialog-subhead-weight, 500)}.actions-container{display:flex;gap:10px}.no-entity-tabs{padding:10px;background-color:red;color:#f5f5f5}::ng-deep .mdc-dialog .mdc-dialog__content{padding:6px 20px!important}mat-dialog-actions{justify-content:space-between;align-items:center;padding-left:20px;padding-right:20px}\n"] }]
|
|
5552
6069
|
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
5553
6070
|
type: Inject,
|
|
5554
6071
|
args: [MAT_DIALOG_DATA]
|
|
@@ -5733,7 +6250,7 @@ class NgxMatEntityTableComponent {
|
|
|
5733
6250
|
const dialogData = new EditEntityDataBuilder(inputDialogData).getResult();
|
|
5734
6251
|
const res = await firstValueFrom(this.dialog.open(NgxMatEntityEditDialogComponent, {
|
|
5735
6252
|
data: dialogData,
|
|
5736
|
-
minWidth: '60%',
|
|
6253
|
+
// minWidth: '60%',
|
|
5737
6254
|
autoFocus: false,
|
|
5738
6255
|
restoreFocus: false
|
|
5739
6256
|
}).afterClosed());
|
|
@@ -5755,11 +6272,13 @@ class NgxMatEntityTableComponent {
|
|
|
5755
6272
|
if (!this.data.baseData.EntityClass) {
|
|
5756
6273
|
throw new Error('No "EntityClass" specified for this table');
|
|
5757
6274
|
}
|
|
6275
|
+
const entity = new this.data.baseData.EntityClass();
|
|
6276
|
+
EntityUtilities.setDefaultValues(entity);
|
|
5758
6277
|
if (this.data.baseData.create) {
|
|
5759
|
-
this.data.baseData.create(
|
|
6278
|
+
this.data.baseData.create(entity);
|
|
5760
6279
|
}
|
|
5761
6280
|
else {
|
|
5762
|
-
this.createDefault(
|
|
6281
|
+
this.createDefault(entity);
|
|
5763
6282
|
}
|
|
5764
6283
|
}
|
|
5765
6284
|
});
|
|
@@ -5832,7 +6351,7 @@ class NgxMatEntityTableComponent {
|
|
|
5832
6351
|
this.dataSource.filter = filterValue.trim().toLowerCase();
|
|
5833
6352
|
}
|
|
5834
6353
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityTableComponent, deps: [{ token: i1.MatDialog }, { token: i0.EnvironmentInjector }, { token: i2$3.Router }], target: i0.ɵɵFactoryTarget.Component });
|
|
5835
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: NgxMatEntityTableComponent, isStandalone: true, 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.tableActions.length\"\n [class.col-lg-2]=\"allowCreate\"\n [class.col-lg-4]=\"!allowCreate\"\n [class.col-md-3]=\"allowCreate\"\n [class.col-md-6]=\"!allowCreate\"\n [class.col-sm-6]=\"allowCreate\"\n [class.col-sm-12]=\"!allowCreate\"\n >\n <button type=\"button\" class=\"actions-button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{data.baseData.tableActionsLabel}}\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button *ngIf=\"data.baseData.allowJsonImport\" type=\"button\" [disabled]=\"tableActionDisabled(importAction)\" (click)=\"runTableAction(importAction)\" mat-menu-item>\n {{importAction.displayName}}\n </button>\n <button type=\"button\" *ngFor=\"let action of data.baseData.tableActions\" [disabled]=\"tableActionDisabled(action)\" (click)=\"runTableAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n\n <div\n *ngIf=\"allowCreate\"\n [class.col-lg-2]=\"data.baseData.tableActions.length\"\n [class.col-lg-4]=\"!data.baseData.tableActions.length\"\n [class.col-md-3]=\"data.baseData.tableActions.length\"\n [class.col-md-6]=\"!data.baseData.tableActions.length\"\n [class.col-sm-6]=\"data.baseData.tableActions.length\"\n [class.col-sm-12]=\"!data.baseData.tableActions.length\"\n >\n <button type=\"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 [dataSource]=\"dataSource\" matSort>\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox (change)=\"$event ? SelectionUtilities.masterToggle(selection, dataSource) : null\"\n [checked]=\"selection.hasValue() && SelectionUtilities.isAllSelected(selection, dataSource)\"\n [indeterminate]=\"selection.hasValue() && !SelectionUtilities.isAllSelected(selection, dataSource)\">\n </mat-checkbox>\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n <mat-checkbox (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? selection.toggle(entity) : null\"\n [checked]=\"selection.isSelected(entity)\">\n </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]=\"!dCol.disableClick && (allowUpdate(entity) || allowRead(entity))\"\n (click)=\"editEntity(entity, dCol)\"\n *matCellDef=\"let entity\"\n >\n <ng-container *ngIf=\"dCol.Component\">\n <display-column-value [entity]=\"entity\" [ComponentClass]=\"dCol.Component\"></display-column-value>\n </ng-container>\n <ng-container *ngIf=\"!dCol.Component\">\n {{getDisplayColumnValue(entity, dCol)}}\n </ng-container>\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-spinner *ngIf=\"isLoading && data.baseData.displayLoadingSpinner\">\n </mat-spinner>\n\n <mat-paginator [length]=\"dataSource.filteredData.length\" [pageIndex]=\"0\" [pageSize]=\"10\" [pageSizeOptions]=\"[5, 10, 25, 50]\"></mat-paginator>\n</div>", styles: [".mdc-data-table__row:last-child .mdc-data-table__cell{border-bottom:1px solid rgba(0,0,0,.12)}button{width:100%}mat-spinner{margin:10px auto}.title{text-align:center}.actions-button,.create-button{height:56px;line-height:24px;font-size:16px}.mat-column-select{flex:0 0 75px}.enabled:hover{cursor:pointer}@media (max-width: 767px){.actions-button,.create-button{margin-bottom:15px}}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$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"] }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i4.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i16.MatPaginator, selector: "mat-paginator", inputs: ["disabled"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type:
|
|
6354
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.0", type: NgxMatEntityTableComponent, isStandalone: true, 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.tableActions.length\"\n [class.col-lg-2]=\"allowCreate\"\n [class.col-lg-4]=\"!allowCreate\"\n [class.col-md-3]=\"allowCreate\"\n [class.col-md-6]=\"!allowCreate\"\n [class.col-sm-6]=\"allowCreate\"\n [class.col-sm-12]=\"!allowCreate\"\n >\n <button type=\"button\" class=\"actions-button\" [matMenuTriggerFor]=\"menu\" mat-raised-button>\n {{data.baseData.tableActionsLabel}}\n </button>\n </div>\n <mat-menu #menu=\"matMenu\">\n <button *ngIf=\"data.baseData.allowJsonImport\" type=\"button\" [disabled]=\"tableActionDisabled(importAction)\" (click)=\"runTableAction(importAction)\" mat-menu-item>\n {{importAction.displayName}}\n </button>\n <button type=\"button\" *ngFor=\"let action of data.baseData.tableActions\" [disabled]=\"tableActionDisabled(action)\" (click)=\"runTableAction(action)\" mat-menu-item>\n {{action.displayName}}\n </button>\n </mat-menu>\n\n <div\n *ngIf=\"allowCreate\"\n [class.col-lg-2]=\"data.baseData.tableActions.length\"\n [class.col-lg-4]=\"!data.baseData.tableActions.length\"\n [class.col-md-3]=\"data.baseData.tableActions.length\"\n [class.col-md-6]=\"!data.baseData.tableActions.length\"\n [class.col-sm-6]=\"data.baseData.tableActions.length\"\n [class.col-sm-12]=\"!data.baseData.tableActions.length\"\n >\n <button type=\"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 [dataSource]=\"dataSource\" matSort>\n <!-- select Column -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef>\n <mat-checkbox (change)=\"$event ? SelectionUtilities.masterToggle(selection, dataSource) : null\"\n [checked]=\"selection.hasValue() && SelectionUtilities.isAllSelected(selection, dataSource)\"\n [indeterminate]=\"selection.hasValue() && !SelectionUtilities.isAllSelected(selection, dataSource)\">\n </mat-checkbox>\n </mat-header-cell>\n <mat-cell class=\"entity\" *matCellDef=\"let entity\">\n <mat-checkbox (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? selection.toggle(entity) : null\"\n [checked]=\"selection.isSelected(entity)\">\n </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]=\"!dCol.disableClick && (allowUpdate(entity) || allowRead(entity))\"\n (click)=\"editEntity(entity, dCol)\"\n *matCellDef=\"let entity\"\n >\n <ng-container *ngIf=\"dCol.Component\">\n <display-column-value [entity]=\"entity\" [ComponentClass]=\"dCol.Component\"></display-column-value>\n </ng-container>\n <ng-container *ngIf=\"!dCol.Component\">\n {{getDisplayColumnValue(entity, dCol)}}\n </ng-container>\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-spinner *ngIf=\"isLoading && data.baseData.displayLoadingSpinner\">\n </mat-spinner>\n\n <mat-paginator [length]=\"dataSource.filteredData.length\" [pageIndex]=\"0\" [pageSize]=\"10\" [pageSizeOptions]=\"[5, 10, 25, 50]\"></mat-paginator>\n</div>", styles: [".mdc-data-table__row:last-child .mdc-data-table__cell{border-bottom:1px solid rgba(0,0,0,.12)}button{width:100%}mat-spinner{margin:10px auto}.title{text-align:center}.actions-button,.create-button{height:56px;line-height:24px;font-size:16px}.mat-column-select{flex:0 0 75px}.enabled:hover{cursor:pointer}@media (max-width: 767px){.actions-button,.create-button{margin-bottom:15px}}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$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"] }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i4.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i16.MatPaginator, selector: "mat-paginator", inputs: ["disabled"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i18.MatSort, selector: "[matSort]", inputs: ["matSortDisabled", "matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i18.MatSortHeader, selector: "[mat-sort-header]", inputs: ["disabled", "mat-sort-header", "arrowPosition", "start", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i14.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { kind: "component", type: i14.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i14.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i15.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: DisplayColumnValueComponent, selector: "display-column-value", inputs: ["entity", "ComponentClass"] }] });
|
|
5836
6355
|
}
|
|
5837
6356
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityTableComponent, decorators: [{
|
|
5838
6357
|
type: Component,
|
|
@@ -5845,6 +6364,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
5845
6364
|
MatCheckboxModule,
|
|
5846
6365
|
MatTableModule,
|
|
5847
6366
|
MatPaginatorModule,
|
|
6367
|
+
MatSortModule,
|
|
5848
6368
|
MatButtonModule,
|
|
5849
6369
|
MatMenuModule,
|
|
5850
6370
|
MatDialogModule,
|
|
@@ -5920,6 +6440,15 @@ class PropertyDecoratorConfig {
|
|
|
5920
6440
|
*/
|
|
5921
6441
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5922
6442
|
isReadOnly;
|
|
6443
|
+
/**
|
|
6444
|
+
* The value that the property should be prefilled with. Only active in create mode.
|
|
6445
|
+
*/
|
|
6446
|
+
default;
|
|
6447
|
+
/**
|
|
6448
|
+
* A function that runs just before the inputChangeEvent every time the property is changed.
|
|
6449
|
+
*/
|
|
6450
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6451
|
+
change;
|
|
5923
6452
|
}
|
|
5924
6453
|
|
|
5925
6454
|
/**
|
|
@@ -6461,6 +6990,7 @@ class DateTimeDateDecoratorConfigInternal extends PropertyDecoratorConfigInterna
|
|
|
6461
6990
|
this.minTime = data.minTime;
|
|
6462
6991
|
this.maxTime = data.maxTime;
|
|
6463
6992
|
this.filterTime = data.filterTime;
|
|
6993
|
+
this.defaultWidths = [6, 12, 12];
|
|
6464
6994
|
}
|
|
6465
6995
|
}
|
|
6466
6996
|
|
|
@@ -7015,5 +7545,5 @@ class StringDecoratorConfig extends PropertyDecoratorConfig {
|
|
|
7015
7545
|
* Generated bundle index. Do not edit.
|
|
7016
7546
|
*/
|
|
7017
7547
|
|
|
7018
|
-
export { ArrayDecoratorConfig, DateUtilities, DecoratorTypes, Entity, EntityService, EntityUtilities, FileUtilities, NGX_EDIT_DATA, NGX_EDIT_DATA_ENTITY, NGX_EDIT_DATA_ENTITY_SERVICE, NGX_GET_VALIDATION_ERROR_MESSAGE, NgxMatEntityBaseDisplayColumnValueComponent, NgxMatEntityBaseInputComponent, NgxMatEntityConfirmDialogComponent, NgxMatEntityCreateDialogComponent, NgxMatEntityEditDialogComponent, NgxMatEntityEditPageComponent, NgxMatEntityInputComponent, NgxMatEntityInputModule, NgxMatEntityTableComponent, UnsavedChangesGuard, array, boolean, custom, date, defaultEditDataRoute, exportAsCsvMultiAction, exportAsJsonMultiAction, exportAsXmlMultiAction, file, hasMany, importFromJsonMultiAction, number, object, referencesMany, referencesOne, string };
|
|
7548
|
+
export { ArrayDecoratorConfig, DateUtilities, DecoratorTypes, Entity, EntityService, EntityUtilities, FileUtilities, NGX_EDIT_DATA, NGX_EDIT_DATA_ENTITY, NGX_EDIT_DATA_ENTITY_SERVICE, NGX_GET_VALIDATION_ERROR_MESSAGE, NGX_VALIDATION_ERRORS_TOOLTIP_TITLE, NgxMatEntityBaseDisplayColumnValueComponent, NgxMatEntityBaseInputComponent, NgxMatEntityConfirmDialogComponent, NgxMatEntityCreateDialogComponent, NgxMatEntityEditDialogComponent, NgxMatEntityEditPageComponent, NgxMatEntityInputComponent, NgxMatEntityInputModule, NgxMatEntityTableComponent, TooltipComponent, UnsavedChangesGuard, ValidationUtilities, array, boolean, custom, date, defaultEditDataRoute, exportAsCsvMultiAction, exportAsJsonMultiAction, exportAsXmlMultiAction, file, getValidationErrorsTooltipContent, hasMany, importFromJsonMultiAction, number, object, referencesMany, referencesOne, string };
|
|
7019
7549
|
//# sourceMappingURL=ngx-material-entity.mjs.map
|