src/app/modules/shared/components/on-demand-reports/on-demand-reports.component.ts
                OnInit
    
| selector | app-on-demand-reports | 
            
| styleUrls | ./on-demand-reports.component.scss | 
            
| templateUrl | ./on-demand-reports.component.html | 
            
                        Properties | 
                
                        
  | 
                
                        Methods | 
                
                        Inputs | 
                
constructor(resourceService: ResourceService, telemetryService: TelemetryService, onDemandReportService: OnDemandReportService, toasterService: ToasterService)
                     | 
                |||||||||||||||
| 
                             
                                    Parameters :
                                     
                    
  | 
                
| batch | |
                        Type :         any
                     | 
                |
| reportTypes | |
                        Type :         any
                     | 
                |
| tag | |
                        Type :         any
                     | 
                |
| userId | |
                        Type :         any
                     | 
                |
| checkStatus | 
checkStatus()
                 | 
            
| 
                     
                        Returns :          
                boolean
                     | 
            
| dataModification | ||||
dataModification(row)
                 | 
            ||||
| 
                     
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    any
                     | 
            
| generateTelemetry | ||||||||
generateTelemetry(fieldType, batchId, courseId)
                 | 
            ||||||||
| 
                     
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    void
                     | 
            
| loadReports | ||||||
loadReports(batchDetails?: any)
                 | 
            ||||||
| 
                     
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    void
                     | 
            
| ngOnInit | 
ngOnInit()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| onDownloadLinkFail | ||||
onDownloadLinkFail(data)
                 | 
            ||||
| 
                     
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    void
                     | 
            
| reportChanged | ||||
reportChanged(ev)
                 | 
            ||||
| 
                     
                        Parameters :
                        
                         
                    
 
                        Returns :          
                    void
                     | 
            
| submitRequest | 
submitRequest()
                 | 
            
| 
                     
                        Returns :          
                void
                     | 
            
| Public fileName | 
                        Type :         string
                     | 
                
                        Default value : ''
                     | 
                
| instance | 
                        Type :         string
                     | 
                
| Public isDownloadReport | 
                        Default value : false
                     | 
                
| Public isProcessed | 
                        Default value : false
                     | 
                
| Public message | 
                        Type :         string
                     | 
                
                        Default value : 'There is no data available'
                     | 
                
| Public onDemandReportData | 
                        Type :     any[]
                     | 
                
| Public onDemandReportService | 
                        Type :         OnDemandReportService
                     | 
                
| Public reportForm | 
                        Type :         UntypedFormGroup
                     | 
                
| reportStatus | 
                        Type :         object
                     | 
                
                        Default value : {
    'submitted': 'SUBMITTED',
    'processing': 'PROCESSING',
    'failed': 'FAILED',
    'success': 'SUCCESS',
  }
                     | 
                
| Public resourceService | 
                        Type :         ResourceService
                     | 
                
| Public selectedReport | 
| Public telemetryService | 
                        Type :         TelemetryService
                     | 
                
| Public toasterService | 
                        Type :         ToasterService
                     | 
                
