diff --git a/projects/v3/src/app/components/activity/activity.component.html b/projects/v3/src/app/components/activity/activity.component.html
index efa3d4ca5..5b9f6562b 100644
--- a/projects/v3/src/app/components/activity/activity.component.html
+++ b/projects/v3/src/app/components/activity/activity.component.html
@@ -18,27 +18,40 @@
-
+
+
+
+
+
+
+
-
+ title="For team members only">
+
+
+
+
diff --git a/projects/v3/src/app/components/activity/activity.component.ts b/projects/v3/src/app/components/activity/activity.component.ts
index 0f1dd09f7..dd929575f 100644
--- a/projects/v3/src/app/components/activity/activity.component.ts
+++ b/projects/v3/src/app/components/activity/activity.component.ts
@@ -1,6 +1,6 @@
-import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { SharedService } from '@v3/app/services/shared.service';
-import { Activity, Task } from '@v3/services/activity.service';
+import { Activity, ActivityService, Task } from '@v3/services/activity.service';
import { Submission } from '@v3/services/assessment.service';
import { NotificationsService } from '@v3/services/notifications.service';
import { BrowserStorageService } from '@v3/services/storage.service';
@@ -11,17 +11,35 @@ import { UtilsService } from '@v3/services/utils.service';
templateUrl: './activity.component.html',
styleUrls: ['./activity.component.scss'],
})
-export class ActivityComponent {
+export class ActivityComponent implements OnChanges {
@Input() activity: Activity;
@Input() currentTask: Task;
@Input() submission: Submission;
@Output() navigate = new EventEmitter();
+
+ // when user isn't in a team & all tasks are found to be team tasks, emit this event
+ // true: user not allowed to access
+ // false: at least one non-team task
+ @Output() cannotAccessTeamActivity = new EventEmitter();
+ isForTeamOnly: boolean = false;
+
constructor(
private utils: UtilsService,
private storageService: BrowserStorageService,
private notificationsService: NotificationsService,
private sharedService: SharedService,
- ) { }
+ private activityService: ActivityService
+ ) {}
+
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes.activity?.currentValue?.tasks?.length > 0) {
+ this.activityService.nonTeamActivity(changes.activity.currentValue?.tasks).then((nonTeamActivity) => {
+ this.isForTeamOnly = !nonTeamActivity;
+ this.cannotAccessTeamActivity.emit(this.isForTeamOnly);
+ });
+ }
+ }
+
/**
* Task icon type
diff --git a/projects/v3/src/app/components/topic/topic.component.html b/projects/v3/src/app/components/topic/topic.component.html
index 3dabeeec6..1299042cc 100644
--- a/projects/v3/src/app/components/topic/topic.component.html
+++ b/projects/v3/src/app/components/topic/topic.component.html
@@ -36,7 +36,8 @@
diff --git a/projects/v3/src/app/components/topic/topic.component.ts b/projects/v3/src/app/components/topic/topic.component.ts
index 5739f6f9d..0919e90c9 100644
--- a/projects/v3/src/app/components/topic/topic.component.ts
+++ b/projects/v3/src/app/components/topic/topic.component.ts
@@ -9,6 +9,8 @@ import { EmbedVideoService } from '@v3/services/ngx-embed-video.service';
import { SafeHtml } from '@angular/platform-browser';
import { FilestackService } from '@v3/app/services/filestack.service';
import { NotificationsService } from '@v3/app/services/notifications.service';
+import { BehaviorSubject } from 'rxjs';
+import { Activity, Task } from '@v3/app/services/activity.service';
@Component({
selector: 'app-topic',
@@ -17,8 +19,11 @@ import { NotificationsService } from '@v3/app/services/notifications.service';
})
export class TopicComponent implements OnChanges {
@Input() topic: Topic;
+ @Input() task: Task;
continuing: boolean;
@Output() continue = new EventEmitter();
+ @Input() buttonDisabled$: BehaviorSubject = new BehaviorSubject(false);
+ thisTask
iframeHtml = '' as SafeHtml;
btnToggleTopicIsDone = false;
@@ -42,14 +47,10 @@ export class TopicComponent implements OnChanges {
}
this._initVideoPlayer();
}
- // mark topic as started after topic load
- // this._markAsStartStop('started');
}
ionViewWillLeave() {
this.sharedService.stopPlayingVideos();
- // mark topic as stopped when leave topic page
- // this._markAsStartStop('stopped');
}
private _setVideoUrlElelemts() {
diff --git a/projects/v3/src/app/pages/activity-desktop/activity-desktop.page.html b/projects/v3/src/app/pages/activity-desktop/activity-desktop.page.html
index aa4410b37..1a3a4bb7c 100644
--- a/projects/v3/src/app/pages/activity-desktop/activity-desktop.page.html
+++ b/projects/v3/src/app/pages/activity-desktop/activity-desktop.page.html
@@ -25,34 +25,45 @@
[currentTask]="currentTask"
[submission]="submission"
(navigate)="goToTask($event)"
+ (cannotAccessTeamActivity)="allTeamTasks($event)"
>
-
-
-
-
+
+
+ This assessment can only be accessed when you are in a team.
+
+
+
+
+
+
+
+
+
diff --git a/projects/v3/src/app/pages/activity-desktop/activity-desktop.page.scss b/projects/v3/src/app/pages/activity-desktop/activity-desktop.page.scss
index 2839b5803..5edc8139b 100644
--- a/projects/v3/src/app/pages/activity-desktop/activity-desktop.page.scss
+++ b/projects/v3/src/app/pages/activity-desktop/activity-desktop.page.scss
@@ -23,3 +23,11 @@ ion-content {
.no-review {
padding: 10px 15%;
}
+
+.centered-text {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100vh;
+ text-align: center;
+}
diff --git a/projects/v3/src/app/pages/activity-desktop/activity-desktop.page.ts b/projects/v3/src/app/pages/activity-desktop/activity-desktop.page.ts
index 1db9c6691..cfc41ab98 100644
--- a/projects/v3/src/app/pages/activity-desktop/activity-desktop.page.ts
+++ b/projects/v3/src/app/pages/activity-desktop/activity-desktop.page.ts
@@ -8,7 +8,7 @@ import { BrowserStorageService } from '@v3/app/services/storage.service';
import { Topic, TopicService } from '@v3/app/services/topic.service';
import { UtilsService } from '@v3/app/services/utils.service';
import { BehaviorSubject, Subscription } from 'rxjs';
-import { delay, tap } from 'rxjs/operators';
+import { delay, filter, tap } from 'rxjs/operators';
const SAVE_PROGRESS_TIMEOUT = 10000;
@@ -28,6 +28,7 @@ export class ActivityDesktopPage {
loading: boolean;
savingText$: BehaviorSubject = new BehaviorSubject('');
btnDisabled$: BehaviorSubject = new BehaviorSubject(false);
+ notInATeamAndForTeamOnly: boolean = false;
// grabs from URL parameter
urlParams = {
@@ -49,7 +50,11 @@ export class ActivityDesktopPage {
ionViewWillEnter() {
this.subscriptions.push(
- this.activityService.activity$.subscribe(res => this.activity = res)
+ this.activityService.activity$
+ .pipe(filter(res => res?.id === +this.route.snapshot.paramMap.get('id')))
+ .subscribe(res => {
+ this.activity = res;
+ })
);
this.subscriptions.push(
this.activityService.currentTask$.subscribe(res => this.currentTask = res)
@@ -105,6 +110,11 @@ export class ActivityDesktopPage {
}));
}
+ ionViewWillLeave() {
+ this.currentTask = null;
+ this.topicService.clearTopic();
+ }
+
ionViewDidLeave() {
this.subscriptions.forEach(sub => {
if (sub.closed !== true) {
@@ -114,6 +124,7 @@ export class ActivityDesktopPage {
}
async goToTask(task: Task): Promise {
+ this.currentTask = null;
const taskContentElement = this.document.getElementById('task-content');
if (taskContentElement) {
taskContentElement.focus();
@@ -123,6 +134,7 @@ export class ActivityDesktopPage {
}
async topicComplete(task: Task) {
+ this.btnDisabled$.next(true);
if (task.status === 'done') {
// just go to the next task without any other action
this.btnDisabled$.next(false);
@@ -131,9 +143,11 @@ export class ActivityDesktopPage {
// mark the topic as complete
this.loading = true;
await this.topicService.updateTopicProgress(task.id, 'completed').toPromise();
+
// get the latest activity tasks and navigate to the next task
return this.activityService.getActivity(this.activity.id, true, task, () => {
this.loading = false;
+ this.btnDisabled$.next(false);
});
}
@@ -197,14 +211,14 @@ export class ActivityDesktopPage {
}
}
- async readFeedback(submissionId, task: Task) {
+ async readFeedback(submissionId, currentTask: Task) {
try {
this.loading = true;
const savedReview = this.assessmentService.saveFeedbackReviewed(submissionId);
await savedReview.pipe(
// get the latest activity tasks and navigate to the next task
// wait for a while for the server to save the "read feedback" status
- tap(() => this.activityService.getActivity(this.activity.id, true, task)),
+ tap(() => this.activityService.getActivity(this.activity.id, true, currentTask)),
delay(400)
).toPromise();
await this.reviewRatingPopUp();
@@ -233,6 +247,12 @@ export class ActivityDesktopPage {
}
goBack() {
+ this.currentTask = null;
+ this.topicService.clearTopic();
this.router.navigate(['v3', 'home']);
}
+
+ allTeamTasks(forTeamOnlyWarning: boolean) {
+ this.notInATeamAndForTeamOnly = forTeamOnlyWarning;
+ }
}
diff --git a/projects/v3/src/app/pages/home/home.page.html b/projects/v3/src/app/pages/home/home.page.html
index 101cf4841..d4441a043 100644
--- a/projects/v3/src/app/pages/home/home.page.html
+++ b/projects/v3/src/app/pages/home/home.page.html
@@ -128,7 +128,8 @@
+
diff --git a/projects/v3/src/app/pages/topic-mobile/topic-mobile.page.ts b/projects/v3/src/app/pages/topic-mobile/topic-mobile.page.ts
index 2e9634170..4a3e111f6 100644
--- a/projects/v3/src/app/pages/topic-mobile/topic-mobile.page.ts
+++ b/projects/v3/src/app/pages/topic-mobile/topic-mobile.page.ts
@@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ActivityService, Task } from '@v3/app/services/activity.service';
import { TopicService, Topic } from '@v3/app/services/topic.service';
+import { BehaviorSubject } from 'rxjs';
@Component({
selector: 'app-topic-mobile',
@@ -10,10 +11,11 @@ import { TopicService, Topic } from '@v3/app/services/topic.service';
})
export class TopicMobilePage implements OnInit {
topic$ = this.topicService.topic$;
+ btnDisabled$: BehaviorSubject = new BehaviorSubject(false);
topic: Topic;
activityId: number;
- currentTask: Task
+ currentTask: Task;
constructor(
private route: ActivatedRoute,
@@ -32,6 +34,7 @@ export class TopicMobilePage implements OnInit {
}
async continue() {
+ this.btnDisabled$.next(true);
if (!this.currentTask) {
this.currentTask = {
id: this.topic.id,
@@ -40,16 +43,20 @@ export class TopicMobilePage implements OnInit {
status: ''
};
}
+
if (this.currentTask.status === 'done') {
// just go to the next task without any other action
- await this.activityService.goToNextTask(this.currentTask);
- // this.btnDisabled$.next(false); - conflicts from [CORE-6106]
+ this.activityService.goToNextTask(this.currentTask);
+ this.btnDisabled$.next(false);
return;
}
+
// mark the topic as completer
- await this.topicService.updateTopicProgress(this.topic.id, 'completed').subscribe();
+ await this.topicService.updateTopicProgress(this.topic.id, 'completed').toPromise();
// get the latest activity tasks and navigate to the next task
- return this.activityService.getActivity(this.activityId, true, this.currentTask);
+ return this.activityService.getActivity(this.activityId, true, this.currentTask, () => {
+ this.btnDisabled$.next(false);
+ });
}
goBack() {
diff --git a/projects/v3/src/app/services/activity.service.ts b/projects/v3/src/app/services/activity.service.ts
index 2d6abd99b..39f112378 100644
--- a/projects/v3/src/app/services/activity.service.ts
+++ b/projects/v3/src/app/services/activity.service.ts
@@ -191,6 +191,7 @@ export class ActivityService {
};
}
});
+
this._activity$.next(result);
this.activity = result;
if (goToNextTask) {
@@ -248,6 +249,12 @@ export class ActivityService {
// if there is no next task
if (!nextTask) {
if (afterTask) {
+ this.assessment.getAssessment(
+ afterTask.id,
+ 'assessment',
+ this.activity.id,
+ afterTask.contextId
+ );
return this._activityCompleted(hasUnfinishedTask);
}
nextTask = tasks[0]; // go to the first task
@@ -305,4 +312,27 @@ export class ActivityService {
}
}
+
+ /**
+ * @name nonTeamActivity
+ * @description check if the activity is accessible by current
+ * user (team or individual assessment).
+ * When milestone contain only team assessment, only participant from a team
+ * can access the activities.
+ *
+ * @param {number} activityId
+ *
+ * @return {Promise} false when inaccessible, otherwise true
+ */
+ async nonTeamActivity(tasks?: Task[]): Promise {
+ const teamStatus = await this.sharedService.getTeamInfo().toPromise();
+ if (teamStatus?.data?.user?.teams.length > 0) {
+ return true;
+ }
+
+ const nonTeamAsmt = (tasks || [])
+ .filter((task: Task) => task.isForTeam !== true);
+
+ return nonTeamAsmt.length > 0;
+ }
}
diff --git a/projects/v3/src/app/services/assessment.service.ts b/projects/v3/src/app/services/assessment.service.ts
index a98b24b07..7d1bb9f04 100644
--- a/projects/v3/src/app/services/assessment.service.ts
+++ b/projects/v3/src/app/services/assessment.service.ts
@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
-import { BehaviorSubject, of } from 'rxjs';
+import { BehaviorSubject, of, Subscription } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { RequestService } from 'request';
import { UtilsService } from '@v3/services/utils.service';
@@ -136,7 +136,7 @@ export class AssessmentService {
this._assessment$.next(null);
}
- getAssessment(id, action, activityId, contextId, submissionId?) {
+ getAssessment(id, action, activityId, contextId, submissionId?): Subscription {
if (!this.assessment || this.assessment.id !== id) {
this.clearAssessment();
}
diff --git a/projects/v3/src/app/services/home.service.ts b/projects/v3/src/app/services/home.service.ts
index 5d522e2c1..5b71e3589 100644
--- a/projects/v3/src/app/services/home.service.ts
+++ b/projects/v3/src/app/services/home.service.ts
@@ -7,7 +7,7 @@ import { ApolloService } from './apollo.service';
import { NotificationsService } from './notifications.service';
import { AuthService } from './auth.service';
import { SharedService } from './shared.service';
-import { ActivityService, TaskBase } from './activity.service';
+import { ActivityBase, ActivityService, Task, TaskBase } from './activity.service';
export interface Experience {
leadImage: string;
@@ -186,28 +186,4 @@ export class HomeService {
this._projectProgress$.next(data.data.project);
this._experienceProgress$.next(Math.round(data.data.project.progress * 100));
}
-
- /**
- * @name isAccessible
- * @description check if the activity is accessible by current
- * user (team or individual assessment).
- * When milestone contain only team assessment, only participant from a team
- * can access the activities.
- *
- * @param {number} activityId
- *
- * @return {Promise} false when inaccessible, otherwise true
- */
- async isAccessible(activityId: number): Promise {
- const teamStatus = await this.sharedServise.getTeamInfo().toPromise();
- if (teamStatus?.data?.user?.teams.length > 0) {
- return true;
- }
-
- const activitiesBase = await this.activityService.getActivityBase(activityId).toPromise();
- const nonTeamAsmt = (activitiesBase?.data?.activity?.tasks || [])
- .filter((task: TaskBase) => task.isTeam !== true);
-
- return nonTeamAsmt.length > 0;
- }
}