File

src/app/manage-learn/project/task-view/task-view.page.ts

Metadata

Index

Properties
Methods

Constructor

constructor(router: Router, params: ActivatedRoute, db: DbService, utils: UtilsService, toast: ToastService, translate: TranslateService, alert: AlertController, attachmentService: AttachmentService, location: Location, networkService: NetworkService, headerService: AppHeaderService, popupService: GenericPopUpService, contentService: ContentService, navigateService: NavigationService, commonUtilService: CommonUtilService, routereParams: ActivatedRoute)
Parameters :
Name Type Optional
router Router No
params ActivatedRoute No
db DbService No
utils UtilsService No
toast ToastService No
translate TranslateService No
alert AlertController No
attachmentService AttachmentService No
location Location No
networkService NetworkService No
headerService AppHeaderService No
popupService GenericPopUpService No
contentService ContentService No
navigateService NavigationService No
commonUtilService CommonUtilService No
routereParams ActivatedRoute No

Methods

Public addSubtask
addSubtask()
Returns : void
Async askPermissionToDelete
askPermissionToDelete(subtask, type)
Parameters :
Name Optional
subtask No
type No
Returns : any
checkDisabled
checkDisabled()
Returns : boolean
closemarkTaskAsCompleted
closemarkTaskAsCompleted()
Returns : void
delete
delete(data)
Parameters :
Name Optional
data No
Returns : void
doAction
doAction()
Returns : void
Async edit
edit(what, placeholder: string, subtask?, subTaskIndex?)
Parameters :
Name Type Optional Default value
what No
placeholder string No ""
subtask Yes
subTaskIndex Yes
Returns : any
enableTaskMarkButton
enableTaskMarkButton()
Returns : void
getSubtasksCount
getSubtasksCount(task)
Parameters :
Name Optional
task No
Returns : any
getTask
getTask()
Returns : void
insertAttachment
insertAttachment()
Returns : void
ionViewWillEnter
ionViewWillEnter()
Returns : void
openAction
openAction()
Returns : void
openBodh
openBodh(link)
Parameters :
Name Optional
link No
Returns : void
Async openEditModal
openEditModal(what, name, placeholder, subtask, subTaskIndex)
Parameters :
Name Optional
what No
name No
placeholder No
subtask No
subTaskIndex No
Returns : any
openResources
openResources(task)
Parameters :
Name Optional
task No
Returns : void
prepareSubTaskMeta
prepareSubTaskMeta()
Returns : void
saveChanges
saveChanges()
Returns : void
saveSubTaskChanges
saveSubTaskChanges(subtask, index)
Parameters :
Name Optional
subtask No
index No
Returns : void
selectedStatus
selectedStatus(event)
Parameters :
Name Optional
event No
Returns : void
selectedTaskStatus
selectedTaskStatus(event)
Parameters :
Name Optional
event No
Returns : void
setDate
setDate()
Returns : void
setTaskEndDate
setTaskEndDate()
Returns : void
toEdit
toEdit(type, copyOfString)
Parameters :
Name Optional
type No
copyOfString No
Returns : void
update
update(goBack?)
Parameters :
Name Optional
goBack Yes
Returns : void

Properties

attachments
Type : []
Default value : []
copyOfSelectEditField
copyOfTaskDetails
currentYear
Default value : new Date().getFullYear()
editField
enableMarkButton
Type : boolean
Default value : false
headerConfig
Type : object
Default value : { showHeader: true, showBurgerMenu: false, actionButtons: [] }
newSubtask
Type : any
Default value : {}
parameters
project
projectCopy
showAttachments
Type : boolean
Default value : false
stateData
statuses
Default value : statuses
sTime
Decorators :
@ViewChild('dateTime', {static: false})
subTaskCount
Type : number
Default value : 0
task
viewOnlyMode
Type : boolean
Default value : false
import { Component, ViewChild, Inject } from "@angular/core";
import { Router, ActivatedRoute } from "@angular/router";
import * as _ from "underscore";
import { TranslateService } from "@ngx-translate/core";
import { AlertController } from "@ionic/angular";
import { Location } from "@angular/common";
import { statuses,statusType } from "../../core/constants/statuses.constant";
import { UtilsService } from "../../core/services/utils.service";
import { NetworkService } from "../../core/services/network.service";
import { AppHeaderService, CommonUtilService } from "@app/services";
import { DbService } from "../../core/services/db.service";
import { AttachmentService, ToastService } from "../../core";
import { GenericPopUpService } from '../../shared';
import { ContentDetailRequest, Content, ContentService } from 'sunbird-sdk';
import { NavigationService } from '@app/services/navigation-handler.service';
import { RouterLinks } from "@app/app/app.constant";


