diff --git a/src/main/webapp/app/entities/competency.model.ts b/src/main/webapp/app/entities/competency.model.ts index 245cfd71553c..51afaa1b18a3 100644 --- a/src/main/webapp/app/entities/competency.model.ts +++ b/src/main/webapp/app/entities/competency.model.ts @@ -46,7 +46,11 @@ export enum CourseCompetencyType { export const DEFAULT_MASTERY_THRESHOLD = 100; +export const HIGH_COMPETENCY_LINK_WEIGHT = 1; export const MEDIUM_COMPETENCY_LINK_WEIGHT = 0.5; +export const LOW_COMPETENCY_LINK_WEIGHT = 0.25; +export const LOW_COMPETENCY_LINK_WEIGHT_CUT_OFF = 0.375; // halfway between low and medium +export const MEDIUM_COMPETENCY_LINK_WEIGHT_CUT_OFF = 0.75; // halfway between medium and high export abstract class BaseCompetency implements BaseEntity { id?: number; diff --git a/src/main/webapp/app/shared/competency-selection/competency-selection.component.html b/src/main/webapp/app/shared/competency-selection/competency-selection.component.html index b15b8f4cfd8f..7fba47389226 100644 --- a/src/main/webapp/app/shared/competency-selection/competency-selection.component.html +++ b/src/main/webapp/app/shared/competency-selection/competency-selection.component.html @@ -32,6 +32,23 @@ {{ competencyLink.competency.title }} + @if (checkboxStates[competencyLink.competency.id]) { + + } } } diff --git a/src/main/webapp/app/shared/competency-selection/competency-selection.component.ts b/src/main/webapp/app/shared/competency-selection/competency-selection.component.ts index 224abeb3cabe..41f2dcf0e67a 100644 --- a/src/main/webapp/app/shared/competency-selection/competency-selection.component.ts +++ b/src/main/webapp/app/shared/competency-selection/competency-selection.component.ts @@ -1,7 +1,16 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, forwardRef } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons'; -import { CompetencyLearningObjectLink, CourseCompetency, MEDIUM_COMPETENCY_LINK_WEIGHT, getIcon } from 'app/entities/competency.model'; +import { + CompetencyLearningObjectLink, + CourseCompetency, + HIGH_COMPETENCY_LINK_WEIGHT, + LOW_COMPETENCY_LINK_WEIGHT, + LOW_COMPETENCY_LINK_WEIGHT_CUT_OFF, + MEDIUM_COMPETENCY_LINK_WEIGHT, + MEDIUM_COMPETENCY_LINK_WEIGHT_CUT_OFF, + getIcon, +} from 'app/entities/competency.model'; import { ActivatedRoute } from '@angular/router'; import { CourseStorageService } from 'app/course/manage/course-storage.service'; import { finalize } from 'rxjs'; @@ -40,6 +49,12 @@ export class CompetencySelectionComponent implements OnInit, ControlValueAccesso // eslint-disable-next-line @typescript-eslint/no-unused-vars _onChange = (value: any) => {}; + protected readonly HIGH_COMPETENCY_LINK_WEIGHT = HIGH_COMPETENCY_LINK_WEIGHT; + protected readonly MEDIUM_COMPETENCY_LINK_WEIGHT = MEDIUM_COMPETENCY_LINK_WEIGHT; + protected readonly LOW_COMPETENCY_LINK_WEIGHT = LOW_COMPETENCY_LINK_WEIGHT; + protected readonly LOW_COMPETENCY_LINK_WEIGHT_CUT_OFF = LOW_COMPETENCY_LINK_WEIGHT_CUT_OFF; // halfway between low and medium + protected readonly MEDIUM_COMPETENCY_LINK_WEIGHT_CUT_OFF = MEDIUM_COMPETENCY_LINK_WEIGHT_CUT_OFF; // halfway between medium and high + constructor( private route: ActivatedRoute, private courseStorageService: CourseStorageService, @@ -122,7 +137,19 @@ export class CompetencySelectionComponent implements OnInit, ControlValueAccesso } } + updateLinkWeight(link: CompetencyLearningObjectLink, value: number) { + link.weight = value; + + this._onChange(this.selectedCompetencyLinks); + this.valueChange.emit(this.selectedCompetencyLinks); + } + writeValue(value?: CompetencyLearningObjectLink[]): void { + this.competencyLinks?.forEach((link) => { + const selectedLink = value?.find((value) => value.competency?.id === link.competency?.id); + link.weight = selectedLink?.weight ?? MEDIUM_COMPETENCY_LINK_WEIGHT; + }); + if (value && this.competencyLinks) { // Compare the ids of the competencies instead of the whole objects const ids = value.map((el) => el.competency?.id); diff --git a/src/main/webapp/i18n/de/competency.json b/src/main/webapp/i18n/de/competency.json index aaef36b9f34a..f06f02951cda 100644 --- a/src/main/webapp/i18n/de/competency.json +++ b/src/main/webapp/i18n/de/competency.json @@ -117,7 +117,13 @@ "link": { "title": "Verbundene Kompetenzen", "lectureUnit": "Verbinde diese Vorlesungseinheit wahlweise mit einer oder mehreren Kompetenzen.", - "exercise": "Verbinde diese Übung wahlweise mit einer oder mehreren Kompetenzen." + "exercise": "Verbinde diese Übung wahlweise mit einer oder mehreren Kompetenzen.", + "weightTooltip": "Die Relevanz dieses Lernobjektes für die Kompetenz.", + "weightLabels": { + "low": "Niedrig", + "medium": "Mittel", + "high": "Hoch" + } }, "competencyCard": { "connectedLectureUnits": "Verbundene Vorlesungseinheiten", diff --git a/src/main/webapp/i18n/en/competency.json b/src/main/webapp/i18n/en/competency.json index e4aedbe82c77..6cac8ddf0256 100644 --- a/src/main/webapp/i18n/en/competency.json +++ b/src/main/webapp/i18n/en/competency.json @@ -117,7 +117,13 @@ "link": { "title": "Linked Competencies", "lectureUnit": "Optionally link this lecture unit to one or more competencies.", - "exercise": "Optionally link this exercise to one or more competencies." + "exercise": "Optionally link this exercise to one or more competencies.", + "weightTooltip": "The relevance of this learning object for the competency.", + "weightLabels": { + "low": "Low", + "medium": "Medium", + "high": "High" + } }, "competencyCard": { "connectedLectureUnits": "Linked Lecture Units", diff --git a/src/test/javascript/spec/component/shared/competency-selection.component.spec.ts b/src/test/javascript/spec/component/shared/competency-selection.component.spec.ts index a58b665e45cc..13cdf686b9c9 100644 --- a/src/test/javascript/spec/component/shared/competency-selection.component.spec.ts +++ b/src/test/javascript/spec/component/shared/competency-selection.component.spec.ts @@ -14,6 +14,7 @@ import { By } from '@angular/platform-browser'; import { CourseStorageService } from 'app/course/manage/course-storage.service'; import { ChangeDetectorRef } from '@angular/core'; import { CourseCompetencyService } from 'app/course/competencies/course-competency.service'; +import { Prerequisite } from 'app/entities/prerequisite.model'; describe('CompetencySelection', () => { let fixture: ComponentFixture; @@ -122,6 +123,22 @@ describe('CompetencySelection', () => { expect(component.selectedCompetencyLinks?.first()?.competency?.title).toBe('test'); }); + it('should update link weight when value is written', () => { + jest.spyOn(courseStorageService, 'getCourse').mockReturnValue({ + competencies: [{ id: 1, title: 'test' } as Competency, { id: 2, title: 'testAgain' } as Prerequisite, { id: 3, title: 'testMore' } as Competency], + }); + + fixture.detectChanges(); + + component.writeValue([ + new CompetencyLearningObjectLink({ id: 1, title: 'other' } as Competency, 0.5), + new CompetencyLearningObjectLink({ id: 3, title: 'otherMore' } as Competency, 1), + ]); + expect(component.selectedCompetencyLinks).toBeArrayOfSize(2); + expect(component.selectedCompetencyLinks?.first()?.weight).toBe(0.5); + expect(component.selectedCompetencyLinks?.last()?.weight).toBe(1); + }); + it('should trigger change detection after loading competencies', () => { jest.spyOn(courseStorageService, 'getCourse').mockReturnValue({ competencies: undefined }); const changeDetector = fixture.debugElement.injector.get(ChangeDetectorRef);