src/app/modules/public/module/offline/components/library/library.component.ts
OnInit
OnDestroy
selector | app-library |
styleUrls | ./library.component.scss |
templateUrl | ./library.component.html |
constructor(activatedRoute: ActivatedRoute, router: Router, utilService: UtilService, toasterService: ToasterService, configService: ConfigService, resourceService: ResourceService, publicPlayerService: PublicPlayerService, searchService: SearchService, connectionService: ConnectionService, navigationHelperService: NavigationHelperService, telemetryService: TelemetryService, contentManagerService: ContentManagerService, offlineCardService: OfflineCardService, systemInfoService: SystemInfoService, layoutService: LayoutService, userService: UserService, orgDetailsService: OrgDetailsService)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameters :
|
window:scroll |
window:scroll()
|
addHoverData |
addHoverData()
|
Returns :
void
|
constructSearchRequest |
constructSearchRequest()
|
Returns :
any
|
downloadContent | ||||
downloadContent(contentId)
|
||||
Parameters :
Returns :
void
|
exportContent | ||||
exportContent(contentId)
|
||||
Parameters :
Returns :
void
|
fetchContentOnParamChange |
fetchContentOnParamChange()
|
Returns :
void
|
fetchContents | ||||||
fetchContents(isFilterChange?: boolean)
|
||||||
Parameters :
Returns :
void
|
fetchCurrentPageData |
fetchCurrentPageData()
|
Returns :
void
|
Public getFilters | ||||
getFilters(filters)
|
||||
Parameters :
Returns :
void
|
getOrgDetails |
getOrgDetails()
|
Returns :
void
|
hideLoader |
hideLoader()
|
Returns :
void
|
hoverActionClicked | ||||
hoverActionClicked(event)
|
||||
Parameters :
Returns :
void
|
initLayout |
initLayout()
|
Returns :
void
|
logTelemetry | ||||||
logTelemetry(content, actionId)
|
||||||
Parameters :
Returns :
void
|
navigateToMyDownloads |
navigateToMyDownloads()
|
Returns :
void
|
ngOnDestroy |
ngOnDestroy()
|
Returns :
void
|
ngOnInit |
ngOnInit()
|
Returns :
void
|
onScroll |
onScroll()
|
Decorators :
@HostListener('window:scroll', undefined)
|
Returns :
void
|
playContent | ||||||
playContent(event: any)
|
||||||
Parameters :
Returns :
void
|
Private prepareCarouselData | ||||||||
prepareCarouselData(sections: [])
|
||||||||
Parameters :
Returns :
any
|
prepareVisits |
prepareVisits()
|
Returns :
void
|
redoLayout |
redoLayout()
|
Returns :
void
|
setTelemetryData |
setTelemetryData()
|
Returns :
void
|
updateCardData |
updateCardData()
|
Returns :
void
|
Public cardInteractCdata |
Type : any
|
Public cardInteractObject |
Type : any
|
Public carouselMasterData |
Type : Array<ICaraouselData>
|
Default value : []
|
Public channelId |
Type : string
|
Public contentData |
Type : any
|
contentDownloadStatus |
Type : object
|
Default value : {}
|
Public contentManagerService |
Type : ContentManagerService
|
contentName |
Type : string
|
currentPageData |
Public custodianOrg |
Default value : true
|
Public dataDrivenFilterEvent |
Default value : new EventEmitter()
|
Public dataDrivenFilters |
Type : any
|
Default value : {}
|
Public defaultFilters |
downloadIdentifier |
Type : string
|
facets |
FIRST_PANEL_LAYOUT |
Public formData |
Public globalSearchFacets |
Type : Array<string>
|
Public hashTagId |
Type : string
|
infoData |
Public initFilters |
Default value : false
|
isConnected |
Default value : navigator.onLine
|
isDesktopApp |
Default value : false
|
isFilterChanged |
Default value : false
|
languageDirection |
Type : string
|
Default value : 'ltr'
|
layoutConfiguration |
Type : any
|
Public layoutService |
Type : LayoutService
|
Readonly MAXIMUM_CPU_LOAD |
Type : number
|
Default value : 90
|
Readonly MINIMUM_REQUIRED_RAM |
Type : number
|
Default value : 100
|
Public modifiedFilters |
Type : any
|
Public navigationHelperService |
Type : NavigationHelperService
|
organisationId |
Type : string
|
Public pageSections |
Type : Array<ICaraouselData>
|
Default value : []
|
pageTitle |
pageTitleSrc |
Public queryParams |
Type : any
|
Public resourceService |
Type : ResourceService
|
Public router |
Type : Router
|
Public searchService |
Type : SearchService
|
SECOND_PANEL_LAYOUT |
Public sections |
Type : Array<any>
|
Default value : []
|
Public selectedFilters |
Type : any
|
showCpuLoadWarning |
Default value : false
|
showDownloadLoader |
Default value : false
|
showExportLoader |
Default value : false
|
showLoadContentModal |
Default value : false
|
Public showLoader |
Default value : true
|
showMinimumRAMWarning |
Default value : false
|
showModal |
Default value : false
|
Public showSectionLoader |
Default value : false
|
slideConfig |
Default value : this.configService.appConfig.AllDownloadsSection.slideConfig
|
Public slug |
Type : string
|
svgToDisplay |
Public telemetryImpression |
Type : IImpressionEventInput
|
Public telemetryService |
Type : TelemetryService
|
Public unsubscribe$ |
Default value : new Subject<void>()
|
Public userDetails |
Type : any
|
Default value : {}
|
Public userService |
Type : UserService
|
Public viewAllInteractEdata |
Type : IInteractEventEdata
|
import { Component, OnInit, EventEmitter, HostListener, OnDestroy } from '@angular/core';
import { Router, ActivatedRoute, NavigationStart } from '@angular/router';
import { combineLatest, Subject } from 'rxjs';
import { tap, filter, takeUntil, first, debounceTime, delay } from 'rxjs/operators';
import * as _ from 'lodash-es';
import {
OfflineCardService, ResourceService, ToasterService, ConfigService, UtilService, ICaraouselData,
NavigationHelperService, ILanguage, LayoutService, COLUMN_TYPE, ConnectionService
} from '@sunbird/shared';
import { SearchService, UserService, OrgDetailsService } from '@sunbird/core';
import { PublicPlayerService } from '@sunbird/public';
import { IInteractEventEdata, IImpressionEventInput, TelemetryService } from '@sunbird/telemetry';
import { ContentManagerService, SystemInfoService } from '../../services';
@Component({
selector: 'app-library',
templateUrl: './library.component.html',
styleUrls: ['./library.component.scss']
})
export class LibraryComponent implements OnInit, OnDestroy {
public showLoader = true;
public showSectionLoader = false;
public queryParams: any;
public hashTagId: string;
public dataDrivenFilters: any = {};
public slug: string;
organisationId: string;
public carouselMasterData: Array<ICaraouselData> = [];
public pageSections: Array<ICaraouselData> = [];
public sections: Array<any> = [];
public initFilters = false;
public userDetails: any = {};
public selectedFilters: any;
public dataDrivenFilterEvent = new EventEmitter();
public unsubscribe$ = new Subject<void>();
public modifiedFilters: any;
isConnected = navigator.onLine;
slideConfig = this.configService.appConfig.AllDownloadsSection.slideConfig;
showExportLoader = false;
showDownloadLoader = false;
contentName: string;
infoData;
languageDirection = 'ltr';
isFilterChanged = false;
showModal = false;
showLoadContentModal = false;
downloadIdentifier: string;
readonly MINIMUM_REQUIRED_RAM = 100;
readonly MAXIMUM_CPU_LOAD = 90;
showMinimumRAMWarning = false;
showCpuLoadWarning = false;
isDesktopApp = false;
contentDownloadStatus = {};
/* Telemetry */
public viewAllInteractEdata: IInteractEventEdata;
public telemetryImpression: IImpressionEventInput;
public cardInteractObject: any;
public cardInteractCdata: any;
public contentData: any;
layoutConfiguration: any;
FIRST_PANEL_LAYOUT;
SECOND_PANEL_LAYOUT;
pageTitle;
svgToDisplay;
pageTitleSrc;
facets;
currentPageData;
public channelId: string;
public custodianOrg = true;
public defaultFilters;
public formData;
public globalSearchFacets: Array<string>;
@HostListener('window:scroll', []) onScroll(): void {
if ((window.innerHeight + window.scrollY) >= (document.body.offsetHeight * 2 / 3)
&& this.pageSections.length < this.carouselMasterData.length) {
this.pageSections.push(this.carouselMasterData[this.pageSections.length]);
this.addHoverData();
}
}
constructor(
private activatedRoute: ActivatedRoute,
public router: Router,
private utilService: UtilService,
private toasterService: ToasterService,
private configService: ConfigService,
public resourceService: ResourceService,
private publicPlayerService: PublicPlayerService,
public searchService: SearchService,
private connectionService: ConnectionService,
public navigationHelperService: NavigationHelperService,
public telemetryService: TelemetryService,
public contentManagerService: ContentManagerService,
private offlineCardService: OfflineCardService,
private systemInfoService: SystemInfoService,
public layoutService: LayoutService,
public userService: UserService,
private orgDetailsService: OrgDetailsService
) {
}
redoLayout() {
if (this.layoutConfiguration != null) {
this.FIRST_PANEL_LAYOUT = this.layoutService.redoLayoutCSS(0, this.layoutConfiguration, COLUMN_TYPE.threeToNine, true);
this.SECOND_PANEL_LAYOUT = this.layoutService.redoLayoutCSS(1, this.layoutConfiguration, COLUMN_TYPE.threeToNine, true);
} else {
this.FIRST_PANEL_LAYOUT = this.layoutService.redoLayoutCSS(0, null, COLUMN_TYPE.fullLayout);
this.SECOND_PANEL_LAYOUT = this.layoutService.redoLayoutCSS(1, null, COLUMN_TYPE.fullLayout);
}
}
initLayout() {
this.layoutConfiguration = this.layoutService.initlayoutConfig();
this.redoLayout();
this.layoutService.switchableLayout().
pipe(takeUntil(this.unsubscribe$)).subscribe(layoutConfig => {
if (layoutConfig != null) {
this.layoutConfiguration = layoutConfig.layout;
}
this.redoLayout();
});
}
fetchCurrentPageData() {
this.searchService.getContentTypes(true).pipe(takeUntil(this.unsubscribe$)).subscribe(formData => {
this.currentPageData = _.find(formData, (o) => o.title === 'frmelmnts.lbl.desktop.mylibrary');
const { contentType, title, theme: { imageName = null } = {} } = this.currentPageData;
this.pageTitle = _.get(this.resourceService, title);
this.pageTitleSrc = _.get(this.resourceService, 'RESOURCE_CONSUMPTION_ROOT') + title;
this.formData = formData;
this.svgToDisplay = imageName;
this.globalSearchFacets = _.get(this.currentPageData, 'search.facets');
this.globalSearchFacets = [
'se_boards',
'se_gradeLevels',
'se_subjects',
'se_mediums',
'primaryCategory',
'mimeType'
];
this.getOrgDetails();
}, error => {
this.toasterService.error(this.resourceService.frmelmnts.lbl.fetchingContentFailed);
this.navigationHelperService.goBack();
});
}
getOrgDetails() {
this.orgDetailsService.getOrgDetails(this.userService.slug).pipe(
tap((orgDetails: any) => {
this.hashTagId = orgDetails.hashTagId;
this.initFilters = true;
return this.dataDrivenFilterEvent;
}), first()
).subscribe((filters: any) => {
this.dataDrivenFilters = filters;
this.fetchContentOnParamChange();
},
error => {
this.router.navigate(['']);
}
);
}
ngOnInit() {
this.isDesktopApp = this.utilService.isDesktopApp;
this.activatedRoute.queryParams.pipe(takeUntil(this.unsubscribe$)).subscribe(queryParams => {
this.queryParams = { ...queryParams };
});
this.fetchCurrentPageData();
this.initLayout();
this.setTelemetryData();
this.contentManagerService.contentDownloadStatus$.subscribe( contentDownloadStatus => {
this.contentDownloadStatus = contentDownloadStatus;
this.updateCardData();
});
this.systemInfoService.getSystemInfo().pipe(takeUntil(this.unsubscribe$)).subscribe(data => {
let { availableMemory } = data.result;
availableMemory = Math.floor(availableMemory / (1024 * 1024));
const availableCpuLoad = _.get(data.result, 'cpuLoad');
this.showCpuLoadWarning = availableCpuLoad ? Boolean(availableCpuLoad > this.MAXIMUM_CPU_LOAD) : false;
this.showMinimumRAMWarning = availableMemory ? Boolean(availableMemory < this.MINIMUM_REQUIRED_RAM) : false;
}, error => {
this.showCpuLoadWarning = false;
this.showMinimumRAMWarning = false;
});
this.connectionService.monitor()
.pipe(takeUntil(this.unsubscribe$))
.subscribe(isConnected => {
this.isConnected = isConnected;
});
this.contentManagerService.completeEvent
.pipe(takeUntil(this.unsubscribe$))
.subscribe((data) => {
const url = this.router.url.split('?');
if (url[0] === '/mydownloads') {
this.fetchContents(false);
}
});
this.router.events
.pipe(filter((event) => event instanceof NavigationStart), takeUntil(this.unsubscribe$))
.subscribe(x => { this.prepareVisits(); });
this.utilService.languageChange
.pipe(takeUntil(this.unsubscribe$))
.subscribe((language: ILanguage) => {
this.languageDirection = language.dir;
});
this.utilService.clearSearchQuery();
}
fetchContentOnParamChange() {
combineLatest(this.activatedRoute.params, this.activatedRoute.queryParams)
.pipe(debounceTime(5),
delay(10),
tap(data => this.setTelemetryData()),
takeUntil(this.unsubscribe$)
).subscribe(() => {
this.showLoader = true;
this.fetchContents();
});
}
ngOnDestroy() {
this.unsubscribe$.next();
this.unsubscribe$.complete();
}
public getFilters(filters) {
const filterData = filters && filters.filters || {};
if (filterData.channel && this.facets) {
const channelIds = [];
const facetsData = _.find(this.facets, { 'name': 'channel' });
_.forEach(filterData.channel, (value, index) => {
const data = _.find(facetsData.values, { 'identifier': value });
if (data) {
channelIds.push(data.name);
}
});
if (channelIds && Array.isArray(channelIds) && channelIds.length > 0) {
filterData.channel = channelIds;
}
}
this.selectedFilters = filterData;
const defaultFilters = _.reduce(filters, (collector: any, element) => {
if (element.code === 'board') {
collector.board = _.get(_.orderBy(element.range, ['index'], ['asc']), '[0].name') || '';
}
return collector;
}, {});
this.dataDrivenFilterEvent.emit(defaultFilters);
this.carouselMasterData = [];
}
constructSearchRequest() {
const selectedMediaType = _.isArray(_.get(this.queryParams, 'mediaType')) ? _.get(this.queryParams, 'mediaType')[0] :
_.get(this.queryParams, 'mediaType');
const mimeType = _.find(_.get(this.currentPageData, 'search.filters.mimeType'), (o) => {
return o.name === (selectedMediaType || 'all');
});
const pageType = _.get(this.queryParams, 'pageTitle');
const filters: any = _.omit(this.queryParams, ['key', 'sort_by', 'sortType', 'appliedFilters', 'softConstraints', 'selectedTab', 'mediaType', 'contentType', 'board', 'medium', 'gradeLevel', 'subject']);
if (!filters.channel) {
filters.channel = this.hashTagId;
}
filters.mimeType = _.get(mimeType, 'values');
_.forEach(this.formData, (form, key) => {
const pageTitle = _.get(this.resourceService, form.title);
if (pageTitle && pageType && (pageTitle === pageType)) {
filters.contentType = _.get(form, 'search.filters.contentType');
}
});
const softConstraints = _.get(this.activatedRoute.snapshot, 'data.softConstraints') || {};
if (this.queryParams.key) {
delete softConstraints['board'];
}
const option: any = {
filters: _.omitBy(filters || {}, value => _.isArray(value) ? (!_.get(value, 'length') ? true : false) : false),
fields: _.get(this.currentPageData, 'search.fields'),
query: this.queryParams.key,
softConstraints: softConstraints,
facets: this.globalSearchFacets,
params: this.configService.appConfig.ExplorePage.contentApiQueryParams || {}
};
if (this.queryParams.softConstraints) {
try {
option.softConstraints = JSON.parse(this.queryParams.softConstraints);
} catch {
}
}
return option;
}
fetchContents(isFilterChange?: boolean) {
const shouldGetAllDownloads = !(isFilterChange);
const option = this.constructSearchRequest();
this.searchService.contentSearch(option).subscribe(searchRes => {
if (searchRes) {
const facets = this.searchService.updateFacetsData(_.get(searchRes, 'result.facets'));
this.facets = facets.filter(facet => facet.values.length > 0);
const filteredContents = _.omit(_.groupBy(searchRes['result'].content, 'subject'), ['undefined']);
const otherContents = _.filter(searchRes['result'].content, (content) => !content.subject );
// Check for multiple subjects
for (const [key, value] of Object.entries(filteredContents)) {
const isMultipleSubjects = key.split(',').length > 1;
if (isMultipleSubjects) {
const subjects = key.split(',');
subjects.forEach((subject) => {
if (filteredContents[subject]) {
filteredContents[subject] = _.uniqBy(filteredContents[subject].concat(value), 'identifier');
} else {
filteredContents[subject] = value;
}
});
delete filteredContents[key];
}
}
if (!shouldGetAllDownloads && this.sections[0]) {
this.sections.splice(1, this.sections.length);
} else {
this.sections = [];
}
const contents = []; // to sort the contents/textbooks other than downloads
for (const section in filteredContents) {
if (section) {
contents.push({
name: section,
contents: filteredContents[section].sort((a, b) => a.name.localeCompare(b.name))
});
}
}
// should not affect the download contents order(should be top)
contents.sort((a, b) => a.name.localeCompare(b.name));
contents.push({
name: this.resourceService.frmelmnts.lbl.other,
contents: otherContents.sort((a, b) => a.name.localeCompare(b.name))
});
this.sections.push(...contents);
this.carouselMasterData = this.prepareCarouselData(this.sections);
this.hideLoader();
if (!this.carouselMasterData.length) {
return; // no page section
}
this.pageSections = _.cloneDeep(this.carouselMasterData);
this.resourceService.languageSelected$.pipe(takeUntil(this.unsubscribe$)).subscribe(item => {
this.addHoverData();
this.facets = this.searchService.updateFacetsData(this.facets);
});
} else {
this.hideLoader();
this.carouselMasterData = [];
this.pageSections = [];
this.toasterService.error(this.resourceService.messages.fmsg.m0004);
}
});
}
hideLoader() {
this.showLoader = false;
this.showSectionLoader = false;
}
addHoverData() {
_.each(this.pageSections, (pageSection) => {
_.forEach(pageSection.contents, contents => {
if (this.contentDownloadStatus[contents.identifier]) {
contents['downloadStatus'] = this.contentDownloadStatus[contents.identifier];
}
});
this.pageSections[pageSection] = this.utilService.addHoverData(pageSection.contents, false);
});
}
private prepareCarouselData(sections = []) {
const { constantData, metaData, dynamicFields } = this.configService.appConfig.ExplorePage;
const carouselData = _.reduce(sections, (collector, element) => {
const contents = _.get(element, 'contents') || [];
element.contents = this.utilService.getDataForCard(contents, constantData, dynamicFields, metaData);
if (element.contents && element.contents.length) {
element.contents.forEach((item) => {
item.cardImg = item.cardImg || item.courseLogoUrl || 'assets/images/book.png';
});
collector.push(element);
}
return collector;
}, []);
return carouselData;
}
setTelemetryData() {
this.telemetryImpression = {
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,
subtype: this.activatedRoute.snapshot.data.telemetry.subtype,
duration: this.navigationHelperService.getPageLoadTime()
}
};
this.viewAllInteractEdata = {
id: `view-all-button`,
type: 'click',
pageid: 'library'
};
}
prepareVisits() {
const visits = [];
_.map(this.sections, section => {
_.forEach(section.contents, (content, index) => {
visits.push({
objid: content.metaData.identifier,
objtype: content.metaData.contentType,
index: index,
section: section.name,
});
});
});
this.telemetryImpression.edata.visits = visits;
this.telemetryImpression.edata.subtype = 'pageexit';
this.telemetryImpression = Object.assign({}, this.telemetryImpression);
}
logTelemetry(content, actionId) {
const telemetryInteractObject = {
id: content.metaData.identifier || content.metaData.courseId,
type: content.metaData.contentType || 'TextBook',
ver: content.metaData.pkgVersion ? content.metaData.pkgVersion.toString() : '1.0'
};
const appTelemetryInteractData: any = {
context: {
env: _.get(this.activatedRoute, 'snapshot.root.firstChild.data.telemetry.env') ||
_.get(this.activatedRoute, 'snapshot.data.telemetry.env') ||
_.get(this.activatedRoute.snapshot.firstChild, 'children[0].data.telemetry.env')
},
edata: {
id: actionId,
type: 'click',
pageid: this.router.url.split('/')[1] || 'library'
}
};
if (telemetryInteractObject) {
if (telemetryInteractObject.ver) {
telemetryInteractObject.ver = _.isNumber(telemetryInteractObject.ver) ?
_.toString(telemetryInteractObject.ver) : telemetryInteractObject.ver;
}
appTelemetryInteractData.object = telemetryInteractObject;
}
this.telemetryService.interact(appTelemetryInteractData);
}
hoverActionClicked(event) {
event['data'] = event.content;
this.contentName = event.content.name;
this.contentData = event.data;
let telemetryButtonId: any;
switch (event.hover.type.toUpperCase()) {
case 'OPEN':
this.playContent(event);
this.logTelemetry(this.contentData, 'play-content');
break;
case 'DOWNLOAD':
this.downloadIdentifier = _.get(event, 'content.metaData.identifier');
this.showModal = this.offlineCardService.isYoutubeContent(this.contentData);
if (!this.showModal) {
this.showDownloadLoader = true;
this.downloadContent(this.downloadIdentifier);
}
telemetryButtonId = this.contentData.mimeType ===
'application/vnd.ekstep.content-collection' ? 'download-collection' : 'download-content';
this.logTelemetry(this.contentData, telemetryButtonId);
break;
case 'SAVE':
this.showExportLoader = true;
this.exportContent(_.get(event, 'content.metaData.identifier'));
telemetryButtonId = this.contentData.mimeType ===
'application/vnd.ekstep.content-collection' ? 'export-collection' : 'export-content';
this.logTelemetry(this.contentData, telemetryButtonId);
break;
}
}
playContent(event: any) {
this.publicPlayerService.playContent(event);
}
exportContent(contentId) {
this.contentManagerService.exportContent(contentId)
.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);
}
});
}
downloadContent(contentId) {
this.contentManagerService.downloadContentId = contentId;
this.contentManagerService.downloadContentData = this.contentData;
this.contentManagerService.failedContentName = this.contentName;
this.contentManagerService.startDownload({})
.pipe(takeUntil(this.unsubscribe$))
.subscribe(data => {
this.downloadIdentifier = '';
this.contentManagerService.downloadContentId = '';
this.contentManagerService.downloadContentData = {};
this.contentManagerService.failedContentName = '';
this.showDownloadLoader = false;
}, error => {
this.downloadIdentifier = '';
this.contentManagerService.downloadContentId = '';
this.contentManagerService.downloadContentData = {};
this.contentManagerService.failedContentName = '';
this.showDownloadLoader = false;
_.each(this.pageSections, (pageSection) => {
_.each(pageSection.contents, (pageData) => {
pageData['downloadStatus'] = this.resourceService.messages.stmsg.m0138;
});
});
if (!(error.error.params.err === 'LOW_DISK_SPACE')) {
this.toasterService.error(this.resourceService.messages.fmsg.m0090);
}
});
}
updateCardData() {
_.each(this.pageSections, (pageSection) => {
_.each(pageSection.contents, (pageData) => {
this.publicPlayerService.updateDownloadStatus(this.contentDownloadStatus, pageData);
});
});
this.addHoverData();
}
navigateToMyDownloads() {
this.router.navigate(['/']);
}
}
<app-landing-section [textToDisplay]="pageTitleSrc" [svgToDisplay]="svgToDisplay"
[layoutConfiguration]="layoutConfiguration"></app-landing-section>
<div [ngClass]="layoutConfiguration ? 'sbt-fluid-content-bg':''">
<div class="sb-g" [ngClass]="layoutConfiguration ? 'sb-g sbt-container sbt-page-content' : 'sb-g'"
[appTelemetryImpression]="telemetryImpression">
<div [ngClass]="FIRST_PANEL_LAYOUT">
<div class="sb-desktop-filter-section">
<div *ngIf="layoutConfiguration">
<div *ngIf="isDesktopApp">
<app-network-status></app-network-status>
<app-load-offline-content></app-load-offline-content>
<app-system-warning></app-system-warning>
</div>
</div>
<app-global-search-filter [layoutConfiguration]="layoutConfiguration" [facets]="facets" [isOpen]='true'
*ngIf="initFilters" (filterChange)="getFilters($event)">
</app-global-search-filter>
</div>
</div>
<div [ngClass]="SECOND_PANEL_LAYOUT">
<div [appTelemetryImpression]="telemetryImpression"
[ngClass]="layoutConfiguration ? 'sbt-page-content-area' : 'ui container mt-24'">
<div>
<div class="ui container relative9">
<div class="ui stackable grid m-0">
<div class="twele wide column p-0">
<div *ngIf="showLoader">
<app-loader [data]='loaderMessage'></app-loader>
</div>
<app-global-search-selected-filter [facets]="facets" [selectedFilters]="selectedFilters"
*ngIf="initFilters && facets && layoutConfiguration" (filterChange)="getFilters($event)">
</app-global-search-selected-filter>
<section *ngFor="let section of pageSections; let index=index;">
<div class="sb-desktop-library-card relative9">
<sb-library-cards-grid *ngIf="section?.name !== 'Recently Added'" [layoutConfig]="layoutConfiguration"
[type]="'infinite_card_grid_with_hover'" [title]="section?.name" [contentList]="section?.contents"
[maxCardCount]="3" (hoverActionClick)="hoverActionClicked($event)">
</sb-library-cards-grid>
</div>
</section>
<div class="twelve wide column" *ngIf="!pageSections?.length">
<app-no-result-found [title]="resourceService?.messages?.stmsg?.m0030"></app-no-result-found>
</div>
<div *ngIf="showSectionLoader">
<app-loader [data]='loaderMessage'></app-loader>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<app-load-content *ngIf="showLoadContentModal" (close)="showLoadContentModal = false"></app-load-content>
<!-- Show Modal if content has any YouTube data-->
<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)="callDownload(); showModal = !showModal; logTelemetry(contentData, 'confirm-download-content');">
{{resourceService.frmelmnts?.btn?.yes}}
</button>
<button class="sb-btn sb-btn-normal sb-btn-outline-primary" tabindex="0"
(click)="showModal = !showModal; logTelemetry(contentData, 'cancel-download-content');">
{{resourceService.frmelmnts?.btn?.cancel}}
</button>
</div>
</div>
</div>
</div>
</ng-template>
</app-modal-wrapper>
<app-loader *ngIf="showExportLoader" [data]="{loaderMessage: resourceService.frmelmnts?.lbl?.exportingContent | interpolate:'{contentName}':contentName}"> </app-loader>
<app-loader *ngIf="showDownloadLoader" [data]="{loaderMessage: resourceService.frmelmnts?.lbl?.downloadingContent | interpolate:'{contentName}':contentName}"> </app-loader>
./library.component.scss
@use "@project-sunbird/sb-styles/assets/mixins/mixins" as *;
:host {
.page {
background: rgba(var(--rc-rgba-black), 0.6);
h6 {
color: var(--gray-0);
font-weight: normal;
}
}
.page-container {
margin: calculateRem(16px) calculateRem(32px);
}
.header {
display: flex;
flex-direction: row;
margin: calculateRem(24px) 0 calculateRem(16px) 0;
align-items: center;
.title {
text-overflow: ellipsis;
overflow: hidden;
flex: 1;
height: calculateRem(24px);
color: var(--primary-color);
font-size: calculateRem(16px);
font-weight: bold;
text-transform: capitalize;
line-height: calculateRem(24px);
display: flex;
align-items: center;
}
}
.sbcardwidth {
width: calculateRem(292px) !important;
padding: 0px 0px calculateRem(4px) 0px;
}
[dir="rtl"] .sbcardwidth:first-child {
margin-right: 0px !important;
}
}
.ui.dimmer .ui.loader:before {
border-color: rgba(var(--rc-rgba-white), 0.01);
}
.ui.dimmer .ui.loader:after {
border-color: var(--primary-200) transparent transparent;
}
// sb grid template css
.sbgrid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(291.98px, 1fr));
grid-gap: 1rem;
grid-row-gap: 1.5rem;
}
/* sb-card styles getting overriden by _cards.scss */
:host ::ng-deep {
.slick-slider .slick-track {
// width: auto !important;
padding-top: 0px;
}
[dir="ltr"].slick-slider .slick-prev,
[dir="rtl"].slick-slider .slick-next {
left: calculateRem(-16px) !important;
right: auto !important;
}
[dir="rtl"].slick-slider .slick-prev,
[dir="ltr"].slick-slider .slick-next {
right: calculateRem(-8px) !important;
left: auto !important;
}
}
.sb--card:hover {
transform: none !important;
}