File

src/app/modules/learn/components/course-consumption/course-consumption-header/course-consumption-header.component.ts

Implements

OnInit AfterViewInit OnDestroy

Metadata

Index

Properties
Methods
Inputs

Constructor

constructor(activatedRoute: ActivatedRoute, courseConsumptionService: CourseConsumptionService, resourceService: ResourceService, router: Router, permissionService: PermissionService, toasterService: ToasterService, copyContentService: CopyContentService, changeDetectorRef: ChangeDetectorRef, courseProgressService: CourseProgressService, contentUtilsServiceService: ContentUtilsServiceService, externalUrlPreviewService: ExternalUrlPreviewService, coursesService: CoursesService, userService: UserService, telemetryService: TelemetryService, groupService: GroupsService, navigationHelperService: NavigationHelperService, orgDetailsService: OrgDetailsService, generaliseLabelService: GeneraliseLabelService, connectionService: ConnectionService, courseBatchService: CourseBatchService, utilService: UtilService, contentManagerService: ContentManagerService, formService: FormService, offlineCardService: OfflineCardService, discussionService: DiscussionService, discussionTelemetryService: DiscussionTelemetryService)
Parameters :
Name Type Optional
activatedRoute ActivatedRoute No
courseConsumptionService CourseConsumptionService No
resourceService ResourceService No
router Router No
permissionService PermissionService No
toasterService ToasterService No
copyContentService CopyContentService No
changeDetectorRef ChangeDetectorRef No
courseProgressService CourseProgressService No
contentUtilsServiceService ContentUtilsServiceService No
externalUrlPreviewService ExternalUrlPreviewService No
coursesService CoursesService No
userService UserService No
telemetryService TelemetryService No
groupService GroupsService No
navigationHelperService NavigationHelperService No
orgDetailsService OrgDetailsService No
generaliseLabelService GeneraliseLabelService No
connectionService ConnectionService No
courseBatchService CourseBatchService No
utilService UtilService No
contentManagerService ContentManagerService No
formService FormService No
offlineCardService OfflineCardService No
discussionService DiscussionService No
discussionTelemetryService DiscussionTelemetryService No

Inputs

courseHierarchy
Type : any
enrolledBatchInfo
Type : any
groupId
Type : string
layoutConfiguration
Type : any
showAddGroup
Type : boolean
Default value : false

Methods

assignForumData
assignForumData(routerData)
Parameters :
Name Optional
routerData No
Returns : void
checkDownloadStatus
checkDownloadStatus()
Returns : void
checkStatus
checkStatus(status)
Parameters :
Name Optional
status No
Returns : any
closeDashboard
closeDashboard()
Returns : void
closeSharePopup
closeSharePopup(id)
Parameters :
Name Optional
id No
Returns : void
copyContent
copyContent(contentData: ContentData)

This method calls the copy API service

Parameters :
Name Type Optional
contentData ContentData No
Returns : void
deleteCollection
deleteCollection(collectionData)
Parameters :
Name Optional
collectionData No
Returns : void
downloadCollection
downloadCollection(collection)
Parameters :
Name Optional
collection No
Returns : void
exportCollection
exportCollection(collection)
Parameters :
Name Optional
collection No
Returns : void
flagCourse
flagCourse()
Returns : void
generateDataForDF
generateDataForDF()
Returns : void
getAllBatchDetails
getAllBatchDetails()
Returns : void
getBatchStatus
getBatchStatus()
Returns : boolean
Private getCustodianOrgUser
getCustodianOrgUser()
Returns : void
getFormData
getFormData()
Returns : void
getTimeRemaining
getTimeRemaining(endTime)
Parameters :
Name Optional
endTime No
Returns : string
Async goBack
goBack()
Returns : any
isEnrollmentAllowed
isEnrollmentAllowed(enrollmentEndDate)
Parameters :
Name Optional
enrollmentEndDate No
Returns : any
isValidEnrollmentEndDate
isValidEnrollmentEndDate(enrollmentEndDate)
Parameters :
Name Optional
enrollmentEndDate No
Returns : boolean
isYoutubeContentPresent
isYoutubeContentPresent(collection)
Parameters :
Name Optional
collection No
Returns : void
logTelemetry
logTelemetry(id, content?: literal type)
Parameters :
Name Type Optional
id No
content literal type Yes
Returns : void
ngAfterViewInit
ngAfterViewInit()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
onShareLink
onShareLink()
Returns : void
resumeCourse
resumeCourse(showExtUrlMsg?: boolean)
Parameters :
Name Type Optional
showExtUrlMsg boolean Yes
Returns : void
setTelemetryShareData
setTelemetryShareData(param)
Parameters :
Name Optional
param No
Returns : void
showDashboard
showDashboard()
Returns : void
showJoinModal
showJoinModal(event)
Parameters :
Name Optional
event No
Returns : void
updateCollection
updateCollection(collection)
Parameters :
Name Optional
collection No
Returns : void

Properties

batchEndCounter
Type : number
batchEndDate
Type : any
batchId
Type : any
batchList
Type : []
Default value : []
batchRemaningTime
Type : any
Public connectionService
Type : ConnectionService
contentDownloadStatus
Type : object
Default value : {}
contentId
Type : string
Public contentManagerService
Type : ContentManagerService
Public contentUtilsServiceService
Type : ContentUtilsServiceService
Public copyContentService
Type : CopyContentService
Public courseBatchService
Type : CourseBatchService
Public courseConsumptionService
Type : CourseConsumptionService
courseId
Type : string
courseInteractObject
Type : IInteractEventObject
Public coursesService
Type : CoursesService
courseStatus
Type : string
dashboardPermission
Type : []
Default value : ['COURSE_MENTOR', 'CONTENT_CREATOR']
disableDelete
Default value : false
Public discussionService
Type : DiscussionService
Public discussionTelemetryService
Type : DiscussionTelemetryService
enableProgress
Default value : false
enrolledCourse
Default value : false
enrollmentEndDate
Type : string
Public externalUrlPreviewService
Type : ExternalUrlPreviewService
fetchForumIdReq
Type : IForumContext

