From 364ee7ce7860d1d4f8d8030c382339134f5a26aa Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 20 Jan 2025 11:52:12 +0100 Subject: [PATCH 1/2] docs: update README.md badges --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f1d4c4daad..f414f2aa12 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,19 @@ [![Release Version](https://img.shields.io/github/release/Aam-Digital/ndb-core.svg)](https://github.com/Aam-Digital/ndb-core/releases) -[![Build Status](https://github.com/Aam-Digital/ndb-core/actions/workflows/master-push.yml/badge.svg)](https://github.com/Aam-Digital/ndb-core/actions/workflows/master-push.yml) -[![Code Climate](https://codeclimate.com/github/Aam-Digital/ndb-core/badges/gpa.svg)](https://codeclimate.com/github/Aam-Digital/ndb-core) -[![Test Coverage](https://api.codeclimate.com/v1/badges/4e4a7a6301064019b2c9/test_coverage)](https://codeclimate.com/github/Aam-Digital/ndb-core/test_coverage) -[![E2E Tests](https://img.shields.io/endpoint?url=https://dashboard.cypress.io/badge/simple/2petka/master&style=flat&logo=cypress)](https://dashboard.cypress.io/projects/2petka/runs) -[![Known Vulnerabilities](https://snyk.io/test/github/Aam-Digital/ndb-core/badge.svg)](https://snyk.io/test/github/Aam-Digital/ndb-core) -[![Guides](https://img.shields.io/badge/Tutorial%20%26%20Guides-available-blue)](https://aam-digital.github.io/ndb-core/documentation/additional-documentation/overview.html) [![DPG Badge](https://img.shields.io/badge/Verified-DPG-3333AB?logo=data:image/svg%2bxml;base64,PHN2ZyB3aWR0aD0iMzEiIGhlaWdodD0iMzMiIHZpZXdCb3g9IjAgMCAzMSAzMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE0LjIwMDggMjEuMzY3OEwxMC4xNzM2IDE4LjAxMjRMMTEuNTIxOSAxNi40MDAzTDEzLjk5MjggMTguNDU5TDE5LjYyNjkgMTIuMjExMUwyMS4xOTA5IDEzLjYxNkwxNC4yMDA4IDIxLjM2NzhaTTI0LjYyNDEgOS4zNTEyN0wyNC44MDcxIDMuMDcyOTdMMTguODgxIDUuMTg2NjJMMTUuMzMxNCAtMi4zMzA4MmUtMDVMMTEuNzgyMSA1LjE4NjYyTDUuODU2MDEgMy4wNzI5N0w2LjAzOTA2IDkuMzUxMjdMMCAxMS4xMTc3TDMuODQ1MjEgMTYuMDg5NUwwIDIxLjA2MTJMNi4wMzkwNiAyMi44Mjc3TDUuODU2MDEgMjkuMTA2TDExLjc4MjEgMjYuOTkyM0wxNS4zMzE0IDMyLjE3OUwxOC44ODEgMjYuOTkyM0wyNC44MDcxIDI5LjEwNkwyNC42MjQxIDIyLjgyNzdMMzAuNjYzMSAyMS4wNjEyTDI2LjgxNzYgMTYuMDg5NUwzMC42NjMxIDExLjExNzdMMjQuNjI0MSA5LjM1MTI3WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg==)](https://digitalpublicgoods.net/r/aam-digital) +[![User Support Center](https://img.shields.io/badge/User%20Support%20Center-available-blue)](https://chatwoot.help/hc/aam-digital/en) + ![English](https://img.shields.io/poeditor/progress/740876/en?token=56acaf6808f07eb52c5b39a3abea19a7) ![French](https://img.shields.io/poeditor/progress/740876/fr?token=56acaf6808f07eb52c5b39a3abea19a7) ![Italian](https://img.shields.io/poeditor/progress/740876/it?token=56acaf6808f07eb52c5b39a3abea19a7) ![German](https://img.shields.io/poeditor/progress/740876/de?token=56acaf6808f07eb52c5b39a3abea19a7) +[![Code Climate](https://codeclimate.com/github/Aam-Digital/ndb-core/badges/gpa.svg)](https://codeclimate.com/github/Aam-Digital/ndb-core) +[![Test Coverage](https://api.codeclimate.com/v1/badges/4e4a7a6301064019b2c9/test_coverage)](https://codeclimate.com/github/Aam-Digital/ndb-core/test_coverage) +[![E2E Tests](https://img.shields.io/endpoint?url=https://dashboard.cypress.io/badge/simple/2petka/master&style=flat&logo=cypress)](https://dashboard.cypress.io/projects/2petka/runs) +[![Known Vulnerabilities](https://snyk.io/test/github/Aam-Digital/ndb-core/badge.svg)](https://snyk.io/test/github/Aam-Digital/ndb-core) +[![Developer Guides](https://img.shields.io/badge/Tutorial%20%26%20Guides-available-blue)](https://aam-digital.github.io/ndb-core/documentation/additional-documentation/overview.html) + + # Aam Digital _Enabling social organizations digitally to transform lives._ From 393b6358f477eb2e0f500740d9171b7560622165 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 20 Jan 2025 15:18:57 +0100 Subject: [PATCH 2/2] fix(Admin UI): hide special EventNote entity type from admin lists (#2764) --- .../attendance/model/event-note.ts | 20 +++---------------- .../children/model/childSchoolRelation.ts | 2 ++ .../admin-entity-field.component.spec.ts | 6 ++++-- .../entity-type-select.component.ts | 17 +++++++++++----- src/app/core/entity/model/entity.spec.ts | 10 ++++++---- src/app/core/entity/model/entity.ts | 10 +--------- src/app/core/site-settings/site-settings.ts | 1 - .../matching-entities.component.spec.ts | 5 ++++- .../public-form/public-form-config.ts | 2 -- 9 files changed, 32 insertions(+), 41 deletions(-) diff --git a/src/app/child-dev-project/attendance/model/event-note.ts b/src/app/child-dev-project/attendance/model/event-note.ts index 8a7afba7b9..9143173fba 100644 --- a/src/app/child-dev-project/attendance/model/event-note.ts +++ b/src/app/child-dev-project/attendance/model/event-note.ts @@ -1,25 +1,11 @@ -/* - * This file is part of ndb-core. - * - * ndb-core is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * ndb-core is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ndb-core. If not, see . - */ - import { DatabaseEntity } from "../../../core/entity/database-entity.decorator"; import { Note } from "../../notes/model/note"; @DatabaseEntity("EventNote") export class EventNote extends Note { + static override label = undefined; // hide the EventNote entity type from Admin UIs to avoid confusion with the Note entity type + static override labelPlural = undefined; + static override create(date: Date, subject: string = ""): EventNote { const instance = new EventNote(); instance.date = date; diff --git a/src/app/child-dev-project/children/model/childSchoolRelation.ts b/src/app/child-dev-project/children/model/childSchoolRelation.ts index 134c783f05..d3371a66af 100644 --- a/src/app/child-dev-project/children/model/childSchoolRelation.ts +++ b/src/app/child-dev-project/children/model/childSchoolRelation.ts @@ -10,6 +10,8 @@ import { TimePeriod } from "../../../core/entity-details/related-time-period-ent */ @DatabaseEntity("ChildSchoolRelation") export class ChildSchoolRelation extends TimePeriod { + static override label = "School Enrollment"; + static override labelPlural = "School Enrollments"; static override hasPII = true; @DatabaseField({ diff --git a/src/app/core/admin/admin-entity-details/admin-entity-field/admin-entity-field.component.spec.ts b/src/app/core/admin/admin-entity-details/admin-entity-field/admin-entity-field.component.spec.ts index 1b160d49f1..1a0be156ce 100644 --- a/src/app/core/admin/admin-entity-details/admin-entity-field/admin-entity-field.component.spec.ts +++ b/src/app/core/admin/admin-entity-details/admin-entity-field/admin-entity-field.component.spec.ts @@ -27,6 +27,7 @@ import { Validators } from "@angular/forms"; import { RecurringActivity } from "../../../../child-dev-project/attendance/model/recurring-activity"; import { AdminEntityService } from "../../admin-entity.service"; import { EntitySchemaField } from "../../../entity/schema/entity-schema-field"; +import { TestEntity } from "../../../../utils/test-utils/TestEntity"; describe("AdminEntityFieldComponent", () => { let component: AdminEntityFieldComponent; @@ -85,6 +86,7 @@ describe("AdminEntityFieldComponent", () => { it("should include 'additional' field only for relevant datatypes", fakeAsync(() => { const dataTypeForm = component.schemaFieldsForm.get("dataType"); let additionalInput: MatInputHarness; + function findAdditionalInputComponent() { loader .getHarness( @@ -179,7 +181,7 @@ describe("AdminEntityFieldComponent", () => { })); it("should init 'additional' options for entity datatypes", fakeAsync(() => { - const mockEntityTypes = [Entity, RecurringActivity]; + const mockEntityTypes = [TestEntity, RecurringActivity]; const entityRegistry = TestBed.inject(EntityRegistry); spyOn(entityRegistry, "getEntityTypes").and.returnValue( mockEntityTypes.map((x) => ({ key: x.ENTITY_TYPE, value: x })), @@ -192,7 +194,7 @@ describe("AdminEntityFieldComponent", () => { tick(); expect(component.typeAdditionalOptions).toEqual([ - { value: "Entity", label: "Entity" }, + { value: TestEntity.ENTITY_TYPE, label: TestEntity.label }, { value: RecurringActivity.ENTITY_TYPE, label: RecurringActivity.label }, ]); expect(component.additionalForm.value).toBe(RecurringActivity.ENTITY_TYPE); diff --git a/src/app/core/entity/entity-type-select/entity-type-select.component.ts b/src/app/core/entity/entity-type-select/entity-type-select.component.ts index adc6baec97..b812bf6926 100644 --- a/src/app/core/entity/entity-type-select/entity-type-select.component.ts +++ b/src/app/core/entity/entity-type-select/entity-type-select.component.ts @@ -1,4 +1,4 @@ -import { Component, inject, Input } from "@angular/core"; +import { Component, inject, Input, OnInit } from "@angular/core"; import { BASIC_AUTOCOMPLETE_COMPONENT_IMPORTS, BasicAutocompleteComponent, @@ -17,14 +17,20 @@ import { MatFormFieldControl } from "@angular/material/form-field"; { provide: MatFormFieldControl, useExisting: EntityTypeSelectComponent }, ], }) -export class EntityTypeSelectComponent extends BasicAutocompleteComponent< - EntityConstructor, - string -> { +export class EntityTypeSelectComponent + extends BasicAutocompleteComponent + implements OnInit +{ @Input() override multi = false; @Input() override placeholder = $localize`:EntityTypeSelect placeholder:Select Entity Type`; + /** + * whether to include entity types without a human-readable label + * (usually only used internally for technical purposes) + */ + @Input() showInternalTypes: boolean = false; + private entityRegistry = inject(EntityRegistry); override optionToString = (option: EntityConstructor) => option.label; @@ -33,6 +39,7 @@ export class EntityTypeSelectComponent extends BasicAutocompleteComponent< override ngOnInit() { this.options = this.entityRegistry .getEntityTypes(true) + .filter(({ value }) => this.showInternalTypes || !!value.label) .map(({ value }) => value); super.ngOnInit(); diff --git a/src/app/core/entity/model/entity.spec.ts b/src/app/core/entity/model/entity.spec.ts index 4f27e519ec..674a93205f 100644 --- a/src/app/core/entity/model/entity.spec.ts +++ b/src/app/core/entity/model/entity.spec.ts @@ -59,12 +59,14 @@ describe("Entity", () => { expect(otherEntity).toBeInstanceOf(TestEntity); }); - it("should use entity type as default label if none is explicitly configured", () => { + it("should use label as default for labelPlural if none is explicitly configured", () => { @DatabaseEntity("TestEntityForLabel") - class TestEntity extends Entity {} + class TestEntity extends Entity { + static override label = "X"; + } - expect(TestEntity.label).toBe("TestEntityForLabel"); - expect(TestEntity.labelPlural).toBe("TestEntityForLabel"); + expect(TestEntity.label).toBe("X"); + expect(TestEntity.labelPlural).toBe("X"); }); it("should return the route based on entity type name", () => { diff --git a/src/app/core/entity/model/entity.ts b/src/app/core/entity/model/entity.ts index b3de68235b..0b54ad6060 100644 --- a/src/app/core/entity/model/entity.ts +++ b/src/app/core/entity/model/entity.ts @@ -86,15 +86,7 @@ export class Entity { /** * human-readable name/label of the entity in the UI */ - static get label(): string { - return this._label ?? this.ENTITY_TYPE; - } - - static set label(value: string) { - this._label = value; - } - - private static _label: string; + static label: string; /** * human-readable label for uses of plural of the entity in the UI diff --git a/src/app/core/site-settings/site-settings.ts b/src/app/core/site-settings/site-settings.ts index 35be3a3250..df4a4aa9c8 100644 --- a/src/app/core/site-settings/site-settings.ts +++ b/src/app/core/site-settings/site-settings.ts @@ -11,7 +11,6 @@ import { ConfigurableEnumValue } from "../basic-datatypes/configurable-enum/conf @DatabaseEntity("SiteSettings") export class SiteSettings extends Entity { static ENTITY_ID = "global"; - static override label = $localize`Site settings`; static create(value: Partial): SiteSettings { return Object.assign(new SiteSettings(), value); diff --git a/src/app/features/matching-entities/matching-entities/matching-entities.component.spec.ts b/src/app/features/matching-entities/matching-entities/matching-entities.component.spec.ts index a3c2bc19c7..9aa559c57e 100644 --- a/src/app/features/matching-entities/matching-entities/matching-entities.component.spec.ts +++ b/src/app/features/matching-entities/matching-entities/matching-entities.component.spec.ts @@ -228,7 +228,10 @@ describe("MatchingEntitiesComponent", () => { schoolId: testEntity.getId(), childId: matchedEntity.getId(), name: - "ChildSchoolRelation " + testEntity.toString() + " - matched child", + ChildSchoolRelation.label + + " " + + testEntity.toString() + + " - matched child", } as Partial), ); expect(saveSpy).toHaveBeenCalledWith(jasmine.any(ChildSchoolRelation)); diff --git a/src/app/features/public-form/public-form-config.ts b/src/app/features/public-form/public-form-config.ts index 53e2c868b3..31671be288 100644 --- a/src/app/features/public-form/public-form-config.ts +++ b/src/app/features/public-form/public-form-config.ts @@ -10,8 +10,6 @@ import { FieldGroup } from "app/core/entity-details/form/field-group"; */ @DatabaseEntity("PublicFormConfig") export class PublicFormConfig extends Entity { - static override label = $localize`:PublicFormConfig:Public Form`; - static override labelPlural = $localize`:PublicFormConfig:Public Forms`; static override route = "admin/public-form"; static override toStringAttributes = ["title"];