File

src/app/modules/public/module/course/components/course-consumption/public-course-player/public-course-player.component.ts

Implements

OnInit OnDestroy AfterViewInit

Metadata

Index

Properties
Methods

Constructor

constructor(activatedRoute: ActivatedRoute, configService: ConfigService, courseConsumptionService: CourseConsumptionService, router: Router, resourceService: ResourceService, navigationhelperService: NavigationHelperService, userService: UserService, telemetryService: TelemetryService, contentUtilsServiceService: ContentUtilsServiceService, generaliseLabelService: GeneraliseLabelService)
Parameters :
Name Type Optional
activatedRoute ActivatedRoute No
configService ConfigService No
courseConsumptionService CourseConsumptionService No
router Router No
resourceService ResourceService No
navigationhelperService NavigationHelperService No
userService UserService No
telemetryService TelemetryService No
contentUtilsServiceService ContentUtilsServiceService No
generaliseLabelService GeneraliseLabelService No

Methods

closeSharePopup
closeSharePopup(id)
Parameters :
Name Optional
id No
Returns : void
getAllBatchDetails
getAllBatchDetails(event)
Parameters :
Name Optional
event No
Returns : void
getGeneraliseResourceBundle
getGeneraliseResourceBundle()
Returns : void
isExpanded
isExpanded(index: number)
Parameters :
Name Type Optional
index number No
Returns : any
logTelemetry
logTelemetry(id, content?: literal type)
Parameters :
Name Type Optional
id No
content literal type Yes
Returns : void
Public navigateToContent
navigateToContent(event: any, id)
Parameters :
Name Type Optional
event any No
id No
Returns : void
ngAfterViewInit
ngAfterViewInit()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
Private parseChildContent
parseChildContent()
Returns : void
Private setTelemetryCourseImpression
setTelemetryCourseImpression()
Returns : void
setTelemetryShareData
setTelemetryShareData(param)
Parameters :
Name Optional
param No
Returns : void
shareUnitLink
shareUnitLink(unit: any)
Parameters :
Name Type Optional
unit any No
Returns : void

Properties

Public activatedRoute
Type : ActivatedRoute
cardType
Type : TocCardType
Default value : TocCardType.COURSE
collectionTreeNodes
Type : any
collectionTreeOptions
Type : ICollectionTreeOptions
courseHierarchy
Type : any
Private courseId
Type : string
curriculum
Type : []
Default value : []
Public generaliseLabelService
Type : GeneraliseLabelService
isExpandedAll
Type : boolean
joinTrainingModal
Decorators :
@ViewChild('joinTrainingModal')
loader
Default value : true
loaderMessage
Type : ILoaderMessage
Default value : { headerMessage: 'Please wait...', loaderMessage: 'Fetching content details!' }
Public navigationhelperService
Type : NavigationHelperService
readMore
Default value : false
Public resourceService
Type : ResourceService
Public router
Type : Router
shareLink
Type : string
shareLinkModal
Default value : false
showContentCreditsModal
Type : boolean
showError
Default value : false
showJoinTrainingModal
Default value : false
telemetryCourseImpression
Type : IImpressionEventInput
Public telemetryService
Type : TelemetryService
telemetryShareData
Type : Array<ITelemetryShare>
treeModel
Type : any
unsubscribe
Default value : new Subject<void>()
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Component, OnInit, OnDestroy, AfterViewInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import * as _ from 'lodash-es';
import {
  ILoaderMessage, ConfigService, ICollectionTreeOptions, ResourceService,
  NavigationHelperService
} from '@sunbird/shared';
import { CourseConsumptionService } from '@sunbird/learn';
import { IImpressionEventInput, TelemetryService } from '@sunbird/telemetry';
import TreeModel from 'tree-model';
import { UserService, GeneraliseLabelService } from '@sunbird/core';
import { TocCardType } from '@project-sunbird/common-consumption';
import { ITelemetryShare, ContentUtilsServiceService } from '@sunbird/shared';