input data for fetchforum Ids

flaggedCourse
Default value : false

contains link that can be shared

forumIds
Type : []
Default value : []
Public generaliseLabelService
Type : GeneraliseLabelService
Public interval
Type : any
isAvailableLocally
Default value : false
isConnected
Default value : true
isCustodianOrgUser
Default value : false
isDesktopApp
Default value : false
isGroupAdmin
Default value : false
isGroupURL
Type : Boolean
isTrackable
Default value : false
lastPlayedContentId
Type : string
onPageLoadResume
Default value : false
Public orgDetailsService
Type : OrgDetailsService
Public permissionService
Type : PermissionService
profileInfo
Type : literal type
progress
Type : number
Default value : 0
Public resourceService
Type : ResourceService
Public router
Type : Router
shareLink
Type : string
sharelinkModal
Type : boolean
showBatchCounter
Type : boolean
showCopyLoader
Default value : false

to show loader while copying content

showDeleteModal
Default value : false
showDownloadLoader
Default value : false
showError
Default value : false
showExportLoader
Default value : false
showLoader
Default value : false
showModal
Default value : false
showProfileUpdatePopup
Default value : false
showResumeCourse
Default value : true
showUpdate
Default value : false
telemetryCdata
Type : Array<literal type>
telemetryShareData
Type : Array<ITelemetryShare>

telemetryShareData

Public toasterService
Type : ToasterService
tocId
todayDate
Default value : dayjs(new Date()).format('YYYY-MM-DD')
Public unsubscribe
Default value : new Subject<void>()
viewDashboard
Default value : false
import { combineLatest as observableCombineLatest, Subject } from 'rxjs';
import { takeUntil} from 'rxjs/operators';
import { Component, OnInit, Input, AfterViewInit, ChangeDetectorRef, OnDestroy } from '@angular/core';
import { CourseConsumptionService, CourseProgressService } from './../../../services';
import { ActivatedRoute, Router } from '@angular/router';
import * as _ from 'lodash-es';
import { CoursesService, PermissionService, CopyContentService,
  OrgDetailsService, UserService, GeneraliseLabelService,  } from '@sunbird/core';
import {
  ResourceService, ToasterService, ContentData, ContentUtilsServiceService, ITelemetryShare,
  ExternalUrlPreviewService, UtilService, ConnectionService, OfflineCardService, ServerResponse
} from '@sunbird/shared';
import { IInteractEventObject, TelemetryService } from '@sunbird/telemetry';
import dayjs from 'dayjs';
import { GroupsService } from '../../../../groups/services/groups/groups.service';
import { NavigationHelperService } from '@sunbird/shared';
import { CourseBatchService } from './../../../services';
import { DiscussionService } from '../../../../discussion/services/discussion/discussion.service';
import { FormService } from '../../../../core/services/form/form.service';
import { IForumContext } from '../../../interfaces';
import { ContentManagerService } from '../../../../public/module/offline/services';
import { DiscussionTelemetryService } from './../../../../shared/services/discussion-telemetry/discussion-telemetry.service';

@Component({
  selector: 'app-course-consumption-header',
  templateUrl: './course-consumption-header.component.html',
  styleUrls: ['./course-consumption-header.component.scss']
})
export class CourseConsumptionHeaderComponent implements OnInit, AfterViewInit, OnDestroy {

  sharelinkModal: boolean;
  showProfileUpdatePopup = false;
  profileInfo: {
    firstName: string,
    lastName: string,
    id: string
  };
  /**
   * input data for fetchforum Ids
   */
  fetchForumIdReq: IForumContext;
  /**
   * contains link that can be shared
   */
  flaggedCourse = false;
  /**
	 * telemetryShareData
	*/
  telemetryShareData: Array<ITelemetryShare>;
  shareLink: string;
  /**
   * to show loader while copying content
   */
  showCopyLoader = false;
  onPageLoadResume = false;
  courseInteractObject: IInteractEventObject;
  @Input() courseHierarchy: any;
  @Input() enrolledBatchInfo: any;
  @Input() groupId: string;
  @Input() showAddGroup = false;
  @Input() layoutConfiguration;
  isGroupAdmin = false;
  enrolledCourse = false;
  batchId: any;
  dashboardPermission = ['COURSE_MENTOR', 'CONTENT_CREATOR'];
  courseId: string;
  lastPlayedContentId: string;
  showResumeCourse = true;
  contentId: string;
  progress = 0;
  courseStatus: string;
  public unsubscribe = new Subject<void>();
  batchEndDate: any;
  batchRemaningTime: any;
  public interval: any;
  telemetryCdata: Array<{}>;
  enableProgress = false;
  isCustodianOrgUser = false;
  // courseMentor = false;
  // courseCreator = false;
  forumIds = [];
  isTrackable = false;
  viewDashboard = false;
  tocId;
  showLoader = false;
  batchEndCounter: number;
  showBatchCounter: boolean;
  isDesktopApp = false;
  isConnected = true;
  contentDownloadStatus = {};
  showUpdate = false;
  showExportLoader = false;
  showModal = false;
  showDownloadLoader = false;
  disableDelete = false;
  isAvailableLocally = false;
  showDeleteModal = false;
  batchList = [];
  enrollmentEndDate: string;
  todayDate = dayjs(new Date()).format('YYYY-MM-DD');
  showError = false;
  isGroupURL: Boolean;

