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

Description

The component that is responsible for listing the Notes that are related to a certain entity.

Extends

RelatedEntitiesComponent<Note>

Example

Metadata

Relationships

Index

Properties
Methods
Inputs
Outputs

Inputs

loaderMethod
Type : LoaderMethod
Default value : LoaderMethod.NotesRelatedToEntity
Inherited from RelatedEntitiesComponent

Load related notes via the ChildrenService (see EntitySpecialLoaderService).

clickMode
Type : "popup" | "navigate" | "popup-details"
Default value : "popup"
Inherited from RelatedEntitiesComponent
columns
Type : ColumnConfig[]
Default value : []
Inherited from RelatedEntitiesComponent

Columns to be displayed in the table

dataSource
Type : DataSourceType
Inherited from RelatedEntitiesComponent
editable
Type : boolean
Default value : true
Inherited from RelatedEntitiesComponent
entity
Type : Entity
Inherited from RelatedEntitiesComponent

currently viewed/main entity for which related entities are displayed in this component

entityType
Type : string
Inherited from RelatedEntitiesComponent

entity type of the related entities to be displayed

filter
Type : DataFilter<E>
Inherited from RelatedEntitiesComponent

This filter is applied before displaying the data.

property
Type : string | string[]
Inherited from RelatedEntitiesComponent

Property name of the related entities (type given in this.entityType) that holds the entity id to be matched with the id of the current main entity (given in this.entity). If not explicitly set, this will be inferred based on the defined relations between the entities.

manually setting this is only necessary if you have multiple properties referencing the same entity type and you want to list only records related to one of them. For example: if you set entityType = "Project" (to display a list of projects here) and the Project entities have a properties "participants" and "supervisors" both storing references to User entities, you can set property = "supervisors" to only list those projects where the current User is supervisors, not participant.

showInactive
Type : boolean | undefined
Default value : undefined
Inherited from RelatedEntitiesComponent

Whether inactive/archived records should be shown.

Outputs

showInactive
Type : boolean | undefined
Inherited from RelatedEntitiesComponent

Whether inactive/archived records should be shown.

Methods

createNewRecordFactory
createNewRecordFactory()
Inherited from RelatedEntitiesComponent
Returns : () => any
Protected getDefaultColumns
getDefaultColumns()
Inherited from RelatedEntitiesComponent
Returns : FormFieldConfig[]
showNoteDetails
showNoteDetails(note: Note)
Parameters :
Name Type Optional
note Note No
Returns : void
Protected getColumns
getColumns(value: ColumnConfig[] | undefined)
Inherited from RelatedEntitiesComponent
Parameters :
Name Type Optional
value ColumnConfig[] | undefined No
Returns : FormFieldConfig[]
Protected getProperty
getProperty()
Inherited from RelatedEntitiesComponent

Auto-detect which properties of the related entity type reference the current entity. Returns dot-paths for nested references (e.g. "attendance.participant").

Returns : string | []
Protected initFilter
initFilter()
Inherited from RelatedEntitiesComponent
Returns : DataFilter<E>

Properties

entityCtr
Type : unknown
Default value : computed(() => Note)
Inherited from RelatedEntitiesComponent
Readonly getColor
Type : unknown
Default value : computed(() => { if (this.entity()?.getType() === "Child") { return (note: Note) => note?.getColorForId(this.entity()?.getId()); } return (note: Note) => note?.getColor(); })
newRecordFactory
Type : unknown
Default value : this.createNewRecordFactory()
Readonly _columns
Type : unknown
Default value : computed(() => { const entity = this.entity(); const rawCols = this.getColumns(this.columns()); if (!entity) return rawCols; return rawCols.map((column) => { if (typeof column.additional === "object" && column.additional !== null) { return { ...column, additional: { ...column.additional, relatedEntitiesParent: entity }, }; } return column; }); })
Inherited from RelatedEntitiesComponent
Readonly columnsToDisplay
Type : unknown
Default value : computed(() => this._columns() .filter((column) => { if (column?.hideFromTable) return false; const numericValue = ScreenSize[column?.visibleFrom]; if (numericValue === undefined) return true; return this.currentScreenSize() >= numericValue; }) .map((c) => c.id), )
Inherited from RelatedEntitiesComponent
Readonly filterObj
Type : unknown
Default value : signal<DataFilter<E>>({})
Inherited from RelatedEntitiesComponent
Protected filterService
Type : unknown
Default value : inject(FilterService)
Inherited from RelatedEntitiesComponent
recordsDataSource
Type : unknown
Default value : computed(() => resolveDataSource<E>(this.injector, this.dataSource(), this.loaderMethod()), )
Inherited from RelatedEntitiesComponent
Protected Readonly relationProperty
Type : unknown
Default value : computed<string | string[]>(() => { const entity = this.entity(); const entityCtr = this.entityCtr(); if (!entity || !entityCtr) { return []; } const resolvedProperty = this.property() ?? this.getProperty(); return typeof resolvedProperty === "string" ? this.resolvePropertyPath(resolvedProperty) : resolvedProperty.map((p) => this.resolvePropertyPath(p)); })
Inherited from RelatedEntitiesComponent
import {
  ChangeDetectionStrategy,
  Component,
  computed,
  inject,
  input,
} from "@angular/core";
import { Note } from "../model/note";
import { FormDialogService } from "../../../core/form-dialog/form-dialog.service";
import { DynamicComponent } from "../../../core/config/dynamic-components/dynamic-component.decorator";
import { Entity } from "../../../core/entity/model/entity";
import { ChildSchoolRelation } from "../../children/model/childSchoolRelation";
import { EntityDatatype } from "../../../core/basic-datatypes/entity/entity.datatype";
import { asArray } from "app/utils/asArray";
import { EntitiesTableComponent } from "../../../core/common-components/entities-table/entities-table.component";
import { FormFieldConfig } from "../../../core/common-components/entity-form/FormConfig";
import { RelatedEntitiesComponent } from "../../../core/entity-details/related-entities/related-entities.component";
import { LoaderMethod } from "../../../core/entity/entity-special-loader/entity-special-loader.service";
import { CustomFormLinkButtonComponent } from "app/features/public-form/custom-form-link-button/custom-form-link-button.component";
import { RELATED_ENTITIES_DEFAULT_CONFIGS } from "app/utils/related-entities-default-config";

