Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2bf6e68
feat: render basic empty calendar
stampaaaron Dec 3, 2024
d2992eb
feat: include entries in questionnaire endpoints
stampaaaron Dec 3, 2024
e0a226a
fix: validation for entry creation
stampaaaron Dec 3, 2024
0f1d7a5
feat: render calendar events from questionnaire
stampaaaron Dec 4, 2024
433dc7f
feat: apply basic calendar styling
stampaaaron Dec 4, 2024
be923fe
fix: exports from ui package
stampaaaron Dec 4, 2024
10d24e1
refactor: extract questionnaire entry to separat component
stampaaaron Dec 4, 2024
b385bd1
chore: extract calendar base config to object
stampaaaron Dec 4, 2024
8fa4b49
feat: open modal when selecting dates
stampaaaron Dec 4, 2024
9ac4613
fix: entry creation
stampaaaron Dec 4, 2024
d0cb896
feat: setup basic entity form component
stampaaaron Dec 5, 2024
f93399e
feat: add languageEntries to EntryForm
stampaaaron Dec 5, 2024
886b403
feat: auto calculate language ratios
stampaaaron Dec 9, 2024
d384e78
feat: introduce form validation
stampaaaron Dec 9, 2024
7f52add
feat: pass start and end time to entry form
stampaaaron Dec 9, 2024
bbf8158
feat: add selects for carer and languages
stampaaaron Dec 9, 2024
145a911
chore: remove console log
stampaaaron Dec 9, 2024
d90f647
feat: improve modal form styling
stampaaaron Dec 9, 2024
d8906a5
feat: add labels to form fields
stampaaaron Dec 9, 2024
5cb8fb5
fix: use correct column for database constraint
stampaaaron Dec 9, 2024
64f8ca1
fix: resolving correct date for sundays
stampaaaron Dec 9, 2024
a8419c7
feat: add create entry logic
stampaaaron Dec 9, 2024
8e3f4c2
fix: form names
stampaaaron Dec 9, 2024
1e42711
feat: allow updating entries
stampaaaron Dec 10, 2024
c4f22cb
fix: questionnaire index type
stampaaaron Dec 10, 2024
6f7c876
feat: allow resizing entries in calendar
stampaaaron Dec 10, 2024
2480198
feat: allow dragging events in calendar
stampaaaron Dec 10, 2024
725923b
feat: allow deleting entries from calendar
stampaaaron Dec 10, 2024
a6f7cc4
fix: period picker
stampaaaron Dec 10, 2024
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
7 changes: 4 additions & 3 deletions apps/backend/db/migrations/.snapshot-postgres.json
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,8 @@
},
{
"name": "entry_weekly_recurring_check",
"expression": "weekday >= 1",
"definition": "check ((weekday >= 1))",
"expression": "weekly_recurring >= 1",
"definition": "check ((weekly_recurring >= 1))",
"columnName": "weekly_recurring"
}
],
Expand Down Expand Up @@ -558,7 +558,7 @@
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"nullable": true,
"mappedType": "integer"
}
},
Expand Down Expand Up @@ -607,6 +607,7 @@
"id"
],
"referencedTableName": "public.entry",
"deleteRule": "cascade",
"updateRule": "cascade"
}
},
Expand Down
15 changes: 15 additions & 0 deletions apps/backend/db/migrations/Migration20241209144817.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Migration } from "@mikro-orm/migrations";

export class Migration20241209144817 extends Migration {
override async up(): Promise<void> {
this.addSql(`alter table "entry" drop constraint entry_weekly_recurring_check;`);

this.addSql(`alter table "entry" add constraint entry_weekly_recurring_check check(weekly_recurring >= 1);`);
}

override async down(): Promise<void> {
this.addSql(`alter table "entry" drop constraint entry_weekly_recurring_check;`);

this.addSql(`alter table "entry" add constraint entry_weekly_recurring_check check(weekday >= 1);`);
}
}
23 changes: 23 additions & 0 deletions apps/backend/db/migrations/Migration20241210094456.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Migration } from "@mikro-orm/migrations";