  constructor(private activatedRoute: ActivatedRoute, public courseConsumptionService: CourseConsumptionService,
    public resourceService: ResourceService, public router: Router, public permissionService: PermissionService,
    public toasterService: ToasterService, public copyContentService: CopyContentService, private changeDetectorRef: ChangeDetectorRef,
    private courseProgressService: CourseProgressService, public contentUtilsServiceService: ContentUtilsServiceService,
    public externalUrlPreviewService: ExternalUrlPreviewService, public coursesService: CoursesService, private userService: UserService,
    private telemetryService: TelemetryService, private groupService: GroupsService,
    private navigationHelperService: NavigationHelperService, public orgDetailsService: OrgDetailsService,
    public generaliseLabelService: GeneraliseLabelService, public connectionService: ConnectionService,
    public courseBatchService: CourseBatchService, private utilService: UtilService, public contentManagerService: ContentManagerService,
    private formService: FormService, private offlineCardService: OfflineCardService,
    public discussionService: DiscussionService, public discussionTelemetryService: DiscussionTelemetryService) { }

  showJoinModal(event) {
    this.courseConsumptionService.showJoinCourseModal.emit(event);
  }

  ngOnInit() {
    this.isGroupAdmin = _.get(this.groupService, 'groupData.isAdmin');
    this.isGroupURL=_.includes(_.get(this.router,'url'),'groupId');
    this.isDesktopApp = this.utilService.isDesktopApp;
    if (this.isDesktopApp) {
      this.connectionService.monitor().pipe(takeUntil(this.unsubscribe)).subscribe(isConnected => {
        this.isConnected = isConnected;
      });
      this.contentManagerService.contentDownloadStatus$.pipe(takeUntil(this.unsubscribe)).subscribe( contentDownloadStatus => {
        this.contentDownloadStatus = contentDownloadStatus;
        this.checkDownloadStatus();
      });
    }
    this.getCustodianOrgUser();
    if (!this.courseConsumptionService.getCoursePagePreviousUrl) {
      this.courseConsumptionService.setCoursePagePreviousUrl();
    }
    this.isTrackable = this.courseConsumptionService.isTrackableCollection(this.courseHierarchy);
    this.viewDashboard = this.courseConsumptionService.canViewDashboard(this.courseHierarchy);

    this.profileInfo = this.userService.userProfile;

    observableCombineLatest(this.activatedRoute.firstChild.params, this.activatedRoute.firstChild.queryParams,
      (params, queryParams) => {
        return { ...params, ...queryParams };
      }).subscribe((params) => {
        this.courseId = params.courseId;
        this.batchId = params.batchId;
        this.getAllBatchDetails();
        this.courseStatus = params.courseStatus;
        this.contentId = params.contentId;
        this.tocId = params.textbook;
        this.courseInteractObject = {
          id: this.courseHierarchy.identifier,
          type: 'Course',
          ver: this.courseHierarchy.pkgVersion ? this.courseHierarchy.pkgVersion.toString() : '1.0',
        };
        if (this.courseHierarchy.status === 'Flagged') {
          this.flaggedCourse = true;
        }
        if (this.batchId) {
          this.enrolledCourse = true;
          this.telemetryCdata = [{ id: this.batchId, type: 'CourseBatch' }];
        }
      });
    this.interval = setInterval(() => {
      if (document.getElementById('closebutton')) {
        this.showResumeCourse = true;
      } else {
        this.showResumeCourse = false;
      }
    }, 500);
    this.courseConsumptionService.userCreatedAnyBatch.subscribe((visibility: boolean) => {
      this.viewDashboard = this.viewDashboard && visibility;
    });
    this.generateDataForDF();
  }
  ngAfterViewInit() {
    this.courseProgressService.courseProgressData.pipe(
      takeUntil(this.unsubscribe))
      .subscribe((courseProgressData) => {
        if (this.batchId) {
          this.enrolledCourse = true;
          this.progress = courseProgressData.progress ? Math.floor(courseProgressData.progress) : 0;
          this.lastPlayedContentId = courseProgressData.lastPlayedContentId;
          if (!this.flaggedCourse && this.onPageLoadResume &&
            !this.contentId && this.enrolledBatchInfo.status > 0 && this.lastPlayedContentId) {
            this.onPageLoadResume = false;
            this.showResumeCourse = false;
            this.resumeCourse();
          } else if (!this.flaggedCourse && this.contentId && this.enrolledBatchInfo.status > 0 && this.lastPlayedContentId) {
            this.onPageLoadResume = false;
            this.showResumeCourse = false;
          } else {
            this.onPageLoadResume = false;
          }
        }
      });

      this.courseConsumptionService.updateContentConsumedStatus.emit(
        {
          courseId: this.courseId,
          batchId: this.batchId,
          courseHierarchy: this.courseHierarchy
         });
  }

  getTimeRemaining(endTime) {
    this.getFormData();
    const countDownDate = new Date(endTime).getTime() + 1000 * 60 * 60 * 24;
    const now = new Date().getTime();
    const total = countDownDate - now;
    const days = Math.floor(total / (1000 * 60 * 60 * 24));
    const hours = Math.floor((total / (1000 * 60 * 60)) % 24);
    const minutes = Math.floor((total / 1000 / 60) % 60);
    if (days >= 0) {
      this.showBatchCounter = this.batchEndCounter >= days;
      if (this.showBatchCounter) {
        return days + ' ' + 'day(s)' + ' ' + hours + 'h' + ' ' + minutes + 'm';
      }
    } else {
      this.showBatchCounter = false;
    }
    return;
  }

  getFormData() {
    const formServiceInputParams = {
      formType: 'contentcategory',
      formAction: 'menubar',
      contentType: 'global'
    };
    this.formService.getFormConfig(formServiceInputParams).subscribe((data: any) => {
      _.forEach(data, (value, key) => {
        if ('frmelmnts.tab.courses' === value.title) {
          this.batchEndCounter = value.batchEndCounter || null;
        }
      });
    });
  }

  showDashboard() {
    this.router.navigate(['learn/course', this.courseId, 'dashboard', 'batches']);
  }

  // To close the dashboard
  closeDashboard() {
    this.router.navigate(['learn/course', this.courseId]);
  }

