File

src/app/modules/shared/components/sb-datatable/sb-datatable.component.ts

Implements

OnInit OnChanges

Metadata

Index

Properties
Methods
Inputs
Outputs

Constructor

constructor(resourceService: ResourceService, telemetryService: TelemetryService)
Parameters :
Name Type Optional
resourceService ResourceService No
telemetryService TelemetryService No

Inputs

batch
Type : any
columns
Type : any
data
Type : any
downloadCSV
Type : any
isColumnsSearchable
Type : any
message
Type : any
name
Type : any

Outputs

downloadLink
Type : EventEmitter

Methods

clearSearch
clearSearch()
Returns : void
downloadCSVFile
downloadCSVFile()
Returns : void
downloadUrl
downloadUrl(prop, row)
Parameters :
Name Optional
prop No
row No
Returns : void
filterDataTable
filterDataTable()
Returns : void
ngOnChanges
ngOnChanges()
Returns : void
ngOnInit
ngOnInit()
Returns : void
onColumnFilter
onColumnFilter(key, value)
Parameters :
Name Optional
key No
value No
Returns : void
setInteractEventData
setInteractEventData()
Returns : void

Properties

Public csvExporter
Type : any
Public filterModel
Type : object
Default value : {}
Public keyUp
Default value : new Subject<object>()
Public listFilter
Type : object
Default value : {}
Public resourceService
Type : ResourceService
Public searchData
Public showLoader
Default value : false
Public tableData
Type : []
Default value : []
Public tableMessage
Public telemetryService
Type : TelemetryService
import { Component, OnInit, Input, OnChanges, EventEmitter, Output } from '@angular/core';
import { ExportToCsv } from 'export-to-csv';
import * as _ from 'lodash-es';
import dayjs from 'dayjs';
import {ResourceService} from '../../services/resource/resource.service';
import { Subject } from 'rxjs';
import { TelemetryService } from '@sunbird/telemetry';

export const multiFilter = (arr: Object[], filters: Object) => {
  const filterKeys = Object.keys(filters);
  return arr.filter(eachObj => {
    return filterKeys.every(eachKey => {
      if (!filters[eachKey]) {
        return true;
      } else if (!filters[eachKey].length) {
        return true;
      }
        if (typeof (eachObj[eachKey]) === 'string' && eachObj[eachKey] !== null && eachObj[eachKey] !== undefined) {
          const each = eachObj[eachKey].toLowerCase();
          return each.includes(filters[eachKey].toLowerCase().trim());
        } else {
          const keys = eachKey.split('.');
          if (keys.length > 1) {
            return filters[eachKey].includes(eachObj[keys[0]][keys[1]]);
          } else {
            return filters[eachKey].includes(eachObj[keys[0]]);
          }
        }
    });
  });
};

@Component({
  selector: 'sb-datatable',
  templateUrl: './sb-datatable.component.html',
  styleUrls: ['./sb-datatable.component.scss']
})
export class SbDatatableComponent implements OnInit, OnChanges {

  @Input() data;
  @Input() columns;
  @Input() downloadCSV;
  @Input() name;
  @Input() message;
  @Input() batch;
  @Input() isColumnsSearchable;
  @Output() downloadLink = new EventEmitter();
  public tableData = [];
  public searchData;
  public showLoader = false;
  public csvExporter: any;
  public keyUp = new Subject<object>();
  public listFilter = {};
  public filterModel = {};
  public tableMessage;

  constructor(public resourceService: ResourceService, public telemetryService: TelemetryService) {
  }

  ngOnInit() {
      this.keyUp
      .subscribe(obj => {
        this.onColumnFilter(obj['key'], obj['value']);
      });
  }

  onColumnFilter(key, value) {
    if (value) {
      this.listFilter[key] = value;
    } else {
      delete this.listFilter[key];
    }
    this.filterDataTable();
  }

  filterDataTable() {
    this.tableData = multiFilter(this.data, this.listFilter);
  }
  ngOnChanges() {
    this.tableMessage = {
      'emptyMessage': this.message
    };
    this.tableData = _.cloneDeep(this.data);
    _.forEach(this.columns, (x) => {
      this.filterModel[x.prop] = null;
    });
  }

