File

src/app/modules/dashboard/components/report/report.component.ts

Implements

OnInit

Metadata

Index

Properties
Methods
Accessors

Constructor

constructor(reportService: ReportService, activatedRoute: ActivatedRoute, resourceService: ResourceService, toasterService: ToasterService, navigationhelperService: NavigationHelperService, router: Router, telemetryService: TelemetryService, layoutService: LayoutService, cdr: ChangeDetectorRef, userService: UserService, tncService: TncService, location: Location)
Parameters :
Name Type Optional
reportService ReportService No
activatedRoute ActivatedRoute No
resourceService ResourceService No
toasterService ToasterService No
navigationhelperService NavigationHelperService No
router Router No
telemetryService TelemetryService No
layoutService LayoutService No
cdr ChangeDetectorRef No
userService UserService No
tncService TncService No
location Location No

Methods

Private closeConfirmationModal
closeConfirmationModal()
Returns : void
Public closeSummaryModal
closeSummaryModal()
Returns : void
Private convertHTMLToCanvas
convertHTMLToCanvas(element, options)
Parameters :
Name Optional
element No
options No
Returns : any
Public downloadCSV
downloadCSV(downloadUrl?: string)
Parameters :
Name Type Optional
downloadUrl string Yes
Returns : void
downloadReport
downloadReport(reportType)
Parameters :
Name Optional
reportType No
Returns : void
Private downloadReportAsImage
downloadReportAsImage()
Returns : void
Private downloadReportAsPdf
downloadReportAsPdf()
Returns : void
Private fetchConfig
fetchConfig(reportId, hash?: string)
Parameters :
Name Type Optional
reportId No
hash string Yes
Returns : Observable<any>
Public filterChanged
filterChanged(data: any)
Parameters :
Name Type Optional
data any No
Returns : void
getAllChartData
getAllChartData()
Returns : {}
getChartData
getChartData(chart)
Parameters :
Name Optional
chart No
Returns : any
Private getLatestSummary
getLatestSummary(reportId: string)
Parameters :
Name Type Optional
reportId string No
Returns : any
Public getParametersValueForDropDown
getParametersValueForDropDown(report?: object)
Parameters :
Name Type Optional
report object Yes
Returns : any
getReportViewerTncPolicy
getReportViewerTncPolicy()
Returns : void
Public gotoListPage
gotoListPage()
Returns : void
Private handleAddSummaryStreams
handleAddSummaryStreams()
Returns : any
Public handleConfirmationEvent
handleConfirmationEvent(event: boolean)
Parameters :
Name Type Optional
event boolean No
Returns : void
Public handleParameterChange
handleParameterChange(val)
Parameters :
Name Optional
val No
Returns : void
Private handlePublishBtnStream
handlePublishBtnStream()
Returns : any
Private handleRetireBtnStream
handleRetireBtnStream()
Returns : any
Private handleUpdatedMarkdown
handleUpdatedMarkdown()
Returns : any
initLayout
initLayout()
Returns : void
Private logTelemetry
logTelemetry(undefined)
Parameters :
Name Optional
No
Returns : void
Private mergeClickEventStreams
mergeClickEventStreams()
Returns : void
ngOnInit
ngOnInit()
Returns : void
Public onAddSummary
onAddSummary(event: ISummaryObject)
Parameters :
Name Type Optional
event ISummaryObject No
Returns : void
Public onPublish
onPublish(event)
Parameters :
Name Optional
event No
Returns : void
Public onRetire
onRetire(event)
Parameters :
Name Optional
event No
Returns : void
Public openAddSummaryModal
openAddSummaryModal(undefined: ISummaryObject)
Parameters :
Name Type Optional
ISummaryObject No
Returns : void
Public openConfirmationModal
openConfirmationModal(eventType: "publish" | "retire")
Parameters :
Name Type Optional
eventType "publish" | "retire" No
Returns : void
Public openReportSummaryModal
openReportSummaryModal()
Returns : void
Private refreshComponent
refreshComponent()
Returns : void
Private renderReport
renderReport(reportId: string, hash?: string)
Parameters :
Name Type Optional
reportId string No
hash string Yes
Returns : any
resetFilter
resetFilter()
Returns : void
selectedTabChange
selectedTabChange(event)
Parameters :
Name Optional
event No
Returns : void
Public setDownloadUrl
setDownloadUrl(url)
Parameters :
Name Optional
url No
Returns : void
Public setTelemetryInteractEdata
setTelemetryInteractEdata(val)
Parameters :
Name Optional
val No
Public setTelemetryInteractObject
setTelemetryInteractObject(val?: string)
Parameters :
Name Type Optional
val string Yes
showReportViewerTncForFirstUser
showReportViewerTncForFirstUser()
Returns : void
Private toggleHtmlVisibilty
toggleHtmlVisibilty(flag: boolean)
Parameters :
Name Type Optional
flag boolean No
Returns : void

Properties

