File

src/app/modules/program-dashboard/components/program-datasets/program-datasets.component.ts

Implements

OnInit OnDestroy

Metadata

Index

Properties
Methods

Constructor

constructor(activatedRoute: ActivatedRoute, layoutService: LayoutService, telemetryService: TelemetryService, resourceService: ResourceService, kendraService: KendraService, userService: UserService, onDemandReportService: OnDemandReportService, config: ConfigService, toasterService: ToasterService, formService: FormService, router: Router, location: Location, reportService: ReportService)
Parameters :
Name Type Optional
activatedRoute ActivatedRoute No
layoutService LayoutService No
telemetryService TelemetryService No
resourceService ResourceService No
kendraService KendraService No
userService UserService No
onDemandReportService OnDemandReportService No
config ConfigService No
toasterService ToasterService No
formService FormService No
router Router No
location Location No
reportService ReportService No

Methods

addFilters
addFilters()
Returns : void
blockChanged
blockChanged($event)
Parameters :
Name Optional
$event No
Returns : void
checkStatus
checkStatus()
Returns : boolean
Private closeConfirmationModal
closeConfirmationModal()
Returns : void
Public closeConfirmModal
closeConfirmModal()
Returns : void
closeDashboard
closeDashboard()
Returns : void
Public closeModal
closeModal()
Returns : void
confirm
confirm()
Returns : void
Private convertHTMLToCanvas
convertHTMLToCanvas(element, options)
Parameters :
Name Optional
element No
options No
Returns : any
Public csvRequest
csvRequest()
Returns : void
dataFilterQuery
dataFilterQuery(filterKeysObj, keys)
Parameters :
Name Optional
filterKeysObj No
keys No
Returns : void
dataModification
dataModification(row)
Parameters :
Name Optional
row No
Returns : any
dateChanged
dateChanged($event, type)
Parameters :
Name Optional
$event No
type No
Returns : void
dependentFilterMsg
dependentFilterMsg()
Returns : void
districtSelection
districtSelection($event)
Parameters :
Name Optional
$event No
Returns : void
downloadReport
downloadReport(reportType)
Parameters :
Name Optional
reportType No
Returns : void
downloadReportAsImage
downloadReportAsImage()
Returns : void
downloadReportAsPdf
downloadReportAsPdf()
Returns : void
fetchConfig
fetchConfig(filters)
Parameters :
Name Optional
filters No
Returns : Observable<any>
getDataSourceById
getDataSourceById(dataSources: literal type[], id: string)
Parameters :
Name Type Optional Default value
dataSources literal type[] No
id string No 'default'
Returns : any
getDistritAndOrganisationList
getDistritAndOrganisationList(requestBody: ResourceAPIRequestBody)
Parameters :
Name Type Optional
requestBody ResourceAPIRequestBody No
Returns : void
Public getFormDetails
getFormDetails()
Returns : void
getProgramsList
getProgramsList()
Returns : void
Public getReportTypes
getReportTypes(programId, solutionType)
Parameters :
Name Optional
programId No
solutionType No
Returns : void
getSolutionList
getSolutionList(program)
Parameters :
Name Optional
program No
Returns : void
getTableData
getTableData(data: literal type[], tableId)
Parameters :
Name Type Optional
data literal type[] No
tableId No
Returns : any
Public getUpdatedParameterizedPath
getUpdatedParameterizedPath(dataSources)
Parameters :
Name Optional
dataSources No
Returns : any
goBack
goBack()
Returns : void
Public handleConfirmationEvent
handleConfirmationEvent(event: boolean)
Parameters :
Name Type Optional
event boolean No
Returns : void
hashTheTag
hashTheTag(key: string)
Parameters :
Name Type Optional
key string No
Returns : string
initLayout
initLayout()
Returns : void
loadReports
loadReports()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
onDownloadLinkFail
onDownloadLinkFail(data)
Parameters :
Name Optional
data No
Returns : void
organisationSelection
organisationSelection($event)
Parameters :
Name Optional
$event No
Returns : void
pdFilterChanged
pdFilterChanged($event)
Parameters :
Name Optional
$event No
Returns : void
prepareTableData
prepareTableData(tablesArray: any, data: any, downloadUrl: string)
Parameters :
Name Type Optional
tablesArray any No
data any No
downloadUrl string No
Public programSelection
programSelection($event)
Parameters :
Name Optional
$event No
Returns : void
renderReport
renderReport(reportId)
Parameters :
Name Optional
reportId No
Returns : Observable<any>
reportChanged
reportChanged(selectedReportData)
Parameters :
Name Optional
selectedReportData No
Returns : void
Public requestDataset
requestDataset()
Returns : void
resetConfigFilters
resetConfigFilters()
Returns : void
Public resetFilter
resetFilter()
Returns : void
Public resolveParameterizedPath
resolveParameterizedPath(path: string, explicitValue?: string)
Parameters :
Name Type Optional
path string No
explicitValue string Yes
Returns : string
selectedTabChange
selectedTabChange(event)
Parameters :
Name Optional
event No
Returns : void
Public selectSolution
selectSolution($event)
Parameters :
Name Optional
$event No
Returns : void
submitRequest
submitRequest()
Returns : void
timeRangeInit
timeRangeInit()
Returns : void
Private toggleHtmlVisibilty
toggleHtmlVisibilty(flag: boolean)
Parameters :
Name Type Optional
flag boolean No
Returns : void

Properties

Public activatedRoute
Type : ActivatedRoute
appliedFilters
Type : object
Default value : {}
awaitPopUp
Default value : false
blocks
Type : object[]
Default value : []
chartsReportData
Type : any
Public columns
Type : []
Default value : [ { name: 'Report type', isSortable: true, prop: 'datasetConfig.title', placeholder: 'Filter report type' }, { name: 'Request date', isSortable: true, prop: 'jobStats.dtJobSubmitted', placeholder: 'Filter request date', type: 'date' }, { name: 'Status', isSortable: false, prop: 'status', placeholder: 'Filter status' }, { name: 'Report link', isSortable: false, prop: 'downloadUrls', placeholder: 'Filter download link' }, { name: 'Generated date', isSortable: true, prop: 'jobStats.dtJobCompleted', placeholder: 'Filter generated date', type: 'dateTime' }, ]
config
configuredFilters
Type : any
Default value : {}
Public dashboardReport$
displayFilters
Type : any
Default value : {}
districts
Type : any
downloadCSV
Default value : true
errorMessage
Default value : this.resourceService?.frmelmnts?.lbl?.resourceSelect
exportOptions
Type : []
Default value : ['Pdf', 'Img']
filter
Type : any
Default value : []
formData
Type : Object
Public formService
Type : FormService
globalDistrict
Type : any
globalOrg
Type : any
goToPrevLocation
Type : boolean
Default value : true
hashedTag
hideElements
Type : boolean
Default value : false
hideTableToCsv
Type : boolean
Default value : true
instance
Type : string
isColumnsSearchable
Default value : false
Public isProcessed
Default value : false
Public kendraService
Type : KendraService
layoutConfiguration
Type : any
Public layoutService
Type : LayoutService
loadash
Default value : _
Public location
Type : Location
maxEndDate
Type : any
maxStartDate
Type : any
Public message
Default value : this.resourceService?.frmelmnts?.msg?.noDataDisplayed
minEndDate
Type : any
modal
Decorators :
@ViewChild('modal', {static: false})
newData
Type : boolean
Default value : false
Public noResult
Type : boolean
Public noResultMessage
Type : INoResultMessage
oldProgram
Public onDemandReportData
Type : []
Default value : []
Public onDemandReportService
Type : OnDemandReportService
organisations
Type : any
Default value : []
passwordForm
Default value : new UntypedFormGroup({ password: new UntypedFormControl('', [Validators.minLength(8), Validators.required, Validators.pattern('^(?=.*[0-9])(?=.*[a-zA-Z])([a-zA-Z0-9]+)$')]) })
pdFilters
Type : ConfigFilter[]
Default value : []
popup
Default value : false
programs
Type : []
Default value : []
programSelected
Type : any
reportConfig
Type : any
Public reportExportInProgress
Default value : false
reportForm
Default value : new UntypedFormGroup({ programName: new UntypedFormControl('', [Validators.required]), solution: new UntypedFormControl(), reportType: new UntypedFormControl('', [Validators.required]), districtName: new UntypedFormControl(), organisationName: new UntypedFormControl(), startDate: new UntypedFormControl(), endDate: new UntypedFormControl(), blockName:new UntypedFormControl() })
reportSection
Decorators :
@ViewChild('reportSection')
Public reportService
Type : ReportService
reportStatus
Type : object
Default value : { 'submitted': 'SUBMITTED', 'processing': 'PROCESSING', 'failed': 'FAILED', 'success': 'SUCCESS', }
reportTypes
Type : []
Default value : []
Public resourceService
Type : ResourceService
Public router
Type : Router
Public selectedReport
Public selectedSolution
Type : string
Public showConfirmationModal
Default value : false
showErrorForGraphs
Type : boolean
Default value : false
showPopUpModal
Type : boolean
solutions
Type : []
Default value : []
solutionSelected
Type : any
solutionType
Type : any
tabIndex
Type : number
Default value : 0
tableToCsv
Type : boolean
tag
Type : string
Public telemetryService
Type : TelemetryService
Public toasterService
Type : ToasterService
Public unsubscribe$
Default value : new Subject<void>()
Public userAccess
Type : boolean
userDataSubscription
Type : Subscription
Public userId
Type : string
userProfile
Type : IUserProfile

