Skip to content

Commit

Permalink
Release 3.30.0
Browse files Browse the repository at this point in the history
  • Loading branch information
sleidig authored Jan 25, 2024
2 parents 5ed1de9 + aab9dc1 commit a8a4fd8
Show file tree
Hide file tree
Showing 58 changed files with 942 additions and 546 deletions.
10 changes: 5 additions & 5 deletions build/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ ENV NOMINATIM_URL="https://nominatim.openstreetmap.org"
# (also see Developer Documentation: https://aam-digital.github.io/ndb-core/documentation/additional-documentation/concepts/security.html)
ENV CSP_REPORT_URI="https://o167951.ingest.sentry.io/api/1242399/security/"
# overwrite the Content-Security-Policy rules (report-uri is added automatically)
## default includes all required whitelists for production server
## to disable any CSP blocking, set to "default-src * data: blob: filesystem: about: ws: wss: 'unsafe-inline' 'unsafe-eval'"
ENV CSP="default-src 'self' 'unsafe-eval' data: https://*.tile.openstreetmap.org/ https://matomo.aam-digital.org https://*.aam-digital.com https://api.github.com/repos/Aam-Digital/ https://sentry.io $CSP_REPORT_URI 'sha256-gtzIf+c+ujwirISvjI8lnwlaZwnMkh04eA9ZDBCd8TY='; style-src 'self' 'unsafe-inline'"
### 'sha256-gtzIf+c+ujwirISvjI8lnwlaZwnMkh04eA9ZDBCd8TY=' for index.html writing browser details
### 'unsafe-eval' required for pouchdb https://github.com/pouchdb/pouchdb/issues/7853#issuecomment-535020600
# default includes all required whitelists for production server
# to disable any CSP blocking, set to "default-src * data: blob: filesystem: about: ws: wss: 'unsafe-inline' 'unsafe-eval'"
ENV CSP="default-src 'self' 'unsafe-eval' 'unsafe-inline' data: blob: https://*.tile.openstreetmap.org/ https://matomo.aam-digital.org https://*.aam-digital.com https://api.github.com/repos/Aam-Digital/ https://sentry.io $CSP_REPORT_URI; style-src 'self' 'unsafe-inline'"
# 'unsafe-eval' required for pouchdb https://github.com/pouchdb/pouchdb/issues/7853#issuecomment-535020600
# TODO remove 'unsave-inline' and fix the reported issues

# variables are inserted into the nginx config
CMD envsubst '$$PORT $$COUCHDB_URL $$QUERY_URL $$NOMINATIM_URL $$CSP $$CSP_REPORT_URI' < /etc/nginx/templates/default.conf > /etc/nginx/conf.d/default.conf &&\
Expand Down
3 changes: 2 additions & 1 deletion build/default.conf
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ server {

root /usr/share/nginx/html;

add_header Content-Security-Policy-Report-Only "${CSP}; report-uri ${CSP_REPORT_URI}";
add_header Content-Security-Policy-Report-Only "${CSP}; report-uri ${CSP_REPORT_URI}?ngsw-bypass=true";
# ?ngsw-bypass prevents angular serviceworker to intercept and break CSP reporting (https://github.com/angular/angular/issues/31477)

# TODO: consider adding `trusted-types angular angular#unsafe-bypass; require-trusted-types-for 'script';` CSP in future
add_header X-Frame-Options: SAMEORIGIN; # only applies in older browsers, CSP frame-ancestors takes prevalence https://stackoverflow.com/a/40417609/1473411
Expand Down
4 changes: 2 additions & 2 deletions src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ describe("AppComponent", () => {
fixture.detectChanges();
}));

afterEach(() => {
afterEach(waitForAsync(() => {
environment.demo_mode = false;
jasmine.DEFAULT_TIMEOUT_INTERVAL = intervalBefore;
return TestBed.inject(Database).destroy();
});
}));