Private _reportSummary
Type : string
Private addSummaryBtnClickStream$
Default value : new Subject<ISummaryObject>()
chartsComponentList
Type : QueryList<DataChartComponent>
Decorators :
@ViewChildren(DataChartComponent)
Public chartsReportData
Type : any
Public confirmationPopupInput
Type : literal type
Public currentReportSummary
Type : any
Private downloadUrl
Type : string
Public exportOptions
Type : []
Default value : ['Pdf', 'Img']
filterType
Type : string
Default value : 'report-filter'
Public getCDataObj
Default value : () => {...}
Public getParametersValueForDropDown$
Type : Observable<any>
Public getTelemetryImpressionObj
Default value : () => {...}
Public getTelemetryInteractEdata
Default value : () => {...}
Public globalFilterChange
Type : Object
Private hash
Type : string
Public hideElements
Type : boolean
Public inputForSummaryModal
Type : any
Public isUserReportAdmin
Default value : false
layoutConfiguration
Type : any
Public location
Type : Location
Public markdownUpdated$
Default value : new Subject()
Private materializedReport
Default value : false
Public noResult
Type : boolean
Public noResultMessage
Type : INoResultMessage
Private publishBtnStream$
Default value : new Subject()
Public report
Type : any
Public report$
Private reportConfig
Type : object
Public reportData
Type : any
reportElement
Decorators :
@ViewChild('reportElement')
Public reportExportInProgress
Default value : false
Public reportObj
Type : any
Public reportResult
Type : any
Public reportService
Type : ReportService
reportViewerTncUrl
Type : string
reportViewerTncVersion
Type : string
Public resetFilters
Type : Object
Private retireBtnStream$
Default value : new Subject()
Public selectedFilters
Type : Object
Public showChart
Default value : true
Public showComponent
Default value : true
Public showConfirmationModal
Default value : false
Public showExportsOption
Default value : true
showResetFilter
Default value : true
Public showSummaryModal
Default value : false
showTncPopup
Default value : false
Public tncService
Type : TncService
Public type
Type : ReportType
Default value : ReportType.report
userProfile

Accessors

setMaterializedReportStatus
setsetMaterializedReportStatus(val: string)
Parameters :
Name Type Optional
val string No
Returns : void
setParametersHash
setsetParametersHash(report)
Parameters :
Name Optional
report No
Returns : void
import { TelemetryService } from '@sunbird/telemetry';
import { UserService, TncService } from '@sunbird/core';
import { INoResultMessage, ResourceService, ToasterService, NavigationHelperService, LayoutService } from '@sunbird/shared';
import { ActivatedRoute, Router } from '@angular/router';
import { Component, OnInit, ViewChildren, QueryList, ViewChild, ChangeDetectorRef } from '@angular/core';
import { ReportService } from '../../services';
import * as _ from 'lodash-es';
import { Observable, throwError, of, forkJoin, Subject, merge, combineLatest } from 'rxjs';
import { mergeMap, switchMap, map, retry, catchError, tap, pluck, first } from 'rxjs/operators';
import { DataChartComponent } from '../data-chart/data-chart.component';
import html2canvas from 'html2canvas';
import * as jspdf from 'jspdf';
import { ISummaryObject } from '../../interfaces';
import { Location } from '@angular/common';

enum ReportType {
  report,
  dataset
}

@Component({
  selector: 'app-report',
  templateUrl: './report.component.html',
  styleUrls: ['./report.component.scss']
})
export class ReportComponent implements OnInit {
  public report: any;
  public showSummaryModal = false;
  public report$;
  public noResultMessage: INoResultMessage;
  public noResult: boolean;
  private downloadUrl: string;
  public reportObj: any;
  public isUserReportAdmin = false;
  @ViewChildren(DataChartComponent) chartsComponentList: QueryList<DataChartComponent>;
  @ViewChild('reportElement') reportElement;
  public hideElements: boolean;
  public reportExportInProgress = false;
  public exportOptions = ['Pdf', 'Img'];
  public inputForSummaryModal: any;
  private _reportSummary: string;
  private addSummaryBtnClickStream$ = new Subject<ISummaryObject>();
  private publishBtnStream$ = new Subject();
  private retireBtnStream$ = new Subject();
  public markdownUpdated$ = new Subject();
  public currentReportSummary: any;
  public showComponent = true;
  public showConfirmationModal = false;
  public confirmationPopupInput: { title: string, event: 'retire' | 'publish', body: string };
  private materializedReport = false;
  private hash: string;
  public getParametersValueForDropDown$: Observable<any>;
  public type: ReportType = ReportType.report;
  private reportConfig: object;
  layoutConfiguration: any;
  public selectedFilters: Object;
  public showChart = true;
  public reportData: any;
  public chartsReportData: any;
  public globalFilterChange: Object;
  public resetFilters: Object;
  filterType = 'report-filter';
  public reportResult: any;
  public showExportsOption = true;
  private set setMaterializedReportStatus(val: string) {
    this.materializedReport = (val === 'true');
  }
  userProfile;
  reportViewerTncVersion: string;
  reportViewerTncUrl: string;
  showTncPopup = false;
  showResetFilter = true;

  private set setParametersHash(report) {
    const { hash } = this.activatedRoute.snapshot.params;
    this.hash = hash;
    if (this.reportService.isReportParameterized(report) && !this.reportService.isUserSuperAdmin()) {
      this.hash = _.get(report, 'hashed_val') || this.reportService.getParametersHash(this.report);
    }
  }

  constructor(public reportService: ReportService, private activatedRoute: ActivatedRoute,
    private resourceService: ResourceService, private toasterService: ToasterService,
    private navigationhelperService: NavigationHelperService,
    private router: Router, private telemetryService: TelemetryService, private layoutService: LayoutService,
    private cdr: ChangeDetectorRef, private userService: UserService, public tncService: TncService,
    public location:Location
  ) { }


  ngOnInit() {
    this.initLayout();
    this.userService.userData$.pipe(first()).subscribe(async (user) => {
      if (user && user.userProfile) {
        this.userProfile = user.userProfile;
        this.getReportViewerTncPolicy();
      }
    });
    this.report$ = combineLatest(this.activatedRoute.params, this.activatedRoute.queryParams).pipe(
      switchMap(params => {
        const { reportId, hash } = this.activatedRoute.snapshot.params;
        this.setMaterializedReportStatus = this.activatedRoute.snapshot.queryParams.materialize;
        return this.reportService.isAuthenticated(_.get(this.activatedRoute, 'snapshot.data.roles')).pipe(
          mergeMap((isAuthenticated: boolean) => {
            this.noResult = false;
            this.hideElements = false;
            return isAuthenticated ? this.renderReport(reportId, hash) : throwError({ messageText: 'messages.stmsg.m0144' });
          }),
          catchError(err => {
            console.error('Error while rendering report', err);
            this.noResultMessage = {
              'messageText': _.get(err, 'messageText') || 'messages.stmsg.m0131'
            };
            this.noResult = true;
            return of({});
          })
        );

      })
    );

    this.mergeClickEventStreams();
  }