var environment = {
  db: {
    projects: "project.db",
    categories: "categories.db",
  },
  deepLinkAppsUrl: ''
};
@Component({
  selector: "app-task-view",
  templateUrl: "./task-view.page.html",
  styleUrls: ["./task-view.page.scss"],
})
export class TaskViewPage {
  parameters;
  @ViewChild("dateTime", { static: false }) sTime;
  editField;
  task;
  project;
  copyOfTaskDetails;
  attachments = [];
  showAttachments: boolean = false;
  enableMarkButton: boolean = false;
  subTaskCount: number = 0;
  newSubtask: any = {};
  currentYear = new Date().getFullYear();
  statuses = statuses;
  projectCopy;
  copyOfSelectEditField;
  headerConfig = {
    showHeader: true,
    showBurgerMenu: false,
    actionButtons: []
  };
  viewOnlyMode: boolean = false;
  stateData;

  constructor(
    private router: Router,
    private params: ActivatedRoute,
    private db: DbService,
    private utils: UtilsService,
    private toast: ToastService,
    private translate: TranslateService,
    private alert: AlertController,
    private attachmentService: AttachmentService,
    private location: Location,
    private networkService: NetworkService,
    private headerService: AppHeaderService,
    private popupService: GenericPopUpService,
    @Inject('CONTENT_SERVICE') private contentService: ContentService,
    private navigateService: NavigationService,
    private commonUtilService: CommonUtilService,
    private routereParams: ActivatedRoute
    // private openResourceSrvc: OpenResourcesService
  ) {
    this.saveChanges = _.debounce(this.saveChanges, 800);
    this.saveSubTaskChanges = _.debounce(this.saveSubTaskChanges, 800);
    routereParams.queryParams.subscribe(params => {
      this.viewOnlyMode = (params.viewOnlyMode === 'true');
    })
    params.params.subscribe((parameters) => {
      this.parameters = parameters;
      this.getTask();
      this.prepareSubTaskMeta();
    });
    this.stateData = this.router.getCurrentNavigation().extras.state;


  }

  


  ionViewWillEnter() {
    this.headerConfig = this.headerService.getDefaultPageConfig();
    this.headerConfig.actionButtons = [];
    this.headerConfig.showHeader = true;
    this.headerConfig.showBurgerMenu = false;
    this.headerService.updatePageConfig(this.headerConfig);
  }

  prepareSubTaskMeta() {
    this.newSubtask = JSON.parse(JSON.stringify(this.utils.getMetaData("subTask")));
  }

  getTask() {
    this.db.query({ _id: this.parameters.id }).then(
      (success) => {
        if(success?.docs.length){
          this.project = success.docs[0]
        } else {
          this.viewOnlyMode = true;
          this.project = this.stateData.projectDetails;
        }
        // this.project = success.docs.length ? success.docs[0] : success.docs;
        this.projectCopy = JSON.parse(JSON.stringify(this.project));
        let task = _.findIndex(this.projectCopy.tasks, (item) => {
          return item._id == this.parameters.taskId;
        });
        task > -1 ? (this.task = this.project.tasks[task]) : this.toast.showMessage("FRMELEMNTS_MSG_NO_TASK_FOUND", "danger");
        this.enableMarkButton = this.task.status === 'completed' ? true : false;
        this.copyOfTaskDetails = JSON.stringify(this.task);
        this.attachments = [];
        this.getSubtasksCount(this.task).then((data: number) => {
          this.subTaskCount = data;
        });
      },
      (error) => { }
    );
  }
  selectedStatus(event) {
    this.enableTaskMarkButton();
  }
  selectedTaskStatus(event) {
    this.task.status == 'completed' ? this.enableMarkButton = true : this.enableMarkButton = false;
    if (this.task.status == 'completed' && this.task.children && this.task.children.length) {
      this.task.children.forEach(element => {
        element.status = 'completed';
      });
    }
    this.enableTaskMarkButton();
  }