  resumeCourse(showExtUrlMsg?: boolean) {
    const IsStoredLocally = localStorage.getItem('isCertificateNameUpdated_' + this.profileInfo.id) || 'false' ;
    const certificateDescription = this.courseBatchService.getcertificateDescription(this.enrolledBatchInfo);
    if (IsStoredLocally !== 'true'
    &&
    certificateDescription &&
    certificateDescription.isCertificate
    && this.isCustodianOrgUser && this.progress < 100) {
      this.showProfileUpdatePopup = true;
    } else {
      this.courseConsumptionService.launchPlayer.emit();
      this.coursesService.setExtContentMsg(showExtUrlMsg);
    }
  }

  flagCourse() {
    this.router.navigate(['flag'], { relativeTo: this.activatedRoute.firstChild });
  }
  /**
   * This method calls the copy API service
   * @param {contentData} ContentData Content data which will be copied
   */
  copyContent(contentData: ContentData) {
    this.showCopyLoader = true;
    this.copyContentService.copyContent(contentData).pipe(
      takeUntil(this.unsubscribe))
      .subscribe(
        (response) => {
          this.toasterService.success(this.resourceService.messages.smsg.m0042);
          this.showCopyLoader = false;
        },
        (err) => {
          this.showCopyLoader = false;
          this.toasterService.error(this.resourceService.messages.emsg.m0008);
        });
  }
  onShareLink() {
    this.shareLink = this.contentUtilsServiceService.getCoursePublicShareUrl(this.courseId);
    this.setTelemetryShareData(this.courseHierarchy);
  }
  setTelemetryShareData(param) {
    this.telemetryShareData = [{
      id: param.identifier,
      type: param.contentType,
      ver: param.pkgVersion ? param.pkgVersion.toString() : '1.0'
    }];
  }
  ngOnDestroy() {
    clearInterval(this.interval);
    this.unsubscribe.next();
    this.unsubscribe.complete();
  }
  getBatchStatus() {
   /* istanbul ignore else */
   if (_.get(this.enrolledBatchInfo, 'endDate')) {
    this.batchEndDate = dayjs(this.enrolledBatchInfo.endDate).format('YYYY-MM-DD');
    const leftTimeDate = dayjs(this.batchEndDate).format('MMM DD, YYYY');
    this.batchRemaningTime = this.getTimeRemaining(leftTimeDate);
   }
   return (_.get(this.enrolledBatchInfo, 'status') === 2 && this.progress <= 100);
  }

  closeSharePopup(id) {
    this.sharelinkModal = false;
    const interactData = {
      context: {
        env: _.get(this.activatedRoute.snapshot.data.telemetry, 'env') || 'content',
        cdata: this.telemetryCdata
      },
      edata: {
        id: id,
        type: 'click',
        pageid: _.get(this.activatedRoute.snapshot.data.telemetry, 'pageid') || 'course-details',
      },
      object: {
        id: _.get(this.courseHierarchy, 'identifier'),
        type: _.get(this.courseHierarchy, 'contentType') || 'Course',
        ver: `${_.get(this.courseHierarchy, 'pkgVersion')}` || `1.0`,
        rollup: {l1: this.courseId}
      }
    };
    this.telemetryService.interact(interactData);
  }
  private getCustodianOrgUser() {
    this.orgDetailsService.getCustodianOrgDetails().subscribe(custodianOrg => {
      if (_.get(this.userService, 'userProfile.rootOrg.rootOrgId') === _.get(custodianOrg, 'result.response.value')) {
        this.isCustodianOrgUser = true;
      } else {
        this.isCustodianOrgUser = false;
      }
    });
  }
  logTelemetry(id, content?: {}) {
    if (this.batchId) {
      this.telemetryCdata = [{ id: this.batchId, type: 'courseBatch' }];
    }
    const objectRollUp = this.courseConsumptionService.getContentRollUp(this.courseHierarchy, _.get(content, 'identifier'));
    const interactData = {
      context: {
        env: _.get(this.activatedRoute.snapshot.data.telemetry, 'env') || 'Course',
        cdata: this.telemetryCdata || []
      },
      edata: {
        id: id,
        type: 'click',
        pageid: _.get(this.activatedRoute.snapshot.data.telemetry, 'pageid') || 'course-consumption',
      },
      object: {
        id: content ? _.get(content, 'identifier') : this.activatedRoute.snapshot.params.courseId,
        type: content ? _.get(content, 'primaryCategory') : 'Course',
        ver: content ? `${_.get(content, 'pkgVersion')}` : `1.0`,
        rollup: this.courseConsumptionService.getRollUp(objectRollUp) || {}
      }
    };
    this.telemetryService.interact(interactData);
  }
  generateDataForDF() {
    const isCreator = this.userService.userid === _.get(this.courseHierarchy, 'createdBy');
    const isMentor = this.permissionService.checkRolesPermissions(['COURSE_MENTOR']);
    if (isCreator) {
      this.fetchForumIdReq = {
        type: 'course',
        identifier: [this.courseId]
      };
    } else if (this.enrolledCourse) {
      this.fetchForumIdReq = {
        type: 'batch',
        identifier: [this.batchId]
      };
    } else if (isMentor) {
      // TODO: make getBatches() api call;
      this.fetchForumIdReq = {
        type: 'course',
        identifier: [this.courseId]
      };
    }
  }
  async goBack() {
    const previousPageUrl: any = this.courseConsumptionService.getCoursePagePreviousUrl;
    this.courseConsumptionService.coursePagePreviousUrl = '';
    if (this.isDesktopApp && !this.isConnected) {
      this.router.navigate(['/mydownloads'], { queryParams: { selectedTab: 'mydownloads' } });
      return;
    }
    if (this.tocId) {
      const navigateUrl = this.userService.loggedIn ? '/resources/play/collection' : '/play/collection';
      this.router.navigate([navigateUrl, this.tocId], { queryParams: { textbook: this.tocId } });
    } else if (!previousPageUrl) {
      this.router.navigate(['/resources'], { queryParams: { selectedTab: 'course' } });
      return;
    }
    if (previousPageUrl.url.indexOf('/my-groups/') >= 0) {
      this.navigationHelperService.goBack();
    } else {
      if (previousPageUrl.queryParams) {
        this.router.navigate([previousPageUrl.url], {queryParams: previousPageUrl.queryParams});
      } else {
        this.router.navigate([previousPageUrl.url]);
      }
    }
  }
  checkStatus(status) {
    this.checkDownloadStatus();
    return this.utilService.getPlayerDownloadStatus(status, this.courseHierarchy);
  }
  checkDownloadStatus() {
    if (this.courseHierarchy) {
      const downloadStatus = ['CANCELED', 'CANCEL', 'FAILED', 'DOWNLOAD'];
      const status = this.contentDownloadStatus[this.courseHierarchy.identifier];
      this.courseHierarchy['downloadStatus'] = _.isEqual(downloadStatus, status) ? 'DOWNLOAD' :
      (_.includes(['INPROGRESS', 'RESUME', 'INQUEUE'], status) ? 'DOWNLOADING' : _.isEqual(status, 'COMPLETED') ? 'DOWNLOADED' : status);
    }
  }
  updateCollection(collection) {
    collection['downloadStatus'] = this.resourceService.messages.stmsg.m0140;
    this.logTelemetry('update-collection');
    const request = {
      contentId: collection.identifier
    };
    this.contentManagerService.updateContent(request).pipe(takeUntil(this.unsubscribe)).subscribe(data => {
      collection['downloadStatus'] = this.resourceService.messages.stmsg.m0140;
      this.showUpdate = false;
    }, (err) => {
      this.showUpdate = true;
      const errorMessage = !this.isConnected ? _.replace(this.resourceService.messages.smsg.m0056, '{contentName}', collection.name) :
        this.resourceService.messages.fmsg.m0096;
      this.toasterService.error(errorMessage);
    });
  }