export class Migration20241210094456 extends Migration {
override async up(): Promise<void> {
this.addSql(`alter table "entry_language" drop constraint "entry_language_entry_id_foreign";`);

this.addSql(`alter table "entry_language" alter column "entry_id" type int using ("entry_id"::int);`);
this.addSql(`alter table "entry_language" alter column "entry_id" drop not null;`);
this.addSql(
`alter table "entry_language" add constraint "entry_language_entry_id_foreign" foreign key ("entry_id") references "entry" ("id") on update cascade on delete cascade;`
);
}

override async down(): Promise<void> {
this.addSql(`alter table "entry_language" drop constraint "entry_language_entry_id_foreign";`);

this.addSql(`alter table "entry_language" alter column "entry_id" type int using ("entry_id"::int);`);
this.addSql(`alter table "entry_language" alter column "entry_id" set not null;`);
this.addSql(
`alter table "entry_language" add constraint "entry_language_entry_id_foreign" foreign key ("entry_id") references "entry" ("id") on update cascade;`
);
}
}
12 changes: 6 additions & 6 deletions apps/backend/src/research/entries/entries.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

async create(entryCreationDto: EntryCreationDto) {
const entry = new Entry();
entry.assign(entryCreationDto);
entry.assign(entryCreationDto, { em: this.em });

Check warning on line 17 in apps/backend/src/research/entries/entries.service.ts

View check run for this annotation

Codecov / codecov/patch

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

Added line #L17 was not covered by tests

try {
await this.em.persist(entry).flush();
Expand All @@ -25,23 +25,23 @@
throw e;
}

return entry.toObject();
return (await entry.populate(["entryLanguages"])).toObject();

Check warning on line 28 in apps/backend/src/research/entries/entries.service.ts

View check run for this annotation

Codecov / codecov/patch

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

Added line #L28 was not covered by tests
}

async findAll() {
return (await this.entryRepository.findAll()).map((entry) => entry.toObject());
return (await this.entryRepository.findAll({ populate: ["entryLanguages"] })).map((entry) => entry.toObject());

Check warning on line 32 in apps/backend/src/research/entries/entries.service.ts

View check run for this annotation

Codecov / codecov/patch

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

Added line #L32 was not covered by tests
}

async findOne(id: number) {
return (await this.entryRepository.findOneOrFail(id)).toObject();
return (await this.entryRepository.findOneOrFail(id, { populate: ["entryLanguages"] })).toObject();

Check warning on line 36 in apps/backend/src/research/entries/entries.service.ts

View check run for this annotation

Codecov / codecov/patch

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

Added line #L36 was not covered by tests
}

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

Check warning on line 40 in apps/backend/src/research/entries/entries.service.ts

View check run for this annotation

Codecov / codecov/patch

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

Added line #L40 was not covered by tests
}

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

Check warning on line 44 in apps/backend/src/research/entries/entries.service.ts

View check run for this annotation

Codecov / codecov/patch

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

Added line #L44 was not covered by tests

entry.assign(entryMutationDto);

Expand Down
24 changes: 16 additions & 8 deletions apps/backend/src/research/entries/entry.dto.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { ApiProperty, OmitType, PartialType } from "@nestjs/swagger";
import { Type } from "class-transformer";
import { IsOptional, IsDate, Min, Max } from "class-validator";
import { QuestionnaireDto } from "../questionnaires/questionnaire.dto";
import { IsOptional, Min, Max, IsMilitaryTime } from "class-validator";
import { CarerDto } from "../../defaults/carers/carer.dto";
import { EntryQuestionnaireDto, QuestionnaireDto } from "../questionnaires/questionnaire.dto";
import { EntryLanguageCreationDto, EntryLanguageResponseDto } from "../entry-languages/entry-language.dto";

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

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

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

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

@Type(() => QuestionnaireDto)
questionnaire: QuestionnaireDto;
questionnaire: EntryQuestionnaireDto;

@Type(() => CarerDto)
carer: CarerDto;

@Type(() => Array<number>)
entryLanguages: number[];
@Type(() => Array<EntryLanguageResponseDto>)

Check warning on line 36 in apps/backend/src/research/entries/entry.dto.ts

View check run for this annotation

Codecov / codecov/patch

apps/backend/src/research/entries/entry.dto.ts#L36