  setDate() {
    this.update();
  }
  setTaskEndDate() {
    this.sTime.open();
  }
  public addSubtask() {
    if (this.newSubtask.name) {
      this.newSubtask.isDeletable = true;
      !this.task.children ? (this.task.children = []) : "";
      this.task.children.push(this.newSubtask);
      this.enableTaskMarkButton();
    }
  }
  toEdit(type, copyOfString) {
    this.editField = type;
    this.copyOfSelectEditField = copyOfString;
  }

  saveChanges() {
    if (this.task.name) {
      this.editField = "";
      this.update();
    } else {
      this.task.name = this.copyOfSelectEditField;
      this.toast.showMessage("FRMELEMNTS_MSG_REQUIRED_FIELDS", "danger");
    }
  }

  saveSubTaskChanges(subtask, index) {
    if (subtask.name) {
      this.editField = ""; // removed as it closing the edit field as one letter is entered
      this.update();
    } else {
      this.task.children[index].name = this.copyOfSelectEditField;
      this.toast.showMessage("FRMELEMNTS_MSG_REQUIRED_FIELDS", "danger");
    }
  }

  update(goBack?) {
    if (this.task.name) {
      if (!this.task.isEdit) {
        this.task.isEdit = this.copyOfTaskDetails === JSON.stringify(this.task) ? false : true;
        this.project.isEdit = this.task.isEdit ? true : this.project.isEdit;
      }
      if (JSON.stringify(this.copyOfTaskDetails) !== JSON.stringify(this.task)) {
        this.project.isEdit = true;
        this.project.status =  this.project.status ? this.project.status : statusType.notStarted;
        this.project.status =  this.project.status == statusType.notStarted ? statusType.inProgress:this.project.status;
      }
      const isProjectEdit = _.filter(this.project.tasks, (eachTask) => {
        return eachTask.isEdit;
      });
      this.project.isEdit = isProjectEdit.length ? true : this.project.isEdit;
      this.project = this.utils.setStatusForProject(this.project);
      this.db
        .update(this.project)
        .then((success) => {
          this.project._rev = success.rev;
          this.prepareSubTaskMeta();
          this.attachments = [];
          this.toast.showMessage('FRMELEMNTS_MSG_YOUR_CHANGES_ARE_SAVED', 'success');
          goBack ? this.location.back() : "";
        })
    } else {
      this.toast.showMessage("FRMELEMNTS_MSG_REQUIRED_FIELDS", "danger");
    }
  }

  openResources(task) {
    if (task && task.learningResources && task.learningResources.length === 1) {
      let link = task.learningResources[0].link;
      this.openBodh(link);
      return;
    }
    if (task) {
      this.router.navigate(["/project/learning-resources", this.project._id, task._id]);
    } else {
      this.router.navigate(["/project/learning-resources", this.project._id]);
    }
  }

  openBodh(link) {
    if(this.commonUtilService.networkInfo.isNetworkAvailable){
      const id = link.split('/').pop();
      const req: ContentDetailRequest = {
        contentId: id,
        attachFeedback: false,
        attachContentAccess: false,
        emitUpdateIfAny: false
      };
  
      this.contentService.getContentDetails(req).toPromise()
        .then(async (data: Content) => {
          this.navigateService.navigateToDetailPage(data, { content: data });
        });
    } else {
      this.toast.showMessage('FRMELEMNTS_MSG_OFFLINE_SHARE_PROJECT', 'danger');
    }

  }

  delete(data) {
    data.isDeleted = true;
    this.enableTaskMarkButton();
  }

  // task and project delete permission.
  async askPermissionToDelete(subtask, type) {
    let data;
    this.translate.get(["FRMELEMNTS_LBL_DELETE_CONFIRMATION", "NO", "YES"]).subscribe((text) => {
      data = text;
    });
    const alert = await this.alert.create({
      message: data["FRMELEMNTS_LBL_DELETE_CONFIRMATION"],
      cssClass: 'background-theme-color',
      buttons: [
        {
          text: data["NO"],
          role: "cancel",
          cssClass: "secondary",
          handler: (blah) => { },
        },
        {
          text: data["YES"],
          handler: () => {
            this.delete(subtask);
          },
        },
      ],
    });
    await alert.present();
  }

