src/app/modules/dashboard/components/course-progress/course-progress.component.ts
This component shows the course progress dashboard
OnInit
OnDestroy
AfterViewInit
selector | app-course-progress |
styleUrls | ./course-progress.component.scss |
templateUrl | ./course-progress.component.html |
constructor(user: UserService, route: Router, activatedRoute: ActivatedRoute, resourceService: ResourceService, toasterService: ToasterService, telemetryService: TelemetryService, courseProgressService: CourseProgressService, paginationService: PaginationService, config: ConfigService, onDemandReportService: OnDemandReportService, formService: FormService, navigationhelperService: NavigationHelperService, usageService: UsageService)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Constructor to create injected service(s) object
Parameters :
|
assignForumData | ||||
assignForumData(routerData)
|
||||
Parameters :
Returns :
void
|
Private downloadAssessmentReport |
downloadAssessmentReport()
|
method to download assessment score reports
Returns :
any
|
Private downloadCourseReport | ||||||
downloadCourseReport(reportType: string)
|
||||||
method to download course progress reports
Parameters :
Returns :
any
|
downloadReport | ||||||
downloadReport(downloadAssessmentReport: boolean)
|
||||||
method to download assessment/course progress report
Parameters :
Returns :
void
|
generateDataForDF | ||||
generateDataForDF(batchId)
|
||||
Parameters :
Returns :
void
|
getFieldValue | ||||||
getFieldValue(array, field)
|
||||||
Parameters :
Returns :
any
|
getFormData |
getFormData()
|
Returns :
void
|
getSummaryReports |
getSummaryReports()
|
Returns :
void
|
keyup | ||||
keyup(event)
|
||||
Parameters :
Returns :
void
|
loadOndemandReports | ||||
loadOndemandReports(tabNumber)
|
||||
Load on demand reports
Parameters :
Returns :
void
|
navigate |
navigate()
|
Method to update the url with selected query params
Returns :
void
|
navigateToPage | ||||||
navigateToPage(page: number)
|
||||||
Parameters :
Returns :
undefined | void
|
ngAfterViewInit |
ngAfterViewInit()
|
Returns :
void
|
ngOnDestroy |
ngOnDestroy()
|
Returns :
void
|
ngOnInit |
ngOnInit()
|
To method subscribes the user data to get the user id. It also subscribes the activated route params to get the course id and timeperiod
Returns :
void
|
populateBatchData |
populateBatchData()
|
To method helps to get all batches related to the course. Then it helps to set flag dependeing on number of batches.
Returns :
void
|
populateCourseDashboardData | ||||||
populateCourseDashboardData(batch?: any)
|
||||||
To method fetches the dashboard data with specific batch id and timeperiod
Parameters :
Returns :
void
|
redirect |
redirect()
|
Returns :
void
|
searchBatch |
searchBatch()
|
Returns :
void
|
selectedTabChange | ||||
selectedTabChange(event)
|
||||
Parameters :
Returns :
void
|
setBatchId | ||||||
setBatchId(batch?: any)
|
||||||
To method helps to set batch id and calls the populateCourseDashboardData
Parameters :
Returns :
void
|
setCounts | ||||
setCounts(currentBatch)
|
||||
Parameters :
Returns :
void
|
setFilterDescription |
setFilterDescription()
|
To method helps to set filter description
Returns :
void
|
setInteractEventData |
setInteractEventData()
|
Returns :
void
|
setInteractEventDataForTabs | ||||
setInteractEventDataForTabs(id)
|
||||
Parameters :
Returns :
void
|
setOrder | ||||||||
setOrder(value: string)
|
||||||||
To method helps to set order of a specific field
Parameters :
Returns :
void
|
setTimePeriod | ||||||||
setTimePeriod(timePeriod: string)
|
||||||||
To method helps to set time period and calls the populateCourseDashboardData
Parameters :
Returns :
void
|
summaryReport | ||||
summaryReport(tabNumber)
|
||||
Parameters :
Returns :
void
|
Private activatedRoute |
Type : ActivatedRoute
|
To send activatedRoute.snapshot to router navigation service for redirection to parent component |
batchId |
Type : string
|
batchlist |
Type : Array<IBatchListData>
|
This variable sets the batch list data related to the given course |
Public config |
Type : ConfigService
|
To get url, app configs |
courseId |
Type : string
|
This variable sets the course id |
Public courseProgressService |
Type : CourseProgressService
|
To get user profile of logged-in user |
currentBatch |
Type : any
|
to store the current batch when updated; |
dashboarData |
Type : ICourseProgressData
|
This variable sets the dashboard result related to the given batch |
fetchForumIdReq |
Type : IForumContext
|
input data for fetchforum Ids |
fileName |
Type : string
|
filterText |
Type : string
|
This variable sets the filter description which is displayed inside the dashboard |
Public formService |
Type : FormService
|
interactObject |
Type : any
|
isDownloadReport |
Default value : false
|
Public message |
Type : string
|
Default value : 'There is no data available'
|
modelChanged |
Type : Subject<string>
|
Default value : new Subject<string>()
|
Public navigationhelperService |
Type : NavigationHelperService
|
Public onDemandReports |
Type : OnDemandReportsComponent
|
Decorators :
@ViewChild(OnDemandReportsComponent)
|
Public onDemandReportService |
Type : OnDemandReportService
|
order |
Type : string
|
This variable sets the name of the field which is to be sorted |
pageLimit |
Type : number
|
Contains page limit of inbox list |
pageNumber |
Type : number
|
Default value : 1
|
Current page number of inbox list |
pager |
Type : IPagination
|
Contains returned object of the pagination service which is needed to show the pagination on inbox view |
Private paginationService |
Type : PaginationService
|
For showing pagination on draft list |
paramSubcription |
Type : any
|
This variable helps to unsubscribe the params and queryparams |
Public progressReportUpdatedOn |
To display progress report updated date |
queryParams |
Type : any
|
This variable sets the queryparams on url |
reportTypes |
Type : []
|
Default value : []
|
Public resourceService |
Type : ResourceService
|
To call resource service which helps to use language constant |
reverse |
Default value : true
|
This variable sets the order to true or false |
route |
Type : Router
|
To navigate to other pages |
Public scoreReportUpdatedOn |
To display score report updated date |
searchText |
Type : string
|
value typed |
selectedOption |
Type : string
|
This variable sets selected batch id, if exist |
selectedTab |
Type : number
|
Default value : 2
|
showDownloadLink |
Default value : true
|
This variable helps to show the csv downloadURl |
showDownloadModal |
Default value : false
|
This variable helps to show the download modal after successful download API call |
showLoader |
Default value : true
|
This variable helps to show and hide page loader. |
showNoBatch |
Default value : false
|
This variable is set to true when the length of batch is 0. It helps to show a message div on html |
showWarningDiv |
Default value : false
|
This variable helps to show the warning div |
stateWiseReportData |
Type : []
|
Default value : []
|
subscription |
Type : Subscription
|
telemetryCdata |
Type : Array<literal type>
|
telemetryImpression |
Type : IImpressionEventInput
|
telemetryImpression object for course progress page |
Public telemetryService |
Type : TelemetryService
|
Private toasterService |
Type : ToasterService
|
To show toaster(error, success etc) after any API calls |
totalCount |
Type : Number
|
totalCount of the list |
Public unsubscribe |
Default value : new Subject<void>()
|
Variable to gather and unsubscribe all observable subscriptions in this component. |
Public user |
Type : UserService
|
To get user profile of logged-in user |
userConsent |
userDataSubscription |
Type : Subscription
|
userId |
Type : string
|
This variable sets the user id |
userRoles |
import { combineLatest, Subscription, Subject, of } from 'rxjs';
import { first, takeUntil, map, debounceTime, distinctUntilChanged, switchMap, tap } from 'rxjs/operators';
import { Component, OnInit, OnDestroy, AfterViewInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import * as _ from 'lodash-es';
import { UserService, FormService } from '@sunbird/core';
import {
ResourceService, ToasterService, ServerResponse, PaginationService, ConfigService,
NavigationHelperService, IPagination, OnDemandReportsComponent
} from '@sunbird/shared';
import { CourseProgressService, UsageService } from './../../services';
import { ICourseProgressData, IBatchListData, IForumContext } from './../../interfaces';
import { IImpressionEventInput, TelemetryService } from '@sunbird/telemetry';
import { OnDemandReportService } from './../../../shared/services/on-demand-report/on-demand-report.service';
/**
* This component shows the course progress dashboard
*/
@Component({
selector: 'app-course-progress',
templateUrl: './course-progress.component.html',
styleUrls: ['./course-progress.component.scss']
})
export class CourseProgressComponent implements OnInit, OnDestroy, AfterViewInit {
modelChanged: Subject<string> = new Subject<string>();
@ViewChild(OnDemandReportsComponent)
public onDemandReports: OnDemandReportsComponent;
/**
* Variable to gather and unsubscribe all observable subscriptions in this component.
*/
public unsubscribe = new Subject<void>();
interactObject: any;
/**
* This variable helps to show and hide page loader.
*/
showLoader = true;
/**
* This variable sets the batch list data related to the given course
*/
batchlist: Array<IBatchListData>;
/**
* This variable sets the course id
*/
courseId: string;
userDataSubscription: Subscription;
// TODO: We have to remove this & use currentBatch.id
batchId: string;
/**
* This variable sets the user id
*/
userId: string;
/**
* value typed
*/
searchText: string;
/**
* This variable sets the dashboard result related to the given batch
*/
dashboarData: ICourseProgressData;
/**
* This variable is set to true when the length of batch is 0.
* It helps to show a message div on html
*/
showNoBatch = false;
/**
* This variable helps to show the download modal after successful download API call
*/
showDownloadModal = false;
/**
* This variable sets the filter description which is displayed inside the dashboard
*/
filterText: string;
/**
* This variable sets the name of the field which is to be sorted
*/
order: string;
/**
* This variable sets the order to true or false
*/
reverse = true;
/**
* This variable sets the queryparams on url
*/
queryParams: any;
/**
* This variable sets selected batch id, if exist
*/
selectedOption: string;
/**
* This variable helps to unsubscribe the params and queryparams
*/
paramSubcription: any;
/**
* This variable helps to show the warning div
*/
showWarningDiv = false;
/**
* This variable helps to show the csv downloadURl
*/
showDownloadLink = true;
/**
* To navigate to other pages
*/
route: Router;
/**
* Contains page limit of inbox list
*/
pageLimit: number;
/**
* Current page number of inbox list
*/
pageNumber = 1;
/**
* totalCount of the list
*/
totalCount: Number;
/**
* to store the current batch when updated;
*/
currentBatch: any;
/**
* Contains returned object of the pagination service
* which is needed to show the pagination on inbox view
*/
pager: IPagination;
/**
* input data for fetchforum Ids
*/
fetchForumIdReq: IForumContext;
/**
* To send activatedRoute.snapshot to router navigation
* service for redirection to parent component
*/
private activatedRoute: ActivatedRoute;
/**
* To call resource service which helps to use language constant
*/
public resourceService: ResourceService;
/**
* To show toaster(error, success etc) after any API calls
*/
private toasterService: ToasterService;
/**
* To get user profile of logged-in user
*/
public user: UserService;
/**
* To get user profile of logged-in user
*/
public courseProgressService: CourseProgressService;
/**
* For showing pagination on draft list
*/
private paginationService: PaginationService;
/**
* To get url, app configs
*/
public config: ConfigService;
/**
* To display score report updated date
*/
public scoreReportUpdatedOn;
/**
* To display progress report updated date
*/
public progressReportUpdatedOn;
/**
* telemetryImpression object for course progress page
*/
telemetryImpression: IImpressionEventInput;
telemetryCdata: Array<{}>;
subscription: Subscription;
isDownloadReport = false;
stateWiseReportData = [];
public message = 'There is no data available';
columns = [
{ name: 'State', isSortable: true, prop: 'state', placeholder: 'Filter state' },
{ name: 'District', isSortable: true, prop: 'district', placeholder: 'Filter district' },
{ name: 'No. of Enrolment', isSortable: false, prop: 'noOfEnrollments', placeholder: 'Filter enrollment' }];
fileName: string;
userConsent;
reportTypes = [];
userRoles;
selectedTab = 2;
/**
* Constructor to create injected service(s) object
* @param {UserService} user Reference of UserService
* @param {Router} route Reference of Router
* @param {ActivatedRoute} activatedRoute Reference of ActivatedRoute
* @param {ResourceService} resourceService Reference of ResourceService
* @param {ToasterService} toasterService Reference of ToasterService
* @param {CourseProgressService} courseProgressService Reference of CourseProgressService
*/
constructor(user: UserService,
route: Router,
activatedRoute: ActivatedRoute,
resourceService: ResourceService,
toasterService: ToasterService,
public telemetryService: TelemetryService,
courseProgressService: CourseProgressService, paginationService: PaginationService,
config: ConfigService,
public onDemandReportService: OnDemandReportService,
public formService: FormService,
public navigationhelperService: NavigationHelperService, private usageService: UsageService,
) {
this.user = user;
this.route = route;
this.activatedRoute = activatedRoute;
this.resourceService = resourceService;
this.toasterService = toasterService;
this.courseProgressService = courseProgressService;
this.paginationService = paginationService;
this.config = config;
this.route.onSameUrlNavigation = 'ignore';
this.pageLimit = this.config.appConfig.DASHBOARD.PAGE_LIMIT;
}
/**
* To method helps to get all batches related to the course.
* Then it helps to set flag dependeing on number of batches.
*/
populateBatchData(): void {
this.showLoader = true;
const searchParamsCreator = {
courseId: this.courseId,
status: ['0', '1', '2'],
createdBy: this.userId
};
const searchParamsMentor = {
courseId: this.courseId,
status: ['0', '1', '2'],
mentors: [this.userId]
};
combineLatest(
this.courseProgressService.getBatches(searchParamsCreator),
this.courseProgressService.getBatches(searchParamsMentor),
).pipe(takeUntil(this.unsubscribe))
.subscribe((results) => {
this.batchlist = _.union(results[0].result.response.content, results[1].result.response.content);
this.showLoader = false;
const isBatchExist = _.find(this.batchlist, (batch) => batch.id === this.queryParams.batchIdentifier);
if (this.batchlist.length === 0) {
this.showNoBatch = true;
} else if (isBatchExist) {
this.selectedOption = this.queryParams.batchIdentifier;
this.currentBatch = isBatchExist;
this.populateCourseDashboardData(isBatchExist);
} else if (this.batchlist.length === 1 && isBatchExist === undefined) {
this.queryParams.batchIdentifier = this.batchlist[0].id;
this.selectedOption = this.batchlist[0].id;
this.currentBatch = this.batchlist[0];
this.generateDataForDF(this.currentBatch);
this.setBatchId(this.currentBatch);
this.populateCourseDashboardData(this.batchlist[0]);
} else {
this.showWarningDiv = true;
}
this.paramSubcription.unsubscribe();
}, (err) => {
this.toasterService.error(this.resourceService.messages.emsg.m0005);
this.showLoader = false;
this.showNoBatch = true;
});
}
summaryReport(tabNumber) {
this.setInteractEventDataForTabs('summary-report');
this.selectedTab = tabNumber;
this.getSummaryReports();
}
/**
* To method helps to set batch id and calls the populateCourseDashboardData
*
* @param {string} batchId batch identifier
*/
setBatchId(batch?: any): void {
this.fetchForumIdReq = null;
this.showWarningDiv = false;
this.queryParams.batchIdentifier = _.get(batch, 'value.id');
this.queryParams.pageNumber = this.pageNumber;
this.searchText = '';
this.currentBatch = _.get(batch, 'value');;
// this.currentBatch.lastUpdatedOn = dayjs(this.currentBatch.lastUpdatedOn).format('DD-MMM-YYYY hh:mm a');
this.batchId = _.get(batch, 'value.id');
this.setCounts(this.currentBatch);
this.populateCourseDashboardData(_.get(batch, 'value'));
if (this.selectedTab === 1) {
this.summaryReport(1);
} else {
this.loadOndemandReports(2);
}
}
/**
* Method to update the url with selected query params
*/
navigate(): void {
this.route.navigate([], { queryParams: this.queryParams });
}
redirect() {
this.route.navigate(['/learn/course', this.courseId]);
}
/**
* To method helps to set time period and calls the populateCourseDashboardData
*
* @param {string} timePeriod time period
*/
setTimePeriod(timePeriod: string): void {
this.queryParams.timePeriod = timePeriod;
this.populateCourseDashboardData();
}
setInteractEventDataForTabs(id) {
const telemetryObj = {
context: {
env: 'reports',
cdata: [
{id: _.get(this.currentBatch , 'courseId'), type: 'Course'},
{id: _.get(this.currentBatch , 'batchId'), type: 'Batch'}
]
},
edata: {
id: id,
type: 'click',
pageid: id
}
};
this.telemetryService.interact(telemetryObj);
}
getSummaryReports() {
if (_.get(this.currentBatch, 'collectionId') || _.get(this.currentBatch, 'courseId')) {
const request = {
'request': {
'filters': {
'collectionId': _.get(this.currentBatch, 'collectionId') || _.get(this.currentBatch, 'courseId'),
'batchId': _.get(this.currentBatch, 'batchId')
},
'groupBy': ['dist', 'state'],
'granularity': 'ALL' // data conformation
}
};
this.onDemandReportService.getSummeryReports(request).subscribe((reports: any) => {
if (reports && reports.result && !_.isEmpty(reports.result)) {
const result = _.get(reports, 'result');
const groupData = _.get(result, 'groupBy');
this.stateWiseReportData = _.map(groupData, (x) => {
return {
state: x.state,
district: x.district,
noOfEnrollments: this.getFieldValue(x.values, 'enrolment')
};
});
this.stateWiseReportData = [...this.stateWiseReportData];
const metrics = _.get(result, 'metrics');
this.currentBatch.participantCount = this.getFieldValue(metrics, 'enrolment');
this.currentBatch.completedCount = this.getFieldValue(metrics, 'complete');
this.currentBatch.lastUpdatedOn = _.get(result, 'lastUpdatedOn') || '';
}
this.generateDataForDF(this.currentBatch);
}, error => {
this.stateWiseReportData = [
{
state: 'Andhra Pradesh',
district: 'Chittoor',
noOfEnrollments: 20
},
{
state: 'Andhra Pradesh',
district: 'Vishakapatanam',
noOfEnrollments: 50
},
{
state: 'Andhra Pradesh',
district: 'Guntur',
noOfEnrollments: 70
},
{
state: 'Andhra Pradesh',
district: 'Kadapa',
noOfEnrollments: 65
},
{
state: 'Andhra Pradesh',
district: 'Nellore',
noOfEnrollments: 100
},
{
state: 'Telengana',
district: 'Hydrabad',
noOfEnrollments: 45
}
];
this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
this.generateDataForDF(this.currentBatch);
});
}
}
/**
* To method fetches the dashboard data with specific batch id and timeperiod
*/
// TODO: This function will be removed. API got deprecated.
populateCourseDashboardData(batch?: any): void {
return ;
if (!batch && this.currentBatch) {
batch = this.currentBatch;
}
this.showWarningDiv = false;
this.navigate();
this.showLoader = true;
const option: any = {
batchIdentifier: this.queryParams.batchIdentifier,
limit: this.pageLimit,
offset: (this.pageNumber - 1) * (this.pageLimit),
};
if (this.order) {
option.sortBy = this.order;
option.sortOrder = this.reverse ? 'desc' : 'asc';
}
if (this.searchText) {
option.username = this.searchText;
}
this.courseProgressService.getDashboardData(option).pipe(
takeUntil(this.unsubscribe))
.subscribe(
(apiResponse: ServerResponse) => {
if (!apiResponse.result.count && _.get(apiResponse, 'result.data.length')) {
apiResponse.result.count = _.get(apiResponse, 'result.data.length');
} else {
apiResponse.result.count = 0;
}
this.showLoader = false;
this.dashboarData = apiResponse.result;
this.showDownloadLink = apiResponse.result.showDownloadLink ? apiResponse.result.showDownloadLink : false;
this.dashboarData.count = _.get(batch, 'participantCount') || _.get(apiResponse, 'result.data.length');
this.totalCount = _.get(batch, 'participantCount') || _.get(apiResponse, 'result.data.length');
if (this.totalCount >= 10000) {
this.pager = this.paginationService.getPager(10000, this.pageNumber, this.config.appConfig.DASHBOARD.PAGE_LIMIT);
} else {
this.pager = this.paginationService.getPager(
apiResponse.result.count, this.pageNumber, this.config.appConfig.DASHBOARD.PAGE_LIMIT);
}
},
err => {
this.toasterService.error(err.error.params.errmsg);
this.showLoader = false;
}
);
}
/**
* To method helps to set order of a specific field
*
* @param {string} value Field name that is to be sorted
*/
setOrder(value: string): void {
this.order = value;
this.reverse = !this.reverse;
this.setInteractEventData();
if (this.currentBatch) {
this.populateCourseDashboardData(this.currentBatch);
}
}
/**
* method to download course progress reports
*/
private downloadCourseReport(reportType: string) {
const batchId = this.queryParams.batchIdentifier;
const url = `/courseReports/${reportType}/report-${batchId}.csv`;
return this.usageService.getData(url)
.pipe(
tap(response => {
if (_.get(response, 'responseCode') === 'OK') {
const signedUrl = _.get(response, 'result.signedUrl');
if (signedUrl) { window.open(signedUrl, '_blank'); }
} else {
this.toasterService.error(this.resourceService.messages.stmsg.m0141);
}
})
);
}
/**
* method to download assessment score reports
*/
private downloadAssessmentReport() {
const option = {
batchIdentifier: this.queryParams.batchIdentifier,
};
return this.courseProgressService.downloadDashboardData(option).pipe(
tap((apiResponse: ServerResponse) => {
let downloadUrl;
downloadUrl = _.get(apiResponse, 'result.reports.assessmentReportUrl');
if (downloadUrl) {
window.open(downloadUrl, '_blank');
} else {
this.toasterService.error(this.resourceService.messages.stmsg.m0141);
}
}));
}
/**
* To method helps to set filter description
*/
setFilterDescription(): void {
const filterDesc = {
'7d': this.resourceService.messages.imsg.m0022,
'14d': this.resourceService.messages.imsg.m0023,
'5w': this.resourceService.messages.imsg.m0024,
'fromBegining': this.resourceService.messages.imsg.m0025
};
this.filterText = filterDesc[this.queryParams.timePeriod];
}
/**
* method to download assessment/course progress report
* @param downloadAssessmentReport
*/
downloadReport(downloadAssessmentReport: boolean) {
of(downloadAssessmentReport)
.pipe(
switchMap((flag: boolean) => flag ? this.downloadCourseReport('assessment-reports') :
this.downloadCourseReport('course-progress-reports')),
takeUntil(this.unsubscribe)
)
.subscribe(res => { }, err => {
this.toasterService.error(this.resourceService.messages.emsg.m0076);
});
}
navigateToPage(page: number): undefined | void {
if (page < 1 || page > this.pager.totalPages) {
return;
}
this.pageNumber = page;
this.queryParams.pageNumber = this.pageNumber;
this.navigate();
if (this.currentBatch) {
this.populateCourseDashboardData(this.currentBatch);
}
}
keyup(event) {
this.modelChanged.next(_.trim(event));
}
searchBatch() {
this.modelChanged.pipe(debounceTime(1000),
distinctUntilChanged(),
switchMap(search => of(search))
).
subscribe(query => {
this.populateCourseDashboardData();
});
}
getFieldValue(array, field) {
if (_.find(array, {'type': field})) {
return _.find(array, {'type': field}).count;
} else {
return;
}
}
/**
* To method subscribes the user data to get the user id.
* It also subscribes the activated route params to get the
* course id and timeperiod
*/
ngOnInit() {
// ---- Mock data Start-----
const apiData = {
userConsent: 'No',
audience: 'Teacher'
};
this.fileName = 'State wise report';
this.isDownloadReport = true;
// this.searchFields = ['state', 'district'];
// ----- Mock date end -------------
this.userDataSubscription = this.user.userData$.pipe(first()).subscribe(userdata => {
if (userdata && !userdata.err) {
this.userId = userdata.userProfile.userId;
this.userRoles = _.get(userdata, 'userProfile.userRoles');
this.paramSubcription = combineLatest(this.activatedRoute.parent.params,
this.activatedRoute.params, this.activatedRoute.queryParams,
(parentParams: any, params: any, queryParams: any) => {
return {
params: parentParams || params,
queryParams: queryParams
};
})
.subscribe(bothParams => {
this.courseId = bothParams.params.courseId;
this.batchId = bothParams.params.batchId;
this.queryParams = { ...bothParams.queryParams };
this.interactObject = { id: this.courseId, type: 'Course', ver: '1.0' };
this.populateBatchData();
});
}
});
this.searchBatch();
this.setInteractEventData();
}
/**
* Load on demand reports
*/
loadOndemandReports(tabNumber) {
this.getSummaryReports();
setTimeout(() => {
if (this.onDemandReports) {
this.setInteractEventDataForTabs('on-demand-reports');
this.selectedTab = tabNumber;
if (_.isEmpty(this.reportTypes)) {
this.getFormData();
}
this.onDemandReports.loadReports(this.currentBatch);
}
}, 500);
}
ngAfterViewInit() {
setTimeout(() => {
this.telemetryImpression = {
context: {
env: this.activatedRoute.snapshot.data.telemetry.env,
cdata: [{ id: this.activatedRoute.snapshot.params.courseId, type: 'Course' }]
},
edata: {
uri: '/learn/course/' + this.courseId + '/dashboard&batchIdentifier=' + this.activatedRoute.snapshot.params.batchId,
type: this.activatedRoute.snapshot.data.telemetry.type,
pageid: this.activatedRoute.snapshot.data.telemetry.pageid,
duration: this.navigationhelperService.getPageLoadTime()
},
object: {
id: this.courseId,
type: this.activatedRoute.snapshot.data.telemetry.object.type,
ver: this.activatedRoute.snapshot.data.telemetry.object.ver
}
};
});
}
/**
* @since - #SH-601
* @param {} currentBatch
* @description - This will set completedCount and participantCount to the currentBatch object;
*/
setCounts(currentBatch) {
if (currentBatch) {
this.currentBatch['completedCount'] = _.get(currentBatch, 'completedCount') ? _.get(currentBatch, 'completedCount') : 0;
this.currentBatch['participantCount'] = _.get(currentBatch, 'participantCount') ? _.get(currentBatch, 'participantCount') : 0;
}
}
setInteractEventData() {
if (_.get(this.queryParams, 'batchIdentifier')) {
this.telemetryCdata = [{ 'type': 'batch', 'id': this.queryParams.batchIdentifier }];
} else {
this.telemetryCdata = [{ 'type': 'course', 'id': this.courseId }];
}
}
ngOnDestroy() {
if (this.userDataSubscription) {
this.userDataSubscription.unsubscribe();
}
this.unsubscribe.next();
this.unsubscribe.complete();
}
getFormData() {
const isCourseCreator = _.includes(this.userRoles, 'CONTENT_CREATOR');
const formReadInputParams = {
formType: 'batch',
formAction: 'list',
contentType: 'report_types'
};
this.formService.getFormConfig(formReadInputParams).subscribe((formResponsedata) => {
if (formResponsedata) {
const options = formResponsedata;
if (isCourseCreator) {
this.reportTypes = options;
} else {
this.reportTypes = _.filter(options, (report) => report.title !== 'User profile exhaust');
}
}
}, error => {
this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
});
}
generateDataForDF(batchId) {
this.fetchForumIdReq = null;
if (batchId) {
this.fetchForumIdReq = {
type: 'batch',
identifier: [batchId.id]
};
}
}
/**
* @description - navigate to the DF Page when the event is emited from the access-discussion component
* @param {} routerData
*/
assignForumData(routerData) {
this.route.navigate(['/discussion-forum'], {
queryParams: {
categories: JSON.stringify({ result: routerData.forumIds }),
userId: routerData.userId
}
});
}
selectedTabChange(event) {
const { index } = _.get(event, 'tab.textLabel');
if (index == 2) {
this.loadOndemandReports(2);
}
}
}
<app-modal-wrapper *ngIf="showDownloadModal" [config]="{disableClose: true, size: 'large', panelClass: 'material-modal'}"
(dismiss)="modal.deny(); showDownloadModal = false;" #modal>
<ng-template sbModalContent>
<div class="sb-mat__modal">
<!-- Download report popup-->
<div mat-dialog-title class="mb-0">
<div class="title" tabindex="0">{{resourceService?.frmelmnts?.instn?.t0060}}</div>
<button aria-label="close dialog" mat-dialog-close class="close-btn"></button>
</div>
<!--/Header-->
<!--Content-->
<div class="sb-mat__modal__content">
<p class="meta">{{resourceService?.messages?.stmsg?.m0132}}</p>
</div>
<!--/Content-->
<mat-dialog-actions class="sb-mat__modal__actions"></mat-dialog-actions>
</div>
</ng-template>
</app-modal-wrapper>
<!-- Updated code as per new design for semantic datatable-->
<div class="p-16 progress-content">
<div>
<div id="dashoardFiltersHolder" *ngIf="batchlist && batchlist.length > 0">
<div class="d-flex progress-report-content">
<div class="d-flex w-300 flex-dc">
<div class="sb-field">
<mat-form-field appearance="fill" class="sb-mat__dropdown w-100 mb-16">
<mat-label>{{resourceService?.frmelmnts?.lbl?.selectBatch}}</mat-label>
<mat-select role="listbox" aria-label="resourceService?.frmelmnts?.lbl?.selectBatch" class="selection"
[(ngModel)]="selectedOption" (selectionChange)="setBatchId($event)">
<mat-option class="mat-dropdown__options" role="option" *ngFor="let option of batchlist" [value]="option"
attr.aria-label="{{option.name}}">{{option.name}}</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
<!-- below needs to be done score card -->
<app-access-discussion *ngIf="fetchForumIdReq" [fetchForumIdReq]="fetchForumIdReq"
(routerData)="assignForumData($event)"> </app-access-discussion>
</div>
<!-- NOTE: Using currentBatch data instead of dashboardData, as API got deprecated -->
<div class="d-flex flex-dc current-batch-list">
<p *ngIf="currentBatch?.lastUpdatedOn" class="d-flex flex-ai-flex-end mr-24 fsmall mt-8 mb-0 update-text">
{{resourceService?.frmelmnts?.lbl?.batchReportUpdateNote | interpolate:'{date}': (currentBatch?.lastUpdatedOn
| sbDataTable : 'dateTime')}}</p>
<div class="d-flex flex-dc my-16 sb-course-progress-status" *ngIf="currentBatch">
<div class="sb-course-progress-status-label">
<span class="course-start-dt course-participants-label">
<span *ngIf="currentBatch.startDate">
{{resourceService?.frmelmnts?.lbl?.batchstartdate}}
</span>
</span>
<span class="course-end-dt course-participants-label">
<span>{{resourceService?.frmelmnts?.lbl?.batchenddate}}
</span>
</span>
<span *ngIf="currentBatch.participantCount !== null"
class="d-flex flex-dc course-participants course-participants-label">
<span>{{resourceService?.frmelmnts?.lbl?.totalEnrolments}}</span>
</span>
</div>
<div class="sb-course-progress-status-result">
<span class="course-start-dt course-participants-label">
<span class="font-weight-bold"> {{currentBatch.startDate | dateFormat :'DD/MM/YYYY' }}</span>
</span>
<span class="course-end-dt course-participants-label">
<span *ngIf="currentBatch.endDate" class="font-weight-bold">{{currentBatch.endDate | dateFormat
:'DD/MM/YYYY'}}</span>
<span *ngIf="!currentBatch.endDate">-</span>
</span>
<span *ngIf="currentBatch.participantCount !== null" class="course-participants course-participants-label">
<span class="font-weight-bold">{{currentBatch.participantCount}}</span>
</span>
</div>
</div>
</div>
<!-- Select Batch image content start-->
<div class="d-flex flex-jc-center" *ngIf="batchlist && batchlist.length > 1 && showWarningDiv && !showLoader">
<div class="d-flex flex-dc flex-ai-center pb-24">
<div><img src="assets/images/batch.png" width="329px" height="229px" alt="batch"></div>
<p class="img-text">Select batch to view details</p>
</div>
</div>
<!-- Select Batch image content end-->
</div>
<div class="sb-toaster sb-toast-info sb-mw-100 sb-toast-sm-padding"
*ngIf="currentBatch && currentBatch.count>10000">
<div class="sb-toast-body">
<div class="sb-toast-texts">
<div class="sb-toast-message">{{resourceService?.frmelmnts?.instn?.t0085}}</div>
</div>
</div>
</div>
<div class="tweleve wide column" *ngIf="showLoader">
<app-loader></app-loader>
</div>
<div class="ui grid" *ngIf="showNoBatch">
<div class="twelve wide column">
<div class="ui info message">
<div class="header">{{resourceService?.frmelmnts?.instn?.t0061}}</div>
<ul class="list">
<li>{{resourceService?.frmelmnts?.instn?.t0062}}</li>
</ul>
</div>
</div>
</div>
</div>
<mat-tab-group *ngIf="currentBatch" (selectedTabChange)="selectedTabChange($event)">
<mat-tab [label]="{index: 2}">
<ng-template mat-tab-label>
<span>{{resourceService?.frmelmnts?.lbl?.detailedWiseReport}}</span>
</ng-template>
<app-on-demand-reports [reportTypes]="reportTypes" [userId]="userId" [batch]="currentBatch"
[tag]="courseId + '_'+batchId"></app-on-demand-reports>
</mat-tab>
</mat-tab-group>
</div>
./course-progress.component.scss
@use "@project-sunbird/sb-styles/assets/mixins/mixins" as *;
.w-300 {
width: calculateRem(300px);
}
.download-file-container {
background-color: var(--gray-100);
height: calculateRem(48px);
}
a {
&.download-file {
text-decoration: underline;
}
}
.course-participants-label {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
}
.course-completed:last-child {
flex: unset;
}
.download-report.sb-btn.sb-btn-link:disabled {
background-color: transparent;
border: none;
color: var(--gray-200);
}
.info-outline-img {
background-image: url(/assets/images/info-outline.png);
background-size: cover;
background-repeat: no-repeat;
background-position: center;
display: inline-block;
width: calculateRem(14px);
height: calculateRem(14px);
}
.sb-btn-link {
font-size: calculateRem(14px);
}
::ng-deep {
.ui.selection.dropdown {
line-height: 1em;
}
.ui.search.dropdown.course-dashboard-select>.text {
margin: calculateRem(6px) calculateRem(16px) calculateRem(6px) calculateRem(6px);
}
}
.table-headerDashboard {
color: var(--primary-color);
font-weight: bold;
}
.CloseButtonFont {
font-size: 1.5rem !important;
}
.summary-text {
font-style: italic;
color:var(--gray-200); word-break: break-word;
}
.progress-content {
// margin-top: calculateRem(36px);
background-color: var(--state-medium-container-bg);
.sb-course-progress-status .sb-course-progress-status-label {
background: var(--sbt-body-bg);
}
@include respond-below(sm) {
margin-top: 0px;
}
.progress-report-content {
height: calculateRem(64px);
align-items: center;
@include respond-below(sm) {
flex-direction: column;
height: auto;
}
.report-buttons {
align-items: flex-end;
height: 100%;
@include respond-below(sm) {
flex-direction: column;
margin-top: calculateRem(8px);
}
&__divider {
width: calculateRem(1px);
border-left: calculateRem(1px) solid var(--gray-100);
height: calculateRem(32px);
margin: 0 calculateRem(16px);
@include respond-below(sm) {
display: none;
}
}
}
}
.current-batch-list {
overflow: auto;
}
}
.update-text {
font-style: italic;
justify-content: flex-end;
color:var(--gray-200);
}