Skip to content

Commit 482feae

Browse files
sadaf895sleidig
andauthored
fix(Admin UI): make photo and percentage field types available for configuration (#2546)
by adding them as new Datatype implementations closes #2503, closes #2121 --------- Co-authored-by: Sebastian <[email protected]>
1 parent f884a06 commit 482feae

File tree

8 files changed

+145
-7
lines changed

8 files changed

+145
-7
lines changed

build/Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ COPY --from=base-with-dependencies /opt/app /opt/app
3535

3636
RUN apt-get update && apt-get install -y curl
3737
WORKDIR /tmp
38-
# 121.0.6167.139-1~deb12u1 -> 2024-02-01
39-
ARG CHROMIUM_VERSION=121.0.6167.139-1~deb12u1
38+
# 120.0.6099.224-1~deb11u1 -> 2024-02-01
39+
# 128.0.6613.113-1~deb12u1-> 2024-08-30
40+
ARG CHROMIUM_VERSION=128.0.6613.113-1~deb12u1
4041
RUN curl -o chromium-common.deb https://ftp.debian.org/debian/pool/main/c/chromium/chromium-common_${CHROMIUM_VERSION}_$(dpkg --print-architecture).deb
4142
RUN curl -o chromium.deb https://ftp.debian.org/debian/pool/main/c/chromium/chromium_${CHROMIUM_VERSION}_$(dpkg --print-architecture).deb
4243
RUN apt-get install -y ./chromium-common.deb ./chromium.deb build-essential git libssl-dev
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Injectable } from "@angular/core";
2+
import { NumberDatatype } from "../number.datatype";
3+
4+
/** Datatype for percentage values */
5+
@Injectable()
6+
export class PercentageDatatype extends NumberDatatype {
7+
static override dataType = "percentage";
8+
static override label: string = $localize`:datatype-label:Percentage`;
9+
10+
override viewComponent = "DisplayPercentage";
11+
override editComponent = "EditNumber";
12+
}

src/app/core/config/config-fix.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,9 +1018,8 @@ export const defaultJsonConfig = {
10181018
label: $localize`:Label for the remarks about a dropout of a child:Dropout remarks`,
10191019
},
10201020
photo: {
1021-
dataType: "file",
1021+
dataType: "photo",
10221022
label: $localize`:Label for the file field of a photo of a child:Photo`,
1023-
editComponent: "EditPhoto",
10241023
},
10251024
phone: {
10261025
dataType: "string",
@@ -1301,10 +1300,8 @@ export const defaultJsonConfig = {
13011300
anonymize: "retain",
13021301
},
13031302
result: {
1304-
dataType: "number",
1303+
dataType: "percentage",
13051304
label: $localize`:Label for the percentage result of a relation:Result`,
1306-
viewComponent: "DisplayPercentage",
1307-
editComponent: "EditNumber",
13081305
validators: {
13091306
min: 0,
13101307
max: 100,

src/app/core/config/config.service.spec.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,4 +550,89 @@ describe("ConfigService", () => {
550550
const actualFromNew = service.getConfig("view:X");
551551
expect(actualFromNew).toEqual(newFormat);
552552
}));
553+
554+
it("should migrate to new photo dataType", fakeAsync(() => {
555+
const config = new Config();
556+
const oldFormat = {
557+
attributes: {
558+
myPhoto: {
559+
dataType: "file",
560+
editComponent: "EditPhoto",
561+
label: "My Photo",
562+
},
563+
simpleFile: {
564+
dataType: "file",
565+
label: "Simple File attachment",
566+
},
567+
},
568+
};
569+
570+
const newFormat: EntityConfig = {
571+
attributes: {
572+
myPhoto: {
573+
dataType: "photo",
574+
label: "My Photo",
575+
},
576+
simpleFile: {
577+
dataType: "file",
578+
label: "Simple File attachment",
579+
},
580+
},
581+
};
582+
583+
config.data = { "entity:X": oldFormat };
584+
updateSubject.next({ entity: config, type: "update" });
585+
tick();
586+
const actualFromOld = service.getConfig<EntityConfig>("entity:X");
587+
expect(actualFromOld).toEqual(newFormat);
588+
589+
config.data = { "entity:X": newFormat };
590+
updateSubject.next({ entity: config, type: "update" });
591+
tick();
592+
const actualFromNew = service.getConfig<EntityConfig>("entity:X");
593+
expect(actualFromNew).toEqual(newFormat);
594+
}));
595+
596+
it("should migrate to Percentage dataType", fakeAsync(() => {
597+
const config = new Config();
598+
const oldFormat = {
599+
attributes: {
600+
myPercentage: {
601+
dataType: "number",
602+
viewComponent: "DisplayPercentage",
603+
editComponent: "EditNumber",
604+
label: "My Percentage",
605+
},
606+
simpleNumber: {
607+
dataType: "number",
608+
label: "Simple Number",
609+
},
610+
},
611+
};
612+
613+
const newFormat: EntityConfig = {
614+
attributes: {
615+
myPercentage: {
616+
dataType: "percentage",
617+
label: "My Percentage",
618+
},
619+
simpleNumber: {
620+
dataType: "number",
621+
label: "Simple Number",
622+
},
623+
},
624+
};
625+
626+
config.data = { "entity:X": oldFormat };
627+
updateSubject.next({ entity: config, type: "update" });
628+
tick();
629+
const actualFromOld = service.getConfig<EntityConfig>("entity:X");
630+
expect(actualFromOld).toEqual(newFormat);
631+
632+
config.data = { "entity:X": newFormat };
633+
updateSubject.next({ entity: config, type: "update" });
634+
tick();
635+
const actualFromNew = service.getConfig<EntityConfig>("entity:X");
636+
expect(actualFromNew).toEqual(newFormat);
637+
}));
553638
});