Reference of User Profile interface

Public userRoles
Type : Array<string>
Default value : []

all user role

Public userService
Type : UserService
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { INoResultMessage, ToasterService, IUserData, IUserProfile, LayoutService, ResourceService, ConfigService, OnDemandReportService } from '@sunbird/shared';
import { TelemetryService } from '@sunbird/telemetry';
import { Subject, Subscription, throwError ,Observable, of, combineLatest, queueScheduler} from 'rxjs';
import { KendraService, UserService, FormService } from '@sunbird/core';
import { mergeMap, switchMap, takeUntil,map, catchError} from 'rxjs/operators';
import { ActivatedRoute, Router } from '@angular/router';
import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms';
import * as _ from 'lodash-es';
import { Location } from '@angular/common';
import { ReportService } from '../../../dashboard/services';
import dayjs from 'dayjs';
import html2canvas from 'html2canvas';
import * as jspdf from 'jspdf';
import { Md5 } from 'ts-md5';
import { HttpErrorResponse } from '@angular/common/http';

const PRE_DEFINED_PARAMETERS = ['$slug', 'hawk-eye'];
export interface ConfigFilter{
    label: string,
    controlType: string,
    reference: string,
    defaultValue: number
}
export interface ResourceAPIRequestBody{
  type:string,
  id:string,
  projection:string,
  solutionType?:string,
  districtLocationId?:string
}
@Component({
  selector: 'app-datasets',
  templateUrl: './program-datasets.component.html',
  styleUrls: ['./program-datasets.component.scss'],
})
export class DatasetsComponent implements OnInit, OnDestroy {
  public activatedRoute: ActivatedRoute;
  public showConfirmationModal = false;
  public dashboardReport$;
  public noResultMessage: INoResultMessage;
  public noResult: boolean;
  showPopUpModal: boolean;
  config;
  reportTypes = [];
  programs = [];
  solutions = [];
  public message = this.resourceService?.frmelmnts?.msg?.noDataDisplayed;
  instance: string;
  @ViewChild('reportSection') reportSection;
  public reportExportInProgress = false;
  @ViewChild('modal', { static: false }) modal;
  popup = false;
  awaitPopUp = false;
  reportStatus = {
    'submitted': 'SUBMITTED',
    'processing': 'PROCESSING',
    'failed': 'FAILED',
    'success': 'SUCCESS',
  };

  public isProcessed = false;
  formData: Object;
  public columns = [
    { name: 'Report type', isSortable: true, prop: 'datasetConfig.title', placeholder: 'Filter report type' },
    { name: 'Request date', isSortable: true, prop: 'jobStats.dtJobSubmitted', placeholder: 'Filter request date', type: 'date' },
    { name: 'Status', isSortable: false, prop: 'status', placeholder: 'Filter status' },
    { name: 'Report link', isSortable: false, prop: 'downloadUrls', placeholder: 'Filter download link' },
    { name: 'Generated date', isSortable: true, prop: 'jobStats.dtJobCompleted', placeholder: 'Filter generated date', type: 'dateTime' },
  ];

  public onDemandReportData = [];

  downloadCSV = true;
  isColumnsSearchable = false;
  tag: string;

  reportForm = new UntypedFormGroup({
    programName: new UntypedFormControl('', [Validators.required]),
    solution: new UntypedFormControl(),
    reportType: new UntypedFormControl('', [Validators.required]),
    districtName: new UntypedFormControl(),
    organisationName: new UntypedFormControl(),
    startDate: new UntypedFormControl(),
    endDate: new UntypedFormControl(),
    blockName:new UntypedFormControl()
  });

  passwordForm = new UntypedFormGroup({
    password: new UntypedFormControl('', [Validators.minLength(8), Validators.required, Validators.pattern('^(?=.*[0-9])(?=.*[a-zA-Z])([a-zA-Z0-9]+)$')])
  });
  programSelected: any;
  solutionSelected: any;
  districts: any;
  organisations: any = [];
  filter: any = [];
  newData: boolean = false;
  goToPrevLocation: boolean = true;
  reportConfig: any;
  chartsReportData: any;
  exportOptions = ['Pdf', 'Img'];
  hideElements: boolean = false;
  globalDistrict: any;
  globalOrg: any;
  tabIndex: number = 0;
  tableToCsv: boolean;
  hideTableToCsv:boolean = true;
  minEndDate: any;  //Min end date - has to be one more than start date 
  maxEndDate: any;  //Max end date -  current date has to be max
  maxStartDate: any; //Start date - has to be one day less than end date
  displayFilters:any = {};
  loadash = _;
  pdFilters:ConfigFilter[] = [];
  configuredFilters:any = {};
  appliedFilters:object = {};
  blocks:object[] = [];
  errorMessage = this.resourceService?.frmelmnts?.lbl?.resourceSelect;
  solutionType: any;
  showErrorForGraphs: boolean = false;
  constructor(
    activatedRoute: ActivatedRoute,
    public layoutService: LayoutService,
    public telemetryService: TelemetryService,
    public resourceService: ResourceService,
    public kendraService: KendraService,
    public userService: UserService,
    public onDemandReportService: OnDemandReportService,
    config: ConfigService,
    public toasterService: ToasterService,
    public formService: FormService,
    public router: Router,
    public location: Location,
    public reportService: ReportService
  ) {
    this.config = config;
    this.activatedRoute = activatedRoute;
  }

  layoutConfiguration: any;
  public unsubscribe$ = new Subject<void>();
  userDataSubscription: Subscription;
  /**
   * Reference of User Profile interface
   */
  userProfile: IUserProfile;
  /**
   * all user role
   */
  public userRoles: Array<string> = [];
  public userId: string;
  public selectedReport;
  public selectedSolution: string;
  public userAccess:boolean;
  hashedTag;
  oldProgram;
  getProgramsList() {
    const paramOptions = {
      url:
        this.config.urlConFig.URLS.KENDRA.PROGRAMS_BY_PLATFORM_ROLES + '?role=' + this.userRoles.toString()
    };
    this.kendraService.get(paramOptions).pipe(takeUntil(this.unsubscribe$)).subscribe(data => {
      if (data && data.result) {
        this.programs = data.result;
      }
    }, error => {
      this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
    });

  }

  getSolutionList(program) {

    const paramOptions = {
      url:
        this.config.urlConFig.URLS.KENDRA.SOLUTIONS_BY_PROGRAMID + '/' + program._id + '?role=' + program.role[0]
    };
    this.kendraService.get(paramOptions).pipe(takeUntil(this.unsubscribe$)).subscribe(data => {
      if (data && data.result) {
        this.solutions = data.result;
      }
    }, error => {
      this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
    });

  }