Added line #L36 was not covered by tests
entryLanguages: Array<EntryLanguageResponseDto>;
}
export class EntryResponseDto extends EntryDto {}
export class EntryCreationDto extends OmitType(EntryDto, ["id"]) {}
export class QuestionnaireEntryDto extends OmitType(EntryDto, ["questionnaire"]) {}
export class EntryCreationDto extends OmitType(EntryDto, ["id", "carer", "questionnaire", "entryLanguages"]) {
carer: number;
questionnaire: number;

@Type(() => EntryLanguageCreationDto)

Check warning on line 45 in apps/backend/src/research/entries/entry.dto.ts

View check run for this annotation

Codecov / codecov/patch

apps/backend/src/research/entries/entry.dto.ts#L45

Added line #L45 was not covered by tests
entryLanguages: Array<EntryLanguageCreationDto>;
}
export class EntryMutationDto extends PartialType(EntryCreationDto) {}
4 changes: 2 additions & 2 deletions apps/backend/src/research/entries/entry.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
weekday!: number;

@Property({ default: 1, columnType: "smallint" })
@Check<Entry>({ expression: (columns) => `${columns.weekday} >= 1` })
@Check<Entry>({ expression: (columns) => `${columns.weeklyRecurring} >= 1` })

Check warning on line 23 in apps/backend/src/research/entries/entry.entity.ts

View check run for this annotation

Codecov / codecov/patch

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

Added line #L23 was not covered by tests
weeklyRecurring!: number & Opt;

@ManyToOne()
Expand All @@ -29,6 +29,6 @@
@ManyToOne()
carer!: Carer;

@OneToMany(() => EntryLanguage, (entryLanguage) => entryLanguage.entry)
@OneToMany(() => EntryLanguage, (entryLanguage) => entryLanguage.entry, { orphanRemoval: true })

Check warning on line 32 in apps/backend/src/research/entries/entry.entity.ts

View check run for this annotation

Codecov / codecov/patch

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

Added line #L32 was not covered by tests
entryLanguages = new Collection<EntryLanguage>(this);
}
17 changes: 10 additions & 7 deletions apps/backend/src/research/entry-languages/entry-language.dto.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ApiProperty, OmitType, PartialType } from "@nestjs/swagger";
import { ApiProperty, OmitType } from "@nestjs/swagger";
import { Type } from "class-transformer";
import { Min, Max } from "class-validator";
import { LanguageDto } from "../../defaults/languages/language.dto";
import { EntryDto } from "../entries/entry.dto";
import { QuestionnaireEntryDto } from "../entries/entry.dto";

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

@Type(() => EntryDto)
entry: EntryDto;
@Type(() => QuestionnaireEntryDto)

Check warning on line 19 in apps/backend/src/research/entry-languages/entry-language.dto.ts

View check run for this annotation

Codecov / codecov/patch

apps/backend/src/research/entry-languages/entry-language.dto.ts#L19

Added line #L19 was not covered by tests
entry: QuestionnaireEntryDto;
}
export class EntryLanguageResponseDto extends EntryLanguageDto {}
export class EntryLanguageCreationDto extends OmitType(EntryLanguageDto, ["id"]) {}
export class EntryLanguageMutationDto extends PartialType(EntryLanguageCreationDto) {}
export class EntryLanguageResponseDto extends OmitType(EntryLanguageDto, ["entry"]) {}
export class EntryLanguageMutationDto extends OmitType(EntryLanguageDto, ["id", "entry", "language"]) {
id?: number;
language?: number;
}
export class EntryLanguageCreationDto extends OmitType(EntryLanguageMutationDto, ["id"]) {}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Check, Entity, ManyToOne, Property } from "@mikro-orm/core";
import { Cascade, Check, Entity, ManyToOne, Property } from "@mikro-orm/core";
import { BaseEntity } from "../../common/entities/base.entity";
import { Language } from "../../defaults/languages/language.entity";
import { Entry } from "../entries/entry.entity";
Expand All @@ -12,6 +12,6 @@ export class EntryLanguage extends BaseEntity {
@ManyToOne()
language!: Language;

@ManyToOne()
@ManyToOne({ cascade: [Cascade.ALL] })
entry!: Entry;
}
7 changes: 5 additions & 2 deletions apps/backend/src/research/questionnaires/questionnaire.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { IsDateString, IsNotEmpty } from "class-validator";
import { ParticipantDto } from "../participants/participant.dto";
import { StudyDto } from "../studies/study.dto";
import { QuestionnaireEntryDto } from "../entries/entry.dto";

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

