src/app/modules/dial-code-search/components/dial-code/dial-code.component.ts
OnInit
OnDestroy
selector | app-dial-code |
styleUrls | ./dial-code.component.scss |
templateUrl | ./dial-code.component.html |
constructor(resourceService: ResourceService, userService: UserService, coursesService: CoursesService, router: Router, activatedRoute: ActivatedRoute, searchService: SearchService, toasterService: ToasterService, configService: ConfigService, utilService: UtilService, navigationHelperService: NavigationHelperService, playerService: PlayerService, telemetryService: TelemetryService, publicPlayerService: PublicPlayerService, dialCodeService: DialCodeService, layoutService: LayoutService)
|
||||||||||||||||||||||||||||||||||||||||||||||||
Parameters :
|
window:popstate |
Arguments : '$event'
|
window:popstate(event)
|
appendItems | ||||||
appendItems(startIndex, endIndex)
|
||||||
Parameters :
Returns :
void
|
closeMobileAppPopup |
closeMobileAppPopup()
|
Returns :
void
|
Public getEvent | ||||
getEvent(event)
|
||||
Parameters :
Returns :
void
|
goBack |
goBack()
|
Returns :
any
|
Public handleCloseButton |
handleCloseButton()
|
Returns :
any
|
handleMobilePopupBanner |
handleMobilePopupBanner()
|
Returns :
void
|
initLayout |
initLayout()
|
Returns :
void
|
inview | ||||
inview(event)
|
||||
Parameters :
Returns :
void
|
logInteractEvent | |||
logInteractEvent(undefined)
|
|||
Parameters :
Returns :
void
|
logTelemetryEvents | ||||||
logTelemetryEvents(status: boolean)
|
||||||
Parameters :
Returns :
void
|
ngOnDestroy |
ngOnDestroy()
|
Returns :
void
|
ngOnInit |
ngOnInit()
|
Returns :
void
|
onPopState | ||||
onPopState(event)
|
||||
Decorators :
@HostListener('window:popstate', ['$event'])
|
||||
Parameters :
Returns :
void
|
onScrollDown |
onScrollDown()
|
Returns :
void
|
Public playCourse | |||
playCourse(undefined)
|
|||
Parameters :
Returns :
void
|
Private processDialCode | ||||
processDialCode(params)
|
||||
Parameters :
Returns :
any
|
Private processTextBook | ||||
processTextBook(params)
|
||||
Parameters :
Returns :
any
|
Public redirectToDetailsPage | ||||
redirectToDetailsPage(contentId)
|
||||
Parameters :
Returns :
void
|
redirectToDikshaApp |
redirectToDikshaApp()
|
Returns :
void
|
setTelemetryData |
setTelemetryData()
|
Returns :
void
|
updateCardData | ||||
updateCardData(downloadListdata)
|
||||
Parameters :
Returns :
void
|
Public activatedRoute |
Type : ActivatedRoute
|
Public appMobileDownloadInteractData |
Type : any
|
Public backInteractEdata |
Type : IInteractEventEdata
|
chapterName |
Type : string
|
Public closeMobilePopupInteractData |
Type : any
|
Public configService |
Type : ConfigService
|
contentName |
Type : string
|
courseList |
Type : []
|
Default value : []
|
Public coursesService |
Type : CoursesService
|
Public dialCode |
dialContentId |
Type : string
|
Public dialResultImpression |
Type : IImpressionEventInput
|
Public dialSearchSource |
Type : string
|
Private initialize |
Default value : () => {...}
|
instance |
Type : string
|
Public inviewLogs |
Type : any
|
Default value : []
|
isBrowse |
Default value : false
|
Public isRedirectToDikshaApp |
Default value : false
|
isTextbookDetailsPage |
Default value : false
|
Public itemsToDisplay |
Type : any
|
Default value : []
|
Initializing the infinite scroller |
Public itemsToLoad |
Type : number
|
Default value : 50
|
layoutConfiguration |
Type : any
|
Public layoutService |
Type : LayoutService
|
Public loaderMessage |
Type : any
|
Public navigationHelperService |
Type : NavigationHelperService
|
Public numberOfSections |
Default value : new Array(this.configService.appConfig.DIAL_CODE.PAGE_LIMIT)
|
Public numOfItemsToAddOnScroll |
Type : number
|
Default value : 20
|
Public playerService |
Type : PlayerService
|
Public publicPlayerService |
Type : PublicPlayerService
|
redirectCollectionUrl |
Type : string
|
redirectContentUrl |
Type : string
|
redirectQuestionsetUrl |
Type : string
|
Public resourceService |
Type : ResourceService
|
Public router |
Type : Router
|
Public scrollDistance |
Type : number
|
Default value : 2
|
Public searchResults |
Type : Array<any>
|
Default value : []
|
Public searchService |
Type : SearchService
|
Public selectChapterInteractEdata |
Type : IInteractEventEdata
|
Public selectChapterTelemetryCdata |
Type : Array<literal type>
|
Default value : []
|
Public selectedCourseBatches |
Type : any
|
Public showBatchInfo |
Default value : false
|
showDownloadLoader |
Default value : false
|
showExportLoader |
Default value : false
|
Public showLoader |
Default value : true
|
Public showMobilePopup |
Default value : false
|
showSelectChapter |
Default value : false
|
Public singleContentRedirect |
Type : string
|
Default value : ''
|
Public telemetryCdata |
Type : Array<literal type>
|
Default value : []
|
Public telemetryImpression |
Type : IImpressionEventInput
|
telemetryImpression |
Public telemetryService |
Type : TelemetryService
|
textbookList |
Type : []
|
Default value : []
|
Public throttle |
Type : number
|
Default value : 50
|
Public toasterService |
Type : ToasterService
|
Public unsubscribe$ |
Default value : new Subject<void>()
|
Public userService |
Type : UserService
|
Public utilService |
Type : UtilService
|
import { Component, OnInit, OnDestroy, HostListener } from '@angular/core';
import { combineLatest as observableCombineLatest, of } from 'rxjs';
import { ResourceService, ToasterService, ConfigService, UtilService, NavigationHelperService, LayoutService} from '@sunbird/shared';
import { Router, ActivatedRoute } from '@angular/router';
import { SearchService, PlayerService, CoursesService, UserService } from '@sunbird/core';
import { PublicPlayerService } from '@sunbird/public';
import * as _ from 'lodash-es';
import { IInteractEventEdata, IImpressionEventInput, TelemetryService } from '@sunbird/telemetry';
import {mergeMap, tap, retry, catchError, map, finalize, debounceTime, takeUntil} from 'rxjs/operators';
import { Subject } from 'rxjs';
import { DialCodeService } from '../../services/dial-code/dial-code.service';
@Component({
selector: 'app-dial-code',
templateUrl: './dial-code.component.html',
styleUrls: ['./dial-code.component.scss']
})
export class DialCodeComponent implements OnInit, OnDestroy {
public inviewLogs: any = [];
/**
* telemetryImpression
*/
public telemetryImpression: IImpressionEventInput;
public dialResultImpression: IImpressionEventInput;
/**
* Initializing the infinite scroller
*/
public itemsToDisplay: any = [];
public itemsToLoad = 50;
public throttle = 50;
public numOfItemsToAddOnScroll = 20;
public scrollDistance = 2;
public dialCode;
public showLoader = true;
public loaderMessage: any;
public searchResults: Array<any> = [];
public unsubscribe$ = new Subject<void>();
public telemetryCdata: Array<{}> = [];
public backInteractEdata: IInteractEventEdata;
public selectChapterTelemetryCdata: Array<{}> = [];
public selectChapterInteractEdata: IInteractEventEdata;
public showMobilePopup = false;
public isRedirectToDikshaApp = false;
public closeMobilePopupInteractData: any;
public appMobileDownloadInteractData: any;
public dialSearchSource: string;
public showBatchInfo = false;
public selectedCourseBatches: any;
public singleContentRedirect = '';
public numberOfSections = new Array(this.configService.appConfig.DIAL_CODE.PAGE_LIMIT);
showExportLoader = false;
contentName: string;
instance: string;
redirectCollectionUrl: string;
redirectContentUrl: string;
redirectQuestionsetUrl: string;
showDownloadLoader = false;
isBrowse = false;
showSelectChapter = false;
chapterName: string;
dialContentId: string;
textbookList = [];
courseList = [];
isTextbookDetailsPage = false;
layoutConfiguration: any;
constructor(public resourceService: ResourceService, public userService: UserService,
public coursesService: CoursesService, public router: Router, public activatedRoute: ActivatedRoute,
public searchService: SearchService, public toasterService: ToasterService, public configService: ConfigService,
public utilService: UtilService, public navigationHelperService: NavigationHelperService,
public playerService: PlayerService, public telemetryService: TelemetryService,
public publicPlayerService: PublicPlayerService, private dialCodeService: DialCodeService,
public layoutService: LayoutService) {
}
ngOnInit() {
this.initLayout();
observableCombineLatest(this.activatedRoute.params, this.activatedRoute.queryParams,
(params, queryParams) => {
return { ...params, ...queryParams };
}).pipe(
debounceTime(10),
tap(this.initialize),
mergeMap(params => _.get(params, 'textbook') ? this.processTextBook(params) : this.processDialCode(params)),
).subscribe(res => {
const linkedContents = _.flatMap(_.values(res));
const { constantData, metaData, dynamicFields } = this.configService.appConfig.GetPage;
this.searchResults = this.utilService.getDataForCard(linkedContents, constantData, dynamicFields, metaData);
if (_.get(this.searchResults[0], 'contentType') === 'TextBook') {
sessionStorage.setItem('l1parent', this.searchResults[0].identifier);
}
this.appendItems(0, this.itemsToLoad);
if (this.searchResults.length === 1) {
if (_.get(this.searchResults[0], 'metaData.mimeType') === 'application/vnd.ekstep.content-collection' ||
!sessionStorage.getItem('singleContentRedirect')) {
this.singleContentRedirect = this.searchResults[0]['name'];
if (this.searchResults[0].contentType.toLowerCase() !== 'course') {
this.getEvent({
data: this.searchResults[0]
});
}
}
}
this.showLoader = false;
const telemetryInteractEdata = {
id: 'content-explode',
type: 'view',
subtype: 'post-populate'
};
if (_.get(res, 'collection.length') > 1) {
telemetryInteractEdata.id = 'content-collection';
}
if (this.searchResults.length !== 1) {
this.logInteractEvent(telemetryInteractEdata);
}
}, err => {
this.showLoader = false;
this.toasterService.error(this.resourceService.messages.fmsg.m0049);
}, () => {
this.showLoader = false;
});
}
initLayout() {
this.layoutConfiguration = this.layoutService.initlayoutConfig();
this.layoutService.switchableLayout().pipe(takeUntil(this.unsubscribe$)).subscribe(layoutConfig => {
if (layoutConfig != null) {
this.layoutConfiguration = layoutConfig.layout;
}
});
}
private initialize = (params) => {
EkTelemetry.config.batchsize = 2;
this.isBrowse = Boolean(this.router.url.includes('browse'));
this.dialSearchSource = _.get(params, 'source') || 'search';
this.isTextbookDetailsPage = !!_.get(params, 'textbook');
this.itemsToDisplay = [];
this.searchResults = [];
this.dialCode = _.get(params, 'dialCode');
this.showLoader = true;
this.instance = _.upperCase(_.get(this.resourceService, 'instance'));
this.handleMobilePopupBanner();
this.setTelemetryData();
this.inview({ inview: [] })
}
private processDialCode(params) {
return of(params).pipe(
finalize(() => {
this.logInteractEvent({
id: 'search-dial-init',
type: 'view',
subtype: 'auto',
});
}),
mergeMap(param => this.dialCodeService.searchDialCodeAssemble(_.get(param, 'dialCode'), this.isBrowse)
.pipe(
tap(value => {
this.logInteractEvent({
id: 'search-dial-success',
type: 'view',
subtype: 'auto',
});
this.logTelemetryEvents(true);
}, err => {
this.logInteractEvent({
id: 'search-dial-failed',
type: 'view',
subtype: 'auto',
});
this.logTelemetryEvents(false);
}),
retry(1),
catchError(error => {
return of({
content: [],
collections: []
});
}),
mergeMap(this.dialCodeService.filterDialSearchResults),
tap((res) => {
this.showSelectChapter = false;
})
))
);
}
private processTextBook(params) {
const textBookUnit = _.get(params, 'textbook');
const content = _.find(_.get(this.dialCodeService, 'dialCodeResult.contents'), contentObj => {
return (_.get(contentObj, 'identifier') === textBookUnit);
});
if (content) {
if (_.toLower(_.get(content, 'contentType')) === 'textbook') {
this.chapterName = _.get(content, 'name');
this.dialContentId = _.get(content, 'identifier');
this.showSelectChapter = true;
}
return this.dialCodeService.getAllPlayableContent([textBookUnit]).pipe(
map(contents => {
return { contents };
})
);
} else {
this.router.navigate(['/get/dial', _.get(this.activatedRoute, 'snapshot.params.dialCode')]);
return of([]);
}
}
onScrollDown() {
const startIndex = this.itemsToLoad;
this.itemsToLoad = this.itemsToLoad + this.numOfItemsToAddOnScroll;
this.appendItems(startIndex, this.itemsToLoad);
}
appendItems(startIndex, endIndex) {
this.itemsToDisplay.push(...this.searchResults.slice(startIndex, endIndex));
this.courseList = this.itemsToDisplay.filter(item => item.contentType.toLowerCase() === 'course');
this.textbookList = this.itemsToDisplay.filter(item => item.contentType.toLowerCase() !== 'course');
}
public playCourse({ section, data }) {
const metaData = data;
if (this.userService.loggedIn) {
this.coursesService.getEnrolledCourses().subscribe(() => {
const { onGoingBatchCount, expiredBatchCount, openBatch, inviteOnlyBatch } =
this.coursesService.findEnrolledCourses(metaData.identifier);
if (!expiredBatchCount && !onGoingBatchCount) { // go to course preview page, if no enrolled batch present
return this.playerService.playContent(metaData);
}
if (onGoingBatchCount === 1) { // play course if only one open batch is present
metaData.batchId = openBatch.ongoing.length ? openBatch.ongoing[0].batchId : inviteOnlyBatch.ongoing[0].batchId;
return this.playerService.playContent(metaData);
}
this.selectedCourseBatches = { onGoingBatchCount, expiredBatchCount, openBatch, inviteOnlyBatch, courseId: metaData.identifier };
this.showBatchInfo = true;
}, error => {
this.publicPlayerService.playContent(metaData);
});
} else {
this.publicPlayerService.playContent(metaData);
}
}
public getEvent(event) {
this.redirectCollectionUrl = 'play/collection';
this.redirectContentUrl = 'play/content';
this.redirectQuestionsetUrl = 'play/questionset';
if (event.data.metaData.mimeType === this.configService.appConfig.PLAYER_CONFIG.MIME_TYPE.collection) {
if (_.get(event, 'data.metaData.childTextbookUnit') || _.toLower(_.get(event, 'data.contentType') === 'textbook')) {
this.router.navigate([], {
relativeTo: this.activatedRoute,
queryParams: {
l1Parent: event.data.metaData.l1Parent,
textbook: _.get(event, 'data.metaData.childTextbookUnit.identifier') || _.get(event, 'data.metaData.identifier')
}
});
} else {
this.router.navigate([this.redirectCollectionUrl, event.data.metaData.identifier],
{ queryParams: { dialCode: this.dialCode, l1Parent: event.data.metaData.l1Parent } });
}
} else if (event.data.metaData.mimeType === this.configService.appConfig.PLAYER_CONFIG.MIME_TYPE.questionset) {
this.router.navigate([this.redirectQuestionsetUrl, event.data.metaData.identifier],
{ queryParams: { dialCode: this.dialCode, l1Parent: sessionStorage.getItem('l1parent') || event.data.metaData.l1Parent },
state: { 'isSingleContent': this.searchResults.length > 1 ? false : true} });
} else {
this.router.navigate([this.redirectContentUrl, event.data.metaData.identifier],
{ queryParams: { dialCode: this.dialCode, l1Parent: sessionStorage.getItem('l1parent') || event.data.metaData.l1Parent },
state: { 'isSingleContent': this.searchResults.length > 1 ? false : true} });
}
}
inview(event) {
_.forEach(event.inview, (inview, key) => {
const obj = _.find(this.inviewLogs, (o) => {
return o.objid === inview.data.metaData.identifier;
});
if (obj === undefined) {
this.inviewLogs.push({
objid: inview.data.metaData.identifier,
objtype: inview.data.metaData.contentType || 'content',
index: inview.id
});
}
});
this.telemetryImpression.edata.visits = this.inviewLogs;
this.telemetryImpression.edata.pageid = this.activatedRoute.snapshot.data.telemetry.pageid;
this.telemetryImpression.edata.subtype = 'pageexit';
this.telemetryImpression = Object.assign({}, this.telemetryImpression);
}
closeMobileAppPopup() {
if (localStorage) {
localStorage.setItem('showMobilePopUp', 'true');
}
if (!this.isRedirectToDikshaApp) {
this.telemetryService.interact(this.closeMobilePopupInteractData);
(document.querySelector('.mobile-app-popup') as HTMLElement).style.bottom = '-999px';
(document.querySelector('.mobile-popup-dimmer') as HTMLElement).style.display = 'none';
}
}
redirectToDikshaApp() {
this.isRedirectToDikshaApp = true;
this.telemetryService.interact(this.appMobileDownloadInteractData);
let applink = this.configService.appConfig.UrlLinks.downloadDikshaApp;
const utm_source = this.userService.slug ? `diksha-${this.userService.slug}` : 'diksha';
applink = `${applink}&utm_source=${utm_source}&utm_medium=${this.dialSearchSource}&utm_campaign=dial&utm_term=${this.dialCode}`;
window.location.href = applink.replace(/\s+/g, '');
}
setTelemetryData() {
if (this.dialCode) {
this.telemetryCdata = [{ 'type': 'DialCode', 'id': this.dialCode }];
}
this.closeMobilePopupInteractData = {
context: {
cdata: this.telemetryCdata,
env: this.activatedRoute.snapshot.data.telemetry.env,
},
edata: {
id: 'mobile-popup-close',
type: 'click',
pageid: 'get-dial'
}
};
this.backInteractEdata = {
id: 'dialpage-back',
type: 'click',
pageid: 'get-dial',
};
this.selectChapterInteractEdata = {
id: 'select-chapter-button',
type: 'click',
pageid: 'get-dial'
};
this.selectChapterTelemetryCdata = [
{ 'type': 'DialCode', 'id': this.dialCode },
{ 'id': 'scan:result:collection:list', 'type': 'Feature' },
{ 'id': 'SB-15628', 'type': 'Task' }];
this.appMobileDownloadInteractData = {
context: {
cdata: this.telemetryCdata,
env: this.activatedRoute.snapshot.data.telemetry.env,
},
edata: {
id: 'app-download-mobile',
type: 'click',
pageid: 'get-dial'
}
};
this.telemetryImpression = {
context: {
env: this.activatedRoute.snapshot.data.telemetry.env,
cdata: [{
type: 'DialCode',
id: this.activatedRoute.snapshot.params.dialCode
}]
},
object: {
id: this.activatedRoute.snapshot.params.dialCode,
type: 'DialCode',
ver: '1.0'
},
edata: {
type: this.activatedRoute.snapshot.data.telemetry.type,
pageid: `${this.activatedRoute.snapshot.data.telemetry.pageid}`,
uri: this.userService.slug ? '/' + this.userService.slug + this.router.url : this.router.url,
subtype: _.get(this.activatedRoute, 'snapshot.data.telemetry.subtype'),
duration: this.navigationHelperService.getPageLoadTime()
}
};
}
ngOnDestroy() {
sessionStorage.removeItem('singleContentRedirect');
EkTelemetry.config.batchsize = 10;
this.unsubscribe$.next();
this.unsubscribe$.complete();
}
handleMobilePopupBanner() {
setTimeout(() => {
if (localStorage && !localStorage.getItem('showMobilePopUp')) {
this.showMobilePopup = true;
}
}, 500);
}
updateCardData(downloadListdata) {
_.each(this.itemsToDisplay, (contents) => {
this.publicPlayerService.updateDownloadStatus(downloadListdata, contents);
});
}
logTelemetryEvents(status: boolean) {
let level = 'ERROR';
let msg = 'Search Dialcode failed';
if (status) {
level = 'SUCCESS';
msg = 'Search Dialcode was success';
}
const event = {
context: {
env: 'dialcode',
cdata: this.telemetryCdata
},
edata: {
type: 'search-dialcode',
level: level,
message: msg,
pageid: this.router.url.split('?')[0]
}
};
this.telemetryService.log(event);
}
public handleCloseButton() {
if (_.get(this.activatedRoute, 'snapshot.queryParams.textbook') && _.get(this.dialCodeService, 'dialCodeResult.count') > 1) {
return this.router.navigate(['/get/dial', _.get(this.activatedRoute, 'snapshot.params.dialCode')]);
}
const previousUrl = _.get(this.navigationHelperService.getPreviousUrl(), 'url') || '/get';
if (_.includes(previousUrl, 'play')) {
if (this.userService.loggedIn) {
this.router.navigate(['/resources']);
} else {
this.router.navigate(['/explore']);
}
}
}
goBack() {
/*istanbul ignore else */
if (_.get(this.activatedRoute, 'snapshot.queryParams.textbook') && _.get(this.dialCodeService, 'dialCodeResult.count') > 1) {
return this.router.navigate(['/get/dial', _.get(this.activatedRoute, 'snapshot.params.dialCode')]);
}
if (this.userService.loggedIn) {
this.router.navigate(['/resources']);
} else {
this.router.navigate(['/explore']);
}
}
public redirectToDetailsPage(contentId) {
if (this.userService.loggedIn) {
this.router.navigate(['/resources/play/collection', contentId], {
queryParams: { contentType: 'TextBook', 'dialCode': this.dialCode },
state: { action: 'dialcode' }
});
} else {
this.router.navigate(['/play/collection', contentId], { queryParams: { contentType: 'TextBook', 'dialCode': this.dialCode } });
}
}
logInteractEvent({ id, type, subtype }) {
const telemetry = {
context: { env: _.get(this.activatedRoute, 'snapshot.data.telemetry.env'), cdata: this.telemetryCdata },
edata: {
id,
type,
pageid: 'get-dial'
}
};
if (subtype) {
telemetry.edata['subtype'] = subtype;
}
this.telemetryService.interact(telemetry);
}
@HostListener('window:popstate', ['$event'])
onPopState(event) {
if (event && this.router.url.includes('/get/dial')) {
this.goBack();
}
}
}
<app-landing-section [noTitle]="true" [layoutConfiguration]="layoutConfiguration">
</app-landing-section>
<div [ngClass]="layoutConfiguration ? 'sbt-center-container relative9 sbt-dial-code sbt-inside-page-container':''" >
<!-- Back button -->
<div class="sb-bg-color-white sb-back-btn-panel">
<div class="ui container py-8">
<button type="button" appTelemetryInteract [telemetryInteractEdata]="backInteractEdata"
[telemetryInteractCdata]="telemetryCdata" class="sb-btn sb-btn-normal sb-btn-link
sb-btn-link-primary sb-left-icon-btn px-0" (click)="goBack()" tabindex="0">
<i class="icon-svg icon-svg--xxs icon-back mr-4" aria-hidden="true">
<svg class="icon icon-svg--primary">
<use xlink:href="./assets/images/sprite.svg#arrow-long-left"></use>
</svg>
</i> {{resourceService?.frmelmnts?.btn?.back}}
</button>
</div>
</div>
<!-- Main container -->
<div class="ui container py-24" [appTelemetryImpression]="telemetryImpression">
<div class="sb-grid" *ngIf="showLoader">
<div [id]="i" [data]=[] class="sb-grid--item" *ngFor="let i of numberOfSections">
<sb-library-card [indexToDisplay]="i" [layoutConfig]="layoutConfiguration" [type]="'portal_qrcode_flatresult'" [isLoading]="true"></sb-library-card>
</div>
</div>
<div class="dial-code-section-result">
<div class="sb-pageSection" *ngIf="!showLoader && searchResults.length > 0">
<div class="section-header">
<p>
{{resourceService?.frmelmnts?.lbl?.showingResultsForWithCount | interpolate:'{resultCount}' : searchResults.length}} "<strong>{{dialCode}}</strong>"
</p>
</div>
</div>
<div *ngIf="showSelectChapter && !showLoader && searchResults?.length > 0" class="my-24">
<button appTelemetryInteract [telemetryInteractEdata]="selectChapterInteractEdata"
[telemetryInteractCdata]="selectChapterTelemetryCdata" tabindex="0" (click)="redirectToDetailsPage(dialContentId)"
class="sb-btn sb-btn-normal sb-btn-primary sb-right-icon-btn"
type="button">{{resourceService.frmelmnts?.lbl?.selectChapter}}
<i class="icon chevron circle right" aria-hidden="true"></i></button>
<span class="ml-8 fmedium">{{resourceService.frmelmnts?.lbl?.fromTheTextBook}}
<strong>"{{chapterName}}"</strong>
</span>
</div>
</div>
<!-- START - CCD for DIAL Code search result(s) For Textbooks -->
<div [appTelemetryImpression]="dialResultImpression">
<div>
<div *ngIf="!showLoader && textbookList?.length" in-view-container (inview)="inview($event)" [throttle]="[1000]"
[trigger]="textbookList" class="twelve wide column mb-16">
<div class="header" *ngIf="!isTextbookDetailsPage">
<div class="title">
{{resourceService?.frmelmnts?.lbl?.textbooks}}
<span class="badge">{{textbookList?.length}}</span>
</div>
</div>
<div class="sb-grid mt-16">
<div [id]="i" [data]="content" class="sb-grid--item grey-background"
*ngFor="let content of textbookList;let i = index;">
<!-- START - Results page -->
<sb-library-card [indexToDisplay]="i" [layoutConfig]="layoutConfiguration" *ngIf="content.contentType.toLowerCase() !== 'course' && !isTextbookDetailsPage"
(cardClick)="getEvent($event)" (enterKey)="getEvent($event)" [content]="content" [cardImg]="content?.image || 'assets/images/book.png'"
appTelemetryInteract appContentDirection [data]="content" [type]="'qrcode_result'"
[moreInfoLabel]="resourceService?.frmelmnts?.lbl?.section"
[section]="content?.metaData?.childTextbookUnit?.name || ''"
[telemetryInteractObject]="{id:content.metaData.identifier,type:content.contentType,ver:content.metaData.pkgVersion ? content.metaData.pkgVersion.toString():'1.0'}"
[telemetryInteractEdata]="content.telemetryInteractEdata"
[telemetryInteractCdata]="[{ 'type': 'DialCode', 'id': dialCode}]">
</sb-library-card>
<!-- END - Results page -->
<!-- START - Flattened page -->
<sb-library-card [indexToDisplay]="i" [layoutConfig]="layoutConfiguration" [type]="'portal_qrcode_flatresult'" [btnlabel]="resourceService.frmelmnts?.lbl?.play"
*ngIf="content.contentType.toLowerCase() !== 'course' && !content.metaData.childTextbookUnit && isTextbookDetailsPage"
(cardClick)="getEvent($event)" (enterKey)="getEvent($event)" [content]="content" [cardImg]="content?.image || 'assets/images/book.png'"
appTelemetryInteract appContentDirection [data]="content"
[telemetryInteractObject]="{id:content.metaData.identifier,type:content.contentType,ver:content.metaData.pkgVersion ? content.metaData.pkgVersion.toString():'1.0'}"
[telemetryInteractEdata]="content.telemetryInteractEdata"
[telemetryInteractCdata]="[{ 'type': 'DialCode', 'id': dialCode}]">
</sb-library-card>
<!-- END - Flattened page -->
</div>
</div>
</div>
</div>
</div>
<!-- END - CCD for DIAL Code search result(s) -->
<div [appTelemetryImpression]="dialResultImpression">
<div class="content-grid">
<div *ngIf="!showLoader && courseList?.length" in-view-container (inview)="inview($event)" [throttle]="[1000]"
[trigger]="courseList" class="twelve wide column">
<div class="header" *ngIf="!isTextbookDetailsPage">
<div class="title">
{{resourceService?.frmelmnts?.tab?.courses}}
<span class="badge">{{courseList?.length}}</span>
</div>
</div>
<div class="sb-card-grid mt-16">
<div [id]="i" [data]="content" *ngFor="let content of courseList;let i = index;">
<sb-course-card appContentDirection [data]="content" class="sb-card-grid__item" [course]="content"
[cardImg]="content?.image || 'assets/images/book.png'" (cardClick)="playCourse($event)" [section]="null"
appTelemetryInteract [telemetryInteractCdata]="[{ 'type': 'DialCode', 'id': dialCode}]"
[telemetryInteractObject]="{id:content.metaData.identifier,type:content.contentType,ver:content.metaData.pkgVersion ? content.metaData.pkgVersion.toString():'1.0'}"
[telemetryInteractEdata]="content.telemetryInteractEdata">
</sb-course-card>
</div>
</div>
</div>
</div>
<div class="sb-placeholder">
<div *ngIf="!showLoader && !searchResults.length">
<app-comming-soon></app-comming-soon>
</div>
</div>
</div>
</div>
<div class="mobile-popup-dimmer" *ngIf="showMobilePopup" tabindex="0" (click)="closeMobileAppPopup()"
[ngClass]="{'bottom-0': showMobilePopup}">
<div class="mobile-app-popup" [ngClass]="{'bottom-0': showMobilePopup}">
<div class="download-mobile-app">
<div class="mobile-app-popup-close">
<i class="close icon" aria-hidden="true"></i>
</div>
<div class="download-mobile-app-logo p-15" tabindex="0" (click)="redirectToDikshaApp()">
<div class="mobile-circles">
<div class="big-box border-round border-r50"></div>
<div class="oval-box border-round ml-24"></div>
<div class="small-box border-round border-r50 ml-16 mr-8"></div>
<div class="small-box border-round border-r50"></div>
</div>
<label
class="d-block text-center">{{resourceService?.frmelmnts?.lbl?.downloadDikshaForMobile | interpolate:'{instance}': instance}}</label>
<a id='app-download-mobile' class="d-block pb-10 text-center app-download">
<img class="playStore-img" src="assets/images/google_playstore.png"
alt="{{resourceService?.frmelmnts?.lbl?.dikshaForMobile | interpolate:'{instance}':instance}}"
title="{{resourceService?.frmelmnts?.lbl?.dikshaForMobile | interpolate:'{instance}':instance}}">
</a>
<p class="d-block text-center py-8">{{resourceService.frmelmnts?.lbl?.getUnlimitedAccess}}
</p>
</div>
</div>
</div>
</div>
</div>
<app-batch-info *ngIf="showBatchInfo" [enrolledBatchInfo]="selectedCourseBatches" (modelClose)="showBatchInfo = false">
</app-batch-info>
./dial-code.component.scss
@use "@project-sunbird/sb-styles/assets/mixins/mixins" as *;
/*get dial code page responsive css*/
.mobile-popup-dimmer {
background: rgba(var(--rc-rgba-black), 0.5);
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: -999px;
z-index: 9998;
transition: 0.75s ease;
.mobile-app-popup {
display: none;
position: fixed;
bottom: -999px;
z-index: 9999;
left: 0;
right: 0;
transition: 0.75s ease;
.download-mobile-app {
border-radius: calculateRem(20px) calculateRem(20px) 0 0;
position: absolute;
bottom: 0 !important;
padding: calculateRem(32px) calculateRem(12px) 0 calculateRem(12px);
background: var(--gray-800);
box-shadow: 0 calculateRem(20px) calculateRem(20px) calculateRem(10px) rgba(var(--rc-rgba-black), 0.2);
max-width: calculateRem(250px);
right: 0;
left: 0;
margin: 0 auto;
transition: 0.75s ease-in-out;
.mobile-app-popup-close {
position: absolute;
top: calculateRem(-15px);
right: calculateRem(15px);
width: calculateRem(25px);
height: calculateRem(25px);
background: var(--white);
margin: 0;
border-radius: calculateRem(25px);
z-index: 9999;
text-align: center;
cursor: pointer;
.icon {
margin: 0 !important;
color: var(--gray-400);
}
}
img {
width: calculateRem(120px);
}
.download-mobile-app-logo {
background: var(--white);
color: var(--black);
border-radius: calculateRem(8px) calculateRem(8px) 0 0;
p {
font-size: calculateRem(12px);
line-height: calculateRem(16px);
}
label {
font-size: calculateRem(12px);
}
}
label {
font-weight: bold;
}
.close {
line-height: normal;
margin: 0 0 calculateRem(2px) 0 !important;
}
.mobile-circles {
position: absolute;
top: calculateRem(10px);
display: flex;
align-items: center;
margin: 0 calculateRem(20px);
}
.mobile-circles .border-round {
background: var(--gray-400);
border: none;
}
.mobile-circles .border-r50 {
border-radius: 50%;
}
.mobile-circles .big-box {
height: calculateRem(14px);
width: calculateRem(14px);
}
.mobile-circles .oval-box {
height: calculateRem(6px);
width: calculateRem(76px);
border-radius: calculateRem(3px);
margin-left: calculateRem(10px);
}
.mobile-circles .small-box {
height: calculateRem(8px);
width: calculateRem(8px);
}
}
}
}
.bottom-0 {
bottom: 0;
}
.dial-code-section-result {
align-items: center !important;
.header {
display: inline-flex;
align-items: center;
}
.header-label {
font-size: calculateRem(12px);
}
}
@media screen and (min-width: 240px) and (max-width: 767px) {
.mobile-popup-dimmer {
display: block;
.mobile-app-popup {
display: block;
.download-mobile-app {
display: block;
bottom: 0;
margin: 0 auto;
right: 0;
left: 0;
box-shadow: 0 0 calculateRem(20px) calculateRem(10px) rgba(var(--rc-rgba-black), 0.2);
height: calculateRem(185px);
p {
display: block !important;
}
.close-mobile-div {
display: flex;
}
.download-mobile-app-logo {
height: calculateRem(160px);
overflow: hidden;
}
}
}
}
}
.sb-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(252px, 1fr));
grid-gap: 1rem;
grid-row-gap: 1.5rem;
}
.section-header {
display: flex;
flex-direction: row;
align-items: center;
}
.header {
display: flex;
flex-direction: row;
margin:1rem 0 0 0;
padding: 0px 0;
align-items: center;
.title {
font-family: inherit;
text-overflow: ellipsis;
overflow: hidden;
flex: 1;
height: calculateRem(24px);
color: var(--primary-color);
font-size: calculateRem(18px);
font-weight: bold;
text-transform: capitalize;
line-height: calculateRem(26px);
display: flex;
align-items: center;
.badge {
display: inline-block;
background: var(--sbt-badge-bg);
color: var(--gray-800);
text-align: center;
padding: calculateRem(0px) calculateRem(12px);
border-radius: calculateRem(4px);
height: calculateRem(24px);
line-height: calculateRem(24px);
font-size: calculateRem(16px);
font-weight: normal;
margin-left: calculateRem(8px);
}
}
}
.sb-placeholder {
justify-content: center !important;
}