  getDistritAndOrganisationList(requestBody:ResourceAPIRequestBody) {

    const paramOptions = {
      url:
        this.config.urlConFig.URLS.KENDRA.DISTRICTS_AND_ORGANISATIONS+`?resourceType=${requestBody.type}&resourceId=${requestBody.id}`,
      data: {
        projection: requestBody.projection,
        ...(requestBody.solutionType) && {solutionType:requestBody.solutionType},
        ...(requestBody.districtLocationId) && {query : {districtLocationId:requestBody.districtLocationId}},
        programId:  _.get(this.reportForm, 'controls.programName.value')
      }
    };

    this.kendraService.post(paramOptions).pipe(takeUntil(this.unsubscribe$)).subscribe(data => {
      if (data && Object.keys(data.result).length) {
        const processData = (result) => {
          if (result) {
            return result.filter(data => data?.name !== null);
          }
          return []
        };
        
       if(requestBody.projection !== 'block'){
        this.organisations = processData(data.result.organisations);
        this.districts = processData(data.result.districts);
       }
        this.blocks = processData(data.result.block);     
      }
    }, error => {
      this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
    });

  }

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

  ngOnInit() {
    this.showPopUpModal = true;
    this.instance = _.upperCase(this.resourceService.instance || 'SUNBIRD');
    this.userDataSubscription = this.userService.userData$.subscribe(
      (user: IUserData) => {
        if (user && !user.err) {
          this.userProfile = user.userProfile;
          this.userRoles = user.userProfile.userRoles;
          this.userId = user.userProfile.id;

        }
      });
    this.initLayout();
    this.getProgramsList();
    this.getFormDetails();
    this.timeRangeInit();
  }

  timeRangeInit() {
    const currentYear = new Date().getFullYear();
    const currentMonth = new Date().getMonth();
    const today = new Date().getDate();
    this.minEndDate = new Date(currentYear - 100, 0, 1);
    this.maxEndDate = new Date(currentYear + 0, currentMonth, today);
    this.maxStartDate = new Date(currentYear + 0, currentMonth, today - 1);
  }

  public resolveParameterizedPath(path: string, explicitValue?: string): string {
    return _.reduce(PRE_DEFINED_PARAMETERS, (result: string, parameter: string) => {
      if (_.includes(result, parameter)) {
        result = _.replace(result, parameter, explicitValue);
      }
      return result;
    }, path);
  }

  public getUpdatedParameterizedPath(dataSources) {
    const explicitValue = !this.reportForm.controls.solution.value ? _.get(this.reportForm, 'controls.programName.value') : _.get(this.reportForm, 'controls.solution.value')
    return _.map(dataSources, (dataSource) => ({
      id: dataSource.id,
      path: this.resolveParameterizedPath(dataSource.path, explicitValue)
    }));
  }
  
  selectedTabChange(event) {
    this.tabIndex = event.index;
  }

  public programSelection($event) {
    this.reportForm.reset();
    this.displayFilters = {};
    const program = this.programs.filter(data => {
      if (data._id == $event.value) {
        return data;
      }
    });
    this.solutions = [];
    this.reportTypes = [];
    this.onDemandReportData = [];
    this.resetConfigFilters();
    this.getSolutionList(program[0]);
    this.displayFilters['Program'] = [program[0].name]
    this.reportForm.controls.programName.setValue($event.value);
    this.appliedFilters = {};
    this.districts = this.organisations = this.blocks = [];
    this.errorMessage = this.resourceService?.frmelmnts?.lbl?.resourceSelect;
    this.getReportTypes($event.value,'user_detail_report');
    this.oldProgram = !_.has(program[0],'requestForPIIConsent')
    this.userAccess = this.reportTypes.length > 0 && _.has(program[0],'requestForPIIConsent');
    if(this.userAccess){
      this.tag = program[0]._id + '_' + this.userId;
      this.hashedTag = this.hashTheTag(this.tag)
      this.loadReports();
    }
    this.newData = !this.userAccess;
    this.showErrorForGraphs = false;
    const requestBody:ResourceAPIRequestBody= {
      type:'program',
      id:$event.value,
      projection:'district'
    }
    this.getDistritAndOrganisationList(requestBody);
  }

  public selectSolution($event) {
    this.newData = false;
    this.showErrorForGraphs = false;
    this.noResult = false;
    this.districts = this.organisations = []
    this.userAccess = true;
    this.resetConfigFilters();
    delete this.displayFilters['District'];
    delete this.displayFilters['Organisation'];
    this.errorMessage = this.resourceService?.frmelmnts?.lbl?.resourceSelect;
    this.appliedFilters = {}
    if (this.programSelected && this.reportForm.value && this.reportForm.value['solution']) {
      const solution = this.solutions.filter(data => {
        if (data._id == $event.value) {
          return data;
        }
      });
      this.tag = solution[0]._id + '_' + this.userId;
      this.hashedTag = this.hashTheTag(this.tag)
      this.loadReports();

      const program = this.programSelected;
      this.reportForm.reset();
      this.reportForm.controls.solution.setValue($event.value);
      this.reportForm.controls.programName.setValue(program);
      this.displayFilters['Resource'] = [$event?.source?.triggerValue]
      if (solution[0].isRubricDriven === true && solution[0].type === 'observation') {
        const type = solution[0].criteriaLevelReport ? solution[0].type + '_with_rubric' : solution[0].type + '_with_rubric_no_criteria_level_report'
        this.getReportTypes(this.programSelected, type);
      } else {
        this.getReportTypes(this.programSelected, solution[0].type);
      }
      this.solutionType = solution[0].type
      const requestBody:ResourceAPIRequestBody = {
        type:'solution',
        id:$event.value,
        projection:'district',
        solutionType:this.solutionType
      }
      this.getDistritAndOrganisationList(requestBody);


    }
  }

  public getReportTypes(programId, solutionType) {
    this.reportTypes = [];
    let selectedProgram = this.programs.filter(program => program._id == programId);
    if (selectedProgram && selectedProgram[0]) {
      let role = selectedProgram[0]['role'];
      let types = this.formData[solutionType];

      let filtersForReport = {
        "reportconfig.report_type": "program_dashboard",
        "reportconfig.solution_type": `${(solutionType === 'improvementProject') ? "project" : solutionType}`,
        "reportconfig.report_status": "active"
      }

      this.dashboardReport$ = this.renderReport(filtersForReport).pipe(
        catchError(err => {
          console.error('Error while rendering report', err);
          this.noResultMessage = {
            'messageText': _.get(err, 'messageText') || 'messages.stmsg.m0131'
          };
          this.noResult = true;
          return of({});
        })
      );

      if (types && types.length > 0) {
        types.forEach(element => {
          let roleMatch = role.some(e => element.roles.includes(e));
          if (roleMatch) {
            this.reportTypes.push(element);
          }
        });
      }
    }
  }

  fetchConfig(filters): Observable<any> {
    return this.reportService.listAllReports(filters).pipe(
      mergeMap(apiResponse => {
        const report = _.get(apiResponse, 'reports');
        return report ? of(_.head(report)) : throwError('No report found');
      })
    );
  }