@Type(() => Array<number>)
entries?: number[];
@Type(() => Array<QuestionnaireEntryDto>)

Check warning on line 33 in apps/backend/src/research/questionnaires/questionnaire.dto.ts

View check run for this annotation

Codecov / codecov/patch

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

Added line #L33 was not covered by tests
entries?: QuestionnaireEntryDto[];
}
export class QuestionnaireResponseDto extends QuestionnaireDto {}
export class EntryQuestionnaireDto extends OmitType(QuestionnaireDto, ["entries"]) {}
export class QuestionnairesResponseDto extends OmitType(QuestionnaireDto, ["entries"]) {}
export class QuestionnaireCreationDto extends OmitType(QuestionnaireDto, ["id", "study", "participant"]) {
study: number;
participant: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ErrorResponseDto } from "../../common/dto/error.dto";
import { Roles } from "../../system/users/roles.decorator";
import { UserRole } from "../../system/users/user.entity";
import { QuestionnairesService } from "./questionnaires.service";
import { QuestionnaireCreationDto, QuestionnaireResponseDto, QuestionnaireMutationDto } from "./questionnaire.dto";
import { QuestionnaireCreationDto, QuestionnaireResponseDto, QuestionnaireMutationDto, QuestionnairesResponseDto } from "./questionnaire.dto";

@ApiTags("Questionnaires")
@Controller("questionnaires")
Expand All @@ -20,7 +20,7 @@ export class QuestionnairesController {

@Get()
@ApiOperation({ summary: "Get all questionnairess" })
index(): Promise<QuestionnaireResponseDto[]> {
index(): Promise<QuestionnairesResponseDto[]> {
return this.questionnairesService.findAll();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,27 @@
throw e;
}

return questionnaire.toObject();
return (await questionnaire.populate(["entries", "entries.carer", "entries.entryLanguages.language"])).toObject();

Check warning on line 28 in apps/backend/src/research/questionnaires/questionnaires.service.ts

View check run for this annotation

Codecov / codecov/patch

apps/backend/src/research/questionnaires/questionnaires.service.ts#L28

Added line #L28 was not covered by tests
}

async findAll() {
return (await this.questionnaireRepository.findAll()).map((questionnaire) => questionnaire.toObject());
}

async findOne(id: number) {
return (await this.questionnaireRepository.findOneOrFail(id)).toObject();
return (

Check warning on line 36 in apps/backend/src/research/questionnaires/questionnaires.service.ts

View check run for this annotation

Codecov / codecov/patch

apps/backend/src/research/questionnaires/questionnaires.service.ts#L36

Added line #L36 was not covered by tests
await this.questionnaireRepository.findOneOrFail(id, { populate: ["entries", "entries.carer", "entries.entryLanguages.language"] })
).toObject();
}

async findBy(filter: FilterQuery<Questionnaire>) {
return (await this.questionnaireRepository.findOneOrFail(filter)).toObject();
}

async update(id: number, questionnaireMutationDto: QuestionnaireMutationDto) {
const questionnaire = await this.questionnaireRepository.findOneOrFail(id);
const questionnaire = await this.questionnaireRepository.findOneOrFail(id, {

Check warning on line 46 in apps/backend/src/research/questionnaires/questionnaires.service.ts

View check run for this annotation

Codecov / codecov/patch

apps/backend/src/research/questionnaires/questionnaires.service.ts#L46

Added line #L46 was not covered by tests
populate: ["entries", "entries.carer", "entries.entryLanguages.language"],
});
questionnaire.assign(questionnaireMutationDto);

await this.em.persist(questionnaire).flush();
Expand Down
4 changes: 4 additions & 0 deletions apps/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
"test": "vitest"
},
"dependencies": {
"@fullcalendar/core": "^6.1.15",
"@fullcalendar/interaction": "^6.1.15",
"@fullcalendar/react": "^6.1.15",
"@fullcalendar/timegrid": "^6.1.15",
"@mantine/form": "^7.14.3",
"@nanostores/i18n": "^0.12.2",
"@nanostores/persistent": "^0.10.2",
Expand Down
Loading
Loading