  /**
   * @description fetches a report by its report id
   * @param reportId
   */
  private fetchConfig(reportId, hash?: string): Observable<any> {
    if (this.materializedReport) { hash = null; }
    return this.reportService.fetchReportById(reportId, hash).pipe(
      mergeMap(apiResponse => {
        const report = _.get(apiResponse, 'reports');
        return report ? of(_.head(report)) : throwError('No report found');
      })
    );
  }

  /**
   * @description This function fetches config file, datasource and prepares chart and tables data from it.
   * @param reportId
   */
  private renderReport(reportId: string, hash?: string) {
    return this.fetchConfig(reportId, hash)
      .pipe(
        switchMap(report => {
          const isUserReportAdmin = this.isUserReportAdmin = this.reportService.isUserReportAdmin();
          if (!isUserReportAdmin && _.toLower(_.get(report, 'status')) !== 'live') {
            return throwError({ messageText: 'messages.stmsg.m0144' });
          } else {
            this.report = report;
            this.type = _.get(report, 'report_type') === 'report' ? ReportType.report : ReportType.dataset;
            if (this.reportService.isReportParameterized(report) && _.get(report, 'children.length') &&
              !this.reportService.isUserSuperAdmin()) {
              return throwError({ messageText: 'messages.emsg.mutliParametersFound' });
            }
            this.setParametersHash = this.report;
            this.getParametersValueForDropDown$ = this.getParametersValueForDropDown(report);
            if (this.materializedReport) {
              this.report.status = 'draft';
            }
            const reportConfig = this.reportConfig = _.get(report, 'reportconfig');
            this.setDownloadUrl(_.get(reportConfig, 'downloadUrl'));
            const dataSource = _.get(reportConfig, 'dataSource') || [];
            let updatedDataSource = _.isArray(dataSource) ? dataSource : [{ id: 'default', path: dataSource }];
            updatedDataSource = this.reportService.getUpdatedParameterizedPath(updatedDataSource, this.hash);
            const charts = _.get(reportConfig, 'charts'), tables = _.get(reportConfig, 'table'), files = _.get(reportConfig, 'files');
            return forkJoin(this.reportService.downloadMultipleDataSources(updatedDataSource), this.getLatestSummary(reportId)).pipe(
              retry(1),
              map((apiResponse) => {
                const [data, reportSummary] = apiResponse;
                const result: any = Object.assign({});
                const chart = (charts && this.reportService.prepareChartData(charts, data, updatedDataSource,
                  _.get(reportConfig, 'reportLevelDataSourceId'))) || [];
                result['charts'] = chart;
                result['tables'] = (tables && this.reportService.prepareTableData(tables, data, _.get(reportConfig, 'downloadUrl'),
                  this.hash)) || [];
                result['reportMetaData'] = reportConfig;
                result['reportSummary'] = reportSummary;
                result['files'] = this.reportService.getParameterizedFiles(files || [], this.hash);
                result['lastUpdatedOn'] = this.reportService.getFormattedDate(this.reportService.getLatestLastModifiedOnDate(data));
                this.chartsReportData = JSON.parse(JSON.stringify(result));
                this.reportData = JSON.parse(JSON.stringify(result));
                return result;
              })
            );
          }
        })
      );
  }

  /**
   * @description Downloads csv file from azure blob storage
   * @param downloadUrl
   */
  public downloadCSV(downloadUrl?: string) {
    this.reportService.downloadReport(downloadUrl || this.downloadUrl).subscribe(
      result => {
        window.open(result, '_blank');
      }, err => {
        this.toasterService.error(this.resourceService.messages.emsg.m0076);
      }
    );
  }
  /**
   * @description sets downloadUrl for active tab
   * @param url
   */
  public setDownloadUrl(url) {
    this.downloadUrl = this.reportService.resolveParameterizedPath(url, this.hash ?
      this.reportService.getParameterFromHash(this.hash) : null);
  }

  public getTelemetryInteractEdata = ({ id = 'report-chart', type = 'click', pageid = this.activatedRoute.snapshot.data.telemetry.pageid,
    subtype = null }) => ({ id, type, pageid, ...subtype && { subtype } })

  public setTelemetryInteractObject(val?: string) {
    return {
      id: val || this.activatedRoute.snapshot.params.reportId,
      type: 'Report',
      ver: '1.0'
    };
  }

  public setTelemetryInteractEdata(val) {
    return {
      id: val,
      type: 'click',
      pageid: this.activatedRoute.snapshot.data.telemetry.pageid
    };
  }

  downloadReport(reportType) {
    this.reportExportInProgress = true;
    this.toggleHtmlVisibilty(true);
    setTimeout(() => {
      switch (_.toLower( _.get(reportType, 'value'))) {
        case 'img': {
          this.downloadReportAsImage();
          break;
        }
        case 'pdf': {
          this.downloadReportAsPdf();
          break;
        }
      }
      const telemetryObj = this.getTelemetryImpressionObj({ type: 'export-request', subtype: _.toLower( _.get(reportType, 'value')) });
      this.telemetryService.impression(telemetryObj);
    }, 1500);
  }


  private convertHTMLToCanvas(element, options) {
    return html2canvas(element, options);
  }