  renderReport(reportId): Observable<any> {
    return this.fetchConfig(reportId).pipe(switchMap(
      (report => {
        const reportConfig = this.reportConfig = _.get(report, 'reportconfig');
        const dataSource = _.get(reportConfig, 'dataSource') || [];
        let updatedDataSource = _.isArray(dataSource) ? dataSource : [{ id: 'default', path: dataSource }];
        updatedDataSource = this.getUpdatedParameterizedPath(updatedDataSource);
        const charts = _.get(reportConfig, 'charts'), tables = _.get(reportConfig, 'table')
        return this.reportService.downloadMultipleDataSources(updatedDataSource).pipe(map((apiResponse) => {
          const data = 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.prepareTableData(tables, data, _.get(reportConfig, 'downloadUrl'))) || [];
          this.hideTableToCsv = (result?.tables[0]?.data != undefined) ? true : false;
          result['reportMetaData'] = reportConfig;
          result['lastUpdatedOn'] = this.reportService.getFormattedDate(this.reportService.getLatestLastModifiedOnDate(data));
          this.chartsReportData = JSON.parse(JSON.stringify(result));
          return result;
        }))
      })
    ))
  }

  prepareTableData(tablesArray: any, data: any, downloadUrl: string): Array<{}> {
    tablesArray = _.isArray(tablesArray) ? tablesArray : [tablesArray];
    return _.map(tablesArray, table => {
      const tableId = _.get(table, 'id') || `table-${_.random(1000)}`;
      const dataset = this.getTableData(data, _.get(table, 'id'));
      const tableData: any = {};
      tableData.id = tableId;
      tableData.name = _.get(table, 'name') || 'Table';
      tableData.config = _.get(table, 'config') || false;
      tableData.data = dataset.data;
      let columns = []
      tableData.header = _.get(table, 'columns') || _.get(dataset, _.get(table, 'columnsExpr'));
      tableData.header && tableData.header.map((col) => {
        let obj = { title: col, data: col }
        columns.push(obj);
      })
      tableData.columnsConfiguration = {
        columnConfig: columns,
        bLengthChange: true,
        info: true,
        lengthMenu: [10, 25, 50, 100],
        paging: true,
        searchable: true
      }
      tableData.downloadUrl = this.resolveParameterizedPath(_.get(table, 'downloadUrl') || downloadUrl, (this.userAccess && !this.reportForm.controls.solution.value ? _.get(this.reportForm, 'controls.programName.value') : _.get(this.reportForm, 'controls.solution.value')));
      return tableData;

    });
  }

  getTableData(data: { result: any, id: string }[], tableId) {
    if (data.length === 1) {
      const [dataSource] = data;
      if (dataSource.id === 'default') {
        return dataSource.result;
      }
    }
    return this.getDataSourceById(data, tableId) || {};
  }

  getDataSourceById(dataSources: { result: any, id: string }[], id: string = 'default') {
    return _.get(_.find(dataSources, ['id', id]), 'result');
  }

  downloadReport(reportType) {
    this.reportExportInProgress = true;
    this.toggleHtmlVisibilty(true);
    setTimeout(() => {
      switch (_.toLower(_.get(reportType, 'value'))) {
        case 'img': {
          this.downloadReportAsImage();
          break;
        }
        case 'pdf': {
          this.downloadReportAsPdf();
          break;
        }
      }
    })
  }

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

  downloadReportAsPdf() {
    this.convertHTMLToCanvas(this.reportSection.nativeElement, {
      scrollX: 0,
      scrollY: -window.scrollY,
      scale: 2
    }).then(canvas => {
      const imageURL = canvas.toDataURL('image/jpeg');
      const pdfFormat = new jspdf('p', 'px', 'a4');
      const docWidth = pdfFormat.internal.pageSize.getWidth();
      const imageHeight = (canvas.height * docWidth) / canvas.width;
      pdfFormat.internal.pageSize.setHeight(imageHeight);
      pdfFormat.addImage(imageURL, 'JPEG', 10, 8, docWidth - 28, imageHeight - 24);
      pdfFormat.save('report.pdf');
      this.toggleHtmlVisibilty(false);
      this.reportExportInProgress = false;
    }).catch(_err => {
      this.toggleHtmlVisibilty(false);
      this.reportExportInProgress = false;
    });
  }

  downloadReportAsImage() {
    this.convertHTMLToCanvas(this.reportSection.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 closeModal(): void {
    this.popup = false;
  }

  public csvRequest() {
    this.popup = false;
    this.submitRequest();
  }

  public requestDataset() {
    if (this.selectedReport.encrypt == true) {
      this.popup = true;
    } else {
      this.showConfirmationModal = true;
    }
  }

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

  goBack() {
    this.goToPrevLocation ? this.location.back() : (this.showPopUpModal = false);
  }

  confirm() {
    this.showPopUpModal = false;
  }
  public handleConfirmationEvent(event: boolean) {
    this.closeConfirmationModal();
    if (event == true) {
      this.submitRequest();
    }
  }
  public closeConfirmModal() {
    this.awaitPopUp = false;
  }

  public resetFilter() {
    this.reportForm.reset();
    this.filter = [];
    this.districts = [];
    this.organisations = [];
    this.solutions = [];
    this.reportTypes = [];
    this.onDemandReportData = [];
    this.goToPrevLocation = false;
    this.showPopUpModal = true;
    this.appliedFilters = {}
    this.displayFilters = {};
    this.timeRangeInit();
    this.resetConfigFilters();
  }

  loadReports() {
    const requestWithUnhashedTag = this.onDemandReportService.getReportList(this.tag);
    const requestWithHashedTag = this.onDemandReportService.getReportList(this.hashedTag);

    combineLatest([
      requestWithHashedTag.pipe(catchError((err) => of(err))),
      requestWithUnhashedTag.pipe(catchError((err) => of(err))),
    ])
      .pipe(
        map(([response1, response2]: [any, any]) => {
          const jobs1 = response1 instanceof HttpErrorResponse ? null : response1?.result?.jobs || null;
          const jobs2 = response2 instanceof HttpErrorResponse ? null : response2?.result?.jobs || null;

          if (jobs1 === null && jobs2 === null) {
            throw new Error("Both job requests failed");
          }
          const jobs = _.compact(_.concat(jobs1, jobs2));
          return jobs;
        }),
        catchError((error) => {
          this.toasterService.error(
            _.get(this.resourceService, "messages.fmsg.m0004")
          );
          return throwError("Report list APIs failed", queueScheduler);
        }),
        takeUntil(this.unsubscribe$)
      )
      .subscribe((reportData: object[]) => {
        this.onDemandReportData = reportData.length
          ? _.map(reportData, (row) => this.dataModification(row))
          : [];
      });
  }

  districtSelection($event) {
    this.newData = false;
    this.showErrorForGraphs = false
    this.appliedFilters = {...this.appliedFilters, district_externalId: $event.value}
    this.reportForm.controls.districtName.setValue($event.value);
    this.errorMessage = this.resourceService?.frmelmnts?.lbl?.resourceSelect;
    this.displayFilters['District'] = [$event?.source?.triggerValue];
    const requestBody:ResourceAPIRequestBody = {
      type:_.get(this.reportForm, 'controls.solution.value') ? 'solution' : 'program',
      id:_.get(this.reportForm, 'controls.solution.value') || _.get(this.reportForm, 'controls.programName.value'),
      projection:'block',
      districtLocationId:$event.value,
      ...(_.get(this.reportForm, 'controls.solution.value')) && {solutionType : this.solutionType}

    }
    this.getDistritAndOrganisationList(requestBody);
    const tagBasedOnUserAccess = (this.userAccess ? _.get(this.reportForm, 'controls.programName.value') : _.get(this.reportForm, 'controls.solution.value'))
    this.tag = tagBasedOnUserAccess + '_' + this.userId+'_'+ _.toLower(_.trim([$event?.source?.triggerValue]," "));
    this.hashedTag = this.hashTheTag( tagBasedOnUserAccess + '_' + this.userId+'_'+ $event.value);
    this.loadReports();
  }

  organisationSelection($event) {
    this.appliedFilters= {...this.appliedFilters, organisation_id:$event.value}
    this.reportForm.controls.organisationName.setValue($event.value);
    this.displayFilters['Organisation'] = [$event?.source?.triggerValue]
    this.newData = false;
    this.showErrorForGraphs = false;
    this.errorMessage = this.resourceService?.frmelmnts?.lbl?.resourceSelect;
  }

  blockChanged($event){
    this.reportForm.controls.blockName.setValue($event.value)
    if($event.value.length){
      this.appliedFilters = {...this.appliedFilters, block_externalId:$event.value};
      this.displayFilters['Block'] = [$event?.source?.triggerValue];
      const tagBasedOnUserAccess = (this.userAccess ? _.get(this.reportForm, 'controls.programName.value') : _.get(this.reportForm, 'controls.solution.value'))
      this.tag = tagBasedOnUserAccess + '_' + this.userId+'_'+ _.get(this.reportForm, 'controls.districtName.value') + ($event.value).sort();
      this.hashedTag = this.hashTheTag(this.tag);
      this.loadReports();
    }else{
      delete this.appliedFilters['block_externalId']
      this.appliedFilters = { ...this.appliedFilters }
    }
  }
  dependentFilterMsg(){
    if(!this.reportForm.controls.districtName.value){
      this.newData = true;
      this.errorMessage = this.resourceService?.frmelmnts?.lbl?.blockWithoutDistrict;
      this.showErrorForGraphs = true;
    }
  }

  reportChanged(selectedReportData) {
    this.resetConfigFilters();
    this.selectedReport = selectedReportData;
    if(this.selectedReport.configurableFilters){
      this.pdFilters = this.selectedReport.uiFilters;
      this.pdFilters.map(filter => {
        if(filter['controlType'] === 'number'){
          this.configuredFilters[filter['reference']] = filter['defaultValue'] as number -1
        }else if(filter['controlType'] === 'multi-select'){
          this.configuredFilters[filter['reference']] = undefined
        }
      })
    }
  }
  
  resetConfigFilters(){
    this.pdFilters = [];
    this.configuredFilters = {};
  }

  pdFilterChanged($event){
    if($event.data){
      const [reference, value]= [Object.keys($event.data),Object.values($event.data)] ;
      if($event.controlType === 'number'){
        if([0,null].includes(value[0] as number) || value[0] as number < 0){
          this.configuredFilters[reference[0]] = undefined;
        }else{
          this.configuredFilters[reference[0]] = value[0] as number -1;
        }
      }else if($event.controlType === 'multi-select'){
          if((value[0] as string[]).length){
            this.configuredFilters[reference[0]] = value[0]
          }else{
            this.configuredFilters[reference[0]] = undefined;
          }
      }
    }
  }

  addFilters() {
    this.pdFilters.map(filter => {
     if(filter['controlType'] === 'multi-select' && this.configuredFilters[filter['reference']] === undefined){
      this.configuredFilters[filter['reference']] = filter['options']
      }
    })
    const filterKeysObj = {
      "program_id": _.get(this.reportForm, 'controls.programName.value') || undefined,
      "solution_id": _.get(this.reportForm, 'controls.solution.value') || undefined,
      "programId": _.get(this.reportForm, 'controls.programName.value') || undefined,
      "solutionId": _.get(this.reportForm, 'controls.solution.value') || undefined,
      "district_externalId": _.get(this.reportForm, 'controls.districtName.value') || undefined,
      "district_id":_.get(this.reportForm, 'controls.districtName.value') || undefined,
      "organisation_id": _.get(this.reportForm, 'controls.organisationName.value') || undefined,
      "object_id":_.get(this.reportForm, 'controls.programName.value') || undefined,
      "user_locations['district_id']":_.get(this.reportForm, 'controls.districtName.value') || undefined,
      '>=':_.get(this.reportForm,'controls.startDate.value') || undefined,
      '<=':_.get(this.reportForm,'controls.endDate.value') || undefined,
      ...this.configuredFilters
    }
    const keys = Object.keys(filterKeysObj);
    this.dataFilterQuery(filterKeysObj,keys);
  }
  submitRequest() {
    this.addFilters();
    this.selectedSolution = this.reportForm.controls.solution.value;
    const isRequestAllowed = this.checkStatus();
    if (isRequestAllowed) {
      this.isProcessed = false;
      const config = {
        type: this.selectedReport['datasetId'],
        params: {
          ...((_.get(this.reportForm, 'controls.startDate.value') && _.get(this.reportForm, 'controls.solution.value')) && { 'start_date': _.get(this.reportForm, 'controls.startDate.value') }),
          ...((_.get(this.reportForm, 'controls.endDate.value') && _.get(this.reportForm, 'controls.solution.value') ) && { 'end_date': _.get(this.reportForm, 'controls.endDate.value') }),
          filters: this.filter
        },
        title: this.selectedReport.name
      };
      const request = {
        request: {
          dataset: this.selectedReport['dataset'],
          tag: this.hashedTag,
          requestedBy: this.userId,
          datasetConfig: config,
          output_format: 'csv'

        }
      };

      if (this.selectedReport.encrypt === true) {
        request.request['encryptionKey'] = this.passwordForm.controls.password.value;
      }

      this.onDemandReportService.submitRequest(request).subscribe((data: any) => {
        if (data && data.result) {
          if (data.result.status === this.reportStatus.failed) {
            const error = _.get(this.resourceService, 'frmelmnts.lbl.reportRequestFailed');
            this.toasterService.error(error);
          } else {

            if (data['result'] && data['result']['requestId']) {

              const dataFound = this.onDemandReportData.filter(function (submittedReports) {
                if (submittedReports['requestId'] == data['result']['requestId']) {
                  return data;
                }

              });
              if (dataFound && dataFound.length > 0) {
                this.popup = false;
                this.isProcessed = true;
                setTimeout(() => {
                  this.isProcessed = false;
                }, 5000);
                this.toasterService.error(_.get(this.resourceService, 'frmelmnts.lbl.reportRequestFailed'));
                this.passwordForm.reset();

              } else {
                data = this.dataModification(data['result']);
                const updatedReportList = [data, ...this.onDemandReportData];
                this.onDemandReportData = updatedReportList;
                this.awaitPopUp = true;
                this.passwordForm.reset();

              }
            }
          }

        }
      }, error => {
        this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
      });
      this.filter = [];

    } else {
      this.popup = false;
      this.isProcessed = true;
      this.filter = [];
      setTimeout(() => {
        this.isProcessed = false;
      }, 10000);
      this.toasterService.error(_.get(this.resourceService, 'frmelmnts.lbl.reportRequestFailed'));
      this.passwordForm.reset();
    }
  }

  public getFormDetails() {

    const formServiceInputParams = {
      formType: 'program-dashboard',
      formAction: 'reportData',
      contentType: 'csv-dataset',
      component: 'portal'
    };

    this.formService.getFormConfig(formServiceInputParams).subscribe((formData) => {
      if (formData) {
        this.formData = formData;
      }
    }, error => {
      this.toasterService.error(this.resourceService.messages.emsg.m0005);
    });

  }

  checkStatus() {
    let requestStatus = true;
    const selectedReportList = [];
    _.forEach(this.onDemandReportData, (value) => {
      if (value.datasetConfig.type === this.selectedReport.datasetId){
        _.forEach(value.datasetConfig.params.filters, (filter) => {
          const conditionForSolutionBasedReports = ['solutionId','solution_id'].includes(filter['dimension']) && filter.value  === this.selectedSolution
          const conditionForProgramBasedReports = ['object_id'].includes(filter?.table_filters?.[0]['name']) && filter?.table_filters?.[0].value === this.reportForm.controls.programName.value
          if(conditionForSolutionBasedReports || conditionForProgramBasedReports){
            selectedReportList.push(value);
          }
        });
      }
    });
    const sortedReportList = _.sortBy(selectedReportList, [(data) => {
      return data && data.jobStats && data.jobStats.dtJobSubmitted;
    }]);

    const reportListData = _.last(sortedReportList) || {};
    if (!_.isEmpty(reportListData)) {
      const isInProgress = this.onDemandReportService.isInProgress(reportListData, this.reportStatus);
      if (!isInProgress) {
        requestStatus = true;
      } else {
        requestStatus = false;
      }
    }
    return requestStatus;
  }
  onDownloadLinkFail(data) {
    const tagId = data && data.tag && data.tag.split(':');
    this.onDemandReportService.getReport(_.head(tagId), data.requestId).subscribe((data: any) => {
      if (data) {
        const downloadUrls = _.get(data, 'result.downloadUrls') || [];
        const downloadPath = _.head(downloadUrls);
        if (downloadPath) {
          window.open(downloadPath, '_blank');
        } else {
          this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
        }
      }
    }, error => {
      this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
    });
  }
  dataModification(row) {
    row.title = row.datasetConfig.title;
    return row;
  }

  dateChanged($event, type) {
    if (dayjs($event.value).isValid()) {
      this.newData = false;
      this.showErrorForGraphs = false;
      this.errorMessage = this.resourceService?.frmelmnts?.lbl?.resourceSelect;
      const year = new Date($event.value._d).getFullYear();
      const month = new Date($event.value._d).getMonth();
      const day = new Date($event.value._d).getDate();
      if(type === 'startDate'){
        this.minEndDate = new Date(year, month, day + 1);
      }else{
        this.maxStartDate = new Date(year, month, day - 1);
      }
      this.reportForm.controls[type].setValue(dayjs(_.get($event, 'value._d')).format('YYYY-MM-DD'));
    }
  }

  closeDashboard(){
    this.location.back()
  }

  dataFilterQuery(filterKeysObj,keys){
    if(this.selectedReport['queryType'] === "cassandra"){
      this.filter = _.cloneDeep(this.selectedReport['filters'])
      _.map(this.filter, filterObj => {
         _.remove(filterObj['table_filters'], filterItem => {
             _.map(keys,key => {
            (filterItem.name === key || filterItem.operator === key) && (filterItem.value = filterKeysObj[key])
          })
          return filterItem.value === undefined
        })
      })
    }else{
        this.selectedReport['filters'].map(data => {
        keys.filter(key => {
          return data.dimension === key && (_.has(data,'value') ? data.value = filterKeysObj[key] : data.values = filterKeysObj[key]);
        })
        if (data.value !== undefined || data.values !== undefined) {
          this.filter.push(data);
        }
      });
    }
  }

  hashTheTag(key:string):string{
    return Md5.hashStr(key);
  }

  ngOnDestroy() {
    if (this.userDataSubscription) {
      this.userDataSubscription.unsubscribe();
    }
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }
}
<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 relative12'"
  class="relative position mt-0">
    <div class="py-0 d-flex flex-ai-center w-100">
      <!-- /* Back button */ -->
       <div class="mr-12">
        <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)="closeDashboard()" id="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>
     <div class="textbook d-flex flex-jc-space-between w-100">
       
        <!-- title -->
        <h4 class="textbook__title sb-color-primary font-weight-bold mt-8 ml-24" >{{resourceService?.frmelmnts?.lnk?.programDashboard}}</h4>
        <div>
          <button class="sb-btn sb-btn-primary sb-btn-normal px-24" (click)="closeDashboard()">
            {{resourceService?.frmelmnts?.btn?.closedb}}
          </button>
        </div>           
        
    </div>
  
    </div>
  