it("should be created", () => {
expect(component).toBeTruthy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class ActivitiesOverviewComponent
extends RelatedEntitiesComponent<RecurringActivity>
implements OnInit
{
entityType = RecurringActivity.ENTITY_TYPE;
entityCtr = RecurringActivity;
property = "linkedGroups";

titleColumn: FormFieldConfig = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
[records]="records"
[customColumns]="columns"
clickMode="none"
(rowClick)="showDetails($event)"
(entityClick)="showDetails($event)"
[getBackgroundColor]="getBackgroundColor"
[editable]="false"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ <h1 mat-dialog-title>
[records]="entity.events"
[customColumns]="eventsColumns"
clickMode="none"
(rowClick)="showEventDetails($event)"
(entityClick)="showEventDetails($event)"
[editable]="false"
>
</app-entities-table>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,53 @@ import { Child } from "../../model/child";
import { FormFieldConfig } from "../../../../core/common-components/entity-form/FormConfig";
import { DynamicComponent } from "../../../../core/config/dynamic-components/dynamic-component.decorator";
import { EntitiesTableComponent } from "../../../../core/common-components/entities-table/entities-table.component";
import { RelatedEntitiesComponent } from "../../../../core/entity-details/related-entities/related-entities.component";
import { EntityMapperService } from "../../../../core/entity/entity-mapper/entity-mapper.service";
import { EntityRegistry } from "../../../../core/entity/database-entity.decorator";
import { ScreenWidthObserver } from "../../../../utils/media/screen-size-observer.service";

@DynamicComponent("HealthCheckup")
@Component({
selector: "app-health-checkup",
templateUrl: "./health-checkup.component.html",
templateUrl:
"../../../../core/entity-details/related-entities/related-entities.component.html",
imports: [EntitiesTableComponent],
standalone: true,
})
export class HealthCheckupComponent implements OnInit {
records: HealthCheck[] = [];
export class HealthCheckupComponent
extends RelatedEntitiesComponent<HealthCheck>
implements OnInit
{
@Input() entity: Child;
property = "child";
entityCtr = HealthCheck;

/**
* Column Description for the SubentityRecordComponent
* Column Description
* The Date-Column needs to be transformed to apply the MathFormCheck in the SubentityRecordComponent
* BMI is rounded to 2 decimal digits
*/
@Input() config: { columns: FormFieldConfig[] } = {
columns: [
{ id: "date" },
{ id: "height" },
{ id: "weight" },
{
id: "bmi",
label: $localize`:Table header, Short for Body Mass Index:BMI`,
viewComponent: "ReadonlyFunction",
description: $localize`:Tooltip for BMI info:This is calculated using the height and the weight measure`,
additional: (entity: HealthCheck) => this.getBMI(entity),
},
],
};
@Input() entity: Child;
override _columns: FormFieldConfig[] = [
{ id: "date" },
{ id: "height" },
{ id: "weight" },
{
id: "bmi",
label: $localize`:Table header, Short for Body Mass Index:BMI`,
viewComponent: "ReadonlyFunction",
description: $localize`:Tooltip for BMI info:This is calculated using the height and the weight measure`,
additional: (entity: HealthCheck) => this.getBMI(entity),
},
];

constructor(private childrenService: ChildrenService) {}
constructor(
private childrenService: ChildrenService,
entityMapper: EntityMapperService,
entityRegistry: EntityRegistry,
screenWidthObserver: ScreenWidthObserver,
) {
super(entityMapper, entityRegistry, screenWidthObserver);
}

private getBMI(healthCheck: HealthCheck): string {
const bmi = healthCheck.bmi;
Expand All @@ -49,16 +62,11 @@ export class HealthCheckupComponent implements OnInit {
}
}

ngOnInit() {
return this.loadData();
}

generateNewRecordFactory() {
override createNewRecordFactory() {
return () => {
const newHC = new HealthCheck(Date.now().toString());
const newHC = new HealthCheck();

// use last entered date as default, otherwise today's date
newHC.date = this.records.length > 0 ? this.records[0].date : new Date();
newHC.date = new Date();
newHC.child = this.entity.getId();

return newHC;
Expand All @@ -68,11 +76,10 @@ export class HealthCheckupComponent implements OnInit {
/**
* implements the health check loading from the children service and is called in the onInit()
*/
async loadData() {
this.records = await this.childrenService.getHealthChecksOfChild(
this.entity.getId(),
);
this.records.sort(
override async initData() {
this.data = (
await this.childrenService.getHealthChecksOfChild(this.entity.getId())
).sort(
(a, b) =>
(b.date ? b.date.valueOf() : 0) - (a.date ? a.date.valueOf() : 0),
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<app-entities-table
[entityType]="entityConstructor"
[records]="records"
[customColumns]="columns"
[entityType]="entityCtr"
[records]="data"
[customColumns]="_columns"
[filter]="filter"
[newRecordFactory]="newRecordFactory"
clickMode="none"
(rowClick)="showNoteDetails($event)"
(entityClick)="showNoteDetails($event)"
[getBackgroundColor]="getColor"
>
</app-entities-table>
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,6 @@ describe("NotesRelatedToEntityComponent", () => {
expect(mockChildrenService.getNotesRelatedTo).toHaveBeenCalledWith(
component.entity.getId(true),
);
expect(component.records).toEqual([n1, n2, n3]);
expect(component.data).toEqual([n1, n2, n3]);
}));
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Input, OnInit } from "@angular/core";
import { Component } from "@angular/core";
import { Note } from "../model/note";
import { NoteDetailsComponent } from "../note-details/note-details.component";
import { ChildrenService } from "../../children/children.service";
Expand All @@ -13,66 +13,62 @@ import { ChildSchoolRelation } from "../../children/model/childSchoolRelation";
import { EntityDatatype } from "../../../core/basic-datatypes/entity/entity.datatype";
import { EntityArrayDatatype } from "../../../core/basic-datatypes/entity-array/entity-array.datatype";
import { asArray } from "../../../utils/utils";
import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
import { applyUpdate } from "../../../core/entity/model/entity-update";
import { EntitiesTableComponent } from "../../../core/common-components/entities-table/entities-table.component";
import { EntityMapperService } from "../../../core/entity/entity-mapper/entity-mapper.service";
import { ColumnConfig } from "../../../core/common-components/entity-form/FormConfig";
import { DataFilter } from "../../../core/filter/filters/filters";
import { FormFieldConfig } from "../../../core/common-components/entity-form/FormConfig";
import { RelatedEntitiesComponent } from "../../../core/entity-details/related-entities/related-entities.component";
import { EntityRegistry } from "../../../core/entity/database-entity.decorator";
import { ScreenWidthObserver } from "../../../utils/media/screen-size-observer.service";

/**
* The component that is responsible for listing the Notes that are related to a certain entity.
*/
@DynamicComponent("NotesRelatedToEntity")
@DynamicComponent("NotesOfChild") // for backward compatibility
@UntilDestroy()
@Component({
selector: "app-notes-related-to-entity",
templateUrl: "./notes-related-to-entity.component.html",
imports: [EntitiesTableComponent],
standalone: true,
})
export class NotesRelatedToEntityComponent implements OnInit {
@Input() entity: Entity;
records: Array<Note>;

@Input() columns: ColumnConfig[] = [
export class NotesRelatedToEntityComponent extends RelatedEntitiesComponent<Note> {
override entityCtr = Note;
override _columns: FormFieldConfig[] = [
{ id: "date", visibleFrom: "xs" },
{ id: "subject", visibleFrom: "xs" },
{ id: "text", visibleFrom: "md" },
{ id: "authors", visibleFrom: "md" },
{ id: "warningLevel", visibleFrom: "md" },
];
@Input() filter: DataFilter<Note> = {};

/**
* returns the color for a note; passed to the entity subrecord component
* @param note note to get color for
*/
getColor = (note: Note) => note?.getColor();
newRecordFactory: () => Note;

entityConstructor = Note;
newRecordFactory = this.generateNewRecordFactory();

constructor(
private childrenService: ChildrenService,
private entityMapper: EntityMapperService,
private formDialog: FormDialogService,
private filterService: FilterService,
) {}
entityMapper: EntityMapperService,
entities: EntityRegistry,
screenWidthOberserver: ScreenWidthObserver,
) {
super(entityMapper, entities, screenWidthOberserver);
}

ngOnInit(): void {
override ngOnInit() {
if (this.entity.getType() === Child.ENTITY_TYPE) {
// When displaying notes for a child, use attendance color highlighting
this.getColor = (note: Note) => note?.getColorForId(this.entity.getId());
}
this.newRecordFactory = this.generateNewRecordFactory();
this.initNotesOfEntity();
this.listenToEntityUpdates();
return super.ngOnInit();
}

private async initNotesOfEntity() {
this.records = await this.childrenService
override async initData() {
this.data = await this.childrenService
.getNotesRelatedTo(this.entity.getId(true))
.then((notes: Note[]) => {
notes.sort((a, b) => {
Expand All @@ -86,15 +82,6 @@ export class NotesRelatedToEntityComponent implements OnInit {
});
}

private listenToEntityUpdates() {
this.entityMapper
.receiveUpdates(this.entityConstructor)
.pipe(untilDestroyed(this))
.subscribe((next) => {
this.records = applyUpdate(this.records, next);
});
}

generateNewRecordFactory() {
return () => {
const newNote = new Note(Date.now().toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ import { EntityDatatype } from "../../../basic-datatypes/entity/entity.datatype"
import { EntityArrayDatatype } from "../../../basic-datatypes/entity-array/entity-array.datatype";
import { ConfigurableEnumService } from "../../../basic-datatypes/configurable-enum/configurable-enum.service";
import { EntityRegistry } from "../../../entity/database-entity.decorator";
import { uniqueIdValidator } from "../../../common-components/entity-form/unique-id-validator";
import { AdminEntityService } from "../../admin-entity.service";
import { ConfigureEnumPopupComponent } from "../../../basic-datatypes/configurable-enum/configure-enum-popup/configure-enum-popup.component";
import { ConfigurableEnum } from "../../../basic-datatypes/configurable-enum/configurable-enum";
import { generateIdFromLabel } from "../../../../utils/generate-id-from-label/generate-id-from-label";
import { merge } from "rxjs";
import { filter } from "rxjs/operators";
import { uniqueIdValidator } from "app/core/common-components/entity-form/unique-id-validator/unique-id-validator";

/**
* Allows configuration of the schema of a single Entity field, like its dataType and labels.
Expand Down Expand Up @@ -115,10 +115,12 @@ export class AdminEntityFieldComponent implements OnChanges {
}

private initSettings() {
this.fieldIdForm = this.fb.control(this.fieldId, [
Validators.required,
uniqueIdValidator(Array.from(this.entityType.schema.keys())),
]);
this.fieldIdForm = this.fb.control(this.fieldId, {
validators: [Validators.required],
asyncValidators: [
uniqueIdValidator(Array.from(this.entityType.schema.keys())),
],
});
this.additionalForm = this.fb.control(this.entitySchemaField.additional);

this.schemaFieldsForm = this.fb.group({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<mat-form-field>
<mat-label>{{ label }}</mat-label>
<input [formControl]="formControl" matInput [title]="label" type="text" />
<mat-error *ngIf="formControl.errors">
<mat-error>
<app-error-hint [form]="formControl"></app-error-hint>
</mat-error>
</mat-form-field>
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
<app-entity-create-button
[entityType]="_entityType"
[newRecordFactory]="newRecordFactory"
(entityCreate)="showEntity($event)"
(entityCreate)="showEntity($event); entityClick.emit($event)"
[iconOnly]="true"
></app-entity-create-button>
</th>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ describe("EntitiesTableComponent", () => {

it("should notify when an entity is clicked", (done) => {
const child = new Child();
component.rowClick.subscribe((entity) => {
component.entityClick.subscribe((entity) => {
expect(entity).toEqual(child);
done();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,10 @@ export class EntitiesTableComponent<T extends Entity> implements AfterViewInit {
idForSavingPagination: string;

@Input() clickMode: "popup" | "navigate" | "none" = "popup";
@Output() rowClick: EventEmitter<T> = new EventEmitter<T>();
/**
* Emits the entity being clicked in the table - or the newly created entity from the "create" button.
*/
@Output() entityClick = new EventEmitter<T>();

/**
* BULK SELECT
Expand Down Expand Up @@ -262,7 +265,7 @@ export class EntitiesTableComponent<T extends Entity> implements AfterViewInit {
}

this.showEntity(row.record);
this.rowClick.emit(row.record);
this.entityClick.emit(row.record);
}

showEntity(entity: T) {
Expand Down
Loading

0 comments on commit a8a4fd8

Please sign in to comment.