Skip to content

Commit

Permalink
feat(react-grid): support column data types (#336)
Browse files Browse the repository at this point in the history
  • Loading branch information
gsobolev committed Sep 22, 2017
1 parent 26fd6f2 commit 1528800
Show file tree
Hide file tree
Showing 41 changed files with 1,157 additions and 76 deletions.
101 changes: 101 additions & 0 deletions packages/dx-react-demos/src/bootstrap3/data-types/editors.jsx
@@ -0,0 +1,101 @@
import React from 'react';
import {
DataTypeProvider,
EditingState,
} from '@devexpress/dx-react-grid';
import {
Grid,
TableView,
TableHeaderRow,
TableEditRow,
TableEditColumn,
} from '@devexpress/dx-react-grid-bootstrap3';

import {
generateRows,
globalSalesValues,
} from '../../demo-data/generator';

const BooleanTypeProvider = () => (
<DataTypeProvider
type="boolean"
formatterTemplate={({ value }) =>
<span className="label label-default">{value ? 'Yes' : 'No'}</span>}
editorTemplate={({ value, onValueChange }) => (
<select
className="form-control"
value={value}
onChange={e => onValueChange(e.target.value === 'true')}
>
<option value={false}>No</option>
<option value>Yes</option>
</select>
)}
/>
);

export default class Demo extends React.PureComponent {
constructor(props) {
super(props);

this.state = {
columns: [
{ name: 'customer', title: 'Customer' },
{ name: 'product', title: 'Product' },
{ name: 'units', title: 'Units' },
{ name: 'shipped', title: 'Shipped', dataType: 'boolean' },
],
rows: generateRows({
columnValues: { id: ({ index }) => index, ...globalSalesValues },
length: 14,
}),
};

this.commitChanges = ({ added, changed, deleted }) => {
let rows = this.state.rows;
if (added) {
const startingAddedId = (rows.length - 1) > 0 ? rows[rows.length - 1].id + 1 : 0;
rows = [
...rows,
...added.map((row, index) => ({
id: startingAddedId + index,
...row,
})),
];
}
if (changed) {
rows = rows.map(row => (changed[row.id] ? { ...row, ...changed[row.id] } : row));
}
if (deleted) {
const deletedSet = new Set(deleted);
rows = rows.filter(row => !deletedSet.has(row.id));
}
this.setState({ rows });
};
}
render() {
const { rows, columns } = this.state;

return (
<Grid
rows={rows}
columns={columns}
getRowId={row => row.id}
>
<BooleanTypeProvider />
<EditingState
onCommitChanges={this.commitChanges}
defaultEditingRows={[0]}
/>
<TableView />
<TableHeaderRow />
<TableEditRow />
<TableEditColumn
allowAdding
allowEditing
allowDeleting
/>
</Grid>
);
}
}
11 changes: 11 additions & 0 deletions packages/dx-react-demos/src/bootstrap3/data-types/editors.test.jsx
@@ -0,0 +1,11 @@
import React from 'react';
import { mount } from 'enzyme';
import Demo from './editors';

describe('BS3: data types formatting demo', () => {
it('should work', () => {
mount(
<Demo />,
);
});
});
61 changes: 61 additions & 0 deletions packages/dx-react-demos/src/bootstrap3/data-types/formatters.jsx
@@ -0,0 +1,61 @@
import React from 'react';
import {
DataTypeProvider,
} from '@devexpress/dx-react-grid';
import {
Grid,
TableView,
TableHeaderRow,
} from '@devexpress/dx-react-grid-bootstrap3';

import {
generateRows,
globalSalesValues,
} from '../../demo-data/generator';

const CurrencyTypeProvider = () => (
<DataTypeProvider
type="currency"
formatterTemplate={({ value }) => (
<b className="text-primary">${value}</b>
)}
/>
);
const DateTypeProvider = () => (
<DataTypeProvider
type="date"
formatterTemplate={({ value }) =>
value.replace(/(\d{4})-(\d{2})-(\d{2})/, '$3.$2.$1')}
/>
);

export default class Demo extends React.PureComponent {
constructor(props) {
super(props);

this.state = {
columns: [
{ name: 'customer', title: 'Customer' },
{ name: 'product', title: 'Product' },
{ name: 'saleDate', title: 'Sale Date', dataType: 'date' },
{ name: 'amount', title: 'Sale Amount', dataType: 'currency', align: 'right' },
],
rows: generateRows({ columnValues: globalSalesValues, length: 14 }),
};
}
render() {
const { rows, columns } = this.state;

return (
<Grid
rows={rows}
columns={columns}
>
<CurrencyTypeProvider />
<DateTypeProvider />
<TableView />
<TableHeaderRow />
</Grid>
);
}
}
@@ -0,0 +1,11 @@
import React from 'react';
import { mount } from 'enzyme';
import Demo from './formatters';

describe('BS3: custom editors demo', () => {
it('should work', () => {
mount(
<Demo />,
);
});
});
1 change: 1 addition & 0 deletions packages/dx-react-demos/src/demo-data/generator.js
Expand Up @@ -124,6 +124,7 @@ export const globalSalesValues = {
year: 2016,
month: () => Math.floor(random() * 3) + 1,
}),
shipped: [true, false],
};