  private downloadReportAsPdf() {

    this.convertHTMLToCanvas(this.reportElement.nativeElement, {
      scrollX: 0,
      scrollY: -window.scrollY,
      scale: 2
    }).then(canvas => {
      const imageURL = canvas.toDataURL('image/jpeg');
      const pdf = new jspdf('p', 'px', 'a4');
      const pageWidth = pdf.internal.pageSize.getWidth();

      const imageHeight = (canvas.height * pageWidth) / canvas.width;
      pdf.internal.pageSize.setHeight(imageHeight);
      pdf.addImage(imageURL, 'JPEG', 10, 8, pageWidth - 28, imageHeight - 24);
      pdf.save('report.pdf');
      this.toggleHtmlVisibilty(false);
      this.reportExportInProgress = false;
    }).catch(err => {
      this.toggleHtmlVisibilty(false);
      this.reportExportInProgress = false;
    });
  }

  private downloadReportAsImage() {

    this.convertHTMLToCanvas(this.reportElement.nativeElement, {
      scrollX: 0,
      scrollY: -window.scrollY,
      scale: 2
    }).then(canvas => {
      const imageURL = canvas.toDataURL('image/jpeg');
      const anchorElement = document.createElement('a');
      anchorElement.href = imageURL.replace('image/jpeg', 'image/octet-stream');
      anchorElement.download = 'report.jpg';
      anchorElement.click();
      this.toggleHtmlVisibilty(false);
      this.reportExportInProgress = false;
    }).catch(err => {
      this.toggleHtmlVisibilty(false);
      this.reportExportInProgress = false;
    });
  }

  private toggleHtmlVisibilty(flag: boolean): void {
    this.hideElements = flag;
  }

  public openAddSummaryModal({ type, title, index = null, chartId = null,
    summary = null }: ISummaryObject): void {
    this.showSummaryModal = true;
    this.inputForSummaryModal = { title, type, index, chartId, summary };
  }

  public openReportSummaryModal(): void {
    this.openAddSummaryModal({
      title: (this.currentReportSummary != '' ? 'Update ' : 'Add ') + _.get(this.resourceService, 'frmelmnts.lbl.reportSummary'),
      type: 'report',
      ...(this._reportSummary && { summary: this._reportSummary })
    });
  }

  private getLatestSummary(reportId: string) {
    const hash = this.hash;
    return this.reportService.getLatestSummary({ reportId, hash }).pipe(
      map(reportSummary => {
        this._reportSummary = '';
        const summaries = this.currentReportSummary = _.map(reportSummary, summaryObj => {
          const summary = _.get(summaryObj, 'summary');
          this._reportSummary = summary;

          return {
            label: (this.currentReportSummary != '' ? 'Update ' : 'Add ') + _.get(this.resourceService, 'frmelmnts.lbl.reportSummary'),
            text: [summary],
            createdOn: _.get(summaryObj, 'createdon')
          };
        });
        return summaries;
      })
    );
  }

  public closeSummaryModal(): void {
    this.showSummaryModal = false;
  }

  public onAddSummary(event: ISummaryObject) {
    this.addSummaryBtnClickStream$.next(event);
  }

  public openConfirmationModal(eventType: 'publish' | 'retire') {
    const { confirmReportPublish, confirmRetirePublish } = _.get(this.resourceService, 'messages.imsg');
    this.confirmationPopupInput = {
      title: 'Confirm',
      body: eventType === 'publish' ? confirmReportPublish : confirmRetirePublish,
      event: eventType
    };
    this.showConfirmationModal = true;
  }

  private closeConfirmationModal() {
    this.showConfirmationModal = false;
  }

  public handleConfirmationEvent(event: boolean) {
    this.closeConfirmationModal();
    if (event) {
      switch (this.confirmationPopupInput.event) {
        case 'publish': {
          this.onPublish(event);
          break;
        }
        case 'retire': {
          this.onRetire(event);
          break;
        }
      }
    }
  }

  public onPublish(event) {
    this.publishBtnStream$.next(event);
  }

  public onRetire(event): void {
    this.retireBtnStream$.next(event);
  }

  private mergeClickEventStreams() {
    merge(this.handleAddSummaryStreams(), this.handlePublishBtnStream(), this.handleRetireBtnStream(),
      this.handleUpdatedMarkdown())
      .subscribe(res => {
        this.refreshComponent();
      }, err => {
        console.log({ err });
        this.toasterService.error(this.resourceService.messages.emsg.m0005);
      });
  }

  /**
  * @description handles click stream from add report and chart summary button
  * @private
  * @returns
  * @memberof ReportComponent
  */
  private handleAddSummaryStreams() {
    return this.addSummaryBtnClickStream$.pipe(
      mergeMap(event => {
        const { reportId } = this.activatedRoute.snapshot.params;
        event['hash'] = this.hash;
        this.closeSummaryModal();
        const cdata = [...(event['chartId'] ? [this.getCDataObj({ id: event['chartId'], type: 'Chart' })] : [])];
        this.logTelemetry({ type: 'select-submit', cdata, subtype: _.get(event, 'type') });
        return this.reportService.addReportSummary({
          reportId,
          summaryDetails: event
        });
      }),
      tap(res => {
        this.toasterService.info(this.resourceService.messages.imsg.reportSummaryAdded);
      })
    );
  }
  /**
   * @description refreshes the component to show updated data
   * @private
   * @memberof ReportComponent
   */
  private refreshComponent() {
    this.showComponent = false;
    setTimeout(() => {
      this.showComponent = true;
    });
  }

  /**
   * @description handles click stream from publish button
   * @private
   * @returns
   * @memberof ReportComponent
   */
  private handlePublishBtnStream() {
    return this.publishBtnStream$.pipe(
      switchMap(event => {
        const { reportId } = this.activatedRoute.snapshot.params;
        const hash = this.hash;
        return this.reportService.publishReport(reportId, hash);
      }),
      tap(res => {
        this.toasterService.info(this.resourceService.messages.imsg.reportPublished);
        this.report.status = 'live';
        if (this.materializedReport) {
          this.materializedReport = false;
          this.router.navigate(['.'], { relativeTo: this.activatedRoute, queryParams: {} });
        }
      })
    );
  }

