diff --git a/projects/v3/src/app/components/assessment/assessment.component.html b/projects/v3/src/app/components/assessment/assessment.component.html
index f83e8a57e..c4165efdf 100644
--- a/projects/v3/src/app/components/assessment/assessment.component.html
+++ b/projects/v3/src/app/components/assessment/assessment.component.html
@@ -144,6 +144,21 @@
{{ group.name }}
+
+
+
+
+
+
visible', animate('200ms ease-out')),
+ transition('visible => hidden', animate('100ms ease-in')),
+ ]),
+ ],
})
export class AssessmentComponent implements OnInit, OnChanges, OnDestroy {
/**
@@ -46,6 +55,22 @@ export class AssessmentComponent implements OnInit, OnChanges, OnDestroy {
// continue to the next task
@Output() continue = new EventEmitter();
+ autosaving: {
+ [key: number]: boolean
+ } = {};
+ saved: {
+ [key:number]: boolean
+ } = {};
+
+ onAnimationEnd(event, questionId: number) {
+ if (event.toState === 'visible') {
+ // Animation has ended with the tick being visible, now toggle the saved flag after a short delay
+ timer(1000).pipe(take(1)).subscribe(() => {
+ this.autosaving[questionId] = false;
+ });
+ }
+ }
+
// used to resubscribe to the assessment service
resubscribe$ = new Subject();
// used to save the assessment/review answers
@@ -115,9 +140,12 @@ export class AssessmentComponent implements OnInit, OnChanges, OnDestroy {
filter(() => !this._preventSubmission()), // skip when false
concatMap(request => {
if (request?.reviewSave) {
+ // this.saved[request.reviewSave.questionId] = true;
return this.saveReviewAnswer(request.reviewSave);
}
if (request?.questionSave) {
+ this.autosaving[request.questionSave.questionId] = true;
+ this.saved[request.questionSave.questionId] = false;
return this.saveQuestionAnswer(request.questionSave);
}
return of(request);
@@ -192,6 +220,10 @@ export class AssessmentComponent implements OnInit, OnChanges, OnDestroy {
questionInput.questionId,
answer,
).pipe(
+ tap((_res) => {
+ this.autosaving[questionInput.questionId] = false;
+ this.saved[questionInput.questionId] = true;
+ }),
delay(800)
);
}
diff --git a/projects/v3/src/app/components/branding-logo/branding-logo.component.html b/projects/v3/src/app/components/branding-logo/branding-logo.component.html
index cdc48b1ec..4dbb2d8e7 100644
--- a/projects/v3/src/app/components/branding-logo/branding-logo.component.html
+++ b/projects/v3/src/app/components/branding-logo/branding-logo.component.html
@@ -1 +1 @@
-
+
diff --git a/projects/v3/src/app/components/branding-logo/branding-logo.component.ts b/projects/v3/src/app/components/branding-logo/branding-logo.component.ts
index 57b7550d3..b9df6abe8 100644
--- a/projects/v3/src/app/components/branding-logo/branding-logo.component.ts
+++ b/projects/v3/src/app/components/branding-logo/branding-logo.component.ts
@@ -9,5 +9,7 @@ export class BrandingLogoComponent {
@Input() logo: string;
@Input() name?: string;
- constructor(public storage: BrowserStorageService) {}
+ constructor(public storage: BrowserStorageService) {
+ this.logo = this.logo || this.storage.getConfig().logo;
+ }
}
diff --git a/projects/v3/src/app/components/multiple/multiple.component.html b/projects/v3/src/app/components/multiple/multiple.component.html
index 6ffa2e30d..c6eb2277f 100644
--- a/projects/v3/src/app/components/multiple/multiple.component.html
+++ b/projects/v3/src/app/components/multiple/multiple.component.html
@@ -87,6 +87,7 @@ {
>
+
;
@Input() question;
@@ -33,17 +35,19 @@ export class MultipleComponent implements ControlValueAccessor, OnInit {
@Input() doReview: Boolean;
// FormControl that is passed in from parent component
@Input() control: AbstractControl;
- // answer field for submitter & reviewer
- @ViewChild('answer') answerRef: ElementRef;
// comment field for reviewer
@ViewChild('commentEle') commentRef: ElementRef;
+ autosave$ = new Subject();
+
// the value of answer
innerValue: any;
comment: string;
// validation errors array
errors: Array = [];
+ subscriptions: Subscription[] = [];
+
constructor(
private utils: UtilsService,
) {}
@@ -52,6 +56,46 @@ export class MultipleComponent implements ControlValueAccessor, OnInit {
this._showSavedAnswers();
}
+ ngAfterViewInit() {
+ this.autosave$.pipe(
+ debounceTime(800),
+ ).subscribe(() => {
+ const action: {
+ autoSave?: boolean;
+ goBack?: boolean;
+ questionSave?: {};
+ reviewSave?: {};
+ } = {
+ autoSave: true,
+ goBack: false,
+ };
+
+ if (this.doReview === true) {
+ action.reviewSave = {
+ reviewId: this.reviewId,
+ submissionId: this.submissionId,
+ questionId: this.question.id,
+ answer: this.innerValue.answer,
+ comment: this.innerValue.comment,
+ };
+ }
+
+ if (this.doAssessment === true) {
+ action.questionSave = {
+ submissionId: this.submissionId,
+ questionId: this.question.id,
+ answer: this.innerValue,
+ };
+ }
+
+ this.submitActions$.next(action);
+ });
+ }
+
+ ngOnDestroy() {
+ this.subscriptions.forEach(sub => sub.unsubscribe());
+ }
+
// propagate changes into the form control
propagateChange = (_: any) => {};
@@ -106,35 +150,7 @@ export class MultipleComponent implements ControlValueAccessor, OnInit {
}
}
- const action: {
- autoSave?: boolean;
- goBack?: boolean;
- questionSave?: {};
- reviewSave?: {};
- } = {
- autoSave: true,
- goBack: false,
- };
-
- if (this.doReview === true) {
- action.reviewSave = {
- reviewId: this.reviewId,
- submissionId: this.submissionId,
- questionId: this.question.id,
- answer: this.innerValue.answer,
- comment: this.innerValue.comment,
- };
- }
-
- if (this.doAssessment === true) {
- action.questionSave = {
- submissionId: this.submissionId,
- questionId: this.question.id,
- answer: this.innerValue,
- };
- }
-
- this.submitActions$.next(action);
+ this.autosave$.next();
}
// From ControlValueAccessor interface
diff --git a/projects/v3/src/app/components/oneof/oneof.component.ts b/projects/v3/src/app/components/oneof/oneof.component.ts
index 84543b40b..06d2796db 100644
--- a/projects/v3/src/app/components/oneof/oneof.component.ts
+++ b/projects/v3/src/app/components/oneof/oneof.component.ts
@@ -1,6 +1,7 @@
-import { Component, Input, Output, EventEmitter, forwardRef, ViewChild, ElementRef, OnInit } from '@angular/core';
-import { NG_VALUE_ACCESSOR, ControlValueAccessor, FormControl, AbstractControl } from '@angular/forms';
+import { Component, Input, forwardRef, ViewChild, ElementRef, OnInit } from '@angular/core';
+import { NG_VALUE_ACCESSOR, ControlValueAccessor, AbstractControl } from '@angular/forms';
import { Subject } from 'rxjs';
+import { debounceTime } from 'rxjs/operators';
@Component({
selector: 'app-oneof',
@@ -43,12 +44,50 @@ export class OneofComponent implements ControlValueAccessor, OnInit {
// validation errors array
errors: Array = [];
+ autosave$ = new Subject();
+
constructor() {}
ngOnInit() {
this._showSavedAnswers();
}
+ ngAfterViewInit() {
+ this.autosave$.pipe(
+ debounceTime(800),
+ ).subscribe(() => {
+ const action: {
+ autoSave?: boolean;
+ goBack?: boolean;
+ questionSave?: {};
+ reviewSave?: {};
+ } = {
+ autoSave: true,
+ goBack: false,
+ };
+
+ if (this.doReview === true) {
+ action.reviewSave = {
+ reviewId: this.reviewId,
+ submissionId: this.submissionId,
+ questionId: this.question.id,
+ answer: this.innerValue.answer,
+ comment: this.innerValue.comment,
+ };
+ }
+
+ if (this.doAssessment === true) {
+ action.questionSave = {
+ submissionId: this.submissionId,
+ questionId: this.question.id,
+ answer: this.innerValue,
+ };
+ }
+
+ this.submitActions$.next(action);
+ });
+ }
+
// propagate changes into the form control
propagateChange = (_: any) => {};
@@ -83,35 +122,7 @@ export class OneofComponent implements ControlValueAccessor, OnInit {
}
}
- const action: {
- autoSave?: boolean;
- goBack?: boolean;
- questionSave?: {};
- reviewSave?: {};
- } = {
- autoSave: true,
- goBack: false,
- };
-
- if (this.doReview === true) {
- action.reviewSave = {
- reviewId: this.reviewId,
- submissionId: this.submissionId,
- questionId: this.question.id,
- answer: this.innerValue.answer,
- comment: this.innerValue.comment,
- };
- }
-
- if (this.doAssessment === true) {
- action.questionSave = {
- submissionId: this.submissionId,
- questionId: this.question.id,
- answer: this.innerValue,
- };
- }
-
- this.submitActions$.next(action);
+ this.autosave$.next();
}
// From ControlValueAccessor interface
diff --git a/projects/v3/src/app/components/text/text.component.ts b/projects/v3/src/app/components/text/text.component.ts
index 54c533c17..7fa53296e 100644
--- a/projects/v3/src/app/components/text/text.component.ts
+++ b/projects/v3/src/app/components/text/text.component.ts
@@ -1,7 +1,7 @@
import { Component, Input, forwardRef, ViewChild, ElementRef, OnInit, AfterViewInit, OnDestroy } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor, FormControl, AbstractControl } from '@angular/forms';
import { IonTextarea } from '@ionic/angular';
-import { AssessmentService, Question } from '@v3/services/assessment.service';
+import { Question } from '@v3/services/assessment.service';
import { Subject, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged, filter, map } from 'rxjs/operators';
@@ -48,9 +48,7 @@ export class TextComponent implements ControlValueAccessor, OnInit, AfterViewIni
// validation errors array
errors: Array = [];
- constructor(
- private assessmentService: AssessmentService,
- ) {}
+ constructor() {}
ngOnInit() {
this._showSavedAnswers();
@@ -60,8 +58,8 @@ export class TextComponent implements ControlValueAccessor, OnInit, AfterViewIni
if (this.answerRef?.ionInput) {
this.subcriptions.push(this.answerRef.ionInput.pipe(
map(e => (e.target as HTMLInputElement).value),
- filter(text => text.length > 0),
- debounceTime(1250),
+ filter(text => text.length >= 0),
+ debounceTime(800),
distinctUntilChanged(),
).subscribe(_data => {
const action: {
diff --git a/projects/v3/src/app/services/utils.service.spec.ts b/projects/v3/src/app/services/utils.service.spec.ts
index abc345876..f969a9383 100644
--- a/projects/v3/src/app/services/utils.service.spec.ts
+++ b/projects/v3/src/app/services/utils.service.spec.ts
@@ -123,39 +123,6 @@ describe('UtilsService', () => {
expect(result.length).toEqual(0);
expect(result.length).not.toEqual(1);
});
-
- it('should accept object and remove subject from it', () => {
- const result = service.addOrRemove