From ef271600492a9b3a9dce08cbc8920080e53b8d76 Mon Sep 17 00:00:00 2001 From: Adrian Kunz Date: Wed, 8 Nov 2023 12:43:31 +0100 Subject: [PATCH 01/13] fix(frontend): Confirm before deleting assignee --- .../assignee-dropdown.component.html | 6 +++--- .../assignee-dropdown/assignee-dropdown.component.ts | 12 +++++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.html b/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.html index 890a27986..594586b74 100644 --- a/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.html +++ b/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.html @@ -6,18 +6,18 @@ {{ (assignee || '') | initials }}
- -
diff --git a/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.ts b/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.ts index d56e33ac3..227368615 100644 --- a/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.ts +++ b/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.ts @@ -21,8 +21,18 @@ export class AssigneeDropdownComponent { ) { } - save(): void { + save(assignee: string | undefined): void { + if (!assignee) { + if (!this.assignee) { + // nothing to do; prevent an unnecessary API call that errors + return; + } + if (!confirm('Are you sure you want to unassign? This may remove the recorded duration and feedback.')) { + return; + } + } this.assigneeService.setAssignee(this.assignment, this.solution, this.assignee).subscribe(result => { + this.assignee = result?.assignee; this.assigneeChange.next(result?.assignee); this.toastService.success('Assignee', result ? `Successfully assigned to ${result.assignee}` : 'Successfully de-assigned'); }, error => { From 07bbcfddb6a954b3eca6e6f0d0b0560b9482ff2a Mon Sep 17 00:00:00 2001 From: Adrian Kunz Date: Wed, 8 Nov 2023 12:47:18 +0100 Subject: [PATCH 02/13] feat(frontend): Copy assignee column --- .../assignment/solution-table/solution-table.component.html | 5 ++++- .../assignment/solution-table/solution-table.component.ts | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.html b/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.html index f89965dea..081d54ffe 100644 --- a/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.html +++ b/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.html @@ -118,7 +118,10 @@ - Assignee + + Assignee + + Actions diff --git a/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.ts b/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.ts index 833ec0445..4aacf4e9a 100644 --- a/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.ts +++ b/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.ts @@ -195,6 +195,11 @@ export class SolutionTableComponent implements OnInit { this.toastService.success('Copy Points', `Copied ${this.solutions.length} rows to clipboard`); } + copyAssignee() { + this.clipboardService.copy(this.solutions!.map(s => this.assignees[s._id!] || '').join('\n')); + this.toastService.success('Copy Assignees', `Copied ${this.solutions.length} rows to clipboard`); + } + copyAuthor(name: string, key: keyof AuthorInfo) { this.clipboardService.copy(this.solutions!.map(s => s.author[key] ?? '').join('\n')); this.toastService.success(`Copy ${name}`, `Copied ${this.solutions.length} rows to clipboard`); From 27aa06986b031458975c64bb6ed4135d2ed7779e Mon Sep 17 00:00:00 2001 From: Adrian Kunz Date: Wed, 8 Nov 2023 12:49:12 +0100 Subject: [PATCH 03/13] refactor(frontend): Simplify solution table copy methods --- .../solution-table/solution-table.component.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.ts b/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.ts index 4aacf4e9a..115ce76cf 100644 --- a/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.ts +++ b/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.ts @@ -191,17 +191,19 @@ export class SolutionTableComponent implements OnInit { } copyPoints() { - this.clipboardService.copy(this.solutions!.map(s => s.points ?? '').join('\n')); - this.toastService.success('Copy Points', `Copied ${this.solutions.length} rows to clipboard`); + this.copy('Points', s => (s.points || '').toString()); } copyAssignee() { - this.clipboardService.copy(this.solutions!.map(s => this.assignees[s._id!] || '').join('\n')); - this.toastService.success('Copy Assignees', `Copied ${this.solutions.length} rows to clipboard`); + this.copy('Assignees', s => this.assignees[s._id!] || ''); } copyAuthor(name: string, key: keyof AuthorInfo) { - this.clipboardService.copy(this.solutions!.map(s => s.author[key] ?? '').join('\n')); + this.copy(name, s => s.author[key] || ''); + } + + copy(name: string, select: (s: Solution) => string) { + this.clipboardService.copy(this.solutions!.map(select).join('\n')); this.toastService.success(`Copy ${name}`, `Copied ${this.solutions.length} rows to clipboard`); } From b8f5890f34ed1e9acb335aa0d4da0782e3dd5405 Mon Sep 17 00:00:00 2001 From: Adrian Kunz Date: Wed, 8 Nov 2023 12:50:48 +0100 Subject: [PATCH 04/13] fix(frontend): Make consent import info an alert --- .../modules/import/import-consent/import-consent.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/assignment/modules/import/import-consent/import-consent.component.html b/frontend/src/app/assignment/modules/import/import-consent/import-consent.component.html index 1270cb890..f746c08b8 100644 --- a/frontend/src/app/assignment/modules/import/import-consent/import-consent.component.html +++ b/frontend/src/app/assignment/modules/import/import-consent/import-consent.component.html @@ -1,7 +1,7 @@

Import consent flags by pasting tab-, space- or comma-separated values below.

-
+
More Info

The first line should specify the column names (case insensitive), for example: From d73608bd84af3ecf4cb973a8e70fc5def43c12f5 Mon Sep 17 00:00:00 2001 From: Adrian Kunz Date: Wed, 8 Nov 2023 12:55:41 +0100 Subject: [PATCH 05/13] feat(frontend): Use tabs in consent import --- .../import-consent/import-consent.component.html | 10 ++++++++-- .../import/import-consent/import-consent.component.ts | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/assignment/modules/import/import-consent/import-consent.component.html b/frontend/src/app/assignment/modules/import/import-consent/import-consent.component.html index f746c08b8..679b5a3a4 100644 --- a/frontend/src/app/assignment/modules/import/import-consent/import-consent.component.html +++ b/frontend/src/app/assignment/modules/import/import-consent/import-consent.component.html @@ -1,5 +1,5 @@

- Import consent flags by pasting tab-, space- or comma-separated values below. + Import consent flags by pasting tab- or comma-separated values below.

More Info @@ -19,4 +19,10 @@ and accept boolean values like true or false (case-insensitive).

- + diff --git a/frontend/src/app/assignment/modules/import/import-consent/import-consent.component.ts b/frontend/src/app/assignment/modules/import/import-consent/import-consent.component.ts index f288b8967..f5d991669 100644 --- a/frontend/src/app/assignment/modules/import/import-consent/import-consent.component.ts +++ b/frontend/src/app/assignment/modules/import/import-consent/import-consent.component.ts @@ -28,7 +28,7 @@ export class ImportConsentComponent { import(): Observable { const assignment = this.route.snapshot.params.aid; const lines = this.consentText.split('\n'); - const splitter = /[\s,;]/; + const splitter = /[\t,;]/; const columns = lines[0].split(splitter); const updates: Partial[] = []; for (let i = 1; i < lines.length; i++) { From 1852fae350dadf1eec7cd443757df376850f4351 Mon Sep 17 00:00:00 2001 From: Adrian Kunz Date: Wed, 8 Nov 2023 13:07:02 +0100 Subject: [PATCH 06/13] feat(frontend): Copy timestamp as text for Excel --- frontend/src/app/assignment/model/solution.ts | 2 +- .../solution-table/solution-table.component.html | 1 + .../solution-table/solution-table.component.ts | 11 +++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/assignment/model/solution.ts b/frontend/src/app/assignment/model/solution.ts index b057f8cd3..0e844b74a 100644 --- a/frontend/src/app/assignment/model/solution.ts +++ b/frontend/src/app/assignment/model/solution.ts @@ -33,7 +33,7 @@ export default class Solution { commit?: string; consent?: Consent; - timestamp?: Date; + timestamp?: string; points?: number; feedback?: Feedback; } diff --git a/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.html b/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.html index 081d54ffe..6b73a3bad 100644 --- a/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.html +++ b/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.html @@ -86,6 +86,7 @@ Submitted +
diff --git a/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.ts b/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.ts index 115ce76cf..f086e59c8 100644 --- a/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.ts +++ b/frontend/src/app/assignment/modules/assignment/solution-table/solution-table.component.ts @@ -190,6 +190,17 @@ export class SolutionTableComponent implements OnInit { return [...valueSet].sort(); } + copyTimestamp() { + this.copy('Timestamp', s => { + if (!s.timestamp) { + return ''; + } + const date = new Date(s.timestamp); + // format as YYYY-MM-DD HH:mm:ss (local time) to be understood by Excel + return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`; + }); + } + copyPoints() { this.copy('Points', s => (s.points || '').toString()); } From 6f5d73741cd86a92eb61f416fc8cc037a5ddb2c2 Mon Sep 17 00:00:00 2001 From: Adrian Kunz Date: Wed, 8 Nov 2023 13:20:08 +0100 Subject: [PATCH 07/13] feat(assignments-service): Bulk update assignee --- .../assignments/src/assignee/assignee.controller.ts | 12 +++++++++++- .../apps/assignments/src/assignee/assignee.dto.ts | 5 +++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/services/apps/assignments/src/assignee/assignee.controller.ts b/services/apps/assignments/src/assignee/assignee.controller.ts index 00322cae0..5dab2ff8d 100644 --- a/services/apps/assignments/src/assignee/assignee.controller.ts +++ b/services/apps/assignments/src/assignee/assignee.controller.ts @@ -2,7 +2,7 @@ import {NotFound} from '@mean-stream/nestx'; import {Body, Controller, Delete, Get, Param, Patch, Put} from '@nestjs/common'; import {ApiOkResponse, ApiTags} from '@nestjs/swagger'; import {AssignmentAuth} from '../assignment/assignment-auth.decorator'; -import {PatchAssigneeDto, UpdateAssigneeDto} from './assignee.dto'; +import {BulkUpdateAssigneeDto, PatchAssigneeDto, UpdateAssigneeDto} from './assignee.dto'; import {Assignee} from './assignee.schema'; import {AssigneeService} from './assignee.service'; @@ -25,6 +25,16 @@ export class AssigneeController { return this.assigneeService.findAll({assignment}, {sort: {assignee: 1}}); } + @Patch('assignments/:assignment/assignees') + @AssignmentAuth({forbiddenResponse}) + @ApiOkResponse({type: Assignee}) + async updateMany( + @Param('assignment') assignment: string, + @Body() dtos: BulkUpdateAssigneeDto[], + ): Promise { + return Promise.all(dtos.map(dto => this.assigneeService.upsert({assignment, solution: dto.solution}, dto))); + } + @Get('assignments/:assignment/solutions/:solution/assignee') @NotFound() @AssignmentAuth({forbiddenResponse}) diff --git a/services/apps/assignments/src/assignee/assignee.dto.ts b/services/apps/assignments/src/assignee/assignee.dto.ts index 410c9644a..19981582c 100644 --- a/services/apps/assignments/src/assignee/assignee.dto.ts +++ b/services/apps/assignments/src/assignee/assignee.dto.ts @@ -9,3 +9,8 @@ export class UpdateAssigneeDto extends OmitType(Assignee, [ export class PatchAssigneeDto extends PartialType(UpdateAssigneeDto) { } + +export class BulkUpdateAssigneeDto extends OmitType(Assignee, [ + 'assignment', +] as const) { +} From 1db328b717ee61627b40ee5d0c8e5bf0432b26f1 Mon Sep 17 00:00:00 2001 From: Adrian Kunz Date: Wed, 8 Nov 2023 13:49:21 +0100 Subject: [PATCH 08/13] feat(frontend): Bulk update assignee --- frontend/src/app/assignment/model/assignee.ts | 1 + frontend/src/app/assignment/services/assignee.service.ts | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/assignment/model/assignee.ts b/frontend/src/app/assignment/model/assignee.ts index b1e95df34..192c36eb0 100644 --- a/frontend/src/app/assignment/model/assignee.ts +++ b/frontend/src/app/assignment/model/assignee.ts @@ -89,4 +89,5 @@ export interface Assignee { } export type UpdateAssigneeDto = Omit; +export type BulkUpdateAssigneeDto = Omit; export type PatchAssigneeDto = Partial; diff --git a/frontend/src/app/assignment/services/assignee.service.ts b/frontend/src/app/assignment/services/assignee.service.ts index 438821a01..73f635343 100644 --- a/frontend/src/app/assignment/services/assignee.service.ts +++ b/frontend/src/app/assignment/services/assignee.service.ts @@ -1,6 +1,6 @@ import {Injectable} from "@angular/core"; import {Observable} from "rxjs"; -import {Assignee, PatchAssigneeDto, UpdateAssigneeDto} from "../model/assignee"; +import {Assignee, BulkUpdateAssigneeDto, PatchAssigneeDto, UpdateAssigneeDto} from "../model/assignee"; import {environment} from "../../../environments/environment"; import {HttpClient} from "@angular/common/http"; import {map} from "rxjs/operators"; @@ -20,6 +20,10 @@ export class AssigneeService { return this.http.get(`${environment.assignmentsApiUrl}/assignments/${assignment}/assignees`); } + updateMany(assignment: string, dtos: BulkUpdateAssigneeDto[]): Observable { + return this.http.patch(`${environment.assignmentsApiUrl}/assignments/${assignment}/assignees`, dtos); + } + findOne(assignment: string, solution: string): Observable { return this.http.get(url(assignment, solution)); } From 7f7e50bb8b9a9b094201ef4c35d9553018bbba38 Mon Sep 17 00:00:00 2001 From: Adrian Kunz Date: Wed, 8 Nov 2023 13:50:07 +0100 Subject: [PATCH 09/13] fix(frontend): Set assignee --- .../shared/assignee-dropdown/assignee-dropdown.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.ts b/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.ts index 227368615..5469891cf 100644 --- a/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.ts +++ b/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.ts @@ -31,7 +31,7 @@ export class AssigneeDropdownComponent { return; } } - this.assigneeService.setAssignee(this.assignment, this.solution, this.assignee).subscribe(result => { + this.assigneeService.setAssignee(this.assignment, this.solution, assignee).subscribe(result => { this.assignee = result?.assignee; this.assigneeChange.next(result?.assignee); this.toastService.success('Assignee', result ? `Successfully assigned to ${result.assignee}` : 'Successfully de-assigned'); From 75affecd15e4a511f6dbbb3f2bb7d367b92715ae Mon Sep 17 00:00:00 2001 From: Adrian Kunz Date: Wed, 8 Nov 2023 14:01:42 +0100 Subject: [PATCH 10/13] fix(frontend): Better assignee color --- .../modules/shared/pipes/assignee-color.pipe.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/assignment/modules/shared/pipes/assignee-color.pipe.ts b/frontend/src/app/assignment/modules/shared/pipes/assignee-color.pipe.ts index f7910a514..92715a3da 100644 --- a/frontend/src/app/assignment/modules/shared/pipes/assignee-color.pipe.ts +++ b/frontend/src/app/assignment/modules/shared/pipes/assignee-color.pipe.ts @@ -9,8 +9,17 @@ export class AssigneeColorPipe implements PipeTransform { if (!value) { return undefined; } - const hash = value.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0); + const hash = hashCode(value); const hue = (hash % 30) * 12; return `hsl(${hue}, 50%, 50%)`; } } + +function hashCode(str: string): number { + let hash = 0; + for (let i = 0; i < str.length; i++) { + hash = ((hash << 5) - hash) + str.charCodeAt(i); + hash |= 0; + } + return hash; +} From 2c815471f05280b660a664e80c36cda6362f7538 Mon Sep 17 00:00:00 2001 From: Adrian Kunz Date: Wed, 8 Nov 2023 14:18:15 +0100 Subject: [PATCH 11/13] feat(frontend): Copy assignees in course --- .../course/students/students.component.html | 31 +++++++++++++++---- .../course/students/students.component.ts | 26 +++++++++++++++- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/frontend/src/app/assignment/modules/course/students/students.component.html b/frontend/src/app/assignment/modules/course/students/students.component.html index e7529fa74..274c14e83 100644 --- a/frontend/src/app/assignment/modules/course/students/students.component.html +++ b/frontend/src/app/assignment/modules/course/students/students.component.html @@ -4,12 +4,31 @@ {{ prop[0] }} - - {{ assignmentNames[index] }} + +
+ + {{ assignmentNames[index] }} + +
+ +
+ + +
+
+
diff --git a/frontend/src/app/assignment/modules/course/students/students.component.ts b/frontend/src/app/assignment/modules/course/students/students.component.ts index 7fd4abb5b..4cc673fe5 100644 --- a/frontend/src/app/assignment/modules/course/students/students.component.ts +++ b/frontend/src/app/assignment/modules/course/students/students.component.ts @@ -5,7 +5,9 @@ import {CourseService} from 'src/app/assignment/services/course.service'; import Course, {CourseStudent} from '../../../model/course'; import {authorInfoProperties} from '../../../model/solution'; import {AssignmentService} from "../../../services/assignment.service"; -import Assignment, {ReadAssignmentDto} from "../../../model/assignment"; +import {ReadAssignmentDto} from "../../../model/assignment"; +import {AssigneeService} from "../../../services/assignee.service"; +import {BulkUpdateAssigneeDto} from "../../../model/assignee"; @Component({ selector: 'app-students', @@ -25,6 +27,7 @@ export class StudentsComponent implements OnInit { private route: ActivatedRoute, private courseService: CourseService, private assignmentService: AssignmentService, + private assigneeService: AssigneeService, ) { } @@ -62,4 +65,25 @@ export class StudentsComponent implements OnInit { )].sort(); }); } + + copyAssignees(to: number, from: number) { + if (!this.course || !this.students) { + return; + } + this.assigneeService.updateMany(this.course.assignments[to], this.students + .map(student => { + const fromSolution = student.solutions[from]; + const toSolution = student.solutions[to]; + if (!fromSolution || !toSolution || !fromSolution.assignee) { + return; + } + toSolution.assignee = fromSolution.assignee; + return { + solution: toSolution._id, + assignee: fromSolution.assignee, + }; + }) + .filter((x): x is BulkUpdateAssigneeDto => !!x), + ); + } } From 96e59888a6373ea751c6e25bdb0ccce52b7d5bc8 Mon Sep 17 00:00:00 2001 From: Adrian Kunz Date: Wed, 8 Nov 2023 14:25:55 +0100 Subject: [PATCH 12/13] fix(frontend): Update assignee in course table only if request succeeds --- .../course/students/students.component.ts | 19 +++++++++++++++++-- .../assignment/services/assignee.service.ts | 4 ++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/assignment/modules/course/students/students.component.ts b/frontend/src/app/assignment/modules/course/students/students.component.ts index 4cc673fe5..20f3ed584 100644 --- a/frontend/src/app/assignment/modules/course/students/students.component.ts +++ b/frontend/src/app/assignment/modules/course/students/students.component.ts @@ -8,6 +8,7 @@ import {AssignmentService} from "../../../services/assignment.service"; import {ReadAssignmentDto} from "../../../model/assignment"; import {AssigneeService} from "../../../services/assignee.service"; import {BulkUpdateAssigneeDto} from "../../../model/assignee"; +import {ToastService} from "@mean-stream/ngbx"; @Component({ selector: 'app-students', @@ -28,6 +29,7 @@ export class StudentsComponent implements OnInit { private courseService: CourseService, private assignmentService: AssignmentService, private assigneeService: AssigneeService, + private toastService: ToastService, ) { } @@ -77,13 +79,26 @@ export class StudentsComponent implements OnInit { if (!fromSolution || !toSolution || !fromSolution.assignee) { return; } - toSolution.assignee = fromSolution.assignee; return { solution: toSolution._id, assignee: fromSolution.assignee, }; }) .filter((x): x is BulkUpdateAssigneeDto => !!x), - ); + ).subscribe(assignees => { + const solutionIdToAssignee = Object.fromEntries(assignees.map(a => [a.solution, a.assignee])); + for (const student of this.students!) { + const solution = student.solutions[to]; + if (!solution) { + continue; + } + const assignee = solutionIdToAssignee[solution._id]; + if (!assignee) { + continue; + } + solution.assignee = assignee; + } + this.toastService.success('Copy Assignees', `Successfully copied ${assignees.length} assignees.`); + }); } } diff --git a/frontend/src/app/assignment/services/assignee.service.ts b/frontend/src/app/assignment/services/assignee.service.ts index 73f635343..97c275c5e 100644 --- a/frontend/src/app/assignment/services/assignee.service.ts +++ b/frontend/src/app/assignment/services/assignee.service.ts @@ -20,8 +20,8 @@ export class AssigneeService { return this.http.get(`${environment.assignmentsApiUrl}/assignments/${assignment}/assignees`); } - updateMany(assignment: string, dtos: BulkUpdateAssigneeDto[]): Observable { - return this.http.patch(`${environment.assignmentsApiUrl}/assignments/${assignment}/assignees`, dtos); + updateMany(assignment: string, dtos: BulkUpdateAssigneeDto[]): Observable { + return this.http.patch(`${environment.assignmentsApiUrl}/assignments/${assignment}/assignees`, dtos); } findOne(assignment: string, solution: string): Observable { From 65fd31dd0bfff44b5068152fc2d79d95aac9f11e Mon Sep 17 00:00:00 2001 From: Adrian Kunz Date: Wed, 8 Nov 2023 14:55:02 +0100 Subject: [PATCH 13/13] fix(frontend): Materialize assignee dropdown only when open --- .../assignee-dropdown.component.html | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.html b/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.html index 594586b74..34e6be753 100644 --- a/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.html +++ b/frontend/src/app/assignment/modules/shared/assignee-dropdown/assignee-dropdown.component.html @@ -1,4 +1,4 @@ -
+
- - + + + + +