src/app/core/config/config.service.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ export class ConfigService extends LatestEntityLoader<Config> {
6969
migrateEntitySchemaDefaultValue,
7070
migrateChildrenListConfig,
7171
migrateHistoricalDataComponent,
72+
migratePhotoDatatype,
73+
migratePercentageDatatype,
7274
];
7375

7476
// TODO: execute this on server via ndb-admin
@@ -259,6 +261,32 @@ const migrateEntityArrayDatatype: ConfigMigration = (key, configPart) => {
259261
return configPart;
260262
};
261263

264+
/** Migrate the "file" datatype to use the new "photo" datatype and remove editComponent if no longer needed */
265+
const migratePhotoDatatype: ConfigMigration = (key, configPart) => {
266+
if (
267+
configPart?.dataType === "file" &&
268+
configPart?.editComponent === "EditPhoto"
269+
) {
270+
configPart.dataType = "photo";
271+
delete configPart.editComponent;
272+
}
273+
return configPart;
274+
};
275+
276+
/** Migrate the number datatype to use the new "percentage" datatype */
277+
const migratePercentageDatatype: ConfigMigration = (key, configPart) => {
278+
if (
279+
configPart?.dataType === "number" &&
280+
configPart?.viewComponent === "DisplayPercentage"
281+
) {
282+
configPart.dataType = "percentage";
283+
delete configPart.viewComponent;
284+
delete configPart.editComponent;
285+
}
286+
287+
return configPart;
288+
};
289+
262290
const migrateEntitySchemaDefaultValue: ConfigMigration = (
263291
key: string,
264292
configPart: any,

src/app/core/core.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { LongTextDatatype } from "./basic-datatypes/string/long-text.datatype";
1818
import { UpdateMetadataDatatype } from "./entity/model/update-metadata.datatype";
1919
import { CurrentUserSubject } from "./session/current-user-subject";
2020
import { SessionSubject } from "./session/auth/session-info";
21+
import { PercentageDatatype } from "./basic-datatypes/number/display-percentage/percentage.datatype";
2122

2223
/**
2324
* Core module registering basic parts like datatypes and components.
@@ -37,6 +38,7 @@ import { SessionSubject } from "./session/auth/session-info";
3738
{ provide: DefaultDatatype, useClass: MonthDatatype, multi: true },
3839
{ provide: DefaultDatatype, useClass: DateDatatype, multi: true },
3940
{ provide: DefaultDatatype, useClass: EntityDatatype, multi: true },
41+
{ provide: DefaultDatatype, useClass: PercentageDatatype, multi: true },
4042
],
4143
imports: [CommonModule],
4244
})

src/app/features/file/file.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { ComponentRegistry } from "../../dynamic-components";
99
import { fileComponents } from "./file-components";
1010
import { DefaultDatatype } from "../../core/entity/default-datatype/default.datatype";
1111
import { FileDatatype } from "./file.datatype";
12+
import { PhotoDatatype } from "./photo.datatype";
1213

1314
@NgModule({
1415
providers: [
@@ -20,6 +21,7 @@ import { FileDatatype } from "./file.datatype";
2021
: injector.get(MockFileService);
2122
}),
2223
{ provide: DefaultDatatype, useClass: FileDatatype, multi: true },
24+
{ provide: DefaultDatatype, useClass: PhotoDatatype, multi: true },
2325
],
2426
})
2527
export class FileModule {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { Injectable } from "@angular/core";
2+
import { FileDatatype } from "./file.datatype";
3+
4+
/** Datatype for saving a photo on an entity property.*/
5+
@Injectable()
6+
export class PhotoDatatype extends FileDatatype {
7+
static override dataType = "photo";
8+
static override label: string = $localize`:datatype-label:profile photo`;
9+
10+
override editComponent = "EditPhoto";
11+
}

0 commit comments

Comments
 (0)