  getSubtasksCount(task) {
    return new Promise(function (resolve) {
      let count = 0;
      if (task.children && task.children.length) {
        task.children.forEach((subtask) => {
          if (!subtask.isDeleted) {
            count = count + 1;
          }
        });
        resolve(count);
      } else {
        resolve(null);
      }
    });
  }

  enableTaskMarkButton() {
    this.getSubtasksCount(this.task).then((count: number) => {
      this.subTaskCount = count;
      if (count) {
        let inProgress = 0;
        let completed = 0;
        if (this.task.children.length) {
          this.task.children.forEach((child) => {
            if (!child.isDeleted) {
              if (child.status == "inProgress") {
                inProgress = inProgress + 1;
              } else if (child.status == "completed") {
                completed = completed + 1;
              }
            }
          });
        }
        if (count === completed) {
          this.task.status = "completed";
        } else if (inProgress > 0) {
          this.task.status = "inProgress";
        }
        this.task.status == "completed" ? (this.enableMarkButton = true) : (this.enableMarkButton = false);
      } else {
        this.task.status == "completed" ? (this.enableMarkButton = true) : (this.enableMarkButton = false);
      }
      this.update();
    });
  }

  closemarkTaskAsCompleted(){
    this.showAttachments = false;
  }
  insertAttachment() {
    this.showAttachments = false;
    !this.task.attachments ? (this.task.attachments = []) : "";
    if (this.attachments && this.attachments.length) {
      this.attachments.forEach((element) => {
        this.task.attachments.push(element);
      });
    }
    this.update("goBack");
  }
  openAction() {
    this.attachmentService.selectImage().then((data) => {
      data.data ? this.attachments.push(data.data) : "";
    });
  }

  doAction() {
    this.popupService.showPPPForProjectPopUp('FRMELEMNTS_LBL_EVIDENCES_CONTENT_POLICY', 'FRMELEMNTS_LBL_EVIDENCES_CONTENT_POLICY_TEXT', 'FRMELEMNTS_LBL_EVIDENCES_CONTENT_POLICY_LABEL', 'FRMELEMNTS_LBL_UPLOAD_EVIDENCES', 'https://diksha.gov.in/term-of-use.html', 'contentPolicy').then((data: any) => {
      if (data.isClicked) {
        data.isChecked ? this.router.navigate([`${RouterLinks.PROJECT}/${RouterLinks.ADD_FILE}`,this.parameters.id],{queryParams:{taskId:this.task._id}}) : this.toast.showMessage('FRMELEMNTS_MSG_EVIDENCES_CONTENT_POLICY_REJECT', 'danger');
      }
    })
  }

  async edit(what, placeholder = "", subtask?, subTaskIndex?) {
    let name;
    switch (what) {
      case 'task':
        if(this.task.isDeletable){
          name = "Edit Task";
          this.openEditModal(what,name,placeholder,subtask,subTaskIndex);
         }
        break
      case 'subtask':
        if(subtask.isDeletable){
          name = "Edit Subtask"
          this.openEditModal(what,name,placeholder,subtask,subTaskIndex);
         }
      break
    }
  }

 async openEditModal(what,name,placeholder,subtask,subTaskIndex){
    const alert = await this.alert.create({
      cssClass: "central-alert",
      header: name,
      // message: "Message <strong>text</strong>!!!",
      inputs: [
        {
          name: "field",
          type: "text",
          value: placeholder
        },
      ],
      buttons: [
        {
          text: "Cancel",
          role: "cancel",
          cssClass: "secondary",
          handler: (blah) => { },
        },
        {
          text: "Save",
          handler: (data) => {
            if (data.field == "" && what != "assignName") {
              this.toast.showMessage("FRMELEMNTS_MSG_REQUIRED_FIELDS", "danger");
              return;
            }

            if (what == "subtask") {
              subtask.name = data.field;
              this.saveSubTaskChanges(subtask, subTaskIndex);
            } else if (what == "assignName") {
              this.task.assignee = data.field;
              this.saveChanges()
            } else {
              this.task.name = data.field;
              this.update();
            }
          },
        },
      ],
    });

    await alert.present();
    alert.present().then(() => {
      const firstInput: any = document.querySelector("ion-alert input");
      firstInput.focus();
      return;
    });
  }

