src/app/modules/shared-feature/components/content-player/content-player.component.ts
OnInit
AfterViewInit
OnDestroy
ComponentCanDeactivate
selector | app-content-player |
styleUrls | ./content-player.component.scss |
templateUrl | ./content-player.component.html |
Properties |
|
Methods |
HostListeners |
constructor(activatedRoute: ActivatedRoute, navigationHelperService: NavigationHelperService, userService: UserService, resourceService: ResourceService, router: Router, toasterService: ToasterService, windowScrollService: WindowScrollService, playerService: PlayerService, publicPlayerService: PublicPlayerService, copyContentService: CopyContentService, permissionService: PermissionService, contentUtilsServiceService: ContentUtilsServiceService, popupControlService: PopupControlService, configService: ConfigService, layoutService: LayoutService, telemetryService: TelemetryService)
|
|||||||||||||||||||||||||||||||||||||||||||||||||||
Parameters :
|
window:beforeunload |
window:beforeunload()
|
canDeactivate |
canDeactivate()
|
Decorators :
@HostListener('window:beforeunload')
|
Returns :
boolean
|
copyContent | ||||||
copyContent(contentData: ContentData)
|
||||||
Parameters :
Returns :
void
|
getContent |
getContent()
|
Returns :
void
|
getPublicContent |
getPublicContent()
|
Returns :
void
|
getQuestionSetHierarchy |
getQuestionSetHierarchy()
|
Returns :
void
|
goBack |
goBack()
|
Returns :
void
|
initLayout |
initLayout()
|
Returns :
void
|
ngAfterViewInit |
ngAfterViewInit()
|
Returns :
void
|
ngOnDestroy |
ngOnDestroy()
|
Returns :
void
|
ngOnInit |
ngOnInit()
|
Returns :
void
|
onShareLink |
onShareLink()
|
Returns :
void
|
setTelemetryData |
setTelemetryData()
|
Returns :
void
|
setTelemetryShareData | ||||
setTelemetryShareData(param)
|
||||
Parameters :
Returns :
void
|
Public activatedRoute |
Type : ActivatedRoute
|
contentData |
Type : ContentData
|
contentId |
Type : string
|
contentStatus |
Type : string
|
Public contentUtilsServiceService |
Type : ContentUtilsServiceService
|
copyContentInteractEdata |
Type : IInteractEventEdata
|
Public copyContentService |
Type : CopyContentService
|
Public dialCode |
Type : string
|
errorMessage |
Type : string
|
groupId |
Type : string
|
isDesktopApp |
Default value : false
|
isFullScreenView |
Default value : false
|
isGroupAdmin |
Type : boolean
|
isQuestionSet |
Default value : false
|
isTypeCopyQuestionset |
Type : boolean
|
Default value : false
|
layoutConfiguration |
Public layoutService |
Type : LayoutService
|
Public navigationHelperService |
Type : NavigationHelperService
|
objectInteract |
Type : IInteractEventObject
|
Public objectRollup |
Type : object
|
Default value : {}
|
Public pageLoadDuration |
Type : Number
|
Public permissionService |
Type : PermissionService
|
playerConfig |
Type : PlayerConfig
|
playerOption |
Type : any
|
Public playerService |
Type : PlayerService
|
Public popupControlService |
Type : PopupControlService
|
Public publicPlayerService |
Type : PublicPlayerService
|
Public resourceService |
Type : ResourceService
|
Public router |
Type : Router
|
shareLink |
Type : string
|
sharelinkModal |
Type : boolean
|
showError |
Default value : false
|
showLoader |
Default value : true
|
showPlayer |
Default value : false
|
telemetryImpression |
Type : IImpressionEventInput
|
Public telemetryService |
Type : TelemetryService
|
telemetryShareData |
Type : Array<ITelemetryShare>
|
Public toasterService |
Type : ToasterService
|
Public unsubscribe |
Default value : new Subject<void>()
|
Public unsubscribe$ |
Default value : new Subject<void>()
|
Public userService |
Type : UserService
|
Public windowScrollService |
Type : WindowScrollService
|
import { ActivatedRoute } from '@angular/router';
import { Component, OnInit, AfterViewInit, OnDestroy, HostListener } from '@angular/core';
import { Router } from '@angular/router';
import { UserService, PlayerService, CopyContentService, PermissionService } from '@sunbird/core';
import * as _ from 'lodash-es';
import {
ConfigService, ResourceService, ToasterService, WindowScrollService, NavigationHelperService,
PlayerConfig, ContentData, ContentUtilsServiceService, ITelemetryShare, LayoutService
} from '@sunbird/shared';
import { IInteractEventObject, IInteractEventEdata, IImpressionEventInput, TelemetryService } from '@sunbird/telemetry';
import { PopupControlService } from '../../../../service/popup-control.service';
import { takeUntil, mergeMap } from 'rxjs/operators';
import { Subject, of, throwError } from 'rxjs';
import { PublicPlayerService, ComponentCanDeactivate } from '@sunbird/public';
import { CsGroupAddableBloc } from '@project-sunbird/client-services/blocs';
@Component({
selector: 'app-content-player',
templateUrl: './content-player.component.html',
styleUrls: ['./content-player.component.scss']
})
export class ContentPlayerComponent implements OnInit, AfterViewInit, OnDestroy, ComponentCanDeactivate {
telemetryImpression: IImpressionEventInput;
objectInteract: IInteractEventObject;
copyContentInteractEdata: IInteractEventEdata;
sharelinkModal: boolean;
shareLink: string;
contentId: string;
contentStatus: string;
playerConfig: PlayerConfig;
showPlayer = false;
showError = false;
errorMessage: string;
contentData: ContentData;
telemetryShareData: Array<ITelemetryShare>;
public pageLoadDuration: Number;
playerOption: any;
showLoader = true;
isFullScreenView = false;
layoutConfiguration;
public unsubscribe = new Subject<void>();
public dialCode: string;
public unsubscribe$ = new Subject<void>();
public objectRollup = {};
isGroupAdmin: boolean;
groupId: string;
isQuestionSet = false;
isDesktopApp = false;
isTypeCopyQuestionset:boolean = false;
@HostListener('window:beforeunload')
canDeactivate() {
// returning true will navigate without confirmation
// returning false will show a confirm dialog before navigating away
const deviceType = this.telemetryService.getDeviceType();
return deviceType === 'Desktop' && this.isQuestionSet && !this.isTypeCopyQuestionset ? false : true;
}
constructor(public activatedRoute: ActivatedRoute, public navigationHelperService: NavigationHelperService,
public userService: UserService, public resourceService: ResourceService, public router: Router,
public toasterService: ToasterService, public windowScrollService: WindowScrollService,
public playerService: PlayerService, public publicPlayerService: PublicPlayerService,
public copyContentService: CopyContentService, public permissionService: PermissionService,
public contentUtilsServiceService: ContentUtilsServiceService, public popupControlService: PopupControlService,
private configService: ConfigService,
public layoutService: LayoutService, public telemetryService: TelemetryService) {
this.playerOption = {
showContentRating: true
};
}
ngOnInit() {
console.log('content');
this.isQuestionSet = _.includes(this.router.url, 'questionset');
this.isDesktopApp = this.userService.isDesktopApp;
this.initLayout();
this.activatedRoute.params.subscribe((params) => {
this.showPlayer = false;
this.contentId = params.contentId;
this.contentStatus = params.contentStatus;
this.dialCode = _.get(this.activatedRoute, 'snapshot.queryParams.dialCode');
if (_.get(this.activatedRoute, 'snapshot.queryParams.l1Parent')) {
this.objectRollup = {
l1: _.get(this.activatedRoute, 'snapshot.queryParams.l1Parent')
};
}
CsGroupAddableBloc.instance.state$.pipe(takeUntil(this.unsubscribe$)).subscribe(data => {
this.groupId = _.get(data, 'groupId') || _.get(this.activatedRoute.snapshot, 'queryParams.groupId');
});
this.getContent();
CsGroupAddableBloc.instance.state$.pipe(takeUntil(this.unsubscribe$)).subscribe(data => {
this.isGroupAdmin = !_.isEmpty(_.get(this.activatedRoute.snapshot, 'queryParams.groupId'))
&& _.get(data.params, 'groupData.isAdmin');
});
});
this.navigationHelperService.contentFullScreenEvent.
pipe(takeUntil(this.unsubscribe)).subscribe(isFullScreen => {
this.isFullScreenView = isFullScreen;
});
}
initLayout() {
this.layoutConfiguration = this.layoutService.initlayoutConfig();
this.layoutService.switchableLayout().
pipe(takeUntil(this.unsubscribe)).subscribe(layoutConfig => {
if (layoutConfig != null) {
this.layoutConfiguration = layoutConfig.layout;
}
});
}
setTelemetryData() {
this.telemetryImpression = {
context: {
env: this.activatedRoute.snapshot.data.telemetry.env,
cdata: this.groupId ? [{id: this.groupId, type: 'Group'}] : [],
},
object: {
id: this.contentId,
type: this.contentData.contentType,
ver: this.contentData.pkgVersion ? this.contentData.pkgVersion.toString() : '1.0'
},
edata: {
type: this.activatedRoute.snapshot.data.telemetry.type,
pageid: this.activatedRoute.snapshot.data.telemetry.pageid,
uri: this.router.url,
subtype: this.activatedRoute.snapshot.data.telemetry.subtype,
duration: this.pageLoadDuration
}
};
this.objectInteract = {
id: this.contentId,
type: this.contentData.contentType,
ver: this.contentData.pkgVersion ? this.contentData.pkgVersion.toString() : '1.0'
};
this.copyContentInteractEdata = {
id: 'copy-content-button',
type: 'click',
pageid: this.activatedRoute.snapshot.data.telemetry.pageid
};
}
goBack() {
this.navigationHelperService.goBack();
}
getContent() {
if (this.isQuestionSet) {
this.getQuestionSetHierarchy();
} else if (this.userService.loggedIn) {
const option = { params: this.configService.appConfig.ContentPlayer.contentApiQueryParams };
if (this.contentStatus && this.contentStatus === 'Unlisted') {
option.params = { mode: 'edit' };
}
this.playerService.getContent(this.contentId, option).subscribe(
(response) => {
this.showLoader = false;
if (response.result.content.status === 'Live' || response.result.content.status === 'Unlisted') {
this.showPlayer = true;
const contentDetails = {
contentId: this.contentId,
contentData: response.result.content
};
this.playerConfig = this.playerService.getConfig(contentDetails);
this.contentData = response.result.content;
this.setTelemetryData();
this.windowScrollService.smoothScroll('content-player');
} else {
this.toasterService.warning(this.resourceService.messages.imsg.m0027);
}
},
(err) => {
this.showLoader = false;
this.showError = true;
this.errorMessage = this.resourceService.messages.stmsg.m0009;
});
} else {
this.getPublicContent();
}
}
getQuestionSetHierarchy() {
const serveiceRef = this.userService.loggedIn ? this.playerService : this.publicPlayerService;
this.publicPlayerService.getQuestionSetHierarchy(this.contentId).pipe(
takeUntil(this.unsubscribe$))
.subscribe((response) => {
this.showLoader = false;
const contentDetails = {
contentId: this.contentId,
contentData: response.questionSet
};
this.playerConfig = serveiceRef.getConfig(contentDetails);
this.playerConfig.context.objectRollup = this.objectRollup;
this.contentData = response.questionSet;
this.showPlayer = true;
}, (err) => {
this.showLoader = false;
this.showError = true;
this.errorMessage = this.resourceService.messages.stmsg.m0009;
});
}
getPublicContent() {
const options: any = { dialCode: this.dialCode };
const params = { params: this.configService.appConfig.PublicPlayer.contentApiQueryParams };
this.publicPlayerService.getContent(this.contentId, params).pipe(
mergeMap((response) => {
if (_.get(response, 'result.content.status') === 'Unlisted') {
return throwError({
code: 'UNLISTED_CONTENT'
});
}
return of(response);
}),
takeUntil(this.unsubscribe$))
.subscribe((response) => {
this.showLoader = false;
const contentDetails = {
contentId: this.contentId,
contentData: response.result.content
};
this.playerConfig = this.publicPlayerService.getConfig(contentDetails, options);
this.playerConfig.context.objectRollup = this.objectRollup;
this.contentData = response.result.content;
this.showPlayer = true;
}, (err) => {
this.showLoader = false;
this.showError = true;
this.errorMessage = this.resourceService.messages.stmsg.m0009;
});
}
copyContent(contentData: ContentData) {
let successMsg = '';
let errorMsg = '';
this.isTypeCopyQuestionset = _.get(contentData, 'mimeType') === 'application/vnd.sunbird.questionset';
this.isTypeCopyQuestionset ? (successMsg = this.resourceService.messages.smsg.m0067, errorMsg = this.resourceService.messages.emsg.m0067) : (successMsg = this.resourceService.messages.smsg.m0042, errorMsg = this.resourceService.messages.emsg.m0008);
this.copyContentService.copyContent(contentData).subscribe(
(response) => {
this.toasterService.success(successMsg);
},
(err) => {
this.toasterService.error(errorMsg);
});
}
onShareLink() {
this.shareLink = this.contentUtilsServiceService.getPublicShareUrl(this.contentId, this.contentData.mimeType);
this.setTelemetryShareData(this.contentData);
}
ngAfterViewInit() {
this.pageLoadDuration = this.navigationHelperService.getPageLoadTime();
}
setTelemetryShareData(param) {
this.telemetryShareData = [{
id: param.identifier,
type: param.contentType,
ver: param.pkgVersion ? param.pkgVersion.toString() : '1.0'
}];
}
ngOnDestroy() {
this.unsubscribe$.next();
this.unsubscribe$.complete();
}
}
<app-landing-section [textToDisplay]="" [layoutConfiguration]="layoutConfiguration" [noTitle]="true">
</app-landing-section>
<!--CC-Player Content Header -->
<div
[ngClass]="{'sb-back-actionbar' : layoutConfiguration,'sb-bg-white cc-player__btn-back': !layoutConfiguration,'header-block': isFullScreenView}"
class="relative position mt-0">
<div class="ui container py-0 px-0 d-flex flex-ai-center">
<div class="w-100 d-flex flex-ai-center flex-w-wrap flex-jc-space-between" *ngIf="contentData">
<div class="d-flex flex-ai-center">
<button type="button" (click)="goBack()"
[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" 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>
<div class="textbook__details d-flex ml-16 flex-basis-1 flex-ai-center">
<div class="textbook__heading">
<h5 class="sb-color-primary font-weight-bold mb-0 sb__ellipsis" tabindex="0" role="heading" aria-level="2">
{{contentData.name}}</h5>
<div class="content-header__info mt-4">
<span class="fnormal" *ngIf="contentData?.subject">{{contentData?.subject}}</span>
<span class="dot-divider" *ngIf="contentData.gradeLevel"></span>
<span class="fnormal" *ngIf="contentData?.gradeLevel">{{contentData?.gradeLevel}}</span>
</div>
</div>
</div>
</div>
<div class="d-flex flex-ai-end flex-w-wrap content-header__buttons ml-auto">
<a href="javascript:void(0)" tabindex="0" (click)="onShareLink();sharelinkModal=true;"
class="sb-btn sb-btn-normal sb-btn-outline-primary mr-8">
<i class="blue share alternate icon"></i>
{{resourceService?.frmelmnts?.lbl?.share}}
</a>
<button type="button" *ngIf='!isDesktopApp && permissionService?.permissionAvailable ' appPermission
[permission]="['CONTENT_CREATOR', 'CONTENT_REVIEWER']" tabindex="0" (click)="copyContent(contentData)"
appTelemetryInteract [telemetryInteractEdata]="copyContentInteractEdata"
[telemetryInteractObject]="objectInteract" class="sb-btn sb-btn-normal sb-btn-outline-primary mr-8">
<i class="blue clone outline icon"></i> {{resourceService?.frmelmnts?.lbl?.copy}}
</button>
<div class="certified-course__btn" *ngIf="isGroupAdmin">
<button class="sb-btn sb-btn-secondary sb-btn-normal ml-auto textbook__addbtn" appAddToGroup
[identifier]="contentData?.identifier" [pageId]="contentData?.primaryCategory.toLowerCase()">
{{resourceService?.frmelmnts?.lbl?.AddtoGroup}}</button>
</div>
</div>
</div>
</div>
</div>
<div [ngClass]="layoutConfiguration ? 'sbt-inside-page-container' : ''">
<div class="relative9" [ngStyle]="{'height':'fit-content'}" [style.display]="!showLoader ? 'block' : 'none'"
*ngIf="contentData">
<!-- CC-Player Video -->
<div class="sb-single-resource">
<div class="ui container">
<div class="cc-player sb-g">
<section class="sb-g-col-xs-12 sb-g-col-md-12 sb-g-col-lg-12 sb-g-col-xxxl-16 cc-player__video"
[appTelemetryImpression]="telemetryImpression">
<app-contentplayer-page [playerConfig]="playerConfig" [tocPage]="true" [contentDetails]="contentData"
[isContentPresent]="isContentPresent" [objectRollUp]="objectRollup">
</app-contentplayer-page>
</section>
</div>
</div>
</div>
<div class="twelve wide column" *ngIf="showLoader">
<app-loader [data]='loaderMessage'></app-loader>
</div>
<app-modal-wrapper *ngIf="sharelinkModal" [config]="{disableClose: false, panelClass: 'material-modal'}"
(dismiss)="sharelinkModal = false">
<ng-template sbModalContent>
<app-share-link [shareLink]="shareLink" [telemetryShareData]="telemetryShareData">
</app-share-link>
</ng-template>
</app-modal-wrapper>
</div>
</div>
./content-player.component.scss
@use "@project-sunbird/sb-styles/assets/mixins/mixins" as *;
@use 'pages/content-header' as *;
.sb-single-resource {
width: 100%;
height: 100%;
max-width: calculateRem(896px);
margin: 0 auto;
@include respond-above(lg) {
max-width: calculateRem(960px);
}
@include respond-above(xl) {
max-width: calculateRem(1024px);
}
@include respond-above(xxxl) {
max-width: calculateRem(1088px);
}
}
.cc-player {
&__btn-back {
z-index: 100;
}
}
.content-header {
min-height: calculateRem(80px);
background-color: var(--gray-0);
box-shadow: 0 0 calculateRem(10px) 0 rgba(var(--rc-rgba-black), 0.25);
z-index: 99;
&__info {
max-height: calculateRem(48px);
overflow-y: auto;
}
}
@include respond-below(sm) {
.ui.container.sb-toc-view-container {
margin-left: 0px !important;
margin-right: 0px !important;
}
}
.content-player-landscape {
position: absolute;
}
.header-block {
display: none !important;
}