  exportCollection(collection) {
    this.logTelemetry('export-collection');
    this.showExportLoader = true;
    this.contentManagerService.exportContent(collection.identifier)
      .pipe(takeUntil(this.unsubscribe))
      .subscribe(data => {
        this.showExportLoader = false;
        this.toasterService.success(this.resourceService.messages.smsg.m0059);
      }, error => {
        this.showExportLoader = false;
        if (_.get(error, 'error.responseCode') !== 'NO_DEST_FOLDER') {
          this.toasterService.error(this.resourceService.messages.fmsg.m0091);
        }
      });
  }

  isYoutubeContentPresent(collection) {
    this.logTelemetry('is-youtube-in-collection');
    this.showModal = this.offlineCardService.isYoutubeContent(collection);
    if (!this.showModal) {
      this.downloadCollection(collection);
    }
  }

  downloadCollection(collection) {
    this.showDownloadLoader = true;
    this.disableDelete = false;
    collection['downloadStatus'] = this.resourceService.messages.stmsg.m0140;
    this.logTelemetry('download-collection');
    this.contentManagerService.downloadContentId = collection.identifier;
    this.contentManagerService.downloadContentData = collection;
    this.contentManagerService.failedContentName = collection.name;
    this.contentManagerService.startDownload({}).pipe(takeUntil(this.unsubscribe)).subscribe(data => {
      this.contentManagerService.downloadContentId = '';
      this.contentManagerService.downloadContentData = {};
      this.showDownloadLoader = false;
      collection['downloadStatus'] = this.resourceService.messages.stmsg.m0140;
    }, error => {
      this.disableDelete = true;
      this.showDownloadLoader = false;
      this.contentManagerService.downloadContentId = '';
      this.contentManagerService.downloadContentData = {};
      this.contentManagerService.failedContentName = '';
      collection['downloadStatus'] = this.resourceService.messages.stmsg.m0138;
      if (!(error.error.params.err === 'LOW_DISK_SPACE')) {
        this.toasterService.error(this.resourceService.messages.fmsg.m0090);
          }
    });
  }

  deleteCollection(collectionData) {
    this.disableDelete = true;
    this.logTelemetry('delete-collection');
    const request = {request: {contents: [collectionData.identifier]}};
    this.contentManagerService.deleteContent(request).pipe(takeUntil(this.unsubscribe)).subscribe(data => {
      this.toasterService.success(this.resourceService.messages.stmsg.desktop.deleteCourseSuccessMessage);
      collectionData['downloadStatus'] = 'DOWNLOAD';
      collectionData['desktopAppMetadata.isAvailable'] = false;
      this.goBack();
    }, err => {
      this.disableDelete = false;
      this.toasterService.error(this.resourceService.messages.etmsg.desktop.deleteCourseErrorMessage);
    });
  }
   /**
     * @description - navigate to the DF Page when the event is emited from the access-discussion component
     * @param  {} routerData
     */
  assignForumData(routerData) {
    this.router.navigate(['/discussion-forum'], {
      queryParams: {
        categories: JSON.stringify({ result: routerData.forumIds }),
        userId: routerData.userId
      }
    });
  }

  isEnrollmentAllowed(enrollmentEndDate) {
    return dayjs(enrollmentEndDate).isBefore(this.todayDate);
  }

  isValidEnrollmentEndDate(enrollmentEndDate) {
    return !!enrollmentEndDate;
  }