import {Component, OnInit, Input} from '@angular/core';
import {ResourceService, ToasterService} from '../../services';
import {OnDemandReportService} from '../../services/on-demand-report/on-demand-report.service';
import * as _ from 'lodash-es';
import {Validators, UntypedFormControl, UntypedFormGroup} from '@angular/forms';
import {TelemetryService} from '@sunbird/telemetry';
@Component({
  selector: 'app-on-demand-reports',
  templateUrl: './on-demand-reports.component.html',
  styleUrls: ['./on-demand-reports.component.scss']
})
export class OnDemandReportsComponent implements OnInit {
  @Input() reportTypes;
  @Input() tag;
  @Input() userId;
  @Input() batch;
  public columns = [
    {name: 'Report type', isSortable: true, prop: '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'},
    // { name: 'Requested by', isSortable: true, prop: 'requested_by', placeholder: 'Filter request by' },
  ];
  public onDemandReportData: any[];
  public isDownloadReport = false;
  public fileName = '';
  public selectedReport;
  public reportForm: UntypedFormGroup;
  // public password = new FormControl('', [Validators.minLength(6), Validators.required, Validators.pattern('^(?=.*[0-9])(?=.*[a-zA-Z])([a-zA-Z0-9]+)$')]);
  public message = 'There is no data available';
  public isProcessed = false;
  reportStatus = {
    'submitted': 'SUBMITTED',
    'processing': 'PROCESSING',
    'failed': 'FAILED',
    'success': 'SUCCESS',
  };
  instance: string;
  constructor(public resourceService: ResourceService, public telemetryService: TelemetryService,
    public onDemandReportService: OnDemandReportService, public toasterService: ToasterService) {
      this.reportForm = new UntypedFormGroup({
        reportType: new UntypedFormControl('', [Validators.required]),
        password : new UntypedFormControl('', [Validators.minLength(6), Validators.required, Validators.pattern('^(?=.*[0-9])(?=.*[a-zA-Z])([a-zA-Z0-9]+)$')])
      });
  }
  ngOnInit() {
    this.instance = _.upperCase(this.resourceService.instance || 'SUNBIRD');
  }
  loadReports(batchDetails?: any) {
    if (batchDetails) {
      this.batch = batchDetails;
      this.tag = batchDetails.courseId + '_' + batchDetails.batchId;
    }
    if (this.batch) {
      this.onDemandReportService.getReportList(this.tag).subscribe((data) => {
        if (data) {
          const reportData = _.get(data, 'result.jobs');
          this.onDemandReportData = _.map(reportData, (row) => this.dataModification(row));
          this.onDemandReportData = [...this.onDemandReportData];
        }
      }, error => {
        this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
      });
    }
  }
  reportChanged(ev) {
    this.selectedReport = _.get(ev, 'value');
  }
  generateTelemetry(fieldType, batchId, courseId) {
    const interactData = {
      context: {
        env: 'reports',
        cdata: [{id: courseId, type: 'Course'}, {id: batchId, type: 'Batch'}]
      },
      edata: {
        id: fieldType,
        type: 'click',
        pageid: 'on-demand-reports'
      }
    };
    this.telemetryService.interact(interactData);
  }
  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'));
    });
  }
  submitRequest() {
    const isRequestAllowed = this.checkStatus();
    if (isRequestAllowed) {
      this.isProcessed = false;
      const request = {
        request: {
          tag: this.tag,
          requestedBy: this.userId,
          dataset: this.selectedReport.dataset,
          datasetConfig: {
            batchId: this.batch.batchId
          },
          output_format: 'csv'
        }
      };
      if (this.selectedReport.encrypt === 'true') {
        request.request['encryptionKey'] = this.reportForm.controls.password.value;
      }
      console.log('submit the report');
      this.generateTelemetry(this.selectedReport.dataset, this.batch.batchId, this.batch.courseId);
      this.onDemandReportService.submitRequest(request).subscribe((data: any) => {
        if (data && data.result) {
          if (data.result.status === this.reportStatus.failed) {
            const error = _.get(data, 'result.statusMessage') || _.get(this.resourceService, 'frmelmnts.lbl.requestFailed');
            this.toasterService.error(error);
          }
          data = this.dataModification(data['result']);
          const updatedReportList = [data, ...this.onDemandReportData];
          this.onDemandReportData = _.slice(updatedReportList, 0, 10);
        }
        this.reportForm.reset();
      }, error => {
        this.reportForm.reset();
        this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
      });
    } else {
      this.isProcessed = true;
      setTimeout(() => {
        this.isProcessed = false;
      }, 5000);
      this.toasterService.error(_.get(this.resourceService, 'frmelmnts.lbl.requestFailed'));
    }
  }
  checkStatus() {
    let requestStatus = true;
    const selectedReportList = [];
    _.forEach(this.onDemandReportData, (value) => {
      if (value.dataset === this.selectedReport.dataset) {
        selectedReportList.push(value);
      }
    });
    const sortedReportList = _.sortBy(selectedReportList, [(data) => {
      return data && data.jobStats && data.jobStats.dtJobSubmitted;
    }]);
    const reportListData = _.last(sortedReportList) || {};
    let batchEndDate;
    if (this.batch.endDate) {
      batchEndDate = new Date(`${this.batch.endDate} 23:59:59`).getTime();
    }
    if (!_.isEmpty(reportListData)) { // checking the report is already created or not
      const isInProgress = this.onDemandReportService.isInProgress(reportListData, this.reportStatus); // checking the report is in SUBMITTED/PROCESSING state
      if (!isInProgress) {
        requestStatus = true;
        // TODO: The below code has commented because of API lag to generate the reports
        // requestStatus = this.onDemandReportService.canRequestReport(_.get(reportListData, 'jobStats.dtJobSubmitted'), batchEndDate); // performing the date checks if the report is not in SUBMITTED/PROCESSING state
      } else {
        requestStatus = false; // report is in SUBMITTED/PROCESSING state and can not create new report
      }
    }
    return requestStatus;
  }
  dataModification(row) {
    const dataSet = _.find(this.reportTypes, {dataset: row.dataset}) || {};
    row.title = dataSet.title;
    return row;
  }
}
    <div class='ui stackable grid mt-0'>
  <div class="twelve wide column pt-0">
    <div class="d-flex flex-dc">
      <!-- <label class="request-report-label font-weight-normal">{{resourceService?.frmelmnts?.lbl?.requestReport}}</label> -->
      <div [formGroup]="reportForm" class="d-flex flex-ai-center">
        <div class="sb-field w-25">
        <mat-form-field appearance="fill" class="sb-mat__dropdown w-100 mb-16">
          <mat-label>Choose your report</mat-label>
          <mat-select formControlName="reportType" role="listbox" aria-label="Choose your report" class="selection"
            (selectionChange)="reportChanged($event)">
            <mat-option class="mat-dropdown__options" role="option" *ngFor="let option of reportTypes" [value]="option"
            attr.aria-label="{{option.title}}">{{option.title}}</mat-option>
          </mat-select>
        </mat-form-field>
      </div>
        <div class="sb-field filterTable mx-16 mb-0">
          <input class="sb-form-control" type="text" formControlName="password" placeholder="Enter password" aria-label="enter password">
        </div>
        <button type="button" [disabled]="(!selectedReport || (selectedReport?.encrypt === 'true' && !reportForm.valid))"
        [ngClass]="{'sb-btn-disabled': (!selectedReport || (selectedReport?.encrypt === 'true' && !reportForm.valid))}"
        tabindex="0" (click)="submitRequest()" class="sb-btn sb-btn-normal sb-btn-primary">
          {{resourceService?.frmelmnts?.lbl?.request}}
        </button>
      </div>
      <!-- <p *ngIf="!isProcessed" class="fnormal note-text mt-8 mb-24 administrator-text">{{resourceService.frmelmnts?.lbl?.downloadReqNote}}</p> -->
      <div *ngIf="isProcessed" class="d-flex">
        <div class="information-icon">
          <img src="assets/images/error-icon.svg" width="18px"></div>
        <p class="fsmall note-text my-8 administrator-text">{{resourceService.frmelmnts?.lbl?.reportStatus}}</p>
      </div>
      <!-- <p class="administrator-text">{{resourceService.frmelmnts?.lbl?.ondemandReportNote | interpolate:'{instance}': instance}}</p> -->
      <p class="fsmall note-text my-8 administrator-text" *ngIf="!isProcessed"> 
       {{resourceService?.frmelmnts?.lbl?.pswdRule}}
        </p>
     
         
    </div>
  </div>
</div>
<div class="fsmall font-weight-bold download-section-text">{{resourceService.frmelmnts?.lbl?.downloadSectionNote}}</div>
<p class="fsmall mt-8 mb-16 administrator-text">{{resourceService?.frmelmnts?.lbl?.repgenAdminNote | interpolate:'{instance_course_terms}': instance}}</p>
<sb-datatable [name]="fileName" [message]="message" [data]="onDemandReportData" [columns]="columns"
              [downloadCSV]="isDownloadReport" (downloadLink)="onDownloadLinkFail($event)" ></sb-datatable>
    
                    ./on-demand-reports.component.scss
                
@use "@project-sunbird/sb-styles/assets/mixins/mixins" as *;
.information-icon{
    position: relative;
    top: calculateRem(8px);
  }
  .administrator-text {
    font-style: italic;
  }
  .administrator-text {
    font-style: italic;
    color:var(--gray-200);
  }
  .download-section-text{
    font-size: calculateRem(14px);
    color: var(--gray-800);
  }
  ::ng-deep {
    html[layout=joy] .sb-btn-normal {
      height: 2rem;
      box-shadow: none;
   }
  }