import { Location } from '@angular/common';
import { Component, Input, NgZone, OnInit } from '@angular/core';
import { MimeType, RouterLinks, EventTopics } from '@app/app/app.constant';
import { TelemetryGeneratorService } from '@app/services/telemetry-generator.service';
import { CommonUtilService } from '@app/services/common-util.service';
import { ComingSoonMessageService } from '@app/services/coming-soon-message.service';
import { PopoverController } from '@ionic/angular';
import { Events } from '@app/util/events';
import { SbGenericPopoverComponent } from '@app/app/components/popups/sb-generic-popover/sb-generic-popover.component';
import { Content, TelemetryObject, Rollup, ContentStateResponse } from 'sunbird-sdk';
import { Router, NavigationExtras } from '@angular/router';
import { TextbookTocService } from '@app/app/collection-detail-etb/textbook-toc-service';
import {
Environment,
InteractSubtype,
InteractType,
PageId
} from '@app/services/telemetry-constants';
import { ContentUtil } from '@app/util/content-util';
import { AddActivityToGroup } from '../../my-groups/group.interface';
import { NavigationService } from '@app/services/navigation-handler.service';
import { CsPrimaryCategory } from '@project-sunbird/client-services/services/content';
@Component({
selector: 'app-collection-child',
templateUrl: './collection-child.component.html',
styleUrls: ['./collection-child.component.scss'],
})
export class CollectionChildComponent implements OnInit {
cardData: any;
parentId: any;
// isTextbookTocPage: Boolean = false;
@Input() childData: Content;
@Input() index: any;
@Input() depth: any;
@Input() corRelationList: any;
@Input() isDepthChild: any;
@Input() breadCrumb: any;
@Input() defaultAppIcon: string;
@Input() localImage: string;
@Input() activeMimeTypeFilter: any;
@Input() rootUnitId: any;
@Input() isTextbookTocPage: boolean;
@Input() bookID: string;
@Input() isEnrolled: boolean;
@Input() fromCourseToc: boolean;
@Input() isBatchNotStarted: boolean;
@Input() updatedCourseCardData: boolean;
@Input() stckyUnitTitle: string;
@Input() stckyindex: string;
@Input() latestParentName: string;
@Input() latestParentNodes: any;
@Input() batch: any;
@Input() renderLevel: number;
@Input() contentStatusData: ContentStateResponse;
@Input() addActivityToGroupData: AddActivityToGroup;
public telemetryObject: TelemetryObject;
public objRollup: Rollup;
collectionChildIcon: any;
sameHierarchy: boolean;
assessemtnAlert: HTMLIonPopoverElement;
get isContentCompleted(): boolean {
if (this.contentStatusData && this.isEnrolled) {
return !!this.contentStatusData.contentList.find(c => c.contentId === this.childData.identifier
&& c.status === 2);
}
return false;
}
constructor(
private zone: NgZone,
private commonUtilService: CommonUtilService,
private popoverCtrl: PopoverController,
private comingSoonMessageService: ComingSoonMessageService,
private router: Router,
private textbookTocService: TextbookTocService,
private telemetryService: TelemetryGeneratorService,
private location: Location,
private events: Events,
private navService: NavigationService
) { }
ngOnInit(): void {
this.collectionChildIcon = ContentUtil.getAppIcon(this.childData.contentData.appIcon, this.childData.basePath,
this.commonUtilService.networkInfo.isNetworkAvailable);
if (this.latestParentName) {
this.checkHierarchy();
}
this.telemetryObject = ContentUtil.getTelemetryObject(this.childData);
}
private checkHierarchy() {
if (this.childData.hierarchyInfo && this.latestParentNodes[this.stckyindex].hierarchyInfo &&
this.childData.hierarchyInfo.length === this.latestParentNodes[this.stckyindex].hierarchyInfo.length) {
for (let i = 0; i < this.childData.hierarchyInfo.length; i++) {
if (this.childData.hierarchyInfo[i]['identifier'] === this.latestParentNodes[this.stckyindex].hierarchyInfo[i]['identifier']) {
this.sameHierarchy = true;
if (this.latestParentName === this.childData.contentData.name) {
this.events.publish(EventTopics.TOC_COLLECTION_CHILD_ID, { id: this.childData.identifier });
}
} else {
this.sameHierarchy = false;
break;
}
}
} else {
this.sameHierarchy = false;
}
}
setContentId(id: string, collection?) {
if (this.router.url.indexOf(RouterLinks.TEXTBOOK_TOC) !== -1) {
const values = {
unitClicked: id
};
this.telemetryService.generateInteractTelemetry(
InteractType.TOUCH,
InteractSubtype.SUBUNIT_CLICKED,
Environment.HOME,
PageId.TEXTBOOK_TOC,
this.telemetryObject,
values,
this.objRollup,
this.corRelationList
);
this.textbookTocService.setTextbookIds({ rootUnitId: this.rootUnitId, contentId: id, unit: collection, content: collection });
this.location.back();
}
}
navigateToDetailsPage(content: Content, depth) {
if (this.router.url.indexOf(RouterLinks.TEXTBOOK_TOC) !== -1) {
const values = {
contentClicked: content.identifier
};
this.telemetryService.generateInteractTelemetry(
InteractType.TOUCH,
InteractSubtype.CONTENT_CLICKED,
Environment.HOME,
PageId.TEXTBOOK_TOC, this.telemetryObject,
values,
this.objRollup, this.corRelationList
);
this.textbookTocService.setTextbookIds({ rootUnitId: this.rootUnitId, contentId: content.identifier });
this.location.back();
} else if (!this.isEnrolled && this.router.url.indexOf(RouterLinks.ENROLLED_COURSE_DETAILS) !== -1) {
this.events.publish('courseToc:content-clicked', { isBatchNotStarted: this.isBatchNotStarted, isEnrolled: this.isEnrolled });
} else if (this.isEnrolled && this.isBatchNotStarted && this.router.url.indexOf(RouterLinks.ENROLLED_COURSE_DETAILS) !== -1) {
this.events.publish('courseToc:content-clicked', { isBatchNotStarted: this.isBatchNotStarted, isEnrolled: this.isEnrolled });
} else {
const values = {
contentClicked: content.identifier
};
this.zone.run(async () => {
if(ContentUtil.isTrackable(content)) {
this.isDepthChild = true;
const collectionDetailsParams: NavigationExtras = {
state: {
content,
depth,
corRelation: this.corRelationList,
breadCrumb: this.breadCrumb
}
};
this.navService.navigateToCollection(collectionDetailsParams.state);
}
else{
const goToContentDetails = () => {
this.textbookTocService.setTextbookIds({ rootUnitId: this.rootUnitId, contentId: content.identifier });
this.telemetryService.generateInteractTelemetry(
InteractType.TOUCH,
InteractSubtype.CONTENT_CLICKED,
Environment.HOME,
PageId.COLLECTION_DETAIL, this.telemetryObject,
values, this.objRollup, this.corRelationList
);
const contentDetailsParams: NavigationExtras = {
state: {
isChildContent: true,
content,
depth,
course: this.updatedCourseCardData || undefined,
corRelation: this.corRelationList,
breadCrumb: this.breadCrumb,
...this.addActivityToGroupData
}
};
this.navService.navigateToContent(contentDetailsParams.state);
};
if (content.primaryCategory === CsPrimaryCategory.COURSE_ASSESSMENT.toLowerCase()
&& this.batch && this.batch.status === 2) {
this.assessemtnAlert = await this.popoverCtrl.create({
component: SbGenericPopoverComponent,
componentProps: {
sbPopoverHeading: this.commonUtilService.translateMessage(content['status'] ? 'REDO_ASSESSMENT' : 'START_ASSESSMENT'),
sbPopoverMainTitle: this.commonUtilService.translateMessage(content['status'] ?
'TRAINING_ENDED_REDO_ASSESSMENT' : 'TRAINING_ENDED_START_ASSESSMENT'),
actionsButtons: [
{
btntext: this.commonUtilService.translateMessage('SKIP'),
btnClass: 'sb-btn sb-btn-sm sb-btn-outline-info'
}, {
btntext: this.commonUtilService.translateMessage(content['status'] ? 'REDO' : 'START'),
btnClass: 'popover-color'
}
],
showHeader: true,
icon: null
},
cssClass: 'sb-popover sb-dw-delete-popover',
showBackdrop: false,
backdropDismiss: false,
animated: true
});
await this.assessemtnAlert.present();
const { data } = await this.assessemtnAlert.onDidDismiss();
if (data && data.isLeftButtonClicked === false) {
goToContentDetails();
}
} else {
goToContentDetails();
}
}
});
}
}
async showComingSoonPopup(childData: any) {
const message = await this.comingSoonMessageService.getComingSoonMessage(childData);
if (childData.contentData.mimeType === MimeType.COLLECTION && !childData.children) {
const popover = await this.popoverCtrl.create({
component: SbGenericPopoverComponent,
componentProps: {
sbPopoverHeading: this.commonUtilService.translateMessage('CONTENT_COMMING_SOON'),
sbPopoverMainTitle: message ? this.commonUtilService.translateMessage(message) :
this.commonUtilService.translateMessage('CONTENT_IS_BEEING_ADDED', { content_name: childData.contentData.name }),
actionsButtons: [
{
btntext: this.commonUtilService.translateMessage('OKAY'),
btnClass: 'popover-color'
}
],
},
cssClass: 'sb-popover warning',
});
await popover.present();
}
}
hasMimeType(activeMimeType: string[], mimeType: string, content): boolean {
if (!activeMimeType) {
return true;
} else {
if (activeMimeType.indexOf('all') > -1) {
return true;
}
return !!activeMimeType.find(m => m === mimeType);
}
}
getMediaIcon(content: Content) {
const mimeType = content.mimeType;
if (content.contentData.primaryCategory === CsPrimaryCategory.COURSE_ASSESSMENT) {
return './assets/imgs/selfassess.svg';
} else if (mimeType) {
if (MimeType.DOCS.indexOf(mimeType) !== -1) {
return './assets/imgs/doc.svg';
} else if (MimeType.VIDEO.indexOf(mimeType) !== -1) {
return './assets/imgs/play.svg';
} else {
return './assets/imgs/touch.svg';
}
} else {
return './assets/imgs/touch.svg';
}
}
playContent(content: Content) {
this.events.publish(EventTopics.CONTENT_TO_PLAY, { content });
}
}
<div>
<ng-container *ngIf="childData | hasMimeType: activeMimeTypeFilter : isTextbookTocPage">
<div [ngClass]="{'unit-hierachy sb-topic-item': !isTextbookTocPage, 'sub-unit': !isTextbookTocPage}"
(click)="!fromCourseToc && setContentId(childData.identifier, childData)" [id]="childData.identifier"
*ngIf="childData?.contentData?.mimeType === 'application/vnd.ekstep.content-collection' && childData?.children && !isTextbookTocPage">
{{childData?.contentData?.name}}
</div>
<div
[ngClass]="{'row sb-textbook-toc px-16': isTextbookTocPage, 'sb-highlighted-row' : (latestParentName === childData?.contentData?.name && sameHierarchy)}"
(click)="!fromCourseToc && setContentId(childData.identifier, childData)" [id]="childData.identifier"
*ngIf="childData?.contentData?.mimeType === 'application/vnd.ekstep.content-collection' && childData?.children && isTextbookTocPage">
<div class="pull-left px-16">
{{childData?.contentData?.name}}
</div>
</div>
</ng-container>
<div [id]="childData.identifier" [ngClass]="{'etb-topic-item': !isTextbookTocPage && !fromCourseToc, 'row sb-topic-item': !stckyUnitTitle, 'sb-highlighted-row' : (latestParentName === childData?.contentData?.name) ,
'row sb-topic-item': (stckyUnitTitle !== childData?.contentData?.name)}" class="sticky-header-title-box"
[attr.data-text]="childData.contentData.name" [attr.data-render-level]="renderLevel"
*ngIf="!isTextbookTocPage && childData?.contentData?.mimeType !== 'application/vnd.ekstep.content-collection' && hasMimeType(activeMimeTypeFilter, childData?.contentData?.mimeType, childData)"
(click)="navigateToDetailsPage(childData, depth + '.' + (i + 1))">
<div class="sb-ftue-design etb-card-item" *ngIf="!fromCourseToc && !isTextbookTocPage">
<ng-container *ngIf="!isTextbookTocPage">
<div class="etb-card-item" [ngClass]="{'sb-accordian-grey-text': !commonUtilService.networkInfo.isNetworkAvailable && !childData?.isAvailableLocally,
'sb-play-selected':childData?.isAvailableLocally,'sb-play-unselected':!childData?.isAvailableLocally}">
<div class="etb-card-item-content">
<div class="image-position">
<img class="content-icon" alt="content-logo" aria-hidden="true"
[src]="commonUtilService.convertFileSrc(localImage) || commonUtilService.convertFileSrc(collectionChildIcon) ||
commonUtilService.convertFileSrc(childData?.contentData?.appIcon) || defaultAppIcon">
<span class="icon-position" *ngIf="childData?.isAvailableLocally">
<ion-icon class="sb-checkmark-icon" name="checkmark-circle"></ion-icon>
</span>
</div>
<span class="content-name">{{childData?.contentData?.name}}</span>
</div>
<div class="etb-card-item-play-container">
<ion-button class="play-button" shape="round" fill="outline" size="small"
(click)="$event.stopPropagation(); $event.preventDefault(); playContent(childData)">
<img style="display: inline-block; width: 1rem" role="button" src="./assets/imgs/play.svg" alt="play">
<span class="content-playbutton">{{'PLAY' | translate}}</span>
</ion-button>
</div>
</div>
</ng-container>
<ng-container *ngIf="fromCourseToc">
<div class="clearfix" [ngClass]="{'sb-accordian-grey-text': !commonUtilService.networkInfo.isNetworkAvailable && !childData?.isAvailableLocally,
'sb-play-selected':childData?.isAvailableLocally,'sb-play-unselected':!childData?.isAvailableLocally}">
<div class="pull-left">
{{childData?.contentData?.name}}
<span *ngIf="childData?.isAvailableLocally">
<ion-icon class="sb-checkmark-icon" name="checkmark-circle"></ion-icon>
</span>
</div>
<div class="pull-right">
<img class="content-icon" alt=""
[src]="commonUtilService.convertFileSrc(localImage) || commonUtilService.convertFileSrc(collectionChildIcon) || commonUtilService.convertFileSrc(childData?.contentData?.appIcon) || defaultAppIcon">
</div>
</div>
</ng-container>
</div>
<!-- only for QR CODE SCanner-->
<div class="sb-ftue-design" *ngIf="!fromCourseToc && isTextbookTocPage">
<div class="clearfix" class="sb-blue-text">
<div class="pull-left px-16">
{{childData?.contentData?.name}}
</div>
</div>
</div>
<!-- only for course toc -->
<div class="sb-ftue-design sb-ftue-design-course-toc" *ngIf="fromCourseToc">
<div class="clearfix" [ngClass]="{'sb-accordian-grey-text': !commonUtilService.networkInfo.isNetworkAvailable && !childData?.isAvailableLocally,
'sb-play-selected':childData?.isAvailableLocally,'sb-play-unselected':!childData?.isAvailableLocally}">
<div class="pull-left">
<span class="content-type-container">
<img [src]="getMediaIcon(childData)" alt="">
</span>
{{childData?.contentData?.name}}
</div>
<div class="pull-right done-pt-8" *ngIf="isContentCompleted">
<!--'DONE' text doesnot need translation-->
<span class="done">Done</span>
</div>
</div>
</div>
</div>
<div class="row sb-topic-item"(click)="showComingSoonPopup(childData)"
*ngIf="isTextbookTocPage && childData?.contentData?.mimeType === 'application/vnd.ekstep.content-collection' && !childData?.children">
<div class="sb-accordian-grey-text">{{childData?.contentData?.name}}</div>
<ion-icon name="alert" class="grey-icon mt-4"></ion-icon>
</div>
<ng-container *ngIf="!(childData?.contentData?.trackable?.enabled === 'Yes')">
<div *ngFor="let firstChildren of childData?.children; let j = index;"
[ngClass]="{'sb-collection-child-ftue': isTextbookTocPage}">
<app-collection-child [renderLevel]="renderLevel + 1" [childData]="firstChildren" [breadCrumb]="breadCrumb"
[activeMimeTypeFilter]="activeMimeTypeFilter" [rootUnitId]="rootUnitId" [isTextbookTocPage]="isTextbookTocPage"
[bookID]="bookID" [isEnrolled]="isEnrolled" [fromCourseToc]="fromCourseToc"
[isBatchNotStarted]="isBatchNotStarted" [stckyUnitTitle]="stckyUnitTitle" [stckyindex]="stckyindex"
[latestParentName]="latestParentName" [latestParentNodes]="latestParentNodes"
[contentStatusData]="contentStatusData" [updatedCourseCardData]="updatedCourseCardData" [batch]="batch"
[addActivityToGroupData]="addActivityToGroupData">
</app-collection-child>
</div>
</ng-container>
</div>
@import "src/assets/styles/base/_variables.scss";
@import "src/assets/styles/_custom-mixins.scss";
@import "src/assets/styles/_variables.scss";
:host {
.separator-line {
height: 0.063rem;
opacity: 0.36;
background-color: map-get($colors, dark_gray);
width: 100%;
}
.pull-right{
float: right !important;
}
.P10{
padding: 10px;
}
.play-icon
{
color : map-get($colors, vivid_green);
font-size: 1.875rem;
}
.checkmark-icon
{
color : map-get($colors, vivid_green);
font-size: 1.125rem;
margin-left: 5px;
}
.font-grey-text
{
color : map-get($colors, dark_gray);
}
.grey-icon-span
{
position: relative;
top : 8px;
}
.grey-icon
{
color : map-get($colors, dark_gray);
font-size: 1.125rem;
}
.ml8{
// migration-TODO
// @include margin (null, null, null, 8px);
}
.mtb-8{
margin-top: 8px;
margin-bottom: 8px;
}
.sb-topic-item{
@include padding($base-block-space * 1);
display: flex;
}
.sb-topics-container .sb-topic-container.sb-topics-1child {
.sb-separator-line {
@include margin(null, $base-block-space * 1);
}
}
.content-icon{
width: 2.375rem;
height: 2.375rem;
border: 0.5px solid map-get($colors, medium_light_gray);
background-color: map-get($colors, medium_gray);
display: inline-block;
}
.content-name {
padding-left: 1em;
color: map-get($colors, black);
}
.sb-checkmark-icon{
color : $secondary-200;
font-size: ($font-size-base + 0.25);
@include margin(null,null,null,($base-block-space * .5));
vertical-align: middle;
}
.clearfix {
@include clearfix;
}
.sb-collection-child-ftue{
padding-left: 8px;
}
.sb-bold-blue{
font-weight: bolder;
color: $blue;
padding: 8px;
}
.sb-blue-text{
color: $blue;
}
.sb-highlighted-row{
@include padding($base-block-space * 1);
display: flex;
background-color: lightblue;
}
.sb-textbook-toc{
@include padding($base-block-space * 1);
display: flex;
color: $blue;
@include clearfix;
}
}
.done-pt-8 {
padding-top: 8px !important;
}
.content-playbutton {
padding-left: 4px;
color: $blue;
}
.play-button{
--border-color: #{$blue};
--border-width: 0.063rem;
text-transform: none;
height: 3rem;
}
.image-position{
display: inline-block;
position: relative;
.icon-position {
position: absolute;
top: -0.5rem;
right: -0.5rem;
}
}
.sub-unit {
padding-left: 16px !important;
}