Skip to content

Commit

Permalink
fix: Educational material summary updates automatically (#1250)
Browse files Browse the repository at this point in the history
fixes #1239
  • Loading branch information
TheSlimvReal authored May 5, 2022
1 parent 7921328 commit 8d7b6c5
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 28 deletions.
8 changes: 0 additions & 8 deletions src/app/child-dev-project/children/children.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { from, Observable, Subject } from "rxjs";
import { Child } from "./model/child";
import { EntityMapperService } from "../../core/entity/entity-mapper.service";
import { Note } from "../notes/model/note";
import { EducationalMaterial } from "./educational-material/model/educational-material";
import { Aser } from "./aser/model/aser";
import { ChildSchoolRelation } from "./model/childSchoolRelation";
import { HealthCheck } from "./health-checkup/model/health-check";
Expand Down Expand Up @@ -240,13 +239,6 @@ export class ChildrenService {
return this.dbIndexing.createIndex(designDoc);
}

async getEducationalMaterialsOfChild(
childId: string
): Promise<EducationalMaterial[]> {
const allMaterials = await this.entityMapper.loadType(EducationalMaterial);
return allMaterials.filter((mat) => mat.child === childId);
}

/**
*
* @param childId should be set in the specific components and is passed by the URL as a parameter
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing";

import { EducationalMaterialComponent } from "./educational-material.component";
import { ChildrenService } from "../../children.service";
import { Child } from "../../model/child";
import { ChildrenModule } from "../../children.module";
import { MockedTestingModule } from "../../../../utils/mocked-testing.module";
import { EducationalMaterial } from "../model/educational-material";
import { ConfigurableEnumValue } from "../../../../core/configurable-enum/configurable-enum.interface";
import { EntityMapperService } from "../../../../core/entity/entity-mapper.service";
import { Subject } from "rxjs";
import { UpdatedEntity } from "../../../../core/entity/model/entity-update";

describe("EducationalMaterialComponent", () => {
let component: EducationalMaterialComponent;
let fixture: ComponentFixture<EducationalMaterialComponent>;
let mockChildrenService: jasmine.SpyObj<ChildrenService>;
const updates = new Subject<UpdatedEntity<EducationalMaterial>>();
const child = new Child("22");
const PENCIL: ConfigurableEnumValue = {
id: "pencil",
Expand All @@ -24,15 +26,11 @@ describe("EducationalMaterialComponent", () => {

beforeEach(
waitForAsync(() => {
mockChildrenService = jasmine.createSpyObj([
"getEducationalMaterialsOfChild",
]);
TestBed.configureTestingModule({
imports: [ChildrenModule, MockedTestingModule.withState()],
providers: [
{ provide: ChildrenService, useValue: mockChildrenService },
],
}).compileComponents();
const entityMapper = TestBed.inject(EntityMapperService);
spyOn(entityMapper, "receiveUpdates").and.returnValue(updates);
})
);

Expand Down Expand Up @@ -84,10 +82,10 @@ describe("EducationalMaterialComponent", () => {

it("loads all education data associated with a child and updates the summary", async () => {
const educationalData = [
{ materialType: PENCIL, materialAmount: 1 },
{ materialType: RULER, materialAmount: 2 },
{ materialType: PENCIL, materialAmount: 1, child: child.getId() },
{ materialType: RULER, materialAmount: 2, child: child.getId() },
].map(EducationalMaterial.create);
mockChildrenService.getEducationalMaterialsOfChild.and.resolveTo(
spyOn(TestBed.inject(EntityMapperService), "loadType").and.resolveTo(
educationalData
);
await component.loadData("22");
Expand All @@ -96,8 +94,33 @@ describe("EducationalMaterialComponent", () => {
});

it("associates a new record with the current child", () => {
component.child = child;
const newRecord = component.newRecordFactory();
expect(newRecord.child).toBe(child.getId());
});

it("should update the summary when entity updates are received", async () => {
const update1 = EducationalMaterial.create({
child: child.getId(),
materialType: PENCIL,
materialAmount: 1,
});
updates.next({ entity: update1, type: "new" });

expect(component.records).toEqual([update1]);
expect(component.summary).toBe(`${PENCIL.label}: 1`);

const update2 = update1.copy() as EducationalMaterial;
update2.materialAmount = 2;
updates.next({ entity: update2, type: "update" });

expect(component.records).toEqual([update2]);
expect(component.summary).toBe(`${PENCIL.label}: 2`);

const unrelatedUpdate = update1.copy() as EducationalMaterial;
unrelatedUpdate.child = "differentChild";
updates.next({ entity: unrelatedUpdate, type: "new" });
// No change
expect(component.records).toEqual([update2]);
expect(component.summary).toBe(`${PENCIL.label}: 2`);
});
});
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import { Component, Input, OnChanges, SimpleChanges } from "@angular/core";
import { EducationalMaterial } from "../model/educational-material";
import { ChildrenService } from "../../children.service";
import { Child } from "../../model/child";
import { OnInitDynamicComponent } from "../../../../core/view/dynamic-components/on-init-dynamic-component.interface";
import { PanelConfig } from "../../../../core/entity-components/entity-details/EntityDetailsConfig";
import { FormFieldConfig } from "../../../../core/entity-components/entity-form/entity-form/FormConfig";
import { DynamicComponent } from "../../../../core/view/dynamic-components/dynamic-component.decorator";
import { EntityMapperService } from "../../../../core/entity/entity-mapper.service";
import { applyUpdate } from "../../../../core/entity/model/entity-update";
import { filter } from "rxjs/operators";
import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";

/**
* Displays educational materials of a child, such as a pencil, rulers, e.t.c
* as well as a summary
*/
@DynamicComponent("EducationalMaterial")
@UntilDestroy()
@Component({
selector: "app-educational-material",
templateUrl: "./educational-material.component.html",
Expand All @@ -29,7 +33,21 @@ export class EducationalMaterialComponent
{ id: "description", visibleFrom: "md" },
];

constructor(private childrenService: ChildrenService) {}
constructor(private entityMapper: EntityMapperService) {
this.entityMapper
.receiveUpdates(EducationalMaterial)
.pipe(
untilDestroyed(this),
filter(
({ entity, type }) =>
type === "remove" || entity.child === this.child.getId()
)
)
.subscribe((update) => {
this.records = applyUpdate(this.records, update);
this.updateSummary();
});
}

async ngOnChanges(changes: SimpleChanges): Promise<void> {
if (changes.hasOwnProperty("child")) {
Expand All @@ -51,9 +69,8 @@ export class EducationalMaterialComponent
* @param id The id of the child to load the data for
*/
async loadData(id: string) {
this.records = await this.childrenService.getEducationalMaterialsOfChild(
id
);
const allMaterials = await this.entityMapper.loadType(EducationalMaterial);
this.records = allMaterials.filter((mat) => mat.child === id);
this.updateSummary();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@ describe("HealthCheckupComponent", () => {
waitForAsync(() => {
mockChildrenService = jasmine.createSpyObj([
"getChild",
"getEducationalMaterialsOfChild",
"getHealthChecksOfChild",
]);
mockChildrenService.getChild.and.returnValue(of(child));
mockChildrenService.getEducationalMaterialsOfChild.and.resolveTo([]);
mockChildrenService.getHealthChecksOfChild.and.returnValue(of([]));

TestBed.configureTestingModule({
Expand Down
2 changes: 1 addition & 1 deletion src/app/core/entity/model/entity-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export interface UpdatedEntity<T extends Entity> {
export function applyUpdate<T extends Entity>(
entities: T[],
next: UpdatedEntity<T>
) {
): T[] {
if (!next || !next.entity) {
return entities;
}
Expand Down

0 comments on commit 8d7b6c5

Please sign in to comment.