  downloadUrl(prop, row) {
    if (prop === 'downloadUrls') {
      const isLinkExpired = new Date().getTime() > new Date(row.expiresAt).getTime();
      if (isLinkExpired) {
        this.downloadLink.emit(row);
      } else {
        window.open(row['downloadUrls'][0], '_blank');
      }
    }
  }

  clearSearch() {
    this.searchData = '';
  }

  setInteractEventData() {
    const downloadReports = {
      context: {
        env: 'reports',
        cdata: [
          {id: _.get(this.batch , 'courseId'), type: 'Course'},
          {id: _.get(this.batch , 'batchId'), type: 'Batch'}
        ]
      },
      edata: {
        id: 'download-summary-report',
        type: 'click',
        pageid: 'summary-report'
      }
    };
    this.telemetryService.interact(downloadReports);
  }


  downloadCSVFile() {
    this.setInteractEventData();
    this.name = `${this.name}_${dayjs().format('YYYY-MM-DD_HH_mm')}`;
    const options = {
      filename: this.name,
      fieldSeparator: ',',
      quoteStrings: '"',
      decimalSeparator: '.',
      showLabels: true,
      useTextFile: false,
      useBom: true,
      useKeysAsHeaders: false,
      headers: _.map(this.columns, (column) => column.name)
    };
    this.csvExporter = new ExportToCsv(options);
    this.csvExporter.generateCsv(this.tableData);
  }
}
<div class="datatable-content">
    <div  *ngIf="downloadCSV" class="d-flex flex-ai-center flex-jc-flex-end download-report">
      <span class="mx-8 cursor-pointer fsmall" tabindex="0" (click)="downloadCSVFile()">{{resourceService.frmelmnts?.lbl?.downloadAsCSV}}</span>
      <img src="assets/images/download-icon.svg">
    </div>
  <div class="sb-table-responsive-div">
    <ngx-datatable #table class="material striped" [columnMode]="'force'" [rows]="tableData" [headerHeight]="50"
      [messages]="tableMessage" [reorderable]="false"  [scrollbarV]="true"  [virtualization]="false" [rowHeight]="50" [footerHeight]="0" >
      <ngx-datatable-column *ngFor="let col of columns" [name]="col.name" [sortable]="col.isSortable"
        [draggable]="false" [resizeable]="false" [prop]="col.prop" [width]="100">
        <ng-template ngx-datatable-header-template>
          <div class="sb-field-group">
            <label class="pl-0 mb-8">{{col.name}}</label>
            <div class="sb-field filterTable" *ngIf="isColumnsSearchable">
              <input class="sb-form-control" [(ngModel)]="filterModel[col.prop]"
                (input)="keyUp.next({value:$event.target.value,key:col.prop})" type="text"
                [placeholder]="col.placeholder">
            </div>
          </div>
        </ng-template>
        <ng-template let-value="value" let-row="row" ngx-datatable-cell-template>
          <span *ngIf="col.prop !== 'downloadUrls'"
                [ngClass]="{'success-label' : (col.prop === 'status' && value === 'SUCCESS'),'inprocess-label' : (col.prop === 'status' && value === 'PROCESSING'),'inprocess-label' : (col.prop === 'status' && value === 'SUBMITTED'),'failed-label' : (col.prop === 'status' && value === 'FAILED')}">
            {{ value | sbDataTable : col.type}}
          </span>
          <span *ngIf="col.prop === 'downloadUrls' && value && value.length > 0" tabindex="0" (click)="downloadUrl(col.prop , row)">
            <a href="javascript:void(0)">{{resourceService?.frmelmnts?.btn?.download}}</a>
          </span>
        </ng-template>
      </ngx-datatable-column>
    </ngx-datatable>
  </div>
</div>