@Component({
  selector: 'app-public-course-player',
  templateUrl: './public-course-player.component.html',
  styleUrls: ['./public-course-player.component.scss']
})
export class PublicCoursePlayerComponent implements OnInit, OnDestroy, AfterViewInit {
  private courseId: string;
  collectionTreeNodes: any;
  loader = true;
  showError = false;
  courseHierarchy: any;
  readMore = false;
  curriculum = [];
  telemetryCourseImpression: IImpressionEventInput;
  treeModel: any;
  showContentCreditsModal: boolean;
  cardType: TocCardType = TocCardType.COURSE;
  loaderMessage: ILoaderMessage = {
    headerMessage: 'Please wait...',
    loaderMessage: 'Fetching content details!'
  };
  collectionTreeOptions: ICollectionTreeOptions;
  unsubscribe = new Subject<void>();
  showJoinTrainingModal = false;
  shareLinkModal = false;
  telemetryShareData: Array<ITelemetryShare>;
  shareLink: string;
  @ViewChild('joinTrainingModal') joinTrainingModal;
  isExpandedAll: boolean;

  constructor(
    public activatedRoute: ActivatedRoute,
    private configService: ConfigService,
    private courseConsumptionService: CourseConsumptionService,
    public router: Router,
    public resourceService: ResourceService,
    public navigationhelperService: NavigationHelperService,
    private userService: UserService,
    public telemetryService: TelemetryService,
    private contentUtilsServiceService: ContentUtilsServiceService,
    public generaliseLabelService: GeneraliseLabelService
  ) {
    this.collectionTreeOptions = this.configService.appConfig.collectionTreeOptions;
  }

  ngOnInit() {
    const routeParams: any = { ...this.activatedRoute.snapshot.params };
    this.courseId = routeParams.courseId;
    const inputParams = { params: this.configService.appConfig.CourseConsumption.contentApiQueryParams };
    this.courseConsumptionService.getCourseHierarchy(routeParams.courseId, inputParams).pipe(
      takeUntil(this.unsubscribe))
      .subscribe(courseHierarchy => {
        this.loader = false;
        this.courseHierarchy = courseHierarchy;
        this.isExpandedAll = this.courseHierarchy.children && this.courseHierarchy.children.length === 1 ? true : undefined;
        this.parseChildContent();
        this.collectionTreeNodes = { data: this.courseHierarchy };
        this.getGeneraliseResourceBundle();
      });
  }

  getGeneraliseResourceBundle() {
    this.resourceService.languageSelected$.pipe(takeUntil(this.unsubscribe)).subscribe(item => {
      this.generaliseLabelService.initialize(this.courseHierarchy, item.value);
    });
  }

  private parseChildContent() {
    const model = new TreeModel();
    const mimeTypeCount = {};
    this.treeModel = model.parse(this.courseHierarchy);
    this.treeModel.walk((node) => {
      if (node.model.mimeType !== 'application/vnd.ekstep.content-collection') {
        if (mimeTypeCount[node.model.mimeType]) {
          mimeTypeCount[node.model.mimeType] += 1;
        } else {
          mimeTypeCount[node.model.mimeType] = 1;
        }
      }
    });

    let videoContentCount = 0;
    _.forEach(mimeTypeCount, (value, key) => {
      if (key.includes('video')) {
        videoContentCount = videoContentCount + value;
      } else {
        this.curriculum.push({ mimeType: key, count: value });
      }
    });
    if (videoContentCount > 0) {
      this.curriculum.push({ mimeType: 'video', count: videoContentCount });
    }
  }
  ngAfterViewInit() {
    setTimeout(() => {
      this.setTelemetryCourseImpression();
    });
  }

  isExpanded(index: number) {
    if (_.isUndefined(this.isExpandedAll)) {
      return Boolean(index === 0);
    }
    return this.isExpandedAll;
  }

  ngOnDestroy() {
    if (this.joinTrainingModal && this.joinTrainingModal.deny) {
      this.joinTrainingModal.deny();
    }
    this.unsubscribe.next();
    this.unsubscribe.complete();
  }
  private setTelemetryCourseImpression() {
    this.telemetryCourseImpression = {
      context: {
        env: this.activatedRoute.snapshot.data.telemetry.env
      },
      edata: {
        type: this.activatedRoute.snapshot.data.telemetry.type,
        pageid: this.activatedRoute.snapshot.data.telemetry.pageid,
        uri: this.router.url,
        duration: this.navigationhelperService.getPageLoadTime()
      },
      object: {
        id: this.activatedRoute.snapshot.params.courseId,
        type: 'Course',
        ver: '1.0',
        rollup: {
          l1: this.activatedRoute.snapshot.params.courseId
        }
      }
    };
  }

