Skip to content

Commit

Permalink
fix(admin-ui): correctly undo entity core field changes (#2169)
Browse files Browse the repository at this point in the history
fixes #2165
  • Loading branch information
sleidig authored Jan 10, 2024
1 parent cbdddd9 commit 3c4b653
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 2 deletions.
27 changes: 27 additions & 0 deletions src/app/core/entity/entity-config.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { EntityMapperService } from "./entity-mapper/entity-mapper.service";
import { mockEntityMapper } from "./entity-mapper/mock-entity-mapper-service";
import { EntityConfig } from "./entity-config";
import { EntitySchemaField } from "./schema/entity-schema-field";
import { Child } from "../../child-dev-project/children/model/child";

describe("EntityConfigService", () => {
let service: EntityConfigService;
Expand Down Expand Up @@ -82,6 +83,32 @@ describe("EntityConfigService", () => {
expect(Test2.schema).toHaveKey(ATTRIBUTE_2_NAME);
});

it("should reset attribute to basic class config if custom attribute disappears from config doc", () => {
const originalLabel = Child.schema.get("name").label;
const customLabel = "custom label";

const mockEntityConfigs: (EntityConfig & { _id: string })[] = [
{
_id: "entity:Child",
attributes: { name: { label: customLabel } },
},
];
mockConfigService.getAllConfigs.and.returnValue(mockEntityConfigs);
service.setupEntitiesFromConfig();
expect(Child.schema.get("name").label).toEqual(customLabel);

mockConfigService.getAllConfigs.and.returnValue([
{
_id: "entity:Child",
attributes: {
/* undo custom label */
},
},
]);
service.setupEntitiesFromConfig();
expect(Child.schema.get("name").label).toEqual(originalLabel);
});

it("should allow to configure the `.toString` method", () => {
mockConfigService.getAllConfigs.and.returnValue([
{ _id: "entity:Test", toStringAttributes: ["name", "entityId"] },
Expand Down
47 changes: 45 additions & 2 deletions src/app/core/entity/entity-config.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { IconName } from "@fortawesome/fontawesome-svg-core";
import { EntityConfig } from "./entity-config";
import { addPropertySchema } from "./database-field.decorator";
import { PREFIX_VIEW_CONFIG } from "../config/dynamic-routing/view-config.interface";
import { EntitySchemaField } from "./schema/entity-schema-field";
import { EntitySchema } from "./schema/entity-schema";

/**
* A service that allows to work with configuration-objects
Expand All @@ -19,6 +21,9 @@ export class EntityConfigService {
/** @deprecated will become private, use the service to access the data */
static readonly PREFIX_ENTITY_CONFIG = "entity:";

/** original initial entity schemas without overrides from config */
private coreEntitySchemas = new Map<string, EntitySchema>();

static getDetailsViewId(entityConstructor: EntityConstructor) {
return (
PREFIX_VIEW_CONFIG + entityConstructor.route.replace(/^\//, "") + "/:id"
Expand All @@ -30,7 +35,21 @@ export class EntityConfigService {
constructor(
private configService: ConfigService,
private entities: EntityRegistry,
) {}
) {
this.storeCoreEntitySchemas();
}

private storeCoreEntitySchemas() {
this.entities.forEach((ctr, key) => {
this.coreEntitySchemas.set(key, this.deepCopySchema(ctr.schema));
});
}

private deepCopySchema(schema: EntitySchema): EntitySchema {
return new Map<string, EntitySchemaField>(
JSON.parse(JSON.stringify(Array.from(schema))),
);
}

/**
* Assigns additional schema-fields to all entities that are
Expand All @@ -49,6 +68,7 @@ export class EntityConfigService {
this.createNewEntity(id, config.extends);
}
const ctor = this.entities.get(id);
this.setCoreSchemaAttributes(ctor, config.extends);
this.addConfigAttributes(ctor, config);
}
}
Expand All @@ -58,14 +78,37 @@ export class EntityConfigService {
? this.entities.get(parent)
: Entity;

const schema = this.deepCopySchema(parentClass.schema);
class DynamicClass extends parentClass {
static schema = new Map(parentClass.schema.entries());
static schema = schema;
static ENTITY_TYPE = id;
}

this.entities.set(id, DynamicClass);
}

/**
* Set field definitons from the core schema to ensure undoing customized attributes is correctly applied.
* @param entityType
* @param parent
*/
private setCoreSchemaAttributes(
entityType: EntityConstructor,
parent: string,
) {
const coreEntityId = parent ?? entityType.ENTITY_TYPE;
const coreSchema =
this.coreEntitySchemas.get(coreEntityId) ?? Entity.schema;

for (const [key, value] of coreSchema.entries()) {
addPropertySchema(
entityType.prototype,
key,
JSON.parse(JSON.stringify(value)),
);
}
}

/**
* Appends the given (dynamic) attributes to the schema of the provided Entity.
* If no arguments are provided, they will be loaded from the config
Expand Down

0 comments on commit 3c4b653

Please sign in to comment.