  checkDisabled() {
    if (this.task.type == "assessment" || this.task.type == "observation") {
      return this.subTaskCount == 0 || this.subTaskCount == undefined || this.subTaskCount > 0; // disabled all the time 
    } else {
      return this.subTaskCount > 0;
    }
  }
}
<ion-content *ngIf="task" class="ion-padding background-theme-color">
  <div [ngClass]="{'disablePage' : viewOnlyMode}">
    <div class="heading-name" (click)="edit('task',task?.name)">
      <h4 *ngIf="editField != 'name'">{{task?.name}}</h4>
      <ion-icon name="create" color="primary" class="iconAdj" *ngIf="task.isDeletable"> </ion-icon>
    </div>

    <ion-row>
      <ion-col size="3">
        <img src="assets/imgs/timetable.png" class="filter-icon-calendar" (click)="setTaskEndDate()"  alt=""/>
      </ion-col>
      <ion-col size="9">
        <ion-datetime (ionChange)="setDate()" #dateTime value="{{task?.endDate}}" display-timezone="utc"
          min="{{currentYear - 2}}" max="{{currentYear + 5}}" display-timezone="utc" [(ngModel)]="task.endDate">
        </ion-datetime>
      </ion-col>
    </ion-row>
    <ion-row>
      <ion-col size="4" class="status-label">
        <ion-label position="fixed"> {{'FRMELEMNTS_LBL_STATUS' | translate}} </ion-label>
      </ion-col>
      <ion-col size="8">

        <ion-select [(ngModel)]="task.status" class="custom-select" [disabled]="checkDisabled()" [interfaceOptions]="{
             cssClass: 'select-box',
             animated: false
           }" placeholder="{{'FRMELEMNTS_LBL_SELECT_STATUS_PLACEHOLDER' | translate}}"
          (ionChange)="selectedTaskStatus($event)">
          <ion-select-option *ngFor="let status of statuses" value="{{status.title}}"
            selected="status.title === task.status">{{status.title | camelToTitle}}</ion-select-option>
        </ion-select>

      </ion-col>
    </ion-row>
    <div class="subtask-form" *ngIf="task?.type !='observation' && task?.type != 'assessment'">
      <h4>{{'FRMELEMNTS_LBL_SUBTASKS' | translate}}</h4>
      <ion-row>
        <ion-col size="3"> <img src="assets/imgs/subdirectory_arrow.png" class="filter-icon arrow-image"  alt=""/> </ion-col>
        <ion-col size="9">
          <ion-item>
            <ion-input type="text" placeholder="{{'FRMELEMNTS_LBL_ADD_SUBTASK_PALCEHOLDER' | translate}}"
              [(ngModel)]="newSubtask.name" autocapitalize='on'>
            </ion-input>
          </ion-item>
          <ion-button (click)="addSubtask()" [ngClass]="{'btn-disabled': !newSubtask.name}"
            class="custom-btn-txt-transform-none">
            {{'FRMELEMNTS_LBL_ADD_SUBTASK' | translate}} </ion-button>
        </ion-col>
      </ion-row>
    </div>

    <div class="subtask-box " *ngFor="let subtask of task?.children; let subTaskIndex = index">
      <ion-card class="ion-padding" style="background: #ffffff;" *ngIf="!subtask.isDeleted">
        <ion-row>
          <ion-col size="1">
            <ion-icon name="radio-button-off" color="primary"></ion-icon>
          </ion-col>
          <ion-col size="10" class="subtask-title" (click)="edit('subtask',subtask.name,subtask,subTaskIndex)"
            *ngIf="editField != 'subtaskName'">
            {{subtask.name}}
          </ion-col>
          <ion-col size="1" style="margin: auto; text-align: center" *ngIf="subtask.isDeletable">
            <img src="assets/imgs/Delete.png" class="filter-icon" style="width: 1.25rem"
              (click)="askPermissionToDelete(subtask,'subtask')" alt=""/>
          </ion-col>
        </ion-row>
        <ion-row>
          <ion-col size="6">
            <ion-item class="ion-date-time" lines="none">
              <img src="assets/imgs/timetable.png" class="filter-icon subtask-date-picker" alt=""/>
              <ion-datetime value="{{subtask?.endDate}}" (ionChange)="setDate()" [(ngModel)]="subtask.endDate"
                displayFormat="DD/MM/YYYY" min="{{currentYear - 2}}" max="{{currentYear + 5}}" display-timezone="utc">
              </ion-datetime>
            </ion-item>
          </ion-col>
          <ion-col size="6">
            <ion-select [(ngModel)]="subtask.status" class="custom-select"
              placeholder="{{'FRMELEMNTS_LBL_SELECT_STATUS_PLACEHOLDER' | translate}}"
              (ionChange)="selectedStatus($event)" [interfaceOptions]="{
                     cssClass: 'select-box',
                     animated: false
                   }">
              <ion-select-option *ngFor="let status of statuses" value="{{status.title}}"
                selected="status.title === subtask.status">{{status.title | camelToTitle}}</ion-select-option>
            </ion-select>
          </ion-col>
        </ion-row>
      </ion-card>
    </div>

    <ion-button expand="block" shape="round" (click)="doAction()"
      class="custom-btn-txt-transform-none" *ngIf="!task?.learningResources?.length">
      {{'FRMELEMNTS_LBL_ADD_FILES' | translate}}
    </ion-button>

    <ion-row *ngIf="task?.learningResources?.length">
      <ion-col size="5">
        <ion-button class="roundedButton custom-btn-txt-transform-none" expand="block" shape="round" (click)="openResources(task)">
          {{'FRMELEMNTS_LBL_VIEW_RESOURCES' | translate}}
        </ion-button>
      </ion-col>
      <ion-col size="7">
        <ion-button class="roundedButton custom-btn-txt-transform-none"  expand="block"
          shape="round" (click)="doAction()">
          {{'FRMELEMNTS_LBL_ADD_FILES' | translate}}
        </ion-button>
      </ion-col>
    </ion-row>
  </div>

