diff --git a/projects/request/src/lib/request.service.ts b/projects/request/src/lib/request.service.ts index 41e26cd5a..7e3d56e97 100644 --- a/projects/request/src/lib/request.service.ts +++ b/projects/request/src/lib/request.service.ts @@ -14,6 +14,7 @@ import { has, isEmpty, each } from 'lodash'; interface RequestOptions { headers?: any; params?: any; + observe?: string; } @Injectable({ providedIn: 'root' }) @@ -127,6 +128,9 @@ export class RequestService { if (!has(httpOptions, 'params')) { httpOptions.params = ''; } + if (!has(httpOptions, 'observe')) { + httpOptions.observe = 'body'; + } const request = this.http.get(this.getEndpointUrl(endPoint), { headers: this.appendHeaders(httpOptions.headers), diff --git a/projects/v3/src/app/components/activity/activity.component.ts b/projects/v3/src/app/components/activity/activity.component.ts index 484dbbccb..7e61561ff 100644 --- a/projects/v3/src/app/components/activity/activity.component.ts +++ b/projects/v3/src/app/components/activity/activity.component.ts @@ -1,4 +1,5 @@ -import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; +import { Subject } from 'rxjs'; +import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges } from '@angular/core'; import { SharedService } from '@v3/app/services/shared.service'; import { UnlockIndicatorService } from '@v3/app/services/unlock-indicator.service'; import { Activity, ActivityService, Task } from '@v3/services/activity.service'; @@ -6,13 +7,14 @@ import { Submission } from '@v3/services/assessment.service'; import { NotificationsService } from '@v3/services/notifications.service'; import { BrowserStorageService } from '@v3/services/storage.service'; import { UtilsService } from '@v3/services/utils.service'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-activity', templateUrl: './activity.component.html', styleUrls: ['./activity.component.scss'], }) -export class ActivityComponent implements OnInit, OnChanges { +export class ActivityComponent implements OnInit, OnChanges, OnDestroy { @Input() activity: Activity; @Input() currentTask: Task; @Input() submission: Submission; @@ -25,6 +27,7 @@ export class ActivityComponent implements OnInit, OnChanges { // false: at least one non-team task @Output() cannotAccessTeamActivity = new EventEmitter(); isForTeamOnly: boolean = false; + private unsubscribe$: Subject = new Subject(); constructor( private utils: UtilsService, @@ -32,17 +35,28 @@ export class ActivityComponent implements OnInit, OnChanges { private notificationsService: NotificationsService, private sharedService: SharedService, private activityService: ActivityService, - private unlockIndicatorService: UnlockIndicatorService, + private unlockIndicatorService: UnlockIndicatorService ) {} - ngOnInit() { - this.leadImage = this.storageService.getUser().programImage; - this.unlockIndicatorService.unlockedTasks$.subscribe((unlockedTasks) => { - this.newTasks = {}; - unlockedTasks.forEach((task) => { + ngOnDestroy(): void { + this.unsubscribe$.next(); + this.unsubscribe$.complete(); + } + + resetTaskIndicator(unlockedTasks) { + this.newTasks = {}; + unlockedTasks + .filter((task) => task.taskId) + .forEach((task) => { this.newTasks[task.taskId] = true; }); - }); + } + + ngOnInit() { + this.leadImage = this.storageService.getUser().programImage; + this.unlockIndicatorService.unlockedTasks$ + .pipe(takeUntil(this.unsubscribe$)) + .subscribe(this.resetTaskIndicator); } ngOnChanges(changes: SimpleChanges): void { @@ -56,23 +70,28 @@ export class ActivityComponent implements OnInit, OnChanges { const currentValue = changes.activity.currentValue; if (currentValue.tasks?.length > 0) { - this.activityService.nonTeamActivity(changes.activity.currentValue?.tasks).then((nonTeamActivity) => { - this.isForTeamOnly = !nonTeamActivity; - this.cannotAccessTeamActivity.emit(this.isForTeamOnly); - }); + this.activityService + .nonTeamActivity(changes.activity.currentValue?.tasks) + .then((nonTeamActivity) => { + this.isForTeamOnly = !nonTeamActivity; + this.cannotAccessTeamActivity.emit(this.isForTeamOnly); + }); const unlockedTasks = this.unlockIndicatorService.getTasksByActivity(this.activity); + this.resetTaskIndicator(unlockedTasks); if (unlockedTasks.length === 0) { const clearedActivities = this.unlockIndicatorService.clearActivity(this.activity.id); clearedActivities.forEach((activity) => { - this.notificationsService.markTodoItemAsDone(activity).subscribe(); + this.notificationsService + .markTodoItemAsDone(activity) + .pipe(takeUntil(this.unsubscribe$)) + .subscribe(); }); } } } } - /** * Task icon type * diff --git a/projects/v3/src/app/components/assessment/assessment.component.ts b/projects/v3/src/app/components/assessment/assessment.component.ts index 09464ea65..dfe5b36c9 100644 --- a/projects/v3/src/app/components/assessment/assessment.component.ts +++ b/projects/v3/src/app/components/assessment/assessment.component.ts @@ -127,7 +127,7 @@ export class AssessmentComponent implements OnInit, OnChanges, OnDestroy { }), ).subscribe( (data: { - autoSave: boolean; + autoSave: boolean; // true: this request is for autosave; false: request is for submission (manual submission); goBack: boolean; questionSave?: { submissionId: number; @@ -297,7 +297,6 @@ export class AssessmentComponent implements OnInit, OnChanges, OnDestroy { this.doAssessment = true; if (this.submission) { this.savingMessage$.next($localize `Last saved ${this.utils.timeFormatter(this.submission.modified)}`); - this.btnDisabled$.next(false); } return; } @@ -637,6 +636,10 @@ export class AssessmentComponent implements OnInit, OnChanges, OnDestroy { return this.utils.isColor('red', this.storage.getUser().colors?.primary); } + /** + * Resubmit the assessment submission + * (mostly for regenerate AI feedback) + */ resubmit(): Subscription { if (!this.assessment?.id || !this.submission?.id || !this.activityId) { return; diff --git a/projects/v3/src/app/components/multi-team-member-selector/multi-team-member-selector.component.html b/projects/v3/src/app/components/multi-team-member-selector/multi-team-member-selector.component.html index 1695b0279..b1039ad18 100644 --- a/projects/v3/src/app/components/multi-team-member-selector/multi-team-member-selector.component.html +++ b/projects/v3/src/app/components/multi-team-member-selector/multi-team-member-selector.component.html @@ -11,7 +11,7 @@