Skip to content

Commit

Permalink
feat: user-editable dropdowns (#1661)
Browse files Browse the repository at this point in the history
closes #1642

This functionality has been developed for the project “QualitätsMENTOR”.
QualitätsMENTOR is developed under the projects “Landungsbrücken – Patenschaften in Hamburg stärken” and “openTransfer Patenschaften”. It is funded through the program “Menschen stärken Menschen” by the German Federal Ministry of Family Affairs, Senior Citizens, Women and Youth.
More information at https://github.com/qualitaetsmentor

“Landungsbrücken – Patenschaften in Hamburg stärken” is a project of BürgerStiftung Hamburg in cooperation with the Mentor.Ring Hamburg. With a mix of networking opportunities, capacity building and financial support the project strengthens Hamburg’s scene of mentoring projects since its founding in 2016.

The “Stiftung Bürgermut” foundation since 2007 supports the digital and real exchange of experiences and connections of active citizens. Within the federal program “Menschen stärken Menschen” the foundation as part of its program “openTransfer Patenschaften” offers support services for connecting, spreading and upskilling mentoring organisations across Germany. 

Diese Funktion wurde entwickelt für das Projekt QualitätsMENTOR.
Der QualitätsMENTOR wird entwickelt im Rahmen der Projekte Landungsbrücken – Patenschaften in Hamburg stärken und openTransfer Patenschaften. Er ist gefördert durch das Bundesprogramm Menschen stärken Menschen des Bundesministeriums für Familie, Senioren, Frauen und Jugend.
Mehr Informationen unter https://github.com/qualitaetsmentor

“Landungsbrücken – Patenschaften in Hamburg stärken” ist ein Projekt der BürgerStiftung Hamburg in Kooperation mit dem Mentor.Ring Hamburg. Mit einer Mischung aus Vernetzungsangeboten, Qualifizierungsmaßnahmen und finanzieller Förderung stärkt das Projekt die Hamburger Szene der Patenschaftsprojekte seit der Gründung im Jahr 2016.

Die Stiftung Bürgermut fördert seit 2007 den digitalen und realen Erfahrungsaustausch und die Vernetzung von engagierten Bürger:innen. Innerhalb des Bundesprogramms „Menschen stärken Menschen” bietet die Stiftung im Rahmen ihres Programms openTransfer Patenschaften Unterstützungsleistungen zur Vernetzung, Verbreitung und Qualifizierung von Patenschafts- und Mentoringorganisationen bundesweit.

Co-authored-by: QualitaetsMENTOR <117934638+QualitaetsMENTOR@users.noreply.github.com>
Co-authored-by: Simon <simon@aam-digital.com>
  • Loading branch information
3 people authored Feb 7, 2023
1 parent 8b4067f commit 5ff22b6
Show file tree
Hide file tree
Showing 81 changed files with 2,804 additions and 1,588 deletions.
6 changes: 3 additions & 3 deletions e2e/integration/LinkingChildToSchool.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ describe("Scenario: Linking a child to a school - E2E test", function () {
.click();

// choose the school to add
cy.get('[ng-reflect-placeholder="Select School"]')
.type("E2E School", { force: true })
.click();
cy.contains("mat-form-field", "School")
.find("[matInput]")
.type("E2E School{enter}");

// save school in child profile
cy.contains("button", "Save").click({ force: true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
import { RollCallComponent } from "./roll-call.component";
import { Note } from "../../../notes/model/note";
import { By } from "@angular/platform-browser";
import { ConfigService } from "../../../../core/config/config.service";
import { Child } from "../../../children/model/child";
import { LoggingService } from "../../../../core/logging/logging.service";
import { MockedTestingModule } from "../../../../utils/mocked-testing.module";
Expand All @@ -18,6 +17,7 @@ import { LoginState } from "../../../../core/session/session-states/login-state.
import { SimpleChange } from "@angular/core";
import { AttendanceLogicalStatus } from "../../model/attendance-status";
import { ChildrenService } from "../../../children/children.service";
import { ConfigurableEnumService } from "../../../../core/configurable-enum/configurable-enum.service";

const PRESENT = {
id: "PRESENT",
Expand Down Expand Up @@ -82,8 +82,8 @@ describe("RollCallComponent", () => {

it("should display all available attendance status to select", async () => {
const options = [PRESENT, ABSENT];
const configService = TestBed.inject(ConfigService);
spyOn(configService, "getConfigurableEnumValues").and.returnValue(options);
const enumService = TestBed.inject(ConfigurableEnumService);
spyOn(enumService, "getEnumValues").and.returnValue(options);
component.eventEntity.addChild(participant1);
await component.ngOnChanges(dummyChanges);
fixture.detectChanges();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
} from "../../model/attendance-status";
import { Note } from "../../../notes/model/note";
import { EventAttendance } from "../../model/event-attendance";
import { ConfigService } from "../../../../core/config/config.service";
import { EntityMapperService } from "../../../../core/entity/entity-mapper.service";
import { Child } from "../../../children/model/child";
import { LoggingService } from "../../../../core/logging/logging.service";
Expand All @@ -32,6 +31,7 @@ import {
HammerModule,
} from "@angular/platform-browser";
import Hammer from "hammerjs";
import { ConfigurableEnumService } from "../../../../core/configurable-enum/configurable-enum.service";

// Only allow horizontal swiping
class HorizontalHammerConfig extends HammerGestureConfig {
Expand Down Expand Up @@ -114,7 +114,7 @@ export class RollCallComponent implements OnChanges {
children: Child[] = [];

constructor(
private configService: ConfigService,
private enumService: ConfigurableEnumService,
private entityMapper: EntityMapperService,
private formDialog: FormDialogService,
private loggingService: LoggingService
Expand Down Expand Up @@ -156,10 +156,9 @@ export class RollCallComponent implements OnChanges {
}

private loadAttendanceStatusTypes() {
this.availableStatus =
this.configService.getConfigurableEnumValues<AttendanceStatusType>(
ATTENDANCE_STATUS_CONFIG_ID
);
this.availableStatus = this.enumService.getEnumValues<AttendanceStatusType>(
ATTENDANCE_STATUS_CONFIG_ID
);
}

private async loadParticipants() {
Expand Down
7 changes: 2 additions & 5 deletions src/app/child-dev-project/attendance/attendance.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ export class AttendanceService {
sinceDate?: Date
): Promise<ActivityAttendance[]> {
const periods = new Map<number, ActivityAttendance>();

function getOrCreateAttendancePeriod(event) {
const month = new Date(event.date.getFullYear(), event.date.getMonth());
let attMonth = periods.get(month.getTime());
Expand Down Expand Up @@ -192,11 +193,7 @@ export class AttendanceService {
until: Date
): Promise<ActivityAttendance[]> {
const matchingEvents = await this.getEventsOnDate(from, until);

const groupedEvents: Map<string, EventNote[]> = groupBy(
matchingEvents,
"relatesTo"
);
const groupedEvents = groupBy(matchingEvents, "relatesTo");

const records = [];
for (const [activityId, activityEvents] of groupedEvents) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,10 @@ export class AttendanceWeekDashboardComponent
.forEach((r) => lowAttendanceCases.add(r.childId));
}

const groupedRecords = groupBy(records, "childId");
this.tableDataSource.data = Array.from(lowAttendanceCases.values()).map(
(childId) => groupedRecords.get(childId)
);
const groups = groupBy(records, "childId");
this.tableDataSource.data = groups
.filter(([childId]) => lowAttendanceCases.has(childId))
.map(([_, attendance]) => attendance);
this.loadingDone = true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,8 @@ export class ChildrenBmiDashboardComponent
async loadBMIData() {
// Maybe replace this by a smart index function
const healthChecks = await this.entityMapper.loadType(HealthCheck);
const healthCheckMap = groupBy(healthChecks, "child");
const BMIs: BmiRow[] = [];
healthCheckMap.forEach((checks, childId) => {
groupBy(healthChecks, "child").forEach(([childId, checks]) => {
const latest = checks.reduce((prev, cur) =>
cur.date > prev.date ? cur : prev
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { Angulartics2Module } from "angulartics2";
import { DashboardWidgetComponent } from "../../../../core/dashboard/dashboard-widget/dashboard-widget.component";
import { WidgetContentComponent } from "../../../../core/dashboard/dashboard-widget/widget-content/widget-content.component";
import { groupBy } from "../../../../utils/utils";

@DynamicComponent("ChildrenCountDashboard")
@DynamicComponent("EntityCountDashboard")
Expand Down Expand Up @@ -63,7 +64,7 @@ export class EntityCountDashboardComponent

async ngOnInit() {
const entities = await this.entityMapper.loadType(this.entity);
this.updateCounts(entities);
this.updateCounts(entities.filter((e) => e.isActive));
}

goToChildrenList(filterId: string) {
Expand All @@ -74,31 +75,16 @@ export class EntityCountDashboardComponent
}

private updateCounts(entities: Entity[]) {
this.totalEntities = 0;

const countMap = new Map<any, number>();
entities.forEach((entity) => {
if (entity.isActive) {
let count = countMap.get(entity[this.groupBy]);
if (count === undefined) {
count = 0;
}

count++;
this.totalEntities++;
countMap.set(entity[this.groupBy], count);
}
this.totalEntities = entities.length;
const groups = groupBy(entities, this.groupBy as keyof Entity);
this.entityGroupCounts = groups.map(([group, entities]) => {
const label = extractHumanReadableLabel(group);
return {
label: label,
value: entities.length,
id: group?.["id"] || label,
};
});

this.entityGroupCounts = Array.from(countMap.entries()) // direct use of Map creates change detection problems
.map((entry) => {
const label = extractHumanReadableLabel(entry[0]);
return {
label: label,
value: entry[1],
id: entry[0]?.id || label,
};
});
this.loading = false;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { Center } from "../../model/child";

export const centersWithProbability: Array<Center> = [
// multiple entries for the same value increase its probability
{ id: "alipore", label: $localize`:center:Alipore` },
export const centersUnique: Center[] = [
{ id: "alipore", label: $localize`:center:Alipore` },
{ id: "tollygunge", label: $localize`:center:Tollygunge` },
{ id: "barabazar", label: $localize`:center:Barabazar` },
];

export const centersUnique = centersWithProbability.filter(
(value, index, self) => self.indexOf(value) === index
);
// multiple entries for the same value increase its probability
export const centersWithProbability = [0, 0, 1, 2].map((i) => centersUnique[i]);
4 changes: 2 additions & 2 deletions src/app/child-dev-project/notes/model/note.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
import { testEntitySubclass } from "../../../core/entity/model/entity.spec";
import { defaultInteractionTypes } from "../../../core/config/default-config/default-interaction-types";
import { Ordering } from "../../../core/configurable-enum/configurable-enum-ordering";
import { createTestingConfigService } from "../../../core/config/testing-config-service";
import { createTestingConfigurableEnumService } from "../../../core/configurable-enum/configurable-enum-testing";

const testStatusTypes: ConfigurableEnumConfig<AttendanceStatusType> = [
{
Expand Down Expand Up @@ -86,7 +86,7 @@ describe("Note", () => {

entitySchemaService = new EntitySchemaService();
entitySchemaService.registerSchemaDatatype(
new ConfigurableEnumDatatype(createTestingConfigService(testConfigs))
new ConfigurableEnumDatatype(createTestingConfigurableEnumService())
);
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe("NoteDetailsComponent", () => {
let children: Child[];
let testNote: Note;

beforeEach(() => {
beforeEach(async () => {
children = [new Child("1"), new Child("2"), new Child("3")];
testNote = generateTestNote(children);

Expand All @@ -46,7 +46,7 @@ describe("NoteDetailsComponent", () => {

const dialogRefMock = { beforeClosed: () => EMPTY, close: () => {} };

TestBed.configureTestingModule({
await TestBed.configureTestingModule({
imports: [
NoteDetailsComponent,
MockedTestingModule.withState(LoginState.LOGGED_IN, children),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export class ChildSchoolOverviewComponent
newRelation.start =
this.allRecords.length && this.allRecords[0].end
? moment(this.allRecords[0].end).add(1, "day").toDate()
: new Date();
: moment().startOf("day").toDate();
} else if (mode === "school") {
newRelation.schoolId = entityId;
}
Expand Down
1 change: 1 addition & 0 deletions src/app/core/config-setup/config-import-parser.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export class ConfigImportParserService {
"appConfig:usage-analytics",
"navigationMenu",
"view:",
// TODO what do we do with these?
"enum:interaction-type",
"enum:warning-levels",
"view:note",
Expand Down
Loading

0 comments on commit 5ff22b6

Please sign in to comment.