src/app/features/attendance/model/attendance.datatype.ts
Datatype for attendance tracking on any entity.
Use this as dataType: "attendance" with isArray: true on an entity field
to store an array of AttendanceItem objects, each referencing a participant entity.
The allowed entity types for the participant field can be overridden via
the field's additional config, e.g.:
{
"dataType": "attendance",
"isArray": true,
"additional": {
"participant": { "dataType": "entity", "additional": ["Child", "School"] }
}
}
Properties |
|
Methods |
| Static detectAllFieldsInEntity | ||||||
detectAllFieldsInEntity(entityOrType: Entity | EntityConstructor)
|
||||||
|
Inherited from
DefaultDatatype
|
||||||
|
Defined in
DefaultDatatype:165
|
||||||
|
Detect all
Parameters :
Returns :
literal type[]
|
| Static detectFieldInEntity | ||||||
detectFieldInEntity(entityOrType: Entity | EntityConstructor)
|
||||||
|
Inherited from
DefaultDatatype
|
||||||
|
Defined in
DefaultDatatype:155
|
||||||
|
Parameters :
Returns :
string | undefined
|
| getExportColumns | ||||||
getExportColumns(schemaField: EntitySchemaField)
|
||||||
|
Inherited from
DefaultDatatype
|
||||||
|
Defined in
DefaultDatatype:50
|
||||||
|
Parameters :
Returns :
ExportColumnMapping[]
|
| normalizeSchemaField | ||||||
normalizeSchemaField(schemaField: EntitySchemaField)
|
||||||
|
Inherited from
DefaultDatatype
|
||||||
|
Defined in
DefaultDatatype:43
|
||||||
|
Parameters :
Returns :
EntitySchemaField
|
| transformToDatabaseFormat | |||||||||
transformToDatabaseFormat(value: EntityType, schemaField?: EntitySchemaField)
|
|||||||||
|
Inherited from
DefaultDatatype
|
|||||||||
|
Defined in
DefaultDatatype:92
|
|||||||||
|
Parameters :
Returns :
DBType
|
| transformToObjectFormat | |||||||||
transformToObjectFormat(value: DBType, schemaField?: EntitySchemaField)
|
|||||||||
|
Inherited from
DefaultDatatype
|
|||||||||
|
Defined in
DefaultDatatype:103
|
|||||||||
|
Parameters :
Returns :
EntityType
|
| Async anonymize | ||||||||||||||||
anonymize(value: EntityType, schemaField: EntitySchemaField, parent: any)
|
||||||||||||||||
|
Inherited from
DefaultDatatype
|
||||||||||||||||
|
Defined in
DefaultDatatype:259
|
||||||||||||||||
|
(Partially) anonymize to "retain-anonymized" for reporting purposes without personal identifiable information.
Parameters :
Returns :
Promise<any>
|
| importIncompleteAdditionalConfigBadge | ||||||
importIncompleteAdditionalConfigBadge(col: ColumnMapping)
|
||||||
|
Inherited from
DefaultDatatype
|
||||||
|
Defined in
DefaultDatatype:209
|
||||||
|
Output a label indicating whether the given column mapping needs user configuration for the "additional" config or has a valid, complete "additional" config. returns "undefined" if no user action is required.
Parameters :
Returns :
string
|
| Async importMapFunction | ||||||||||||||||||||
importMapFunction(val: any, schemaField: EntitySchemaField, additional?: any, importProcessingContext?: any)
|
||||||||||||||||||||
|
Inherited from
DefaultDatatype
|
||||||||||||||||||||
|
Defined in
DefaultDatatype:188
|
||||||||||||||||||||
|
The function used to map values from the import data to values in the entities to be created. to share information across processing of multiple columns and rows.
Parameters :
Returns :
Promise<EntityType>
|
| Static Readonly dataType |
Type : string
|
Default value : "attendance"
|
|
Inherited from
DefaultDatatype
|
|
Defined in
DefaultDatatype:35
|
| editComponent |
Type : string
|
Default value : "EditAttendance"
|
|
Inherited from
DefaultDatatype
|
|
Defined in
DefaultDatatype:40
|
| embeddedType |
Type : unknown
|
Default value : AttendanceItem
|
|
Inherited from
SchemaEmbedDatatype
|
|
Defined in
SchemaEmbedDatatype:38
|
| Static label |
Type : string
|
Default value : $localize`:datatype-label:attendance (participants with status)`
|
|
Inherited from
DefaultDatatype
|
|
Defined in
DefaultDatatype:36
|
| viewComponent |
Type : string
|
Default value : "DisplayAttendance"
|
|
Inherited from
DefaultDatatype
|
|
Defined in
DefaultDatatype:41
|
| Protected Readonly schemaService |
Type : unknown
|
Default value : inject(EntitySchemaService)
|
|
Inherited from
SchemaEmbedDatatype
|
|
Defined in
SchemaEmbedDatatype:70
|
| Readonly importAllowsMultiMapping |
Type : boolean
|
Default value : false
|
|
Inherited from
DefaultDatatype
|
|
Defined in
DefaultDatatype:123
|
|
Whether this datatype allows multiple values to be mapped to the same entity field during import. |
| Optional importConfigComponent |
Type : string
|
|
Inherited from
DefaultDatatype
|
|
Defined in
DefaultDatatype:201
|
|
A component to be display as a dialog to configure the transformation function (e.g. defining a format or mapping) |
import { inject, Injectable } from "@angular/core";
import { SchemaEmbedDatatype } from "#src/app/core/basic-datatypes/schema-embed/schema-embed.datatype";
import { AttendanceItem } from "./attendance-item";
import { EntitySchemaField } from "#src/app/core/entity/schema/entity-schema-field";
import { Entity, EntityConstructor } from "#src/app/core/entity/model/entity";
import { EventAttendanceMapDatatype } from "../deprecated/event-attendance-map.datatype";
import { EntityMapperService } from "#src/app/core/entity/entity-mapper/entity-mapper.service";
import {
ExportColumnMapping,
DefaultDatatype,
} from "#src/app/core/entity/default-datatype/default.datatype";
/**
* Datatype for attendance tracking on any entity.
*
* Use this as `dataType: "attendance"` with `isArray: true` on an entity field
* to store an array of {@link AttendanceItem} objects, each referencing a participant entity.
*
* The allowed entity types for the `participant` field can be overridden via
* the field's `additional` config, e.g.:
* ```json
* {
* "dataType": "attendance",
* "isArray": true,
* "additional": {
* "participant": { "dataType": "entity", "additional": ["Child", "School"] }
* }
* }
* ```
*/
@Injectable()
export class AttendanceDatatype extends SchemaEmbedDatatype {
private readonly entityMapper = inject(EntityMapperService);
static override readonly dataType = "attendance";
static override label: string = $localize`:datatype-label:attendance (participants with status)`;
override embeddedType = AttendanceItem;
override editComponent = "EditAttendance";
override viewComponent = "DisplayAttendance";
override normalizeSchemaField(
schemaField: EntitySchemaField,
): EntitySchemaField {
// attendance always requires isArray
return { ...schemaField, isArray: true };
}
override getExportColumns(
schemaField: EntitySchemaField,
): ExportColumnMapping[] {
if (!schemaField.label) {
return [];
}
return [
{
keySuffix: "",
label: schemaField.label + " (participation details)",
resolveValue: async (value: AttendanceItem[]) => {
const attendance = Array.isArray(value) ? value : [];
const participantCache = new Map<string, Promise<string>>();
const details = await Promise.all(
attendance.map((attendanceItem) =>
this.toParticipationDetails(attendanceItem, participantCache),
),
);
return details.join(", ");
},
},
{
keySuffix: "_participant_count",
label: schemaField.label + " (number of participants)",
resolveValue: (value: AttendanceItem[]) => {
const attendance = Array.isArray(value) ? value : [];
return attendance.length;
},
},
];
}
private async toParticipationDetails(
attendanceItem: AttendanceItem,
participantCache: Map<string, Promise<string>>,
): Promise<string> {
const participant = await this.getParticipantReadable(
attendanceItem,
participantCache,
);
const statusLabel = this.getStatusLabel(attendanceItem);
if (participant && statusLabel) {
return `${participant} (${statusLabel})`;
}
if (participant) {
return participant;
}
if (statusLabel) {
return statusLabel;
}
return "";
}
private async getParticipantReadable(
attendanceItem: AttendanceItem,
participantCache: Map<string, Promise<string>>,
): Promise<string> {
const participantId = attendanceItem?.participant;
if (!participantId) {
return "";
}
const cachedResult = participantCache.get(participantId);
if (cachedResult) {
return cachedResult;
}
const readableResultPromise = this.entityMapper
.load(Entity.extractTypeFromId(participantId), participantId)
.then((entity) => entity.toString())
.catch(() => "<not_found>");
participantCache.set(participantId, readableResultPromise);
return readableResultPromise;
}
private getStatusLabel(attendanceItem: AttendanceItem): string {
const status = attendanceItem?.status;
if (!status) {
return "";
}
if (typeof status === "string") {
return status;
}
if (typeof status === "object" && "label" in status) {
return status.label ?? "";
}
return "";
}
private static readonly ATTENDANCE_DATATYPES = [
AttendanceDatatype.dataType,
EventAttendanceMapDatatype.dataType,
];
/** @override Detects the first `attendance` or legacy `event-attendance-map` field in the entity schema. */
static override detectFieldInEntity(
entityOrType: Entity | EntityConstructor,
): string | undefined {
return DefaultDatatype.detectFieldInEntity(
entityOrType,
AttendanceDatatype.ATTENDANCE_DATATYPES,
);
}
/** Detect all `attendance` or legacy `event-attendance-map` fields in the entity schema. */
static override detectAllFieldsInEntity(
entityOrType: Entity | EntityConstructor,
): { fieldId: string; schemaField: EntitySchemaField }[] {
return DefaultDatatype.detectAllFieldsInEntity(
entityOrType,
AttendanceDatatype.ATTENDANCE_DATATYPES,
);
}
}