Skip to content

Commit a89c021

Browse files
authored
Merge pull request #180 from openscript-ch/7-implement-basic-calendar-view-date-navigation-time-slots
7 implement basic calendar view date navigation time slots
2 parents d1deb84 + a6f7cc4 commit a89c021

File tree

27 files changed

+692
-148
lines changed

27 files changed

+692
-148
lines changed

apps/backend/db/migrations/.snapshot-postgres.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -481,8 +481,8 @@
481481
},
482482
{
483483
"name": "entry_weekly_recurring_check",
484-
"expression": "weekday >= 1",
485-
"definition": "check ((weekday >= 1))",
484+
"expression": "weekly_recurring >= 1",
485+
"definition": "check ((weekly_recurring >= 1))",
486486
"columnName": "weekly_recurring"
487487
}
488488
],
@@ -558,7 +558,7 @@
558558
"unsigned": false,
559559
"autoincrement": false,
560560
"primary": false,
561-
"nullable": false,
561+
"nullable": true,
562562
"mappedType": "integer"
563563
}
564564
},
@@ -607,6 +607,7 @@
607607
"id"
608608
],
609609
"referencedTableName": "public.entry",
610+
"deleteRule": "cascade",
610611
"updateRule": "cascade"
611612
}
612613
},
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Migration } from "@mikro-orm/migrations";
2+
3+
export class Migration20241209144817 extends Migration {
4+
override async up(): Promise<void> {
5+
this.addSql(`alter table "entry" drop constraint entry_weekly_recurring_check;`);
6+
7+
this.addSql(`alter table "entry" add constraint entry_weekly_recurring_check check(weekly_recurring >= 1);`);
8+
}
9+
10+
override async down(): Promise<void> {
11+
this.addSql(`alter table "entry" drop constraint entry_weekly_recurring_check;`);
12+
13+
this.addSql(`alter table "entry" add constraint entry_weekly_recurring_check check(weekday >= 1);`);
14+
}
15+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Migration } from "@mikro-orm/migrations";
2+
3+
export class Migration20241210094456 extends Migration {
4+
override async up(): Promise<void> {
5+
this.addSql(`alter table "entry_language" drop constraint "entry_language_entry_id_foreign";`);
6+
7+
this.addSql(`alter table "entry_language" alter column "entry_id" type int using ("entry_id"::int);`);
8+
this.addSql(`alter table "entry_language" alter column "entry_id" drop not null;`);
9+
this.addSql(
10+
`alter table "entry_language" add constraint "entry_language_entry_id_foreign" foreign key ("entry_id") references "entry" ("id") on update cascade on delete cascade;`
11+
);
12+
}
13+
14+
override async down(): Promise<void> {
15+
this.addSql(`alter table "entry_language" drop constraint "entry_language_entry_id_foreign";`);
16+
17+
this.addSql(`alter table "entry_language" alter column "entry_id" type int using ("entry_id"::int);`);
18+
this.addSql(`alter table "entry_language" alter column "entry_id" set not null;`);
19+
this.addSql(
20+
`alter table "entry_language" add constraint "entry_language_entry_id_foreign" foreign key ("entry_id") references "entry" ("id") on update cascade;`
21+
);
22+
}
23+
}