  getAllBatchDetails() {
    this.batchList = [];
    const searchParams: any = {
      filters: {
        status: '1',
        courseId: this.courseId
      },
      offset: 0,
      sort_by: { createdDate: 'desc' }
    };
    searchParams.filters.enrollmentType = 'open';
    this.courseBatchService.getAllBatchDetails(searchParams).pipe(
      takeUntil(this.unsubscribe))
      .subscribe((data: ServerResponse) => {
        if (data.result.response.content && data.result.response.content.length > 0) {
          this.batchList = data.result.response.content;
          this.enrollmentEndDate = _.get(this.batchList[0], 'enrollmentEndDate');
        }
      },
      (err: ServerResponse) => {
        this.showError = true;
        this.toasterService.error(this.resourceService.messages.fmsg.m0004);
      });
  }
}
<!-- Loader -->
<div class="two wide column" *ngIf="showLoader">
  <app-loader></app-loader>
</div>
<!-- /Loader-->
<!-- Back Button -->
  <div [ngClass]="layoutConfiguration ? 'sb-back-actionbar' : 'sb-bg-color-white back-btn-container cc-player__btn-back relative9'" class="relative position mt-0">
    <div class="ui container px-0 d-flex flex-ai-center">
    <div class="w-100 d-flex flex-ai-center flex-w-wrap flex-jc-space-between">
      <div class="d-flex flex-ai-center">
        <!-- /* Back button */ -->
      <button type="button" [ngClass]="layoutConfiguration ? 'sb-btn-primary sb-btn-round' : 'sb-btn-link sb-btn-link-primary sb-left-icon-btn px-0'" class="sb-btn sb-btn-normal" tabindex="0" (click)="goBack()" attr.aria-label="{{resourceService?.frmelmnts?.btn?.back}}">
        <i class="icon-svg icon-svg--xxs icon-back mr-4"><svg class="icon icon-svg--primary">
            <use xlink:href="assets/images/sprite.svg#arrow-long-left"></use>
          </svg></i>
        <span>{{resourceService?.frmelmnts?.btn?.back}}</span>
      </button>