  public navigateToContent(event: any, id) {
    this.logTelemetry(id, event.data);
    if (!_.get(this.userService, 'userid') && !_.isEmpty(event.event)) {
      this.showJoinTrainingModal = true;
    }
  }



  logTelemetry(id, content?: {}) {
    const objectRollUp = this.courseConsumptionService.getContentRollUp(this.courseHierarchy, _.get(content, 'identifier'));
    const interactData = {
      context: {
        env: _.get(this.activatedRoute.snapshot.data.telemetry, 'env') || 'content',
        cdata: []
      },
      edata: {
        id: id,
        type: 'click',
        pageid: _.get(this.activatedRoute.snapshot.data.telemetry, 'pageid') || 'explore-course-toc',
      },
      object: {
        id: content ? _.get(content, 'identifier') : this.activatedRoute.snapshot.params.courseId,
        type: content ? _.get(content, 'contentType') : 'Course',
        ver: content ? `${_.get(content, 'pkgVersion')}` : `1.0`,
        rollup: this.courseConsumptionService.getRollUp(objectRollUp) || {}
      }
    };
    this.telemetryService.interact(interactData);
  }

  getAllBatchDetails(event) {
    this.courseConsumptionService.getAllOpenBatches(event);
  }

  shareUnitLink(unit: any) {
    this.shareLink = `${this.contentUtilsServiceService.getCoursePublicShareUrl(this.courseId)}?moduleId=${unit.identifier}`;
    this.shareLinkModal = true;
    this.setTelemetryShareData(this.courseHierarchy);
  }

  setTelemetryShareData(param) {
    this.telemetryShareData = [{
      id: param.identifier,
      type: param.contentType,
      ver: param.pkgVersion ? param.pkgVersion.toString() : '1.0'
    }];
  }