</div>
<div class="sbt-inside-page-container" #reportSection>
  <mat-tab-group class="sb-mat__tab sb-mat__tab--tabinacc" (selectedTabChange)="selectedTabChange($event)">
    <mat-tab appTelemetryInteract>
         <ng-template mat-tab-label>
            <span class="font-weight-bold">{{resourceService?.frmelmnts?.lbl?.programDatasets}}</span>
         </ng-template>
        <ng-container *ngTemplateOutlet="programDataset"></ng-container>
      </mat-tab>
      <ng-container *ngIf="!noResult && (dashboardReport$ | async) as currentReport">
        <mat-tab appTelemetryInteract>
          <ng-template mat-tab-label>
             <span class="font-weight-bold">{{resourceService?.frmelmnts?.lbl?.graphs}}</span>
          </ng-template>
         <ng-container *ngTemplateOutlet="graphs;context:{$implicit:currentReport}"></ng-container>
       </mat-tab>
        <mat-tab *ngFor="let table of currentReport?.tables;"> 
          <ng-template mat-tab-label>
             <span class="font-weight-bold">{{table.name}}</span>
          </ng-template>
         <ng-container *ngTemplateOutlet="tables;context:{$implicit:table}"></ng-container>
       </mat-tab> 
       </ng-container>
    </mat-tab-group>
