src/app/manage-learn/project/project-details/project-details.component.ts
OnInit
selector | app-project-details |
styleUrls | ./project-details.component.scss |
templateUrl | ./project-details.component.html |
constructor(params: ActivatedRoute, headerService: AppHeaderService, translate: TranslateService, db: DbService, network: NetworkService, toast: ToastService, commonUtilService: CommonUtilService, router: Router, alert: AlertController, ref: ChangeDetectorRef, unnatiService: UnnatiDataService, location: Location, projectServ: ProjectService, modal: ModalController, utils: UtilsService, ngZone: NgZone, share: SharingFeatureService)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameters :
|
Async addNewTask |
addNewTask()
|
Returns :
unknown
|
doSyncAction |
doSyncAction()
|
Returns :
void
|
getAllActiveTasks |
getAllActiveTasks()
|
Returns :
void
|
getAssessmentTypeTaskId |
getAssessmentTypeTaskId()
|
Returns :
{}
|
getProject |
getProject()
|
Returns :
void
|
getProjectsApi | ||||
getProjectsApi(certificate?)
|
||||
Parameters :
Returns :
void
|
getProjectTaskStatus |
getProjectTaskStatus()
|
Returns :
void
|
ionViewWillEnter |
ionViewWillEnter()
|
Returns :
void
|
ionViewWillLeave |
ionViewWillLeave()
|
Returns :
void
|
ngOnInit |
ngOnInit()
|
Returns :
void
|
onAction | ||||
onAction(event)
|
||||
Parameters :
Returns :
void
|
onTaskAction | ||||
onTaskAction(event)
|
||||
Parameters :
Returns :
void
|
openResource | ||||
openResource(resource)
|
||||
Parameters :
Returns :
void
|
refreshTheActions |
refreshTheActions()
|
Returns :
void
|
segmentChanged | ||||
segmentChanged(event)
|
||||
Parameters :
Returns :
void
|
setActionButtons |
setActionButtons()
|
Returns :
void
|
setCardMetaData |
setCardMetaData()
|
Returns :
void
|
setHeaderConfig |
setHeaderConfig()
|
Returns :
void
|
submitImprovment |
submitImprovment()
|
Returns :
void
|
updateAssessmentStatus | ||||
updateAssessmentStatus(data)
|
||||
Parameters :
Returns :
void
|
updateLocalDb | ||||||
updateLocalDb(setIsEditTrue)
|
||||||
Parameters :
Returns :
void
|
_appHeaderSubscription |
Type : Subscription
|
_headerConfig |
Private _networkSubscription |
Type : Subscription
|
allStatusTypes |
Default value : statusType
|
allStrings |
cardMetaData |
categories |
Type : []
|
Default value : []
|
certificateCriteria |
Type : any
|
Default value : []
|
isNotSynced |
Type : boolean
|
networkFlag |
Type : boolean
|
Public params |
Type : ActivatedRoute
|
programId |
projectActions |
projectCompletionPercent |
projectDetails |
projectDetailsCopy |
projectId |
projectType |
segmentType |
Type : string
|
Default value : "details"
|
shareTaskId |
solutionId |
taskCount |
Type : number
|
Default value : 0
|
taskNoDataFound |
Type : string
|
Default value : "FRMELEMNTS_LBL_PLEASE_CREATE_AND_COMPLETE_TASKS"
|
templateId |
import { ChangeDetectorRef, Component, NgZone, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { AppHeaderService, CommonUtilService } from '@app/services';
import { TranslateService } from '@ngx-translate/core';
import { actions } from '../../core/constants/actions.constants';
import { DbService } from '../../core/services/db.service';
import { ToastService, NetworkService, ProjectService, statusType, UtilsService } from '../../core';
import { Subscription } from 'rxjs';
import { RouterLinks } from '@app/app/app.constant';
import { urlConstants } from '../../core/constants/urlConstants';
import { SharingFeatureService } from '../../core/services/sharing-feature.service';
import { AlertController, ModalController } from '@ionic/angular';
import { UnnatiDataService } from '../../core/services/unnati-data.service';
import { Location } from '@angular/common';
import * as _ from 'underscore';
import { CreateTaskFormComponent } from '../../shared';
@Component({
selector: 'app-project-details',
templateUrl: './project-details.component.html',
styleUrls: ['./project-details.component.scss'],
})
export class ProjectDetailsComponent implements OnInit {
projectId;
solutionId;
programId
templateId;
projectType;
_headerConfig;
allStrings;
projectDetails;
categories = [];
isNotSynced: boolean;
cardMetaData;
projectActions;
segmentType = "details";
networkFlag: boolean;
private _networkSubscription: Subscription;
shareTaskId
_appHeaderSubscription: Subscription;
projectCompletionPercent;
allStatusTypes = statusType;
taskCount = 0;
projectDetailsCopy;
taskNoDataFound="FRMELEMNTS_LBL_PLEASE_CREATE_AND_COMPLETE_TASKS"
certificateCriteria:any =[];
constructor(
public params: ActivatedRoute,
private headerService: AppHeaderService,
private translate: TranslateService,
private db: DbService,
private network: NetworkService,
private toast: ToastService,
private commonUtilService: CommonUtilService,
private router: Router,
private alert: AlertController,
private ref: ChangeDetectorRef,
private unnatiService: UnnatiDataService,
private location: Location,
private projectServ: ProjectService,
private modal: ModalController,
private utils: UtilsService,
private ngZone: NgZone,
private share: SharingFeatureService
) {
params.queryParams.subscribe((parameters) => {
this.networkFlag = this.commonUtilService.networkInfo.isNetworkAvailable;
this._networkSubscription = this.commonUtilService.networkAvailability$.subscribe(async (available: boolean) => {
this.networkFlag = available;
})
this.setHeaderConfig();
this.projectId = parameters.projectId;
this.solutionId = parameters.solutionId;
this.programId = parameters.programId;
this.projectType = parameters.type ? parameters.type : '';
this.templateId = parameters.templateId;
this.getProject()
});
}
ngOnInit() {
this.translate
.get([
"FRMELEMNTS_MSG_SOMETHING_WENT_WRONG",
"FRMELEMNTS_MSG_NO_ENTITY_MAPPED",
"FRMELEMNTS_MSG_CANNOT_GET_PROJECT_DETAILS",
"FRMELEMNTS_LBL_IMPORT_PROJECT_MESSAGE",
"YES",
"NO"
])
.subscribe((texts) => {
this.allStrings = texts;
});
}
ionViewWillEnter() {
this._appHeaderSubscription = this.headerService.headerEventEmitted$.subscribe(eventName => {
this.location.back();
});
}
ionViewWillLeave() {
if (this._appHeaderSubscription) {
this._appHeaderSubscription.unsubscribe();
}
}
setHeaderConfig() {
this._headerConfig = {
showHeader: true,
showBurgerMenu: false,
pageTitle: '',
actionButtons: [],
};
this.headerService.updatePageConfig(this._headerConfig);
}
refreshTheActions() {
this.setActionButtons();
this.projectCompletionPercent = this.projectServ.getProjectCompletionPercentage(this.projectDetails);
this.getAllActiveTasks();
}
getProject() {
if (this.projectId) {
this.db.query({ _id: this.projectId }).then(
(success) => {
if (success.docs.length) {
this.categories = [];
this.projectDetails = success.docs.length ? success.docs[0] : {};
if(this.projectDetails.certificate){
this.certificateCriteria =[];
let criteria = Object.keys(this.projectDetails?.certificate?.criteria?.conditions);
criteria.forEach(element => {
let config ={
name:this.projectDetails?.certificate?.criteria?.conditions[element].validationText
}
this.certificateCriteria.push(config);
})
}
this.setActionButtons();
this.isNotSynced = this.projectDetails ? (this.projectDetails.isNew || this.projectDetails.isEdit) : false;
this.projectDetails.categories.forEach((category: any) => {
category.label ? this.categories.push(category.label) : this.categories.push(category.name);
});
this.setCardMetaData();
this.projectCompletionPercent = this.projectServ.getProjectCompletionPercentage(this.projectDetails);
this.getProjectTaskStatus();
this.taskCount = this.utils.getTaskCount(this.projectDetails);
this.getAllActiveTasks();
} else {
this.getProjectsApi();
}
},
(error) => {
this.getProjectsApi();
}
);
} else {
this.getProjectsApi();
}
}
getAllActiveTasks() {
const profileDetailsCopy = { ...this.projectDetails }
let activeTask = _.filter(this.projectDetails.tasks, function(el) {
return !el.isDeleted;
});
profileDetailsCopy.tasks = activeTask;
this.ngZone.run(() => {
this.projectDetailsCopy = profileDetailsCopy;
})
}
setCardMetaData() {
this.cardMetaData = {
title: this.projectDetails.title,
subTitle: this.projectDetails.programName || null
}
}
segmentChanged(event) {
this.segmentType = event.detail.value;
}
setActionButtons() {
let defaultOptions = actions.PROJECT_ACTIONS;
if (this.projectDetails.isNew || this.projectDetails.isEdit) {
const indexOfSync = defaultOptions.length - 1;
defaultOptions[indexOfSync] = actions.SYNC_ACTION;
} else {
const indexOfSync = defaultOptions.length - 1;
defaultOptions[indexOfSync] = actions.SYNCED_ACTION;
}
if (this.projectDetails.downloaded) {
defaultOptions[0] = actions.DOWNLOADED_ACTION
} else {
defaultOptions[0] = actions.NOT_DOWNLOADED;
}
if (this.projectDetails.status === statusType.submitted) {
if(this.projectDetails.certificate){
defaultOptions = actions.SUBMITTED_PROJECT_ACTIONS.concat(actions.CERTIFICATE_ACTION);
}else{
defaultOptions = actions.SUBMITTED_PROJECT_ACTIONS
}
}
this.projectActions = defaultOptions;
}
doSyncAction() {
if (this.network.isNetworkAvailable) {
this.projectDetails.isNew
? this.projectServ.createNewProject(this.projectDetails)
: this.router.navigate([`${RouterLinks.PROJECT}/${RouterLinks.SYNC}`], { queryParams: { projectId: this.projectId } });
} else {
this.toast.showMessage('FRMELEMNTS_MSG_PLEASE_GO_ONLINE', 'danger');
}
}
onAction(event) {
switch (event) {
case 'download':
if (this.network.isNetworkAvailable) {
this.projectDetails.downloaded = true;
this.updateLocalDb();
this.toast.showMessage('FRMELEMNTS_MSG_DOWNLOADED_SUCCESSFULLY', 'success');
this.setActionButtons();
} else {
this.toast.showMessage('FRMELEMNTS_LBL_PROJECT_DOWNLOAD_OFFLINE', 'danger');
}
break;
case 'downloaded':
break;
case 'sync':
this.doSyncAction();
break;
case 'synced':
break;
case 'share':
this.network.isNetworkAvailable
? this.projectServ.openSyncSharePopup('shareProject', this.projectDetails.title, this.projectDetails)
: this.toast.showMessage('FRMELEMNTS_MSG_PLEASE_GO_ONLINE', 'danger');
break;
case 'files':
this.router.navigate([`${RouterLinks.ATTACHMENTS_LIST}`, this.projectDetails._id]);
break
case 'edit':
this.router.navigate([`/${RouterLinks.PROJECT}/${RouterLinks.PROJECT_EDIT}`, this.projectDetails._id]);
break;
case 'certificate':
this.getProjectsApi(true);
break
}
}
onTaskAction(event) {
switch (event.type) {
case 'deleteTask':
let index = 0;
for (const task of this.projectDetails.tasks) {
if(event.taskId === task._id){
break;
}
index++
}
this.projectDetails.tasks[index].isDeleted = true;
this.projectDetails.tasks[index].isEdit = true;
this.refreshTheActions();
this.updateLocalDb(true);
this.taskCount = this.utils.getTaskCount(this.projectDetails);
break
}
}
openResource(resource) {
this.projectServ.openResources(resource);
}
updateLocalDb(setIsEditTrue = false) {
this.projectDetails.isEdit = setIsEditTrue ? true : this.projectDetails.isEdit;
this.db.update(this.projectDetails).then(success => {
this.projectDetails._rev = success.rev;
this.taskCount = this.utils.getTaskCount(this.projectDetails);
})
}
getProjectsApi(certificate?) {
const payload = {
projectId: this.projectId,
solutionId: this.solutionId,
isProfileInfoRequired: false,
programId: this.programId,
templateId: this.templateId,
certificate : certificate
};
this.projectServ.getProjectDetails(payload);
}
getProjectTaskStatus() {
if (!this.projectDetails.tasks && !this.projectDetails.tasks.length) {
return
}
let taskIdArr = this.getAssessmentTypeTaskId()
if (!taskIdArr.length) {
return
}
if (!this.networkFlag) {
return;
}
const config = {
url: urlConstants.API_URLS.PROJCET_TASK_STATUS + `${this.projectDetails._id}`,
payload: {
taskIds: taskIdArr,
},
};
this.unnatiService.post(config).subscribe(
(success) => {
if (!success.result) {
return;
}
this.updateAssessmentStatus(success.result);
},
(error) => {
}
);
}
updateAssessmentStatus(data) {
// if task type is assessment or observation then check if it is submitted and change the status and update in db
let isChnaged = false
this.projectDetails.tasks.map((t) => {
data.map((d) => {
if (d.type == 'assessment' || d.type == 'observation') {//check if type is observation or assessment
if (d._id == t._id && d.submissionDetails.status) {
// check id matches and task details has submissionDetails
if (!t.submissionDetails || JSON.stringify(t.submissionDetails) != JSON.stringify(d.submissionDetails) ) {
t.submissionDetails = d.submissionDetails;
t.status = d.submissionDetails.status;
t.isEdit = true
isChnaged = true;
t.isEdit = true
this.projectDetails.isEdit = true
this.refreshTheActions();
}
}
}
});
});
isChnaged ? this.updateLocalDb(true) : null// if any assessment/observatiom task status is changed then only update
this.ref.detectChanges();
}
getAssessmentTypeTaskId() {
const assessmentTypeTaskIds = [];
for (const task of this.projectDetails.tasks) {
task.type === "assessment" || task.type === "observation" ? assessmentTypeTaskIds.push(task._id) : null;
}
return assessmentTypeTaskIds;
}
submitImprovment() {
if (!this.network.isNetworkAvailable) {
this.toast.showMessage('FRMELEMNTS_MSG_YOU_ARE_WORKING_OFFLINE_TRY_AGAIN', 'danger')
}
this.router.navigate([`${RouterLinks.PROJECT}/${RouterLinks.ADD_FILE}`, this.projectDetails._id])
}
async addNewTask() {
const modal = await this.modal.create({
component: CreateTaskFormComponent,
cssClass: "create-task-modal",
});
modal.onDidDismiss().then((data) => {
if (data.data) {
!this.projectDetails.tasks ? (this.projectDetails.tasks = []) : "";
this.projectDetails.status = this.projectDetails.status ? this.projectDetails.status : statusType.notStarted;
this.projectDetails.status = this.projectDetails.status == statusType.notStarted ? statusType.inProgress : this.projectDetails.status;
this.projectDetails.tasks.push(data.data);
this.toast.showMessage("FRMELEMNTS_MSG_NEW_TASK_ADDED_SUCCESSFUL", 'success');
this.updateLocalDb(true);
this.refreshTheActions();
}
});
return await modal.present();
}
}
<ion-content class="ion-padding">
<app-metadata-details translucent="true" [data]="cardMetaData" id="projectMetaDataCard">
<div class="certificate-tag" certificate *ngIf="projectDetails?.certificate">
{{'CERTIFICATE' | translate}}
</div>
<div class="sb-dt-card-actions">
<div class="wrapper">
<app-metadata-actions (actionEvent)="onAction($event)" [actionItems]="projectActions" id="projectActions"></app-metadata-actions>
</div>
<div class="sb-course-progress-container"
*ngIf="projectDetails?.status?.length && projectDetails?.status !== allStatusTypes.submitted" id="projectStatus">
<p><strong>{{'YOUR_PROGRESS_LABEL' | translate}}</strong>
</p>
<p>{{projectCompletionPercent?.completedTasks}} / {{projectCompletionPercent?.totalTasks}} {{'COMPLETED' |
translate}}
</p>
<ion-progress-bar
[value]="projectCompletionPercent?.completedTasks/projectCompletionPercent?.totalTasks"
[ngClass]="{'completed':projectCompletionPercent?.completedTasks===projectCompletionPercent?.totalTasks && projectCompletionPercent?.totalTasks !==0, 'in-progress': projectCompletionPercent?.completedTasks !== projectCompletionPercent?.totalTasks && projectCompletionPercent?.totalTasks !==0, 'zeroTask': projectCompletionPercent?.totalTasks == 0}"
class="progress-bar-style"></ion-progress-bar>
</div>
</div>
<div class="submit-text" *ngIf="(taskCount && projectCompletionPercent?.completedTasks == projectCompletionPercent?.totalTasks) && projectDetails?.status != allStatusTypes.submitted"> {{'FRMELEMNTS_LBL_TO_SUBMIT_PROJECT' | translate}} <ion-icon name="arrow-down"></ion-icon>
</div>
<ion-button (click)="submitImprovment()" id="submitImprovement"
*ngIf="projectDetails?.status && projectDetails?.status !== allStatusTypes.submitted" expand="block"
class="ion-text-none ion-margin-top custom-btn-txt-transform-none"
[ngClass]="{'button-disabled':projectCompletionPercent?.completedTasks !== projectCompletionPercent?.totalTasks || !taskCount}"
[disabled]="!taskCount || (projectCompletionPercent?.completedTasks !== projectCompletionPercent?.totalTasks)">
{{'FRMELEMNTS_LBL_SUBMIT_IMPROVEMENT' | translate}}
</ion-button>
<div class="sb-course-complete-container ion-padding" *ngIf="projectDetails?.status === allStatusTypes.submitted">
<div class="img-container">
<img class="success-badge" src='assets/imgs/Badge green.svg' alt="completed">
</div>
<div class="text-container">
<p><strong>{{'FRMELEMNTS_LBL_SUBMIT_IMPROVEMENT_SUCCESS_MESSAGE' | translate }}</strong></p>
</div>
</div>
</app-metadata-details>
<div class="project-segments">
<ion-segment [(ngModel)]="segmentType" (ionChange)="segmentChanged($event)" class="segment-card">
<ion-segment-button value="details" class="flex-5">
<ion-label class="font-12 text-transform-none">{{'FRMELEMNTS_LBL_PROJECT_DETAILS' | translate }}</ion-label>
</ion-segment-button>
<div class="hr-div">
<hr class="hr-height">
</div>
<ion-segment-button value="tasks" class="flex-5">
<ion-label class="font-12 text-transform-none">{{'FRMELEMNTS_LBL_TASK_DETAILS' | translate }}
</ion-label>
</ion-segment-button>
</ion-segment>
</div>
<div *ngIf="segmentType == 'details'">
<app-project-details-card [data]="projectDetails" [categories]="categories">
</app-project-details-card>
<app-accordion-list [data]="projectDetails?.learningResources" (actionEvent)="openResource($event)"
[title]="'FRMELEMNTS_LBL_LEARNING_RESOURCES'" *ngIf="projectDetails?.learningResources?.length">
</app-accordion-list>
<app-accordion-list *ngIf="certificateCriteria.length" [data]="certificateCriteria" [showCard]="false"
[title]="'FRMELEMNTS_LBL_CERTIFICATION_CRITERIA'"> </app-accordion-list>
</div>
<app-task-card *ngIf="segmentType == 'tasks'" [data]="projectDetailsCopy" (actionEvent)="onTaskAction($event)"
[viewOnly]="projectDetailsCopy?.status === allStatusTypes.submitted"></app-task-card>
<app-no-data class="ion-padding" *ngIf="segmentType == 'tasks' && taskCount==0 && (projectDetails?.status && projectDetails?.status !== allStatusTypes.submitted)" [message]="taskNoDataFound" [color]="'text-primary'"></app-no-data>
<ion-card class="add-task" (click)="addNewTask()" *ngIf="segmentType == 'tasks' && projectDetails?.status && projectDetails?.status !== allStatusTypes.submitted">
<ion-card-content>
<ion-grid>
<ion-row class="flex-box">
<ion-icon name="add-circle" class="icon"></ion-icon>
<ion-label class="label ion-margin-start">{{'FRMELEMNTS_LBL_ADD_YOUR_TASK' | translate}}</ion-label>
</ion-row>
</ion-grid>
</ion-card-content>
</ion-card>
</ion-content>
./project-details.component.scss
@import 'src/assets/styles/_custom-mixins';
@import "src/assets/styles/variables";
@import "src/assets/styles/_variables.scss";
.button-disabled {
--background: #707070 !important;
}
.completed {
--progress-background: var(--app-green) !important;
}
.zeroTask{
--progress-background: var(--app-lighter-gray) !important;
}
.in-progress {
--progress-background: var(--app-quaternary-medium) !important;
}
.sb-course-complete-container {
white-space: nowrap;
width: 100%;
background-color: map-get($colors, light_grayish_green);
@include padding(8px);
.img-container{
width: 20%;
vertical-align: middle;
display: inline-block;
}
.text-container{
color: map-get($colors, office_green);
font-family: "Noto Sans", sans-serif;
font-size: 0.875rem !important;
font-weight: bold;
width: 80%;
vertical-align: middle;
display: inline-block;
padding-left: 10px;
@include padding(0px 0px 0px 11px);
white-space: normal;
}
}
.add-task {
--background: var(--app-primary-light) !important;
background-color: var(--app-primary-light);
.flex-box {
display: flex;
align-items: center;
.icon {
color: var(--app-primary) !important;
font-size: 1.875rem;
}
.label {
flex: 1;
font-size: 0.875rem;
}
}
}
.submit-text{
color: red;
font-weight: 600;
padding: 10px 5px;
padding-bottom: 0px !important;
ion-icon{
background: red;
color: #fff;
border-radius: 50%;
padding: 2px;
vertical-align: middle;
margin-left: 3px;
}
}