  private handleRetireBtnStream() {
    return this.retireBtnStream$.pipe(
      switchMap(event => {
        const { reportId } = this.activatedRoute.snapshot.params;
        const hash = this.hash;
        return this.reportService.retireReport(reportId, hash);
      }),
      tap(res => {
        this.toasterService.info(this.resourceService.messages.imsg.reportRetired);
        this.report.status = 'retired';
        if (this.materializedReport) {
          this.materializedReport = false;
          this.router.navigate(['.'], { relativeTo: this.activatedRoute, queryParams: {} });
        }
      })
    );
  }

  public gotoListPage() {
    this.location.back();
  }

  public getParametersValueForDropDown(report?: object) {
    const { reportId } = this.activatedRoute.snapshot.params;
    return this.reportService.fetchReportById(reportId).pipe(
      pluck('reports'),
      switchMap(reports => {
        if (this.reportService.isUserSuperAdmin()) {
          return this.reportService.getMaterializedChildRows(reports).pipe(
            map(response => {
              const [reportObj] = response;
              return _.get(reportObj, 'children');
            })
          );
        } else {
          return of(_.map(_.get(reports[0], 'children') || [],
            child => ({ ...child, label: this.reportService.getParameterFromHash(child.hashed_val) })));
        }
      })
    );
  }

  public handleParameterChange(val) {
    const { reportId } = this.activatedRoute.snapshot.params;
    const { hashed_val, materialize = false } = _.get(val, 'value');
    this.router.navigate(['/dashBoard/reports', reportId, hashed_val], { queryParams: { ...materialize && { materialize } } }).then(() => {
      this.refreshComponent();
    });
  }

  public getCDataObj = ({ id, type }) => ({ id, type });

  private logTelemetry({ type, cdata = [], subtype = null }) {
    const interactData = {
      context: {
        env: _.get(this.activatedRoute.snapshot.data.telemetry, 'env') || 'reports',
        cdata: [...cdata, { id: _.get(this.reportService.getParameterValues('$slug'), 'value'), type: 'State' }]
      },
      edata: {
        ...this.getTelemetryInteractEdata({ type, subtype }),
      },
      object: {
        ...this.setTelemetryInteractObject(),
        rollup: {}
      }
    };
    this.telemetryService.interact(interactData);
  }

  public getTelemetryImpressionObj = ({ type, subtype = null }) => ({
    context: {
      env: this.activatedRoute.snapshot.data.telemetry.env
    },
    object: {
      id: this.activatedRoute.snapshot.params.reportId,
      type: 'Report',
      ver: '1.0'
    },
    edata: {
      type: type || this.activatedRoute.snapshot.data.telemetry.type,
      pageid: this.activatedRoute.snapshot.data.telemetry.pageid,
      uri: this.router.url,
      duration: this.navigationhelperService.getPageLoadTime(),
      ...(subtype && { subtype })
    }
  })

  private handleUpdatedMarkdown() {
    return this.markdownUpdated$.pipe(
      switchMap((event: { data: string, type: string }) => {
        const updatedReportConfig = {
          ...this.reportConfig,
          dataset: {
            ...this.reportConfig['dataset'],
            [event.type]: btoa(event.data)
          }
        };

        const { reportId } = this.activatedRoute.snapshot.params;
        return this.reportService.updateReport(reportId, {
          reportconfig: updatedReportConfig
        });
      })
    );
  }

  initLayout() {
    this.layoutConfiguration = this.layoutService.initlayoutConfig();
    this.layoutService.switchableLayout()
      .subscribe(layoutConfig => {
        if (layoutConfig != null) {
          this.layoutConfiguration = layoutConfig.layout;
        }
      });
  }

  getAllChartData() {
    const chartData = [];
    if (this.reportData.charts) {
      this.reportData.charts.map(chartInfo => {
        chartData.push({ id: chartInfo.chartConfig.id, data: chartInfo.chartData });
      });
    }
    return chartData;
  }

  getChartData(chart) {
    const chartInfo = this.chartsReportData.charts.find(data => {
      if (data['chartConfig']['id'] == chart['chartConfig']['id']) {
        return true;
      }
    });
    return chartInfo;
  }
  public filterChanged(data: any): void {
    if (this.chartsReportData && this.chartsReportData.charts) {
      this.chartsReportData.charts.map(element => {
        data.chartData.forEach(chart => {
          if (chart['id'] === element['chartConfig']['id']) {
            element.chartData = chart.data;
          }
        });
        return element;
      });
    }
    this.globalFilterChange = {
      chartData: data.chartData,
      filters: data.filters
    };
    this.cdr.detectChanges();
  }

  resetFilter() {
    this.resetFilters = { data: this.getAllChartData(), reset: true };
  }