</div>

<ng-template #globalFilters>
  <ng-container *ngIf="!hideElements">
    <form class="sb-form" [formGroup]="reportForm">
      <div class="d-flex">
        <div class="d-flex flex-w-wrap flex-ai-center ml-32 col-gap">
          <div class="d-flex flex-dc">
            <label>{{resourceService?.frmelmnts?.lbl?.programLbl }}</label>
              <mat-form-field appearance="fill" class="sb-mat__dropdown custom_mat_dd">
              <mat-select role="radio" class="selection" valueField="_id" formControlName="programName"
              [(ngModel)]="programSelected"
              [placeholder]="resourceService?.frmelmnts?.lbl?.program"  (selectionChange)="programSelection($event)">
                <mat-option *ngFor="let program of programs" class="mat-dropdown__options" role="option" [value]="program._id">
                  {{program.name}}
                </mat-option>
              </mat-select>
              </mat-form-field>
          </div>
          <div class="d-flex flex-dc">
            <label>{{ resourceService?.frmelmnts?.lbl?.solutionLbl }}</label>
              <mat-form-field appearance="fill" class="sb-mat__dropdown custom_mat_dd">
              <mat-select role="radio" class="selection" [(ngModel)]="solutionSelected" valueField="_id" formControlName="solution"
              [placeholder]="resourceService?.frmelmnts?.lbl?.solution"  (selectionChange)="selectSolution($event)">
                <mat-option *ngFor="let solution of solutions" class="mat-dropdown__options" role="option" [value]="solution._id">
                  {{solution.name}} 
                </mat-option>
              </mat-select>
              </mat-form-field>
          </div>
          <div class="d-flex flex-dc">
            <label>{{ resourceService?.frmelmnts?.lbl?.dashboarddistrictLbl }}</label>
              <mat-form-field appearance="fill" class="sb-mat__dropdown custom_mat_dd">
              <mat-select role="radio" class="selection"  valueField="locationId" formControlName="districtName"
              [placeholder]="resourceService?.frmelmnts?.lbl?.dashboarddistrict"  (selectionChange)="districtSelection($event)">
                <mat-option *ngFor="let district of districts" class="mat-dropdown__options" role="option" [value]="district.id">
                  {{district.name | titlecase }}
                </mat-option>
              </mat-select>
              </mat-form-field>
          </div>
          <div *ngIf="tabIndex !== 2" class="d-flex flex-dc">
            <label>{{ resourceService?.frmelmnts?.lbl?.block }}</label>
              <mat-form-field appearance="fill" class="sb-mat__dropdown custom_mat_dd" >
              <mat-select role="radio" class="selection"  valueField="locationId" multiple formControlName="blockName"
              [placeholder]="resourceService?.frmelmnts?.lbl?.blockLabel"  (selectionChange)="blockChanged($event)" (click)="dependentFilterMsg()" [disabled]="!reportForm.controls.districtName.value">
                <mat-option *ngFor="let block of blocks" class="mat-dropdown__options custom_mat_multi" role="option" [value]="block.id">
                  {{block.name | titlecase}}
                </mat-option>
              </mat-select>
              </mat-form-field>
          </div>
          <div class="d-flex flex-dc">
            <label>{{ resourceService?.frmelmnts?.lbl?.dashboardOrgLbl }}</label>      
              <mat-form-field appearance="fill" class="sb-mat__dropdown custom_mat_dd">
              <mat-select role="radio" class="selection" valueField="organisationId" formControlName="organisationName"
              [placeholder]="resourceService?.frmelmnts?.lbl?.dashboardOrg"  (selectionChange)="organisationSelection($event)">
                <mat-option *ngFor="let organisation of organisations" class="mat-dropdown__options" role="option" [value]="organisation.id">
                  {{organisation.name | titlecase}}
                </mat-option>
              </mat-select>
              </mat-form-field>
          </div>

          <div *ngIf="tabIndex !== 1 && tabIndex !== 2  && tabIndex !== 3" class="d-flex flex-dc customDate">
            <label>{{resourceService?.frmelmnts?.lbl?.startdate | titlecase }}</label>
            <mat-form-field appearance="fill" class="sb-mat__dropdown custom_mat_dd sb-color-primary">
              <input [disabled]="!reportForm.controls.programName.value" matInput placeholder="dd/mm/yyyy" [max]="maxStartDate" (dateInput)="dateChanged($event,'startDate')" (dateChange)="dateChanged($event,'startDate')" formControlName="startDate" [matDatepicker]="picker">
              <mat-datepicker-toggle matSuffix [for]="picker" class="sb-color-primary"></mat-datepicker-toggle>
              <mat-datepicker #picker></mat-datepicker>
            </mat-form-field>            
          </div>
          <div *ngIf="tabIndex !== 1 && tabIndex !== 2  && tabIndex !== 3" class="d-flex flex-dc customDate">
            <label>{{resourceService?.frmelmnts?.lbl?.enddate | titlecase }}</label>
            <mat-form-field appearance="fill" class="sb-mat__dropdown custom_mat_dd sb-color-primary">
              <input [disabled]="!reportForm.controls.programName.value"  matInput placeholder="dd/mm/yyyy" [min]="minEndDate" [max]="maxEndDate"  (dateInput)="dateChanged($event,'endDate')" (dateChange)="dateChanged($event,'endDate')" formControlName="endDate" [matDatepicker]="picker">
              <mat-datepicker-toggle matSuffix [for]="picker" class="sb-color-primary"></mat-datepicker-toggle>
              <mat-datepicker #picker></mat-datepicker>
            </mat-form-field>            
          </div>
          <ng-container *ngIf="pdFilters.length && tabIndex !== 1 && tabIndex !== 2">
            <ng-container *ngFor="let filter of pdFilters">
              <app-pd-filters [pdFilter]="filter" (filterChanged)="pdFilterChanged($event)"></app-pd-filters>
            </ng-container>
          </ng-container>

          
        </div>
        <div class="d-flex flex-dc ml-auto btn-col">
          <button type="button" class="sb-field sb-btn sb-btn-normal sb-btn-primary reset-filter flex-as-flex-end" (click)="resetFilter()">{{resourceService?.frmelmnts?.btn?.resetFilters}}</button>
          <mat-form-field *ngIf="!noResult && (tabIndex == 1)" appearance="fill" class="sb-mat__dropdown custom_mat_dd">
            <mat-select role="radio" class="selection" placeholder="Export as" (selectionChange)="downloadReport($event)" >
            <mat-option class="mat-dropdown__options" role="option" *ngFor="let option of exportOptions" [value]="option"
            attr.aria-label="{{option}}">{{option}}</mat-option>
            </mat-select>
            </mat-form-field>    
        </div>
      </div>
    </form>
  </ng-container>
  <div class="sb-filter-label pt-16 pb-8" *ngIf="hideElements">
    <div *ngFor="let key of loadash.keys(displayFilters)" class="d-inline-flex flex-w-wrap pr-10">
        <span class="sb-label-name mb-4">{{key}}:</span><span class="sb-label-value"
          *ngFor="let val of displayFilters[key]">{{val}}
        </span>
    </div>
  </div>