  closeSharePopup(id) {
    this.shareLinkModal = false;
    const interactData = {
      context: {
        env: _.get(this.activatedRoute.snapshot.data.telemetry, 'env') || 'explore',
        cdata: [{ id: this.courseId, type: 'Course' }]
      },
      edata: {
        id: id,
        type: 'click',
        pageid: _.get(this.activatedRoute.snapshot.data.telemetry, 'pageid') || 'explore-course-toc',
      },
      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);
  }
}
<div *ngIf="!loader">
  <div class="ui container" [appTelemetryImpression]="telemetryCourseImpression">
    <div class="sb-course-details sb-g sb-g--gap24 text-left course-consumption-container">
      <div class="sb-course-details__training sb-g-col-xs-12 sb-g-col-md-9 sb-g-col-lg-9 sb-g-col-xxxl-12">
        <!-- Course details -->
        <div class="training-info" *ngIf="courseHierarchy">
          <h4 class="font-weight-bold">{{generaliseLabelService?.frmelmnts?.lbl?.courseDetails}}</h4>
          <div class="training-relevant mb-16">
            <h6 class="mt-0 mb-8 fsmall training-relevant__heading">
              {{generaliseLabelService?.frmelmnts?.lbl?.courseRelevantFor}}</h6>
              <div class="training-relevant__class mb-4 sb-color-gray-400 fnormal" *ngIf="courseHierarchy?.se_boards">
                <span>{{resourceService?.frmelmnts?.lbl?.board | transposeTerms: 'frmelmnts.lbl.board' : resourceService?.selectedLang}}:&nbsp;</span><span>{{ courseHierarchy?.se_boards?.join(', ')}}</span>
              </div>
              <div class="training-relevant__medium mb-4 sb-color-gray-400 fnormal" *ngIf="courseHierarchy?.se_mediums">
                <span>{{resourceService?.frmelmnts?.lbl?.medium | transposeTerms: 'frmelmnts.lbl.medium' : resourceService?.selectedLang}}:&nbsp;</span><span>{{ courseHierarchy?.se_mediums?.join(', ')}}</span>
              </div>
              <div class="training-relevant__subject mb-4 sb-color-gray-400 fnormal" *ngIf="courseHierarchy?.se_gradeLevels">
                <span>{{resourceService?.frmelmnts?.lbl?.class | transposeTerms: 'frmelmnts.lbl.class' : resourceService?.selectedLang}}:&nbsp;</span><span>{{ courseHierarchy?.se_gradeLevels?.join(', ')}}</span>
              </div>
              <!-- <div class="training-relevant__medium mb-4 sb-color-gray-400 fnormal" *ngIf="courseHierarchy?.se_subjects">
                <span>{{resourceService?.frmelmnts?.lbl?.subject}}:&nbsp;</span><span>{{ courseHierarchy?.se_subjects?.join(', ')}}</span>
              </div> -->
              <div class="training-relevant__medium mb-4 sb-color-gray-400 fnormal" *ngIf="courseHierarchy?.audience">
                <span>{{resourceService?.frmelmnts?.lbl?.userType}}:&nbsp;</span><span>{{ courseHierarchy?.audience?.join(', ')}}</span>
              </div>
            <div *ngIf="courseHierarchy?.description">
              <label class="fsmall mt-16 mb-8">{{resourceService?.frmelmnts?.lbl?.description}}</label>
              <p *ngIf="!readMore" class="traning-relevant__description sb-color-gray-400 fnormal">
                {{ courseHierarchy?.description | slice:0:200 }}&nbsp;
                <span class="ui cardsKnowMore mouse-pointer"
                  *ngIf="courseHierarchy?.description?.length > 200 && readMore === false"
                  tabindex="0" (click)="readMore = !readMore;">{{resourceService?.frmelmnts?.lbl?.readmore}}</span>
              </p>
              <p *ngIf="readMore" class="traning-relevant__description sb-color-gray-400">
                {{ courseHierarchy?.description}}&nbsp;
                <span class="ui cardsKnowMore mouse-pointer"
                  tabindex="0" (click)="readMore = false;">{{resourceService?.frmelmnts?.lbl?.readless}}</span>
              </p>
            </div>
          </div>
        </div>

        <div class="training-modules my-16">
          <div class="training-modules__title d-flex flex-ai-center mb-16">
            <h4 class="sb-pageSection-title sb-pageSection-title-light">
              {{generaliseLabelService?.frmelmnts?.lbl?.coursestructure}}</h4>
            <button *ngIf="!isExpandedAll"
              class="sb-btn sb-btn-normal sb-btn-outline-primary ml-auto d-flex flex-ai-center" tabindex="0"
              tabindex="0" (click)="isExpandedAll = true; logTelemetry('expand-all', courseHierarchy);"><img
                src="assets/images/plus.png" class="mr-8" alt=""
                width="12px">{{resourceService?.frmelmnts?.lbl?.expandAll}}</button>
            <button *ngIf="isExpandedAll"
              class="sb-btn sb-btn-normal sb-btn-outline-primary ml-auto d-flex flex-ai-center" tabindex="0"
              tabindex="0" (click)="isExpandedAll = false; logTelemetry('collapse-all', courseHierarchy);"><img
                src="assets/images/collapse.png" class="mr-8" alt=""
                width="12px">{{resourceService?.frmelmnts?.lbl?.collapseAll}}</button>
          </div>

          <div class="course-consumption-modules-container" *ngFor="let item of courseHierarchy?.children; let index = index">
            <sb-accordion [multi]="false">
              <sb-accordion-item [expanded]="isExpanded(index)">
                <sb-accordion-header class="sb-bg-color-gray-0">
                  <i class="icon-svg icon-svg--sm icon-tick mr-8"
                    *ngIf="enrolledCourse && item?.consumedContent === item?.contentCount">
                    <svg class="icon">
                      <use xlink:href="./assets/images/sprite.svg#circle-with-check-symbol"></use>
                    </svg>
                  </i>
                  {{item?.name}}
                </sb-accordion-header>
                <sb-accordion-body>
                  <div class="chapter-box sb-g">
                    <section class="sb-g-col-xs-12 sb-g-col-md-12 sb-g-col-lg-12 sb-g-col-xxxl-16">
                      <div *ngIf="item;else noContent">
                        <div
                          *ngIf="item?.mimeType !== 'application/vnd.ekstep.content-collection' && !item?.children?.length">
                          <div class="child-content-padding">
                            <sb-toc-card [content]="item" (tocCardClick)="navigateToContent($event, 'toc-card')"
                              [type]="cardType">
                            </sb-toc-card>
                          </div>
                        </div>
                        <div *ngIf="item?.children?.length">
                          <div *ngFor="let child of item?.children">
                            <div>
                              <sb-toc-child-item [childData]="child"
                                (tocCardClick)="navigateToContent($event, 'child-item')" [type]="cardType" class="sb-toc-child-item">
                              </sb-toc-child-item>
                            </div>
                          </div>
                        </div>
                      </div>
                      <ng-template #noContent>
                        <div class="heading">{{noContentMessage}}</div>
                      </ng-template>
                    </section>
                  </div>
                </sb-accordion-body>
              </sb-accordion-item>
            </sb-accordion>
          </div>
        </div>
      </div>
      <div class="sb-course-details__info sb-g-col-xs-12 sb-g-col-md-3 sb-g-col-lg-3 sb-g-col-xxxl-4">

        <app-public-batch-details [courseId]="courseId" [courseHierarchy]="courseHierarchy"
          (allBatchDetails)="getAllBatchDetails($event)">
        </app-public-batch-details>

        <!-- Credits & License information -->
        <div class="course-player--metadata text-left">
          <app-course-info [courseHierarchy]="courseHierarchy"></app-course-info>
        </div>

      </div>
    </div>
  </div>
