src/app/view-more-activity/view-more-activity.component.ts
OnInit
selector | app-view-more-activity |
styleUrls | ./view-more-activity.component.scss |
templateUrl | ./view-more-activity.component.html |
constructor(contentService: ContentService, eventBusService: EventsBusService, courseService: CourseService, preferences: SharedPreferences, events: Events, ngZone: NgZone, courseUtilService: CourseUtilService, commonUtilService: CommonUtilService, telemetryGeneratorService: TelemetryGeneratorService, headerService: AppHeaderService, route: ActivatedRoute, router: Router, location: Location, platform: Platform, zone: NgZone, appGlobalService: AppGlobalService, popoverCtrl: PopoverController, navService: NavigationService)
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameters :
|
course | |
Type : any
|
|
env | |
Type : string
|
|
index | |
Type : number
|
|
layoutName | |
Type : string
|
|
Contains layout name
|
onProfile | |
Type : boolean
|
|
Default value : false
|
|
pageName | |
Type : string
|
|
sectionName | |
Type : string
|
|
cancelDownload |
cancelDownload()
|
Returns :
void
|
Async checkRetiredOpenBatch |
checkRetiredOpenBatch(content: any, layoutName?: string, payload?: any)
|
Returns :
any
|
Private generateImpressionEvent |
generateImpressionEvent()
|
Returns :
void
|
Private generateLogEvent | ||||
generateLogEvent(searchResult)
|
||||
Parameters :
Returns :
void
|
getContentDetails | ||||
getContentDetails(content)
|
||||
Parameters :
Returns :
void
|
getContentImg | ||||
getContentImg(content)
|
||||
Parameters :
Returns :
any
|
getEnrolledCourse |
getEnrolledCourse()
|
Get enrolled courses
Returns :
void
|
getEnrolledCourses | ||||||||
getEnrolledCourses(returnRefreshedCourses: boolean)
|
||||||||
Parameters :
Returns :
void
|
handleBackButton |
handleBackButton()
|
Returns :
void
|
importContent | ||||||
importContent(identifiers, isChild)
|
||||||
Parameters :
Returns :
void
|
ionViewWillEnter |
ionViewWillEnter()
|
Ionic default life cycle hook
Returns :
void
|
ionViewWillLeave |
ionViewWillLeave()
|
Ionic life cycle hook
Returns :
void
|
loadMore |
loadMore()
|
Load more result
Returns :
void
|
Async mapper |
mapper()
|
Mapper to call api based on page.Layout name
Returns :
any
|
Private Async navigateToBatchListPopup | |||||||||||||||
navigateToBatchListPopup(content: any, layoutName?: string, retiredBatches?: any, payload?: any)
|
|||||||||||||||
Parameters :
Returns :
any
|
navigateToDetailPage | ||||||
navigateToDetailPage(content: any)
|
||||||
Parameters :
Returns :
boolean
|
Private Async navigateToDetailsPage | |||||||||
navigateToDetailsPage(content: any, layoutName)
|
|||||||||
Parameters :
Returns :
any
|
ngOnInit |
ngOnInit()
|
Angular life cycle hooks
Returns :
void
|
openCourseDetails | ||||||
openCourseDetails(course, index)
|
||||||
Parameters :
Returns :
void
|
Async search |
search()
|
Search content
Returns :
any
|
showDisabled | ||||
showDisabled(resource)
|
||||
Parameters :
Returns :
boolean
|
subscribeSdkEvent |
subscribeSdkEvent()
|
Returns :
void
|
subscribeUtilityEvents |
subscribeUtilityEvents()
|
Returns :
void
|
audience |
Type : any
|
backButtonFunc |
Type : Subscription
|
Flag to switch between view-more-card in view |
defaultImg |
Type : string
|
didViewLoad |
Type : boolean
|
downloadPercentage |
Type : number
|
Default value : 0
|
downloadsOnlyToggle |
Default value : false
|
value for downloads only toggle button, may have true/false |
enrolledCourses |
Type : any
|
Private eventSubscription |
Type : Subscription
|
guestUser |
Type : any
|
headerTitle |
Type : string
|
identifier |
Type : string
|
isLoading |
Default value : false
|
isLoadMore |
Default value : false
|
loader |
Type : any
|
loadMoreBtn |
Default value : true
|
Flag to show / hide button |
objId |
objType |
objVer |
offset |
Type : number
|
Default value : 0
|
pageType |
Type : string
|
Default value : 'library'
|
Public platform |
Type : Platform
|
queuedIdentifiers |
Type : Array<any>
|
Default value : []
|
requestParams |
Type : any
|
resumeContentData |
Type : any
|
searchLimit |
Type : number
|
Default value : 10
|
searchList |
Type : any
|
searchQuery |
Type : any
|
showLoader |
Type : any
|
showOverlay |
Default value : false
|
source |
Type : string
|
Default value : ''
|
tabBarElement |
Type : any
|
Contains tab bar element ref |
title |
Type : any
|
totalCount |
Type : number
|
uid |
Type : any
|
userId |
Type : any
|
import { Location } from '@angular/common';
import { Component, Inject, Input, NgZone, OnInit } from '@angular/core';
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
import { BatchConstants, ContentCard, PreferenceKey, RouterLinks, ViewMore } from '@app/app/app.constant';
import { AppGlobalService } from '@app/services/app-global-service.service';
import { AppHeaderService } from '@app/services/app-header.service';
import { CommonUtilService } from '@app/services/common-util.service';
import { CourseUtilService } from '@app/services/course-util.service';
import { NavigationService } from '@app/services/navigation-handler.service';
import {
CorReleationDataType, Environment,
ImpressionType,
InteractSubtype,
InteractType,
PageId
} from '@app/services/telemetry-constants';
import { TelemetryGeneratorService } from '@app/services/telemetry-generator.service';
import { ContentUtil } from '@app/util/content-util';
import { Platform, PopoverController } from '@ionic/angular';
import { Events } from '@app/util/events';
import { Subscription } from 'rxjs';
import {
Batch, Content,
ContentEventType,
ContentImportRequest,
ContentImportResponse,
ContentImportStatus,
ContentSearchCriteria,
ContentSearchResult,
ContentService,
CorrelationData, Course,
CourseBatchesRequest, CourseBatchStatus, CourseEnrollmentType, CourseService,
DownloadEventType,
DownloadProgress,
EventsBusEvent,
EventsBusService,
FetchEnrolledCourseRequest, LogLevel, SearchType,
SharedPreferences,
SortOrder
} from 'sunbird-sdk';
import { EnrollmentDetailsComponent } from '../components/enrollment-details/enrollment-details.component';
@Component({
selector: 'app-view-more-activity',
templateUrl: './view-more-activity.component.html',
styleUrls: ['./view-more-activity.component.scss'],
})
export class ViewMoreActivityComponent implements OnInit {
searchQuery: any;
title: any;
searchList: any;
showLoader: any;
/**
* Contains tab bar element ref
*/
tabBarElement: any;
/**
* Flag to show / hide button
*/
loadMoreBtn = true;
/**
* value for downloads only toggle button, may have true/false
*/
downloadsOnlyToggle = false;
offset = 0;
searchLimit = 10;
totalCount: number;
isLoadMore = false;
/**
* Flag to switch between view-more-card in view
*/
backButtonFunc: Subscription;
headerTitle: string;
pageType = 'library';
source = '';
queuedIdentifiers: Array<any> = [];
downloadPercentage = 0;
showOverlay = false;
resumeContentData: any;
uid: any;
audience: any;
defaultImg: string;
private eventSubscription: Subscription;
enrolledCourses: any;
guestUser: any;
userId: any;
requestParams: any;
@Input() course: any;
/**
* Contains layout name
*
* @example layoutName = In-progress / popular
*/
@Input() layoutName: string;
@Input() pageName: string;
@Input() onProfile = false;
@Input() index: number;
@Input() sectionName: string;
@Input() env: string;
identifier: string;
didViewLoad: boolean;
objId;
objType;
objVer;
loader: any;
isLoading = false;
constructor(
@Inject('CONTENT_SERVICE') private contentService: ContentService,
@Inject('EVENTS_BUS_SERVICE') private eventBusService: EventsBusService,
@Inject('COURSE_SERVICE') private courseService: CourseService,
@Inject('SHARED_PREFERENCES') private preferences: SharedPreferences,
private events: Events,
private ngZone: NgZone,
private courseUtilService: CourseUtilService,
private commonUtilService: CommonUtilService,
private telemetryGeneratorService: TelemetryGeneratorService,
private headerService: AppHeaderService,
private route: ActivatedRoute,
private router: Router,
private location: Location,
public platform: Platform,
private zone: NgZone,
private appGlobalService: AppGlobalService,
private popoverCtrl: PopoverController,
private navService: NavigationService
) {
this.route.queryParams.subscribe(params => {
if (this.router.getCurrentNavigation().extras.state) {
console.log('params from state : ', this.router.getCurrentNavigation().extras.state);
this.uid = this.router.getCurrentNavigation().extras.state.uid;
this.title = this.router.getCurrentNavigation().extras.state.headerTitle;
this.userId = this.router.getCurrentNavigation().extras.state.userId;
this.pageName = this.router.getCurrentNavigation().extras.state.pageName;
this.guestUser = this.router.getCurrentNavigation().extras.state.guestUser;
this.searchQuery = this.router.getCurrentNavigation().extras.state.requestParams;
this.audience = this.router.getCurrentNavigation().extras.state.audience;
this.enrolledCourses = this.router.getCurrentNavigation().extras.state.enrolledCourses;
if (this.router.getCurrentNavigation().extras.state.sectionName) {
this.sectionName = this.router.getCurrentNavigation().extras.state.sectionName;
}
if (this.headerTitle !== this.title) {
this.offset = 0;
this.loadMoreBtn = true;
this.mapper();
}
}
});
this.defaultImg = this.commonUtilService.convertFileSrc('assets/imgs/ic_launcher.png');
this.subscribeUtilityEvents();
}
/**
* Angular life cycle hooks
*/
ngOnInit() {
this.tabBarElement = document.querySelector('.tabbar.show-tabbar');
if (this.tabBarElement) {
this.tabBarElement.style.display = 'none';
}
}
/**
* Ionic default life cycle hook
*/
ionViewWillEnter(): void {
this.zone.run(() => {
this.headerService.showHeaderWithBackButton();
if (this.tabBarElement) {
this.tabBarElement.style.display = 'none';
}
this.handleBackButton();
});
}
subscribeUtilityEvents() {
this.events.subscribe('viewMore:Courseresume', (data) => {
this.resumeContentData = data.content;
this.getContentDetails(data.content);
});
}
handleBackButton() {
this.backButtonFunc = this.platform.backButton.subscribeWithPriority(10, () => {
this.location.back();
this.backButtonFunc.unsubscribe();
});
}
/**
* Search content
*/
async search() {
this.isLoading = true;
const selectedLanguage = await this.preferences.getString(PreferenceKey.SELECTED_LANGUAGE_CODE).toPromise();
const searchCriteria: ContentSearchCriteria = {
searchType: SearchType.FILTER,
languageCode: selectedLanguage
};
this.searchQuery.request['searchType'] = SearchType.FILTER;
this.searchQuery.request['offset'] = this.offset;
this.contentService.searchContent(searchCriteria, this.searchQuery).toPromise()
.then((data: ContentSearchResult) => {
this.ngZone.run(() => {
if (data && data.contentDataList) {
this.loadMoreBtn = data.contentDataList.length >= this.searchLimit;
if (this.isLoadMore) {
data.contentDataList.forEach((value) => {
this.searchList.push(value);
});
} else {
this.searchList = data.contentDataList;
}
} else {
this.loadMoreBtn = false;
}
this.isLoading = false;
});
this.generateImpressionEvent();
this.generateLogEvent(data);
})
.catch(() => {
console.error('Error: while fetching view more content');
this.isLoading = false;
});
}
/**
* Load more result
*/
loadMore() {
this.isLoadMore = true;
this.offset = this.offset + this.searchLimit;
if (!this.commonUtilService.networkInfo.isNetworkAvailable) {
this.commonUtilService.showToast(this.commonUtilService.translateMessage('NO_INTERNET_TITLE'));
} else {
this.mapper();
}
}
/**
* Mapper to call api based on page.Layout name
*/
async mapper() {
const pageName = this.pageName;
switch (pageName) {
case ViewMore.PAGE_COURSE_ENROLLED:
this.pageType = 'enrolledCourse';
this.loadMoreBtn = false;
this.getEnrolledCourse();
break;
case ViewMore.PAGE_COURSE_POPULAR:
this.pageType = 'popularCourses';
this.search();
break;
case ViewMore.PAGE_TV_PROGRAMS:
this.pageType = 'tvPrograms';
this.search();
break;
default:
this.search();
}
console.log('search List =>', this.searchList);
}
/**
* Get enrolled courses
*/
getEnrolledCourse() {
this.isLoading = true;
this.pageType = 'enrolledCourse';
const option = {
userId: this.userId,
returnFreshCourses: true
};
this.courseService.getEnrolledCourses(option).toPromise()
.then((data: Course[]) => {
if (data) {
this.searchList = data;
this.loadMoreBtn = false;
for (const course of data) {
course.completionPercentage = course.completionPercentage || 0;
}
}
this.isLoading = false;
})
.catch((error: any) => {
console.error('error while loading enrolled courses', error);
this.isLoading = false;
});
}
getContentDetails(content) {
const identifier = content.contentId || content.identifier;
this.contentService.getContentDetails({ contentId: identifier, objectType: content.objectType }).toPromise()
.then((data: Content) => {
if (Boolean(data.isAvailableLocally)) {
const contentDetailsParams: NavigationExtras = {
state: {
content: { identifier: content.lastReadContentId },
depth: '1',
contentState: {
batchId: content.batchId ? content.batchId : '',
courseId: identifier
},
isResumedCourse: true,
isChildContent: true,
resumedCourseCardData: this.resumeContentData
}
};
this.router.navigate([RouterLinks.COLLECTION_DETAILS], contentDetailsParams);
} else {
this.subscribeSdkEvent();
this.showOverlay = true;
this.importContent([identifier], false);
}
})
.catch((error: any) => {
console.log(error);
});
}
importContent(identifiers, isChild) {
this.queuedIdentifiers.length = 0;
const option: ContentImportRequest = {
contentImportArray: this.courseUtilService.getImportContentRequestBody(identifiers, isChild),
contentStatusArray: [],
fields: ['appIcon', 'name', 'subject', 'size', 'gradeLevel']
};
this.contentService.importContent(option).toPromise()
.then((data: ContentImportResponse[]) => {
this.ngZone.run(() => {
if (data && data.length) {
data.forEach((value) => {
if (value.status === ContentImportStatus.ENQUEUED_FOR_DOWNLOAD) {
this.queuedIdentifiers.push(value.identifier);
}
});
if (this.queuedIdentifiers.length === 0) {
this.showOverlay = false;
this.downloadPercentage = 0;
this.commonUtilService.showToast('ERROR_CONTENT_NOT_AVAILABLE');
}
}
});
})
.catch(() => {
this.ngZone.run(() => {
this.showOverlay = false;
this.commonUtilService.showToast('ERROR_CONTENT_NOT_AVAILABLE');
});
});
}
subscribeSdkEvent() {
this.eventSubscription = this.eventBusService.events().subscribe((event: EventsBusEvent) => {
this.ngZone.run(() => {
if (event.type === DownloadEventType.PROGRESS) {
const downloadEvent = event as DownloadProgress;
this.downloadPercentage = downloadEvent.payload.progress === -1 ? 0 : downloadEvent.payload.progress;
}
if (event.payload && event.type === ContentEventType.IMPORT_COMPLETED && this.downloadPercentage === 100) {
this.showOverlay = false;
const contentDetailsParams: NavigationExtras = {
state: {
content: { identifier: this.resumeContentData.lastReadContentId },
depth: '1',
contentState: {
batchId: this.resumeContentData.batchId ? this.resumeContentData.batchId : '',
courseId: this.resumeContentData.contentId || this.resumeContentData.identifier
},
isResumedCourse: true,
isChildContent: true,
resumedCourseCardData: this.resumeContentData
}
};
this.router.navigate([RouterLinks.COLLECTION_DETAILS], contentDetailsParams);
}
});
}) as any;
}
cancelDownload() {
this.ngZone.run(() => {
this.contentService.cancelDownload(this.resumeContentData.contentId || this.resumeContentData.identifier)
.toPromise().then(() => {
this.showOverlay = false;
}).catch(() => {
this.showOverlay = false;
});
});
}
showDisabled(resource) {
return !resource.isAvailableLocally && !this.commonUtilService.networkInfo.isNetworkAvailable;
}
/**
* Ionic life cycle hook
*/
ionViewWillLeave() {
this.ngZone.run(() => {
if (this.eventSubscription) {
this.eventSubscription.unsubscribe();
}
if (this.tabBarElement) {
this.tabBarElement.style.display = 'flex';
}
this.isLoadMore = false;
this.showOverlay = false;
this.backButtonFunc.unsubscribe();
});
}
private generateImpressionEvent() {
this.telemetryGeneratorService.generateImpressionTelemetry(
ImpressionType.SEARCH, '',
PageId.VIEW_MORE,
Environment.HOME, '', '', '');
}
private generateLogEvent(searchResult) {
if (searchResult != null) {
const contentArray: Array<any> = searchResult.contentDataList;
const params = new Array<any>();
const paramsMap = new Map();
paramsMap['SearchResults'] = contentArray.length;
paramsMap['SearchCriteria'] = searchResult.request;
params.push(paramsMap);
this.telemetryGeneratorService.generateLogEvent(LogLevel.INFO,
PageId.VIEW_MORE,
Environment.HOME,
ImpressionType.SEARCH, params);
}
}
navigateToDetailPage(content: any): boolean {
if (!content.isAvailableLocally && !this.commonUtilService.networkInfo.isNetworkAvailable) {
return false;
}
const values = new Map();
values['sectionName'] = this.sectionName;
values['positionClicked'] = this.index;
this.telemetryGeneratorService.generateInteractTelemetry(InteractType.TOUCH,
InteractSubtype.CONTENT_CLICKED,
this.env,
PageId.VIEW_MORE,
ContentUtil.getTelemetryObject(content),
values);
this.navService.navigateToDetailPage(content, { content });
}
getContentImg(content) {
const img = this.commonUtilService.getContentImg(content);
return img;
}
openCourseDetails(course, index) {
this.index = index;
const payload = {
guestUser: this.guestUser,
enrolledCourses: this.enrolledCourses
};
this.checkRetiredOpenBatch(course, this.pageType, payload);
}
async checkRetiredOpenBatch(content: any, layoutName?: string, payload?: any) {
this.loader = await this.commonUtilService.getLoader();
await this.loader.present();
let anyOpenBatch = false;
const enrolledCourses = payload.enrolledCourses || [];
let retiredBatches: Array<any> = [];
if (layoutName !== ContentCard.LAYOUT_INPROGRESS) {
retiredBatches = enrolledCourses.filter((element) => {
if (element.contentId === content.identifier && element.batch.status === 1 && element.cProgress !== 100) {
anyOpenBatch = true;
content.batch = element.batch;
}
if (element.contentId === content.identifier && element.batch.status === 2 && element.cProgress !== 100) {
return element;
}
});
}
if (anyOpenBatch || !retiredBatches.length) {
// open the batch directly
this.navigateToDetailsPage(content, layoutName);
} else if (retiredBatches.length) {
this.navigateToBatchListPopup(content, layoutName, retiredBatches, payload);
}
await this.loader.dismiss();
}
private async navigateToBatchListPopup(content: any, layoutName?: string, retiredBatches?: any, payload?: any) {
const ongoingBatches = [];
const courseBatchesRequest: CourseBatchesRequest = {
filters: {
courseId: layoutName === ContentCard.LAYOUT_INPROGRESS ? content.contentId : content.identifier,
enrollmentType: CourseEnrollmentType.OPEN,
status: [CourseBatchStatus.IN_PROGRESS]
},
sort_by: { createdDate: SortOrder.DESC },
fields: BatchConstants.REQUIRED_FIELDS
};
const reqvalues = new Map();
reqvalues['enrollReq'] = courseBatchesRequest;
if (this.commonUtilService.networkInfo.isNetworkAvailable) {
if (!payload.guestUser) {
this.loader = await this.commonUtilService.getLoader();
await this.loader.present();
this.courseService.getCourseBatches(courseBatchesRequest).toPromise()
.then((res: Batch[]) => {
this.zone.run(async () => {
const batches = res;
if (batches.length) {
batches.forEach((batch, key) => {
if (batch.status === 1) {
ongoingBatches.push(batch);
}
});
this.telemetryGeneratorService.generateInteractTelemetry(InteractType.TOUCH,
'showing-enrolled-ongoing-batch-popup',
Environment.HOME,
PageId.CONTENT_DETAIL, undefined,
reqvalues);
await this.loader.dismiss();
const popover = await this.popoverCtrl.create({
component: EnrollmentDetailsComponent,
componentProps: {
upcommingBatches: [],
ongoingBatches,
retiredBatches,
content
},
cssClass: 'enrollement-popover'
});
await popover.present();
const { data } = await popover.onDidDismiss();
if (data && data.isEnrolled) {
this.getEnrolledCourses();
}
} else {
await this.loader.dismiss();
this.navigateToDetailsPage(content, layoutName);
this.commonUtilService.showToast('NO_BATCHES_AVAILABLE');
}
});
})
.catch((error: any) => {
console.log('error while fetching course batches ==>', error);
});
} else {
this.router.navigate([RouterLinks.COURSE_BATCHES]);
}
} else {
this.commonUtilService.showToast('ERROR_NO_INTERNET_MESSAGE');
}
}
private async navigateToDetailsPage(content: any, layoutName) {
const identifier = content.contentId || content.identifier;
const corRelationList: Array<CorrelationData> = [{
id: this.sectionName,
type: CorReleationDataType.SECTION
}, {
id: identifier || '',
type: CorReleationDataType.ROOT_ID
}];
const values = new Map();
values['sectionName'] = this.sectionName;
values['positionClicked'] = this.index;
this.telemetryGeneratorService.generateInteractTelemetry(InteractType.TOUCH,
InteractSubtype.CONTENT_CLICKED,
this.env,
PageId.VIEW_MORE,
ContentUtil.getTelemetryObject(content),
values,
ContentUtil.generateRollUp(undefined, identifier),
this.commonUtilService.deDupe(corRelationList, 'type'));
this.zone.run(async () => {
if (layoutName === 'enrolledCourse') {
this.navService.navigateToTrackableCollection({ content });
} else {
this.navService.navigateToDetailPage(
content,
{ content }
);
}
});
}
getEnrolledCourses(returnRefreshedCourses: boolean = false): void {
const option: FetchEnrolledCourseRequest = {
userId: this.userId,
returnFreshCourses: returnRefreshedCourses
};
this.courseService.getEnrolledCourses(option).toPromise()
.then((enrolledCourses) => {
if (enrolledCourses) {
this.zone.run(() => {
this.enrolledCourses = enrolledCourses;
if (this.enrolledCourses.length > 0) {
const courseList: Array<Course> = [];
for (const course of this.enrolledCourses) {
course.completionPercentage = course.completionPercentage || 0;
courseList.push(course);
}
this.appGlobalService.setEnrolledCourseList(courseList);
}
this.showLoader = false;
});
}
}, (err) => {
this.showLoader = false;
});
}
}
<ion-content overflow-scroll="true" [ngClass]="{'ui-container': !platform.is('ios')}">
<div class="ui-container" *ngIf="platform.is('ios')"></div>
<div class="ui-content">
<div class="empty-search-result ion-text-center ion-padding-top" *ngIf="!showLoader && searchList && searchList.length === 0">
{{ 'EMPTY_SEARCH_RESULTS' | translate }}
</div>
<div>
<div class="view-more-course-bg">
<p class="title" role="heading" aria-level="1" *ngIf="pageType === 'enrolledCourse'">{{'COURSES_IN_PROGRESS' | translate}}</p>
<p class="title" role="heading" aria-level="1" *ngIf="pageType === 'popularCourses' || pageType === 'tvPrograms'">{{title}}</p>
<p *ngIf="searchList && searchList.length" class="count-text">
{{'SHOWING_ITEMS' | translate:{'%s': searchList.length} }}</p>
<ng-container *ngIf="!isLoading">
<div *ngFor="let item of searchList; let i = index" class="mb-8">
<sb-my-course-card *ngIf="pageType === 'enrolledCourse'" [course]="item" [section]="null"
[cardImg]="getContentImg(item)" (click)="openCourseDetails(item, i)" [hideProgress]="true">
</sb-my-course-card>
<sb-course-card *ngIf="pageType === 'popularCourses'" [course]="item" [section]="null"
[cardImg]="getContentImg(item)" (click)="openCourseDetails(item, i)"></sb-course-card>
<sb-library-card *ngIf="pageType === 'tvPrograms'" [isOffline]="!commonUtilService.networkInfo.isNetworkAvailable" [content]="item"
[type]="'mobile_textbook'" (cardClick)="navigateToDetailPage(item)" [isLoading]="isLoading"
[cardImg]="item?.appIcon || defaultAppIcon">
</sb-library-card>
</div>
</ng-container>
<ng-container *ngIf="isLoading">
<div *ngFor="let item of [0,1,2,3,4,5,6,7,8,9,10,11,12,13]" class="mb-8 mt-8">
<sb-my-course-card *ngIf="pageType === 'enrolledCourse'" [isLoading]="isLoading">
</sb-my-course-card>
<sb-course-card *ngIf="pageType === 'popularCourses'" [isLoading]="isLoading"></sb-course-card>
<sb-library-card *ngIf="pageType === 'tvPrograms'" [isOffline]="!commonUtilService.networkInfo.isNetworkAvailable" [content]="item"
[type]="'mobile_textbook'" (cardClick)="navigateToDetailPage(item)" [isLoading]="isLoading"
[cardImg]="item?.appIcon || defaultAppIcon">
</sb-library-card>
</div>
</ng-container>
</div>
</div>
<div class="px-5">
<ion-button expand="block" class="custom-btn-txt-transform-none" *ngIf="searchList && searchList.length && loadMoreBtn" (click)="loadMore();">
{{ 'FRMELEMNTS_BTN_VIEW_MORE' | translate }}
</ion-button>
</div>
</div>
</ion-content>
<ion-backdrop class="loading-backdrop ion-text-center" *ngIf="showOverlay">
<div class="backdrop-container">
<span *ngIf="downloadPercentage !== 100">
<ion-label>{{ 'LOADING_CONTENT' | translate }} {{ downloadPercentage ? (downloadPercentage) : '0' }} %</ion-label>
<app-pb-horizontal [progress]="downloadPercentage" isOnBoardCard="false"></app-pb-horizontal>
</span>
<ion-label *ngIf="downloadPercentage === 100">{{ 'LOADING_CONTENT' | translate }}</ion-label>
</div>
<div class="backdrop-footer" *ngIf="downloadPercentage !== 100">
<ion-button size="small" (click)="cancelDownload()">{{'CANCEL' | translate}}</ion-button>
</div>
</ion-backdrop>
./view-more-activity.component.scss
@import "src/assets/styles/variables";
@import "src/assets/styles/_custom-mixins";
@import "src/assets/styles/fonts";
@import "src/assets/styles/_variables.scss";
:host {
button {
border-radius: 5px !important;
}
.empty-search-result {
font-size: 1.2rem;
}
.loading-backdrop {
.backdrop-container {
width: 100%;
padding: 16px;
text-align: center;
position: absolute;
top: 50%;
margin-top: -50px;
}
.backdrop-footer {
position: absolute;
width: 100%;
bottom: 0;
padding-bottom: 16px;
}
background-color: map-get($colors, white);
height: 100%;
z-index: 1000;
opacity: 1 !important;
}
.downloads-only {
background: map-get($colors, white_f8);
@include margin(-16px, -16px, 16px, -16px);
@include padding(0, 16px);
}
.sb-view-all-container {
width: 100%;
.sb-view-all-items {
background-color: $primary-color;
height: ($base-block-space * 10);
width: 100%;
position: relative;
display: flex;
align-items: center;
@include padding(0, ($base-block-space * 2));
.sb-view-all-title {
color: $white-color;
.page-heading {
font-size: $font-size-base + 0.125;
font-weight: bold;
line-height: 1.375rem;
}
.page-info {
display: block;
font-size: $font-size-base - 0.125;
line-height: 0.938rem;
}
}
.sb-card-scroll-container {
overflow-x: auto;
padding: 0 0 8px 0;
}
}
}
.view-more-course-bg {
background: linear-gradient(#008840, #008840 100px, white 100px, white 100%);
padding: 8px;
.title {
color: map-get($colors, white);
font-family: "Noto Sans", sans-serif;
font-size: 1rem;
font-weight: bold;
margin: 12px 0 0;
}
.count-text {
color: map-get($colors, white_fa);
font-family: "Noto Sans", sans-serif;
font-size: 0.75rem;
margin: 0 0 12px;
}
sb-my-course-card, my-course-card {
margin-bottom: 8px;
border-radius: 2px;
box-shadow: 0 2px 7px 0 rgba(0,0,0,0.16)
}
}
}