src/app/modules/dashboard/components/usage-reports/usage-reports.component.ts
OnInit
AfterViewInit
selector | app-usage-reports |
styleUrls | ./usage-reports.component.scss |
templateUrl | ./usage-reports.component.html |
constructor(usageService: UsageService, sanitizer: DomSanitizer, userService: UserService, toasterService: ToasterService, resourceService: ResourceService, activatedRoute: ActivatedRoute, router: Router, navigationhelperService: NavigationHelperService, layoutService: LayoutService, courseProgressService: CourseProgressService, tncService: TncService)
|
||||||||||||||||||||||||||||||||||||
Parameters :
|
createChartData | ||||||||
createChartData(charts, data, downloadUrl)
|
||||||||
Parameters :
Returns :
void
|
downloadCSV | ||||
downloadCSV(filepath)
|
||||
Parameters :
Returns :
void
|
getReportViewerTncPolicy |
getReportViewerTncPolicy()
|
Returns :
void
|
goBack |
goBack()
|
Returns :
void
|
initLayout |
initLayout()
|
Returns :
void
|
ngAfterViewInit |
ngAfterViewInit()
|
Returns :
void
|
ngOnInit |
ngOnInit()
|
Returns :
void
|
renderFiles | ||||||
renderFiles(files, data)
|
||||||
Parameters :
Returns :
void
|
renderReport | ||||||
renderReport(report: any)
|
||||||
Parameters :
Returns :
void
|
renderTable | ||||||
renderTable(tables, data)
|
||||||
Parameters :
Returns :
void
|
selectedTabChange | ||||
selectedTabChange(event)
|
||||
Parameters :
Returns :
void
|
setDownloadUrl | ||||
setDownloadUrl(url)
|
||||
Parameters :
Returns :
void
|
setTelemetryInteractEdata | ||||
setTelemetryInteractEdata(val)
|
||||
Parameters :
Returns :
{ id: any; type: string; pageid: any; }
|
setTelemetryInteractObject | ||||
setTelemetryInteractObject(val)
|
||||
Parameters :
Returns :
{ id: any; type: string; ver: string; }
|
showReportViewerTncForFirstUser |
showReportViewerTncForFirstUser()
|
Returns :
void
|
transformHTML | ||||||
transformHTML(data: any)
|
||||||
Parameters :
Returns :
any
|
Private activatedRoute |
Type : ActivatedRoute
|
chartData |
Type : Array<object>
|
Default value : []
|
Public courseProgressService |
Type : CourseProgressService
|
currentReport |
Type : any
|
downloadUrl |
files |
Type : any
|
isFileDataLoaded |
Default value : false
|
isTableDataLoaded |
Default value : false
|
layoutConfiguration |
Type : any
|
Public layoutService |
Type : LayoutService
|
Public navigationhelperService |
Type : NavigationHelperService
|
noResult |
Type : boolean
|
noResultMessage |
Type : INoResultMessage
|
reportMetaData |
Type : any
|
reportViewerTncUrl |
Type : string
|
reportViewerTncVersion |
Type : string
|
Public resourceService |
Type : ResourceService
|
showLoader |
Default value : false
|
showTncPopup |
Default value : false
|
slug |
Type : string
|
tables |
Type : any
|
telemetryImpression |
Type : IImpressionEventInput
|
telemetryInteractDirective |
Decorators :
@ViewChild(TelemetryInteractDirective)
|
telemetryInteractDownloadEdata |
Type : IInteractEventEdata
|
telemetryInteractEdata |
Type : IInteractEventEdata
|
Public tncService |
Type : TncService
|
Private unsubscribe$ |
Default value : new Subject<void>()
|
userProfile |
Public userService |
Type : UserService
|
import { IInteractEventEdata, TelemetryInteractDirective, IImpressionEventInput } from '@sunbird/telemetry';
import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
import { CourseProgressService, UsageService } from './../../services';
import * as _ from 'lodash-es';
import dayjs from 'dayjs';
import { DomSanitizer } from '@angular/platform-browser';
import { UserService, TncService } from '@sunbird/core';
import {
ToasterService,
ResourceService,
INoResultMessage,
NavigationHelperService,
LayoutService
} from '@sunbird/shared';
import { ActivatedRoute, Router } from '@angular/router';
import {Subject} from 'rxjs';
import {first, takeUntil} from 'rxjs/operators';
@Component({
selector: 'app-usage-reports',
templateUrl: './usage-reports.component.html',
styleUrls: ['./usage-reports.component.scss']
})
export class UsageReportsComponent implements OnInit, AfterViewInit {
reportMetaData: any;
chartData: Array<object> = [];
tables: any;
files: any;
isTableDataLoaded = false;
isFileDataLoaded = false;
currentReport: any;
slug: string;
noResult: boolean;
showLoader = false;
noResultMessage: INoResultMessage;
private activatedRoute: ActivatedRoute;
telemetryImpression: IImpressionEventInput;
telemetryInteractEdata: IInteractEventEdata;
telemetryInteractDownloadEdata: IInteractEventEdata;
downloadUrl;
public courseProgressService: CourseProgressService;
layoutConfiguration: any;
private unsubscribe$ = new Subject<void>();
reportViewerTncVersion: string;
reportViewerTncUrl: string;
showTncPopup = false;
userProfile;
@ViewChild(TelemetryInteractDirective) telemetryInteractDirective;
constructor(private usageService: UsageService, private sanitizer: DomSanitizer,
public userService: UserService, private toasterService: ToasterService,
public resourceService: ResourceService, activatedRoute: ActivatedRoute, private router: Router,
public navigationhelperService: NavigationHelperService, public layoutService: LayoutService,
courseProgressService: CourseProgressService, public tncService: TncService
) {
this.activatedRoute = activatedRoute;
this.courseProgressService = courseProgressService;
}
ngOnInit() {
this.initLayout();
const reportsLocation = (<HTMLInputElement>document.getElementById('reportsLocation')) ? (<HTMLInputElement>document.getElementById('reportsLocation')).value : '';
this.slug = _.get(this.userService, 'userProfile.rootOrg.slug');
this.userService.userData$.pipe(first()).subscribe(async (user) => {
if (user && user.userProfile) {
this.userProfile = user.userProfile;
this.getReportViewerTncPolicy();
}
});
this.usageService.getData(`/${reportsLocation}/${this.slug}/config.json`)
.subscribe(data => {
if (_.get(data, 'responseCode') === 'OK') {
this.noResult = false;
this.reportMetaData = _.get(data, 'result');
if (this.reportMetaData[0]) { this.renderReport(this.reportMetaData[0]); }
}
}, (err) => {
console.log(err);
this.noResultMessage = {
'messageText': 'messages.stmsg.m0131'
};
this.noResult = true;
});
}
setTelemetryInteractObject(val) {
return {
id: val,
type: 'Report',
ver: '1.0'
};
}
initLayout() {
this.layoutConfiguration = this.layoutService.initlayoutConfig();
this.layoutService.switchableLayout().pipe(takeUntil(this.unsubscribe$)).subscribe(layoutConfig => {
if (layoutConfig != null) {
this.layoutConfiguration = layoutConfig.layout;
}
});
}
setTelemetryInteractEdata(val) {
return {
id: val,
type: 'click',
pageid: this.activatedRoute.snapshot.data.telemetry.pageid
};
}
renderReport(report: any) {
this.chartData = [];
this.tables = [];
this.files = [];
this.currentReport = report;
this.isTableDataLoaded = false;
const url = report.dataSource;
this.showLoader = true;
this.downloadUrl = report.downloadUrl;
this.usageService.getData(url)
.subscribe((response) => {
if (_.get(response, 'responseCode') === 'OK') {
const data = _.get(response, 'result');
this.showLoader = false;
if (_.get(report, 'charts')) {
this.createChartData(_.get(report, 'charts'), data, url);
}
if (_.get(report, 'table')) {
this.renderTable(_.get(report, 'table'), data);
} else {
this.renderTable({}, data);
}
if (_.get(report, 'files')) {
this.renderFiles(_.get(report, 'files'), data);
} else {
this.renderFiles({}, data);
}
} else {
}
}, err => { console.log(err); });
}
renderFiles(files, data) {
this.files = [];
_.forEach(files, file => {
const fileData: any = {};
fileData.id = _.get(file, 'id');
fileData.name = _.get(file, 'name');
fileData.desc = _.get(file, 'description');
fileData.size = _.get(file, 'fileSize');
fileData.createdOn = _.get(file, 'createdOn');
fileData.downloadUrl = _.get(file, 'downloadUrl');
this.files.push(fileData);
});
if (this.files.length) {
this.isFileDataLoaded = true;
} else {
this.isFileDataLoaded = false;
}
_.forEach(this.files, file => {
const path = (file.downloadUrl).replace('/reports/', '');
const requestParams = {
params: {
fileNames: JSON.stringify({ path })
},
telemetryData: this.activatedRoute
};
this.courseProgressService.getReportsMetaData(requestParams).subscribe((response) => {
if (_.get(response, 'responseCode') === 'OK') {
file.size = (_.get(response, 'result.path.fileSize')) / 1024;
if (_.get(response, 'result.path.lastModified')) {
file.createdOn = dayjs(new Date(_.get(response, 'result.path.lastModified'))).format('DD MMM YYYY');
} else {
file.createdOn = '';
}
}
});
});
}
createChartData(charts, data, downloadUrl) {
this.chartData = [];
_.forEach(charts, chart => {
const chartObj: any = {};
chartObj.chartConfig = chart;
chartObj.downloadUrl = downloadUrl;
chartObj.chartData = _.get(data, 'data');
chartObj.lastUpdatedOn = _.get(data, 'metadata.lastUpdatedOn');
this.chartData.push(chartObj);
});
}
renderTable(tables, data) {
this.tables = [];
tables = _.isArray(tables) ? tables : [tables];
_.forEach(tables, table => {
const tableData: any = {};
tableData.id = _.get(table, 'id') || `table-${_.random(1000)}`;
tableData.name = _.get(table, 'name') || 'Table';
tableData.header = _.get(table, 'columns') || _.get(data, _.get(table, 'columnsExpr'));
tableData.data = _.get(table, 'values') || _.get(data, _.get(table, 'valuesExpr'));
tableData.downloadUrl = _.get(table, 'downloadUrl') || this.downloadUrl;
this.tables.push(tableData);
});
this.isTableDataLoaded = true;
}
ngAfterViewInit() {
setTimeout(() => {
this.telemetryImpression = {
context: {
env: this.activatedRoute.snapshot.data.telemetry.env
},
object: {
id: this.userService.userid,
type: 'user',
ver: '1.0'
},
edata: {
type: this.activatedRoute.snapshot.data.telemetry.type,
pageid: this.activatedRoute.snapshot.data.telemetry.pageid,
uri: this.router.url,
duration: this.navigationhelperService.getPageLoadTime()
}
};
});
}
setDownloadUrl(url) {
this.downloadUrl = url;
}
downloadCSV(filepath) {
if (!filepath) {
filepath = this.downloadUrl;
}
this.usageService.getData(filepath).subscribe((response) => {
if (_.get(response, 'responseCode') === 'OK') {
const url = _.get(response, 'result.signedUrl');
if (url) { window.open(url, '_blank'); }
} else {
this.toasterService.error(this.resourceService.messages.emsg.m0076);
}
}, (err) => {
this.toasterService.error(this.resourceService.messages.emsg.m0076);
});
}
transformHTML(data: any) {
return this.sanitizer.bypassSecurityTrustHtml(data);
}
selectedTabChange(event) {
const { downloadURL } = _.get(event, 'tab.textLabel');
downloadURL && this.setDownloadUrl(downloadURL);
}
getReportViewerTncPolicy() {
this.tncService.getReportViewerTnc().subscribe((data) => {
const reportViewerTncData = JSON.parse(_.get(data, 'result.response.value'));
if (_.get(reportViewerTncData, 'latestVersion')) {
this.reportViewerTncVersion = _.get(reportViewerTncData, 'latestVersion');
this.reportViewerTncUrl = _.get(_.get(reportViewerTncData, _.get(reportViewerTncData, 'latestVersion')), 'url');
this.showReportViewerTncForFirstUser();
}
});
}
goBack() {
this.navigationhelperService.goBack();
}
showReportViewerTncForFirstUser() {
const reportViewerTncObj = _.get(this.userProfile, 'allTncAccepted.reportViewerTnc');
if (!reportViewerTncObj) {
this.showTncPopup = true;
}
}
}
<app-landing-section [noTitle]="true" [layoutConfiguration]="layoutConfiguration">
</app-landing-section>
<div
[ngClass]="layoutConfiguration ? 'sb-back-actionbar' : 'sb-bg-color-white back-btn-container cc-player__btn-back relative9'"
class="relative position mt-0">
<div class="ui container py-0 px-0 d-flex flex-ai-center">
<div class="py-0 d-flex flex-ai-center w-100">
<!-- /* Back button */ -->
<button type="button" [ngClass]="layoutConfiguration ? 'sb-btn-primary sb-btn-round' : 'sb-btn-link sb-btn-link-primary sb-left-icon-btn px-0'" class="sb-btn sb-btn-normal" tabindex="0" (click)="goBack()" attr.aria-label="{{resourceService?.frmelmnts?.btn?.back}}">
<em class="icon-svg icon-svg--xxs icon-back mr-4"><svg class="icon icon-svg--primary">
<use xlink:href="assets/images/sprite.svg#arrow-long-left"></use>
</svg></em>
<span>{{resourceService?.frmelmnts?.btn?.back}}</span>
</button>
<div class="textbook d-flex flex-ai-center flex-jc-space-between w-100 ml-16">
<!-- title -->
<h5 class="textbook__title sb-color-primary font-weight-bold mb-0" tabindex="0">{{resourceService.frmelmnts?.lnk?.dashboard}}</h5>
</div>
</div>
</div>
</div>
<div [ngClass]="layoutConfiguration ? 'sbt-inside-page-container' : 'pt-16'">
<div class="ui" [appTelemetryImpression]="telemetryImpression">
<div class="twelve wide column px-0 sb-workspace-bg">
<div class="ui container stackable grid m-0 sb-mid-container-min-height dashboard-body-scroll" *ngIf="!noResult">
<div class="two wide column sb-sidebar-menu p-0">
<h5 class="p-16">{{resourceService.frmelmnts?.lnk?.dashboard}}</h5>
<ul class="m-0">
<li appTelemetryInteract [telemetryInteractObject]="setTelemetryInteractObject(report.id)"
[telemetryInteractEdata]="setTelemetryInteractEdata('report-view')" *ngFor="let report of reportMetaData"
(click)="renderReport(report)" tabindex="0" class="item m-0"
[ngClass]="{'active': currentReport.id === report.id}">
{{report.label || report.title}}</li>
</ul>
</div>
<div class="ten wide column sb-sideview-tab-container pl-40 pt-72 pb-48" *ngIf="currentReport">
<h3 class="mb-16">
{{currentReport?.title || currentReport?.label}}
</h3>
<p *ngIf="currentReport?.description" [innerHTML]="transformHTML(currentReport.description)"></p>
<ng-container *ngIf="!showLoader">
<mat-tab-group (selectedTabChange)="selectedTabChange($event)" class="mat-tab__usage-report">
<mat-tab appTelemetryInteract [telemetryInteractObject]="setTelemetryInteractObject(currentReport.id)"
[telemetryInteractEdata]="setTelemetryInteractEdata('report-graph')"
[label]="{'type': 'chart', 'downloadURL': currentReport.downloadUrl}">
<div class="p-0 b-0 no-bg py-24">
<ng-template mat-tab-label>
<span>{{resourceService?.frmelmnts?.lbl?.graphs}}</span>
</ng-template>
<ng-container *ngTemplateOutlet="commonReportActions">
</ng-container>
<div class="sb-graph-section p-24 my-24"
*ngFor="let chart of chartData; let i = index; let l = last;">
<app-data-chart [telemetryInteractObject]="setTelemetryInteractObject(currentReport.id)"
[chartInfo]="chart"></app-data-chart>
<!-- <hr *ngIf="!l" /> -->
</div>
<div class="ui warning message" *ngIf="!chartData.length">
{{resourceService?.frmelmnts?.lbl?.graphNotAvailable}}
</div>
</div>
</mat-tab>
<ng-container *ngFor="let table of tables">
<mat-tab [label]="{'type': 'table', 'downloadURL': table?.downloadUrl}">
<ng-template mat-tab-label>
<span>{{table?.name}}</span>
</ng-template>
<ng-template matTabContent>
<div class="p-0 b-0 no-bg py-24">
<ng-container *ngTemplateOutlet="commonReportActions">
</ng-container>
<div class="p-0 b-0 no-bg py-24">
<div *ngIf="table.data">
<app-data-table [tableId]="table.id" [headerData]="table.header" [rowsData]="table.data">
</app-data-table>
</div>
<div class="ui warning message" *ngIf="!table.data">
{{resourceService?.frmelmnts?.lbl?.tableNotAvailable}}
</div>
</div>
</div>
</ng-template>
</mat-tab>
</ng-container>
<mat-tab label="{{resourceService?.frmelmnts?.lbl?.dashboard?.download}}" *ngIf="isFileDataLoaded">
<div class="p-0 b-0 no-bg py-24">
<ng-container *ngTemplateOutlet="commonReportActions">
</ng-container>
<div class="sb-graph-section p-24 my-24">
<table *ngIf="isFileDataLoaded" id="downloadTable"
class="sb-table sb-table-striped sb-table-sortable sb-table-fixed sb-table-course-dashboard"
cellspacing="0">
<thead>
<tr>
<th>
<div class="cursor-pointer">
{{resourceService?.frmelmnts?.lbl?.dashboard?.fileName}}
</div>
</th>
<th>
<div class="cursor-pointer">
{{resourceService?.frmelmnts?.lbl?.dashboard?.description}}
</div>
</th>
<th>
<div class="cursor-pointer">
{{resourceService?.frmelmnts?.lbl?.dashboard?.fileSize}}
</div>
</th>
<th>
<div class="cursor-pointer">
{{resourceService?.frmelmnts?.lbl?.createdon}}
</div>
</th>
<th class="table-headerDashboard">
<div class="cursor-pointer">
{{resourceService?.frmelmnts?.lbl?.dashboard?.action}}
</div>
</th>
</tr>
</thead>
<tbody class="sb-table-body">
<tr *ngFor="let file of files; let i = index; let l = last;">
<td *ngIf="file.name">
{{file.name}}
</td>
<td *ngIf="!file.name">
--
</td>
<td *ngIf="file.desc">
{{file.desc}}
</td>
<td *ngIf="!file.desc">
--
</td>
<td *ngIf="file.size">
{{file.size}}
</td>
<td *ngIf="!file.size">
--
</td>
<td *ngIf="file.createdOn">
{{file.createdOn}}
</td>
<td *ngIf="!file.createdOn">
--
</td>
<td>
<button type="button" class="sb-btn sb-btn-primary sb-btn-normal ml-auto mr-8"
appTelemetryInteract
[telemetryInteractObject]="setTelemetryInteractObject(currentReport.id)"
[telemetryInteractEdata]="setTelemetryInteractEdata('report-download')"
(click)="downloadCSV(file.downloadUrl)" tabindex="0"><i class="icon"></i>
{{resourceService?.frmelmnts?.lbl?.dashboard?.downloadfile}}</button>
</td>
</tbody>
</table>
<div class="ui warning message" *ngIf="!files.length">
File Not Available
</div>
</div>
</div>
</mat-tab>
</mat-tab-group>
</ng-container>
<div class="nine wide column workspacesegment" *ngIf="showLoader">
<app-loader></app-loader>
</div>
</div>
</div>
<div *ngIf="noResult">
<app-no-result [data]="noResultMessage"></app-no-result>
</div>
</div>
<div *ngIf="!noResult">
<app-tnc-popup [showAcceptTnc]="showTncPopup" [reportViewerTncVersion]="reportViewerTncVersion" [tncUrl]="reportViewerTncUrl" #termsAndCondPopUp *ngIf="showTncPopup">
</app-tnc-popup>
</div>
</div>
</div>
<ng-template #commonReportActions>
<div class="my-0">
<div class="d-flex flex-ai-center flex-jc-flex-end">
<button appTelemetryInteract [telemetryInteractObject]="setTelemetryInteractObject(currentReport.id)"
[telemetryInteractEdata]="setTelemetryInteractEdata('report-download')" type="button"
*ngIf="!isFileDataLoaded && currentReport?.downloadUrl"
class="sb-left-icon-btn sb-btn sb-btn-tertiary sb-btn-normal mr-8" (click)="downloadCSV()" tabindex="0"><i
class="icon"></i>
{{resourceService?.frmelmnts?.lbl?.downloadCsv}}</button>
</div>
</div>
</ng-template>
./usage-reports.component.scss
@use "@project-sunbird/sb-styles/assets/mixins/mixins" as *;
.sb-graph-section{
border: calculateRem(1px) solid var(--rc-dddddd);
padding: calculateRem(24px);
margin-top: calculateRem(24px);
background: var(--sb-graph-section-bg);
box-shadow: 0 calculateRem(2px) calculateRem(7px) 0 rgba(var(--rc-rgba-black), 0.16);
border-radius: calculateRem(4px);
.sb-table-fixed .sb-table tbody td, .sb-table-fixed .sb-table-body td {
text-overflow: initial;
overflow: initial;
white-space: unset;
}
}
.sb-btn-normal i::after {
content: "\f019";
font-size: calculateRem(13px);
}
.no-bg {
background:none;
}
.dashboard-body-scroll{
display: flex;
align-items: flex-start;
}
.sb-sidebar-menu{
position: sticky !important;
position: -webkit-sticky !important;
top: 0;
}
.table-headerDashboard{
width:calculateRem(200px);
color: var(--primary-color);
font-weight: bold;
}
.sb-workspace-bg{
position: relative;
height: auto;
}