apps/backend/src/research/entries/entries.service.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export class EntriesService {
1414

1515
async create(entryCreationDto: EntryCreationDto) {
1616
const entry = new Entry();
17-
entry.assign(entryCreationDto);
17+
entry.assign(entryCreationDto, { em: this.em });
1818

1919
try {
2020
await this.em.persist(entry).flush();
@@ -25,23 +25,23 @@ export class EntriesService {
2525
throw e;
2626
}
2727

28-
return entry.toObject();
28+
return (await entry.populate(["entryLanguages"])).toObject();
2929
}
3030

3131
async findAll() {
32-
return (await this.entryRepository.findAll()).map((entry) => entry.toObject());
32+
return (await this.entryRepository.findAll({ populate: ["entryLanguages"] })).map((entry) => entry.toObject());
3333
}
3434

3535
async findOne(id: number) {
36-
return (await this.entryRepository.findOneOrFail(id)).toObject();
36+
return (await this.entryRepository.findOneOrFail(id, { populate: ["entryLanguages"] })).toObject();
3737
}
3838

3939
async findBy(filter: FilterQuery<Entry>) {
40-
return (await this.entryRepository.findOneOrFail(filter)).toObject();
40+
return (await this.entryRepository.findOneOrFail(filter, { populate: ["entryLanguages"] })).toObject();
4141
}
4242

4343
async update(id: number, entryMutationDto: EntryMutationDto) {
44-
const entry = await this.entryRepository.findOneOrFail(id);
44+
const entry = await this.entryRepository.findOneOrFail(id, { populate: ["entryLanguages"] });
4545

4646
entry.assign(entryMutationDto);
4747

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import { ApiProperty, OmitType, PartialType } from "@nestjs/swagger";
22
import { Type } from "class-transformer";
3-
import { IsOptional, IsDate, Min, Max } from "class-validator";
4-
import { QuestionnaireDto } from "../questionnaires/questionnaire.dto";
3+
import { IsOptional, Min, Max, IsMilitaryTime } from "class-validator";
54
import { CarerDto } from "../../defaults/carers/carer.dto";
5+
import { EntryQuestionnaireDto, QuestionnaireDto } from "../questionnaires/questionnaire.dto";
6+
import { EntryLanguageCreationDto, EntryLanguageResponseDto } from "../entry-languages/entry-language.dto";
67

78
export class EntryDto {
89
@ApiProperty({ example: 1, description: "The id of the entry" })
910
id: number;
1011

1112
@ApiProperty({ example: "2024-11-01T07:00:00.000Z", description: "The starting date of the entry" })
12-
@IsDate()
13+
@IsMilitaryTime()
1314
startedAt: string;
1415

1516
@ApiProperty({ example: "2024-11-01T08:00:00.00Z", description: "The ending date of the entry" })
16-
@IsDate()
17+
@IsMilitaryTime()
1718
endedAt: string;
1819

1920
@ApiProperty({ example: 1, description: "The weekday of the entry (Sunday is 0 like in JS)" })
@@ -27,14 +28,21 @@ export class EntryDto {
2728
weeklyRecurring?: number;
2829

2930
@Type(() => QuestionnaireDto)
30-
questionnaire: QuestionnaireDto;
31+
questionnaire: EntryQuestionnaireDto;
3132

3233
@Type(() => CarerDto)
3334
carer: CarerDto;
3435

35-
@Type(() => Array<number>)
36-
entryLanguages: number[];
36+
@Type(() => Array<EntryLanguageResponseDto>)
37+
entryLanguages: Array<EntryLanguageResponseDto>;
3738
}
3839
export class EntryResponseDto extends EntryDto {}
39-
export class EntryCreationDto extends OmitType(EntryDto, ["id"]) {}
40+
export class QuestionnaireEntryDto extends OmitType(EntryDto, ["questionnaire"]) {}
41+
export class EntryCreationDto extends OmitType(EntryDto, ["id", "carer", "questionnaire", "entryLanguages"]) {
42+
carer: number;
43+
questionnaire: number;
44+
45+
@Type(() => EntryLanguageCreationDto)
46+
entryLanguages: Array<EntryLanguageCreationDto>;
47+
}
4048
export class EntryMutationDto extends PartialType(EntryCreationDto) {}

apps/backend/src/research/entries/entry.entity.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export class Entry extends BaseEntity {
2020
weekday!: number;
2121

2222
@Property({ default: 1, columnType: "smallint" })
23-
@Check<Entry>({ expression: (columns) => `${columns.weekday} >= 1` })
23+
@Check<Entry>({ expression: (columns) => `${columns.weeklyRecurring} >= 1` })
2424
weeklyRecurring!: number & Opt;
2525

2626
@ManyToOne()
@@ -29,6 +29,6 @@ export class Entry extends BaseEntity {
2929
@ManyToOne()
3030
carer!: Carer;
3131

32-
@OneToMany(() => EntryLanguage, (entryLanguage) => entryLanguage.entry)
32+
@OneToMany(() => EntryLanguage, (entryLanguage) => entryLanguage.entry, { orphanRemoval: true })
3333
entryLanguages = new Collection<EntryLanguage>(this);
3434
}
Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { ApiProperty, OmitType, PartialType } from "@nestjs/swagger";
1+
import { ApiProperty, OmitType } from "@nestjs/swagger";
22
import { Type } from "class-transformer";
33
import { Min, Max } from "class-validator";
44
import { LanguageDto } from "../../defaults/languages/language.dto";
5-
import { EntryDto } from "../entries/entry.dto";
5+
import { QuestionnaireEntryDto } from "../entries/entry.dto";
66

77
export class EntryLanguageDto {
88
@ApiProperty({ example: 1, description: "The id of the entry language" })
@@ -16,9 +16,12 @@ export class EntryLanguageDto {
1616
@Type(() => LanguageDto)
1717
language: LanguageDto;
1818

19-
@Type(() => EntryDto)
20-
entry: EntryDto;
19+
@Type(() => QuestionnaireEntryDto)
20+
entry: QuestionnaireEntryDto;
2121
}
22-
export class EntryLanguageResponseDto extends EntryLanguageDto {}
23-
export class EntryLanguageCreationDto extends OmitType(EntryLanguageDto, ["id"]) {}
24-
export class EntryLanguageMutationDto extends PartialType(EntryLanguageCreationDto) {}
22+
export class EntryLanguageResponseDto extends OmitType(EntryLanguageDto, ["entry"]) {}
23+
export class EntryLanguageMutationDto extends OmitType(EntryLanguageDto, ["id", "entry", "language"]) {
24+
id?: number;
25+
language?: number;
26+
}
27+
export class EntryLanguageCreationDto extends OmitType(EntryLanguageMutationDto, ["id"]) {}

apps/backend/src/research/entry-languages/entry-language.entity.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Check, Entity, ManyToOne, Property } from "@mikro-orm/core";
1+
import { Cascade, Check, Entity, ManyToOne, Property } from "@mikro-orm/core";
22
import { BaseEntity } from "../../common/entities/base.entity";
33
import { Language } from "../../defaults/languages/language.entity";
44
import { Entry } from "../entries/entry.entity";
@@ -12,6 +12,6 @@ export class EntryLanguage extends BaseEntity {
1212
@ManyToOne()
1313
language!: Language;
1414

15-
@ManyToOne()
15+
@ManyToOne({ cascade: [Cascade.ALL] })
1616
entry!: Entry;
1717
}

apps/backend/src/research/questionnaires/questionnaire.dto.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Type } from "class-transformer";
33
import { IsDateString, IsNotEmpty } from "class-validator";
44
import { ParticipantDto } from "../participants/participant.dto";
55
import { StudyDto } from "../studies/study.dto";
6+
import { QuestionnaireEntryDto } from "../entries/entry.dto";
67

78
export class QuestionnaireDto {
89
@ApiProperty({ example: 1, description: "The id of the questionnaire" })
@@ -29,10 +30,12 @@ export class QuestionnaireDto {
2930
@Type(() => ParticipantDto)
3031
participant?: ParticipantDto;
3132

32-
@Type(() => Array<number>)
33-
entries?: number[];
33+
@Type(() => Array<QuestionnaireEntryDto>)
34+
entries?: QuestionnaireEntryDto[];
3435
}
3536
export class QuestionnaireResponseDto extends QuestionnaireDto {}
37+
export class EntryQuestionnaireDto extends OmitType(QuestionnaireDto, ["entries"]) {}
38+
export class QuestionnairesResponseDto extends OmitType(QuestionnaireDto, ["entries"]) {}
3639
export class QuestionnaireCreationDto extends OmitType(QuestionnaireDto, ["id", "study", "participant"]) {
3740
study: number;
3841
participant: number;

apps/backend/src/research/questionnaires/questionnaires.controller.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ErrorResponseDto } from "../../common/dto/error.dto";
44
import { Roles } from "../../system/users/roles.decorator";
55
import { UserRole } from "../../system/users/user.entity";
66
import { QuestionnairesService } from "./questionnaires.service";
7-
import { QuestionnaireCreationDto, QuestionnaireResponseDto, QuestionnaireMutationDto } from "./questionnaire.dto";
7+
import { QuestionnaireCreationDto, QuestionnaireResponseDto, QuestionnaireMutationDto, QuestionnairesResponseDto } from "./questionnaire.dto";
88

99
@ApiTags("Questionnaires")
1010
@Controller("questionnaires")
@@ -20,7 +20,7 @@ export class QuestionnairesController {
2020

2121
@Get()
2222
@ApiOperation({ summary: "Get all questionnairess" })
23-
index(): Promise<QuestionnaireResponseDto[]> {
23+
index(): Promise<QuestionnairesResponseDto[]> {
2424
return this.questionnairesService.findAll();
2525
}
2626

0 commit comments

Comments
 (0)