export const employeeValues = {
Expand Down
10 changes: 10 additions & 0 deletions packages/dx-react-demos/src/demo-registry.js
Expand Up @@ -47,6 +47,16 @@ export const demos = {
'material-ui': require('./material-ui/data-accessors/custom-data-accessors-in-columns').default,
},
},
'data-types': {
formatters: {
bootstrap3: require('./bootstrap3/data-types/formatters').default,
'material-ui': require('./material-ui/data-types/formatters').default,
},
editors: {
bootstrap3: require('./bootstrap3/data-types/editors').default,
'material-ui': require('./material-ui/data-types/editors').default,
},
},
'detail-row': {
'simple-detail-row': {
bootstrap3: require('./bootstrap3/detail-row/simple-detail-row').default,
Expand Down
2 changes: 1 addition & 1 deletion packages/dx-react-demos/src/demo-viewer/demo-renderer.jsx
Expand Up @@ -10,7 +10,7 @@ export const DemoRenderer = ({
}) => {
const Component = demos[currentSection][currentDemo][currentTheme];

if (!Component) return <div>&gt; DEMO NOT AVALIABLE &lt;</div>;
if (!Component) return <div>&gt; DEMO IS NOT AVAILABLE &lt;</div>;

const DemoContainer = themes
.find(({ name: theme }) => theme === currentTheme)
Expand Down
100 changes: 100 additions & 0 deletions packages/dx-react-demos/src/material-ui/data-types/editors.jsx
@@ -0,0 +1,100 @@
import React from 'react';
import Chip from 'material-ui/Chip';
import {
DataTypeProvider,
EditingState,
} from '@devexpress/dx-react-grid';
import {
Grid,
TableView,
TableHeaderRow,
TableEditRow,
TableEditColumn,
DropDownMenu,
} from '@devexpress/dx-react-grid-material-ui';

import {
generateRows,
globalSalesValues,
} from '../../demo-data/generator';

const BooleanTypeProvider = () => (
<DataTypeProvider
type="boolean"
formatterTemplate={({ value }) => <Chip label={value ? 'Yes' : 'No'} />}
editorTemplate={({ value, onValueChange }) => (
<DropDownMenu
selectedItem={value ? 'Yes' : 'No'}
items={['No', 'Yes']}
onItemClick={item => onValueChange(item === 'Yes')}
/>
)}
/>
);

export default class Demo extends React.PureComponent {
constructor(props) {
super(props);

this.state = {
columns: [
{ name: 'customer', title: 'Customer' },
{ name: 'product', title: 'Product' },
{ name: 'units', title: 'Units' },
{ name: 'shipped', title: 'Shipped', dataType: 'boolean' },
],
rows: generateRows({
columnValues: { id: ({ index }) => index, ...globalSalesValues },
length: 14,
}),
};

this.commitChanges = ({ added, changed, deleted }) => {
let rows = this.state.rows;
if (added) {
const startingAddedId = (rows.length - 1) > 0 ? rows[rows.length - 1].id + 1 : 0;
rows = [
...rows,
...added.map((row, index) => ({
id: startingAddedId + index,
...row,
})),
];
}
if (changed) {
rows = rows.map(row => (changed[row.id] ? { ...row, ...changed[row.id] } : row));
}
if (deleted) {
const deletedSet = new Set(deleted);
rows = rows.filter(row => !deletedSet.has(row.id));
}
this.setState({ rows });
};
}
render() {
const { rows, columns } = this.state;

return (
<Grid
rows={rows}
columns={columns}
getRowId={row => row.id}
>
<BooleanTypeProvider />
<EditingState
onCommitChanges={this.commitChanges}
defaultEditingRows={[0]}
/>
<TableView />
<TableHeaderRow />
<TableEditRow />
<TableEditColumn
allowAdding
allowEditing
allowDeleting
/>
</Grid>
);
}
}

@@ -0,0 +1,14 @@
import React from 'react';
import { mount } from 'enzyme';
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
import Demo from './editors';

describe('MUI: custom editors demo', () => {
it('should work', () => {
mount(
<MuiThemeProvider theme={createMuiTheme()}>
<Demo />
</MuiThemeProvider>,
);
});
});
61 changes: 61 additions & 0 deletions packages/dx-react-demos/src/material-ui/data-types/formatters.jsx
@@ -0,0 +1,61 @@
import React from 'react';
import {
DataTypeProvider,
} from '@devexpress/dx-react-grid';
import {
Grid,
TableView,
TableHeaderRow,
} from '@devexpress/dx-react-grid-material-ui';

import {
generateRows,
globalSalesValues,
} from '../../demo-data/generator';

const CurrencyTypeProvider = () => (
<DataTypeProvider
type="currency"
formatterTemplate={({ value }) => (
<b style={{ color: 'darkblue' }}>${value}</b>
)}
/>
);
const DateTypeProvider = () => (
<DataTypeProvider
type="date"
formatterTemplate={({ value }) =>
value.replace(/(\d{4})-(\d{2})-(\d{2})/, '$3.$2.$1')}
/>
);

export default class Demo extends React.PureComponent {
constructor(props) {
super(props);

this.state = {
columns: [
{ name: 'customer', title: 'Customer' },
{ name: 'product', title: 'Product' },
{ name: 'saleDate', title: 'Sale Date', dataType: 'date' },
{ name: 'amount', title: 'Sale Amount', dataType: 'currency', align: 'right' },
],
rows: generateRows({ columnValues: globalSalesValues, length: 14 }),
};
}
render() {
const { rows, columns } = this.state;

return (
<Grid
rows={rows}
columns={columns}
>
<CurrencyTypeProvider />
<DateTypeProvider />
<TableView />
<TableHeaderRow />
</Grid>
);
}
}

0 comments on commit 1528800

Please sign in to comment.