./sb-datatable.component.scss

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

    .datatable-content{
      .note-text {
        color: var(--gray-200);
      }
      .request-report-label,.download-section-text{
        font-size: calculateRem(14px);
        color: var(--gray-800);
      }
    
      .sb-table-course-dashboard {
        border:calculateRem(0.5px) solid var(--gray-100);
        cursor: pointer;
        & thead th {
          font-size: 0.875rem;
          padding: 1rem;
          background-color: var(--primary-100);
      }
      &.sb-table-striped tbody tr:nth-child(n) {
        background-color: var(--white);
      }
        &.sb-table-striped tbody tr:nth-child(2n) {
          background-color: var(--gray-100);
        }
        &.sb-table-sortable {
          th.sb-sort-icon {
            cursor: pointer;
          }
      
          .sb-sort-icon.ascending::before,
          .sb-sort-icon.descending::after {
            border: calculateRem(4px) solid transparent;
            content: "";
            height: 0;
            right: calculateRem(8px);
            top: 50%;
            position: absolute;
            width: 0;
            border-bottom-color: var(--primary-color);
            cursor: pointer;
          }
      
          .sb-sort-icon.ascending::before {
            margin-top: calculateRem(-8px);
          }
      
          .sb-sort-icon.descending::after {
            margin-top: calculateRem(2px);
            transform: rotate(180deg);
            -webkit-transform: rotate(180deg);
          }
        }
        .success-label {
          padding: calculateRem(4px) calculateRem(8px);
          border-radius: calculateRem(12px);
          font-size: calculateRem(10px);
          color: var(--white);
          background: var(--secondary-100);
          text-align: center;
        }
    
        .failed-label {
          padding: calculateRem(4px) calculateRem(8px);
          border-radius: calculateRem(12px);
          font-size: calculateRem(10px);
          color: var(--white);
          background: var(--red-100);
          text-align: center;
        }
    
        .inprocess-label {
          padding: calculateRem(4px) calculateRem(8px);
          border-radius: calculateRem(12px);
          font-size: calculateRem(10px);
          color: var(--white);
          background: var(--tertiary-100);
          text-align: center;
        }
      }
      .request-download-text{
        width: 100%;
        text-align: center;
        border:calculateRem(0.5px) solid var(--gray-100);
        border-top: 0px;
        color:var(--gray-200);
      }
    }


.filterTable{
  z-index: 9999;
}

::ng-deep {
.ngx-datatable .datatable-header .datatable-header-cell .sort-btn{
    cursor: pointer !important;
    position: absolute !important;
    top: 0 !important;
    bottom: calculateRem(24px) !important;
    right: calculateRem(10px) !important;
    left: 0 !important;
    padding-top: calculateRem(19px) !important;
    text-align: right !important;
}

.ngx-datatable.scroll-vertical .datatable-body{
  height: calculateRem(200px) !important;
}

.ngx-datatable.material .datatable-header .datatable-header-cell{
  background-color: transparent !important;
}

.ngx-datatable.material .datatable-body .datatable-body-row .datatable-body-cell {
  .success-label{
    padding: calculateRem(4px) calculateRem(8px) !important;
  border-radius: calculateRem(12px) !important;
  font-size: calculateRem(10px) !important;
  color: var(--secondary-100) !important;
  border: calculateRem(1px) solid var(--secondary-100) !important;
  text-align: center !important;
}
.inprocess-label {
padding: calculateRem(4px) calculateRem(8px) !important;
border-radius: calculateRem(12px) !important;
font-size: calculateRem(10px) !important;
color: var(--tertiary-100) !important;
border: calculateRem(1px) solid var(--tertiary-100) !important;
text-align: center !important;
}
.failed-label {
  padding: calculateRem(4px) calculateRem(8px) !important;
  border-radius: calculateRem(12px) !important;
  font-size: calculateRem(10px) !important;
  color: var(--red-100)  !important;
  border: calculateRem(1px) solid var(--red-100) !important;
  text-align: center !important;
}
.completed-label  {
  padding: calculateRem(4px) calculateRem(8px) !important;
  border-radius: calculateRem(12px) !important;
  font-size: calculateRem(10px) !important;
  color: var(--gray-100)  !important;
  border: calculateRem(1px) solid var(--gray-100) !important;
  text-align: center !important;
}
}
}

.download-report{
  position: relative;
  bottom: calculateRem(10px);
  padding-bottom: calculateRem(12px);
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""