novo-elements
Version:
Bullhorn's NOVO Element Repository for Angular 2
477 lines (447 loc) • 17.8 kB
text/typescript
// NG2
import { Component, OnInit } from '@angular/core';
// APP
// import { MovieDataProvider } from './MovieDataProvider';
import { TableData } from './TableData';
import { ArrayCollection } from './../../../../src/services/data-provider/ArrayCollection';
let TableDemoTpl = require('./templates/TableDemo.html');
let EditableTableDemoTpl = require('./templates/EditableTableDemo.html');
let DetailsTableDemoTpl = require('./templates/DetailsTableDemo.html');
let SelectAllTableDemoTpl = require('./templates/SelectAllTableDemo.html');
let MovieTableDemoTpl = require('./templates/MovieTableDemo.html');
let TotalFooterTableDemoTpl = require('./templates/TotalFooterTableDemo.html');
// Vendor
import { DateCell, PercentageCell, BaseRenderer, NovoTableElement, NovoTableConfig, TextBoxControl, TablePickerControl, SelectControl, NovoDropdownCell } from './../../../../index';
const template = `
<div class="container">
<h1>Table <small><a target="_blank" href="https://bullhorn.github.io/novo-elements/blob/master/src/elements/table">(source)</a></small></h1>
<p>Tables allow users to view date in a tabular format and perform actions such as Sorting and Filtering. Different configuration are possible for pagination or infinite scroll. Feature to be added include: Custom Item Renderers, etc...</p>
<h2>Types</h2>
<h5>Basic Table</h5>
<p>This is the most basic table.</p>
<div class="example table-demo">${TableDemoTpl}</div>
<code-snippet [code]="TableDemoTpl"></code-snippet>
<h5>Details Table</h5>
<p>This has a row renderer to show a new details row that is expanded when you click on the action column.</p>
<div class="example table-demo">${DetailsTableDemoTpl}</div>
<code-snippet [code]="DetailsTableDemoTpl"></code-snippet>
<h5>Select All Table w/ Custom Actions</h5>
<p>This has checkboxes for selection with custom actions.</p>
<div class="example table-demo">${SelectAllTableDemoTpl}</div>
<code-snippet [code]="SelectAllTableDemoTpl"></code-snippet>
<h5>Remote Table Provider</h5>
<p>This has connects to the OMDB service.</p>
<div class="example table-demo">${MovieTableDemoTpl}</div>
<code-snippet [code]="MovieTableDemoTpl"></code-snippet>
<h5>Editable Table</h5>
<p>Can be put into edit mode and use editors that are set on the column to modify the data.</p>
<div class="example table-demo">${EditableTableDemoTpl}</div>
<code-snippet [code]="EditableTableDemoTpl"></code-snippet>
<h5>Total/Average Footer</h5>
<p>Easily configure a footer to sum or average up columns.</p>
<div class="example table-demo">${TotalFooterTableDemoTpl}</div>
<code-snippet [code]="TotalFooterTableDemoTpl"></code-snippet>
</div>
`;
const HEADER_COLORS = ['aqua', 'ocean', 'mint', 'grass', 'sunflower', 'company', 'lead', 'positive', 'black'];
export class StatusCell extends BaseRenderer {
}
export class ExtraDetails extends BaseRenderer {
}
export class ImageCell extends BaseRenderer {
}
export class ActionsCell extends BaseRenderer {
constructor() {
super();
}
getActionContext(data, meta) {
return { item: data, meta };
}
}
interface TableDemoConfig {
rows?: any;
dataProvider?: any;
columns: any[];
config: NovoTableConfig;
}
export class TableDemoComponent implements OnInit {
public TableDemoTpl: string = TableDemoTpl;
public DetailsTableDemoTpl: string = DetailsTableDemoTpl;
public SelectAllTableDemoTpl: string = SelectAllTableDemoTpl;
public MovieTableDemoTpl: string = MovieTableDemoTpl;
public EditableTableDemoTpl: string = EditableTableDemoTpl;
public TotalFooterTableDemoTpl: string = TotalFooterTableDemoTpl;
public customRowOptions: Array<any> = [
{ label: '10', value: 10 },
{ label: '20', value: 20 },
{ label: '30', value: 30 },
{ label: '40', value: 40 }
];
public theme: string;
public basic: TableDemoConfig;
public details: TableDemoConfig;
private selectAll: TableDemoConfig;
public remote: TableDemoConfig;
public totalFooter: TableDemoConfig;
public editable: TableDemoConfig;
public editableNewRowDefault: any = { name: 'Default', jobType: 'Contract' };
constructor() {
let columns = [
{ title: 'Actions', renderer: ActionsCell },
{ title: 'Name', name: 'name', ordering: true, type: 'link', filtering: true },
{ title: 'Position', name: 'position', ordering: true, filtering: true },
{
title: 'Extn.',
name: 'ext',
ordering: true,
renderer: object => {
return object.ext.obj;
},
compare: (sort, previous, current) => {
let first = previous.obj,
second = current.obj;
if (first > second) {
return sort === 'desc' ? -1 : 1;
}
if (first < second) {
return sort === 'asc' ? -1 : 1;
}
return 0;
}
},
{
title: 'Start date',
type: 'date',
name: 'startDate',
renderer: DateCell,
ordering: true,
filtering: true,
range: true
},
{
title: '%',
name: 'percent',
ordering: true,
renderer: PercentageCell
},
{
title: 'Salary',
name: 'salary',
ordering: true,
renderer: (object) => {
return `$ ${Number(object.salary).toFixed(2)}`;
}
},
{
title: 'Status',
name: 'status',
renderer: NovoDropdownCell,
dropdownCellConfig: [
{
category: 'Update Status',
callback: this.updateStatus.bind(this),
options: [
{ label: 'New Lead', value: 'New Lead' },
{ label: 'Active', value: 'Active' },
{ label: 'Archived', value: 'Archived', }
]
},
{
category: 'Move',
callback: this.move.bind(this),
options: ['Kitten', 'Kitty']
},
{
callback: this.move.bind(this),
options: ['Meow', 'Kitty']
}
]
}
];
this.basic = {
columns: columns.slice(),
rows: [],
config: {
paging: {
current: 1,
itemsPerPage: 10,
onPageChange: event => {
this.basic.config.paging.current = event.page;
this.basic.config.paging.itemsPerPage = event.itemsPerPage;
}
},
filtering: true,
sorting: true,
ordering: true,
resizing: true
}
};
this.details = {
columns: columns.slice(),
rows: TableData.slice(),
config: {
paging: {
current: 1,
itemsPerPage: 10,
onPageChange: event => {
this.details.config.paging.current = event.page;
this.details.config.paging.itemsPerPage = event.itemsPerPage;
}
},
sorting: true,
filtering: true,
ordering: true,
resizing: true,
hasDetails: true,
detailsRenderer: ExtraDetails
}
};
this.selectAll = {
columns: columns.slice(),
rows: TableData.slice(),
config: {
paging: {
current: 1,
itemsPerPage: 10,
onPageChange: event => {
this.selectAll.config.paging.current = event.page;
this.selectAll.config.paging.itemsPerPage = event.itemsPerPage;
}
},
sorting: true,
filtering: true,
ordering: true,
resizing: true,
selectAllEnabled: true,
rowSelectionStyle: 'checkbox'
}
};
let imdbColumns = [
{ title: 'Title', name: 'Title', ordering: true, filtering: true },
{ title: 'Year', name: 'Year', ordering: true, filtering: true },
{ title: 'Type', name: 'Type', ordering: true, filtering: true, options: ['movie', 'series', 'episode'], multiple: true },
{ title: 'Poster', name: 'Poster', ordering: false, filtering: false, renderer: ImageCell }
];
// this.remote = {
// columns: imdbColumns.slice(),
// dataProvider: new MovieDataProvider(),
// config: {
// paging: {
// current: 1,
// itemsPerPage: 10,
// onPageChange: event => {
// this.basic.config.paging.current = event.page;
// this.basic.config.paging.itemsPerPage = event.itemsPerPage;
// }
// },
// filtering: true,
// sorting: true,
// ordering: true,
// resizing: true
// }
// };
// For columns that can be edited, pass an editor property
let names = [
'Joshua Godi',
'Kameron Sween',
'Brian Kimball',
'Sweeney Todd',
'Tom Cruise',
'Ed Bailey',
'Bo Jackson',
'Ernie McDudson'
];
this.editable = {
columns: [
{
title: 'Name', name: 'name', ordering: true, filtering: true, editorType: 'TablePickerControl', editorConfig: { key: 'name', config: { options: names } }
},
{
title: 'Job Type', name: 'jobType', ordering: true, filtering: true, editorType: 'SelectControl', editorConfig: { key: 'jobType', options: ['Freelance', 'Contract', 'Billable'] }
},
{
title: 'Rate',
name: 'rate',
ordering: true,
filtering: true,
renderer: PercentageCell,
editorType: 'TextBoxControl',
editorConfig: {
key: 'rate',
type: 'percentage',
required: true,
interactions: [
{
event: 'change',
script: (form) => {
console.log('Form Interaction Called!', form); // tslint:disable-line
if (form.value.rate) {
if (Number(form.value.rate) >= .75) {
form.controls.rating.setValue('High');
} else if (Number(form.value.rate) >= .50) {
form.controls.rating.setValue('Medium');
} else {
form.controls.rating.setValue('Low');
}
}
}
}
]
}
},
{ title: 'Rating', name: 'rating' }
],
rows: new ArrayCollection([
{ id: 1, name: 'Joshua Godi', jobType: 'Freelance', rate: null, rating: 'Low' },
{ id: 2, name: 'Brian Kimball', jobType: 'Contact', rate: .50, rating: 'Medium' },
{ id: 3, name: 'Kameron Sween', jobType: 'Billable', rate: 1.00, rating: 'High' }
]),
config: {
paging: {
current: 1,
itemsPerPage: 10,
onPageChange: event => {
this.basic.config.paging.current = event.page;
this.basic.config.paging.itemsPerPage = event.itemsPerPage;
}
},
filtering: true,
sorting: true,
ordering: true,
resizing: true
}
};
this.totalFooter = {
columns: [
{ title: 'Name', name: 'name', ordering: true, filtering: true },
{ title: 'Count 1', name: 'count1', ordering: true, filtering: true },
{ title: 'Count 2', name: 'count2', ordering: true, filtering: true },
{ title: 'Count 3', name: 'count3', ordering: true, filtering: true }
],
rows: [
{ id: 1, name: 'Name 1', count1: 1, count2: 2, count3: 3 },
{ id: 2, name: 'Name 2', count1: 1, count2: 2, count3: 3 },
{ id: 3, name: 'Name 3', count1: 1, count2: 2, count3: 3 },
{ id: 4, name: 'Name 4', count1: 1, count2: 2, count3: 3 },
{ id: 5, name: 'Name 5', count1: 1, count2: 2, count3: 3 },
],
config: {
paging: {
current: 1,
itemsPerPage: 10,
onPageChange: event => {
this.basic.config.paging.current = event.page;
this.basic.config.paging.itemsPerPage = event.itemsPerPage;
}
},
footers: [{
columns: ['count1', 'count2', 'count3'],
method: 'SUM',
labelColumn: 'name',
label: 'Mega Total'
}, {
columns: ['count1', 'count2', 'count3'],
method: 'AVG',
labelColumn: 'name',
label: 'Yep, Average!'
}],
filtering: true,
sorting: true,
ordering: true,
resizing: true
}
};
}
ngOnInit() {
this.theme = HEADER_COLORS[0];
}
reload() {
this.basic.rows = TableData.slice();
}
changeTheme() {
let idx = HEADER_COLORS.indexOf(this.theme);
if (idx === HEADER_COLORS.length - 1) {
idx = -1;
}
this.theme = HEADER_COLORS[idx + 1];
}
singleAction() {
window.alert('HI!');
}
selectedAction(action) {
window.alert(`You clicked ${action}!`);
}
save(table: NovoTableElement) {
// Save updated data and get fresh data for the table to reflect the changes!
let errorsOrData = table.validateAndGetUpdatedData();
if (!errorsOrData.errors) {
table.toggleLoading(true);
console.log('SAVING', errorsOrData); // tslint:disable-line
// TODO - save data - fetch the data
setTimeout(() => {
table.displayToastMessage({ icon: 'check', theme: 'success', message: 'Saved!' }, 2000);
table.saveChanges();
}, 2000);
} else {
console.log('ERRORS!', errorsOrData); // tslint:disable-line
table.displayToastMessage({ icon: 'caution', theme: 'danger', message: 'Errors!!' });
}
}
public updateStatus(data: any, status: string): void {
console.log('Update Status', data, status); // tslint:disable-line
}
public move(data: any, status: string): void {
console.log('Move', data, status); // tslint:disable-line
}
}