Skip to content

Commit

Permalink
feat(core/table): add sort in table
Browse files Browse the repository at this point in the history
  • Loading branch information
sara-gnucoop committed Sep 13, 2022
1 parent 14c6241 commit 46b752b
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 26 deletions.
16 changes: 10 additions & 6 deletions projects/core/reports/src/xls-report/xls-report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,11 +323,15 @@ function _buildHtml(json: {[key: string]: string}[]): AjfWidget {
});
}

function _buildTable(sheetName: string, json: {[key: string]: string}[]): AjfWidget {
function _buildTable(
sheetName: string,
json: {[key: string]: string | number | boolean}[],
): AjfWidget {
let tableHeader: AjfTableDataset[] = [];
let dataRows = '[]';
let formula = '';
let pageSize = 0;
let pageSize = 10;
let pagination = false;
if (json.length > 1) {
const rowspan = 1;
const titles = Object.keys(json[0]);
Expand Down Expand Up @@ -358,7 +362,7 @@ function _buildTable(sheetName: string, json: {[key: string]: string}[]): AjfWid
borderBottom: '2px solid #ddd',
},
}));
pageSize = json[1]['pageSize'] ? +json[1]['pageSize'] : 0;
pagination = json[1]['pagination'] ? (json[1]['pagination'] as boolean) : false;