  selectedTabChange(event) {

    const { type, downloadURL } = _.get(event, 'tab.textLabel');
    this.showExportsOption = ['chart', 'download'].includes(type);
    this.showResetFilter = ['chart'].includes(type);

    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();
      }
  });
}

  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 ? 'sbt-container relative9 sbt-fluid-content-bg':''">
  <div [appTelemetryImpression]="getTelemetryImpressionObj({type: 'page-request'})" #reportElement>
        <div class="reports-container w-100" *ngIf="showComponent">
          <ng-container *ngIf="(report$ | async) as currentReport else loading">
            <div [appTelemetryImpression]="getTelemetryImpressionObj({type: 'page-loaded'})">
              <div id="report-header" class="report__header">
                <div class="cc-player__content-header relative9 reports-content-header">
                  <div class="ui container py-16">
                    <div class="content-header__content p-10">
                      <div class="d-flex flex-dc flex-basis-1 mr-32 min-w-0 content-header__content__title">
                        <div class="content-header__title font-weight-bold text-left">
                          <div class="d-flex">
                            <div class="d-flex flex-dc flex-basis-4">
                              <span *ngIf="!hideElements"
                                class="relative position relative9 reports-back-btn my-0 pl-0 pr-10">
                                <span class="ui py-8 px-0">
                                  <button type="button"
                                    class="sb-btn sb-btn-link sb-btn-link-primary sb-left-icon-btn back-btn-new mb-5"
                                    aria-label="back-button" (click)="gotoListPage()" tabindex="0">
                                    <i 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></i>
                                  </button>
                                </span>
                              </span>
                            </div>
                  
                            <div *ngIf="!noResult">
                              <div class="report-title"> {{ ( report?.title || currentReport?.reportMetaData?.title ||
                                currentReport?.reportMetaData?.label ) | titlecase }}
                                <br />
                                <span *ngIf="hash && reportService.isUserReportAdmin()">
                                  ( {{reportService.getParameterFromHash(hash)}} )
                                </span>
                              </div>
                              <div *ngIf="!noResult">
                                <span
                                  [ngClass]="{'sb-label-primary-100': report.status === 'retired', 'label-success': report.status === 'live', 'label-warning': report.status === 'draft'}"
                                  *ngIf="isUserReportAdmin && !hideElements" class="px-0">
                                  <span *ngIf="report.status === 'live'" class="sb-live"></span>{{ report?.status |
                                  titlecase }}</span>

                                <span class="ml-auto sb-last-update-status fnormal sb-color-gray-400 px-10 last-update"
                                  *ngIf="currentReport?.lastUpdatedOn && type === 0">
                                  <span>{{resourceService?.frmelmnts?.lbl?.lastUpdatedOn}}&nbsp;: </span> &nbsp;
                                  {{currentReport?.lastUpdatedOn}}
                                </span>
                              </div>

                            </div>
                          </div>

                        </div>

                      </div>
                      <div *ngIf="isUserReportAdmin && !hideElements && !noResult"
                        class="d-flex flex-ai-end flex-w-wrap content-header__buttons">

                        <div
                          *ngIf="reportService.isUserReportAdmin() && report.parameters && report.parameters.length && !hideElements"
                          class="d-flex">
                          <div class="sb-field filter-drop mb-0 mr-8" *ngIf="getParametersValueForDropDown$ | async as options">
                            <mat-form-field appearance="fill" class="sb-mat__dropdown mr-8">
                              <mat-label>Select Parameter</mat-label>
                              <mat-select role="listbox" aria-label="Select Parameter" [(value)]="selectedLanguage" class="selection"
                                (selectionChange)="handleParameterChange($event)">
                                <mat-option class="mat-dropdown__options" role="option"
                                  *ngFor="let option of getParametersValueForDropDown$ | async as options" [value]="option"
                                  attr.aria-label="{{option.label}}">{{option.label}}</mat-option>
                              </mat-select>
                            </mat-form-field>
                          </div>
                        </div>

                        <button *ngIf="type === 0" appTelemetryInteract
                          [telemetryInteractObject]="setTelemetryInteractObject()"
                          [telemetryInteractEdata]="getTelemetryInteractEdata({type: 'report-summary'})"
                          (click)="openReportSummaryModal()" tabindex="0" type="button"
                          class="sb-btn sb-btn-normal sb-btn-outline-primary mr-8">
                          <i class="blue plus alternate icon"></i>
                          {{ this.currentReportSummary !='' ? 'Update' : 'Add' }} {{
                          resourceService.frmelmnts.lbl.reportSummary }}
                        </button>
                        <button appTelemetryInteract [telemetryInteractObject]="setTelemetryInteractObject()"
                          [telemetryInteractCdata]="[getCDataObj({id: '' + currentReport?.charts?.length || '0', type: 'CountCharts'}),
                          getCDataObj({id: reportService.getParameterValues('$slug').value, type: 'State'})]"
                          [telemetryInteractEdata]="getTelemetryInteractEdata({type: 'select-retire'})"
                          (click)="openConfirmationModal('retire')" tabindex="0"
                          *ngIf="report?.status !== 'retired' && !(type === 1 && !reportService?.isUserSuperAdmin())"
                          type="button" class="sb-btn sb-btn-normal sb-btn-outline-primary mr-8">
                          <i class="white minus alternate icon"></i>
                          {{report?.status === 'live' ? 'Retire' : 'Discard'}}
                        </button>
                        <button appTelemetryInteract [telemetryInteractObject]="setTelemetryInteractObject()"
                          [telemetryInteractCdata]="[getCDataObj({id: '' + currentReport?.charts?.length || '0', type: 'CountCharts'}),
                          getCDataObj({id: reportService.getParameterValues('$slug').value, type: 'State'})]"
                          [telemetryInteractEdata]="getTelemetryInteractEdata({type: 'select-publish'})"
                          (click)="openConfirmationModal('publish')" tabindex="0"
                          *ngIf="report?.status === 'draft' && !(type === 1 && !reportService?.isUserSuperAdmin())"
                          type="button" class="sb-btn sb-btn-normal sb-btn-primary mr-8">
                          <i class="white check alternate icon"></i> Publish
                        </button>
                      </div>
                    </div>
                    <p class="report-description py-15 pl-10"
                      *ngIf="(report?.description || currentReport?.reportMetaData?.description ) && !noResult"
                      [innerHTML]="reportService.transformHTML(report?.description || currentReport.reportMetaData.description)">
                    </p>
                  </div>
                </div>
              </div>

              <div class="ui container" *ngIf="!noResult">
                <div class="twelve wide column">
                  <div *ngIf="type === 1">
                    <app-dataset [markdownUpdated$]="markdownUpdated$" [dataset]="report?.reportconfig?.dataset">
                    </app-dataset>
                  </div>
                  <div id="report-body" class="my-16" *ngIf="type === 0">
                    <mat-tab-group (selectedTabChange)="selectedTabChange($event)"
                      class="sb-mat__tab sb-mat__tab--tabinacc">
                      <mat-tab [label]="{'type': 'chart', 'downloadURL': currentReport?.reportMetaData?.downloadUrl}"
                        appTelemetryInteract
                        [telemetryInteractObject]="setTelemetryInteractObject(currentReport.reportMetaData.id)"
                        [telemetryInteractEdata]="setTelemetryInteractEdata('report-graph')">
                        <ng-template mat-tab-label>
                          <span>{{resourceService?.frmelmnts?.lbl?.graphs}}</span>
                        </ng-template>
                        <ng-container *ngTemplateOutlet="commonReportActions">
                        </ng-container>
                        <div class="global-filter px-20 pb-10 d-flex" *ngIf=" currentReport?.reportMetaData?.filters">
                          <div class="d-flex flex-dc flex-basis-1">
                            <app-filter [filterType]="filterType" [resetFilters]="resetFilters"
                              [hideElements]="hideElements" [selectedFilter]="selectedFilters"
                              [filters]="currentReport.reportMetaData.filters" (filterChanged)="filterChanged($event)"
                              [chartData]="getAllChartData(currentReport)"
                              [telemetryInteractObject]="telemetryInteractObject">
                            </app-filter>
                          </div>
                        </div>
                        <div class="ui bottom p-0 b-0 no-bg my-24">
                          <div class="sb-graph-section p-24 my-24"
                            *ngFor="let chart of currentReport.charts; let i = index; let l = last;">
                            <app-map *ngIf="chart?.chartConfig?.chartType === 'map'" [mapData]="chart?.mapData"
                              [options]="chart?.chartConfig?.options">
                            </app-map>
                            <app-data-chart [globalFilter]="globalFilterChange"
                              *ngIf="chart?.chartConfig?.chartType !== 'map' && showChart"
                              [telemetryInteractObject]="setTelemetryInteractObject()" [chartInfo]="getChartData(chart)"
                              [hideElements]="hideElements" [isUserReportAdmin]="isUserReportAdmin"
                              (openAddSummaryModal)="openAddSummaryModal($event)" [hash]="hash">
                            </app-data-chart>
                          </div>
                          <div class="ui warning message" *ngIf="!currentReport.charts.length">
                            {{resourceService?.frmelmnts?.lbl?.graphNotAvailable}}
                          </div>
                        </div>
                      </mat-tab>
                      <mat-tab *ngFor="let table of currentReport.tables"
                        [label]="{'type': 'table', 'downloadURL': table?.downloadUrl}" appTelemetryInteract
                        [telemetryInteractObject]="setTelemetryInteractObject(currentReport.reportMetaData.id)"
                        [telemetryInteractEdata]="setTelemetryInteractEdata('report_table_'+table.name)">
                        <ng-template mat-tab-label>
                          <span>{{table?.name}}</span>
                        </ng-template>
                        <ng-template matTabContent>

                          <div *ngIf="table.data && table.config">
                            <app-sb-table [config]="table.config" [rowsData]="table.data">
                            </app-sb-table>
                          </div>
                          <div *ngIf="table.data && !table.config">
                            <ng-container  *ngTemplateOutlet="commonReportActions">
                            </ng-container>
                            <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>
                        </ng-template>
                      </mat-tab>
                      <mat-tab *ngIf="currentReport?.files?.length"
                        [label]="{'type': 'download', 'downloadURL': currentReport?.reportMetaData?.downloadUrl}"
                        appTelemetryInteract [telemetryInteractObject]="setTelemetryInteractObject()"
                        [telemetryInteractEdata]="getTelemetryInteractEdata({type: 'download'})">

                        <ng-template mat-tab-label>
                          <span>{{resourceService?.frmelmnts?.lbl?.dashboard?.download}}</span>
                        </ng-template>

                        <ng-container *ngTemplateOutlet="commonReportActions">
                        </ng-container>
                        <div class="files-block p-20">
                          <table *ngIf="currentReport?.files?.length" id="downloadTable"
                            class="sb-table sb-table-striped sb-table-sortable sb-table-fixed" cellspacing="0">
                            <thead class="sb-table-header sb-table-thead-gray">
                              <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 currentReport.files; let i = index; let l = last;">
                                <td *ngIf="file.name">
                                  {{file.name}}
                                </td>
                                <td *ngIf="!file.name">
                                  --
                                </td>
                                <td *ngIf="file.description">
                                  {{file.description}}
                                </td>
                                <td *ngIf="!file.description">
                                  --
                                </td>
                                <td *ngIf="file.fileSize">
                                  {{file.fileSize}}
                                </td>
                                <td *ngIf="!file.fileSize">
                                  --
                                </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)">
                                    {{resourceService?.frmelmnts?.lbl?.dashboard?.downloadfile}}</button>
                                </td>
                            </tbody>
                          </table>
                          <div class="ui warning message" *ngIf="!currentReport.files.length">
                            File Not Available
                          </div>
                        </div>
                      </mat-tab>
                    </mat-tab-group>
                  </div>
                  <div class="report__summary" id="report-summary" class="my-16"
                    *ngIf="currentReportSummary && currentReportSummary.length && type === 0">
                    <app-report-summary [inputData]="currentReportSummary"></app-report-summary>
                  </div>
                </div>
              </div>
            </div>
            <div *ngIf="noResult">
              <app-no-result [data]="noResultMessage"></app-no-result>
            </div>
          </ng-container>
          <ng-template #loading>
            <div class="ui container">
              <div class="nine wide column workspacesegment">
                <app-loader></app-loader>
              </div>
            </div>
          </ng-template>
        </div>
  </div>