</ng-template>
<ng-template #programDataset>
  <ng-container *ngTemplateOutlet="globalFilters"></ng-container>
  <div *ngIf="reportForm.controls.programName.value && (!userAccess|| (oldProgram && !reportForm.controls.solution.value) || newData)"class="newData">*{{errorMessage}}</div>
  <div class="sbt-inside-page-container relative position mt-32">
    <div>
      <div>
        <label>{{resourceService?.frmelmnts?.lbl?.detailsReports}}</label>
        <hr>
      </div>
      <div [formGroup]="reportForm" class="mt-32">
        <label>{{ resourceService?.frmelmnts?.lbl?.reportType }}</label>
        <div class="d-flex flex-w-wrap flex-dr">
          <mat-form-field appearance="fill" class="sb-mat__dropdown custom_mat_dd d-flex flex-ai-center w-auto" >
          <mat-select role="listbox" formControlName="reportType" class="selection"
          [placeholder]="resourceService?.frmelmnts?.lbl?.selectReport" [disabled]="!userAccess">
            <mat-option role="option" *ngFor="let report of reportTypes" class="custom_mat_dd mat-dropdown__options" [value]="report?.name" (click)="reportChanged(report)">
              {{report?.name}}
            </mat-option>
          </mat-select>
          </mat-form-field>
          <button [disabled]="(!reportForm.valid)" 
                  [ngClass]="{'sb-btn-disabled': (!reportForm.valid)}"
                  type="button" class="sb-field sb-btn sb-btn-normal sb-btn-primary ml-12" (click)="requestDataset()">
                    {{resourceService?.frmelmnts?.btn?.requestReport}}
                  </button>
        </div>
      </div>
      <div *ngIf="isProcessed" class="d-flex flex-ai-baseline mt-12">
        <div class="information-icon">
          <img src="assets/images/error-icon.svg" class="infoIcon"></div>
        <p class="fsmall note-text my-8 administrator-text ml-12 sb-color-error">{{resourceService.frmelmnts?.lbl?.reportStatus}}</p>
      </div>
     

      <div class="fsmall font-weight-bold download-section-text mt-24">
        {{resourceService.frmelmnts?.lbl?.downloadSectionNote}}</div>
      <p class="fsmall mt-8 mb-16 administrator-text">{{resourceService?.frmelmnts?.lbl?.repgenProgramAdminNote | interpolate:'{instance}': instance }}</p>

      <sb-datatable [message]="message" [data]="onDemandReportData" [columns]="columns"
        [downloadCSV]="false"  (downloadLink)="onDownloadLinkFail($event)"></sb-datatable>
    </div>
  </div>
  
 
</ng-template>
<ng-template #graphs let-currentReport>
  <ng-container *ngTemplateOutlet="globalFilters" ></ng-container>
  <div *ngIf="(oldProgram && newData) || (!oldProgram && showErrorForGraphs)" class="newData">*{{errorMessage}}</div>
  <ng-container *ngIf="(oldProgram && reportForm.controls.solution.value && currentReport.charts.length) || (!oldProgram && currentReport.charts.length)">
    <div class="sb-graph-section p-24 my-24"
        *ngFor="let chart of currentReport.charts;">
        <ng-container *ngIf="chart?.chartConfig?.id == 'Big_Number'">
          <app-sb-bignumber [chart]="chart" [hideElements]="hideElements" [appliedFilters]="appliedFilters"></app-sb-bignumber>
        </ng-container>
        <ng-container *ngIf="chart?.chartConfig?.id !== 'Big_Number' && chart?.chartData && chart?.chartConfig">
      <app-sb-chart [chart]="chart" [hideElements]="hideElements" [appliedFilters]="appliedFilters"></app-sb-chart>
      </ng-container>
      </div>
    </ng-container>
      <div class="ui warning message mt-16" *ngIf="(!reportForm.controls.solution.value && oldProgram) || !currentReport.charts.length">
        {{resourceService?.frmelmnts?.lbl?.graphNotAvailable}}
      </div>
  <div *ngIf="noResult">
    <app-no-result [data]="noResultMessage"></app-no-result>
  </div>
  <ng-template #loading>
    <ng-container *ngIf="!noResult">
      <div class="ui container">
        <div class="nine wide column workspacesegment">
          <app-loader></app-loader>
        </div>
      </div>
    </ng-container>
  </ng-template>
</ng-template>

  <ng-template #tables let-table>
    <ng-container *ngTemplateOutlet="globalFilters"></ng-container>
    <div *ngIf="(oldProgram && newData) || (!oldProgram && !reportForm.controls.solution.value) || newData"class="newData">*{{errorMessage}}</div>
      <div *ngIf="table?.data" class="sb-graph-section p-24 my-24">
            <div class="customTable">
              <app-sb-table [tableToCsv]="tableToCsv" [table]="table" [hideElements]="hideElements" [appliedFilters]="appliedFilters"></app-sb-table>
            </div>
      </div>
      <div class="ui warning message mt-16" *ngIf="!table?.data">
        {{resourceService?.frmelmnts?.lbl?.tableNotAvailable}}
      </div>
  <div *ngIf="noResult">
    <app-no-result [data]="noResultMessage"></app-no-result>
  </div>
  <ng-template #loading>
    <ng-container *ngIf="!noResult">
      <div class="ui container">
        <div class="nine wide column workspacesegment">
          <app-loader></app-loader>
        </div>
      </div>
    </ng-container>
  </ng-template>
  </ng-template>
<app-modal-wrapper [config]="{disableClose: false, size: 'small'}" (dismiss)="closeModal()" #modal *ngIf="popup">
  <ng-template sbModalContent>
    <div class="sb-modal">
      <div class="transition ui dimmer page modals active visible">
        <div class="ui modal transition active visible small">
          <div class="sb-modal-header">

            {{resourceService?.frmelmnts?.lbl?.confirmReportRequest}}
          </div>
          <div class="sb-modal-content o-x-hide" [formGroup]="passwordForm">
            <div class="sb-field-group">
              <div class="sb-field relative">
                <div class="sb-field filterTable mx-16 mb-0">
                  <input class="sb-form-control" formControlName="password" type="text"
                    placeholder="Enter a password to request Report" aria-label="enter password">
                </div>
              </div>
              <p class="fsmall note-text my-8 administrator-text">
                {{resourceService?.frmelmnts?.lbl?.pswdRule}}
              </p>
            </div>
          </div>
          <div class="sb-modal-actions">
            <button class="sb-btn sb-btn-normal sb-btn-primary" [disabled]="(!reportForm.valid || !passwordForm.valid)"
              [ngClass]="{'sb-btn-disabled': (!reportForm.valid || !passwordForm.valid)}" (click)="csvRequest()">
              {{resourceService?.frmelmnts?.btn?.yes}}
            </button>
            <button class="sb-btn sb-btn-normal sb-btn-outline-primary" (click)="closeModal()">
              {{resourceService?.frmelmnts?.btn?.no}}
            </button>
          </div>
        </div>
      </div>
    </div>
  </ng-template>
