Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

user-editable dropdowns #1661

Merged
merged 93 commits into from
Feb 7, 2023
Merged
Show file tree
Hide file tree
Changes from 92 commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
024fa11
refactor: extract enum dropdown into own component
sleidig Jan 12, 2023
e4545df
Merge branch 'master' into user-conf-enum
sleidig Jan 12, 2023
b9342e2
switch enum dropdown to autocomplete UI and generalize a reusable aut…
sleidig Jan 12, 2023
660c6be
fixed story and component issues
TheSlimvReal Jan 17, 2023
2c5b85b
a new option can be selected in the dropdown
TheSlimvReal Jan 17, 2023
416524e
using specific enum functions whenever an enum is loaded
TheSlimvReal Jan 17, 2023
0c48bee
added ConfigurableEnumService to handle enums synchronously
TheSlimvReal Jan 17, 2023
8f84e86
using new ConfigurableEnumService instead of config service
TheSlimvReal Jan 17, 2023
dadd415
new enum options are saved to DB
TheSlimvReal Jan 17, 2023
611333a
default enums are published as demo data
TheSlimvReal Jan 18, 2023
1cbe020
enums are properly updated in demo mode
TheSlimvReal Jan 18, 2023
ef8f092
making enums permission aware
TheSlimvReal Jan 19, 2023
f0a55a3
added popup for editing enums
TheSlimvReal Jan 19, 2023
3003987
added drag and drop for reordering enums
TheSlimvReal Jan 19, 2023
207cc52
removed cancel and save buttons
TheSlimvReal Jan 19, 2023
ce7ca74
added delete option for enum popup
TheSlimvReal Jan 19, 2023
31e80d9
added icon to indicate reorder functionality
TheSlimvReal Jan 19, 2023
a55b673
dropdown values are correctly reset when pressing cancel
TheSlimvReal Jan 20, 2023
b072aef
fixed stories
TheSlimvReal Jan 23, 2023
5f835ac
refactored structure
TheSlimvReal Jan 23, 2023
9df0ff3
working on multi select
TheSlimvReal Jan 23, 2023
5c186b3
slight tuning of enum popup UI
sleidig Jan 24, 2023
3b59e57
added support for multi select
TheSlimvReal Jan 24, 2023
fc8904e
DisplayConfigurableEnum works with arrays
TheSlimvReal Jan 24, 2023
28ed090
Merge remote-tracking branch 'origin/user-conf-enum' into user-conf-enum
TheSlimvReal Jan 24, 2023
be391fa
Merge remote-tracking branch 'origin/master' into user-conf-enum
TheSlimvReal Jan 25, 2023
5f9d9ed
removed safeguard for configurable enum prefix
TheSlimvReal Jan 26, 2023
acc1280
renamed popup component
TheSlimvReal Jan 26, 2023
ac5cdab
fixed enum saving logic for config service
TheSlimvReal Jan 27, 2023
a3408ef
added logic for showing usage of to-be-deleted enum option
TheSlimvReal Jan 27, 2023
0e19274
removed unnecessary enum prefix
TheSlimvReal Jan 27, 2023
f67703b
replaced save with close button
TheSlimvReal Jan 27, 2023
61222de
tests are runnning
TheSlimvReal Jan 30, 2023
38363b6
added todo for no selected option
TheSlimvReal Jan 30, 2023
e8dc66b
Merge remote-tracking branch 'origin/master' into user-conf-enum
TheSlimvReal Jan 30, 2023
3e2a543
reset input if nothing is selected
TheSlimvReal Jan 30, 2023
132ef84
working with ids instead of object equality
TheSlimvReal Jan 30, 2023
a2b4e84
cleaned up some code
TheSlimvReal Jan 30, 2023
aa2e181
added confirmation dialog for creating a new option
TheSlimvReal Jan 30, 2023
9419941
updated translations
TheSlimvReal Jan 30, 2023
dea782b
fixed a lot of tests
TheSlimvReal Jan 30, 2023
ae8f446
only saving config if something changed
TheSlimvReal Jan 30, 2023
92456c6
Merge branch 'master' into user-conf-enum
TheSlimvReal Jan 30, 2023
7600826
correctly cleaning up after test
TheSlimvReal Jan 31, 2023
d416882
fixed tests for autocomplete component
TheSlimvReal Jan 31, 2023
cc4bf0c
added test for not saving unedited config
TheSlimvReal Jan 31, 2023
09eccdd
got custom form control running
TheSlimvReal Jan 31, 2023
eb62759
basic autocomplete is working
TheSlimvReal Jan 31, 2023
9194354
added caret to parent component
TheSlimvReal Jan 31, 2023
70fe4d4
added additional options
TheSlimvReal Jan 31, 2023
98706c1
keeping focus when dropdown is clicked
TheSlimvReal Jan 31, 2023
e9f5ffa
disabled prettier warning
TheSlimvReal Jan 31, 2023
98486e0
fixed all tests
TheSlimvReal Jan 31, 2023
c12b58c
fixed basic autocomplete component
TheSlimvReal Jan 31, 2023
9b4cb3d
properly triggering changes
TheSlimvReal Feb 1, 2023
02ed9c9
in multi mode, form is cleared on focus in
TheSlimvReal Feb 1, 2023
6ec0e28
improved de-focus and focus of input element
TheSlimvReal Feb 1, 2023
db1bf5a
some refactoring
TheSlimvReal Feb 1, 2023
f11f26b
error state handling works in autocomplete component
TheSlimvReal Feb 2, 2023
a3f23c6
fixed storybook component registry issues
TheSlimvReal Feb 2, 2023
b4621a0
fixed test
TheSlimvReal Feb 2, 2023
5531a58
improved test coverage for basic autocomplete component
TheSlimvReal Feb 2, 2023
ab48336
improved test coverage for enum dropdown component
TheSlimvReal Feb 2, 2023
481460b
fix lint issues
TheSlimvReal Feb 2, 2023
22f003c
new child school relations don't trigger a form conflict due to diffe…
TheSlimvReal Feb 2, 2023
17f6c3a
new child school relations don't trigger a form conflict due to diffe…
TheSlimvReal Feb 2, 2023
8c35e1d
fixed e2e test
TheSlimvReal Feb 2, 2023
27b66d5
fixed autocomplete test
TheSlimvReal Feb 2, 2023
ce4f475
abstracted custom form control logic into abstract class
TheSlimvReal Feb 3, 2023
6fbbb95
merged all groupBy implementations
TheSlimvReal Feb 3, 2023
23ffe25
creating groups with more advanced equality check
TheSlimvReal Feb 3, 2023
0a56e64
Merge branch 'master' into user-conf-enum
TheSlimvReal Feb 3, 2023
ff55721
automatically creating new enum if not available
TheSlimvReal Feb 3, 2023
5660c9f
cleaned up custom form control and basic autocomplete
TheSlimvReal Feb 3, 2023
769e8f0
fixed test
TheSlimvReal Feb 3, 2023
48de6de
Merge branch 'master' into user-conf-enum
TheSlimvReal Feb 3, 2023
88c9205
increased timeout for e2e test
TheSlimvReal Feb 3, 2023
71f6939
Merge remote-tracking branch 'origin/user-conf-enum' into user-conf-enum
TheSlimvReal Feb 3, 2023
1865881
increased timeout for e2e test
TheSlimvReal Feb 3, 2023
2da97b8
improve waiting for demo data generation
TheSlimvReal Feb 3, 2023
0f3a9d6
Update src/app/core/configurable-enum/basic-autocomplete/basic-autoco…
TheSlimvReal Feb 6, 2023
2143048
Update src/app/core/configurable-enum/configure-enum-popup/configure-…
TheSlimvReal Feb 6, 2023
2906752
Update src/app/core/configurable-enum/configure-enum-popup/configure-…
TheSlimvReal Feb 6, 2023
84ae179
properly detecting which enums already exist and which not
TheSlimvReal Feb 6, 2023
2dc0a6a
improved test readability
TheSlimvReal Feb 6, 2023
5a526a1
fixed typo
TheSlimvReal Feb 6, 2023
6abdca3
in multi mode configurable enums are also shown with their color
TheSlimvReal Feb 6, 2023
ceacb16
config services checks permissions before updating saving config
TheSlimvReal Feb 6, 2023
7e5b24f
Merge remote-tracking branch 'origin/master' into user-conf-enum
TheSlimvReal Feb 6, 2023
34e760d
fixed test
TheSlimvReal Feb 6, 2023
0cfdba8
onChange is executed when after creating a new option
TheSlimvReal Feb 7, 2023
0df462a
undone temporary config changes
TheSlimvReal Feb 7, 2023
4f0afc2
Merge branch 'master' into user-conf-enum
TheSlimvReal Feb 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
sleidig marked this conversation as resolved.
Show resolved Hide resolved
.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