</div>
<div>
  <app-tnc-popup [showAcceptTnc]="showTncPopup" [reportViewerTncVersion]="reportViewerTncVersion" [tncUrl]="reportViewerTncUrl" #termsAndCondPopUp *ngIf="showTncPopup">
  </app-tnc-popup>
</div>
<app-modal-wrapper *ngIf="reportExportInProgress" [config]="{disableClose: true}" (dismiss)="close.emit()">
  <ng-template sbModalContent>
    <div class="sb-modal sb-hawkeye-modal">
      <div class="transition ui dimmer page modals active visible">
        <div class="ui modal transition active visible normal">
          <div class="sb-modal-content o-y-visible">
            <div class="ui">
              <div class="twelve wide column px-0 mb-30">
                <app-loader [data]="{loaderMessage: 'Report generation is in Progress. Please wait...'}"></app-loader>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </ng-template>
</app-modal-wrapper>

<app-confirm-popup *ngIf="showConfirmationModal" (confirmation)="handleConfirmationEvent($event)"
  [input]="confirmationPopupInput">
</app-confirm-popup>

<app-modal-wrapper [config]="{disableClose: true, size: 'large', panelClass: 'material-modal'}" *ngIf="showSummaryModal">
  <ng-template sbModalContent let-data>
    <app-add-summary-modal (closeModalEvent)="closeSummaryModal()" [input]="inputForSummaryModal"
      (submitButtonEvent)="onAddSummary($event)">
    </app-add-summary-modal>
  </ng-template>