</ion-content>

./task-view.page.scss

@import "src/assets/styles/_variables.scss";
.heading-name{
    display: flex;
    justify-content: space-between;
    align-items: center;
    h4{
        word-break: break-all;
        max-width: 92%;
    }
}
.filter-icon-calendar {
    width: 3rem;
    height: 3rem;
}
.status-label {
    margin: auto;
    font-size: 1.25rem;
    font-weight: 500;
}
.btn-disabled{
    --background: #999999 !important;
    --border-color: #999999 !important;
  }
.subtask-form {
    margin: 0px;
    padding: 5px;

    .arrow-image {
        width: 2.438rem;
        margin-top: 5px;
    }
    ion-item {
        font-size: 0.813rem;
    }
    ion-button {
        text-transform: none;
    }
}

ion-button {
    font-size: 0.875rem;
    height: 1.813rem;
}

.subtask-box {
    ion-icon {
        color: #{$blue};
    }

    .subtask-title {
        font-family: 'SourceSansPro-Bold' !important;
        font-weight: 600;
    }

    ion-row,
    ion-col {
        margin: 0px;
        padding: 0px;
    }
}

.custom-popup {
    position: fixed;
    z-index: 9999;
    width: 100%;
    height: 100%;
    overflow: auto;
    background: #a9a9a966;
    display: flex;

    .border-radius {
        border-radius: 1em;
    }

    .pop-container {
        margin: auto;
        width: 80%;
        box-shadow: 0px 1px 4px 1px #5a6779;
        background: var(--app-primary-background);
        padding: 10px;
        .pop-msg {
            .close-attach-popup{
                float: right;
                text-align: right;
                font-size: 1.5rem;
                margin-top: -15px;
            }
        ion-textarea {
            background: #fff !important;
            border-radius: 0px !important;
        }
    }
    }
}

.roundedButton {
    font-size: 0.75rem;
}
.subtask-date-picker{
    max-width: 1.563rem;  
    margin-right: 5px;
}

.assignee {
    font-weight: normal;
    margin-left: 20px;
    font-size: 1rem;
}

.iconAdj {
    font-size: 1.25rem;
}

.disablePage {
    pointer-events: none;
    opacity: 0.7;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""