File
Implements
Index
Properties
|
|
Methods
|
|
Inputs
|
|
Outputs
|
|
isColumnsSearchable
|
Type : any
|
|
Outputs
downloadLink
|
Type : EventEmitter
|
|
Methods
clearSearch
|
clearSearch()
|
|
|
downloadCSVFile
|
downloadCSVFile()
|
|
|
downloadUrl
|
downloadUrl(prop, row)
|
|
Parameters :
Name |
Optional |
prop |
No
|
row |
No
|
|
filterDataTable
|
filterDataTable()
|
|
|
ngOnChanges
|
ngOnChanges()
|
|
|
onColumnFilter
|
onColumnFilter(key, value)
|
|
Parameters :
Name |
Optional |
key |
No
|
value |
No
|
|
setInteractEventData
|
setInteractEventData()
|
|
|
Public
csvExporter
|
Type : any
|
|
Public
filterModel
|
Type : object
|
Default value : {}
|
|
Public
keyUp
|
Default value : new Subject<object>()
|
|
Public
listFilter
|
Type : object
|
Default value : {}
|
|
Public
showLoader
|
Default value : false
|
|
Public
tableData
|
Type : []
|
Default value : []
|
|
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>
@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 with directive