</app-modal-wrapper>

<ng-template #commonReportActions>
  <div class="d-flex my-0" *ngIf="!hideElements">
    <div class="d-flex flex-dc flex-basis-1 mr-32 min-w-0">
      <h4 class="select-filter-label"
        *ngIf="showExportsOption && reportData?.reportMetaData?.filters && showResetFilter"> {{
        resourceService?.frmelmnts?.lbl?.selectFilters }} <small> {{
          resourceService?.frmelmnts?.lbl?.selectFilterDescription }} </small> </h4>
    </div>
    <div class="d-flex flex-ai-center flex-jc-flex-end pr-10"
      *ngIf="reportData?.reportMetaData?.filters && showResetFilter">
      <button class="sb-btn sb-btn-normal sb-btn-outline-primary  reset-filter" (click)="resetFilter()" tabindex="0">
        {{resourceService?.frmelmnts?.btn?.reset}} {{resourceService?.frmelmnts?.lbl?.filters }}
      </button>
    </div>
    <div class="d-flex flex-ai-center flex-jc-flex-end" >
      <button appTelemetryInteract [telemetryInteractObject]="setTelemetryInteractObject()"
        [telemetryInteractEdata]="getTelemetryInteractEdata({type: 'download'})" type="button"
        *ngIf="reportData?.reportMetaData?.downloadUrl && !reportData?.files?.length"
        class="sb-left-icon-btn sb-btn sb-btn-primary sb-btn-normal mr-8" (click)="downloadCSV()" tabindex="0"><i
          class="download icon"></i>
        {{resourceService?.frmelmnts?.lbl?.downloadCsv}}</button>
      <div class="sb-field mb-0 mr-8 d-flex flex-jc-flex-end">
        <label>
          <mat-form-field appearance="fill" class="sb-mat__dropdown mr-12" [ngClass]="{'ml-auto': !reportData?.reportMetaData?.downloadUrl}">
            <mat-label>Export As</mat-label>
            <mat-select role="listbox" aria-label="Export As" [(value)]="selectedLanguage" class="selection"
              (selectionChange)="downloadReport($event)">
              <mat-option class="mat-dropdown__options" role="option" *ngFor="let option of exportOptions" [value]="option"
              appTelemetryInteract [telemetryInteractObject]="setTelemetryInteractObject()" [telemetryInteractEdata]="getTelemetryInteractEdata({type: 'export-chart', subtype: option})" 
              attr.aria-label="{{option}}">{{option}}</mat-option>
            </mat-select>
          </mat-form-field>
        </label>
      </div>
    </div>
  </div>
</ng-template>

./report.component.scss

@use "@project-sunbird/sb-styles/assets/mixins/mixins"as *;
@use 'pages/content-header'as *;
@use 'pages/reports'as *;

.sb-graph-section {
  background: var(--sb-graph-section-bg);
}

.report-description {
  margin-right: calculateRem(0px) !important;
}

.sb-graph-section.global-filter {
  background-color: var(--sbt-compt-bg) !important;
}

.select-filter-label {
  padding-left: calculateRem(20px);
  font-size: calculateRem(17px);
}

.sbt-report-btns-panel-new {
  border-radius: 0px !important;
  background: var(--sbt-body-bg) !important;
}

.label-success {
  color: var(--success-color);
  padding-left: calculateRem(10px);
  padding-right: calculateRem(10px);
  font-size: calculateRem(14px);
  font-weight: 300;
}

.sb-label-primary-100 {
  background: none !important;
  font-size: calculateRem(14px) !important;

}

.label-warning {
  color: var(--accessibility-red);
  padding-left: calculateRem(10px);
  padding-right: calculateRem(10px);
  font-size: calculateRem(14px);
  font-weight: 300;
}

.sbt-container {
  .reports-container {
    padding-top: calculateRem(16px);
  }

  .reports-content-header {
    border-radius: calculateRem(24px) !important;
  }
}

.reports-content-header {
  background: var(--primary-0);
  box-shadow: var(--sbt-box-shadow-3px);
}

.table-view {
  background: var(--sbt-body-bg) !important;
}

.reset-filter {
  padding-left: calculateRem(20px) !important;
  padding-right: calculateRem(20px) !important;
}

::ng-deep {
  .mat-checkbox-layout .mat-checkbox-label {
    white-space: normal !important;
  }

  .mat-checkbox-inner-container {
    top: 0.25rem !important;
    margin: inherit !important;
    margin-right: 0.5rem !important;
  }
}

.files-block {
  background: var(--sbt-body-bg) !important;
  margin: 0px !important;
  border-radius: 0px 0px calculateRem(24px) calculateRem(24px) !important;
  box-shadow: none;
  border-top: calculateRem(1px) solid var(--gray-100);
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""