Skip to content

Commit 3b64625

Browse files
authored
Release 3.38.0
2 parents bfd5ba2 + 7d5a65a commit 3b64625

27 files changed

+689
-166
lines changed

package-lock.json

Lines changed: 14 additions & 56 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/app.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,6 @@ export class AppComponent {
4747
*/
4848
private detectConfigMode() {
4949
const currentUrl = this.router.url;
50-
this.configFullscreen = currentUrl.startsWith("/admin/entity");
50+
this.configFullscreen = currentUrl.startsWith("/admin/entity/");
5151
}
5252
}

src/app/child-dev-project/notes/model/note.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,8 @@ export class Note extends Entity {
231231
* @param child The child or the id of the child to add to the notes
232232
*/
233233
addChild(child: Child | string) {
234-
const childId = typeof child === "string" ? child : child.getId();
235-
if (this.children.includes(childId)) {
234+
const childId = typeof child === "string" ? child : child?.getId();
235+
if (!childId || this.children.includes(childId)) {
236236
return;
237237
}
238238

src/app/child-dev-project/notes/notes-related-to-entity/notes-related-to-entity.component.spec.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,14 @@ import { ChildSchoolRelation } from "../../children/model/childSchoolRelation";
1313
describe("NotesRelatedToEntityComponent", () => {
1414
let component: NotesRelatedToEntityComponent;
1515
let fixture: ComponentFixture<NotesRelatedToEntityComponent>;
16+
const originalNoteSchema_relatedEntities =
17+
Note.schema.get("relatedEntities").additional;
1618

1719
beforeEach(waitForAsync(() => {
20+
Note.schema.get("relatedEntities").additional = [
21+
ChildSchoolRelation.ENTITY_TYPE,
22+
];
23+
1824
TestBed.configureTestingModule({
1925
imports: [NotesRelatedToEntityComponent, MockedTestingModule.withState()],
2026
}).compileComponents();
@@ -23,10 +29,13 @@ describe("NotesRelatedToEntityComponent", () => {
2329
beforeEach(waitForAsync(() => {
2430
fixture = TestBed.createComponent(NotesRelatedToEntityComponent);
2531
component = fixture.componentInstance;
26-
component.entity = new Child("1");
27-
fixture.detectChanges();
2832
}));
2933

34+
afterEach(() => {
35+
Note.schema.get("relatedEntities").additional =
36+
originalNoteSchema_relatedEntities;
37+
});
38+
3039
it("should create", () => {
3140
expect(component).toBeTruthy();
3241
});
@@ -81,6 +90,21 @@ describe("NotesRelatedToEntityComponent", () => {
8190
expect(note.schools).toEqual([`${Child.ENTITY_TYPE}:someSchool`]);
8291
});
8392

93+
it("should handle ChildSchoolRelation links also if they are arrays", async () => {
94+
const relation = new ChildSchoolRelation();
95+
relation.schoolId = ["School:1"] as any; // assume entity config was overwritten to hold array
96+
relation.childId = ["Child:1", "Child:2"] as any; // assume entity config was overwritten to hold array
97+
98+
component.entity = relation;
99+
await component.ngOnInit();
100+
101+
const newNote = component.createNewRecordFactory()();
102+
103+
expect(newNote.relatedEntities).toContain(relation.getId());
104+
expect(newNote.children).toEqual(relation.childId);
105+
expect(newNote.schools).toEqual(relation.schoolId);
106+
});
107+
84108
it("should create a new note and fill it with indirectly related references (2-hop) of the types allowed for note.relatedEntities", () => {
85109
@DatabaseEntity("EntityWithRelations")
86110
class EntityWithRelations extends Entity {

src/app/child-dev-project/notes/notes-related-to-entity/notes-related-to-entity.component.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,31 @@ export class NotesRelatedToEntityComponent
7575
const newNote = super.createNewRecordFactory()();
7676
//TODO: generalize this code - possibly by only using relatedEntities to link other records here? see #1501
7777
if (this.entity.getType() === ChildSchoolRelation.ENTITY_TYPE) {
78-
newNote.addChild((this.entity as ChildSchoolRelation).childId);
79-
newNote.addSchool((this.entity as ChildSchoolRelation).schoolId);
78+
for (const childId of asArray(
79+
(this.entity as ChildSchoolRelation).childId,
80+
)) {
81+
if (childId) {
82+
newNote.addChild(childId);
83+
}
84+
}
85+
86+
for (const schooldId of asArray(
87+
(this.entity as ChildSchoolRelation).schoolId,
88+
)) {
89+
if (schooldId) {
90+
newNote.addSchool(schooldId);
91+
}
92+
}
8093
}
8194

82-
newNote.relatedEntities.push(this.entity.getId());
83-
this.getIndirectlyRelatedEntityIds(this.entity).forEach((e) =>
84-
newNote.relatedEntities.push(e),
85-
);
95+
for (const e of [
96+
this.entity.getId(),
97+
...this.getIndirectlyRelatedEntityIds(this.entity),
98+
]) {
99+
if (!newNote.relatedEntities.includes(e)) {
100+
newNote.relatedEntities.push(e);
101+
}
102+
}
86103

87104
return newNote;
88105
};

src/app/core/admin/admin-entity-details/admin-entity-field/admin-entity-field.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import { merge } from "rxjs";
4444
import { filter } from "rxjs/operators";
4545
import { uniqueIdValidator } from "app/core/common-components/entity-form/unique-id-validator/unique-id-validator";
4646
import { ConfigureEntityFieldValidatorComponent } from "./configure-entity-field-validator/configure-entity-field-validator.component";
47-
import { DynamicValidator } from "app/core/common-components/entity-form/dynamic-form-validators/form-validator-config";
47+
import { FormValidatorConfig } from "app/core/common-components/entity-form/dynamic-form-validators/form-validator-config";
4848
import { AnonymizeOptionsComponent } from "app/core/common-components/anonymize-options/anonymize-options.component";
4949
import { MatCheckbox } from "@angular/material/checkbox";
5050

@@ -184,7 +184,7 @@ export class AdminEntityFieldComponent implements OnChanges {
184184
}
185185
}
186186

187-
entityFieldValidatorChanges(validatorData: DynamicValidator) {
187+
entityFieldValidatorChanges(validatorData: FormValidatorConfig) {
188188
this.schemaFieldsForm.get("validators").setValue(validatorData);
189189
}
190190
private autoGenerateId() {

src/app/core/admin/admin-entity-details/admin-entity-field/configure-entity-field-validator/configure-entity-field-validator.component.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,28 @@ describe("ConfigureEntityFieldValidatorComponent", () => {
4949
it("should create", () => {
5050
expect(component).toBeTruthy();
5151
});
52+
53+
it("should remove unchanged default values before emitting output", () => {
54+
// set up
55+
const testFormValues = {
56+
required: true,
57+
min: null,
58+
max: 100,
59+
regex: "abc",
60+
validEmail: false,
61+
uniqueId: "",
62+
};
63+
64+
// execute
65+
const actualResult =
66+
component.removeDefaultValuesFromValidatorConfig(testFormValues);
67+
68+
// check result
69+
const expectedResult = {
70+
required: true,
71+
max: 100,
72+
regex: "abc",
73+
};
74+
expect(actualResult).toEqual(expectedResult);
75+
});
5276
});

src/app/core/admin/admin-entity-details/admin-entity-field/configure-entity-field-validator/configure-entity-field-validator.component.ts

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
} from "@angular/forms";
99
import { MatCheckboxModule } from "@angular/material/checkbox";
1010
import { EntitySchemaField } from "app/core/entity/schema/entity-schema-field";
11-
import { DynamicValidator } from "app/core/common-components/entity-form/dynamic-form-validators/form-validator-config";
11+
import { FormValidatorConfig } from "app/core/common-components/entity-form/dynamic-form-validators/form-validator-config";
1212
import { CommonModule } from "@angular/common";
1313
import { HelpButtonComponent } from "../../../../common-components/help-button/help-button.component";
1414

@@ -28,8 +28,17 @@ import { HelpButtonComponent } from "../../../../common-components/help-button/h
2828
})
2929
export class ConfigureEntityFieldValidatorComponent implements OnInit {
3030
validatorForm: FormGroup;
31+
32+
/**
33+
* the field definition with the currently existing validator settings to be edited
34+
*/
3135
@Input() entitySchemaField: EntitySchemaField;
32-
@Output() entityValidatorChanges = new EventEmitter<DynamicValidator>();
36+
37+
/**
38+
* Emit the latest state of the validators config whenever the user changed it in the displayed form.
39+
*/
40+
@Output() entityValidatorChanges = new EventEmitter<FormValidatorConfig>();
41+
3342
constructor(private fb: FormBuilder) {}
3443

3544
ngOnInit() {
@@ -58,7 +67,31 @@ export class ConfigureEntityFieldValidatorComponent implements OnInit {
5867
}
5968

6069
this.validatorForm.valueChanges.subscribe((value) => {
61-
this.entityValidatorChanges.emit(this.validatorForm.getRawValue());
70+
const rawValues = this.validatorForm.getRawValue();
71+
const cleanedValues =
72+
this.removeDefaultValuesFromValidatorConfig(rawValues);
73+
74+
this.entityValidatorChanges.emit(cleanedValues);
6275
});
6376
}
77+
78+
/**
79+
* Removes default fields and returns a validator config that only contains explicitly activated validators.
80+
* @param validators form values including default values that are unchanged
81+
*/
82+
removeDefaultValuesFromValidatorConfig(
83+
validators: FormValidatorConfig,
84+
): FormValidatorConfig {
85+
for (let key of Object.keys(validators)) {
86+
if (isDefaultValue(validators[key])) {
87+
delete validators[key];
88+
}
89+
}
90+
91+
function isDefaultValue(value): boolean {
92+
return value === false || value === "" || value === null;
93+
}
94+
95+
return validators;
96+
}
6497
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<p style="color: red">
2+
This is an internal server admin preview and not stable functionality yet.
3+
</p>
4+
5+
<div class="flex-row gap-regular">
6+
<button mat-raised-button color="accent" (click)="create()">
7+
Add New Entity Type
8+
</button>
9+
10+
<button mat-stroked-button color="accent" (click)="loadEntityTypes(false)">
11+
Also load internal types
12+
</button>
13+
</div>
14+
15+
<table mat-table [dataSource]="entityTypes">
16+
<ng-container matColumnDef="label">
17+
<th mat-header-cell *matHeaderCellDef class="table-header">Entity Type</th>
18+
19+
<td mat-cell *matCellDef="let row">
20+
{{ row.label }}
21+
</td>
22+
</ng-container>
23+
24+
<ng-container matColumnDef="icon">
25+
<th mat-header-cell *matHeaderCellDef class="table-header">Icon</th>
26+
27+
<td mat-cell *matCellDef="let row">
28+
<fa-icon *ngIf="row.icon" [icon]="row.icon"></fa-icon>
29+
</td>
30+
</ng-container>
31+
32+
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
33+
<tr
34+
mat-row
35+
*matRowDef="let row; columns: columnsToDisplay"
36+
[routerLink]="['/admin', 'entity', row.ENTITY_TYPE]"
37+
style="cursor: pointer"
38+
></tr>
39+
</table>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.table-header {
2+
font-weight: bold;
3+
font-style: italic;
4+
}

0 commit comments

Comments
 (0)