<!-- Textbook details with continue playing and join course button routerLink="/registration" -->
  <!-- Textbook details -->
  <div class="textbook__details d-flex ml-16 flex-basis-1 flex-ai-center">
    <!-- Textbook image -->
    <div class="textbook__bookimg">
      <img src="{{courseHierarchy?.appIcon || 'assets/images/book.png'}}" alt="{{courseHierarchy?.name}}">
    </div>
    <div class="ml-8 textbook__heading">
      <!-- Textbook title -->
      <h5 class="sb-color-primary font-weight-bold mb-0 sb__ellipsis" tabindex="0">{{courseHierarchy?.name}}
      </h5>
      <!-- Textbook Rating with share icon -->
      <div class="textbook__rating d-flex flex-ai-center">

        <sui-rating *ngIf="courseStatus !== 'Unlisted'" class="star mini" [isReadonly]="true"
          [ngModel]="courseHierarchy.me_averageRating || 0" [maximum]="5"></sui-rating>

        <button tabindex="0" (click)="onShareLink();sharelinkModal=true;"
          class="sb-btn sb-btn-normal sb-btn-link sb-btn-link-primary sb-left-icon-btn ml-8 sb-btn-icon-fix">
          <i class="icon-svg icon-svg--xs icon-share mr-8"><svg class="icon icon-svg--primary">
              <use xlink:href="assets/images/sprite.svg#share"></use>
            </svg></i>
          {{resourceService?.frmelmnts?.lbl?.share}}
        </button>

        <button class="sb-btn sb-btn-normal sb-btn-link sb-btn-link-primary sb-left-icon-btn ml-8 sb-btn-icon-fix"
          *ngIf="!isDesktopApp && permissionService?.permissionAvailable && courseStatus !== 'Unlisted'" appPermission
          appTelemetryInteract [telemetryInteractObject]="courseInteractObject"
          [telemetryInteractEdata]="{id:'copyContent' , type: 'click' , pageid:'course-consumption'}"
          [permission]="['CONTENT_CREATOR', 'CONTENT_REVIEWER']" tabindex="0" (click)="copyContent(courseHierarchy)"
          title="{{resourceService?.frmelmnts?.lbl?.copy}}">
          <i class="icon-svg icon-svg--xs icon-edit mr-8"><svg class="icon icon-svg--primary">
              <use xlink:href="assets/images/sprite.svg#copy-alternate"></use>
            </svg></i>
          {{resourceService?.frmelmnts?.lbl?.copy}}
        </button>

        <!-- Discussion Forum -->
        <app-access-discussion *ngIf="isConnected && fetchForumIdReq" [fetchForumIdReq]="fetchForumIdReq"
          (routerData)="assignForumData($event)"> </app-access-discussion>
      </div>
    </div>
  </div>
      </div>


  <div class="d-flex flex-w-wrap flex-ai-center textbook cc-player ml-auto">
    <div class="batch-details__created mt-8 fsmall mx-8"
      *ngIf="!enrolledBatchInfo && isValidEnrollmentEndDate(enrollmentEndDate)">
      <span class="sb-label-12size"
        *ngIf="!isEnrollmentAllowed(enrollmentEndDate)">{{resourceService?.messages?.stmsg?.m0136}}
        {{enrollmentEndDate | dateFormat}}</span>
      <span class="sb-label-status-error"
        *ngIf="isEnrollmentAllowed(enrollmentEndDate)">{{resourceService?.messages?.emsg?.m008 | interpolate:'{endDate}':enrollmentEndDate}}</span>
    </div>
    <div *ngIf="batchEndDate && showBatchCounter" class="d-flex">
      <span class="fnormal sb-color-gray-400">{{resourceService?.frmelmnts?.lbl?.BatchExpiringIn}}:&nbsp;</span>
      <span class="fsmall font-weight-bold mb-8 sb-color-gray-800">
        <h6>{{batchRemaningTime}}</h6>
      </span>
    </div>
    <div class="d-flex flex-dc flex-basis-1 mr-32">
      <!-- Info displaying if course is flagged -->
      <h6 class="ui small negative message" *ngIf="courseHierarchy.status === 'Flagged'">
        {{resourceService?.messages?.imsg?.m0001}}</h6>

      <!-- Info displaying if batch has expired -->
      <h6 class="ui small info message" *ngIf="enrolledCourse && getBatchStatus() && batchEndDate">
        {{resourceService?.frmelmnts?.lbl?.expiredBatchWarning | interpolate:'{EndDate}':batchEndDate}}</h6>

    </div>
    <div class="d-flex flex-ai-end flex-w-wrap certified-course" [ngClass]="{'d-flex': isDesktopApp}">
      <div class="certified-course__btn py-8" *ngIf="showAddGroup">
        <button class="sb-btn sb-btn-secondary sb-btn-normal ml-auto textbook__addbtn" appAddToGroup
          [identifier]="courseHierarchy?.identifier" [pageId]="courseHierarchy?.primaryCategory.toLowerCase()">
          {{resourceService?.frmelmnts?.lbl?.AddtoGroup}}</button>
      </div>

      <div *ngIf="isDesktopApp && enrolledCourse && !viewDashboard" class="d-flex py-8">
        <button type="button" class="sb-btn sb-btn-outline-primary sb-btn-normal mr-8"
          *ngIf="isConnected && (checkStatus('DOWNLOADED')) && showUpdate" tabindex="0"
          (click)="updateCollection(courseHierarchy)">{{resourceService?.frmelmnts?.btn?.update}}</button>
        <button type="button" class="sb-btn sb-btn-outline-primary sb-btn-normal mr-8"
        *ngIf="checkStatus('DOWNLOADED')" [disabled]="disableDelete" tabindex="0"
          (click)="logTelemetry('confirm-delete-collection'); showDeleteModal = !showDeleteModal;">{{resourceService?.frmelmnts?.btn?.delete}}</button>
        <button type="button" class="sb-btn sb-btn-outline-primary sb-btn-normal mr-8"
        *ngIf="checkStatus('DOWNLOADED')" tabindex="0"
          (click)="exportCollection(courseHierarchy)">{{resourceService?.frmelmnts?.lbl?.saveToPenDrive}}</button>
        <button type="button" class="sb-btn sb-btn-outline-primary sb-btn-normal mr-8" *ngIf="checkStatus('DOWNLOAD')"
          appOnlineOnly tabindex="0"
          (click)="isYoutubeContentPresent(courseHierarchy)">{{resourceService?.frmelmnts?.btn?.download}}</button>
        <button type="button" class="sb-btn sb-btn-outline-primary sb-btn-normal mr-8"
          *ngIf="checkStatus('DOWNLOADING')">{{resourceService?.frmelmnts?.lbl?.downloading}}</button>
        <button type="button" class="sb-btn sb-btn-outline-primary sb-btn-normal mr-8"
          *ngIf="checkStatus('PAUSED')">{{resourceService.frmelmnts?.lbl?.downloadingPaused}}</button>
      </div>
      <!-- join course, start learning, continue learning, view dashboard buttons -->
      <div *ngIf="!showAddGroup && isTrackable">
        <div class="certified-course__btn py-8" *ngIf="!enrolledCourse && !viewDashboard">
          <button [disabled]="!(courseConsumptionService.enableCourseEntrollment | async) || isEnrollmentAllowed(enrollmentEndDate)"
            [ngClass]="{'sb-btn-disabled': (!(courseConsumptionService.enableCourseEntrollment | async) || isEnrollmentAllowed(enrollmentEndDate))}"
            class="sb-btn sb-btn-secondary sb-btn-normal ml-auto textbook__addbtn" tabindex="0"
            (click)="showJoinModal(true); this.logTelemetry(courseHierarchy?.primaryCategory.toLowerCase() === 'course' ? 'join-course' : 'join', courseHierarchy)">{{resourceService?.frmelmnts?.btn?.enroll}}</button>
        </div>

        <div class="certified-course__btn py-8" *ngIf="enrolledCourse && progress===0 && !viewDashboard">
          <button class="sb-btn sb-btn-secondary sb-btn-normal ml-auto textbook__addbtn" [disabled]="showResumeCourse"
            tabindex="0"
            (click)="resumeCourse(true); this.logTelemetry('course-start', courseHierarchy)">{{resourceService?.frmelmnts?.lbl?.startLearning}}</button>
        </div>

        <div class="certified-course__btn py-8" *ngIf="enrolledCourse && progress>0 && !viewDashboard">
          <button class="sb-btn sb-btn-secondary sb-btn-normal textbook__addbtn ml-8 sb-btn-icon-fix"
            [disabled]="showResumeCourse" tabindex="0"
            (click)="resumeCourse(true); this.logTelemetry('course-resume', courseHierarchy)">
            <i class="icon-svg icon-svg--xs icon-play mr-8"><svg class="icon icon-svg--primary">
                <use xlink:href="assets/images/sprite.svg#play-continue"></use>
              </svg></i>{{resourceService?.frmelmnts?.btn?.continueLearning}}</button>
        </div>

        <div class="ml-auto text-right py-8"
          *ngIf="!enrolledCourse && viewDashboard && !router.url.includes('/dashboard')">
          <button appTelemetryInteract [telemetryInteractObject]="courseInteractObject"
            [telemetryInteractEdata]="{id:'viewCourseDashboard' , type: 'click' , pageid:'course-consumption'}"
            class="sb-btn sb-btn-secondary sb-btn-normal" tabindex="0" (click)="showDashboard()">
            {{resourceService?.frmelmnts?.btn?.viewCourseStatsDashboard}}
          </button>
        </div>

        <div class="ml-auto text-right py-8"
          *ngIf="!isDesktopApp && permissionService?.permissionAvailable && !enrolledCourse && viewDashboard && router.url.includes('/dashboard')"
          appPermission [permission]="dashboardPermission">
          <button appTelemetryInteract [telemetryInteractObject]="courseInteractObject"
            [telemetryInteractEdata]="{id:'close-course-dashboard' , type: 'click' , pageid:'course-consumption'}"
            class="sb-btn sb-btn-normal sb-btn-outline-primary" tabindex="0" (click)="closeDashboard()">
            {{resourceService?.frmelmnts?.btn?.closedb}}
          </button>
        </div>
      </div>
      <!--Activity Dashboard-->
      <div *ngIf="isGroupAdmin && isGroupURL" class="sb-activity-dashboard-btn-content py-8">
        <button
          class="sb-btn sb-btn-normal  sb-left-icon-btn ml-8 sb-btn-icon-fix disabled sb-btn-secondary sb-activity-dashboard-btn"
          appActivityDashboard [hierarchyData]="courseHierarchy">
          <img src="assets/images/Activity_icon.svg" width="20px" class="mr-8" alt="Activity Dashboard">
          {{resourceService?.frmelmnts?.btn?.activityDashboard}}</button>
      </div>
    </div>
  </div>
    </div>
  </div>
