src/app/features/attendance/deprecated/event-attendance-map.datatype.ts
Use the new `attendance` datatype ({@link AttendanceDatatype}) with `isArray: true` instead.
Holds a full register of EventAttendance entries. Each value in the map is an AttendanceItem, transformed using its schema annotations (via EntitySchemaService).
Unlike other SchemaEmbedDatatypes, each entry is stored as a tuple
[participantId, {status, remarks}] instead of the embedded object itself.
Any method of SchemaEmbedDatatype that works on the stored value
(rather than the loaded AttendanceItem[]) therefore has to be overridden here.
Properties |
|
Methods |
| getEmbeddedFieldDbPath | ||||||
getEmbeddedFieldDbPath(innerProp: string)
|
||||||
|
Inherited from
SchemaEmbedDatatype
|
||||||
|
Path of an AttendanceItem property within the stored tuple
Parameters :
Returns :
string
|
| getReferenceSelector | ||||||||||||
getReferenceSelector(fieldId: string, schemaField: EntitySchemaField, referencedId: string)
|
||||||||||||
|
Inherited from
DefaultDatatype
|
||||||||||||
|
Unlike the embedded objects of the
Parameters :
Returns :
DataFilter[]
|
| holdsArray |
holdsArray()
|
|
Inherited from
SchemaEmbedDatatype
|
|
Always an array of entries, although the field does not (and, as the whole array is
(de)serialized here at once, cannot) declare
Returns :
boolean
|
| transformToDatabaseFormat | ||||||
transformToDatabaseFormat(value: AttendanceItem[])
|
||||||
|
Inherited from
DefaultDatatype
|
||||||
|
Parameters :
Returns :
any
|
| transformToObjectFormat | ||||||
transformToObjectFormat(value: any[])
|
||||||
|
Inherited from
DefaultDatatype
|
||||||
|
Parameters :
Returns :
any
|
| getEffectiveSchema | ||||||
getEffectiveSchema(schemaField?: EntitySchemaField)
|
||||||
|
Inherited from
SchemaEmbedDatatype
|
||||||
|
Build the effective inner schema from the embedded type's annotations
and/or the
Parameters :
Returns :
EntitySchema
|
| Async anonymize | ||||||||||||||||
anonymize(value: EntityType, schemaField: EntitySchemaField, parent: any)
|
||||||||||||||||
|
Inherited from
DefaultDatatype
|
||||||||||||||||
|
(Partially) anonymize to "retain-anonymized" for reporting purposes without personal identifiable information.
Parameters :
Returns :
Promise<any>
|
| Static detectAllFieldsInEntity | ||||||||||||
detectAllFieldsInEntity(entityOrType: Entity | EntityConstructor, dataTypes: string | string[])
|
||||||||||||
|
Inherited from
DefaultDatatype
|
||||||||||||
|
Detect all fields of the given datatype(s) in an entity's schema.
Parameters :
Returns :
literal type[]
Array of matching fields with their id and schema definition. |
| Static detectFieldInEntity | ||||||||||||
detectFieldInEntity(entityOrType: Entity | EntityConstructor, dataTypes: string | string[])
|
||||||||||||
|
Inherited from
DefaultDatatype
|
||||||||||||
|
Detect the first field of the given datatype(s) in an entity's schema. Scans the schema for a field whose Subclasses typically override this without the extra
Parameters :
Returns :
string | undefined
The field name of the first matching field, or |
| getExportColumns | ||||||
getExportColumns(schemaField: EntitySchemaField)
|
||||||
|
Inherited from
DefaultDatatype
|
||||||
|
Export columns for a field using this datatype. Each returned column contributes a CSV header and its own value resolver.
The returned The default implementation returns a single column with the raw field value. Readable formatting can be applied by callers during CSV transformation. Override this to provide custom or additional columns (e.g. entity references can add a human-readable name column alongside the ID column).
Parameters :
Returns :
ExportColumnMapping[]
|
| Async importMapFunction | ||||||||||||||||||||
importMapFunction(val: any, schemaField: EntitySchemaField, additional?: any, importProcessingContext?: any)
|
||||||||||||||||||||
|
Inherited from
DefaultDatatype
|
||||||||||||||||||||
|
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>
|
| Async importMatchField | ||||||||||||||||
importMatchField(schemaField: EntitySchemaField, columns: ColumnImportInput[], importProcessingContext?: ImportProcessingContext)
|
||||||||||||||||
|
Inherited from
DefaultDatatype
|
||||||||||||||||
|
Map all columns mapped to one target field to the value(s) stored there. ImportService calls this once per target field per row with every column mapped to that field. The default handles trimming and array splitting and delegates each individual value to importMapFunction. Datatypes that need to consider several columns together (e.g. matching an entity by more than one property) override this. (isArray=true), or undefined if nothing was mapped
Parameters :
Returns :
Promise<unknown>
the value to store: a single value (isArray=false) or array (isArray=true), or undefined if nothing was mapped |
| normalizeSchemaField | ||||||||
normalizeSchemaField(schemaField: EntitySchemaField)
|
||||||||
|
Inherited from
DefaultDatatype
|
||||||||
|
Return the (potentially adjusted) schema field for this datatype. Called when schema fields are set up (e.g. from config), allowing the datatype to normalize or fill in required settings. Override this in a subclass to enforce constraints
(e.g. always setting
Parameters :
Returns :
EntitySchemaField
The schema field to use (default: unchanged) |
| sortValue | ||||||
sortValue(_fieldValue: EntityType)
|
||||||
|
Inherited from
DefaultDatatype
|
||||||
|
Return a comparable primitive for sorting this field's value in a list column.
Return
Parameters :
Returns :
number | string | undefined
|
| Static Readonly dataType |
Type : string
|
Default value : "event-attendance-map"
|
|
Inherited from
DefaultDatatype
|
| editComponent |
Type : string
|
Default value : "EditAttendance"
|
|
Inherited from
DefaultDatatype
|
| embeddedType |
Type : unknown
|
Default value : AttendanceItem
|
|
Inherited from
SchemaEmbedDatatype
|
|
Not used by (de)serialization here (which always hand-rolls the whole
|
| viewComponent |
Type : string
|
Default value : "DisplayAttendance"
|
|
Inherited from
DefaultDatatype
|
| Protected Readonly schemaService |
Type : unknown
|
Default value : inject(EntitySchemaService)
|
|
Inherited from
SchemaEmbedDatatype
|
| Readonly importAllowsMultiMapping |
Type : boolean
|
Default value : false
|
|
Inherited from
DefaultDatatype
|
|
Whether this datatype allows multiple values to be mapped to the same entity field during import. |
| Optional importConfigComponent |
Type : string
|
|
Inherited from
DefaultDatatype
|
|
A component to be rendered inline to configure the import transformation (e.g. defining a format or value mapping). The component receives inputs:
|
| Optional importConfigDialog |
Type : string
|
|
Inherited from
DefaultDatatype
|
|
A dialog component in which the import transformation is configured (see MappingDialogData for the data it receives). Datatypes that require such a dialog get it opened automatically as soon as the user maps a column to one of their fields, so that the suggested settings are reviewed and confirmed rather than silently skipped. |
| Readonly internalValidators |
Type : ValidatorFn[]
|
Default value : []
|
|
Inherited from
DefaultDatatype
|
|
Validators that every value of this datatype has to pass in entity forms,
in addition to the |
| Static label |
Type : string
|
Default value : $localize`:datatype-label:any`
|
|
Inherited from
DefaultDatatype
|
|
The human-readable name for this dataType, used in config UIs. |
import { Injectable } from "@angular/core";
import { AttendanceItem } from "../model/attendance-item";
import { SchemaEmbedDatatype } from "#src/app/core/basic-datatypes/schema-embed/schema-embed.datatype";
import { EntitySchemaField } from "#src/app/core/entity/schema/entity-schema-field";
import type { DataFilter } from "#src/app/core/filter/filters/filters";
/**
* Holds a full register of EventAttendance entries.
* Each value in the map is an {@link AttendanceItem}, transformed
* using its schema annotations (via {@link EntitySchemaService}).
*
* Unlike other {@link SchemaEmbedDatatype}s, each entry is stored as a tuple
* `[participantId, {status, remarks}]` instead of the embedded object itself.
* Any method of {@link SchemaEmbedDatatype} that works on the stored value
* (rather than the loaded `AttendanceItem[]`) therefore has to be overridden here.
*
* @deprecated Use the new `attendance` datatype ({@link AttendanceDatatype}) with `isArray: true` instead.
*/
@Injectable()
export class EventAttendanceMapDatatype extends SchemaEmbedDatatype {
static override readonly dataType = "event-attendance-map";
override editComponent = "EditAttendance";
override viewComponent = "DisplayAttendance";
/**
* Not used by (de)serialization here (which always hand-rolls the whole
* `AttendanceItem.schema` directly, see below), but declared so that generic tooling
* (e.g. `getEmbeddedSchema` for filters) can discover `AttendanceItem`'s fields
* without requiring every one of them to be redeclared in a field's `additional` config.
*/
override embeddedType = AttendanceItem;
/**
* Always an array of entries, although the field does not (and, as the whole array is
* (de)serialized here at once, cannot) declare `isArray: true`.
*/
override holdsArray(): boolean {
return true;
}
/**
* Path of an {@link AttendanceItem} property within the stored tuple
* `[participantId, {status, remarks}]` (see {@link getReferenceSelector} for why an
* integer path segment works on both query engines).
*/
override getEmbeddedFieldDbPath(innerProp: string): string {
return innerProp === "participant" ? "0" : `1.${innerProp}`;
}
/**
* Unlike the embedded objects of the `attendance` datatype, this one stores each entry as a
* two-element tuple `[participantId, {status, remarks}]` (see {@link transformToDatabaseFormat}),
* so the participant is matched by its *index* in that tuple rather than by a property name.
*
* `{$elemMatch: {"0": id}}` is the spelling that works on both query engines:
* CouchDB's `mango_doc:get_field` accepts an integer path segment into an array, and
* pouchdb-find resolves `tuple["0"]` the same way. The nesting that looks more natural,
* `{$elemMatch: {$elemMatch: {$eq: id}}}`, silently matches nothing in pouchdb-find, which
* treats the inner `$elemMatch` as a field name.
*/
override getReferenceSelector(
fieldId: string,
schemaField: EntitySchemaField,
referencedId: string,
): DataFilter<any>[] {
const participantPath = this.getEmbeddedFieldDbPath("participant");
return [{ [fieldId]: { $elemMatch: { [participantPath]: referencedId } } }];
}
override transformToDatabaseFormat(value: AttendanceItem[]) {
if (!Array.isArray(value)) {
console.warn(
'property to be saved with "event-attendance-map" datatype is not of expected type',
value,
);
return value as any;
}
const result: [string, any][] = [];
for (const item of value) {
const attItem = this.schemaService.transformEntityToDatabaseFormat(
item as any,
AttendanceItem.schema,
);
result.push([
item.participant ?? "",
{ status: attItem.status, remarks: attItem.remarks },
]);
}
return result;
}
override transformToObjectFormat(value: any[]) {
if (!Array.isArray(value) || value === null) {
console.warn(
'property to be loaded with "event-attendance-map" datatype is not valid',
value,
);
return value as any;
}
const result: AttendanceItem[] = [];
for (const keyValue of value) {
const transformedValue =
this.schemaService.transformDatabaseToEntityFormat<AttendanceItem>(
keyValue[1],
AttendanceItem.schema,
);
const instance = new AttendanceItem();
Object.assign(instance, transformedValue);
instance.participant = keyValue[0];
result.push(instance);
}
return result;
}
}