439
app/routes/Tables/AgGrid/AgGrid.js
Executable file
439
app/routes/Tables/AgGrid/AgGrid.js
Executable file
@@ -0,0 +1,439 @@
|
||||
import React from 'react';
|
||||
import { chain, reduce } from 'lodash';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
import {
|
||||
Container,
|
||||
Card,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
Input,
|
||||
InputGroup,
|
||||
} from './../../../components';
|
||||
import {
|
||||
AgGridReact,
|
||||
AgGridColumn,
|
||||
} from './../../../components/agGrid';
|
||||
import {
|
||||
HeaderMain,
|
||||
} from './../../components/HeaderMain';
|
||||
import colors from './../../../colors';
|
||||
|
||||
/*
|
||||
CONSTS
|
||||
*/
|
||||
const DATA_URL = "https://api.myjson.com/bins/18oni9";
|
||||
|
||||
const COUNTRY_CODES = {
|
||||
Ireland: "ie",
|
||||
Spain: "es",
|
||||
"United Kingdom": "gb",
|
||||
France: "fr",
|
||||
Germany: "de",
|
||||
Sweden: "se",
|
||||
Italy: "it",
|
||||
Greece: "gr",
|
||||
Iceland: "is",
|
||||
Portugal: "pt",
|
||||
Malta: "mt",
|
||||
Norway: "no",
|
||||
Brazil: "br",
|
||||
Argentina: "ar",
|
||||
Colombia: "co",
|
||||
Peru: "pe",
|
||||
Venezuela: "ve",
|
||||
Uruguay: "uy"
|
||||
};
|
||||
|
||||
const IT_SKILLS = ["android", "css", "html5", "mac", "windows"];
|
||||
const IT_SKILLS_NAMES = ["Android", "CSS", "HTML 5", "Mac", "Windows"];
|
||||
|
||||
const PROFICIENCY_NONE = "none";
|
||||
const PROFICIENCY_ABOVE40 = "above40";
|
||||
const PROFICIENCY_ABOVE60 = "above60";
|
||||
const PROFICIENCY_ABOVE80 = "above80";
|
||||
|
||||
const PROFICIENCY_NAMES = ["No Filter", "Above 40%", "Above 60%", "Above 80%"];
|
||||
const PROFICIENCY_VALUES = [
|
||||
PROFICIENCY_NONE,
|
||||
PROFICIENCY_ABOVE40,
|
||||
PROFICIENCY_ABOVE60,
|
||||
PROFICIENCY_ABOVE80
|
||||
];
|
||||
|
||||
/*
|
||||
Custom Renderers
|
||||
*/
|
||||
const nameRenderer = ({ data }) => `
|
||||
<span class="text-inverse">
|
||||
${ data.name }
|
||||
</span>
|
||||
`;
|
||||
const skillsCellRenderer = ({ data }) =>
|
||||
chain(IT_SKILLS)
|
||||
.map((skill) => data && data.skills[skill] ?
|
||||
`<img src="//www.ag-grid.com/images/skills/${skill}.png" width="16px" title="${ skill }" />` : ''
|
||||
)
|
||||
.compact()
|
||||
.join(' ')
|
||||
.value();
|
||||
const countryCellRenderer = ({ value }) => `
|
||||
<img width="15" height="10" style="margin-bottom: 2px" src="https://flags.fmcdn.net/data/flags/mini/${COUNTRY_CODES[value]}.png" /> ${ value }
|
||||
`;
|
||||
const percentCellRenderer = ({ value }) => {
|
||||
const eDivPercentBar = document.createElement('div');
|
||||
eDivPercentBar.className = 'div-percent-bar';
|
||||
eDivPercentBar.style.width = `${value}%`;
|
||||
if (value < 20) {
|
||||
eDivPercentBar.style.backgroundColor = colors['danger'];
|
||||
} else if (value < 60) {
|
||||
eDivPercentBar.style.backgroundColor = colors['warning'];
|
||||
} else {
|
||||
eDivPercentBar.style.backgroundColor = colors['success'];
|
||||
}
|
||||
|
||||
const eValue = document.createElement('div');
|
||||
eValue.className = 'div-percent-value';
|
||||
eValue.innerHTML = `${value}%`;
|
||||
|
||||
const eOuterDiv = document.createElement('div');
|
||||
eOuterDiv.className = 'div-outer-div';
|
||||
eOuterDiv.appendChild(eDivPercentBar);
|
||||
eOuterDiv.appendChild(eValue);
|
||||
|
||||
return eOuterDiv;
|
||||
}
|
||||
|
||||
/*
|
||||
Custom Filters
|
||||
*/
|
||||
class SkillFilter {
|
||||
init({ filterChangedCallback }) {
|
||||
this.filterChangedCallback = filterChangedCallback;
|
||||
|
||||
// Initial State
|
||||
this.model = {
|
||||
android: false,
|
||||
css: false,
|
||||
html5: false,
|
||||
mac: false,
|
||||
windows: false
|
||||
}
|
||||
}
|
||||
getModel() { }
|
||||
setModel() { }
|
||||
getGui() {
|
||||
const eGui = document.createElement("div");
|
||||
|
||||
const eInstructions = document.createElement("div");
|
||||
eInstructions.className = "h6 dropdown-header";
|
||||
eInstructions.innerText = "Custom Skills Filter";
|
||||
eGui.appendChild(eInstructions);
|
||||
|
||||
const createCheckMarkElement = () => {
|
||||
var eCheckMark = document.createElement('i');
|
||||
eCheckMark.className = "fa fa-check fa-fw ml-auto text-success";
|
||||
|
||||
return eCheckMark;
|
||||
}
|
||||
|
||||
IT_SKILLS.forEach((skill, index) => {
|
||||
const skillName = IT_SKILLS_NAMES[index];
|
||||
|
||||
const eFilter = document.createElement("a");
|
||||
eFilter.className = "dropdown-item d-flex align-items-center"
|
||||
//eFilter.classList.toggle("active", this.model[skill]);
|
||||
eFilter.href="javascript:;";
|
||||
|
||||
const eImg = document.createElement("img");
|
||||
eImg.src = '//www.ag-grid.com/images/skills/' + skill + '.png';
|
||||
eImg.height = 20;
|
||||
eImg.className = "mr-2";
|
||||
|
||||
const eName = document.createElement('span');
|
||||
eName.innerText = skillName;
|
||||
|
||||
eFilter.appendChild(eImg);
|
||||
eFilter.appendChild(eName);
|
||||
if (this.model[skill]) {
|
||||
eFilter.appendChild(
|
||||
createCheckMarkElement()
|
||||
);
|
||||
}
|
||||
eGui.appendChild(eFilter);
|
||||
|
||||
eFilter.addEventListener("click", (e) => {
|
||||
const element = e.currentTarget;
|
||||
this.model[skill] = !this.model[skill];
|
||||
this.filterChangedCallback();
|
||||
|
||||
// Toggle check marks
|
||||
if (this.model[skill]) {
|
||||
element.appendChild(
|
||||
createCheckMarkElement()
|
||||
);
|
||||
} else {
|
||||
const eCheckMark = element.querySelector('i');
|
||||
|
||||
if (eCheckMark) { eCheckMark.remove() }
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
return eGui;
|
||||
}
|
||||
doesFilterPass({ data }) {
|
||||
const rowSkills = data.skills;
|
||||
const { model } = this;
|
||||
|
||||
const passed = reduce(
|
||||
IT_SKILLS,
|
||||
(acc, skill) => acc || (rowSkills[skill] && model[skill]),
|
||||
false
|
||||
);
|
||||
|
||||
return passed;
|
||||
}
|
||||
isFilterActive() {
|
||||
return (
|
||||
this.model.android ||
|
||||
this.model.css ||
|
||||
this.model.html5 ||
|
||||
this.model.mac ||
|
||||
this.model.windows
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ProficiencyFilter {
|
||||
init({ filterChangedCallback, valueGetter }) {
|
||||
this.filterChangedCallback = filterChangedCallback;
|
||||
this.valueGetter = valueGetter;
|
||||
|
||||
this.selected = PROFICIENCY_NONE;
|
||||
}
|
||||
getModel() { }
|
||||
setModel() { }
|
||||
getGui() {
|
||||
const eGui = document.createElement("div");
|
||||
|
||||
const eInstructions = document.createElement("div");
|
||||
eInstructions.className = "h6 dropdown-header";
|
||||
eInstructions.innerText = "Custom Proficiency Filter";
|
||||
eGui.appendChild(eInstructions);
|
||||
|
||||
PROFICIENCY_NAMES.forEach((name, index) => {
|
||||
const eFilter = document.createElement("a");
|
||||
eFilter.className = "dropdown-item"
|
||||
eFilter.classList.toggle("active", PROFICIENCY_VALUES[index] === this.selected);
|
||||
eFilter.href="javascript:;";
|
||||
eFilter.innerText = name;
|
||||
|
||||
eGui.appendChild(eFilter);
|
||||
|
||||
eFilter.addEventListener("click", (e) => {
|
||||
const element = e.currentTarget;
|
||||
element.parentElement.childNodes.forEach(function(node) {
|
||||
node.classList.toggle('active', false);
|
||||
});
|
||||
element.classList.toggle("active");
|
||||
|
||||
this.selected = PROFICIENCY_VALUES[index];
|
||||
this.filterChangedCallback();
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
return eGui;
|
||||
}
|
||||
doesFilterPass(params) {
|
||||
const value = this.valueGetter(params);
|
||||
const valueAsNumber = parseFloat(value);
|
||||
|
||||
switch (this.selected) {
|
||||
case PROFICIENCY_ABOVE40:
|
||||
return valueAsNumber >= 40;
|
||||
case PROFICIENCY_ABOVE60:
|
||||
return valueAsNumber >= 60;
|
||||
case PROFICIENCY_ABOVE80:
|
||||
return valueAsNumber >= 80;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
isFilterActive() {
|
||||
return this.selected !== PROFICIENCY_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
export default class AgGridExample extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
rowData: [],
|
||||
visibleCount: 0,
|
||||
quickFilterValue: ''
|
||||
};
|
||||
|
||||
this.gridApi = null;
|
||||
|
||||
this.onGridReady = this.onGridReady.bind(this);
|
||||
this.onModelUpdated = this.onModelUpdated.bind(this);
|
||||
this.onQuickFilterChange = this.onQuickFilterChange.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
fetch(DATA_URL)
|
||||
.then(res => res.json())
|
||||
.then(fetchedData => {
|
||||
this.setState({ rowData: fetchedData });
|
||||
});
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (this.gridApi) {
|
||||
if (this.state.quickFilterValue !== prevState.quickFilterValue) {
|
||||
this.gridApi.setQuickFilter(this.state.quickFilterValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onModelUpdated() {
|
||||
if (this.gridApi) {
|
||||
const model = this.gridApi.getModel();
|
||||
const visibleCount = model.getRowCount();
|
||||
|
||||
this.setState({ visibleCount });
|
||||
}
|
||||
}
|
||||
|
||||
onGridReady({ api }) {
|
||||
this.gridApi = api;
|
||||
}
|
||||
|
||||
onQuickFilterChange(e) {
|
||||
this.setState({ quickFilterValue: e.target.value });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { rowData, visibleCount, quickFilterValue } = this.state;
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<HeaderMain
|
||||
title="AgGrid"
|
||||
className="mb-5 mt-4"
|
||||
/>
|
||||
<p className="pb-3">
|
||||
<strong>Over 2,500 Companies use ag-Grid.</strong> The "ag" part of ag-Grid stands for "agnostic". The internal ag-Grid engine is implemented in TypeScript with zero dependencies. ag-Grid supports Angular through a wrapper component.
|
||||
The wrapper lets you use ag-Grid in your application like any other Angular component – you pass configuration through property bindings and handle events through event bindings.
|
||||
You can even use Angular components to customize the grid UI and cell contents / behavior.
|
||||
</p>
|
||||
|
||||
<Card>
|
||||
<CardHeader tag="h6" className="d-flex justify-content-between align-items-center bg-white bb-0">
|
||||
<span>AgGrid Example</span>
|
||||
<div className="d-flex align-items-center">
|
||||
<span className="mr-3 text-nowrap small">
|
||||
{ visibleCount } / { rowData.length }
|
||||
</span>
|
||||
|
||||
<InputGroup size="sm">
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Type text to filter..."
|
||||
value={ quickFilterValue }
|
||||
onChange={ this.onQuickFilterChange }
|
||||
/>
|
||||
</InputGroup>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<div className="ag-theme-bootstrap" style={{ height: '600px' }}>
|
||||
<AgGridReact
|
||||
rowData={ rowData }
|
||||
rowSelection="multiple"
|
||||
onGridReady={ this.onGridReady }
|
||||
onModelUpdated={ this.onModelUpdated }
|
||||
defaultColDef={{
|
||||
sortable: true,
|
||||
resizable: true,
|
||||
filter: true,
|
||||
}}
|
||||
>
|
||||
<AgGridColumn
|
||||
headerName=""
|
||||
width={ 70 }
|
||||
checkboxSelection
|
||||
suppressMenu
|
||||
/>
|
||||
|
||||
<AgGridColumn headerName="Employee">
|
||||
<AgGridColumn
|
||||
headerName="Name"
|
||||
field="name"
|
||||
width={ 150 }
|
||||
cellRenderer={ nameRenderer }
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName="Country"
|
||||
field="country"
|
||||
width={ 150 }
|
||||
cellRenderer={ countryCellRenderer }
|
||||
filterParams={{
|
||||
cellRenderer: countryCellRenderer,
|
||||
cellHeight: 20
|
||||
}}
|
||||
/>
|
||||
</AgGridColumn>
|
||||
|
||||
<AgGridColumn headerName="IT Skills">
|
||||
<AgGridColumn
|
||||
headerName="Skills"
|
||||
width={ 125 }
|
||||
sortable={ false }
|
||||
cellRenderer={ skillsCellRenderer }
|
||||
filter={ SkillFilter }
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName="Proficiency"
|
||||
field="proficiency"
|
||||
width={ 150 }
|
||||
cellRenderer={ percentCellRenderer }
|
||||
filter={ ProficiencyFilter }
|
||||
/>
|
||||
</AgGridColumn>
|
||||
|
||||
<AgGridColumn headerName="Contact">
|
||||
<AgGridColumn
|
||||
headerName="Mobile"
|
||||
field="mobile"
|
||||
width={ 180 }
|
||||
filter="agTextColumnFilter"
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName="Land-line"
|
||||
field="landline"
|
||||
width={ 180 }
|
||||
filter="agTextColumnFilter"
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName="Address"
|
||||
field="address"
|
||||
width={ 180 }
|
||||
filter="agTextColumnFilter"
|
||||
/>
|
||||
</AgGridColumn>
|
||||
</AgGridReact>
|
||||
</div>
|
||||
<CardFooter className="bg-white text-center">
|
||||
More examples of this table can be found <a href="https://www.ag-grid.com" target="_blank" rel="noopener noreferrer">Here</a>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
3
app/routes/Tables/AgGrid/index.js
Executable file
3
app/routes/Tables/AgGrid/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import AgGrid from './AgGrid';
|
||||
|
||||
export default AgGrid;
|
63
app/routes/Tables/ExtendedTable/ExtendedTable.js
Executable file
63
app/routes/Tables/ExtendedTable/ExtendedTable.js
Executable file
@@ -0,0 +1,63 @@
|
||||
import React from 'react';
|
||||
import { Container, Row, Col } from './../../../components';
|
||||
|
||||
import {
|
||||
AdvancedTableA,
|
||||
AdvancedTableB,
|
||||
BasicTable,
|
||||
BorderedTable,
|
||||
CellEdit,
|
||||
ClearSearch,
|
||||
LargeTable,
|
||||
SortTable
|
||||
} from './components';
|
||||
import { HeaderMain } from "../../components/HeaderMain";
|
||||
|
||||
export const ExtendedTable = () => (
|
||||
<Container>
|
||||
<HeaderMain
|
||||
title="Extended Tables"
|
||||
className="mb-5 mt-4"
|
||||
/>
|
||||
<Row className="mb-5">
|
||||
<Col>
|
||||
<AdvancedTableA />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="mb-5">
|
||||
<Col>
|
||||
<AdvancedTableB />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="mt-5">
|
||||
<Col>
|
||||
<BasicTable />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="mt-5">
|
||||
<Col>
|
||||
<LargeTable />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="mt-5">
|
||||
<Col>
|
||||
<BorderedTable />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="mt-5">
|
||||
<Col>
|
||||
<SortTable />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="mt-5">
|
||||
<Col>
|
||||
<ClearSearch />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className="mt-5">
|
||||
<Col>
|
||||
<CellEdit />
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
);
|
309
app/routes/Tables/ExtendedTable/components/AdvancedTableA.js
Executable file
309
app/routes/Tables/ExtendedTable/components/AdvancedTableA.js
Executable file
@@ -0,0 +1,309 @@
|
||||
import React from 'react';
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import paginationFactory from 'react-bootstrap-table2-paginator';
|
||||
import filterFactory, { Comparator, dateFilter } from 'react-bootstrap-table2-filter'
|
||||
import ToolkitProvider from 'react-bootstrap-table2-toolkit';
|
||||
import _ from 'lodash';
|
||||
import faker from 'faker/locale/en_US';
|
||||
import moment from 'moment';
|
||||
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
CustomInput,
|
||||
StarRating,
|
||||
ButtonGroup
|
||||
} from './../../../../components';
|
||||
import { CustomExportCSV } from './CustomExportButton';
|
||||
import { CustomSearch } from './CustomSearch';
|
||||
import { CustomPaginationPanel } from './CustomPaginationPanel';
|
||||
import { CustomSizePerPageButton } from './CustomSizePerPageButton';
|
||||
import { CustomPaginationTotal } from './CustomPaginationTotal';
|
||||
import { randomArray } from './../../../../utilities';
|
||||
import {
|
||||
buildCustomTextFilter,
|
||||
buildCustomSelectFilter,
|
||||
buildCustomNumberFilter
|
||||
} from './../filters';
|
||||
|
||||
const INITIAL_PRODUCTS_COUNT = 500;
|
||||
|
||||
const ProductQuality = {
|
||||
Good: 'product-quality__good',
|
||||
Bad: 'product-quality__bad',
|
||||
Unknown: 'product-quality__unknown'
|
||||
};
|
||||
|
||||
const sortCaret = (order) => {
|
||||
if (!order)
|
||||
return <i className="fa fa-fw fa-sort text-muted"></i>;
|
||||
if (order)
|
||||
return <i className={`fa fa-fw text-muted fa-sort-${order}`}></i>
|
||||
}
|
||||
|
||||
const generateRow = (index) => ({
|
||||
id: index,
|
||||
name: faker.commerce.productName(),
|
||||
quality: randomArray([
|
||||
ProductQuality.Bad,
|
||||
ProductQuality.Good,
|
||||
ProductQuality.Unknown
|
||||
]),
|
||||
price: (1000 + Math.random() * 1000).toFixed(2),
|
||||
satisfaction: Math.round(Math.random() * 6),
|
||||
inStockDate: faker.date.past()
|
||||
});
|
||||
|
||||
export class AdvancedTableA extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
products: _.times(INITIAL_PRODUCTS_COUNT, generateRow),
|
||||
selected: []
|
||||
};
|
||||
|
||||
this.headerCheckboxRef = React.createRef();
|
||||
}
|
||||
|
||||
handleSelect(row, isSelected) {
|
||||
if (isSelected) {
|
||||
this.setState({ selected: [...this.state.selected, row.id] })
|
||||
} else {
|
||||
this.setState({
|
||||
selected: this.state.selected.filter(itemId => itemId !== row.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
handleSelectAll(isSelected, rows) {
|
||||
if (isSelected) {
|
||||
this.setState({ selected: _.map(rows, 'id') })
|
||||
} else {
|
||||
this.setState({ selected: [] });
|
||||
}
|
||||
}
|
||||
|
||||
handleAddRow() {
|
||||
const currentSize = this.state.products.length;
|
||||
|
||||
this.setState({
|
||||
products: [
|
||||
generateRow(currentSize + 1),
|
||||
...this.state.products,
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
handleDeleteRow() {
|
||||
this.setState({
|
||||
products: _.filter(this.state.products, product =>
|
||||
!_.includes(this.state.selected, product.id))
|
||||
})
|
||||
}
|
||||
|
||||
handleResetFilters() {
|
||||
this.nameFilter('');
|
||||
this.qualityFilter('');
|
||||
this.priceFilter('');
|
||||
this.satisfactionFilter('');
|
||||
}
|
||||
|
||||
createColumnDefinitions() {
|
||||
return [{
|
||||
dataField: 'id',
|
||||
text: 'Product ID',
|
||||
headerFormatter: column => (
|
||||
<React.Fragment>
|
||||
<span className="text-nowrap">{ column.text }</span>
|
||||
<a
|
||||
href="javascript:;"
|
||||
className="d-block small text-decoration-none text-nowrap"
|
||||
onClick={ this.handleResetFilters.bind(this) }
|
||||
>
|
||||
Reset Filters <i className="fa fa-times fa-fw text-danger"></i>
|
||||
</a>
|
||||
</React.Fragment>
|
||||
)
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name',
|
||||
sort: true,
|
||||
sortCaret,
|
||||
formatter: (cell) => (
|
||||
<span className="text-inverse">
|
||||
{ cell }
|
||||
</span>
|
||||
),
|
||||
...buildCustomTextFilter({
|
||||
placeholder: 'Enter product name...',
|
||||
getFilter: filter => { this.nameFilter = filter; }
|
||||
})
|
||||
}, {
|
||||
dataField: 'quality',
|
||||
text: 'Product Quality',
|
||||
formatter: (cell) => {
|
||||
let pqProps;
|
||||
switch (cell) {
|
||||
case ProductQuality.Good:
|
||||
pqProps = {
|
||||
color: 'success',
|
||||
text: 'Good'
|
||||
}
|
||||
break;
|
||||
case ProductQuality.Bad:
|
||||
pqProps = {
|
||||
color: 'danger',
|
||||
text: 'Bad'
|
||||
}
|
||||
break;
|
||||
case ProductQuality.Unknown:
|
||||
default:
|
||||
pqProps = {
|
||||
color: 'secondary',
|
||||
text: 'Unknown'
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Badge color={pqProps.color}>
|
||||
{ pqProps.text }
|
||||
</Badge>
|
||||
)
|
||||
},
|
||||
sort: true,
|
||||
sortCaret,
|
||||
...buildCustomSelectFilter({
|
||||
placeholder: 'Select Quality',
|
||||
options: [
|
||||
{ value: ProductQuality.Good, label: 'Good' },
|
||||
{ value: ProductQuality.Bad, label: 'Bad' },
|
||||
{ value: ProductQuality.Unknown, label: 'Unknown' }
|
||||
],
|
||||
getFilter: filter => { this.qualityFilter = filter; }
|
||||
})
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price',
|
||||
sort: true,
|
||||
sortCaret,
|
||||
...buildCustomNumberFilter({
|
||||
comparators: [Comparator.EQ, Comparator.GT, Comparator.LT],
|
||||
getFilter: filter => { this.priceFilter = filter; }
|
||||
})
|
||||
}, {
|
||||
dataField: 'satisfaction',
|
||||
text: 'Buyer Satisfaction',
|
||||
sort: true,
|
||||
sortCaret,
|
||||
formatter: (cell) =>
|
||||
<StarRating at={ cell } max={ 6 } />,
|
||||
...buildCustomSelectFilter({
|
||||
placeholder: 'Select Satisfaction',
|
||||
options: _.times(6, (i) => ({ value: i + 1, label: i + 1 })),
|
||||
getFilter: filter => { this.satisfactionFilter = filter; }
|
||||
})
|
||||
}, {
|
||||
dataField: 'inStockDate',
|
||||
text: 'In Stock From',
|
||||
formatter: (cell) =>
|
||||
moment(cell).format('DD/MM/YYYY'),
|
||||
filter: dateFilter({
|
||||
className: 'd-flex align-items-center',
|
||||
comparatorClassName: 'd-none',
|
||||
dateClassName: 'form-control form-control-sm',
|
||||
comparator: Comparator.GT,
|
||||
getFilter: filter => { this.stockDateFilter = filter; }
|
||||
}),
|
||||
sort: true,
|
||||
sortCaret
|
||||
}];
|
||||
}
|
||||
|
||||
render() {
|
||||
const columnDefs = this.createColumnDefinitions();
|
||||
const paginationDef = paginationFactory({
|
||||
paginationSize: 5,
|
||||
showTotal: true,
|
||||
pageListRenderer: (props) => (
|
||||
<CustomPaginationPanel { ...props } size="sm" className="ml-md-auto mt-2 mt-md-0" />
|
||||
),
|
||||
sizePerPageRenderer: (props) => (
|
||||
<CustomSizePerPageButton { ...props } />
|
||||
),
|
||||
paginationTotalRenderer: (from, to, size) => (
|
||||
<CustomPaginationTotal { ...{ from, to, size } } />
|
||||
)
|
||||
});
|
||||
const selectRowConfig = {
|
||||
mode: 'checkbox',
|
||||
selected: this.state.selected,
|
||||
onSelect: this.handleSelect.bind(this),
|
||||
onSelectAll: this.handleSelectAll.bind(this),
|
||||
selectionRenderer: ({ mode, checked, disabled }) => (
|
||||
<CustomInput type={ mode } checked={ checked } disabled={ disabled } />
|
||||
),
|
||||
selectionHeaderRenderer: ({ mode, checked, indeterminate }) => (
|
||||
<CustomInput type={ mode } checked={ checked } innerRef={el => el && (el.indeterminate = indeterminate)} />
|
||||
)
|
||||
};
|
||||
|
||||
return (
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
data={ this.state.products }
|
||||
columns={ columnDefs }
|
||||
search
|
||||
exportCSV
|
||||
>
|
||||
{
|
||||
props => (
|
||||
<React.Fragment>
|
||||
<div className="d-flex justify-content-end align-items-center mb-2">
|
||||
<h6 className="my-0">
|
||||
AdvancedTable A
|
||||
</h6>
|
||||
<div className="d-flex ml-auto">
|
||||
<CustomSearch
|
||||
className="mr-2"
|
||||
{ ...props.searchProps }
|
||||
/>
|
||||
<ButtonGroup>
|
||||
<CustomExportCSV
|
||||
{ ...props.csvProps }
|
||||
>
|
||||
Export
|
||||
</CustomExportCSV>
|
||||
<Button
|
||||
size="sm"
|
||||
outline
|
||||
onClick={ this.handleDeleteRow.bind(this) }
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
outline
|
||||
onClick={ this.handleAddRow.bind(this) }
|
||||
>
|
||||
<i className="fa fa-fw fa-plus"></i>
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
<BootstrapTable
|
||||
classes="table-responsive"
|
||||
pagination={ paginationDef }
|
||||
filter={ filterFactory() }
|
||||
selectRow={ selectRowConfig }
|
||||
bordered={ false }
|
||||
responsive
|
||||
{ ...props.baseProps }
|
||||
/>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
</ToolkitProvider>
|
||||
);
|
||||
}
|
||||
}
|
234
app/routes/Tables/ExtendedTable/components/AdvancedTableB.js
Executable file
234
app/routes/Tables/ExtendedTable/components/AdvancedTableB.js
Executable file
@@ -0,0 +1,234 @@
|
||||
import React from 'react';
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import ToolkitProvider from 'react-bootstrap-table2-toolkit';
|
||||
import moment from 'moment';
|
||||
import _ from 'lodash';
|
||||
import faker from 'faker/locale/en_US';
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Row,
|
||||
Col
|
||||
} from './../../../../components';
|
||||
import { CustomExportCSV } from './CustomExportButton';
|
||||
import { CustomSearch } from './CustomSearch';
|
||||
import { randomArray, randomAvatar } from './../../../../utilities';
|
||||
|
||||
const generateRow = (id) => ({
|
||||
id,
|
||||
photo: randomAvatar(),
|
||||
firstName: faker.name.firstName(),
|
||||
lastName: faker.name.lastName(),
|
||||
role: faker.name.jobType(),
|
||||
status: randomArray([
|
||||
'Active',
|
||||
'Suspended',
|
||||
'Waiting',
|
||||
'Unknown'
|
||||
]),
|
||||
region: randomArray(['North', 'South', 'East', 'West']),
|
||||
earnings: 500 + Math.random() * 1000,
|
||||
earningsCurrencyIcon: randomArray([
|
||||
<i className="fa fa-fw fa-euro text-muted" key="cur_eur"></i>,
|
||||
<i className="fa fa-fw fa-dollar text-muted" key="cur_usd"></i>
|
||||
]),
|
||||
lastLoginDate: faker.date.recent(),
|
||||
ipAddress: faker.internet.ip(),
|
||||
browser: 'Safari 9.1.1(11601.6.17)',
|
||||
os: 'OS X El Capitan',
|
||||
planSelected: randomArray(['Basic', 'Premium', 'Enterprise']),
|
||||
planEnd: faker.date.future()
|
||||
});
|
||||
|
||||
const sortCaret = (order) => {
|
||||
if (!order)
|
||||
return <i className="fa fa-fw fa-sort text-muted"></i>;
|
||||
if (order)
|
||||
return <i className={`fa fa-fw text-muted fa-sort-${order}`}></i>
|
||||
};
|
||||
|
||||
export class AdvancedTableB extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
users: _.times(10, generateRow)
|
||||
}
|
||||
}
|
||||
|
||||
handleAddRow() {
|
||||
const usersLength = this.state.users.length;
|
||||
|
||||
this.setState({
|
||||
users: [
|
||||
generateRow(usersLength + 1),
|
||||
...this.state.users
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
createColumnDefinitions() {
|
||||
return [
|
||||
{
|
||||
dataField: 'photo',
|
||||
text: 'Photo',
|
||||
formatter: (cell) => (
|
||||
<Avatar.Image src={ cell } />
|
||||
)
|
||||
}, {
|
||||
dataField: 'firstName',
|
||||
text: 'First Name',
|
||||
sort: true,
|
||||
sortCaret
|
||||
}, {
|
||||
dataField: 'lastName',
|
||||
text: 'Last Name',
|
||||
sort: true,
|
||||
sortCaret
|
||||
}, {
|
||||
dataField: 'role',
|
||||
text: 'Role',
|
||||
sort: true,
|
||||
sortCaret
|
||||
}, {
|
||||
dataField: 'status',
|
||||
text: 'Status',
|
||||
sort: true,
|
||||
sortCaret,
|
||||
formatter: (cell) => {
|
||||
const color = (status) => {
|
||||
const map = {
|
||||
'Active': 'success',
|
||||
'Suspended': 'danger',
|
||||
'Waiting': 'info',
|
||||
'Unknown': 'secondary'
|
||||
};
|
||||
return map[status];
|
||||
}
|
||||
|
||||
return (
|
||||
<Badge color={ color(cell) }>
|
||||
{ cell }
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
}, {
|
||||
dataField: 'region',
|
||||
text: 'Region',
|
||||
sort: true,
|
||||
sortCaret
|
||||
}, {
|
||||
dataField: 'earnings',
|
||||
text: 'Earnings',
|
||||
sort: true,
|
||||
sortCaret,
|
||||
formatter: (cell, row) => (
|
||||
<span>
|
||||
{ row.earningsCurrencyIcon }
|
||||
{ _.isNumber(cell) && cell.toFixed(2) }
|
||||
</span>
|
||||
)
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
render() {
|
||||
const columnDefs = this.createColumnDefinitions();
|
||||
|
||||
const expandRow = {
|
||||
renderer: row => (
|
||||
<Row>
|
||||
<Col md={ 6 }>
|
||||
<dl className="row">
|
||||
<dt className="col-sm-6 text-right">Last Login</dt>
|
||||
<dd className="col-sm-6">{ moment(row.lastLoginDate).format('DD-MMM-YYYY') }</dd>
|
||||
|
||||
<dt className="col-sm-6 text-right">IP Address</dt>
|
||||
<dd className="col-sm-6">{ row.ipAddress }</dd>
|
||||
|
||||
<dt className="col-sm-6 text-right">Browser</dt>
|
||||
<dd className="col-sm-6">{ row.browser }</dd>
|
||||
</dl>
|
||||
</Col>
|
||||
<Col md={ 6 }>
|
||||
<dl className="row">
|
||||
<dt className="col-sm-6 text-right">Operating System</dt>
|
||||
<dd className="col-sm-6">{ row.os }</dd>
|
||||
|
||||
<dt className="col-sm-6 text-right">Selected Plan</dt>
|
||||
<dd className="col-sm-6">{ row.planSelected }</dd>
|
||||
|
||||
<dt className="col-sm-6 text-right">Plan Expiriation</dt>
|
||||
<dd className="col-sm-6">{ moment(row.planEnd).format('DD-MMM-YYYY') }</dd>
|
||||
</dl>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
showExpandColumn: true,
|
||||
expandHeaderColumnRenderer: ({ isAnyExpands }) => isAnyExpands ? (
|
||||
<i className="fa fa-angle-down fa-fw fa-lg text-muted"></i>
|
||||
) : (
|
||||
<i className="fa fa-angle-right fa-fw fa-lg text-muted"></i>
|
||||
),
|
||||
expandColumnRenderer: ({ expanded }) =>
|
||||
expanded ? (
|
||||
<i className="fa fa-angle-down fa-fw fa-lg text-muted"></i>
|
||||
) : (
|
||||
<i className="fa fa-angle-right fa-fw fa-lg text-muted"></i>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
data={ this.state.users }
|
||||
columns={ columnDefs }
|
||||
search
|
||||
exportCSV
|
||||
>
|
||||
{
|
||||
props => (
|
||||
<React.Fragment>
|
||||
<div className="d-flex justify-content-end align-items-center mb-2">
|
||||
<h6 className="my-0">
|
||||
AdvancedTable B
|
||||
</h6>
|
||||
<div className="d-flex ml-auto">
|
||||
<CustomSearch
|
||||
className="mr-2"
|
||||
{ ...props.searchProps }
|
||||
/>
|
||||
<ButtonGroup>
|
||||
<CustomExportCSV
|
||||
{ ...props.csvProps }
|
||||
>
|
||||
Export
|
||||
</CustomExportCSV>
|
||||
<Button
|
||||
size="sm"
|
||||
outline
|
||||
onClick={ this.handleAddRow.bind(this) }
|
||||
>
|
||||
Add <i className="fa fa-fw fa-plus"></i>
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
<BootstrapTable
|
||||
classes="table-responsive-lg"
|
||||
bordered={ false }
|
||||
expandRow={ expandRow }
|
||||
responsive
|
||||
hover
|
||||
{ ...props.baseProps }
|
||||
/>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
</ToolkitProvider>
|
||||
);
|
||||
}
|
||||
}
|
38
app/routes/Tables/ExtendedTable/components/BasicTable.js
Executable file
38
app/routes/Tables/ExtendedTable/components/BasicTable.js
Executable file
@@ -0,0 +1,38 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import faker from 'faker/locale/en_US';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}
|
||||
];
|
||||
|
||||
const data = _.times(5, (index) => ({
|
||||
id: index,
|
||||
name: faker.commerce.productName(),
|
||||
price: Math.round(2000 + Math.random() * 500)
|
||||
}));
|
||||
|
||||
export const BasicTable = () => (
|
||||
<React.Fragment>
|
||||
<h6 className="mt-0">
|
||||
Basic Table
|
||||
</h6>
|
||||
<BootstrapTable
|
||||
classes="table-responsive-sm"
|
||||
keyField='id'
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
bordered={ false }
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
38
app/routes/Tables/ExtendedTable/components/BorderedTable.js
Executable file
38
app/routes/Tables/ExtendedTable/components/BorderedTable.js
Executable file
@@ -0,0 +1,38 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import faker from 'faker/locale/en_US';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}
|
||||
];
|
||||
|
||||
const data = _.times(5, (index) => ({
|
||||
id: index,
|
||||
name: faker.commerce.productName(),
|
||||
price: Math.round(2000 + Math.random() * 500)
|
||||
}));
|
||||
|
||||
export const BorderedTable = () => (
|
||||
<React.Fragment>
|
||||
<h6 className="mt-0">
|
||||
Bordered Table
|
||||
</h6>
|
||||
<BootstrapTable
|
||||
classes='table-responsive-sm'
|
||||
keyField='id'
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
bordered
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
89
app/routes/Tables/ExtendedTable/components/CellEdit.js
Executable file
89
app/routes/Tables/ExtendedTable/components/CellEdit.js
Executable file
@@ -0,0 +1,89 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import cellEditFactory, { Type } from 'react-bootstrap-table2-editor';
|
||||
import faker from 'faker/locale/en_US';
|
||||
|
||||
import { randomArray } from './../../../../utilities';
|
||||
|
||||
const regions = [
|
||||
{ value: 'Europe', label: 'Europe' },
|
||||
{ value: 'North America', label: 'North America' },
|
||||
{ value: 'Asia', label: 'Asia' },
|
||||
{ value: 'Australia', label: 'Australia' },
|
||||
];
|
||||
|
||||
const columns = [
|
||||
{
|
||||
dataField: 'id',
|
||||
text: 'Product ID',
|
||||
headerClasses: 'text-nowrap'
|
||||
}, {
|
||||
dataField: 'available',
|
||||
text: 'Available',
|
||||
editor: {
|
||||
type: Type.CHECKBOX,
|
||||
value: 'Y:N'
|
||||
},
|
||||
formatter: function AvailableFormatter(cell) {
|
||||
return cell === 'Y' ?
|
||||
<i className="fa fa-fw fa-check"></i> :
|
||||
<i className="fa fa-fw fa-times"></i>;
|
||||
},
|
||||
headerClasses: 'text-nowrap'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name',
|
||||
editor: {
|
||||
type: Type.TEXT
|
||||
},
|
||||
headerClasses: 'text-nowrap'
|
||||
}, {
|
||||
dataField: 'description',
|
||||
text: 'Product Description',
|
||||
editor: {
|
||||
type: Type.TEXTAREA
|
||||
},
|
||||
style: {
|
||||
width: '40%'
|
||||
},
|
||||
headerClasses: 'text-nowrap'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price',
|
||||
headerClasses: 'text-nowrap'
|
||||
}, {
|
||||
dataField: 'region',
|
||||
text: 'Region',
|
||||
headerClasses: 'text-nowrap',
|
||||
editor: {
|
||||
type: Type.SELECT,
|
||||
options: regions
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const data = _.times(5, (index) => ({
|
||||
id: index,
|
||||
available: !Math.round(Math.random()) ? 'Y' : 'N',
|
||||
name: faker.commerce.productName(),
|
||||
description: faker.lorem.paragraph(),
|
||||
price: Math.round(2000 + Math.random() * 500),
|
||||
region: randomArray(_.map(regions, 'value'))
|
||||
}))
|
||||
|
||||
export const CellEdit = () => (
|
||||
<React.Fragment>
|
||||
<h6 className="mt-0">
|
||||
Cell Edit
|
||||
</h6>
|
||||
<BootstrapTable
|
||||
classes="table-responsive"
|
||||
keyField='id'
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
bordered={ false }
|
||||
cellEdit={ cellEditFactory({ mode: 'click', blurToSave: true }) }
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
59
app/routes/Tables/ExtendedTable/components/ClearSearch.js
Executable file
59
app/routes/Tables/ExtendedTable/components/ClearSearch.js
Executable file
@@ -0,0 +1,59 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import ToolkitProvider from 'react-bootstrap-table2-toolkit';
|
||||
import faker from 'faker/locale/en_US';
|
||||
|
||||
import { CustomSearch } from './CustomSearch';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}
|
||||
];
|
||||
|
||||
const data = _.times(5, (index) => ({
|
||||
id: index,
|
||||
name: faker.commerce.productName(),
|
||||
price: Math.round(2000 + Math.random() * 500)
|
||||
}));
|
||||
|
||||
export const ClearSearch = () => (
|
||||
<ToolkitProvider
|
||||
keyField="id"
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
search
|
||||
>
|
||||
{
|
||||
props => (
|
||||
<React.Fragment>
|
||||
<div className="d-flex align-items-center justify-content-between">
|
||||
<h6 className="mt-0">
|
||||
Table Search with Clear
|
||||
</h6>
|
||||
|
||||
<div>
|
||||
<CustomSearch
|
||||
className="mb-2"
|
||||
{ ...props.searchProps }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<BootstrapTable
|
||||
classes="table-responsive-sm"
|
||||
bordered={ false }
|
||||
{ ...props.baseProps }
|
||||
/>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
</ToolkitProvider>
|
||||
);
|
28
app/routes/Tables/ExtendedTable/components/CustomExportButton.js
Executable file
28
app/routes/Tables/ExtendedTable/components/CustomExportButton.js
Executable file
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Button
|
||||
} from './../../../../components';
|
||||
|
||||
export const CustomExportCSV = ({children, onExport, ...props}) => {
|
||||
return (
|
||||
<Button
|
||||
{ ...props }
|
||||
onClick={() => { onExport() }}
|
||||
>
|
||||
{ children }
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
CustomExportCSV.propTypes = {
|
||||
size: PropTypes.string,
|
||||
outline: PropTypes.bool,
|
||||
onExport: PropTypes.func,
|
||||
children: PropTypes.node
|
||||
}
|
||||
|
||||
CustomExportCSV.defaultProps = {
|
||||
size: 'sm',
|
||||
outline: true
|
||||
}
|
31
app/routes/Tables/ExtendedTable/components/CustomPaginationPanel.js
Executable file
31
app/routes/Tables/ExtendedTable/components/CustomPaginationPanel.js
Executable file
@@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { map, isInteger } from 'lodash';
|
||||
import { Pagination, PaginationItem, PaginationLink, Col } from './../../../../components';
|
||||
|
||||
const mapToFa = {
|
||||
'<': <i className="fa fa-angle-left" />,
|
||||
'<<': <i className="fa fa-angle-double-left" />,
|
||||
'>': <i className="fa fa-angle-right" />,
|
||||
'>>': <i className="fa fa-angle-double-right" />
|
||||
}
|
||||
|
||||
export const CustomPaginationPanel = ({ onPageChange, pages, ...otherProps }) => (
|
||||
<Col md={ 6 } className="d-flex">
|
||||
<Pagination aria-label="Page navigation example" { ...otherProps } listClassName="my-0">
|
||||
{
|
||||
map(pages, page => (
|
||||
<PaginationItem active={ page.active } disabled={ page.disabled }>
|
||||
<PaginationLink onClick={() => onPageChange(page.page)}>
|
||||
{ isInteger(page.page) ? page.page : mapToFa[page.page] }
|
||||
</PaginationLink>
|
||||
</PaginationItem>
|
||||
))
|
||||
}
|
||||
</Pagination>
|
||||
</Col>
|
||||
);
|
||||
CustomPaginationPanel.propTypes = {
|
||||
pages: PropTypes.array,
|
||||
onPageChange: PropTypes.func
|
||||
};
|
13
app/routes/Tables/ExtendedTable/components/CustomPaginationTotal.js
Executable file
13
app/routes/Tables/ExtendedTable/components/CustomPaginationTotal.js
Executable file
@@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export const CustomPaginationTotal = ({ from, to, size }) => (
|
||||
<span className="small ml-2">
|
||||
Showing { from } to { to } of { size } Results
|
||||
</span>
|
||||
);
|
||||
CustomPaginationTotal.propTypes = {
|
||||
from: PropTypes.number,
|
||||
to: PropTypes.number,
|
||||
size: PropTypes.number,
|
||||
};
|
57
app/routes/Tables/ExtendedTable/components/CustomSearch.js
Executable file
57
app/routes/Tables/ExtendedTable/components/CustomSearch.js
Executable file
@@ -0,0 +1,57 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Input,
|
||||
InputGroup,
|
||||
Button,
|
||||
InputGroupAddon
|
||||
} from './../../../../components';
|
||||
|
||||
export class CustomSearch extends React.Component {
|
||||
static propTypes = {
|
||||
className: PropTypes.string,
|
||||
onSearch: PropTypes.func
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevState.value !== this.state.value) {
|
||||
this.props.onSearch(this.state.value);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<InputGroup className={ this.props.className } size="sm">
|
||||
<InputGroupAddon addonType="prepend">
|
||||
<i className="fa fa-search fa-fw"></i>
|
||||
</InputGroupAddon>
|
||||
<Input
|
||||
onChange={(e) => { this.setState({ value: e.target.value }) }}
|
||||
value={ this.state.value }
|
||||
className="bg-white"
|
||||
placeholder="Type to search..."
|
||||
/>
|
||||
{
|
||||
this.state.value && (
|
||||
<InputGroupAddon addonType="append">
|
||||
<Button
|
||||
outline
|
||||
onClick={() => { this.setState({value: ''}) }}
|
||||
>
|
||||
<i className="fa fa-fw fa-times"></i>
|
||||
</Button>
|
||||
</InputGroupAddon>
|
||||
)
|
||||
}
|
||||
</InputGroup>
|
||||
)
|
||||
}
|
||||
}
|
40
app/routes/Tables/ExtendedTable/components/CustomSizePerPageButton.js
Executable file
40
app/routes/Tables/ExtendedTable/components/CustomSizePerPageButton.js
Executable file
@@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { map } from 'lodash';
|
||||
import {
|
||||
UncontrolledButtonDropdown,
|
||||
DropdownToggle,
|
||||
DropdownMenu,
|
||||
DropdownItem
|
||||
} from './../../../../components';
|
||||
|
||||
export const CustomSizePerPageButton = ({
|
||||
options,
|
||||
currSizePerPage,
|
||||
onSizePerPageChange,
|
||||
...ddProps,
|
||||
}) => (
|
||||
<UncontrolledButtonDropdown { ...ddProps }>
|
||||
<DropdownToggle size="sm" color="link" className="text-decoration-none">
|
||||
{ currSizePerPage }<i className="fa fa-angle-down ml-2" />
|
||||
</DropdownToggle>
|
||||
<DropdownMenu>
|
||||
<DropdownItem header>Page Size</DropdownItem>
|
||||
{
|
||||
map(options, option => (
|
||||
<DropdownItem
|
||||
onClick={() => onSizePerPageChange(option.page)}
|
||||
active={option.page === currSizePerPage}
|
||||
>
|
||||
{ option.text }
|
||||
</DropdownItem>
|
||||
))
|
||||
}
|
||||
</DropdownMenu>
|
||||
</UncontrolledButtonDropdown>
|
||||
);
|
||||
CustomSizePerPageButton.propTypes = {
|
||||
options: PropTypes.object,
|
||||
currSizePerPage: PropTypes.number,
|
||||
onSizePerPageChange: PropTypes.func
|
||||
}
|
71
app/routes/Tables/ExtendedTable/components/LargeTable.js
Executable file
71
app/routes/Tables/ExtendedTable/components/LargeTable.js
Executable file
@@ -0,0 +1,71 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import faker from 'faker/locale/en_US';
|
||||
|
||||
import classes from './LargeTable.scss';
|
||||
import { Card, CardHeader } from './../../../../components';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name'
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price'
|
||||
}
|
||||
];
|
||||
|
||||
const data = _.times(500, (index) => ({
|
||||
id: index,
|
||||
name: faker.commerce.productName(),
|
||||
price: Math.round(2000 + Math.random() * 500)
|
||||
}));
|
||||
|
||||
const expandRow = {
|
||||
showExpandColumn: true,
|
||||
renderer: function ExtendedRowRender(row) {
|
||||
return (
|
||||
<div>
|
||||
<p>{ `This Expand row is belong to rowKey ${row.id}` }</p>
|
||||
<p>You can render anything here, also you can add additional data on every row object</p>
|
||||
<p>expandRow.renderer callback will pass the origin row object to you</p>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
expandHeaderColumnRenderer: ({ isAnyExpands }) => isAnyExpands ? (
|
||||
<i className="fa fa-angle-down fa-fw fa-lg text-muted"></i>
|
||||
) : (
|
||||
<i className="fa fa-angle-right fa-fw fa-lg text-muted"></i>
|
||||
),
|
||||
expandColumnRenderer: ({ expanded }) =>
|
||||
expanded ? (
|
||||
<i className="fa fa-angle-down fa-fw fa-lg text-muted"></i>
|
||||
) : (
|
||||
<i className="fa fa-angle-right fa-fw fa-lg text-muted"></i>
|
||||
)
|
||||
};
|
||||
|
||||
export const LargeTable = () => (
|
||||
<React.Fragment>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
Large Table
|
||||
</CardHeader>
|
||||
<div className={ classes['table-scroll-wrap'] }>
|
||||
<BootstrapTable
|
||||
classes="table-responsive-sm"
|
||||
keyField='id'
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
bordered={ false }
|
||||
selectRow={ { mode: 'checkbox', clickToSelect: true } }
|
||||
expandRow={ expandRow }
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
</React.Fragment>
|
||||
);
|
4
app/routes/Tables/ExtendedTable/components/LargeTable.scss
Executable file
4
app/routes/Tables/ExtendedTable/components/LargeTable.scss
Executable file
@@ -0,0 +1,4 @@
|
||||
.table-scroll-wrap {
|
||||
max-height: 380px;
|
||||
overflow-y: auto;
|
||||
}
|
44
app/routes/Tables/ExtendedTable/components/SelectAll.js
Executable file
44
app/routes/Tables/ExtendedTable/components/SelectAll.js
Executable file
@@ -0,0 +1,44 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import faker from 'faker/locale/en_US';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name',
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price',
|
||||
}
|
||||
];
|
||||
|
||||
const data = _.times(5, (index) => ({
|
||||
id: index,
|
||||
name: faker.commerce.productName(),
|
||||
price: Math.round(2000 + Math.random() * 500)
|
||||
}));
|
||||
|
||||
const selectRow = {
|
||||
mode: 'checkbox',
|
||||
clickToSelect: true
|
||||
};
|
||||
|
||||
export const SelectAll = () => (
|
||||
<React.Fragment>
|
||||
<h6 className="mt-0">
|
||||
Select All
|
||||
</h6>
|
||||
<BootstrapTable
|
||||
classes="table-responsive"
|
||||
keyField='id'
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
bordered={ false }
|
||||
selectRow={ selectRow }
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
49
app/routes/Tables/ExtendedTable/components/SortTable.js
Executable file
49
app/routes/Tables/ExtendedTable/components/SortTable.js
Executable file
@@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import BootstrapTable from 'react-bootstrap-table-next';
|
||||
import faker from 'faker/locale/en_US';
|
||||
|
||||
const sortCaret = (order) => {
|
||||
if (!order)
|
||||
return <i className="fa fa-fw fa-sort text-muted"></i>;
|
||||
if (order)
|
||||
return <i className={`fa fa-fw text-muted fa-sort-${order}`}></i>
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{
|
||||
dataField: 'id',
|
||||
text: 'Product ID'
|
||||
}, {
|
||||
dataField: 'name',
|
||||
text: 'Product Name',
|
||||
sort: true,
|
||||
sortCaret
|
||||
}, {
|
||||
dataField: 'price',
|
||||
text: 'Product Price',
|
||||
sort: true,
|
||||
sortCaret
|
||||
}
|
||||
];
|
||||
|
||||
const data = _.times(10, (index) => ({
|
||||
id: index,
|
||||
name: faker.commerce.productName(),
|
||||
price: Math.round(2000 + Math.random() * 500)
|
||||
}));
|
||||
|
||||
export const SortTable = () => (
|
||||
<React.Fragment>
|
||||
<h6 className="mt-0">
|
||||
Sort Table
|
||||
</h6>
|
||||
<BootstrapTable
|
||||
classes="table-responsive-sm"
|
||||
keyField='id'
|
||||
data={ data }
|
||||
columns={ columns }
|
||||
bordered={ false }
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
11
app/routes/Tables/ExtendedTable/components/index.js
Executable file
11
app/routes/Tables/ExtendedTable/components/index.js
Executable file
@@ -0,0 +1,11 @@
|
||||
export * from './AdvancedTableA';
|
||||
export * from './AdvancedTableB';
|
||||
export * from './BasicTable';
|
||||
export * from './BorderedTable';
|
||||
export * from './CellEdit';
|
||||
export * from './ClearSearch';
|
||||
export * from './CustomExportButton';
|
||||
export * from './CustomSearch';
|
||||
export * from './LargeTable';
|
||||
export * from './SelectAll';
|
||||
export * from './SortTable';
|
3
app/routes/Tables/ExtendedTable/filters/index.js
Executable file
3
app/routes/Tables/ExtendedTable/filters/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
export * from './textFilter';
|
||||
export * from './selectFilter';
|
||||
export * from './numberFilter';
|
143
app/routes/Tables/ExtendedTable/filters/numberFilter.js
Executable file
143
app/routes/Tables/ExtendedTable/filters/numberFilter.js
Executable file
@@ -0,0 +1,143 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import _ from 'lodash';
|
||||
import uid from 'uuid/v4';
|
||||
import { customFilter, Comparator, FILTER_TYPES } from 'react-bootstrap-table2-filter';
|
||||
|
||||
import { CustomInput, Input } from './../../../../components';
|
||||
|
||||
const comparatorSign = (comp) => {
|
||||
switch (comp) {
|
||||
case Comparator.EQ:
|
||||
return '=';
|
||||
case Comparator.GT:
|
||||
return '>';
|
||||
case Comparator.LT:
|
||||
return '<';
|
||||
}
|
||||
}
|
||||
|
||||
class NumberFilter extends React.Component {
|
||||
static propTypes = {
|
||||
column: PropTypes.object.isRequired,
|
||||
onFilter: PropTypes.func.isRequired,
|
||||
placeholder: PropTypes.string,
|
||||
getFilter: PropTypes.func,
|
||||
comparators: PropTypes.array,
|
||||
comparator: PropTypes.string,
|
||||
onClick: PropTypes.func
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
comparators: [Comparator.EQ],
|
||||
comparator: Comparator.EQ
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
value: '',
|
||||
comparator: props.comparator
|
||||
}
|
||||
|
||||
this.comparatorInputId = uid();
|
||||
this.valueInputId = uid();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (_.isFunction(this.props.getFilter)) {
|
||||
this.props.getFilter((value) => {
|
||||
this.setState({ value });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (
|
||||
prevState.value !== this.state.value ||
|
||||
prevState.comparator !== this.state.comparator
|
||||
) {
|
||||
this.props.onFilter({
|
||||
number: this.state.value,
|
||||
comparator: this.state.comparator
|
||||
});
|
||||
}
|
||||
if (prevProps.comparator !== this.props.comparator) {
|
||||
this.setState({ comparator: this.props.comparator });
|
||||
}
|
||||
}
|
||||
|
||||
handleClick(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
if (this.props.onClick) {
|
||||
this.props.onClick(e);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { placeholder, comparators } = this.props;
|
||||
const { comparator } = this.state;
|
||||
return (
|
||||
<div className='d-flex'>
|
||||
{
|
||||
(!_.isEmpty(comparators) && comparators.length > 0) && (
|
||||
<CustomInput
|
||||
type="select"
|
||||
bsSize="sm"
|
||||
onChange={(e) => { this.setState({ comparator: e.target.value }) }}
|
||||
onClick={this.handleClick}
|
||||
value={ comparator }
|
||||
className="d-block bg-white mr-1"
|
||||
id={this.comparatorInputId}
|
||||
>
|
||||
<option value=""></option>
|
||||
|
||||
{
|
||||
_.map(comparators, (comparator, index) => (
|
||||
<option
|
||||
value={ comparator }
|
||||
key={ index }
|
||||
>
|
||||
{ comparatorSign(comparator) }
|
||||
</option>
|
||||
))
|
||||
}
|
||||
</CustomInput>
|
||||
)
|
||||
}
|
||||
<Input
|
||||
type="number"
|
||||
className="bg-white"
|
||||
bsSize="sm"
|
||||
onChange={(e) => { this.setState({ value: e.target.value }) }}
|
||||
onClick={this.handleClick}
|
||||
value={ this.state.value }
|
||||
placeholder={ placeholder }
|
||||
id={this.valueInputId}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export const buildCustomNumberFilter = ({ placeholder, getFilter, comparators, ...other } = {}) => ({
|
||||
filter: customFilter({
|
||||
type: FILTER_TYPES.NUMBER,
|
||||
...other
|
||||
}),
|
||||
filterRenderer: function NumberFilterWrap(onFilter, column) {
|
||||
return (
|
||||
<NumberFilter
|
||||
{...{
|
||||
onFilter,
|
||||
column,
|
||||
placeholder,
|
||||
getFilter,
|
||||
comparators
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
});
|
90
app/routes/Tables/ExtendedTable/filters/selectFilter.js
Executable file
90
app/routes/Tables/ExtendedTable/filters/selectFilter.js
Executable file
@@ -0,0 +1,90 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import _ from 'lodash';
|
||||
import { customFilter } from 'react-bootstrap-table2-filter';
|
||||
import uid from 'uuid/v4';
|
||||
|
||||
import { CustomInput } from './../../../../components';
|
||||
|
||||
class SelectFilter extends React.Component {
|
||||
static propTypes = {
|
||||
column: PropTypes.object.isRequired,
|
||||
onFilter: PropTypes.func.isRequired,
|
||||
options: PropTypes.array.isRequired,
|
||||
placeholder: PropTypes.string,
|
||||
getFilter: PropTypes.func,
|
||||
onClick: PropTypes.func
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
value: ''
|
||||
}
|
||||
this.inputId = uid();
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (_.isFunction(this.props.getFilter)) {
|
||||
this.props.getFilter((value) => {
|
||||
this.setState({ value });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevState.value !== this.state.value) {
|
||||
this.props.onFilter(this.state.value);
|
||||
}
|
||||
}
|
||||
|
||||
handleClick(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
if (this.props.onClick) {
|
||||
this.props.onClick(e);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { placeholder, options } = this.props;
|
||||
return (
|
||||
<CustomInput
|
||||
type="select"
|
||||
bsSize="sm"
|
||||
onChange={(e) => { this.setState({ value: e.target.value }) }}
|
||||
onClick={ this.handleClick }
|
||||
value={ this.state.value }
|
||||
className="d-block bg-white"
|
||||
id={this.inputId}
|
||||
>
|
||||
<option value="">{ placeholder }</option>
|
||||
|
||||
{
|
||||
_.map(options, ({ value, label }, index) => (
|
||||
<option value={value} key={ index }>{ label }</option>
|
||||
))
|
||||
}
|
||||
</CustomInput>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export const buildCustomSelectFilter = ({ placeholder, options, getFilter, ...other } = {}) => ({
|
||||
filter: customFilter(other),
|
||||
filterRenderer: function TextFilterWrap(onFilter, column) {
|
||||
return (
|
||||
<SelectFilter
|
||||
{...{
|
||||
onFilter,
|
||||
column,
|
||||
placeholder,
|
||||
options,
|
||||
getFilter
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
});
|
89
app/routes/Tables/ExtendedTable/filters/textFilter.js
Executable file
89
app/routes/Tables/ExtendedTable/filters/textFilter.js
Executable file
@@ -0,0 +1,89 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import _ from 'lodash';
|
||||
import { customFilter } from 'react-bootstrap-table2-filter';
|
||||
|
||||
import {
|
||||
Form,
|
||||
Input
|
||||
} from './../../../../components';
|
||||
|
||||
class TextFilter extends React.Component {
|
||||
static propTypes = {
|
||||
column: PropTypes.object.isRequired,
|
||||
onFilter: PropTypes.func.isRequired,
|
||||
placeholder: PropTypes.string,
|
||||
getFilter: PropTypes.func,
|
||||
onClick: PropTypes.func
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
value: ''
|
||||
}
|
||||
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (_.isFunction(this.props.getFilter)) {
|
||||
this.props.getFilter((value) => {
|
||||
this.setState({ value });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevState.value !== this.state.value) {
|
||||
this.props.onFilter(this.state.value);
|
||||
}
|
||||
}
|
||||
|
||||
handleClick(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
if (this.props.onClick) {
|
||||
this.props.onClick(e);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { onFilter, placeholder } = this.props;
|
||||
return (
|
||||
<Form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
onFilter(this.state.value)
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
type="text"
|
||||
bsSize="sm"
|
||||
className="bg-white"
|
||||
onChange={(e) => this.setState({value: e.target.value})}
|
||||
onClick={ this.handleClick }
|
||||
value={ this.state.value }
|
||||
placeholder={ placeholder }
|
||||
/>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export const buildCustomTextFilter = ({ placeholder, getFilter, ...other } = {}) => ({
|
||||
filter: customFilter(other),
|
||||
filterRenderer: function TextFilterWrap(onFilter, column) {
|
||||
return (
|
||||
<TextFilter
|
||||
{...{
|
||||
onFilter,
|
||||
column,
|
||||
placeholder,
|
||||
getFilter
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
});
|
3
app/routes/Tables/ExtendedTable/index.js
Executable file
3
app/routes/Tables/ExtendedTable/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import { ExtendedTable } from './ExtendedTable';
|
||||
|
||||
export default ExtendedTable;
|
483
app/routes/Tables/Tables/Tables.js
Executable file
483
app/routes/Tables/Tables/Tables.js
Executable file
@@ -0,0 +1,483 @@
|
||||
import React from 'react';
|
||||
|
||||
import {
|
||||
Container,
|
||||
Row,
|
||||
Col,
|
||||
Card,
|
||||
CardTitle,
|
||||
CardBody,
|
||||
Table,
|
||||
} from './../../../components';
|
||||
|
||||
import { HeaderMain } from "../../components/HeaderMain";
|
||||
|
||||
import {
|
||||
HeaderDemo
|
||||
} from "../../components/HeaderDemo";
|
||||
|
||||
import {
|
||||
TrTableDefault
|
||||
} from "./components/TrTableDefault";
|
||||
import {
|
||||
TrTableResponsive
|
||||
} from "./components/TrTableResponsive";
|
||||
import {
|
||||
TrTableStriped
|
||||
} from "./components/TrTableStriped";
|
||||
import {
|
||||
TrTableHoverable
|
||||
} from "./components/TrTableHoverable";
|
||||
import {
|
||||
TrTableSmall
|
||||
} from "./components/TrTableSmall";
|
||||
import {
|
||||
TrTableBorderless
|
||||
} from "./components/TrTableBorderless";
|
||||
import {
|
||||
TrTableBordered
|
||||
} from "./components/TrTableBordered";
|
||||
import {
|
||||
TrTableHeads
|
||||
} from "./components/TrTableHeads";
|
||||
import {
|
||||
TrTableContextual
|
||||
} from "./components/TrTableContextual";
|
||||
|
||||
const Tables = () => (
|
||||
<React.Fragment>
|
||||
<Container>
|
||||
<HeaderMain
|
||||
title="Tables"
|
||||
className="mb-5 mt-4"
|
||||
/>
|
||||
{ /* START Header 1 */}
|
||||
<Row>
|
||||
<Col lg={ 12 }>
|
||||
<HeaderDemo
|
||||
no={1}
|
||||
title="Basic Tables"
|
||||
subTitle={(
|
||||
<React.Fragment>
|
||||
All table styles are inherited in Bootstrap 4, meaning any nested tables will be styled in the same manner as the parent.
|
||||
</React.Fragment>
|
||||
)}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
{ /* END Header 1 */}
|
||||
{ /* START Section 1 */}
|
||||
<Row>
|
||||
<Col lg={ 12 }>
|
||||
<Card className="mb-3">
|
||||
<CardBody>
|
||||
<CardTitle tag="h6">
|
||||
Table Default
|
||||
<span className="small ml-1 text-muted">
|
||||
#1.01
|
||||
</span>
|
||||
</CardTitle>
|
||||
<p className="mb-0">
|
||||
Using the most basic table markup, here’s how <code>.table-based</code> tables look in Bootstrap.
|
||||
All table styles are inherited in Bootstrap 4, meaning any nested tables will be styled in the
|
||||
same manner as the parent.
|
||||
</p>
|
||||
</CardBody>
|
||||
{ /* START Table */}
|
||||
<Table className="mb-0" responsive>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="bt-0">Project</th>
|
||||
<th className="bt-0">Deadline</th>
|
||||
<th className="bt-0">Leader</th>
|
||||
<th className="bt-0">Budget</th>
|
||||
<th className="bt-0">Status</th>
|
||||
<th className="text-right bt-0">
|
||||
Actions
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<TrTableDefault />
|
||||
</tbody>
|
||||
</Table>
|
||||
{ /* END Table */}
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
{ /* END Section 1 */}
|
||||
|
||||
{ /* START Section 2 */}
|
||||
<Row>
|
||||
<Col lg={ 12 }>
|
||||
<Card className="mb-3">
|
||||
<CardBody>
|
||||
<CardTitle tag="h6">
|
||||
Table Responsive
|
||||
<span className="small ml-1 text-muted">
|
||||
#2.01
|
||||
</span>
|
||||
</CardTitle>
|
||||
<p className="mb-0">
|
||||
Responsive tables allow tables to be scrolled horizontally with ease.
|
||||
Make any table responsive across all viewports by wrapping a <code>Table</code> with <code>responsive</code>.
|
||||
</p>
|
||||
</CardBody>
|
||||
{ /* START Table */}
|
||||
<Table className="mb-0" responsive>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="bt-0">#</th>
|
||||
<th className="bt-0">Browser & OS</th>
|
||||
<th className="bt-0">IP</th>
|
||||
<th className="bt-0">Location</th>
|
||||
<th className="bt-0">Signed In</th>
|
||||
<th className="text-right bt-0">
|
||||
Action
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<TrTableResponsive />
|
||||
</tbody>
|
||||
</Table>
|
||||
{ /* END Table */}
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
{ /* END Section 2 */}
|
||||
|
||||
{ /* START Section 3 */}
|
||||
<Row>
|
||||
<Col lg={ 12 }>
|
||||
<Card className="mb-3">
|
||||
<CardBody>
|
||||
<CardTitle tag="h6">
|
||||
Table Striped
|
||||
<span className="small ml-1 text-muted">
|
||||
#3.01
|
||||
</span>
|
||||
</CardTitle>
|
||||
<p className="mb-0">
|
||||
Use <code>striped</code> to add zebra-striping to any table row within the <code><tbody></code>.
|
||||
</p>
|
||||
</CardBody>
|
||||
{ /* START Table */}
|
||||
<Table className="mb-0" striped responsive>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="bt-0">#</th>
|
||||
<th className="bt-0">Product Name</th>
|
||||
<th className="bt-0">Last Refresh</th>
|
||||
<th className="text-right bt-0">
|
||||
Last Month
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<TrTableStriped />
|
||||
</tbody>
|
||||
</Table>
|
||||
{ /* END Table */}
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
{ /* END Section 3 */}
|
||||
|
||||
{ /* START Section 4 */}
|
||||
<Row>
|
||||
<Col lg={ 12 }>
|
||||
<Card className="mb-3">
|
||||
<CardBody>
|
||||
<CardTitle tag="h6">
|
||||
Table Hoverable
|
||||
<span className="small ml-1 text-muted">
|
||||
#4.01
|
||||
</span>
|
||||
</CardTitle>
|
||||
<p className="mb-0">
|
||||
Use <code>hover</code> to add zebra-striping to any table row within the <code><tbody></code>.
|
||||
</p>
|
||||
</CardBody>
|
||||
{ /* START Table */}
|
||||
<Table className="mb-0" hover responsive>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="bt-0">#</th>
|
||||
<th className="bt-0">Name</th>
|
||||
<th className="bt-0">Price</th>
|
||||
<th className="text-right bt-0">
|
||||
Date
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<TrTableHoverable />
|
||||
<TrTableHoverable />
|
||||
<TrTableHoverable />
|
||||
<TrTableHoverable />
|
||||
</tbody>
|
||||
</Table>
|
||||
{ /* END Table */}
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
{ /* END Section 4 */}
|
||||
|
||||
{ /* START Section 5 */}
|
||||
<Row>
|
||||
<Col lg={ 12 }>
|
||||
<Card className="mb-3">
|
||||
<CardBody>
|
||||
<CardTitle tag="h6">
|
||||
Table Small
|
||||
<span className="small ml-1 text-muted">
|
||||
#5.01
|
||||
</span>
|
||||
</CardTitle>
|
||||
<p className="mb-0">
|
||||
Add <code>size="sm"</code> to make tables more compact by cutting cell padding in half.
|
||||
</p>
|
||||
</CardBody>
|
||||
{ /* START Table */}
|
||||
<Table className="mb-0" hover responsive>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="bt-0">ID</th>
|
||||
<th className="bt-0">Name</th>
|
||||
<th className="bt-0">Amount</th>
|
||||
<th className="text-right bt-0">
|
||||
Payment
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<TrTableSmall />
|
||||
</tbody>
|
||||
</Table>
|
||||
{ /* END Table */}
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
{ /* END Section 5 */}
|
||||
|
||||
{ /* START Section 6 */}
|
||||
<Row>
|
||||
<Col lg={ 12 }>
|
||||
<Card className="mb-3">
|
||||
<CardBody>
|
||||
<CardTitle tag="h6">
|
||||
Table Borderless
|
||||
<span className="small ml-1 text-muted">
|
||||
#6.01
|
||||
</span>
|
||||
</CardTitle>
|
||||
<p className="mb-0">
|
||||
Add <code>borderless</code> for a table without borders.
|
||||
</p>
|
||||
</CardBody>
|
||||
{ /* START Table */}
|
||||
<Table className="mb-0" borderless responsive>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>ID</th>
|
||||
<th>Date</th>
|
||||
<th>Amount</th>
|
||||
<th>Description</th>
|
||||
<th>Payment Method</th>
|
||||
<th className="text-right">
|
||||
Receipt
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<TrTableBorderless />
|
||||
</tbody>
|
||||
</Table>
|
||||
{ /* END Table */}
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
{ /* END Section 6 */}
|
||||
|
||||
{ /* START Section 7 */}
|
||||
<Row>
|
||||
<Col lg={ 12 }>
|
||||
<Card className="mb-3">
|
||||
<CardBody>
|
||||
<CardTitle tag="h6">
|
||||
Table Bordered
|
||||
<span className="small ml-1 text-muted">
|
||||
#7.01
|
||||
</span>
|
||||
</CardTitle>
|
||||
<p>
|
||||
Add <code>bordered</code> for borders on all sides of the table and cells.
|
||||
</p>
|
||||
{ /* START Table */}
|
||||
<Table className="mb-0" bordered responsive>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Ticket</th>
|
||||
<th>Completion</th>
|
||||
<th>Create</th>
|
||||
<th>Deadline</th>
|
||||
<th className="text-right">
|
||||
Actions
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<TrTableBordered />
|
||||
</tbody>
|
||||
</Table>
|
||||
{ /* END Table */}
|
||||
</CardBody>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
{ /* END Section 7 */}
|
||||
|
||||
{ /* START Section 8 */}
|
||||
<Row>
|
||||
<Col lg={ 12 }>
|
||||
<Card className="mb-3">
|
||||
<CardBody>
|
||||
<CardTitle tag="h6">
|
||||
Table Heads
|
||||
<span className="small ml-1 text-muted">
|
||||
#8.01
|
||||
</span>
|
||||
</CardTitle>
|
||||
<p className="mb-0">
|
||||
Similar to tables and dark tables, use the modifier classes
|
||||
<code>.thead-light</code> or <code>.thead-dark</code> to make
|
||||
<code><thead></code>s appear light or dark gray.
|
||||
</p>
|
||||
</CardBody>
|
||||
{ /* START Table */}
|
||||
<Table className="mb-0" hover responsive>
|
||||
<thead className="thead-light">
|
||||
<tr>
|
||||
<th className="bt-0">#</th>
|
||||
<th className="bt-0">First Name</th>
|
||||
<th className="bt-0">Last Name</th>
|
||||
<th className="bt-0">Email</th>
|
||||
<th className="bt-0">Nick</th>
|
||||
<th className="text-right bt-0">
|
||||
Role
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<TrTableHeads />
|
||||
</tbody>
|
||||
<thead className="thead-dark">
|
||||
<tr>
|
||||
<th className="bt-0">#</th>
|
||||
<th className="bt-0">First Name</th>
|
||||
<th className="bt-0">Last Name</th>
|
||||
<th className="bt-0">Email</th>
|
||||
<th className="bt-0">Nick</th>
|
||||
<th className="text-right bt-0">
|
||||
Role
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<TrTableHeads />
|
||||
</tbody>
|
||||
</Table>
|
||||
{ /* END Table */}
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
{ /* END Section 8 */}
|
||||
|
||||
{ /* START Section 9 */}
|
||||
<Row>
|
||||
<Col lg={ 12 }>
|
||||
<Card className="mb-3">
|
||||
<CardBody>
|
||||
<CardTitle tag="h6">
|
||||
Table Contextual
|
||||
<span className="small ml-1 text-muted">
|
||||
#9.01
|
||||
</span>
|
||||
</CardTitle>
|
||||
<p className="mb-0">
|
||||
Use contextual classes to color table rows or individual cells.
|
||||
</p>
|
||||
</CardBody>
|
||||
{ /* START Table */}
|
||||
<Table className="mb-0" hover responsive>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="bt-0">Invoice</th>
|
||||
<th className="bt-0">Name</th>
|
||||
<th className="bt-0">Date</th>
|
||||
<th className="bt-0">Price</th>
|
||||
<th className="bt-0">Status</th>
|
||||
<th className="text-right bt-0">
|
||||
Country
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<TrTableContextual />
|
||||
</tbody>
|
||||
</Table>
|
||||
{ /* END Table */}
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
{ /* END Section 9 */}
|
||||
|
||||
{ /* START Section 10 */}
|
||||
<Row>
|
||||
<Col lg={ 12 }>
|
||||
<Card className="mb-3" type="background" color="dark">
|
||||
<CardBody>
|
||||
<CardTitle tag="h6">
|
||||
Table Inverse
|
||||
<span className="small ml-1 text-muted">
|
||||
#1.10
|
||||
</span>
|
||||
</CardTitle>
|
||||
<p className="mb-0">
|
||||
You can also invert the colors—with light text on dark backgrounds—with <code>dark</code>.
|
||||
</p>
|
||||
</CardBody>
|
||||
{ /* START Table */}
|
||||
<Table className="mb-0" dark responsive>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="bt-0">Project</th>
|
||||
<th className="bt-0">Deadline</th>
|
||||
<th className="bt-0">Leader</th>
|
||||
<th className="bt-0">Budget</th>
|
||||
<th className="bt-0">Status</th>
|
||||
<th className="text-right bt-0">
|
||||
Actions
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<TrTableDefault
|
||||
projectColor="text-white"
|
||||
leaderStatus="900"
|
||||
dropdownColor="text-white"
|
||||
/>
|
||||
</tbody>
|
||||
</Table>
|
||||
{ /* END Table */}
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
{ /* END Section 10 */}
|
||||
</Container>
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
export default Tables;
|
55
app/routes/Tables/Tables/components/TrTableBordered.js
Executable file
55
app/routes/Tables/Tables/components/TrTableBordered.js
Executable file
@@ -0,0 +1,55 @@
|
||||
import React from 'react';
|
||||
import faker from 'faker/locale/en_US';
|
||||
import _ from 'lodash';
|
||||
|
||||
import {
|
||||
Progress,
|
||||
ButtonGroup,
|
||||
Button
|
||||
} from './../../../../components';
|
||||
|
||||
/*eslint-disable */
|
||||
const completion = [
|
||||
"25",
|
||||
"50",
|
||||
"75",
|
||||
"97"
|
||||
];
|
||||
/*eslint-enable */
|
||||
|
||||
const TrTableBordered = () => (
|
||||
<React.Fragment>
|
||||
{
|
||||
_.times(5, (index) => (
|
||||
<tr key={ index }>
|
||||
<td className="align-middle">
|
||||
<span className="text-inverse">
|
||||
{ faker.company.catchPhrase() }
|
||||
</span>
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
<Progress value={ completion[index%4] } style={{height: "5px"}} />
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
{ faker.date.weekday() }, 12 { faker.date.month() }, 2018
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
{ faker.date.weekday() }, 12 { faker.date.month() }, 2018
|
||||
</td>
|
||||
<td className="align-middle text-right">
|
||||
<ButtonGroup>
|
||||
<Button color="link" className="text-decoration-none">
|
||||
<i className="fa fa-clone"></i>
|
||||
</Button>
|
||||
<Button color="link" className="text-decoration-none">
|
||||
<i className="fa fa-close"></i>
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
}
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
export { TrTableBordered };
|
92
app/routes/Tables/Tables/components/TrTableBorderless.js
Executable file
92
app/routes/Tables/Tables/components/TrTableBorderless.js
Executable file
@@ -0,0 +1,92 @@
|
||||
import React from 'react';
|
||||
import faker from 'faker/locale/en_US';
|
||||
import _ from 'lodash';
|
||||
|
||||
import {
|
||||
Badge,
|
||||
UncontrolledTooltip,
|
||||
} from './../../../../components';
|
||||
|
||||
/*eslint-disable */
|
||||
const payment = [
|
||||
<Badge color="primary">
|
||||
Premium
|
||||
</Badge>,
|
||||
<Badge color="info">
|
||||
Basic
|
||||
</Badge>,
|
||||
<Badge color="warning">
|
||||
Pro
|
||||
</Badge>,
|
||||
<Badge color="danger">
|
||||
Advanced
|
||||
</Badge>,
|
||||
<Badge color="secondary">
|
||||
Free
|
||||
</Badge>
|
||||
];
|
||||
/*eslint-enable */
|
||||
/*eslint-disable */
|
||||
const receipt = [
|
||||
<td className="align-middle text-right">
|
||||
<a href="#" id="UncontrolledTooltipDownload">
|
||||
<i className="fa fa-fw fa-download text-primary"></i>
|
||||
</a>
|
||||
<UncontrolledTooltip placement="left" target="UncontrolledTooltipDownload">
|
||||
Download
|
||||
</UncontrolledTooltip>
|
||||
</td>,
|
||||
<td className="align-middle text-right">
|
||||
</td>
|
||||
];
|
||||
/*eslint-enable */
|
||||
/*eslint-disable */
|
||||
const paymentMethod = [
|
||||
<td className="align-middle">
|
||||
<i className="fa fa-fw fa-paypal text-primary mr-2"></i>
|
||||
{ faker.internet.email() }
|
||||
</td>,
|
||||
<td className="align-middle">
|
||||
<i className="fa fa-fw fa-credit-card-alt mr-2"></i>
|
||||
Visa 4*** **** **** 9221
|
||||
</td>
|
||||
];
|
||||
/*eslint-enable */
|
||||
/*eslint-disable */
|
||||
const status = [
|
||||
<td className="align-middle">
|
||||
<i className="fa fa-fw fa-check text-success"></i>
|
||||
</td>,
|
||||
<td className="align-middle">
|
||||
<i className="fa fa-fw fa-close text-danger"></i>
|
||||
</td>
|
||||
];
|
||||
/*eslint-enable */
|
||||
|
||||
const TrTableBorderless = () => (
|
||||
<React.Fragment>
|
||||
{
|
||||
_.times(5, (index) => (
|
||||
<tr key={ index }>
|
||||
{ status[index%2] }
|
||||
<td className="align-middle">
|
||||
<samp>{ faker.random.number() }</samp>
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
{ faker.date.weekday() }, 12 { faker.date.month() }, 2018
|
||||
</td>
|
||||
<td className="align-middle text-inverse">
|
||||
$ { faker.finance.amount() }
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
{ payment[index%5] }
|
||||
</td>
|
||||
{ paymentMethod[index%2] }
|
||||
{ receipt[index%2] }
|
||||
</tr>
|
||||
))
|
||||
}
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
export { TrTableBorderless };
|
83
app/routes/Tables/Tables/components/TrTableContextual.js
Executable file
83
app/routes/Tables/Tables/components/TrTableContextual.js
Executable file
@@ -0,0 +1,83 @@
|
||||
import React from 'react';
|
||||
import faker from 'faker/locale/en_US';
|
||||
import _ from 'lodash';
|
||||
|
||||
import {
|
||||
Badge
|
||||
} from './../../../../components';
|
||||
|
||||
/*eslint-disable */
|
||||
const trColor = [
|
||||
"table-active",
|
||||
"",
|
||||
|
||||
"table-success",
|
||||
"",
|
||||
|
||||
"table-info",
|
||||
"",
|
||||
|
||||
"table-warning",
|
||||
"",
|
||||
|
||||
"table-danger",
|
||||
"",
|
||||
|
||||
"table-primary",
|
||||
""
|
||||
];
|
||||
/*eslint-enable */
|
||||
/*eslint-disable */
|
||||
const statusColor = [
|
||||
"secondary",
|
||||
"secondary",
|
||||
|
||||
"success",
|
||||
"secondary",
|
||||
|
||||
"info",
|
||||
"secondary",
|
||||
|
||||
"warning",
|
||||
"secondary",
|
||||
|
||||
"danger",
|
||||
"secondary",
|
||||
|
||||
"primary",
|
||||
"secondary"
|
||||
];
|
||||
/*eslint-enable */
|
||||
|
||||
const TrTableContextual = () => (
|
||||
<React.Fragment>
|
||||
{
|
||||
_.times(12, (index) => (
|
||||
<tr className={ trColor[index%12] } key={ index }>
|
||||
<td className="align-middle">
|
||||
#{ faker.finance.mask() }
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
{ faker.name.firstName() } { faker.name.lastName() }
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
{ faker.date.weekday() }, 12 { faker.date.month() }, 2018
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
$ { faker.finance.amount() }
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
<Badge color={ statusColor[index%12] }>
|
||||
{ faker.finance.accountName() }
|
||||
</Badge>
|
||||
</td>
|
||||
<td className="align-middle text-right">
|
||||
{ faker.address.country() }
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
}
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
export { TrTableContextual };
|
127
app/routes/Tables/Tables/components/TrTableDefault.js
Executable file
127
app/routes/Tables/Tables/components/TrTableDefault.js
Executable file
@@ -0,0 +1,127 @@
|
||||
import React from 'react';
|
||||
import faker from 'faker/locale/en_US';
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
UncontrolledButtonDropdown,
|
||||
DropdownToggle,
|
||||
DropdownMenu,
|
||||
DropdownItem,
|
||||
Media,
|
||||
Avatar,
|
||||
AvatarAddOn
|
||||
} from './../../../../components';
|
||||
import { randomAvatar } from './../../../../utilities';
|
||||
|
||||
/*eslint-disable */
|
||||
const colorStatus = [
|
||||
"danger",
|
||||
"success",
|
||||
"warning",
|
||||
"secondary"
|
||||
];
|
||||
/*eslint-enable */
|
||||
|
||||
const TrTableDefault = (props) => (
|
||||
<React.Fragment>
|
||||
{
|
||||
_.times(4, (index) => (
|
||||
<tr key={ index }>
|
||||
<td className="align-middle">
|
||||
<div className={ props.projectColor }>
|
||||
{ faker.name.firstName() } { faker.name.lastName() }
|
||||
</div>
|
||||
<span>
|
||||
{ faker.company.companyName() }
|
||||
</span>
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
<div>
|
||||
Thursday
|
||||
</div>
|
||||
<span className="text-danger">
|
||||
Overdue
|
||||
</span>
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
<Media>
|
||||
<Media left middle className="mr-3">
|
||||
<Avatar.Image
|
||||
size="md"
|
||||
src={ randomAvatar() }
|
||||
addOns={[
|
||||
<AvatarAddOn.Icon
|
||||
className="fa fa-circle"
|
||||
color={ props.leaderStatus }
|
||||
key="avatar-icon-bg"
|
||||
/>,
|
||||
<AvatarAddOn.Icon
|
||||
className="fa fa-circle"
|
||||
color={ colorStatus[index%4] }
|
||||
key="avatar-icon-fg"
|
||||
/>
|
||||
]}
|
||||
/>
|
||||
</Media>
|
||||
<Media body>
|
||||
<div className="mt-0 d-flex text-inverse">
|
||||
{ faker.name.firstName() } { faker.name.lastName() }
|
||||
</div>
|
||||
<span>
|
||||
{ faker.name.jobTitle() }
|
||||
</span>
|
||||
</Media>
|
||||
</Media>
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
<div>
|
||||
{ faker.finance.amount() }
|
||||
</div>
|
||||
<span>
|
||||
Paid
|
||||
</span>
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
<i className="fa fa-circle-o text-success mr-2"></i>
|
||||
{ faker.finance.transactionType() }
|
||||
</td>
|
||||
<td className="align-middle text-right">
|
||||
<UncontrolledButtonDropdown>
|
||||
<DropdownToggle color="link" className={` text-decoration-none ${ props.dropdownColor } `}>
|
||||
<i className="fa fa-gear"></i><i className="fa fa-angle-down ml-2"></i>
|
||||
</DropdownToggle>
|
||||
<DropdownMenu right>
|
||||
<DropdownItem>
|
||||
<i className="fa fa-fw fa-envelope mr-2"></i>
|
||||
Send Email
|
||||
</DropdownItem>
|
||||
<DropdownItem>
|
||||
<i className="fa fa-fw fa-phone mr-2"></i>
|
||||
Call
|
||||
</DropdownItem>
|
||||
<DropdownItem>
|
||||
<i className="fa fa-fw fa-user mr-2"></i>
|
||||
Profile
|
||||
</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</UncontrolledButtonDropdown>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
}
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
TrTableDefault.propTypes = {
|
||||
projectColor: PropTypes.node,
|
||||
leaderStatus: PropTypes.node,
|
||||
dropdownColor: PropTypes.node
|
||||
};
|
||||
TrTableDefault.defaultProps = {
|
||||
projectColor: "text-inverse",
|
||||
leaderStatus: "white",
|
||||
dropdownColor: ""
|
||||
};
|
||||
|
||||
export { TrTableDefault };
|
49
app/routes/Tables/Tables/components/TrTableHeads.js
Executable file
49
app/routes/Tables/Tables/components/TrTableHeads.js
Executable file
@@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import faker from 'faker/locale/en_US';
|
||||
import _ from 'lodash';
|
||||
|
||||
import {
|
||||
Badge
|
||||
} from './../../../../components';
|
||||
|
||||
/*eslint-disable */
|
||||
const colorStatus = [
|
||||
"danger",
|
||||
"success",
|
||||
"warning",
|
||||
"secondary"
|
||||
];
|
||||
/*eslint-enable */
|
||||
|
||||
const TrTableHeads = () => (
|
||||
<React.Fragment>
|
||||
{
|
||||
_.times(4, (index) => (
|
||||
<tr key={ index }>
|
||||
<td className="align-middle">
|
||||
1
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
{ faker.name.firstName() }
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
{ faker.name.lastName() }
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
{ faker.internet.email() }
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
{ faker.internet.userName() }
|
||||
</td>
|
||||
<td className="align-middle text-right">
|
||||
<Badge color={ colorStatus[index%4] }>
|
||||
{ faker.name.jobType() }
|
||||
</Badge>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
}
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
export { TrTableHeads };
|
25
app/routes/Tables/Tables/components/TrTableHoverable.js
Executable file
25
app/routes/Tables/Tables/components/TrTableHoverable.js
Executable file
@@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
import faker from 'faker/locale/en_US';
|
||||
|
||||
const TrTableHoverable = () => (
|
||||
<React.Fragment>
|
||||
<tr>
|
||||
<td className="align-middle">
|
||||
<a href="#">
|
||||
Invoice #{ faker.finance.mask() }
|
||||
</a>
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
{ faker.name.firstName() } { faker.name.lastName() }
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
$ { faker.finance.amount() }
|
||||
</td>
|
||||
<td className="align-middle text-right">
|
||||
{ faker.date.weekday() }, 12 { faker.date.month() }, 2018
|
||||
</td>
|
||||
</tr>
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
export { TrTableHoverable };
|
97
app/routes/Tables/Tables/components/TrTableResponsive.js
Executable file
97
app/routes/Tables/Tables/components/TrTableResponsive.js
Executable file
@@ -0,0 +1,97 @@
|
||||
import React from 'react';
|
||||
import faker from 'faker/locale/en_US';
|
||||
import _ from 'lodash';
|
||||
|
||||
import {
|
||||
UncontrolledTooltip,
|
||||
Media
|
||||
} from './../../../../components';
|
||||
|
||||
/*eslint-disable */
|
||||
const browserOs = [
|
||||
"Safari",
|
||||
"Firefox",
|
||||
"Opera",
|
||||
"Chrome"
|
||||
];
|
||||
/*eslint-enable */
|
||||
/*eslint-disable */
|
||||
const browserIcon = [
|
||||
"desktop",
|
||||
"laptop",
|
||||
"mobile",
|
||||
"tablet"
|
||||
];
|
||||
/*eslint-enable */
|
||||
/*eslint-disable */
|
||||
const colorStatus = [
|
||||
"danger",
|
||||
"success",
|
||||
"warning",
|
||||
"secondary"
|
||||
];
|
||||
/*eslint-enable */
|
||||
|
||||
const TrTableResponsive = () => (
|
||||
<React.Fragment>
|
||||
{
|
||||
_.times(4, (index) => (
|
||||
<tr key={ index }>
|
||||
<td className="align-middle">
|
||||
<i className={`fa fa -fw fa-circle text-${ colorStatus[index%4] }`}></i>
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
<Media>
|
||||
<Media left className="align-self-center mr-3">
|
||||
<i className={`fa fa-fw fa-${ browserIcon[index%4] } fa-lg`}></i>
|
||||
</Media>
|
||||
<Media body>
|
||||
<div className="mt-0 d-flex">
|
||||
<span className="text-inverse">
|
||||
{ browserOs[index%4] }
|
||||
</span> /
|
||||
{ faker.system.semver() }
|
||||
</div>
|
||||
<span>
|
||||
macOs { faker.system.semver() }
|
||||
</span>
|
||||
</Media>
|
||||
</Media>
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
<div>
|
||||
<samp>
|
||||
{ faker.internet.ip() }
|
||||
</samp>
|
||||
</div>
|
||||
<span>
|
||||
-
|
||||
</span>
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
<div>
|
||||
{ faker.address.city() }
|
||||
</div>
|
||||
<span>
|
||||
{ faker.address.state() }, { faker.address.country() }
|
||||
</span>
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
{ faker.date.weekday() }, 12 { faker.date.month() }, 2018<br />
|
||||
12:34 PM
|
||||
</td>
|
||||
<td className="align-middle text-right">
|
||||
<a href="#" id="UncontrolledTooltipRevoke">
|
||||
<i className="fa fa-fw fa-close text-danger"></i>
|
||||
</a>
|
||||
<UncontrolledTooltip placement="left" target="UncontrolledTooltipRevoke">
|
||||
Revoke
|
||||
</UncontrolledTooltip>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
}
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
export { TrTableResponsive };
|
43
app/routes/Tables/Tables/components/TrTableSmall.js
Executable file
43
app/routes/Tables/Tables/components/TrTableSmall.js
Executable file
@@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import faker from 'faker/locale/en_US';
|
||||
import _ from 'lodash';
|
||||
|
||||
import {
|
||||
Badge
|
||||
} from './../../../../components';
|
||||
|
||||
/*eslint-disable */
|
||||
const payment = [
|
||||
"success",
|
||||
"danger",
|
||||
"warning",
|
||||
"secondary"
|
||||
];
|
||||
/*eslint-enable */
|
||||
|
||||
const TrTableSmall = () => (
|
||||
<React.Fragment>
|
||||
{
|
||||
_.times(4, (index) => (
|
||||
<tr key={ index }>
|
||||
<td className="align-middle">
|
||||
#{ faker.finance.mask() }
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
{ faker.name.firstName() } { faker.name.lastName() }
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
$ { faker.finance.amount() }
|
||||
</td>
|
||||
<td className="align-middle text-right">
|
||||
<Badge pill color={ payment[index%4] }>
|
||||
{ faker.finance.transactionType() }
|
||||
</Badge>
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
}
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
export { TrTableSmall };
|
47
app/routes/Tables/Tables/components/TrTableStriped.js
Executable file
47
app/routes/Tables/Tables/components/TrTableStriped.js
Executable file
@@ -0,0 +1,47 @@
|
||||
import React from 'react';
|
||||
import faker from 'faker/locale/en_US';
|
||||
import _ from 'lodash';
|
||||
|
||||
/*eslint-disable */
|
||||
const lastMonth = [
|
||||
<td className="align-middle text-right text-danger">
|
||||
<i className="fa fa-fw fa-caret-down mr-1"></i>92.02%
|
||||
</td>,
|
||||
<td className="align-middle text-right text-success">
|
||||
<i className="fa fa-fw fa-caret-up mr-1"></i>23.02%
|
||||
</td>
|
||||
];
|
||||
/*eslint-enable */
|
||||
/*eslint-disable */
|
||||
const no = [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4"
|
||||
];
|
||||
/*eslint-enable */
|
||||
|
||||
const TrTableStriped = () => (
|
||||
<React.Fragment>
|
||||
{
|
||||
_.times(4, (index) => (
|
||||
<tr key={ index }>
|
||||
<td className="align-middle">
|
||||
{ no[index%4] }.
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
<span className="text-inverse">
|
||||
{ faker.commerce.productName() }
|
||||
</span>
|
||||
</td>
|
||||
<td className="align-middle">
|
||||
{ faker.date.weekday() }, 12 { faker.date.month() }, 2018
|
||||
</td>
|
||||
{ lastMonth[index%2] }
|
||||
</tr>
|
||||
))
|
||||
}
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
export { TrTableStriped };
|
3
app/routes/Tables/Tables/index.js
Executable file
3
app/routes/Tables/Tables/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import Tables from './Tables';
|
||||
|
||||
export default Tables;
|
Reference in New Issue
Block a user