-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(table): add generic table component
- Loading branch information
Showing
13 changed files
with
386 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,12 @@ | ||
export * from './module'; | ||
|
||
export * from './collapsible'; | ||
export * from './confirm-dialog'; | ||
export * from './clickout'; | ||
export * from './clone'; | ||
export * from './keyvalue'; | ||
export * from './list'; | ||
export * from './panel'; | ||
export * from './sidenav'; | ||
export * from './spinner'; | ||
export * from './table'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export * from './table.component'; | ||
export * from './table-database'; | ||
export * from './table-datasource'; | ||
export * from './table-model.interface'; | ||
export * from './table-action-color.enum'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export enum TableActionColor { | ||
primary, | ||
accent, | ||
warn | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import {BehaviorSubject} from 'rxjs/BehaviorSubject'; | ||
|
||
export class TableDatabase { | ||
/** Stream that emits whenever the data has been modified. */ | ||
dataChange: BehaviorSubject<any[]> = new BehaviorSubject<any[]>([]); | ||
get data(): any[] { return this.dataChange.value; } | ||
|
||
constructor(data?) { | ||
if (data) { | ||
this.dataChange.next(data); | ||
} | ||
} | ||
|
||
set(data) { | ||
this.dataChange.next(data); | ||
} | ||
|
||
add(item) { | ||
const copiedData = this.data.slice(); | ||
copiedData.push(item); | ||
this.set(copiedData); | ||
} | ||
|
||
remove(item) { | ||
const copiedData = this.data.slice(); | ||
const index = copiedData.indexOf(item); | ||
copiedData.splice(index, 1); | ||
this.set(copiedData); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { DataSource } from '@angular/cdk'; | ||
import { MdSort } from '@angular/material'; | ||
|
||
import { Observable } from 'rxjs/Observable'; | ||
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; | ||
|
||
import { TableDatabase, TableModel } from './index'; | ||
|
||
export class TableDataSource extends DataSource<any> { | ||
_filterChange = new BehaviorSubject(''); | ||
get filter(): string { return this._filterChange.value; } | ||
set filter(filter: string) { this._filterChange.next(filter); } | ||
|
||
constructor(private _database: TableDatabase, | ||
private _model: TableModel, | ||
private _sort: MdSort) { | ||
super(); | ||
} | ||
|
||
/** Connect function called by the table to retrieve one stream containing the data to render. */ | ||
connect(): Observable<any[]> { | ||
if (!this._database) { return Observable.merge([]); } | ||
const displayDataChanges = [ | ||
this._database.dataChange, | ||
this._filterChange, | ||
this._sort.mdSortChange | ||
]; | ||
|
||
return Observable.merge(...displayDataChanges) | ||
.map(() => { | ||
return this.getFilteredData(this._database.data); | ||
}).map((data) => { | ||
return this.getSortedData(data); | ||
}); | ||
} | ||
|
||
disconnect() {} | ||
|
||
getFilteredData(data): any[] { | ||
if (!this.filter) { return data; } | ||
return data.slice().filter((item: any) => { | ||
|
||
let searchStr: string = this._model.columns | ||
.filter((c) => c.filterable) | ||
.map((c) => item[c.name]) | ||
.join(' ').toLowerCase(); | ||
|
||
return searchStr.indexOf(this.filter.toLowerCase()) != -1; | ||
}); | ||
} | ||
|
||
getSortedData(data): any[] { | ||
if (!this._sort.active || this._sort.direction == '') { return data; } | ||
|
||
return data.sort((a, b) => { | ||
let propertyA: number|string = a[this._sort.active]; | ||
let propertyB: number|string = b[this._sort.active]; | ||
|
||
let valueA = isNaN(+propertyA) ? propertyA : +propertyA; | ||
let valueB = isNaN(+propertyB) ? propertyB : +propertyB; | ||
|
||
return (valueA < valueB ? -1 : 1) * (this._sort.direction == 'asc' ? 1 : -1); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { TableActionColor } from './table-action-color.enum'; | ||
|
||
export interface TableColumn { | ||
name: string, | ||
title: string, | ||
sortable?: boolean, | ||
filterable?: boolean, | ||
displayed?: boolean | ||
} | ||
|
||
export interface ClickAction { | ||
( item: any ): void; | ||
} | ||
|
||
export interface TableAction { | ||
icon: string, | ||
color?: TableActionColor | ||
click: ClickAction | ||
} | ||
|
||
export interface TableModel { | ||
columns: TableColumn[], | ||
actions?: TableAction[] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<div class='table-container'> | ||
<div class='table-header'> | ||
<md-input-container floatPlaceholder='never'> | ||
<input mdInput #filter [placeholder]="'Filter' | translate"> | ||
</md-input-container> | ||
</div> | ||
|
||
<md-table #table [dataSource]='dataSource' mdSort> | ||
|
||
<ng-container [cdkColumnDef]='column.name' *ngFor='let column of model.columns'> | ||
<ng-container *ngIf='column.sortable'> | ||
<md-header-cell *cdkHeaderCellDef md-sort-header> {{column.title}} </md-header-cell> | ||
</ng-container> | ||
|
||
<ng-container *ngIf='!column.sortable'> | ||
<md-header-cell *cdkHeaderCellDef> {{column.title}} </md-header-cell> | ||
</ng-container> | ||
|
||
<md-cell *cdkCellDef='let row' class="mat-cell-text"> {{getValue(row, column.name)}} </md-cell> | ||
</ng-container> | ||
|
||
<!-- Action Column --> | ||
<ng-container cdkColumnDef='action'> | ||
<md-header-cell *cdkHeaderCellDef></md-header-cell> | ||
<md-cell *cdkCellDef='let row'> | ||
<button *ngFor='let action of model.actions' | ||
md-mini-fab | ||
[color]='getActionColor(action.color)' | ||
(click)='action.click(row)'> | ||
<md-icon>{{action.icon}}</md-icon> | ||
</button> | ||
</md-cell> | ||
</ng-container> | ||
|
||
<md-header-row *cdkHeaderRowDef='displayedColumns'></md-header-row> | ||
<md-row *cdkRowDef='let row; columns: displayedColumns;'></md-row> | ||
|
||
</md-table> | ||
|
||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; | ||
|
||
import { IgoTestModule } from '../../../test/module'; | ||
import { IgoSharedModule } from '../../shared'; | ||
|
||
import { TableComponent } from './table.component'; | ||
|
||
|
||
describe('TableComponent', () => { | ||
let component: TableComponent; | ||
let fixture: ComponentFixture<TableComponent>; | ||
|
||
beforeEach(async(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [ | ||
IgoTestModule, | ||
IgoSharedModule | ||
], | ||
declarations: [ | ||
TableComponent | ||
], | ||
providers: [] | ||
}) | ||
.compileComponents(); | ||
})); | ||
|
||
beforeEach(() => { | ||
fixture = TestBed.createComponent(TableComponent); | ||
component = fixture.componentInstance; | ||
fixture.detectChanges(); | ||
}); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
@require '../../../style/var.styl'; | ||
@require '../../../style/media.styl'; | ||
|
||
/*** Main ***/ | ||
:host { | ||
width: 100%; | ||
height: 100%; | ||
display: block; | ||
} | ||
|
||
.table-container { | ||
display: flex; | ||
flex-direction: column; | ||
max-height: 100%; | ||
} | ||
|
||
.table-header { | ||
min-height: 64px; | ||
max-width: 500px; | ||
display: flex; | ||
align-items: baseline; | ||
padding: 8px 24px 0; | ||
font-size: 20px; | ||
justify-content: space-between; | ||
} | ||
|
||
.mat-input-container { | ||
font-size: 14px; | ||
flex-grow: 1; | ||
margin-left: 32px; | ||
} | ||
|
||
.mat-table { | ||
overflow: auto; | ||
} | ||
|
||
.mat-header-row, .mat-row { | ||
height: 60px; | ||
} | ||
|
||
.mat-cell-text { | ||
overflow: hidden; | ||
word-wrap: break-word; | ||
} | ||
|
||
button { | ||
margin-right: 10px; | ||
} |
Oops, something went wrong.