ngx-material-entity 16.0.2 → 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 +1 -1
- package/components/input/input.module.d.ts +4 -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/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 +7 -6
- package/esm2022/components/input/input.module.mjs +10 -4
- 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 +7 -4
- 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 +1374 -905
- 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,6 +16,8 @@ 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 i10 from '@angular/material/badge';
|
|
20
|
+
import { MatBadgeModule } from '@angular/material/badge';
|
|
19
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';
|
|
@@ -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,800 +838,504 @@ 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]);
|
|
1205
|
+
const metadata = this.getPropertyMetadata(entity, key);
|
|
1206
|
+
if (!metadata.display(entity)) {
|
|
1207
|
+
res.push(key);
|
|
1182
1208
|
}
|
|
1183
1209
|
}
|
|
1184
1210
|
return res;
|
|
1185
1211
|
}
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
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);
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
/**
|
|
1215
|
+
* The base decorator for setting metadata on properties.
|
|
1216
|
+
*
|
|
1217
|
+
* @param metadata - The metadata to define.
|
|
1218
|
+
* @param type - The type of metadata.
|
|
1219
|
+
* @param metadataKeysToReset - Any metadata keys which values should be set to undefined on reset.
|
|
1220
|
+
* @returns The method that sets the metadata.
|
|
1221
|
+
*/
|
|
1222
|
+
function baseProperty(metadata, type, metadataKeysToReset) {
|
|
1223
|
+
return function (target, propertyKey) {
|
|
1224
|
+
ReflectUtilities.defineMetadata('metadata', metadata, target, propertyKey);
|
|
1225
|
+
ReflectUtilities.defineMetadata('type', type, target, propertyKey);
|
|
1226
|
+
// eslint-disable-next-line max-len
|
|
1227
|
+
ReflectUtilities.defineMetadata(EntityUtilities.METADATA_KEYS_TO_RESET_KEY, metadataKeysToReset, target, propertyKey);
|
|
1228
|
+
};
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
/**
|
|
1232
|
+
* The default false function.
|
|
1233
|
+
* A boolean false is resolved to this.
|
|
1234
|
+
*
|
|
1235
|
+
* @returns False.
|
|
1236
|
+
*/
|
|
1237
|
+
function defaultFalse() {
|
|
1238
|
+
return false;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
/**
|
|
1242
|
+
* The internal Position. Sets default values and validates user input.
|
|
1243
|
+
*/
|
|
1244
|
+
class PositionInternal {
|
|
1245
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1246
|
+
row;
|
|
1247
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1248
|
+
order;
|
|
1249
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1250
|
+
tab;
|
|
1251
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1252
|
+
tabName;
|
|
1253
|
+
constructor(data) {
|
|
1254
|
+
this.validateInput(data);
|
|
1255
|
+
this.row = data?.row ?? -1;
|
|
1256
|
+
this.order = data?.order ?? -1;
|
|
1257
|
+
this.tab = data?.tab ?? -1;
|
|
1258
|
+
this.tabName = data?.tabName;
|
|
1291
1259
|
}
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
if (valuePriorChanges == null) {
|
|
1297
|
-
return true;
|
|
1260
|
+
validateInput(data) {
|
|
1261
|
+
if (data?.order != null) {
|
|
1262
|
+
if (data.order < 1) {
|
|
1263
|
+
throw new Error('order must be at least 1');
|
|
1298
1264
|
}
|
|
1299
|
-
|
|
1300
|
-
|
|
1265
|
+
if (data.order > 12) {
|
|
1266
|
+
throw new Error('order cannot be bigger than 12 (the minimum value for a bootstrap column)');
|
|
1301
1267
|
}
|
|
1302
1268
|
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
if (files.length !== filesPriorChanges.length) {
|
|
1306
|
-
return false;
|
|
1269
|
+
if (data?.row != null && data.row < 1) {
|
|
1270
|
+
throw new Error('row must be at least 1');
|
|
1307
1271
|
}
|
|
1308
|
-
|
|
1309
|
-
|
|
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
|
-
}
|
|
1272
|
+
if (data?.tab != null && data.tab != -1 && data.tab < 2) {
|
|
1273
|
+
throw new Error('tab must be either -1 for the first tab or at least 2');
|
|
1324
1274
|
}
|
|
1325
|
-
return true;
|
|
1326
1275
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* The internal PropertyDecoratorConfig. Sets default values.
|
|
1279
|
+
*/
|
|
1280
|
+
class PropertyDecoratorConfigInternal {
|
|
1281
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1282
|
+
display;
|
|
1283
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1284
|
+
displayName;
|
|
1285
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1286
|
+
required;
|
|
1287
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1288
|
+
omitForCreate;
|
|
1289
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1290
|
+
omitForUpdate;
|
|
1291
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1292
|
+
defaultWidths;
|
|
1293
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1294
|
+
position;
|
|
1295
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1296
|
+
isReadOnly;
|
|
1297
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1298
|
+
default;
|
|
1299
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1300
|
+
change;
|
|
1301
|
+
constructor(data) {
|
|
1302
|
+
this.display = this.booleanToFunction(data.display ?? true);
|
|
1303
|
+
this.displayName = data.displayName;
|
|
1304
|
+
this.required = this.booleanToFunction(data.required ?? true);
|
|
1305
|
+
this.omitForCreate = data.omitForCreate ?? false;
|
|
1306
|
+
this.omitForUpdate = data.omitForUpdate ?? false;
|
|
1307
|
+
this.defaultWidths = data.defaultWidths ?? [6, 6, 12];
|
|
1308
|
+
this.position = new PositionInternal(data.position);
|
|
1309
|
+
this.isReadOnly = this.booleanToFunction(data.isReadOnly ?? false);
|
|
1310
|
+
this.default = this.defaultToFunction(data.default);
|
|
1311
|
+
this.change = data.change;
|
|
1334
1312
|
}
|
|
1335
1313
|
/**
|
|
1336
|
-
*
|
|
1314
|
+
* Converts the default value to a function or undefined.
|
|
1337
1315
|
*
|
|
1338
|
-
* @param
|
|
1339
|
-
* @
|
|
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'.
|
|
1316
|
+
* @param value - The default value provided by the metadata.
|
|
1317
|
+
* @returns A function that returns a default value or undefined.
|
|
1342
1318
|
*/
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
if (metadataA.position.order === -1) {
|
|
1347
|
-
if (metadataB.position.order === -1) {
|
|
1348
|
-
return 0;
|
|
1349
|
-
}
|
|
1350
|
-
return 1;
|
|
1319
|
+
defaultToFunction(value) {
|
|
1320
|
+
if (value == null) {
|
|
1321
|
+
return undefined;
|
|
1351
1322
|
}
|
|
1352
|
-
|
|
1353
|
-
return
|
|
1323
|
+
if (typeof value == 'function') {
|
|
1324
|
+
return value;
|
|
1354
1325
|
}
|
|
1355
|
-
return
|
|
1326
|
+
return (() => value);
|
|
1356
1327
|
}
|
|
1357
1328
|
/**
|
|
1358
|
-
*
|
|
1329
|
+
* Converts the given boolean or boolean function to a boolean function.
|
|
1359
1330
|
*
|
|
1360
|
-
* @param
|
|
1361
|
-
* @
|
|
1362
|
-
* @param type - Defines for which screen size the column values should be returned.
|
|
1363
|
-
* @returns Bootstrap column value.
|
|
1331
|
+
* @param value - The value to convert.
|
|
1332
|
+
* @returns A function that resolves to a boolean.
|
|
1364
1333
|
*/
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
case 'lg':
|
|
1369
|
-
return metadata.defaultWidths[0];
|
|
1370
|
-
case 'md':
|
|
1371
|
-
return metadata.defaultWidths[1];
|
|
1372
|
-
case 'sm':
|
|
1373
|
-
return metadata.defaultWidths[2];
|
|
1334
|
+
booleanToFunction(value) {
|
|
1335
|
+
if (typeof value !== 'boolean') {
|
|
1336
|
+
return value;
|
|
1374
1337
|
}
|
|
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);
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1511
|
-
return res;
|
|
1512
|
-
}
|
|
1513
|
-
}
|
|
1514
|
-
|
|
1515
|
-
/**
|
|
1516
|
-
* The base decorator for setting metadata on properties.
|
|
1517
|
-
*
|
|
1518
|
-
* @param metadata - The metadata to define.
|
|
1519
|
-
* @param type - The type of metadata.
|
|
1520
|
-
* @param metadataKeysToReset - Any metadata keys which values should be set to undefined on reset.
|
|
1521
|
-
* @returns The method that sets the metadata.
|
|
1522
|
-
*/
|
|
1523
|
-
function baseProperty(metadata, type, metadataKeysToReset) {
|
|
1524
|
-
return function (target, propertyKey) {
|
|
1525
|
-
ReflectUtilities.defineMetadata('metadata', metadata, target, propertyKey);
|
|
1526
|
-
ReflectUtilities.defineMetadata('type', type, target, propertyKey);
|
|
1527
|
-
// eslint-disable-next-line max-len
|
|
1528
|
-
ReflectUtilities.defineMetadata(EntityUtilities.METADATA_KEYS_TO_RESET_KEY, metadataKeysToReset, target, propertyKey);
|
|
1529
|
-
};
|
|
1530
|
-
}
|
|
1531
|
-
|
|
1532
|
-
/**
|
|
1533
|
-
* The default false function.
|
|
1534
|
-
* A boolean false is resolved to this.
|
|
1535
|
-
*
|
|
1536
|
-
* @returns False.
|
|
1537
|
-
*/
|
|
1538
|
-
function defaultFalse() {
|
|
1539
|
-
return false;
|
|
1540
|
-
}
|
|
1541
|
-
|
|
1542
|
-
/**
|
|
1543
|
-
* The internal Position. Sets default values and validates user input.
|
|
1544
|
-
*/
|
|
1545
|
-
class PositionInternal {
|
|
1546
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1547
|
-
row;
|
|
1548
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1549
|
-
order;
|
|
1550
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1551
|
-
tab;
|
|
1552
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1553
|
-
tabName;
|
|
1554
|
-
constructor(data) {
|
|
1555
|
-
this.validateInput(data);
|
|
1556
|
-
this.row = data?.row ?? -1;
|
|
1557
|
-
this.order = data?.order ?? -1;
|
|
1558
|
-
this.tab = data?.tab ?? -1;
|
|
1559
|
-
this.tabName = data?.tabName;
|
|
1560
|
-
}
|
|
1561
|
-
validateInput(data) {
|
|
1562
|
-
if (data?.order != null) {
|
|
1563
|
-
if (data.order < 1) {
|
|
1564
|
-
throw new Error('order must be at least 1');
|
|
1565
|
-
}
|
|
1566
|
-
if (data.order > 12) {
|
|
1567
|
-
throw new Error('order cannot be bigger than 12 (the minimum value for a bootstrap column)');
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1570
|
-
if (data?.row != null && data.row < 1) {
|
|
1571
|
-
throw new Error('row must be at least 1');
|
|
1572
|
-
}
|
|
1573
|
-
if (data?.tab != null && data.tab != -1 && data.tab < 2) {
|
|
1574
|
-
throw new Error('tab must be either -1 for the first tab or at least 2');
|
|
1575
|
-
}
|
|
1576
|
-
}
|
|
1577
|
-
}
|
|
1578
|
-
/**
|
|
1579
|
-
* The internal PropertyDecoratorConfig. Sets default values.
|
|
1580
|
-
*/
|
|
1581
|
-
class PropertyDecoratorConfigInternal {
|
|
1582
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1583
|
-
display;
|
|
1584
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1585
|
-
displayName;
|
|
1586
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1587
|
-
required;
|
|
1588
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1589
|
-
omitForCreate;
|
|
1590
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1591
|
-
omitForUpdate;
|
|
1592
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1593
|
-
defaultWidths;
|
|
1594
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1595
|
-
position;
|
|
1596
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1597
|
-
isReadOnly;
|
|
1598
|
-
constructor(data) {
|
|
1599
|
-
this.display = this.booleanToFunction(data.display ?? true);
|
|
1600
|
-
this.displayName = data.displayName;
|
|
1601
|
-
this.required = this.booleanToFunction(data.required ?? true);
|
|
1602
|
-
this.omitForCreate = data.omitForCreate ?? false;
|
|
1603
|
-
this.omitForUpdate = data.omitForUpdate ?? false;
|
|
1604
|
-
this.defaultWidths = data.defaultWidths ?? [6, 6, 12];
|
|
1605
|
-
this.position = new PositionInternal(data.position);
|
|
1606
|
-
this.isReadOnly = this.booleanToFunction(data.isReadOnly ?? false);
|
|
1607
|
-
}
|
|
1608
|
-
/**
|
|
1609
|
-
* Converts the given boolean or boolean function to a boolean function.
|
|
1610
|
-
*
|
|
1611
|
-
* @param value - The value to convert.
|
|
1612
|
-
* @returns A function that resolves to a boolean.
|
|
1613
|
-
*/
|
|
1614
|
-
booleanToFunction(value) {
|
|
1615
|
-
if (typeof value !== 'boolean') {
|
|
1616
|
-
return value;
|
|
1617
|
-
}
|
|
1618
|
-
return value ? defaultTrue : defaultFalse;
|
|
1338
|
+
return value ? defaultTrue : defaultFalse;
|
|
1619
1339
|
}
|
|
1620
1340
|
}
|
|
1621
1341
|
|
|
@@ -1717,8 +1437,6 @@ class PasswordStringDecoratorConfigInternal extends PropertyDecoratorConfigInter
|
|
|
1717
1437
|
needsConfirmation;
|
|
1718
1438
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1719
1439
|
confirmationDisplayName;
|
|
1720
|
-
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
1721
|
-
passwordsDontMatchErrorMessage;
|
|
1722
1440
|
constructor(data) {
|
|
1723
1441
|
super(data);
|
|
1724
1442
|
this.displayStyle = data.displayStyle;
|
|
@@ -1727,7 +1445,6 @@ class PasswordStringDecoratorConfigInternal extends PropertyDecoratorConfigInter
|
|
|
1727
1445
|
this.regex = data.regex;
|
|
1728
1446
|
this.needsConfirmation = data.needsConfirmation ?? true;
|
|
1729
1447
|
this.confirmationDisplayName = data.confirmationDisplayName ?? 'Confirm Password';
|
|
1730
|
-
this.passwordsDontMatchErrorMessage = data.passwordsDontMatchErrorMessage ?? 'Passwords need to match!';
|
|
1731
1448
|
this.defaultWidths = data.defaultWidths ?? [12, 12, 12];
|
|
1732
1449
|
}
|
|
1733
1450
|
}
|
|
@@ -1946,6 +1663,30 @@ const defaultEditDataRoute = {
|
|
|
1946
1663
|
canDeactivate: [UnsavedChangesGuard]
|
|
1947
1664
|
};
|
|
1948
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
|
+
|
|
1949
1690
|
/**
|
|
1950
1691
|
* A generic EntityService class.
|
|
1951
1692
|
* Offers basic CRUD-functionality.
|
|
@@ -2131,91 +1872,663 @@ class EntityService {
|
|
|
2131
1872
|
}
|
|
2132
1873
|
}
|
|
2133
1874
|
/**
|
|
2134
|
-
* Builds the update request body from the given entity before and after its changes.
|
|
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);
|
|
1884
|
+
}
|
|
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);
|
|
1925
|
+
}
|
|
1926
|
+
/**
|
|
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.
|
|
1931
|
+
*/
|
|
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);
|
|
1947
|
+
}
|
|
1948
|
+
/**
|
|
1949
|
+
* Deletes a specific Entity.
|
|
1950
|
+
*
|
|
1951
|
+
* @param entity - The entity to delete.
|
|
1952
|
+
*/
|
|
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);
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
/**
|
|
1962
|
+
* Contains HelperMethods around handling Validation of entities and properties.
|
|
1963
|
+
*/
|
|
1964
|
+
class ValidationUtilities {
|
|
1965
|
+
/**
|
|
1966
|
+
* Checks if the values on an entity are valid.
|
|
1967
|
+
* Also checks all the validators given by the metadata ("required", "maxLength" etc.).
|
|
1968
|
+
*
|
|
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.
|
|
1972
|
+
*/
|
|
1973
|
+
static isEntityValid(entity, omit) {
|
|
1974
|
+
return this.getEntityValidationErrors(entity, omit).length === 0;
|
|
1975
|
+
}
|
|
1976
|
+
/**
|
|
1977
|
+
* Gets all validation errors on the given entity.
|
|
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.
|
|
1982
|
+
*/
|
|
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
|
+
// }
|
|
2009
|
+
/**
|
|
2010
|
+
* Validates the property on the given entity with the given key.
|
|
2011
|
+
*
|
|
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.
|
|
2017
|
+
*/
|
|
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;
|
|
2140
|
+
}
|
|
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;
|
|
2149
|
+
}
|
|
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
|
+
};
|
|
2240
|
+
}
|
|
2241
|
+
if (metadata.filter && !metadata.filter(value)) {
|
|
2242
|
+
return {
|
|
2243
|
+
property: metadata.displayName,
|
|
2244
|
+
message: 'invalid'
|
|
2245
|
+
};
|
|
2246
|
+
}
|
|
2247
|
+
return undefined;
|
|
2248
|
+
}
|
|
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
|
+
};
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
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
|
+
};
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
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
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
if (metadata.filterTime && !metadata.filterTime(time)) {
|
|
2357
|
+
return {
|
|
2358
|
+
property: metadata.displayName,
|
|
2359
|
+
message: 'invalid time'
|
|
2360
|
+
};
|
|
2361
|
+
}
|
|
2362
|
+
return undefined;
|
|
2363
|
+
}
|
|
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
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
return undefined;
|
|
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 {
|
|
2414
|
+
/**
|
|
2415
|
+
* Emits the dropped files to the parent.
|
|
2416
|
+
*/
|
|
2417
|
+
files = new EventEmitter();
|
|
2418
|
+
constructor() { }
|
|
2419
|
+
/**
|
|
2420
|
+
* Prevents the event default.
|
|
2421
|
+
*
|
|
2422
|
+
* @param evt - The Event when dragged files hover over the parent.
|
|
2423
|
+
*/
|
|
2424
|
+
onDragOver(evt) {
|
|
2425
|
+
evt.preventDefault();
|
|
2426
|
+
evt.stopPropagation();
|
|
2427
|
+
}
|
|
2428
|
+
/**
|
|
2429
|
+
* Prevents the event default.
|
|
2135
2430
|
*
|
|
2136
|
-
* @param
|
|
2137
|
-
* @param entityPriorChanges - The entity before any changes.
|
|
2138
|
-
* @returns A partial of only the changed values.
|
|
2431
|
+
* @param evt - The Event when dragged files leave the parent.
|
|
2139
2432
|
*/
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2433
|
+
onDragLeave(evt) {
|
|
2434
|
+
evt.preventDefault();
|
|
2435
|
+
evt.stopPropagation();
|
|
2143
2436
|
}
|
|
2144
|
-
// TODO: Find a way to use blobs with jest
|
|
2145
|
-
/* istanbul ignore next */
|
|
2146
2437
|
/**
|
|
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.
|
|
2438
|
+
* Prevents the event default and emits the dropped files with the output.
|
|
2150
2439
|
*
|
|
2151
|
-
* @param
|
|
2152
|
-
* @param filePropertyKeys - The keys of all properties which are files and need to separately be appended to the form data.
|
|
2153
|
-
* @param entity - The original entity. Is needed to get the metadata of all the files.
|
|
2154
|
-
* @param id - The id of the entity to update.
|
|
2440
|
+
* @param evt - The Event when files are dropped.
|
|
2155
2441
|
*/
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
const fileDataValues = body[key];
|
|
2162
|
-
for (const value of fileDataValues) {
|
|
2163
|
-
formData.append(key, (await FileUtilities.getFileData(value, this.http)).file, value.name);
|
|
2164
|
-
}
|
|
2165
|
-
}
|
|
2166
|
-
else {
|
|
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;
|
|
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.
|
|
@@ -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 */
|
|
@@ -4547,7 +4819,7 @@ class NgxMatEntityInputComponent {
|
|
|
4547
4819
|
* @param omit - Whether values omitted for create or update should be left out.
|
|
4548
4820
|
*/
|
|
4549
4821
|
checkIsHasManyEntityValid(omit) {
|
|
4550
|
-
this.isHasManyEntityValid =
|
|
4822
|
+
this.isHasManyEntityValid = ValidationUtilities.isEntityValid(this.hasManyEntity, omit);
|
|
4551
4823
|
}
|
|
4552
4824
|
/**
|
|
4553
4825
|
* Checks whether the array item is valid and if the array item is dirty.
|
|
@@ -4566,7 +4838,7 @@ class NgxMatEntityInputComponent {
|
|
|
4566
4838
|
* Checks if the arrayItem is valid.
|
|
4567
4839
|
*/
|
|
4568
4840
|
checkIsArrayItemValid() {
|
|
4569
|
-
this.isArrayItemValid =
|
|
4841
|
+
this.isArrayItemValid = ValidationUtilities.isEntityValid(this.arrayItem, 'create');
|
|
4570
4842
|
}
|
|
4571
4843
|
/**
|
|
4572
4844
|
* Emits that a the value has been changed.
|
|
@@ -4673,11 +4945,11 @@ class NgxMatEntityInputComponent {
|
|
|
4673
4945
|
this.emitChange();
|
|
4674
4946
|
}
|
|
4675
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 });
|
|
4676
|
-
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}::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: 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"] }] });
|
|
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"] }] });
|
|
4677
4949
|
}
|
|
4678
4950
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityInputComponent, decorators: [{
|
|
4679
4951
|
type: Component,
|
|
4680
|
-
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}::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"] }]
|
|
4681
4953
|
}], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i0.EnvironmentInjector }, { type: i2$3.Router }, { type: undefined, decorators: [{
|
|
4682
4954
|
type: Inject,
|
|
4683
4955
|
args: [NGX_GET_VALIDATION_ERROR_MESSAGE]
|
|
@@ -4767,7 +5039,9 @@ class NgxMatEntityInputModule {
|
|
|
4767
5039
|
MatProgressSpinnerModule,
|
|
4768
5040
|
MatPaginatorModule,
|
|
4769
5041
|
DisplayColumnValueComponent,
|
|
4770
|
-
MatSortModule
|
|
5042
|
+
MatSortModule,
|
|
5043
|
+
PasswordMatchValidatorDirective,
|
|
5044
|
+
NumberDirective], exports: [NgxMatEntityInputComponent] });
|
|
4771
5045
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityInputModule, imports: [CommonModule,
|
|
4772
5046
|
MatInputModule,
|
|
4773
5047
|
FormsModule,
|
|
@@ -4841,12 +5115,141 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
4841
5115
|
MatProgressSpinnerModule,
|
|
4842
5116
|
MatPaginatorModule,
|
|
4843
5117
|
DisplayColumnValueComponent,
|
|
4844
|
-
MatSortModule
|
|
5118
|
+
MatSortModule,
|
|
5119
|
+
PasswordMatchValidatorDirective,
|
|
5120
|
+
NumberDirective
|
|
4845
5121
|
],
|
|
4846
5122
|
exports: [NgxMatEntityInputComponent]
|
|
4847
5123
|
}]
|
|
4848
5124
|
}] });
|
|
4849
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
|
+
|
|
4850
5253
|
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
4851
5254
|
class PageEditDataBuilder extends BaseBuilder {
|
|
4852
5255
|
constructor(data) {
|
|
@@ -4904,13 +5307,17 @@ class NgxMatEntityEditPageComponent {
|
|
|
4904
5307
|
EntityClass;
|
|
4905
5308
|
inputData;
|
|
4906
5309
|
http;
|
|
5310
|
+
el;
|
|
5311
|
+
renderer;
|
|
4907
5312
|
EntityUtilities = EntityUtilities;
|
|
4908
5313
|
entityTabs;
|
|
4909
5314
|
entity;
|
|
4910
5315
|
entityPriorChanges;
|
|
4911
5316
|
data;
|
|
5317
|
+
validationErrors = [];
|
|
4912
5318
|
isEntityValid = true;
|
|
4913
5319
|
isEntityDirty = false;
|
|
5320
|
+
tooltipContent = '';
|
|
4914
5321
|
isEntityReadOnly;
|
|
4915
5322
|
allowDelete;
|
|
4916
5323
|
inConfirmNavigation = false;
|
|
@@ -4918,7 +5325,7 @@ class NgxMatEntityEditPageComponent {
|
|
|
4918
5325
|
get hasUnsavedChanges() {
|
|
4919
5326
|
return this.isEntityDirty && this.data.editData.unsavedChangesRequireConfirmDialog;
|
|
4920
5327
|
}
|
|
4921
|
-
constructor(dialog, location, route, injector, entityService, EntityClass, inputData, http) {
|
|
5328
|
+
constructor(dialog, location, route, injector, entityService, EntityClass, inputData, http, el, renderer) {
|
|
4922
5329
|
this.dialog = dialog;
|
|
4923
5330
|
this.location = location;
|
|
4924
5331
|
this.route = route;
|
|
@@ -4927,6 +5334,8 @@ class NgxMatEntityEditPageComponent {
|
|
|
4927
5334
|
this.EntityClass = EntityClass;
|
|
4928
5335
|
this.inputData = inputData;
|
|
4929
5336
|
this.http = http;
|
|
5337
|
+
this.el = el;
|
|
5338
|
+
this.renderer = renderer;
|
|
4930
5339
|
}
|
|
4931
5340
|
/**
|
|
4932
5341
|
* Checks if the input with the given key is readonly.
|
|
@@ -4935,7 +5344,7 @@ class NgxMatEntityEditPageComponent {
|
|
|
4935
5344
|
* @returns Whether or not the input for the key is read only.
|
|
4936
5345
|
*/
|
|
4937
5346
|
isReadOnly(key) {
|
|
4938
|
-
return this.injector
|
|
5347
|
+
return runInInjectionContext(this.injector, () => {
|
|
4939
5348
|
const metadata = EntityUtilities.getPropertyMetadata(this.entity, key);
|
|
4940
5349
|
return this.isEntityReadOnly || metadata.isReadOnly(this.entity);
|
|
4941
5350
|
});
|
|
@@ -4954,11 +5363,34 @@ class NgxMatEntityEditPageComponent {
|
|
|
4954
5363
|
}
|
|
4955
5364
|
this.entity = new this.EntityClass(foundEntity);
|
|
4956
5365
|
this.entityPriorChanges = LodashUtilities.cloneDeep(this.entity);
|
|
4957
|
-
this.injector
|
|
5366
|
+
runInInjectionContext(this.injector, () => {
|
|
4958
5367
|
this.isEntityReadOnly = !this.data.allowUpdate(this.entityPriorChanges);
|
|
4959
5368
|
this.allowDelete = this.data.allowDelete(this.entityPriorChanges);
|
|
4960
5369
|
});
|
|
4961
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
|
+
}
|
|
4962
5394
|
}
|
|
4963
5395
|
/**
|
|
4964
5396
|
* Whether the page can be left without confirmation (of unsaved changes).
|
|
@@ -4972,9 +5404,14 @@ class NgxMatEntityEditPageComponent {
|
|
|
4972
5404
|
* Checks if the entity has become invalid or dirty.
|
|
4973
5405
|
*/
|
|
4974
5406
|
async checkEntity() {
|
|
4975
|
-
this.
|
|
5407
|
+
this.checkIsEntityValid();
|
|
4976
5408
|
this.isEntityDirty = await EntityUtilities.isDirty(this.entity, this.entityPriorChanges, this.http);
|
|
4977
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
|
+
}
|
|
4978
5415
|
/**
|
|
4979
5416
|
* Tries to save the changes and close the dialog afterwards.
|
|
4980
5417
|
* Also handles the confirmation if required.
|
|
@@ -5111,8 +5548,8 @@ class NgxMatEntityEditPageComponent {
|
|
|
5111
5548
|
return !action.enabled(this.entityPriorChanges);
|
|
5112
5549
|
});
|
|
5113
5550
|
}
|
|
5114
|
-
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 });
|
|
5115
|
-
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"] }] });
|
|
5116
5553
|
}
|
|
5117
5554
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityEditPageComponent, decorators: [{
|
|
5118
5555
|
type: Component,
|
|
@@ -5123,8 +5560,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
5123
5560
|
MatTabsModule,
|
|
5124
5561
|
NgxMatEntityInputModule,
|
|
5125
5562
|
MatProgressSpinnerModule,
|
|
5126
|
-
MatMenuModule
|
|
5127
|
-
|
|
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"] }]
|
|
5128
5567
|
}], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i1$1.Location }, { type: i2$3.ActivatedRoute }, { type: i0.EnvironmentInjector }, { type: EntityService, decorators: [{
|
|
5129
5568
|
type: Inject,
|
|
5130
5569
|
args: [NGX_EDIT_DATA_ENTITY_SERVICE]
|
|
@@ -5134,7 +5573,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
5134
5573
|
}] }, { type: undefined, decorators: [{
|
|
5135
5574
|
type: Inject,
|
|
5136
5575
|
args: [NGX_EDIT_DATA]
|
|
5137
|
-
}] }, { 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: [{
|
|
5138
5580
|
type: HostListener,
|
|
5139
5581
|
args: ['window:beforeunload']
|
|
5140
5582
|
}] } });
|
|
@@ -5193,6 +5635,8 @@ class NgxMatEntityCreateDialogComponent {
|
|
|
5193
5635
|
entityService;
|
|
5194
5636
|
data;
|
|
5195
5637
|
isEntityValid = false;
|
|
5638
|
+
validationErrors = [];
|
|
5639
|
+
tooltipContent = '';
|
|
5196
5640
|
constructor(inputData, dialogRef, injector, dialog) {
|
|
5197
5641
|
this.inputData = inputData;
|
|
5198
5642
|
this.dialogRef = dialogRef;
|
|
@@ -5204,12 +5648,15 @@ class NgxMatEntityCreateDialogComponent {
|
|
|
5204
5648
|
this.dialogRef.disableClose = true;
|
|
5205
5649
|
this.entityTabs = EntityUtilities.getEntityTabs(this.data.entity, true);
|
|
5206
5650
|
this.entityService = this.injector.get(this.data.EntityServiceClass);
|
|
5651
|
+
setTimeout(() => this.checkIsEntityValid(), 1);
|
|
5207
5652
|
}
|
|
5208
5653
|
/**
|
|
5209
5654
|
* Checks if the entity is valid.
|
|
5210
5655
|
*/
|
|
5211
5656
|
checkIsEntityValid() {
|
|
5212
|
-
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;
|
|
5213
5660
|
}
|
|
5214
5661
|
/**
|
|
5215
5662
|
* Tries add the new entity and close the dialog afterwards.
|
|
@@ -5249,7 +5696,7 @@ class NgxMatEntityCreateDialogComponent {
|
|
|
5249
5696
|
this.dialogRef.close();
|
|
5250
5697
|
}
|
|
5251
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 });
|
|
5252
|
-
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"] }] });
|
|
5253
5700
|
}
|
|
5254
5701
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityCreateDialogComponent, decorators: [{
|
|
5255
5702
|
type: Component,
|
|
@@ -5260,8 +5707,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
5260
5707
|
MatDialogModule,
|
|
5261
5708
|
FormsModule,
|
|
5262
5709
|
MatButtonModule,
|
|
5263
|
-
MatTabsModule
|
|
5264
|
-
|
|
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"] }]
|
|
5265
5714
|
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
5266
5715
|
type: Inject,
|
|
5267
5716
|
args: [MAT_DIALOG_DATA]
|
|
@@ -5446,6 +5895,8 @@ class NgxMatEntityEditDialogComponent {
|
|
|
5446
5895
|
data;
|
|
5447
5896
|
isEntityValid = true;
|
|
5448
5897
|
isEntityDirty = false;
|
|
5898
|
+
validationErrors = [];
|
|
5899
|
+
tooltipContent = '';
|
|
5449
5900
|
isEntityReadOnly;
|
|
5450
5901
|
allowDelete;
|
|
5451
5902
|
constructor(inputData, dialogRef, injector, dialog, http) {
|
|
@@ -5458,13 +5909,14 @@ class NgxMatEntityEditDialogComponent {
|
|
|
5458
5909
|
ngOnInit() {
|
|
5459
5910
|
this.data = new EditEntityDataBuilder(this.inputData).getResult();
|
|
5460
5911
|
this.entityPriorChanges = LodashUtilities.cloneDeep(this.data.entity);
|
|
5461
|
-
this.injector
|
|
5912
|
+
runInInjectionContext(this.injector, () => {
|
|
5462
5913
|
this.isEntityReadOnly = !this.data.allowUpdate(this.entityPriorChanges);
|
|
5463
5914
|
this.allowDelete = this.data.allowDelete(this.entityPriorChanges);
|
|
5464
5915
|
});
|
|
5465
5916
|
this.dialogRef.disableClose = true;
|
|
5466
5917
|
this.entityTabs = EntityUtilities.getEntityTabs(this.data.entity, false, true);
|
|
5467
5918
|
this.entityService = this.injector.get(this.data.EntityServiceClass);
|
|
5919
|
+
setTimeout(() => this.checkIsEntityValid(), 1);
|
|
5468
5920
|
}
|
|
5469
5921
|
/**
|
|
5470
5922
|
* Checks if the input with the given key is readonly.
|
|
@@ -5473,7 +5925,7 @@ class NgxMatEntityEditDialogComponent {
|
|
|
5473
5925
|
* @returns Whether or not the input for the key is read only.
|
|
5474
5926
|
*/
|
|
5475
5927
|
isReadOnly(key) {
|
|
5476
|
-
return this.injector
|
|
5928
|
+
return runInInjectionContext(this.injector, () => {
|
|
5477
5929
|
const metadata = EntityUtilities.getPropertyMetadata(this.data.entity, key);
|
|
5478
5930
|
return this.isEntityReadOnly || metadata.isReadOnly(this.data.entity);
|
|
5479
5931
|
});
|
|
@@ -5482,9 +5934,14 @@ class NgxMatEntityEditDialogComponent {
|
|
|
5482
5934
|
* Checks if the entity has become invalid or dirty.
|
|
5483
5935
|
*/
|
|
5484
5936
|
async checkEntity() {
|
|
5485
|
-
this.
|
|
5937
|
+
this.checkIsEntityValid();
|
|
5486
5938
|
this.isEntityDirty = await EntityUtilities.isDirty(this.data.entity, this.entityPriorChanges, this.http);
|
|
5487
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
|
+
}
|
|
5488
5945
|
/**
|
|
5489
5946
|
* Tries to save the changes and close the dialog afterwards.
|
|
5490
5947
|
* Also handles the confirmation if required.
|
|
@@ -5558,7 +6015,7 @@ class NgxMatEntityEditDialogComponent {
|
|
|
5558
6015
|
* @param action - The action to run.
|
|
5559
6016
|
*/
|
|
5560
6017
|
runEditAction(action) {
|
|
5561
|
-
const requireConfirmDialog = this.injector
|
|
6018
|
+
const requireConfirmDialog = runInInjectionContext(this.injector, () => {
|
|
5562
6019
|
return action.requireConfirmDialog(this.entityPriorChanges);
|
|
5563
6020
|
});
|
|
5564
6021
|
if (!requireConfirmDialog) {
|
|
@@ -5577,7 +6034,7 @@ class NgxMatEntityEditDialogComponent {
|
|
|
5577
6034
|
});
|
|
5578
6035
|
}
|
|
5579
6036
|
confirmRunEditAction(action) {
|
|
5580
|
-
void this.injector
|
|
6037
|
+
void runInInjectionContext(this.injector, async () => {
|
|
5581
6038
|
await action.action(this.data.entity, this.entityPriorChanges);
|
|
5582
6039
|
await this.checkEntity();
|
|
5583
6040
|
});
|
|
@@ -5589,12 +6046,10 @@ class NgxMatEntityEditDialogComponent {
|
|
|
5589
6046
|
* @returns Whether or not the Action can be used.
|
|
5590
6047
|
*/
|
|
5591
6048
|
editActionDisabled(action) {
|
|
5592
|
-
return this.injector
|
|
5593
|
-
return !action.enabled(this.entityPriorChanges);
|
|
5594
|
-
});
|
|
6049
|
+
return runInInjectionContext(this.injector, () => !action.enabled(this.entityPriorChanges));
|
|
5595
6050
|
}
|
|
5596
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 });
|
|
5597
|
-
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"] }] });
|
|
5598
6053
|
}
|
|
5599
6054
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImport: i0, type: NgxMatEntityEditDialogComponent, decorators: [{
|
|
5600
6055
|
type: Component,
|
|
@@ -5607,8 +6062,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.0", ngImpor
|
|
|
5607
6062
|
MatButtonModule,
|
|
5608
6063
|
MatTabsModule,
|
|
5609
6064
|
NgxMatEntityConfirmDialogComponent,
|
|
5610
|
-
MatMenuModule
|
|
5611
|
-
|
|
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"] }]
|
|
5612
6069
|
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
5613
6070
|
type: Inject,
|
|
5614
6071
|
args: [MAT_DIALOG_DATA]
|
|
@@ -5793,7 +6250,7 @@ class NgxMatEntityTableComponent {
|
|
|
5793
6250
|
const dialogData = new EditEntityDataBuilder(inputDialogData).getResult();
|
|
5794
6251
|
const res = await firstValueFrom(this.dialog.open(NgxMatEntityEditDialogComponent, {
|
|
5795
6252
|
data: dialogData,
|
|
5796
|
-
minWidth: '60%',
|
|
6253
|
+
// minWidth: '60%',
|
|
5797
6254
|
autoFocus: false,
|
|
5798
6255
|
restoreFocus: false
|
|
5799
6256
|
}).afterClosed());
|
|
@@ -5815,11 +6272,13 @@ class NgxMatEntityTableComponent {
|
|
|
5815
6272
|
if (!this.data.baseData.EntityClass) {
|
|
5816
6273
|
throw new Error('No "EntityClass" specified for this table');
|
|
5817
6274
|
}
|
|
6275
|
+
const entity = new this.data.baseData.EntityClass();
|
|
6276
|
+
EntityUtilities.setDefaultValues(entity);
|
|
5818
6277
|
if (this.data.baseData.create) {
|
|
5819
|
-
this.data.baseData.create(
|
|
6278
|
+
this.data.baseData.create(entity);
|
|
5820
6279
|
}
|
|
5821
6280
|
else {
|
|
5822
|
-
this.createDefault(
|
|
6281
|
+
this.createDefault(entity);
|
|
5823
6282
|
}
|
|
5824
6283
|
}
|
|
5825
6284
|
});
|
|
@@ -5981,6 +6440,15 @@ class PropertyDecoratorConfig {
|
|
|
5981
6440
|
*/
|
|
5982
6441
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5983
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;
|
|
5984
6452
|
}
|
|
5985
6453
|
|
|
5986
6454
|
/**
|
|
@@ -6522,6 +6990,7 @@ class DateTimeDateDecoratorConfigInternal extends PropertyDecoratorConfigInterna
|
|
|
6522
6990
|
this.minTime = data.minTime;
|
|
6523
6991
|
this.maxTime = data.maxTime;
|
|
6524
6992
|
this.filterTime = data.filterTime;
|
|
6993
|
+
this.defaultWidths = [6, 12, 12];
|
|
6525
6994
|
}
|
|
6526
6995
|
}
|
|
6527
6996
|
|
|
@@ -7076,5 +7545,5 @@ class StringDecoratorConfig extends PropertyDecoratorConfig {
|
|
|
7076
7545
|
* Generated bundle index. Do not edit.
|
|
7077
7546
|
*/
|
|
7078
7547
|
|
|
7079
|
-
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 };
|
|
7080
7549
|
//# sourceMappingURL=ngx-material-entity.mjs.map
|