</div>

<div *ngIf="loader">
  <app-loader [data]="loaderMessage"></app-loader>
</div>

  <app-modal-wrapper *ngIf="showJoinTrainingModal" [config]="{disableClose: true, size: 'small', panelClass: 'material-modal'}"
    (dismiss)="showJoinTrainingModal = false; logTelemetry('join-training-popup-close')" #joinTrainingModal>
    <ng-template sbModalContent>
      <div class="sb-mat__modal sb-mat__modal--small">
        <div mat-dialog-title class="mb-0">
          <div class="title">{{generaliseLabelService?.frmelmnts?.btn?.enroll}}</div>
          <button aria-label="close dialog" mat-dialog-close class="close-btn"></button>
        </div>

        <div class="sb-mat__modal__content d-flex flex-ai-center flex-jc-center">
          <div>
            <p>{{generaliseLabelService?.frmelmnts?.lbl?.accessToLogin}}</p>
          </div>
        </div>

        <div class="sb-mat__modal__actions"></div>
      </div>
    </ng-template>
  </app-modal-wrapper>

<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>

./public-course-player.component.scss

@use "@project-sunbird/sb-styles/assets/mixins/mixins" as *;
@use "pages/course-player" as *;
@use 'pages/content-header' as *;

.course-list_title {
  color: var(--gray-800);
  font-size: calculateRem(14px);
  font-weight: bold;
  line-height: calculateRem(24px);
}
.course-list-progress {
  padding: calculateRem(16px);
  &__title {
    color: var(--gray-800);
    font-size: calculateRem(12px);
  }
  &__status {
    color: var(--primary-color);
    font-size: calculateRem(14px);
    font-weight: bold;
  }
  &__barholder {
    margin: 0px;
    height: calculateRem(8px);
  }
  &__info {
    color: var(--gray-800);
    font-size: calculateRem(12px);
  }
}

:host ::ng-deep {
  .ui.progress .bar {
    height: calculateRem(8px) !important;
  }
}

.header-shadow {
  min-height: calculateRem(80px);
  background-color: var(--gray-0);
  box-shadow: 0 calculateRem(10px) calculateRem(10px) calculateRem(-10px) rgba(var(--rc-rgba-black), 0.025);
  z-index: 99;
}

.chapter-box {
  border-bottom: .0625rem solid var(--gray-100);
  border-radius: calculateRem(2px);
  &:last-child{
    border-bottom: 0px solid var(--gray-100);
    padding-bottom:0px;
  }
}

.certified-course__certificate {
  background-color: var(--rc-E0F1FD);
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""