if ('dataset' in json[1]) {
formula = _buildFormListTable(json, colspans, textAlign);
Expand All @@ -371,7 +375,7 @@ function _buildTable(sheetName: string, json: {[key: string]: string}[]): AjfWid
titles.forEach(title => {
let elem = row[title] || `''`;
try {
elem = indicatorToJs(elem);
elem = indicatorToJs(elem as string);
} catch (err: any) {
const rowNum = row['__rowNum__'];
err = new Error(
Expand All @@ -392,7 +396,7 @@ function _buildTable(sheetName: string, json: {[key: string]: string}[]): AjfWid
}
}

if (pageSize > 0) {
if (pagination) {
return createWidget({
widgetType: AjfWidgetType.PaginatedTable,
pageSize: pageSize,
Expand Down Expand Up @@ -437,7 +441,7 @@ function _buildTable(sheetName: string, json: {[key: string]: string}[]): AjfWid
* buildFormDataset(projectsDataset, ['id_p','donors','budget','dino_area_name','calc_progress',])"
*/
function _buildFormListTable(
json: {[key: string]: string}[],
json: {[key: string]: string | number | boolean}[],
colspans: number[],
textAlign: string[],
): string {
Expand Down
3 changes: 2 additions & 1 deletion projects/core/table/src/table-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@

import {AjfCommonModule} from '@ajf/core/common';
import {CommonModule} from '@angular/common';
import {MatSortModule} from '@angular/material/sort';
import {NgModule} from '@angular/core';

import {AjfTable} from './table';

@NgModule({
imports: [AjfCommonModule, CommonModule],
imports: [AjfCommonModule, CommonModule, MatSortModule],
declarations: [AjfTable],
exports: [AjfTable],
})
Expand Down
10 changes: 6 additions & 4 deletions projects/core/table/src/table.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
<table *ngIf="data">
<table *ngIf="data" matSort (matSortChange)="sortData($event)">
<tr *ngIf="data.length > 0">
<th
*ngFor="let headerCell of data[0]"
*ngFor="let headerCell of data[0]; let idx = index"
[applyStyles]="headerCell.style"
[ngStyle]="{'padding': cellpadding}"
[attr.colspan]="headerCell.colspan"
[attr.rowspan]="headerCell.rowspan"
[innerHTML]="headerCell.value"
></th>
[mat-sort-header]="'column' + idx"
>
{{headerCell.value}}
</th>
</tr>
<ng-container *ngIf="data.length > 1">
<tr *ngFor="let row of data.slice(1)">
Expand Down
44 changes: 42 additions & 2 deletions projects/core/table/src/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@ import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
EventEmitter,
Input,
OnDestroy,
Output,
SecurityContext,
ViewEncapsulation,
} from '@angular/core';
import {Sort} from '@angular/material/sort';
import {DomSanitizer} from '@angular/platform-browser';

import {AjfTableCell} from './table-cell';

@Component({
Expand All @@ -39,7 +42,10 @@ import {AjfTableCell} from './table-cell';
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class AjfTable {
export class AjfTable implements OnDestroy {
/**
* data to be shown in the table
*/
private _data: AjfTableCell[][] = [];
get data(): AjfTableCell[][] {
return this._data;
Expand All @@ -50,6 +56,9 @@ export class AjfTable {
this._cdr.markForCheck();
}

/**
* cellpadding for all rows, include header
*/
private _cellpadding: string = '';
get cellpadding(): string {
return this._cellpadding;
Expand All @@ -60,6 +69,12 @@ export class AjfTable {
this._cdr.markForCheck();
}

/**
* Emit an event when sort arrows are selected
*/
@Output()
readonly sortSelected = new EventEmitter<Sort>();

/**
* Creates an instance of TableComponent.
*
Expand All @@ -79,4 +94,29 @@ export class AjfTable {
});
return data;
}

/**
* Sort visible data and emit an event to use for paginated table
* @param sort
* @returns
*/
sortData(sort: Sort): void {
if (!sort.active || sort.direction === '') {
return;
}
const sortedData = this._data.slice(1).sort((a, b) => {
const isAsc = sort.direction === 'asc';
return this._compare(a[0], b[0], isAsc);
});
this._data = [this._data[0], ...sortedData];
this.sortSelected.emit(sort);
}

private _compare(a: AjfTableCell, b: AjfTableCell, isAsc: boolean) {
return (a.value < b.value ? -1 : 1) * (isAsc ? 1 : -1);
}

ngOnDestroy(): void {
this.sortSelected.complete();
}
}
2 changes: 1 addition & 1 deletion projects/material/reports/src/paginated-table-widget.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@
</div>
</div>
<div class="ajf-paginated-table-item">
<ajf-table [data]="currentContent"></ajf-table>
<ajf-table [data]="currentContent" (sortSelected)="sortPaginatedData($event)"></ajf-table>
</div>
</div>
64 changes: 52 additions & 12 deletions projects/material/reports/src/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {
ViewEncapsulation,
} from '@angular/core';
import {MatDialog} from '@angular/material/dialog';
import {Sort} from '@angular/material/sort';
import {BehaviorSubject, Observable} from 'rxjs';

import {AjfChartWidgetComponent} from './chart-widget';
Expand Down Expand Up @@ -284,6 +285,8 @@ export class AjfPaginatedTableWidgetComponent
}
private _currentContent: AjfTableCell[][] = [];

private _allDataContent: AjfTableCell[][] = [];

get headerContent(): AjfTableCell[] {
return this._headerContent;
}
Expand All @@ -303,6 +306,10 @@ export class AjfPaginatedTableWidgetComponent
super(cdr, el);
}

/**
* Set initial data for the table on instance changes
* @param changes
*/
ngOnChanges(changes: SimpleChanges): void {
if (changes['instance']) {
if (
Expand All @@ -327,6 +334,11 @@ export class AjfPaginatedTableWidgetComponent
this._updateCurrentContent();
}

/**
* Got to next or previous page
* @param direction
* @returns
*/
goToPage(direction: 'next' | 'previous'): void {
const diff = direction === 'next' ? 1 : -1;
const newPage = this._currentPage + diff;
Expand All @@ -344,37 +356,65 @@ export class AjfPaginatedTableWidgetComponent
this._updateCurrentContent();
}

/**
* Sort all data for the table, not only current page data
* @param sort
* @returns
*/
sortPaginatedData(sort: Sort): void {
if (!sort.active || sort.direction === '') {
return;
}
if (this._allDataContent.length > 1) {
this._currentPage = 1;
this._canGoForward = this._currentPage < this._pages;
this._canGoBackward = false;

this._allDataContent = this._allDataContent.sort((a, b) => {
const isAsc = sort.direction === 'asc';
return this._compare(a[0], b[0], isAsc);
});
this._fillCurrentContent();
}
}

private _compare(a: AjfTableCell, b: AjfTableCell, isAsc: boolean) {
return (a.value < b.value ? -1 : 1) * (isAsc ? 1 : -1);
}

/**
* Set current header and data for the table, starting from page 1
*/
private _updateCurrentContent(): void {
this._canGoBackward = false;
if (this.instance == null || this.instance.data.length === 0) {
this._currentPage = 0;
this._pages = 0;
this._headerContent = [];
this._currentContent = [];
this._allDataContent = [];
} else {
this._headerContent = this.instance.data[0];
this._allDataContent = this.instance.data.slice(1);
this._currentPage = 1;
const {data} = this.instance;

this._pages = Math.ceil((data.length - 1) / this.paginatorConfig.pageSize);
this._pages = Math.ceil(this._allDataContent.length / this.paginatorConfig.pageSize);
this._canGoForward = this._pages > 1;
}
this._fillCurrentContent();
}

/**
* Update current data for the table, using page and sorted data
*/
private _fillCurrentContent(): void {
if (this.instance == null || this.instance.data.length === 0) {
this._headerContent = [];
this._currentContent = [];
return;
}

this._headerContent = this.instance.data[0];
if (this.instance.data.length === 1) {
if (this._allDataContent.length === 0 && this._headerContent.length > 0) {
this._currentContent = [this._headerContent];
} else {
const data = this.instance.data.slice(1);
const start = (this._currentPage - 1) * this.paginatorConfig.pageSize;
this._currentContent = [
this._headerContent,
...data.slice(start, start + this.paginatorConfig.pageSize),
...this._allDataContent.slice(start, start + this.paginatorConfig.pageSize),
];
}
this._cdr.markForCheck();
Expand Down

0 comments on commit 46b752b

Please sign in to comment.