</app-modal-wrapper>

<app-modal-wrapper [config]="{disableClose: false, size: 'small'}" (dismiss)="closeConfirmModal()" #modal
  *ngIf="awaitPopUp">
  <ng-template sbModalContent>
    <div class="sb-modal">
      <div class="transition ui dimmer page modals active visible">
        <div class="ui modal transition active visible small">
          <div class="sb-modal-content mt-16">

            {{resourceService?.frmelmnts?.lbl?.datasetRequestSuccess}}
          </div>
          <div class="sb-modal-actions">
            <button class="sb-btn sb-btn-normal sb-btn-primary" (click)="closeConfirmModal()">
              {{resourceService?.frmelmnts?.btn?.ok}}
            </button>
          </div>
        </div>
      </div>
    </div>
  </ng-template>
</app-modal-wrapper>

<app-modal-wrapper [config]="{disableClose: false, size: 'small'}" (dismiss)="closeConfirmationModal()" #modal
  *ngIf="showConfirmationModal">
  <ng-template sbModalContent>
    <div class="sb-modal">
      <div class="transition ui dimmer page modals active visible">
        <div class="ui modal transition active visible small">
          <div class="sb-modal-content o-x-hide">
            <div class="my-8">
              {{ resourceService?.frmelmnts?.lbl?.confirmReportRequest }}
            </div>
          </div>
          <div class="sb-modal-actions">
            <button class="sb-btn sb-btn-normal sb-btn-primary" (click)="handleConfirmationEvent(true)">
              {{resourceService?.frmelmnts?.btn?.yes}}
            </button>
            <button class="sb-btn sb-btn-normal sb-btn-outline-primary" (click)="handleConfirmationEvent(false)">
              {{resourceService?.frmelmnts?.btn?.no}}
            </button>
          </div>
        </div>
      </div>
    </div>
  </ng-template>
</app-modal-wrapper>

<app-modal-wrapper *ngIf="showPopUpModal" [config]="{disableClose: false, size: 'small'}" (dismiss)="closePopupModal()" #modal>
  <ng-template sbModalContent>
    <div class="sb-modal">
      <div class="transition ui dimmer page modals active visible">
        <div class="ui modal transition active visible small">
          <div class="sb-modal-content o-x-hide">
            <div class="d-flex flex-dir-row my-8">
             <div>
              <mat-icon class="info">info</mat-icon> 
             </div>
             <div class="font-weight-bold sb-color-primary modalNote"> {{resourceService?.frmelmnts?.lbl?.modalNote}}</div>
             <div class="ml-auto">
              <mat-icon class="goback" (click)="goBack()">highlight_off</mat-icon>
             </div>
            </div>
            
            
            <div class="mt-48 flex-dc" [formGroup]="reportForm">
              <label  class="d-flex flex-jc-center sb-color-primary">{{resourceService?.frmelmnts?.lbl?.programLbl }}</label>
               <div class="d-flex flex-jc-center mt-24">
                <mat-form-field appearance="fill" class="sb-mat__dropdown custom_mat_dd w-80">
                  <mat-select role="radio" class="selection" valueField="_id" formControlName="programName"
                  [(ngModel)]="programSelected"
                  [placeholder]="resourceService?.frmelmnts?.lbl?.program"  (selectionChange)="programSelection($event)">
                    <mat-option *ngFor="let program of programs" class="mat-dropdown__options" role="option" [value]="program._id">
                      {{program.name}}
                    </mat-option>
                  </mat-select>
                  </mat-form-field>
               </div>
              
            </div>
            <div class="mt-32 sb-modal-actions">
              <button [disabled]="!reportForm.controls.programName.value" [ngClass]="{'sb-btn-disabled': (!reportForm.controls.programName.value)}" type="button" class="sb-field sb-btn sb-btn-normal sb-btn-primary" (click)="confirm()">{{resourceService?.frmelmnts?.btn?.confirmBtn}}</button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </ng-template>
</app-modal-wrapper>

<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>

./program-datasets.component.scss

@use "@project-sunbird/sb-styles/assets/mixins/mixins" as *;

.sb-modal-actions {
  display: flex;
  align-items: center;
  justify-content: center;
}

.sb-modal .ui.modal {
  margin-top: 15% !important;
}

.ngx-datatable.fixed-header .datatable-header {
  padding: 0.625rem;
}

.sidebar-block {
  min-height: 25rem;
}

.ngx-datatable.datatable-header {
  background: var(--mat-accordion-tab-body-active-bg) !important;
}


.custom_mat_dd .mat-select-arrow-wrapper {
  vertical-align: bottom !important;
}

.reset-filter{
  color: var(--primary);
  background-color: var(--brand-header-tail-text);
  width: fit-content;
}

.newData{
  color:var(--ck-color-base-error);
  margin-left: 1.875rem;
  margin-top: 0.625rem;
}

.info{
  justify-self: flex-start;
  margin-right: 0.625rem;
  cursor: pointer;
  color: var(--primary) !important;
}
.goback{
  justify-self: flex-end;
  cursor: pointer;
  color: var(--ck-color-button-cancel);
}

.ppFilter{
  margin-top: 1.25rem;
}

.col-gap{
  gap:2rem;
}

.btn-col{
  flex-grow: 1;
  margin-left: 5rem !important;
}

.modalNote{
  line-height: initial;
}

.infoIcon{
  width: 1.125rem;
}
.sb-graph-section{

  box-shadow: 0 calculateRem(2px) calculateRem(7px) 0 rgba(var(--rc-rgba-black), 0.16);
  background: var(--sb-graph-section-bg);
  border: 0.0625rem solid var(--rc-dddddd);

}

.sb-last-update-status {
  font-size: calculateRem(12px);
  font-weight: bold;
}

.sb-label-name {
  font-size: 1rem;
}

.sb-label-value {
  border-radius: calculateRem(24px);
  padding: calculateRem(7px);
  padding-right: calculateRem(9px);
  padding-left: calculateRem(9px);
  background-color: var(---rc-e9e8d9) !important;
  box-shadow: calculateRem(4px) calculateRem(4px) calculateRem(3px) 0 var(--gray-100) !important;
  color: var(--gray-800);
  margin-bottom: 0.25rem;
  margin-right: 0.25rem;

}

::ng-deep {
  
  .cdk-overlay-container{
    z-index: 9 !important;
  }

  .customTable{
    sb-dashlets-filters{
      display: none !important;
    }

    .dataTables_length{
      display: flex !important;
      width: 100% !important;
      justify-content: flex-end !important;
    }
    .chart-title{
      font-weight: 700;
    }
    table{
      width: 100% !important;
    }
  }
  .customGraph{
    .sb-filter-g__item{
      border-radius: 1.5rem !important;
    }

    .multiselect-dropdown .dropdown-btn{
      border-radius: 1.5rem !important;
    }
  }
  
  .customDate{
    .mat-form-field-infix{
      width: 8.75rem !important;
    }
  }
  .chart-title {
    font-size: 1rem;
    font-weight: 500;
    margin-bottom: 0.5rem !important;
    padding-top: 0.5rem;
  }

  
  .custom_mat_dd{
    
    .mat-form-field-flex{
      display: flex;
      align-items: center !important;
      box-sizing: border-box;
      width: 100%;
      
      input::placeholder{
        color: rgba(0,0,0,.42) !important;
        font-weight: bold !important;
      }
    }

    .mat-select-arrow-wrapper {
      vertical-align: unset !important;
    }

  }
  .mat-select-panel .mat-option {
    white-space: normal !important;
    display: inline-table !important;
    width: 100% !important;
    line-height: 1.5em !important;
    padding: 0.625rem 1.5em;
  }
  .mat-option-text{
    display: flex !important;
  }

  .mat-dropdown__options span {
    position: unset !important;
  }
  .mat-dropdown__options span:before {
    display: flex !important;
    align-self: flex-end !important;
  }
  .custom_mat_multi.mat-option{
    display: flex !important;
  }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""