</div>

<div class="ui active inverted dimmer" *ngIf="showCopyLoader">
  <div class="ui text centered inline loader mt-40">{{resourceService.frmelmnts.lbl.copycontent}}</div>
</div>

<app-certificate-name-update-popup *ngIf="showProfileUpdatePopup" [profileInfo]="profileInfo"
  (close)="showProfileUpdatePopup = false"></app-certificate-name-update-popup>

<app-modal-wrapper *ngIf="sharelinkModal" [config]="{disableClose: false, panelClass: 'material-modal'}"
  (dismiss)="closeSharePopup('close-share-link-popup')">
  <ng-template sbModalContent>
    <app-share-link [shareLink]="shareLink" [telemetryShareData]="telemetryShareData">
    </app-share-link>
  </ng-template>
</app-modal-wrapper>

<div *ngIf="isDesktopApp">
  <app-modal-wrapper *ngIf="showModal" [config]="{disableClose: true, size: 'normal'}" (dismiss)="showModal = !showModal;"
    #modal>
    <ng-template sbModalContent>
      <div class="sb-modal">
        <div class="transition ui dimmer page modals active visible">
          <div class="ui modal transition active visible normal">
  
            <div class="sb-modal-header">
              {{resourceService.frmelmnts?.btn?.download}}
            </div>
            <div class="sb-modal-content">
              <p>{{resourceService?.messages?.stmsg?.m0137}}</p>
            </div>
            <div class="sb-modal-actions">
              <button class="sb-btn sb-btn-normal sb-btn-primary" tabindex="0"
                (click)="downloadCollection(courseHierarchy); showModal = !showModal;">
                {{resourceService.frmelmnts?.btn?.download}}
              </button>
              <button class="sb-btn sb-btn-normal sb-btn-outline-primary" tabindex="0"
                (click)="logTelemetry('cancel-download-collection'); showModal = !showModal;">
                {{resourceService.frmelmnts?.btn?.cancel}}
              </button>
            </div>
          </div>
        </div>
      </div>
    </ng-template>
  </app-modal-wrapper>


    <app-modal-wrapper *ngIf="showDeleteModal" [config]="{disableClose: true, size: 'normal'}"
      (dismiss)="showDeleteModal = !showDeleteModal;" #modal>
      <ng-template sbModalContent>
        <div class="sb-modal">
          <div class="transition ui dimmer page modals active visible">
            <div class="ui modal transition active visible normal">
    
              <div class="sb-modal-header">
                {{resourceService?.frmelmnts?.lbl?.delete}}
              </div>
              <div class="sb-modal-content">
                <p>{{resourceService?.frmelmnts?.lbl?.desktop?.deleteCourse | interpolate:'{name}': courseHierarchy?.name}}
                </p>
              </div>
              <div class="sb-modal-actions">
                <button class="sb-btn sb-btn-normal sb-btn-primary" tabindex="0"
                  (click)="deleteCollection(courseHierarchy); showDeleteModal = !showDeleteModal;">
                  {{resourceService?.frmelmnts?.lbl?.delete}}
                </button>
                <button class="sb-btn sb-btn-normal sb-btn-outline-primary" tabindex="0"
                  (click)="logTelemetry('cancel-delete-collection'); showDeleteModal = !showDeleteModal;">
                  {{resourceService.frmelmnts?.btn?.cancel}}
                </button>
              </div>
            </div>
          </div>
        </div>
      </ng-template>
    </app-modal-wrapper>
</div>

./course-consumption-header.component.scss

@use "@project-sunbird/sb-styles/assets/mixins/mixins" as *;


.back-btn-container {
  z-index: 1;
}

.certified-course {
  display: flex;
  justify-self: end;
  align-self: center;
}

.textbook {
  &-container {
    z-index: 2;
    box-shadow: 0 0.125rem 0.4375rem 0 rgba(0, 0, 0, .16);
    position: relative;
    background-color: var(--gray-0);
  }

  &__details {
    flex: 1;
    min-width: 0;
  }

  &__bookimg {
    width: calculateRem(48px);
    height: calculateRem(48px);

    img {
      width: calculateRem(48px);
      height: calculateRem(48px);
    }
  }

  &__heading {
    min-width: 0;

    .textbook__title {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }

  &__addbtn {
    white-space: nowrap;
  }
}

@include respond-below(sm) {
  .certified-course {
    justify-self: start;
  }
}


// profile certificate modal styles
.profile-section-content{
  margin: 0 calculateRem(48px);
  @include respond-below(sm) {
    margin: 0;
  }
  .profile-info{
    span{
      &:first-child{
        font-size: calculateRem(12px);
      }
      color: var(--gray);
      font-size: calculateRem(20px);
    }
  }
  .profile-info-para{
    font-size: calculateRem(14px);
  }
}

.sb-activity-dashboard-btn {
  box-shadow: none;
  color: var(--white) !important;
  font-size: calculateRem(12px);
  padding-bottom: calculateRem(28px);
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""