/**
 * The component that is responsible for listing the Notes that are related to a certain entity.
 */
@DynamicComponent("NotesRelatedToEntity")
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: "app-notes-related-to-entity",
  templateUrl: "./notes-related-to-entity.component.html",
  imports: [EntitiesTableComponent, CustomFormLinkButtonComponent],
})
export class NotesRelatedToEntityComponent extends RelatedEntitiesComponent<Note> {
  private formDialog = inject(FormDialogService);

  override entityCtr = computed(() => Note);

  /** Load related notes via the ChildrenService (see EntitySpecialLoaderService). */
  override loaderMethod = input<LoaderMethod>(
    LoaderMethod.NotesRelatedToEntity,
  );
  protected override getDefaultColumns(): FormFieldConfig[] {
    return structuredClone(
      RELATED_ENTITIES_DEFAULT_CONFIGS["NotesRelatedToEntity"].columns,
    );
  }

  readonly getColor = computed(() => {
    if (this.entity()?.getType() === "Child") {
      return (note: Note) => note?.getColorForId(this.entity()?.getId());
    }
    return (note: Note) => note?.getColor();
  });
  newRecordFactory = this.createNewRecordFactory();

  override createNewRecordFactory() {
    return () => {
      const newNote = super.createNewRecordFactory()();

      const entity = this.entity();
      if (!entity) {
        return newNote;
      }
      if (entity.getType() === ChildSchoolRelation.ENTITY_TYPE) {
        this.specialLinkingForChildSchoolRelation(newNote);
      }

      for (const e of [
        entity.getId(),
        ...this.getIndirectlyRelatedEntityIds(entity),
      ]) {
        if (!this.isAlreadyLinked(newNote, e)) {
          newNote.relatedEntities.push(e);
        }
      }

      return newNote;
    };
  }

  private specialLinkingForChildSchoolRelation(newNote: Note) {
    //TODO: generalize this code - possibly by only using relatedEntities to link other records here? see #1501
    for (const childId of asArray(
      (this.entity() as ChildSchoolRelation).childId,
    )) {
      if (childId) {
        newNote.children.push(childId);
      }
    }

    for (const schooldId of asArray(
      (this.entity() as ChildSchoolRelation).schoolId,
    )) {
      if (schooldId) {
        newNote.schools.push(schooldId);
      }
    }
  }

  /**
   * check if an entityId is already referenced in any array properties of the given note
   */
  private isAlreadyLinked(newNote: any, id: string): boolean {
    for (const key in newNote) {
      if (asArray(newNote[key]).includes(id)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Get entities referenced in the given entity that match the entity types allowed for Note.relatedEntities schema
   * and return their ids (including prefix).
   * @param entity
   * @private
   */
  private getIndirectlyRelatedEntityIds(entity: Entity): string[] {
    let relatedIds = [];
    let permittedRelatedTypes = asArray(
      Note.schema.get("relatedEntities").additional,
    );

    for (const [property, schema] of entity.getSchema().entries()) {
      if (!entity[property]) {
        // empty - skip
        continue;
      }

      if (schema.dataType !== EntityDatatype.dataType) {
        // not referencing other entities
        continue;
      }

      for (const referencedId of asArray(entity[property])) {
        const referencedType = Entity.extractTypeFromId(referencedId);

        if (permittedRelatedTypes.includes(referencedType)) {
          // entity can have references of multiple entity types of which only some are allowed to be linked to Notes
          relatedIds.push(
            Entity.createPrefixedId(referencedType, referencedId),
          );
        }
      }
    }

    return relatedIds;
  }

  showNoteDetails(note: Note) {
    this.formDialog.openView(note);
  }
}
<app-entities-table
  [entityType]="entityCtr()"
  [recordsDataSource]="recordsDataSource()"
  [customColumns]="_columns()"
  [filter]="filterObj()"
  [newRecordFactory]="newRecordFactory"
  clickMode="none"
  (entityClick)="showNoteDetails($event)"
  [getBackgroundColor]="getColor()"
>
</app-entities-table>

<app-custom-form-link-button
  [linkedEntity]="entity()"
  [formEntityType]="entityCtr()"
>
</app-custom-form-link-button>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""