diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 9636917058..d8ab62c542 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -10,7 +10,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 name: Build, Lint & Jest Test steps: - name: Get sources @@ -47,7 +47,7 @@ jobs: retention-days: 1 test_cafe: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: build strategy: matrix: @@ -79,7 +79,7 @@ jobs: run: yarn testcafe:ci:${{ matrix.component }} site: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: build name: Site steps: diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml index e515299635..056665a03c 100644 --- a/.github/workflows/lint-pr.yml +++ b/.github/workflows/lint-pr.yml @@ -10,7 +10,7 @@ on: jobs: main: name: Validate PR title - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: amannn/action-semantic-pull-request@v4 env: diff --git a/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/custom-easing.jsx b/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/custom-easing.jsx new file mode 100644 index 0000000000..4fd3e04fdf --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/custom-easing.jsx @@ -0,0 +1,50 @@ +export default () => { + const [currentData, setCurrentData] = useState(data[2017]); + + const changeData = useCallback(e => { + setCurrentData(data[e.target.value]); + }; + + return ( + + + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/simple-animation.jsx b/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/simple-animation.jsx new file mode 100644 index 0000000000..f9af7c2a9b --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/simple-animation.jsx @@ -0,0 +1,30 @@ +export default () => { + return ( + + + + + + + + + + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/with-transition.jsx b/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/with-transition.jsx new file mode 100644 index 0000000000..bb7c3082e0 --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/with-transition.jsx @@ -0,0 +1,67 @@ +const option = [2017, 2018, 2019]; + +export default () => { + const [currentData, setCurrentData] = useState(data[2017]); + const id = useRef(undefined); + const index = useRef(1); + const selectRef = useRef(null); + + useEffect(() => { + id.current = setInterval(() => { + selectRef.selectedIndex = index.current; + setCurrentData(data[option[index.current]]); + + if (index.current === 2) { + index.current = 0; + } else { + index.current += 1; + } + }, 4000); + + return () => clearTimeout(id.current); + }, []); + + const changeData = useCallback(e => { + setCurrentData(data[e.target.value]); + }; + + return ( + + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/bar-chart/$migration/rotated-bar.jsx b/packages/dx-react-chart-demos/src/demo-sources/bar-chart/$migration/rotated-bar.jsx new file mode 100644 index 0000000000..c72599c91d --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/bar-chart/$migration/rotated-bar.jsx @@ -0,0 +1,17 @@ +export default () => { + return ( + + + + + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/area.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/area.jsx new file mode 100644 index 0000000000..bb47950a11 --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/area.jsx @@ -0,0 +1,12 @@ +export default () => { + return ( + <React.Fragment> + <Chart dataSource={chartData}> + <CommonSeriesSettings argumentField="year" type="area" /> + <Series valueField="ru"/> + <Series valueField="ch"/> + <Series valueField="us"/> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/band-axis.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/band-axis.jsx new file mode 100644 index 0000000000..d9dd82213b --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/band-axis.jsx @@ -0,0 +1,12 @@ +export default () => { + return ( + <React.Fragment> + <Chart dataSource={chartData}> + <CommonSeriesSettings argumentField="state" type="bar" /> + <Series valueField="young" name="Young" /> + <Series valueField="middle" name="Middle" /> + <Series valueField="older" name="Older" /> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/bar-line.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/bar-line.jsx new file mode 100644 index 0000000000..c64a7f2f12 --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/bar-line.jsx @@ -0,0 +1,51 @@ +export default () => { + return ( + <React.Fragment> + <Chart dataSource={chartData}> + <ValueAxis + name="oil" + /> + <ValueAxis + name="price" + position="right" + > + <Label format="currency" /> + </ValueAxis> + <CommonSeriesSettings + argumentField="year" + axis="oil" + type="stackedbar" + /> + <Title + text="Oil production vs Oil price" + /> + <Series + name="USA" + valueField="usa" + /> + <Series + name="Saudi Arabia" + valueField="saudiArabia" + /> + <Series + name="Iran" + valueField="iran" + /> + <Series + name="Mexico" + valueField="mexico" + /> + <Series + name="Russia" + valueField="russia" + /> + <Series + name="Oil Price" + valueField="price" + axis="price" + type="line" + /> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/bar.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/bar.jsx new file mode 100644 index 0000000000..bd48ea995e --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/bar.jsx @@ -0,0 +1,13 @@ +export default () => { + return ( + <React.Fragment> + <Chart dataSource={chartData}> + <Series + type="bar" + valueField="population" + argumentField="year" + /> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/basic-legend.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/basic-legend.jsx new file mode 100644 index 0000000000..666649f07f --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/basic-legend.jsx @@ -0,0 +1,16 @@ +export default () => { + return ( + <React.Fragment> + <Chart dataSource={chartData} height={height}> + <Series + name="Series name" + valueField="ch" + argumentField="year" + type="area" + /> + <Title text="Title" /> + <Legend visible={true} /> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/default-axis.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/default-axis.jsx new file mode 100644 index 0000000000..4df8082b6c --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/default-axis.jsx @@ -0,0 +1,11 @@ +export default () => { + return ( + <React.Fragment> + <Chart dataSource={chartData}> + <CommonSeriesSettings argumentField="argument" /> + <Series valueField="lineValue" type="line" /> + <Series valueField="splineValue" type="spline" /> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/legend-customization.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/legend-customization.jsx new file mode 100644 index 0000000000..f78d02beda --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/legend-customization.jsx @@ -0,0 +1,40 @@ +const markerPath = { + 'Original Signal': 'M 0 8 C 2 4 7 4 9.5 8 C 11 12 16 12 18 8 L 18 10 C 16 14 11 14 8.5 10 C 7 6 2 6 0 10 Z', + 'Noisy Signal': 'M 18 8 L 12 12 L 7 3 L 0 7.4 L 0 10 L 6 6 L 11 15 L 18 10.6 Z', + }; + + const markerRender = ({ series, marker: { fill } }) => { + return ( + <svg> + <rect x={0} y={0} width={18} height={18} fill={color} opacity={0.3}></rect> + <path d={markerPath[series.name]} fill={color}></path> + </svg> + ); + }; + + export default () => { + return ( + <React.Fragment> + <Chart dataSource={chartData} height={height}> + <Series + name="Noisy signal" + valueField="value" + argumentField="argument" + type="line" + /> + <Series + name="Original signal" + valueField="originalValue" + argumentField="argument" + type="line" + /> + <Title + text="Noisy and Original signals" + > + <Font size={32} weight={300} /> + + + + + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/line-spline.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/line-spline.jsx new file mode 100644 index 0000000000..eb6f3cd10e --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/line-spline.jsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { + Chart, + Series, + CommonSeriesSettings, +} from 'devextreme-react/chart'; + +/* ... */ + +export default () => { + return ( + + + + + + + + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/logarithm.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/logarithm.jsx new file mode 100644 index 0000000000..74e4b2179f --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/logarithm.jsx @@ -0,0 +1,24 @@ +const format = formatPrefix('.1', 1e24); + +export default () => { + return ( + + + + + + + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/pie.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/pie.jsx new file mode 100644 index 0000000000..d7d39ea8c9 --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/pie.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import PieChart, { + Series, + Label, + Connector, + Size, + Export, + PieChartTypes, +} from 'devextreme-react/pie-chart'; + +export default () => { + return ( + <React.Fragment> + <PieChart + dataSource={chartData} + > + <Series + argumentField="country" + valueField="area" + /> + </PieChart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/point-customization.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/point-customization.jsx new file mode 100644 index 0000000000..838dc2fae1 --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/point-customization.jsx @@ -0,0 +1,22 @@ +export default () => { + return ( + <React.Fragment> + <Chart dataSource={chartData}> + <CommonSeriesSettings argumentField="argument" type="line"> + <Point> + <Border color="white" width={1} /> + </Point> + </CommonSeriesSettings> + <Series valueField="constantValue"> + <Point symbol="polygon" /> + </Series> + <Series valueField="linearValue"> + <Point symbol="cross" /> + </Series> + <Series valueField="powValue"> + <Point image='/static/assets/images/star.png' /> + </Series> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/scatter.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/scatter.jsx new file mode 100644 index 0000000000..93df1fcf6c --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/scatter.jsx @@ -0,0 +1,17 @@ +export default () => { + return ( + <React.Fragment> + <Chart dataSource={chartData}> + <CommonSeriesSettings type="scatter" /> + <Series + valueField="val1" + argumentField="arg1" + /> + <Series + valueField="val2" + argumentField="arg2" + /> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/theme.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/theme.jsx new file mode 100644 index 0000000000..3881b200ff --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/theme.jsx @@ -0,0 +1,34 @@ +export const paletteCollection = ['Material', 'Soft Pastel', 'Harmony Light', 'Pastel', 'Bright', 'Soft', 'Ocean', 'Office', 'Vintage', 'Violet', 'Carmine', 'Dark Moon', 'Soft Blue', 'Dark Violet', 'Green Mist']; + +export default () => { + const [paletteName, setPaletteName] = useState('Material'); + + const changeScheme = useCallback(e => { + setPaletteName(paletteCollection[e.target.value]); + }, []); + + return ( + <React.Fragment> + <PieChart + dataSource={chartData} + palette={paletteName} + > + <Series + valueField="val" + argumentField="category" + /> + </PieChart> + <div className="d-flex justify-content-center mt-3"> + {getPalette(palette).simpleSet.map((color) => <div key={color} style={{ width: '40px', height: '40px', backgroundColor: color }} />)} + </div> + <div className="pb-5 pl-5 w-200" style={{ width: '200px' }}> + <h5>Scheme</h5> + <select className="custom-select" onChange={changeScheme}> + { + paletteCollection.map((palleteName, idx) => <option defaultValue={idx ? false : true} value={idx}>{palleteName}</option>) + } + </select> + </div> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/hover-controlled.jsx b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/hover-controlled.jsx new file mode 100644 index 0000000000..e5911db2ff --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/hover-controlled.jsx @@ -0,0 +1,29 @@ +export default () => { + const [hoveredSeries, setHoveredSeries] = useState(undefined); + const [hoveredPoint, setHoveredPoint] = useState(undefined); + + const onSeriesHoverChanged = useCallback(({ target: series }) => { + setHoveredSeries(series.isHovered() ? series: null); + }, []); + + const onPointHoverChanged = useCallback(({ target: point }) => { + setHoveredSeries(point.isHovered() ? point: null); + }, []); + + return ( + <React.Fragment> + <Chart + dataSource={chartData} + onSeriesHoverChanged={onSeriesHoverChanged} + onPointHoverChanged={onPointHoverChanged} + > + <Series + type="bar" + valueField="population" + argumentField="year" + hoverMode="onlyPoint" + /> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/hover.jsx b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/hover.jsx new file mode 100644 index 0000000000..102cc32a6f --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/hover.jsx @@ -0,0 +1,14 @@ +export default () => { + return ( + <React.Fragment> + <Chart dataSource={chartData}> + <Series + type="bar" + valueField="population" + argumentField="year" + hoverMode="onlyPoint" + /> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/multiple-selection.jsx b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/multiple-selection.jsx new file mode 100644 index 0000000000..593e75c4b6 --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/multiple-selection.jsx @@ -0,0 +1,37 @@ +export default () => { + const [selectedPoints, setSelectedPoints] = useState([]); + + const onPointClick = useCallback(({ target: point }) => { + const isPointSelected = point.isSelected(); + + if (isPointSelected) { + point.clearSelection(); + setSelectedPoints(points => points.filter(selectedPoint => selectedPoint !== point)); + } + else { + point.select(); + setSelectedPoints(selectedPoints => [...selectedPoints, point]); + } + }, []); + + return ( + <React.Fragment> + <span> + Total bars selected: + {' '} + {selectedPoints.length} + </span> + <Chart + dataSource={chartData} + onPointClick={onPointClick} + pointSelectionMode='multiple' + > + <Series + type="bar" + valueField="population" + argumentField="year" + /> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/selection.jsx b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/selection.jsx new file mode 100644 index 0000000000..157bd91cb9 --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/selection.jsx @@ -0,0 +1,34 @@ +export default () => { + const [selectedPoint, setSelectedPoint] = useState(undefined); + + const onPointClick = useCallback(({ target: point, component }) => { + if (point.isSelected()) { + component.clearSelection(); + setSelectedPoint(undefined); + } + else { + point.select(); + setSelectedPoint(point); + } + }, []); + + return ( + <React.Fragment> + <span> + Selected value: + {' '} + {selectedPoint ? data[selectedPoint].population : undefined} + </span> + <Chart + dataSource={chartData} + onPointClick={onPointClick} + > + <Series + type="bar" + valueField="population" + argumentField="year" + /> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/single-multiple-selection.jsx b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/single-multiple-selection.jsx new file mode 100644 index 0000000000..0a122d12e0 --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/single-multiple-selection.jsx @@ -0,0 +1,59 @@ +export default () => { + const [selectedPoints, setSelectedPoints] = useState([]); + + const clearSelection = useCallback((component) => { + component.clearSelection(); + setSelectedPoints([]); + }, []); + + const selectPoint = useCallback((point) => { + point.select(); + setSelectedPoints(points => [...points, point]); + }, []); + + const deselectPoint = useCallback((point) => { + point.clearSelection(); + setSelectedPoints(points => points.filter(selectedPoint => selectedPoint !== point)); + }, []); + + const onPointClick = useCallback(({ target: point, event, component }) => { + const isPointSelected = point.isSelected(); + const selectedPointsCount = selectedPoints.length; + + if (!event.ctrlKey && !event.metaKey) { + clearSelection(component); + if (!isPointSelected || selectedPointsCount > 1) { + selectPoint(point); + } + return; + } + + if (isPointSelected) { + deselectPoint(point) + } + else { + selectPoint(point) + } + }, [selectedPoints, clearSelection, selectPoint, deselectPoint]); + + return ( + <React.Fragment> + <span> + Total bars selected: + {' '} + {selectedPoints.length} + </span> + <Chart + dataSource={chartData} + onPointClick={onPointClick} + pointSelectionMode='multiple' + > + <Series + type="bar" + valueField="population" + argumentField="year" + /> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/layout/$migration/legend.jsx b/packages/dx-react-chart-demos/src/demo-sources/layout/$migration/legend.jsx new file mode 100644 index 0000000000..b4909e4b91 --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/layout/$migration/legend.jsx @@ -0,0 +1,35 @@ +export default () => { + return ( + <React.Fragment> + <Chart dataSource={chartData} height={height}> + <CommonSeriesSettings + argumentField="state" + type="stackedbar" + /> + <Series + name="👶 Young" + valueField="young" + /> + <Series + name="🧑 Adult" + valueField="middle" + /> + <Series + name="🧓 Old" + valueField="older" + /> + <Legend + itemTextPosition={'left'} + > + <Title + text='👪 Population' + horizontalAlignment='right' + > + <Font size={24} /> + <Margin left={24} right={24} /> + + + + + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/layout/$migration/title.jsx b/packages/dx-react-chart-demos/src/demo-sources/layout/$migration/title.jsx new file mode 100644 index 0000000000..3a99fda3fe --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/layout/$migration/title.jsx @@ -0,0 +1,31 @@ +export default () => { + return ( + + + + + + + + <Font size={24} /> + <Margin bottom={16} /> + + + + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/tooltip/$migration/controlled.jsx b/packages/dx-react-chart-demos/src/demo-sources/tooltip/$migration/controlled.jsx new file mode 100644 index 0000000000..fd5046b62e --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/tooltip/$migration/controlled.jsx @@ -0,0 +1,31 @@ +export default () => { + const [tooltipTarget, setTooltipTarget] = useState(undefined); + + const onPointHoverChanged = useCallback(({ target: point, component }) => { + setTooltipTarget(point); + + if (point) { + point.showTooltip(); + } else { + component.hideTooltip(); + } + }, []); + + return ( + + + + + + + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/tooltip/$migration/uncontrolled.jsx b/packages/dx-react-chart-demos/src/demo-sources/tooltip/$migration/uncontrolled.jsx new file mode 100644 index 0000000000..88d3ab8960 --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/tooltip/$migration/uncontrolled.jsx @@ -0,0 +1,19 @@ +export default () => { + return ( + + + + + <Tooltip + enabled={true} + /> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/controlled.jsx b/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/controlled.jsx new file mode 100644 index 0000000000..d08f971f95 --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/controlled.jsx @@ -0,0 +1,44 @@ +export default () => { + const [argumentVisualRange, setArgumentVisualRange] = useState([null, null]); + const [valueVisualRange, setValueVisualRange] = useState([null, null]); + + const onZoomEnd = useCallback(({ axis, range }) => { + if (axis.isArgumentAxis) { + setArgumentVisualRange(range); + } + else { + setValueVisualRange(range); + } + }, []); + + return ( + <React.Fragment> + <Chart + dataSource={chartData} + onZoomEnd={onZoomEnd} + > + <ArgumentAxis> + <VisualRange + startValue={argumentVisualRange[0]} + endValue={argumentVisualRange[1]} + /> + </ArgumentAxis> + <ValueAxis> + <VisualRange + startValue={valueVisualRange[0]} + endValue={valueVisualRange[1]} + /> + </ValueAxis> + <Series + type="line" + valueField="y" + argumentField="x" + /> + <ZoomAndPan + argumentAxis="both" + valueAxis="both" + /> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/datetime.jsx b/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/datetime.jsx new file mode 100644 index 0000000000..a0fffa87da --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/datetime.jsx @@ -0,0 +1,47 @@ +export default () => { + const [zoomAndPanOptions, setZoomAndPanOptions] = useState({ + zoomArgument: true, + panArgument: true, + zoomValue: false, + panValue: false, + }); + + const submit = useCallback(({ target }) => setZoomAndPanOptions(options => ({ + ...options, + [target.id]: target.checked, + })), []); + + const renderInput = useCallback((id, label) => { + const { [id]: checked } = zoomAndPanOptions; + return ( + <div className="custom-control custom-checkbox m-3"> + <input type="checkbox" className="custom-control-input" id={id} checked={checked} onChange={submit} /> + <label className="custom-control-label" htmlFor={id}>{label}</label> + </div> + ); + }, [zoomAndPanOptions, submit]); + + return ( + <React.Fragment> + <Chart + dataSource={chartData} + > + <Series + type="line" + valueField="y" + argumentField="x" + /> + <ZoomAndPan + argumentAxis={getMode(zoomArgument, panArgument)} + valueAxis={getMode(zoomValue, panValue)} + /> + </Chart> + <div style={inputsContainerStyle}> + {renderInput('zoomArgument', 'Zoom argument')} + {renderInput('panArgument', 'Pan argument')} + {renderInput('zoomValue', 'Zoom value')} + {renderInput('panValue', 'Pan value')} + </div> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/uncontrolled.jsx b/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/uncontrolled.jsx new file mode 100644 index 0000000000..fea1440439 --- /dev/null +++ b/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/uncontrolled.jsx @@ -0,0 +1,17 @@ +export default () => { + return ( + <React.Fragment> + <Chart dataSource={chartData}> + <Series + type="line" + valueField="y" + argumentField="x" + /> + <ZoomAndPan + argumentAxis="both" + valueAxis="none" + /> + </Chart> + </React.Fragment> + ); +} \ No newline at end of file diff --git a/packages/dx-react-chart-demos/src/index.jsx b/packages/dx-react-chart-demos/src/index.jsx index 20852d887c..5af2230779 100644 --- a/packages/dx-react-chart-demos/src/index.jsx +++ b/packages/dx-react-chart-demos/src/index.jsx @@ -2,7 +2,7 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { initialize } from '@devexpress/dx-demo-shell'; import '@devexpress/dx-demo-shell/dist/index.css'; -import { demos } from './demo-registry.js'; +import { demos, migrationSamples } from './demo-registry.js'; import { themes } from './theme-registry.js'; import { themeComponents } from './theme-components-registry.js'; import { demoData } from './demo-data-registry.js'; @@ -10,6 +10,7 @@ import './index.css'; initialize({ demoSources: demos, + migrationSamples, themeSources: themes, themeComponents, demoData, diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/basic.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/basic.jsx new file mode 100644 index 0000000000..121f294164 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/basic.jsx @@ -0,0 +1,41 @@ +import React, { useState } from 'react'; + +import { + DataGrid, + Column, +} from 'devextreme-react/data-grid'; + +import 'devextreme/dist/css/dx.light.css'; + +import { + generateRows, + globalSalesValues, +} from '../../../demo-data/generator'; + +export default () => { + const [columns] = useState([ + { name: 'region', title: 'Region' }, + { name: 'sector', title: 'Sector' }, + { name: 'customer', title: 'Customer' }, + { name: 'product', title: 'Product' }, + { name: 'amount', title: 'Sale Amount' }, + ]); + const [rows] = useState(generateRows({ columnValues: globalSalesValues, length: 8 })); + + return ( + <div className="card"> + <DataGrid dataSource={rows}> + { + columns.map((column) => ( + <Column + key={column.name} + dataField={column.name} + caption={column.title} + > + </Column> + )) + } + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/cell-wordwrap.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/cell-wordwrap.jsx new file mode 100644 index 0000000000..36b3fc0eed --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/cell-wordwrap.jsx @@ -0,0 +1,29 @@ +// In CSS, add the following style: +// +// .word-wrap { +// white-space: normal; +// } + +export default () => { + const [columns] = useState([ + { + dataField: "region", + caption: "Region", + cssClass: "word-wrap", + width: 100, + }, + { dataField: "sector", caption: "Sector" }, + { dataField: "customer", caption: "Customer" }, + { dataField: "product", caption: "Product" }, + { dataField: "amount", caption: "Sale Amount" }, + ]); + const [rows] = useState( + generateRows({ columnValues: globalSalesValues, length: 8 }) + ); + + return ( + <div className="card"> + <DataGrid dataSource={rows} columns={columns}></DataGrid> + </div> + ); + }; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/column-alignment.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/column-alignment.jsx new file mode 100644 index 0000000000..48cb5b42dc --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/column-alignment.jsx @@ -0,0 +1,19 @@ +export default () => { + const [columns] = useState([ + { dataField: "region", caption: "Region" }, + { dataField: "sector", caption: "Sector", alignment: "center" }, + { dataField: "customer", caption: "Customer", alignment: "center" }, + { dataField: "product", caption: "Product" }, + { dataField: "amount", caption: "Sale Amount", alignment: "right" }, + ]); + + const [rows] = useState( + generateRows({ columnValues: globalSalesValues, length: 8 }) + ); + + return ( + <div className="card"> + <DataGrid dataSource={rows} columns={columns}></DataGrid> + </div> + ); + }; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/static-column-width.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/static-column-width.jsx new file mode 100644 index 0000000000..3ae83521b7 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/static-column-width.jsx @@ -0,0 +1,19 @@ +export default () => { + const [columns] = useState([ + { dataField: "region", caption: "Region", width: "20%" }, + { dataField: "sector", caption: "Sector", width: "15%" }, + { dataField: "customer", caption: "Customer", width: "auto" }, + { dataField: "product", caption: "Product", width: "auto" }, + { dataField: "amount", caption: "Sale Amount", width: 140 }, + ]); + + const [rows] = useState( + generateRows({ columnValues: globalSalesValues, length: 8 }) + ); + + return ( + <div className="card"> + <DataGrid dataSource={rows} columns={columns}></DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-cell-template.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-cell-template.jsx new file mode 100644 index 0000000000..79c5ab6c91 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-cell-template.jsx @@ -0,0 +1,37 @@ +const HighlightedCell = (cellData) => ( + <div + style={{ + padding: "14px", + backgroundColor: cellData.value < 5000 ? "red" : undefined, + }} + > + <span + style={{ + color: cellData.value < 5000 ? "white" : undefined, + }} + > + {cellData.value} + </span> + </div> + ); + + export default () => { + return ( + <DataGrid + dataSource={rows} + > + { + columns.map(column => ( + <Column + key={column.name} + dataField={column.name} + caption={column.title} + cssClass={column.dataField === "amount" ? "highlightedCell" : ""} + cellRender={column.name === 'amount' ? HighlightedCell : undefined} + > + </Column> + )); + } + </DataGrid> + ); + }; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-header-content-template.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-header-content-template.jsx new file mode 100644 index 0000000000..9eac090ae2 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-header-content-template.jsx @@ -0,0 +1,46 @@ +import IconButton from "@mui/material/IconButton"; +import VisibilityOff from "@mui/icons-material/VisibilityOff"; +import { styled } from "@mui/material/styles"; + +const PREFIX = "Demo"; +const classes = { + button: `${PREFIX}-button`, +}; +const StyledIconButton = styled(IconButton)(({ theme }) => ({ + [`&.${classes.button}`]: { + margin: theme.spacing(0, 1), + }, +})); + +const CustomHeaderCell = ({ column }) => ( + <div> + <span>{column.name}</span> + <StyledIconButton + className={classes.button} + // eslint-disable-next-line no-alert + onClick={() => alert("Custom action")} + size="large" + > + <VisibilityOff /> + </StyledIconButton> + </div> +); + +export default () => { + return ( + <div className="card"> + <DataGrid dataSource={rows}> + {columns.map((column) => ( + <Column + dataField={column.name} + caption={column.title} + allowSorting={column.name === "region" ? false : true} + headerCellRender={ + column.name === "region" ? CustomHeaderCell : undefined + } + ></Column> + ))} + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-row-template.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-row-template.jsx new file mode 100644 index 0000000000..72ce259ebb --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-row-template.jsx @@ -0,0 +1,58 @@ +const styles = { + banking: { + backgroundColor: '#f5f5f5', + }, + health: { + backgroundColor: '#a2e2a4', + }, + telecom: { + backgroundColor: '#b3e5fc', + }, + energy: { + backgroundColor: '#ffcdd2', + }, + insurance: { + backgroundColor: '#f0f4c3', + }, + }; + + const getSectorData = (gridData: DataGridTypes.ColumnCellTemplateData) => gridData.data['sector']; + + + const TableRow = (rowData: DataGridTypes.RowTemplateData) => ( + <tr + role="row" + className="dx-row dx-data-row dx-row-lines" + onClick={() => alert(JSON.stringify(rowData.data))} + style={{ + cursor: "pointer", + ...styles[getSectorData(rowData)], + }} + > + <td role="gridcell">{rowData.data.region}</td> + <td role="gridcell">{rowData.data.sector}</td> + <td role="gridcell">{rowData.data.customer}</td> + <td role="gridcell">{rowData.data.product}</td> + <td role="gridcell">{rowData.data.amount}</td> + </tr> + ); + + export default () => { + return ( + <DataGrid + dataSource={rows} + > + { + columns.map(column => ( + <Column + key={column.name} + dataField={column.name} + caption={column.title} + dataRowRender={TableRow} + > + </Column> + )); + } + </DataGrid> + ); + }; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-template.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-template.jsx new file mode 100644 index 0000000000..cb7552f6aa --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-template.jsx @@ -0,0 +1,10 @@ +export default () => { + return ( + <DataGrid + rowAlternationEnabled={true} + dataSource={rows} + > + /* columns */ + </DataGrid> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/controlled.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/controlled.jsx new file mode 100644 index 0000000000..db0aa906de --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/controlled.jsx @@ -0,0 +1,43 @@ +export default () => { + const [columns] = useState([ + { name: 'name', title: 'Name' }, + { name: 'gender', title: 'Gender' }, + { name: 'city', title: 'City' }, + { name: 'car', title: 'Car' }, + ]); + + const [columnVisibility, setColumnVisibility] = useState({ + '0': true, + '1': false, + '2': true, + '3': false + }); + + const onVisibleChanged = useCallback((columnIndex) => (visibility) => { + setColumnVisibility({ + ...columnVisibility, + [columnIndex]: visibility + }); + }, [columnVisibility]); + + return ( + <div> + <DataGrid + dataSource={rows} + > + { + columns.map((column, idx) => ( + <Column + key={column.name} + dataField={column.name} + caption={column.title} + onVisibleChanged={onVisibleChanged(idx)} + visible={columnVisibility[idx]} + > + </Column> + )); + } + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/disable-toggling-column-visibility.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/disable-toggling-column-visibility.jsx new file mode 100644 index 0000000000..337088bf5d --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/disable-toggling-column-visibility.jsx @@ -0,0 +1,33 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <ColumnChooser + enabled={true} + mode="select" + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + defaultVisible={false} + /> + <Column + dataField={'city'} + caption={'City'} + allowHiding={false} + /> + <Column + dataField={'car'} + caption={'Car'} + defaultVisible={false} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/uncontrolled.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/uncontrolled.jsx new file mode 100644 index 0000000000..eec17e34ae --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/uncontrolled.jsx @@ -0,0 +1,32 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <ColumnChooser + enabled={true} + mode="select" + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + defaultVisible={false} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + defaultVisible={false} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-reordering/$migration/controlled.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-reordering/$migration/controlled.jsx new file mode 100644 index 0000000000..bb40c03344 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-reordering/$migration/controlled.jsx @@ -0,0 +1,44 @@ +export default () => { + const [columns] = useState([ + { name: 'name', title: 'Name' }, + { name: 'gender', title: 'Gender' }, + { name: 'city', title: 'City' }, + { name: 'car', title: 'Car' }, + ]); + + const [visibleIndexes, setVisibleIndexes] = useState({ + '2': 0, + '1': 1, + '3': 2, + '0': 3, + }); + + const onVisibleIndexChanged = useCallback((columnIndex) => (columnVisibleIndex) => { + setVisibleIndexes({ + ...visibleIndexes, + [columnIndex]: columnVisibleIndex + }) + }, [visibleIndexes]); + + return ( + <div> + <DataGrid + dataSource={rows} + allowColumnReordering={true} + > + { + columns.map((column, idx) => ( + <Column + key={column.name} + dataField={column.name} + caption={column.title} + visibleIndex={visibleIndexes[idx]} + onVisibleIndexChanged={onVisibleIndexChanged(idx)} + > + </Column> + )); + } + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-reordering/$migration/uncontrolled.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-reordering/$migration/uncontrolled.jsx new file mode 100644 index 0000000000..6b389a3232 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-reordering/$migration/uncontrolled.jsx @@ -0,0 +1,28 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + allowColumnReordering={true} + > + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + width={100} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + <Column + dataField={'name'} + caption={'Name'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/controlled.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/controlled.jsx new file mode 100644 index 0000000000..38b4b7cac1 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/controlled.jsx @@ -0,0 +1,44 @@ +export default () => { + const [columns] = useState([ + { name: 'name', title: 'Name' }, + { name: 'gender', title: 'Gender' }, + { name: 'city', title: 'City' }, + { name: 'car', title: 'Car' }, + ]); + + const [columnWidths, setColumnWidths] = useState({ + '0': 180, + '1': 180, + '2': 180, + '3': 240 + }); + + const onWidthChanged = useCallback((columnIndex) => (width) => { + setColumnWidths({ + ...columnWidths, + [columnIndex]: width + }) + }, [columnWidths]); + + return ( + <div> + <DataGrid + dataSource={rows} + allowColumnResizing={true} + > + { + columns.map((column, idx) => ( + <Column + key={column.name} + dataField={column.name} + caption={column.title} + onWidthChanged={onWidthChanged(idx)} + width={columnWidths[idx]} + > + </Column> + )); + } + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/resizing-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/resizing-mode.jsx new file mode 100644 index 0000000000..23576b59bb --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/resizing-mode.jsx @@ -0,0 +1,91 @@ +const ModeSelector = (props) => { + const { defaultValue, changeMode } = props; + return ( + <div> + {'Column Resizing Mode:'} +   + <select + defaultValue={defaultValue} + onChange={e => changeMode(e.target.value)} + className="dropdown" + style={{ + height: '2em', + }} + > + <option value="widget">Widget</option> + <option value="nextColumn">NextColumn</option> + </select> + </div> + ); + }; + + const ResetWidthButton = (props) => { + const { resetWidths } = props; + return ( + <button + type="button" + onClick={resetWidths} + className="btn btn-sm" + style={{ + paddingLeft: '8px', + paddingRight: '8px', + height: '2em', + width: 'auto', + fontSize: '1em', + }} + > + Reset widths to default + </button> + ); + }; + + export default () => { + const [defaultColumnWidths] = useState({ + '0': 180, + '1': 180, + '2': 180, + '3': 240 + }); + + const [columnWidths, setColumnWidths] = useState(defaultColumnWidths); + const [resizingMode, setResizingMode] = useState('widget'); + + const onWidthChanged = useCallback((columnIndex) => (width) => { + setColumnWidths({ + ...columnWidths, + [columnIndex]: width + }) + }, [columnWidths]); + + const resetColumnWidths = useCallback(() => { + setColumnWidths(defaultColumnWidths); + }, [defaultColumnWidths]); + + return ( + <div> + <ModeSelector + defaultValue={resizingMode} + changeMode={setResizingMode} + /> + <ResetWidthButton resetWidths={resetColumnWidths} /> + <DataGrid + dataSource={rows} + allowColumnResizing={true} + columnResizingMode={resizingMode} + > + { + columns.map((column, idx) => ( + <Column + key={column.name} + dataField={column.name} + caption={column.title} + onWidthChanged={onWidthChanged(idx)} + width={columnWidths[idx]} + > + </Column> + )); + } + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/uncontrolled.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/uncontrolled.jsx new file mode 100644 index 0000000000..e0fc2ae064 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/uncontrolled.jsx @@ -0,0 +1,31 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + allowColumnResizing={true} + > + <Column + dataField={'name'} + caption={'Name'} + defaultWidth={180} + /> + <Column + dataField={'gender'} + caption={'Gender'} + defaultWidth={180} + /> + <Column + dataField={'city'} + caption={'City'} + defaultWidth={180} + /> + <Column + dataField={'car'} + caption={'Car'} + defaultWidth={240} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-data-accessors/$migration/value-getters.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-data-accessors/$migration/value-getters.jsx new file mode 100644 index 0000000000..cf07956498 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-data-accessors/$migration/value-getters.jsx @@ -0,0 +1,46 @@ +import DataSource from 'devextreme/data/data_source'; +import ArrayStore from 'devextreme/data/array_store'; + +const dataSource = new DataSource({ + store: new ArrayStore({ + data: rows + }), + map: (dataItem) => ({ + firstName: dataItem.user?.firstName, + lastName: dataItem.user?.lastName, + car: dataItem.car?.model, + position: dataItem.position, + city: dataItem.city, + }) +}); + +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Column + dataField={'firstName'} + caption={'First Name'} + /> + <Column + dataField={'lastName'} + caption={'Last Name'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + <Column + dataField={'position'} + caption={'Position'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-data-accessors/$migration/value-setters.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-data-accessors/$migration/value-setters.jsx new file mode 100644 index 0000000000..ceb68db70f --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-data-accessors/$migration/value-setters.jsx @@ -0,0 +1,63 @@ +export default () => { + const calculateFirstName = useCallback(row => (row.user ? row.user.firstName : undefined), []); + const calculateLastName = useCallback(row => (row.user ? row.user.lastName : undefined), []); + const calculateCarModel = useCallback(row => (row.car ? row.car.model : undefined), []); + + const setFirstName = useCallback((newData, value, currentRowData) => { + newData.user = { + ...currentRowData.user, + firstName: value + }; + }, []); + const setLastName = useCallback((newData, value, currentRowData) => { + newData.user = { + ...currentRowData.user, + lastName: value + }; + }, []); + const setCarModel = useCallback((newData, value, currentRowData) => { + newData.car = { + model: value + }; + }, []); + + return ( + <div> + <DataGrid + dataSource={rows} + > + <Editing + allowAdding={true} + allowDeleting={true} + allowUpdating={true} + /> + <Column + name={'firstName'} + caption={'First Name'} + calculateCellValue={calculateFirstName} + setCellValue={setFirstName} + /> + <Column + name={'lastName'} + caption={'Last Name'} + calculateCellValue={calculateLastName} + setCellValue={setLastName} + /> + <Column + name={'car'} + caption={'Car'} + calculateCellValue={calculateCarModel} + setCellValue={setCarModel} + /> + <Column + name={'position'} + caption={'Position'} + /> + <Column + name={'city'} + caption={'City'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/editors.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/editors.jsx new file mode 100644 index 0000000000..c03ecfe0c2 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/editors.jsx @@ -0,0 +1,55 @@ +const booleanCellRender = ({ value }) => ( + <span className="badge badge-secondary"> + {value ? 'Yes' : 'No'} + </span> + ); + + const booleanEditCellRender = ({ value, setValue }) => ( + <select + className="form-control" + value={value} + onChange={e => setValue(e.target.value === 'true')} + > + <option value={false}> + No + </option> + <option value={true}> + Yes + </option> + </select> + ); + + export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Editing + allowAdding={true} + allowDeleting={true} + allowUpdating={true} + editRowKey={[0]} + /> + <Column + dataField={'customer'} + caption={'Customer'} + /> + <Column + dataField={'product'} + caption={'Product'} + /> + <Column + dataField={'units'} + caption={'Units'} + /> + <Column + dataField={'shipped'} + caption={'Shipped'} + cellRender={booleanCellRender} + editCellRender={booleanEditCellRender} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/formatters.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/formatters.jsx new file mode 100644 index 0000000000..78d5a6bcc3 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/formatters.jsx @@ -0,0 +1,38 @@ +const formatCurrency = (value) => value.toLocaleString('en-US', { style: 'currency', currency: 'USD' }); + +const renderSaleAmount = (data) => ( + <b style={{ color: 'darkblue' }}> + {formatCurrency(data.value)} + </b> +); + +const formatDate = (value) => value.replace(/(\d{4})-(\d{2})-(\d{2})/, '$3.$2.$1'); + +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Column + dataField={'customer'} + caption={'Customer'} + /> + <Column + dataField={'product'} + caption={'Product'} + /> + <Column + dataField={'saleDate'} + caption={'Sale Date'} + format={formatDate} + /> + <Column + dataField={'saleAmount'} + caption={'Sale Amount'} + cellRender={renderSaleAmount} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/tooltip.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/tooltip.jsx new file mode 100644 index 0000000000..90960d60af --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/tooltip.jsx @@ -0,0 +1,55 @@ +const tooltipCellRender = ({ + row: { data: { phone, birthDate } }, + value, + columnIndex, + rowIndex + }) => { + return ( + <div> + <span id={`${columnIndex}_${rowIndex}`}> + {value} + </span> + <Tooltip + target={`#${columnIndex}_${rowIndex}`} + showEvent="mouseenter" + hideEvent="mouseleave" + hideOnOutsideClick={false} + > + {`phone: ${phone}`} + <br /> + {`birth date: ${birthDate}`} + </Tooltip> + </div> + ); + }; + + export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Column + dataField={'firstName'} + caption={'First Name'} + cellRender={tooltipCellRender} + /> + <Column + dataField={'lastName'} + caption={'Last Name'} + cellRender={tooltipCellRender} + /> + <Column + dataField={'position'} + caption={'Position'} + cellRender={tooltipCellRender} + /> + <Column + dataField={'state'} + caption={'State'} + cellRender={tooltipCellRender} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-detail-row/$migration/simple-detail-row.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-detail-row/$migration/simple-detail-row.jsx new file mode 100644 index 0000000000..e2d31e238f --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-detail-row/$migration/simple-detail-row.jsx @@ -0,0 +1,52 @@ +const RowDetail = ({ data }) => ( + <div> + Details for + {' '} + {data.name} + {' '} + from + {' '} + {data.city} + </div> + ); + + export default () => { + const [defaultExpandedRows, setDefaultExpandedRows] = useState([2, 5]); + + const onContentReady = useCallback(e => { + if (defaultExpandedRows.length) { + defaultExpandedRows.forEach(key => e.component.expandRow(key)); + setDefaultExpandedRows([]); + } + }, [defaultExpandedRows]); + + return ( + <div> + <DataGrid + dataSource={rows} + onContentReady={onContentReady} + > + <MasterDetail + enabled={true} + render={RowDetail} + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/disable-column-editing.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/disable-column-editing.jsx new file mode 100644 index 0000000000..832d18e044 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/disable-column-editing.jsx @@ -0,0 +1,34 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Editing + allowUpdating={true} + allowAdding={true} + allowDeleting={true} + defaultEditRowKey={0} + mode="row" + /> + <Column + dataField={'name'} + caption={'Name'} + allowEditing={false} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/edit-row-controlled.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/edit-row-controlled.jsx new file mode 100644 index 0000000000..0c34dbd14e --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/edit-row-controlled.jsx @@ -0,0 +1,39 @@ +export default () => { + const [editRowKey, setEditRowKey] = useState(null); + const [editChanges, setEditChanges] = useState([]); + + return ( + <div> + <DataGrid + dataSource={rows} + > + <Editing + allowUpdating={true} + allowAdding={true} + allowDeleting={true} + changes={editChanges} + onChangesChanged={setEditChanges} + editRowKey={editRowKey} + onEditRowKeyChanged={setEditRowKey} + mode="row" + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/edit-row.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/edit-row.jsx new file mode 100644 index 0000000000..68b45402b9 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/edit-row.jsx @@ -0,0 +1,32 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Editing + allowUpdating={true} + allowAdding={true} + allowDeleting={true} + mode="row" + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/inline-cell-editing.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/inline-cell-editing.jsx new file mode 100644 index 0000000000..530d072b1a --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/inline-cell-editing.jsx @@ -0,0 +1,86 @@ +const StartEditActionSelector = (props) => { + const { defaultAction, changeAction } = props; + return ( + <div> + {'Start Edit Action:'} +   + <select + defaultValue={defaultAction} + onChange={e => changeAction(e.target.value)} + className="dropdown" + > + <option value="click">Click</option> + <option value="dblClick">Double Click</option> + </select> + </div> + ); + }; + + const SelectTextChecker = (props) => { + const { isSelectText, changeSelectText } = props; + return ( + <div + style={{ + padding: '0em 1em', + }} + > + <label htmlFor="selectTextChecker" className="form-check-label"> + <input + type="checkbox" + checked={isSelectText} + id="selectTextChecker" + name="selectTextChecker" + className="form-check-input" + onChange={e => changeSelectText(e.target.checked)} + /> + Select Text On Focus + </label> + </div> + ); + }; + + export default () => { + const [selectTextOnEditStart, setSelectTextOnEditStart] = useState(true); + const [startEditAction, setStartEditAction] = useState('click'); + + return ( + <div> + <SelectTextChecker + isSelectText={selectTextOnEditStart} + changeSelectText={setSelectTextOnEditStart} + /> + <StartEditActionSelector + defaultAction={startEditAction} + changeAction={setStartEditAction} + /> + <DataGrid + dataSource={rows} + > + <Editing + allowUpdating={true} + allowAdding={true} + allowDeleting={true} + startEditAction={startEditAction} + selectTextOnEditStart={selectTextOnEditStart} + mode="cell" + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/popup-editing.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/popup-editing.jsx new file mode 100644 index 0000000000..0b91b31106 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/popup-editing.jsx @@ -0,0 +1,56 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Editing + allowUpdating={true} + allowAdding={true} + allowDeleting={true} + mode="popup" + /> + <Popup title="Employee Details" showTitle={true} width={700} height={525} /> + <Form> + <GroupItem caption="Personal Data"> + <SimpleItem dataField="firstName" /> + <SimpleItem dataField="lastName" /> + <SimpleItem dataField="title" /> + <SimpleItem dataField="birthDate" editorType="dxDateBox" /> + </GroupItem> + <GroupItem caption="Business Info"> + <SimpleItem dataField="position" /> + <SimpleItem dataField="phone" editorType="dxTextBox" editorOptions={{ mode: 'tel' }} /> + </GroupItem> + </Form> + <Column + dataField={'firstName'} + caption={'First Name'} + /> + <Column + dataField={'lastName'} + caption={'Last Name'} + /> + <Column + dataField={'title'} + caption={'Title'} + visible={false} + /> + <Column + dataField={'birthDate'} + caption={'Birth Date'} + visible={false} + dataType="date" + /> + <Column + dataField={'position'} + caption={'Position'} + /> + <Column + dataField={'phone'} + caption={'Phone'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/validation-on-typing.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/validation-on-typing.jsx new file mode 100644 index 0000000000..506bcf67c4 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/validation-on-typing.jsx @@ -0,0 +1,36 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Editing + allowUpdating={true} + allowAdding={true} + allowDeleting={true} + mode="row" + /> + <Column + dataField={'firstName'} + caption={'First Name'} + > + <RequiredRule /> + </Column> + <Column + dataField={'lastName'} + caption={'Last Name'} + > + <RequiredRule /> + </Column> + <Column + dataField={'phone'} + caption={'Phone'} + /> + <Column + dataField={'state'} + caption={'State'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/advanced-customization.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/advanced-customization.jsx new file mode 100644 index 0000000000..002311354e --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/advanced-customization.jsx @@ -0,0 +1,122 @@ +/* usual imports */ +import { Workbook } from 'exceljs'; +import { saveAs } from 'file-saver-es'; +import { exportDataGrid } from 'devextreme/excel_exporter'; + +export default () => { + const onExporting = useCallback(e => { + const workbook = new Workbook(); + const worksheet = workbook.addWorksheet('Main sheet'); + + exportDataGrid({ + component: e.component, + worksheet, + autoFilterEnabled: true, + customizeCell: ({ gridCell, excelCell }) => { + if (gridCell.data.OrderDate < new Date(2014, 2, 3)) { + excelCell.font = { color: { argb: 'AAAAAA' } }; + } + if (gridCell.data.SaleAmount > 15000) { + if (gridCell.column.name === 'SaleAmount') { + excelCell.font = { color: { argb: '000000' } }; + excelCell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFBB00' } }; + } + } + if (gridCell.column.name === 'SaleAmount') { + excelCell.numFmt = '$0'; + } + if (!!gridCell.totalSummaryItemName) { + excelCell.font = { italic: true }; + } + } + }).then(() => { + /* Customize the Header */ + const generalStyles = { + font: { bold: true }, + fill: { + type: 'pattern', pattern: 'solid', fgColor: { argb: 'D3D3D3' }, bgColor: { argb: 'D3D3D3' }, + }, + alignment: { horizontal: 'left' }, + }; + for (let rowIndex = 1; rowIndex < 6; rowIndex += 1) { + worksheet.mergeCells(rowIndex, 1, rowIndex, 3); + worksheet.mergeCells(rowIndex, 4, rowIndex, 6); + Object.assign(worksheet.getRow(rowIndex).getCell(1), generalStyles); + Object.assign(worksheet.getRow(rowIndex).getCell(3), generalStyles); + } + worksheet.getRow(1).height = 20; + worksheet.getRow(1).getCell(1).font = { bold: true, size: 16 }; + worksheet.getRow(1).getCell(4).numFmt = 'd mmmm yyyy'; + worksheet.getRow(1).getCell(4).font = { bold: true, size: 16 }; + worksheet.getColumn(1).values = ['Sale Amounts:', 'Company Name:', 'Address:', 'Phone:', 'Website:']; + worksheet.getColumn(4).values = [new Date(), 'K&S Music', '1000 Nicllet Mall Minneapolis Minnesota', '(612) 304-6073', 'www.nowebsitemusic.com']; + worksheet.addRow({}); + + /* Customize the Footer */ + + const { lastRow } = worksheet; + let currentRowIndex = lastRow.number + 2; + for (let rowIndex = 0; rowIndex < 3; rowIndex += 1) { + worksheet.mergeCells(currentRowIndex + rowIndex, 1, currentRowIndex + rowIndex, 6); + Object.assign(worksheet.getRow(currentRowIndex + rowIndex).getCell(1), { font: { bold: true }, alignment: { horizontal: 'right' } }); + } + worksheet.getRow(currentRowIndex).getCell(1).value = 'If you have any questions, please contact John Smith.'; + currentRowIndex += 1; + worksheet.getRow(currentRowIndex).getCell(1).value = 'Phone: +111-111'; + currentRowIndex += 1; + worksheet.getRow(currentRowIndex).getCell(1).value = 'For demonstration purposes only'; + worksheet.getRow(currentRowIndex).getCell(1).font = { italic: true }; + + workbook.xlsx.writeBuffer().then((buffer) => { + saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx'); + }); + }); + }, []); + + return ( + <DataGrid + dataSource={orders} + keyExpr="ID" + width="100%" + showBorders={true} + onExporting={onExporting} + > + <Column + dataField="Employee" + caption="Employee" + /> + <Column + dataField="OrderNumber" + caption="Invoice Number" + /> + <Column + dataField="OrderDate" + caption="Order Date" + format="shortDate" + /> + <Column + dataField="CustomerStoreCity" + caption="City" + /> + <Column + dataField="CustomerStoreState" + caption="State" + /> + <Column + dataField="SaleAmount" + caption="Sale Amount" + /> + <Summary> + <TotalItem + column="OrderNumber" + summaryType="count" + /> + <TotalItem + column="SalesAmount" + summaryType="sum" + /> + </Summary> + <Export enabled={true} /> + </DataGrid> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/basic.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/basic.jsx new file mode 100644 index 0000000000..d60e9d4262 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/basic.jsx @@ -0,0 +1,48 @@ +/* usual imports */ +import { Workbook } from 'exceljs'; +import { saveAs } from 'file-saver-es'; +import { exportDataGrid } from 'devextreme/excel_exporter'; + + +const onExporting = e => { + const workbook = new Workbook(); + const worksheet = workbook.addWorksheet('Main sheet'); + + exportDataGrid({ + component: e.component, + worksheet, + autoFilterEnabled: true, + }).then(() => { + workbook.xlsx.writeBuffer().then((buffer) => { + saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx'); + }); + }); +}; + +export default () => ( + <DataGrid + dataSource={orders} + keyExpr="ID" + width="100%" + showBorders={true} + onExporting={onExporting} + > + <Column + dataField="Employee" + caption="Employee" + /> + <Column + dataField="OrderNumber" + caption="Invoice Number" + /> + <Column + dataField="CustomerStoreCity" + caption="City" + /> + <Column + dataField="SaleAmount" + caption="Sale Amount" + /> + <Export enabled={true} /> + </DataGrid> +); \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/supported-grid-features.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/supported-grid-features.jsx new file mode 100644 index 0000000000..40b82ddcef --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/supported-grid-features.jsx @@ -0,0 +1,100 @@ +/* usual imports */ +import { Workbook } from 'exceljs'; +import { saveAs } from 'file-saver-es'; +import { exportDataGrid } from 'devextreme/excel_exporter'; + +export default () => { + const onExporting = useCallback(e => { + const workbook = new Workbook(); + const worksheet = workbook.addWorksheet('Main sheet'); + + exportDataGrid({ + component: e.component, + worksheet, + autoFilterEnabled: true, + }).then(() => { + workbook.xlsx.writeBuffer().then((buffer) => { + saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx'); + }); + }); + }, []); + + const [defaultGroupsExpanded, setDefaultGroupsExpanded] = useState(false); + const [defaultSelection] = useState([14, 30, 38]); + + const onContentReady = useCallback(e => { + if(!defaultGroupsExpanded) { + e.component.expandRow(['Todd Hoffman']) + .then(() => e.component.expandRow(['Todd Hoffman', 'Denver'])) + .then(() => e.component.expandRow(['Todd Hoffman', 'Casper'])); + setDefaultGroupsExpanded(true); + } + }), [defaultGroupsExpanded]); + + return ( + <DataGrid + dataSource={orders} + keyExpr="ID" + width="100%" + showBorders={true} + onExporting={onExporting} + defaultSelectedRowKeys={defaultSelection} + onContentReady={onContentReady} + > + <Selection mode="multiple" /> + <GroupPanel visible={true} /> + <Grouping autoExpandAll={true} /> + + <Column + dataField="Employee" + caption="Employee" + groupIndex={0} + /> + <Column + dataField="OrderNumber" + caption="Invoice Number" + /> + <Column + dataField="OrderDate" + caption="Order Date" + format="shortDate" + /> + <Column + dataField="CustomerStoreCity" + caption="City" + groupIndex={1} + /> + <Column + dataField="CustomerStoreState" + caption="State" + /> + <Column + dataField="SaleAmount" + caption="Sale Amount" + /> + <Summary> + <TotalItem + column="OrderNumber" + summaryType="count" + /> + <TotalItem + column="SalesAmount" + summaryType="sum" + /> + <GroupItem + column="OrderNumber" + summaryType="count" + showInGroupFooter={true} + alignByColumn={true} + /> + <GroupItem + column="SalesAmount" + summaryType="max" + showInGroupFooter={true} + alignByColumn={true} + /> + </Summary> + <Export enabled={true} allowExportSelectedData={true} /> + </DataGrid> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/advanced-filter-row.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/advanced-filter-row.jsx new file mode 100644 index 0000000000..ccaa98e456 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/advanced-filter-row.jsx @@ -0,0 +1,69 @@ +const CurrencyEditor = ({ data: { value, setValue } } ) => { + const handleChange = (event) => { + const { value: targetValue } = event.target; + if (targetValue.trim() === '') { + setValue(); + return; + } + setValue(parseInt(targetValue, 10)); + }; + return ( + <input + className="form-control text-right" + type="number" + placeholder="Filter..." + value={value === undefined ? '' : value} + min={0} + onChange={handleChange} + /> + ); + }; + + export default () => { + const calculateFilterExpression = useCallback((filterValue, selectedFilterOperation) => { + if (!!filterValue && selectedFilterOperation === 'month') { + const selector = (data) => { + return parseInt(data.saleDate.split('-')[1], 10); + }; + + return [selector, "=", parseInt(filterValue, 10)]; + } + + if(!this.defaultCalculateFilterExpression) + return [this.dataField, 'contains', filterValue]; + + return this.defaultCalculateFilterExpression.apply(this, arguments); + }, []); + + return ( + <div> + <DataGrid + dataSource={rows} + > + <FilterRow + visible={true} + /> + <Column + dataField={'customer'} + caption={'Customer'} + /> + <Column + dataField={'product'} + caption={'Product'} + /> + <Column + dataField={'saleDate'} + caption={'Sale Date'} + filterOperations={['month', 'contains', 'startsWith', 'endsWith']} + calculateFilterExpression={calculateFilterExpression} + /> + <Column + dataField={'amount'} + caption={'Sale Amount'} + filterOperations={['=', '<>', '>', '>=', '<', '<=']} + editCellComponent={CurrencyEditor} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/controlled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/controlled-mode.jsx new file mode 100644 index 0000000000..cdd5027d3c --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/controlled-mode.jsx @@ -0,0 +1,30 @@ +export default () => { + const [filterValue, setFilterValue] = useState({ + ['car', '=', 'cruze'] + }); + + return ( + <div> + <DataGrid + dataSource={rows} + filterValue={filterValue} + onFilterValueChanged={setFilterValue} + > + <FilterRow + visible={true} + showOperationChooser={false} + /> + { + columns.map((column, idx) => ( + <Column + key={column.name} + dataField={column.name} + caption={column.title} + > + </Column> + )); + } + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/custom-filtering-algorithm.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/custom-filtering-algorithm.jsx new file mode 100644 index 0000000000..affe08f86e --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/custom-filtering-algorithm.jsx @@ -0,0 +1,42 @@ +const toLowerCase = value => String(value).toLowerCase(); + +export default () => { + const calculateFilterExpression = useCallback((filterValue) => { + const selector = (data) => { + return toLowerCase(data.city); + }; + + return [selector, "startswith", toLowerCase(filterValue)]; + }, []); + + return ( + <div> + <DataGrid + dataSource={rows} + > + <FilterRow + visible={true} + showOperationChooser={false} + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + defaultFilterValue={'Paris'} + calculateFilterExpression={calculateFilterExpression} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/disable-column-filtering.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/disable-column-filtering.jsx new file mode 100644 index 0000000000..602b05e9ea --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/disable-column-filtering.jsx @@ -0,0 +1,33 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <FilterRow + visible={true} + showOperationChooser={false} + /> + <Column + dataField={'name'} + caption={'Name'} + allowFiltering={false} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + allowFiltering={false} + defaultFilterValue={'cruze'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/filter-row.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/filter-row.jsx new file mode 100644 index 0000000000..ee73af2530 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/filter-row.jsx @@ -0,0 +1,30 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <FilterRow + visible={true} + showOperationChooser={false} + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/remote-filtering.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/remote-filtering.jsx new file mode 100644 index 0000000000..142ec80857 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/remote-filtering.jsx @@ -0,0 +1,73 @@ +function isNotEmpty(value: string | undefined | null) { + return value !== undefined && value !== null && value !== ''; + } + + const store = new CustomStore({ + key: 'OrderNumber', + async load(loadOptions) { + const paramNames = [ + 'skip', 'take', 'requireTotalCount', 'requireGroupCount', + 'sort', 'filter', 'totalSummary', 'group', 'groupSummary', + ]; + + const queryString = paramNames + .filter((paramName) => isNotEmpty(loadOptions[paramName])) + .map((paramName) => `${paramName}=${JSON.stringify(loadOptions[paramName])}`) + .join('&'); + + try { + const response = await fetch(`https://js.devexpress.com/Demos/WidgetsGalleryDataService/api/orders?${queryString}`); + + const result = await response.json(); + + return { + data: result.data, + totalCount: result.totalCount, + summary: result.summary, + groupCount: result.groupCount, + }; + } catch (err) { + throw new Error('Data Loading Error'); + } + }, + }); + + const remoteOperations = { filtering: true } + + const App = () => ( + <DataGrid + dataSource={store} + showBorders={true} + remoteOperations={remoteOperations} + > + <Column + dataField="OrderNumber" + dataType="number" + /> + <Column + dataField="OrderDate" + dataType="date" + /> + <Column + dataField="StoreCity" + dataType="string" + /> + <Column + dataField="StoreState" + dataType="string" + /> + <Column + dataField="Employee" + dataType="string" + /> + <Column + dataField="SaleAmount" + dataType="number" + format="currency" + /> + <FilterRow visible={true} /> + <HeaderFilter visible={true} /> + </DataGrid> +); + +export default App; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-fixed-columns/$migration/basic.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-fixed-columns/$migration/basic.jsx new file mode 100644 index 0000000000..33c3f54eae --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-fixed-columns/$migration/basic.jsx @@ -0,0 +1,55 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Column + dataField={'region'} + caption={'Region'} + fixed={true} + width={150} + /> + <Column + dataField={'sector'} + caption={'Sector'} + width={180} + /> + <Column + dataField={'channel'} + caption={'Channel'} + fixed={true} + width={120} + /> + <Column + dataField={'customer'} + caption={'Customer'} + width={230} + /> + <Column + dataField={'product'} + caption={'Product'} + width={230} + /> + <Column + dataField={'saleDate'} + caption={'Sale Date'} + width={130} + /> + <Column + dataField={'units'} + caption={'Units'} + width={80} + /> + <Column + dataField={'amount'} + caption={'Sale Amount'} + alignment={'right'} + fixed={true} + fixedPosition={'right'} + width={140} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/controlled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/controlled-mode.jsx new file mode 100644 index 0000000000..16c3d3a7d0 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/controlled-mode.jsx @@ -0,0 +1,35 @@ +export default () => { + const [groupIndexes, setGroupIndexes] = useState({ + '2': 0 + }); + + const onGroupIndexChanged = useCallback((columnIndex) => (groupIndex) => { + setGroupIndexes({ + ...groupIndexes, + [columnIndex]: groupIndex, + }); + }, [groupIndexes]); + + return ( + <div> + <DataGrid + dataSource={rows} + > + <GroupPanel visible={true} /> + <Grouping contextMenuEnabled={true} /> + { + columns.map((column, idx) => ( + <Column + key={column.name} + dataField={column.name} + caption={column.title} + groupIndex={groupIndexes[idx]} + onGroupIndexChanged={onGroupIndexChanged(idx)} + > + </Column> + )); + } + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom-advanced.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom-advanced.jsx new file mode 100644 index 0000000000..538815ff4d --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom-advanced.jsx @@ -0,0 +1,55 @@ +const groupCellRender = ({ value }) => ( + <span> + from + {' '} + {value.from} + {' '} + to + {' '} + {value.to} + </apsn> + ); + + const nameGroupCriteria = rowData => { + const firstLetter = String(rowData.name).substr(0, 1).toLowerCase(); + const groupValue = firstLetter < 'n' + ? { from: 'A', to: 'M' } + : { from: 'N', to: 'Z' }; + return { + value: groupValue, + key: `${groupValue.from}-${groupValue.to}`, + }; + }; + + export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Grouping contextMenuEnabled={true} /> + <GroupPanel visible={true} /> + <Column + dataField={'name'} + caption={'Name'} + defaultGroupIndex={0} + calculateGroupValue={nameGroupCriteria} + showWhenGrouped={true} + groupCellRender={groupCellRender} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom-grouping-static.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom-grouping-static.jsx new file mode 100644 index 0000000000..82ee06404b --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom-grouping-static.jsx @@ -0,0 +1,51 @@ +import DataSource from 'devextreme/data/data_source'; +import ArrayStore from 'devextreme/data/array_store'; + +const dataSource = new DataSource({ + store: new ArrayStore({ + data + }), + postProcess: (hierarchicalData) => { + const flatData = hierarchicalData.reduce((acc, value) => { + const items = value.items.map((item) => ({ + ...item, + 'gender': value.key, + })); + + return [ + ...acc, + ...items, + ]; + }, []); + + return flatData; + } +}); + +export default () => { + return ( + <div> + <DataGrid + dataSource={dataSource} + > + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + groupIndex={0} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom.jsx new file mode 100644 index 0000000000..acbbd0d1a9 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom.jsx @@ -0,0 +1,50 @@ +const groupCellRender = ({ column, value }) => ( + <span> + Group + {' '} + <i> + {column.caption} + </i> + {' '} + by first letter: + {' '} + <strong> + {value} + </strong> + </span> + ); + + const cityGroupCriteria = rowData => rowData.city.substr(0, 1); + + export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Grouping contextMenuEnabled={true} /> + <GroupPanel visible={true} /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + groupIndex={0} + calculateGroupValue={cityGroupCriteria} + showWhenGrouped={true} + groupCellRender={groupCellRender} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/disable-column-grouping.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/disable-column-grouping.jsx new file mode 100644 index 0000000000..9d6e481640 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/disable-column-grouping.jsx @@ -0,0 +1,31 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Grouping contextMenuEnabled={true} /> + <GroupPanel visible={true} /> + <Column + dataField={'name'} + caption={'Name'} + allowGrouping={false} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + allowGrouping={false} + groupIndex={0} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/grouping-with-ui.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/grouping-with-ui.jsx new file mode 100644 index 0000000000..327713c69f --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/grouping-with-ui.jsx @@ -0,0 +1,29 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Grouping contextMenuEnabled={true} /> + <GroupPanel visible={true} /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + groupIndex={0} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/remote-grouping-with-local-expanding.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/remote-grouping-with-local-expanding.jsx new file mode 100644 index 0000000000..3f815e2ee2 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/remote-grouping-with-local-expanding.jsx @@ -0,0 +1,74 @@ +function isNotEmpty(value: string | undefined | null) { + return value !== undefined && value !== null && value !== ''; + } + + const store = new CustomStore({ + key: 'OrderNumber', + async load(loadOptions) { + const paramNames = [ + 'skip', 'take', 'requireTotalCount', 'requireGroupCount', + 'sort', 'filter', 'totalSummary', 'group', 'groupSummary', + ]; + + const queryString = paramNames + .filter((paramName) => isNotEmpty(loadOptions[paramName])) + .map((paramName) => `${paramName}=${JSON.stringify(loadOptions[paramName])}`) + .join('&'); + + try { + const response = await fetch(`https://js.devexpress.com/Demos/WidgetsGalleryDataService/api/orders?${queryString}`); + + const result = await response.json(); + + return { + data: result.data, + totalCount: result.totalCount, + summary: result.summary, + groupCount: result.groupCount, + }; + } catch (err) { + throw new Error('Data Loading Error'); + } + }, + }); + + const remoteOperations = { grouping: true } + + + const App = () => ( + <DataGrid + dataSource={store} + showBorders={true} + remoteOperations={remoteOperations} + > + <Column + dataField="OrderNumber" + dataType="number" + /> + <Column + dataField="OrderDate" + dataType="date" + /> + <Column + dataField="StoreCity" + dataType="string" + /> + <Column + dataField="StoreState" + defaultGroupIndex={0} + dataType="string" + /> + <Column + dataField="Employee" + dataType="string" + /> + <Column + dataField="SaleAmount" + dataType="number" + format="currency" + /> + <GroupPanel visible={true} /> + </DataGrid> +); + +export default App; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/static.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/static.jsx new file mode 100644 index 0000000000..50ebb9b695 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/static.jsx @@ -0,0 +1,27 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + groupIndex={0} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/controlled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/controlled-mode.jsx new file mode 100644 index 0000000000..1cc9a9eb1b --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/controlled-mode.jsx @@ -0,0 +1,33 @@ +export default () => { + const [focusedRowIndex, setFocusedRowIndex] = useState(-1); + const [focusedColumnIndex, setFocusedColumnIndex] = useState(-1); + + return ( + <div> + <DataGrid + dataSource={rows} + focusedRowIndex={focusedRowIndex} + onFocusedRowIndexChanged={setFocusedRowIndex} + focusedColumnIndex={focusedColumnIndex} + onFocusedColumnIndexChanged={setFocusedColumnIndex} + > + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/focus-row.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/focus-row.jsx new file mode 100644 index 0000000000..df878cbeeb --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/focus-row.jsx @@ -0,0 +1,27 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + focusedRowEnabled={true} + > + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/uncontrolled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/uncontrolled-mode.jsx new file mode 100644 index 0000000000..373e917428 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/uncontrolled-mode.jsx @@ -0,0 +1,59 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + allowColumnReordering={true} + defaultFocusedRowIndex={1} + defaultFocusedColumnIndex={1} + > + <Editing + allowUpdating={true} + allowAdding={true} + allowDeleting={true} + mode="row" + /> + <ColumnChooser + enabled={true} + mode="select" + /> + <SearchPanel + visible={true} + /> + <Paging + defaultPageIndex={0} + pageSize={5} + /> + <Pager + visible={true} + /> + <FilterRow + visible={true} + showOperationChooser={false} + /> + <Column + dataField={'name'} + caption={'Name'} + defaultVisibleIndex={3} + /> + <Column + dataField={'gender'} + caption={'Gender'} + defaultVisibleIndex={1} + defaultVisible={false} + /> + <Column + dataField={'city'} + caption={'City'} + defaultVisibleIndex={0} + /> + <Column + dataField={'car'} + caption={'Car'} + defaultVisibleIndex={2} + defaultVisible={false} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-lazy-loading/$migration/infinite-scrolling.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-lazy-loading/$migration/infinite-scrolling.jsx new file mode 100644 index 0000000000..6cb7bb7a31 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-lazy-loading/$migration/infinite-scrolling.jsx @@ -0,0 +1,27 @@ +const VIRTUAL_PAGE_SIZE = 50; + +export default () => { + const [columns] = useState([ + { dataField: 'Id', caption: 'ID', width: 80 }, + { dataField: 'ProductCategoryName', caption: 'Category', width: 220 }, + { dataField: 'StoreName', caption: 'Store', width: 220 }, + { dataField: 'ProductName', caption: 'Product' }, + { dataField: 'SalesAmount', caption: 'Amount', width: 120 } + ]); + + return ( + <div> + <DataGrid + dataSource={rows} + columns={columns} + height={440} + > + <Paging pageSize={VIRTUAL_PAGE_SIZE} /> + <Scrolling + mode="infinite" + preloadEnabled={true} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-lazy-loading/$migration/remote-data-basic.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-lazy-loading/$migration/remote-data-basic.jsx new file mode 100644 index 0000000000..910792ce9a --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-lazy-loading/$migration/remote-data-basic.jsx @@ -0,0 +1,27 @@ +const VIRTUAL_PAGE_SIZE = 100; + +export default () => { + const [columns] = useState([ + { dataField: 'Id', caption: 'ID', width: 80 }, + { dataField: 'ProductCategoryName', caption: 'Category', width: 220 }, + { dataField: 'StoreName', caption: 'Store', width: 220 }, + { dataField: 'ProductName', caption: 'Product' }, + { dataField: 'SalesAmount', caption: 'Amount', width: 120 } + ]); + + return ( + <div> + <DataGrid + dataSource={rows} + columns={columns} + height={440} + > + <Paging pageSize={VIRTUAL_PAGE_SIZE} /> + <Scrolling + mode="virtual" + preloadEnabled={true} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-localization/$migration/basic.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-localization/$migration/basic.jsx new file mode 100644 index 0000000000..a723b5413a --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-localization/$migration/basic.jsx @@ -0,0 +1,13 @@ +import deMessages from "devextreme/localization/messages/de.json"; +import { locale, loadMessages } from "devextreme/localization"; + +loadMessages(deMessages); +locale(navigator.language); + +export default () => ( + <DataGrid + dataSource={rows} + > + {/* ... */} + </DataGrid> +); \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/controlled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/controlled-mode.jsx new file mode 100644 index 0000000000..d941c12d8d --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/controlled-mode.jsx @@ -0,0 +1,40 @@ +export default () => { + const [pageSizes] = useState([5, 10, 15]); + const [pageIndex, setPageIndex] = useState(0); + const [pageSize, setPageSize] = useState(5); + + return ( + <div> + <DataGrid + dataSource={rows} + > + <Paging + pageIndex={pageIndex} + onPageIndexChanged={setPageIndex} + pageSize={pageSize} + onPageSizeChanged={setPageSize} + /> + <Pager + allowedPageSizes={pageSizes} + visible={true} + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/page-size-selector.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/page-size-selector.jsx new file mode 100644 index 0000000000..b247a3d9f7 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/page-size-selector.jsx @@ -0,0 +1,36 @@ +export default () => { + const [pageSizes] = useState([5, 10, 15, 'all']); + + return ( + <div> + <DataGrid + dataSource={rows} + > + <Paging + defaultPageIndex={0} + defaultPageSize={5} + /> + <Pager + allowedPageSizes={pageSizes} + visible={true} + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/remote-paging.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/remote-paging.jsx new file mode 100644 index 0000000000..f17c88549f --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/remote-paging.jsx @@ -0,0 +1,78 @@ +function isNotEmpty(value: string | undefined | null) { + return value !== undefined && value !== null && value !== ''; + } + + const store = new CustomStore({ + key: 'OrderNumber', + async load(loadOptions) { + const paramNames = [ + 'skip', 'take', 'requireTotalCount', 'requireGroupCount', + 'sort', 'filter', 'totalSummary', 'group', 'groupSummary', + ]; + + const queryString = paramNames + .filter((paramName) => isNotEmpty(loadOptions[paramName])) + .map((paramName) => `${paramName}=${JSON.stringify(loadOptions[paramName])}`) + .join('&'); + + try { + const response = await fetch(`https://js.devexpress.com/Demos/WidgetsGalleryDataService/api/orders?${queryString}`); + + const result = await response.json(); + + return { + data: result.data, + totalCount: result.totalCount, + summary: result.summary, + groupCount: result.groupCount, + }; + } catch (err) { + throw new Error('Data Loading Error'); + } + }, + }); + + const remoteOperations = { paging: true } + const allowedPageSizes = [8, 12, 20]; + + const App = () => ( + <DataGrid + dataSource={store} + showBorders={true} + remoteOperations={remoteOperations} + > + <Column + dataField="OrderNumber" + dataType="number" + /> + <Column + dataField="OrderDate" + dataType="date" + /> + <Column + dataField="StoreCity" + dataType="string" + /> + <Column + dataField="StoreState" + dataType="string" + /> + <Column + dataField="Employee" + dataType="string" + /> + <Column + dataField="SaleAmount" + dataType="number" + format="currency" + /> + <Paging defaultPageSize={12} /> + <Pager + visible + showPageSizeSelector + allowedPageSizes={allowedPageSizes} + /> + </DataGrid> +); + +export default App; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/uncontrolled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/uncontrolled-mode.jsx new file mode 100644 index 0000000000..91746839cb --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/uncontrolled-mode.jsx @@ -0,0 +1,31 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Paging + defaultPageIndex={0} + pageSize={5} + /> + <Pager visible={true} /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/controlled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/controlled-mode.jsx new file mode 100644 index 0000000000..8cd938df80 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/controlled-mode.jsx @@ -0,0 +1,33 @@ +export default () => { + const [searchPanelText, setSearchPanelText] = useState('Female'); + + return ( + <div> + <DataGrid + dataSource={rows} + > + <SearchPanel + visible={true} + text={searchPanelText} + onTextChanged={setSearchPanelText} + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/remote-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/remote-mode.jsx new file mode 100644 index 0000000000..e976b09abd --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/remote-mode.jsx @@ -0,0 +1,72 @@ +function isNotEmpty(value: string | undefined | null) { + return value !== undefined && value !== null && value !== ''; + } + + const store = new CustomStore({ + key: 'OrderNumber', + async load(loadOptions) { + const paramNames = [ + 'skip', 'take', 'requireTotalCount', 'requireGroupCount', + 'sort', 'filter', 'totalSummary', 'group', 'groupSummary', + ]; + + const queryString = paramNames + .filter((paramName) => isNotEmpty(loadOptions[paramName])) + .map((paramName) => `${paramName}=${JSON.stringify(loadOptions[paramName])}`) + .join('&'); + + try { + const response = await fetch(`https://js.devexpress.com/Demos/WidgetsGalleryDataService/api/orders?${queryString}`); + + const result = await response.json(); + + return { + data: result.data, + totalCount: result.totalCount, + summary: result.summary, + groupCount: result.groupCount, + }; + } catch (err) { + throw new Error('Data Loading Error'); + } + }, + }); + + const remoteOperations = { filtering: true } + + const App = () => ( + <DataGrid + dataSource={store} + showBorders={true} + remoteOperations={remoteOperations} + > + <Column + dataField="OrderNumber" + dataType="number" + /> + <Column + dataField="OrderDate" + dataType="date" + /> + <Column + dataField="StoreCity" + dataType="string" + /> + <Column + dataField="StoreState" + dataType="string" + /> + <Column + dataField="Employee" + dataType="string" + /> + <Column + dataField="SaleAmount" + dataType="number" + format="currency" + /> + <SearchPanel visible /> + </DataGrid> +); + +export default App; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/uncontrolled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/uncontrolled-mode.jsx new file mode 100644 index 0000000000..fd9f86eb88 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/uncontrolled-mode.jsx @@ -0,0 +1,30 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <SearchPanel + visible={true} + defaultText={'Paris'} + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/visible-columns-searching.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/visible-columns-searching.jsx new file mode 100644 index 0000000000..66a837b1fd --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/visible-columns-searching.jsx @@ -0,0 +1,31 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <SearchPanel + visible={true} + defaultText={'Audi A4'} + searchVisibleColumnsOnly={true} + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/basic.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/basic.jsx new file mode 100644 index 0000000000..4cf89761a7 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/basic.jsx @@ -0,0 +1,37 @@ +export default () => { + const [selectedRows, setSelectedRows] = useState([1]); + const onSelectionChanged = useCallback((e) => { + setSelectedRows(e.selectedRowKeys); + }, []); + + return ( + <div> + <DataGrid + dataSource={rows} + selectedRowKeys={selectedRows} + onSelectionChanged={onSelectionChanged} + > + <Selection + mode={'multiple'} + allowSelectAll={false} + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/hidden-checkboxes.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/hidden-checkboxes.jsx new file mode 100644 index 0000000000..7e6bb04abb --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/hidden-checkboxes.jsx @@ -0,0 +1,38 @@ +export default () => { + const [selectedRows, setSelectedRows] = useState([1]); + const onSelectionChanged = useCallback((e) => { + setSelectedRows(e.selectedRowKeys); + }, []); + + return ( + <div> + <DataGrid + dataSource={rows} + selectedRowKeys={selectedRows} + onSelectionChanged={onSelectionChanged} + > + <Selection + mode={'multiple'} + showCheckBoxesMode={'none'} + allowSelectAll={false} + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-by-all-pages.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-by-all-pages.jsx new file mode 100644 index 0000000000..9a44f14b44 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-by-all-pages.jsx @@ -0,0 +1,47 @@ +export default () => { + const [selectedRows, setSelectedRows] = useState([1]); + const onSelectionChanged = useCallback((e) => { + setSelectedRows(e.selectedRowKeys); + }, []); + + return ( + <div> + <div> + Total rows selected: + {' '} + {selectedRows.length} + </div> + <DataGrid + dataSource={rows} + selectedRowKeys={selectedRows} + onSelectionChanged={onSelectionChanged} + > + <Selection + mode={'multiple'} + selectAllMode={'allPages'} + /> + <Paging + defaultPageIndex={0} + pageSize={6} + /> + <Pager visible={true} /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-by-page.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-by-page.jsx new file mode 100644 index 0000000000..1eb8eeb5e3 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-by-page.jsx @@ -0,0 +1,47 @@ +export default () => { + const [selectedRows, setSelectedRows] = useState([1]); + const onSelectionChanged = useCallback((e) => { + setSelectedRows(e.selectedRowKeys); + }, []); + + return ( + <div> + <div> + Total rows selected: + {' '} + {selectedRows.length} + </div> + <DataGrid + dataSource={rows} + selectedRowKeys={selectedRows} + onSelectionChanged={onSelectionChanged} + > + <Selection + mode={'multiple'} + selectAllMode={'page'} + /> + <Paging + defaultPageIndex={0} + pageSize={6} + /> + <Pager visible={true} /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-virtual.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-virtual.jsx new file mode 100644 index 0000000000..487e094618 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-virtual.jsx @@ -0,0 +1,40 @@ +export default () => { + const [selectedRows, setSelectedRows] = useState([1]); + const onSelectionChanged = useCallback((e) => { + setSelectedRows(e.selectedRowKeys); + }, []); + + return ( + <div> + <div> + Total rows selected: + {' '} + {selectedRows.length} + </div> + <DataGrid + dataSource={rows} + selectedRowKeys={selectedRows} + onSelectionChanged={onSelectionChanged} + > + <Selection mode={'multiple'} /> + <Scrolling mode={'virtual'} /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-by-row-click.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-by-row-click.jsx new file mode 100644 index 0000000000..de8cbae074 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-by-row-click.jsx @@ -0,0 +1,38 @@ +export default () => { + const [selectedRows, setSelectedRows] = useState([1]); + const onSelectionChanged = useCallback((e) => { + setSelectedRows(e.selectedRowKeys); + }, []); + + return ( + <div> + <DataGrid + dataSource={rows} + selectedRowKeys={selectedRows} + onSelectionChanged={onSelectionChanged} + > + <Selection + mode={'multiple'} + showCheckBoxesMode={'onClick'} + allowSelectAll={false} + /> + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/controlled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/controlled-mode.jsx new file mode 100644 index 0000000000..2cfa033284 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/controlled-mode.jsx @@ -0,0 +1,32 @@ +export default () => { + const [sorting, setSorting] = useState({ + '2': 'asc' + }); + + const onSortOrderChanged = useCallback((columnIndex) => (columnSorting) => { + setSorting({ + ...sorting, + [columnIndex]: columnSorting, + }) + }, [sorting]); + + return ( + <DataGrid + dataSource={rows} + > + { + columns.map((column, idx) => ( + <Column + key={column.name} + dataField={column.name} + caption={column.title} + allowSorting={true} + onSortOrderChanged={onSortOrderChanged(idx)} + sortOrder={sorting[idx]} + > + </Column> + )); + } + </DataGrid> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/custom-sort-label.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/custom-sort-label.jsx new file mode 100644 index 0000000000..7b40740eb2 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/custom-sort-label.jsx @@ -0,0 +1,65 @@ +const SortingIcon = ({ sortOrder }) => ( + <span + className={`oi oi-arrow-thick-${sortOrder === 'asc' ? 'top' : 'bottom'}`} + style={{ fontSize: '12px', paddingLeft: '5px' }} + /> + ); + + const SortLabel = ({ toggleSort, text, sortOrder }) => ( + <button + type="button" + className="btn btn-light btn-sm" + onClick={toggleSort} + > + {text} + {(sortOrder && <SortingIcon sortOrder={sortOrder} />)} + </button> + ); + + export default () => { + const renderHeaderCell = useCallback(({ column, columnIndex, component }) => { + const sortOrder = component.columnOption(column.name, "sortOrder"); + + const toggleSort = useCallback(() => { + component.columnOption(column.name, "sortOrder", sortOrder === 'asc' ? 'desc' : 'asc'); + }, [sortOrder, component, column]); + + return ( + <SortLabel + toggleSort={toggleSort} + text={column.caption} + sortOrder={sortOrder} + />; + ), []) + }; + + return ( + <div> + <DataGrid + dataSource={rows} + > + <Column + dataField={'name'} + caption={'Name'} + headerCellRender={renderHeaderCell} + /> + <Column + dataField={'gender'} + caption={'Gender'} + headerCellRender={renderHeaderCell} + /> + <Column + dataField={'city'} + caption={'City'} + defaultSortOrder={'asc'} + headerCellRender={renderHeaderCell} + /> + <Column + dataField={'car'} + caption={'Car'} + headerCellRender={renderHeaderCell} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/custom-sorting.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/custom-sorting.jsx new file mode 100644 index 0000000000..336d09856e --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/custom-sorting.jsx @@ -0,0 +1,43 @@ +export default () => { + const priorityWeights = useMemo(() => ({ + Low: 0, + Normal: 1, + High: 2, + }), []); + + const comparePriority = useCallback((a, b) => { + const priorityA = priorityWeights[a]; + const priorityB = priorityWeights[b]; + if (priorityA === priorityB) { + return 0; + } + return (priorityA < priorityB) ? -1 : 1; + }, [priorityWeights]); + + return ( + <div> + <DataGrid + dataSource={rows} + > + <Column + dataField={'subject'} + caption={'Subject'} + width={300} + /> + <Column + dataField={'startDate'} + caption={'Start Date'} + /> + <Column + dataField={'dueDate'} + caption={'Due Date'} + /> + <Column + dataField={'priority'} + caption={'Priority'} + sortingMethod={comparePriority} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/disable-column-sorting.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/disable-column-sorting.jsx new file mode 100644 index 0000000000..a8ed373cb9 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/disable-column-sorting.jsx @@ -0,0 +1,28 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Column + dataField={'name'} + caption={'Name'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + defaultSortOrder={'desc'} + allowSorting={false} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/group-sorting.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/group-sorting.jsx new file mode 100644 index 0000000000..ad1b596632 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/group-sorting.jsx @@ -0,0 +1,31 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Grouping contextMenuEnabled={true} /> + <GroupPanel visible={true} /> + <Column + dataField={'name'} + caption={'Name'} + defaultSortOrder={'desc'} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + defaultSortOrder={'asc'} + defaultGroupIndex={0} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/header-sorting.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/header-sorting.jsx new file mode 100644 index 0000000000..67c1756881 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/header-sorting.jsx @@ -0,0 +1,21 @@ +export default () => { + return ( + <DataGrid + dataSource={rows} + > + { + columns.map(column => ( + <Column + key={column.name} + dataField={column.name} + caption={column.title} + allowSorting={true} + defaultSortOrder={column.name === 'city' ? 'asc' : undefined} + > + </Column> + )); + } + </DataGrid> + ); +}; + \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/remote-sorting.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/remote-sorting.jsx new file mode 100644 index 0000000000..3f5a7516b4 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/remote-sorting.jsx @@ -0,0 +1,78 @@ +function isNotEmpty(value: string | undefined | null) { + return value !== undefined && value !== null && value !== ''; + } + + const store = new CustomStore({ + key: 'OrderNumber', + async load(loadOptions) { + const paramNames = [ + 'skip', 'take', 'requireTotalCount', 'requireGroupCount', + 'sort', 'filter', 'totalSummary', 'group', 'groupSummary', + ]; + + const queryString = paramNames + .filter((paramName) => isNotEmpty(loadOptions[paramName])) + .map((paramName) => `${paramName}=${JSON.stringify(loadOptions[paramName])}`) + .join('&'); + + try { + const response = await fetch(`https://js.devexpress.com/Demos/WidgetsGalleryDataService/api/orders?${queryString}`); + + const result = await response.json(); + + return { + data: result.data, + totalCount: result.totalCount, + summary: result.summary, + groupCount: result.groupCount, + }; + } catch (err) { + throw new Error('Data Loading Error'); + } + }, + }); + + const remoteOperations = { sorting: true } + + const App = () => ( + <DataGrid + dataSource={store} + showBorders={true} + remoteOperations={remoteOperations} + > + <Column + dataField="OrderNumber" + dataType="number" + /> + <Column + dataField="OrderDate" + dataType="date" + /> + <Column + dataField="StoreCity" + defaultSortOrder={'asc'} + defaultGroupIndex={0} + dataType="string" + /> + <Column + dataField="StoreState" + dataType="string" + /> + <Column + dataField="Employee" + dataType="string" + /> + <Column + dataField="SaleAmount" + dataType="number" + format="currency" + /> + <Paging defaultPageSize={12} /> + <Pager + visible + showPageSizeSelector={true} + /> + </DataGrid> +); + +export default App; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/custom-algorithm.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/custom-algorithm.jsx new file mode 100644 index 0000000000..df9423cbf6 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/custom-algorithm.jsx @@ -0,0 +1,70 @@ +export default () => { + const calculateCustomSummary = useCallback(options => { + if(options.name == 'SalesMedianSummary') { + switch(options.summaryProcess) { + case 'start': + options.totalValue = []; + break; + case 'calculate': + options.totalValue.push(options.value); + break; + case 'finalize': + if (!options.totalValue.length) { + options.totalValue = 0; + break; + } + const sortedValues = options.totalValue.sort((a, b) => a - b); + if (options.totalValue.length % 2 === 1) { + options.totalValue = sortedValues[(sortedValues.length + 1) / 2]; + break; + } + const halfIndex = sortedValues.length / 2; + options.totalValue = (sortedValues[halfIndex] + sortedValues[halfIndex + 1]) / 2; + } + } + }, []); + + return ( + <div> + <DataGrid + dataSource={rows} + > + <Column + dataField={'region'} + caption={'Region'} + /> + <Column + dataField={'sector'} + caption={'Sector'} + /> + <Column + dataField={'customer'} + caption={'Customer'} + /> + <Column + dataField={'product'} + caption={'Product'} + /> + <Column + dataField={'amount'} + caption={'Sale Amount'} + alignment={'right'} + format="currency" + /> + <Summary calculateCustomSummary={calculateCustomSummary}> + <TotalItem + name="SalesMedianSummary" + column="amount" + summaryType="custom" + displayFormat="Median: {0}" + /> + <TotalItem + summaryType="avg" + displayFormat="Avg: {0}" + column="amount" + /> + </Summary> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/custom-summary.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/custom-summary.jsx new file mode 100644 index 0000000000..f9b81e9bbf --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/custom-summary.jsx @@ -0,0 +1,76 @@ +export default () => { + const onSelectionChanged = useCallback(e => e.component.refresh(true), []); + + const calculateCustomSummary = useCallback(options => { + if (options.summaryProcess === 'start') { + options.totalValue = 0; + return; + } + + const isRowSelected = options.component.isRowSelected(options.value?.ID); + + if (options.summaryProcess !== 'calculate' || !isRowSelected) { + return; + } + + switch(options.name) { + case 'SalesSumSummary': + options.totalValue += options.value.SaleAmount; + break; + case 'SalesMaxSummary': + options.totalValue = Math.max(options.totalValue, options.value.SaleAmount) + break; + case 'RegionCountSummary': + options.totalValue++; + } + }, []); + + return ( + <div> + <DataGrid + dataSource={rows} + onSelectionChanged={onSelectionChanged} + > + <Column + dataField={'region'} + caption={'Region'} + /> + <Column + dataField={'sector'} + caption={'Sector'} + /> + <Column + dataField={'customer'} + caption={'Customer'} + /> + <Column + dataField={'product'} + caption={'Product'} + /> + <Column + dataField={'amount'} + caption={'Sale Amount'} + alignment={'right'} + format="currency" + /> + <Summary calculateCustomSummary={calculateCustomSummary}> + <TotalItem + name="RegionCountSummary" + summaryType="custom" + displayFormat="Count: {0}" + showInColumn="region" /> + <TotalItem + name="SalesMaxSummary" + summaryType="custom" + displayFormat="Max: {0}" + showInColumn="amount" /> + <TotalItem + name="SalesSumSummary" + summaryType="custom" + displayFormat="Sum: {0}" + showInColumn="amount" /> + </Summary> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/formatless-custom-algorithm.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/formatless-custom-algorithm.jsx new file mode 100644 index 0000000000..5ba8fa2940 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/formatless-custom-algorithm.jsx @@ -0,0 +1,54 @@ +export default () => { + const calculateCustomSummary = useCallback(options => { + if(options.name == 'OverpricedCountSummary') { + switch(options.summaryProcess) { + case 'start': + options.totalValue = 0; + break; + case 'calculate': + options.totalValue += options.value > 6000 ? 1 : 0; + } + } + }, []); + + return ( + <div> + <DataGrid + dataSource={rows} + > + <Column + dataField={'region'} + caption={'Region'} + /> + <Column + dataField={'sector'} + caption={'Sector'} + /> + <Column + dataField={'customer'} + caption={'Customer'} + /> + <Column + dataField={'product'} + caption={'Product'} + /> + <Column + dataField={'amount'} + caption={'Sale Amount'} + alignment={'right'} + width={230} + format="currency" + /> + <Summary calculateCustomSummary={calculateCustomSummary}> + <TotalItem + name="OverpricedCountSummary" + column="amount" + summaryType="custom" + valueFormat="fixedPoint" + displayFormat="Price higher than $6000: {0}" + /> + </Summary> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/group-summary.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/group-summary.jsx new file mode 100644 index 0000000000..c8df6e99fc --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/group-summary.jsx @@ -0,0 +1,62 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Column + dataField={'region'} + caption={'Region'} + groupIndex={0} + /> + <Column + dataField={'customer'} + caption={'Customer'} + /> + <Column + dataField={'product'} + caption={'Product'} + /> + <Column + dataField={'units'} + caption={'Units'} + /> + <Column + dataField={'amount'} + caption={'Sale Amount'} + alignment={'right'} + format="currency" + /> + <Summary> + <GroupItem + column="amount" + summaryType="sum" + valueFormat="currency" + /> + <GroupItem + column="units" + summaryType="sum" + alignByColumn={true} + /> + <GroupItem + column="amount" + summaryType="max" + valueFormat="currency" + alignByColumn={true} + /> + <GroupItem + column="region" + summaryType="count" + showInGroupFooter={true} + /> + <GroupItem + column="amount" + summaryType="sum" + valueFormat="currency" + showInGroupFooter={true} + /> + </Summary> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/total-summary.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/total-summary.jsx new file mode 100644 index 0000000000..ab48d5712f --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/total-summary.jsx @@ -0,0 +1,48 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + > + <Column + dataField={'region'} + caption={'Region'} + /> + <Column + dataField={'sector'} + caption={'Sector'} + /> + <Column + dataField={'customer'} + caption={'Customer'} + /> + <Column + dataField={'product'} + caption={'Product'} + /> + <Column + dataField={'amount'} + caption={'Sale Amount'} + alignment={'right'} + format="currency" + /> + <Summary> + <TotalItem + column="region" + summaryType="count" + /> + <TotalItem + column="amount" + summaryType="sum" + valueFormat="currency" + /> + <TotalItem + column="amount" + summaryType="max" + valueFormat="currency" + /> + </Summary> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/controlled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/controlled-mode.jsx new file mode 100644 index 0000000000..9b63eb31ee --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/controlled-mode.jsx @@ -0,0 +1,35 @@ +export default () => { + const [expandedRowKeys, setExpandedRowKeys] = useState([0, 1]); + + return ( + <TreeList + dataSource={data} + rootValue={null} + expandedRowKeys={expandedRowKeys} + onExpandedRowKeysChanged={setExpandedRowKeys} + showRowLines={true} + showBorders={true} + columnAutoWidth={true} + keyExpr="id" + parentIdExpr="parentId" + > + <Column + dataField={'name'} + caption={'Name'} + width={300} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </TreeList> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/hierarchical-tree.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/hierarchical-tree.jsx new file mode 100644 index 0000000000..c6da68e79b --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/hierarchical-tree.jsx @@ -0,0 +1,30 @@ +export default () => { + return ( + <TreeList + dataSource={data} + showRowLines={true} + showBorders={true} + columnAutoWidth={true} + itemsExpr="items" + dataStructure="tree" + > + <Column + dataField={'name'} + caption={'Name'} + width={300} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </TreeList> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/plain-tree.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/plain-tree.jsx new file mode 100644 index 0000000000..e2ea4b3142 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/plain-tree.jsx @@ -0,0 +1,31 @@ +export default () => { + return ( + <TreeList + dataSource={data} + rootValue={null} + showRowLines={true} + showBorders={true} + columnAutoWidth={true} + keyExpr="id" + parentIdExpr="parentId" + > + <Column + dataField={'name'} + caption={'Name'} + width={300} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </TreeList> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/remote.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/remote.jsx new file mode 100644 index 0000000000..daabef13a6 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/remote.jsx @@ -0,0 +1,46 @@ +const dataSource = { + async load(loadOptions) { + const parentIdsParam = loadOptions.parentIds; + const url = new URL('https://js.devexpress.com/Demos/Mvc/api/treeListData'); + if (parentIdsParam) { + parentIdsParam.forEach((id: string) => { + url.searchParams.append('parentIds', id); + }); + } + + const result = await fetch(url.toString()); + + if (result.status === 200) { + return result.json(); + } + + throw new Error('Data Loading Error'); + }, + }; + + const customizeText = (e) => { + if (e.value !== null) { + return `${Math.ceil(e.value / 1024)} KB`; + } + return null; + }; + + export default () => { + return ( + <TreeList + id="treelist" + dataSource={dataSource} + showBorders={true} + keyExpr="id" + parentIdExpr="parentId" + hasItemsExpr="hasItems" + rootValue="" + > + <RemoteOperations filtering={true} /> + <Column dataField="name" /> + <Column width={100} customizeText={customizeText} dataField="size" /> + <Column width={150} dataField="createdDate" dataType="date" /> + <Column width={150} dataField="modifiedDate" dataType="date" /> + </TreeList> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/select-all.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/select-all.jsx new file mode 100644 index 0000000000..fee8c5476e --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/select-all.jsx @@ -0,0 +1,38 @@ +export default () => { + const [defaultExpandedRowIds] = useState([0]); + + return ( + <TreeList + dataSource={data} + rootValue={null} + defaultExpandedRowKeys={defaultExpandedRowIds} + showRowLines={true} + showBorders={true} + columnAutoWidth={true} + keyExpr="id" + parentIdExpr="parentId" + > + <Selection + recursive={false} + mode="multiple" + /> + <Column + dataField={'name'} + caption={'Name'} + width={300} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </TreeList> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/selection-controls.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/selection-controls.jsx new file mode 100644 index 0000000000..8b98c1c339 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/selection-controls.jsx @@ -0,0 +1,39 @@ +export default () => { + const [defaultExpandedRowIds] = useState([0]); + + return ( + <TreeList + dataSource={data} + rootValue={null} + defaultExpandedRowKeys={defaultExpandedRowIds} + showRowLines={true} + showBorders={true} + columnAutoWidth={true} + keyExpr="id" + parentIdExpr="parentId" + > + <Selection + recursive={false} + allowSelectAll={false} + mode="multiple" + /> + <Column + dataField={'name'} + caption={'Name'} + width={300} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </TreeList> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/uncontrolled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/uncontrolled-mode.jsx new file mode 100644 index 0000000000..6dbaf6218a --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/uncontrolled-mode.jsx @@ -0,0 +1,34 @@ +export default () => { + const [defaultExpandedRowIds] = useState([0, 1]); + + return ( + <TreeList + dataSource={data} + rootValue={null} + defaultExpandedRowKeys={defaultExpandedRowIds} + showRowLines={true} + showBorders={true} + columnAutoWidth={true} + keyExpr="id" + parentIdExpr="parentId" + > + <Column + dataField={'name'} + caption={'Name'} + width={300} + /> + <Column + dataField={'gender'} + caption={'Gender'} + /> + <Column + dataField={'city'} + caption={'City'} + /> + <Column + dataField={'car'} + caption={'Car'} + /> + </TreeList> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/column-virtualization.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/column-virtualization.jsx new file mode 100644 index 0000000000..ddde6161d7 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/column-virtualization.jsx @@ -0,0 +1,26 @@ +export default () => { + return ( + <div> + <DataGrid + dataSource={rows} + columnAutoWidth={true} + height={440} + > + <Scrolling + rowRenderingMode="virtual" + columnRenderingMode="virtual" + /> + { + columns.map((column) => ( + <Column + key={column.name} + dataField={column.name} + caption={column.title} + > + </Column> + )); + } + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/row-virtualization.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/row-virtualization.jsx new file mode 100644 index 0000000000..4c5f7b23ea --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/row-virtualization.jsx @@ -0,0 +1,22 @@ +export default () => { + const [columns] = useState([ + { dataField: 'Id', caption: 'ID' }, + { dataField: 'name', caption: 'Name' }, + { dataField: 'gender', caption: 'Gender' }, + { dataField: 'city', caption: 'City' }, + { dataField: 'car', caption: 'Car' } + ]); + + return ( + <div> + <DataGrid + dataSource={rows} + columns={columns} + height={440} + > + <Paging enabled={false} pageSize={100000} /> + <Scrolling rowRenderingMode="virtual" /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/scroll-to-row.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/scroll-to-row.jsx new file mode 100644 index 0000000000..9d3393af51 --- /dev/null +++ b/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/scroll-to-row.jsx @@ -0,0 +1,31 @@ +export default () => { + const [columns] = useState([ + { dataField: 'name', caption: 'Name', defaultSortOrder: 'asc' }, + { dataField: 'gender', caption: 'Gender', allowSorting: false }, + { dataField: 'city', caption: 'City', allowSorting: false }, + { dataField: 'car', caption: 'Car', allowSorting: false } + ]); + + const onRowInserted = useCallback((e) => { + e.component.navigateToRow(e.key); + }, []); + + return ( + <div> + <DataGrid + dataSource={rows} + columns={columns} + onRowInserted={onRowInserted} + height={440} + > + <Editing + allowUpdating={true} + allowAdding={true} + allowDeleting={true} + mode="row" + /> + <Scrolling rowRenderingMode={'virtual'} /> + </DataGrid> + </div> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-all-day-panel/$migration/week-view.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-all-day-panel/$migration/week-view.jsx new file mode 100644 index 0000000000..2993b0250c --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-all-day-panel/$migration/week-view.jsx @@ -0,0 +1,13 @@ +const views = ['week']; + +export default () => ( + <Scheduler + dataSource={appointments} + defaultCurrentDate={currentDate} + allDayPanelMode='all' + views={views} + textExpr="title" + startDayHour={9} + endDayHour={19} + /> +); \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/basic-setup.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/basic-setup.jsx new file mode 100644 index 0000000000..e8a3cc55dd --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/basic-setup.jsx @@ -0,0 +1,20 @@ +import Scheduler from 'devextreme-react/scheduler'; + +const currentDate = '2018-11-01'; +const schedulerData = [ + { startDate: '2018-11-01T09:45', endDate: '2018-11-01T11:00', title: 'Meeting' }, + { startDate: '2018-11-01T12:00', endDate: '2018-11-01T13:30', title: 'Go to a gym' }, +]; + +const views = ['day']; + +export default () => ( + <Scheduler + dataSource={schedulerData} + views={views} + textExpr="title" + defaultCurrentDate={currentDate} + startDayHour={9} + endDayHour={14} + /> +); \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/custom-template.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/custom-template.jsx new file mode 100644 index 0000000000..68f9ef1b11 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/custom-template.jsx @@ -0,0 +1,66 @@ +const getDateCellClassName = (isToday, isWeekend) => { + if (isToday) { + return 'dark-blue-background'; + } + if (isWeekend) { + return 'dark-gray-background'; + } + }; + + const DateCell = ({ isToday, isWeekend, date }) => { + return ( + <div className={getDateCellClassName(isToday, isWeekend)}> + <div className="data-cell-day-name"> + { date.toLocaleString(window.navigator.language, { weekday: 'short' }) } + </div> + <div className="data-cell-day-number"> + { date.getDate() } + </div> + </div> + ); + }; + + const getDataCellClassName = (isToday, isWeekend) => { + if (isToday) { + return 'blue-background'; + } + if (isWeekend) { + return 'gray-background'; + } + }; + + const DataCell = ({ isToday, isWeekend }) => { + return ( + <div className={getDataCellClassName(isToday, isWeekend)} /> + ); + }; + + const cellRender = (CellComponent, datePropName) => (props) => { + const cellDate = props[datePropName]; + const date = new Date(cellDate); + + if (date.getDate() === new Date().getDate()) { + return <CellComponent isToday={true} date={date} />; + } + + if (date.getDay() === 0 || date.getDay() === 6) { + return <CellComponent isWeekend={true} date={date} />; + } + + return <CellComponent date={date}/>; + }; + + const views = ['week']; + + export default () => ( + <Scheduler + dataSource={appointments} + height={660} + views={views} + textExpr="title" + startDayHour={9} + endDayHour={19} + dataCellRender={cellRender(DataCell, 'startDate')} + dateCellRender={cellRender(DateCell, 'date')} + /> +); \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/day.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/day.jsx new file mode 100644 index 0000000000..88f0666a35 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/day.jsx @@ -0,0 +1,11 @@ +const views = ['day']; + +export default () => ( + <Scheduler + dataSource={appointments} + views={views} + textExpr="title" + startDayHour={8} + endDayHour={13} + /> +); \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/month.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/month.jsx new file mode 100644 index 0000000000..5e0cc1694d --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/month.jsx @@ -0,0 +1,11 @@ +const views = ['month']; +const currentDate = '2018-07-17'; + +export default () => ( + <Scheduler + dataSource={appointments} + views={views} + currentDate={currentDate} + textExpr="title" + /> +); \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/simple-template.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/simple-template.jsx new file mode 100644 index 0000000000..4bb197acc2 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/simple-template.jsx @@ -0,0 +1,29 @@ +const views = ['week']; + +const renderAppointment = ({ targetedAppointmentData }) => { + return ( + <div style={{ + backgroundColor: '#FFC107', + borderRadius: '8px', + }}> + <div>{targetedAppointmentData.text}</div> + <div> + {formatDate(targetedAppointmentData.displayStartDate, 'shortTime')} + {' - '} + {formatDate(targetedAppointmentData.displayEndDate, 'shortTime')} + </div> + </div> + ); +}; + +export default () => ( + <Scheduler + dataSource={appointments} + defaultCurrentDate={currentDate} + views={views} + textExpr="title" + startDayHour={9} + endDayHour={19} + appointmentRender={renderAppointment} + /> +); \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/week.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/week.jsx new file mode 100644 index 0000000000..cb3483e490 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/week.jsx @@ -0,0 +1,12 @@ +const views = ['week']; + +export default () => ( + <Scheduler + dataSource={appointments} + height={660} + views={views} + textExpr="title" + startDayHour={9} + endDayHour={19} + /> +); \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-current-time-indication/$migration/current-time-indicator.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-current-time-indication/$migration/current-time-indicator.jsx new file mode 100644 index 0000000000..79da3345e4 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-current-time-indication/$migration/current-time-indicator.jsx @@ -0,0 +1,54 @@ +/* ... */ + +const CheckBoxContainer = (({ + shadePreviousCells, handleCheckboxChange, + }) => ( + <StyledGrid item container direction="column" className={classes.checkBoxContainer} xs={6}> + <ShadeCellsCheckBox + shadePreviousCells={shadePreviousCells} + handleChange={handleCheckboxChange} + /> + </StyledGrid> + )); + + export default () => { + const [updateInterval, setUpdateInterval] = useState(10000); + const [shadePreviousCells, setShadePreviousCells] = useState(true); + + const handleUpdateIntervalChange = useCallback((nextValue) => { + setUpdateInterval(nextValue * 1000); + }, []) + + const handleCheckboxChange = useCallback(() => { + setShadePreviousCells(shadeCells => !shadeCells); + }, []); + + return ( + <React.Fragment> + <CheckBoxContainer + shadePreviousCells={shadePreviousCells} + handleCheckboxChange={handleCheckboxChange} + /> + <UpdateIntervalBox + updateInterval={updateInterval} + onValueChange={handleUpdateIntervalChange} + /> + <Scheduler + dataSource={data} + height={660} + textExpr="title" + defaultCurrentDate="2018-05-30" + showCurrentTimeIndicator={true} + shadeUntilCurrentTime={shadePreviousCells} + indicatorUpdateInterval={updateInterval} + + > + <View + type="week" + startDayHour={9} + endDayHour={19} + /> + </Scheduler> + </React.Fragment> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-date-navigator/$migration/controlled.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-date-navigator/$migration/controlled.jsx new file mode 100644 index 0000000000..35b7bf8dcd --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-date-navigator/$migration/controlled.jsx @@ -0,0 +1,18 @@ +export default () => { + const [currentDate, setCurrentDate] = useState('2018-06-27'); + + return ( + <Scheduler + dataSource={data} + textExpr="title" + currentDate={currentDate} + onCurrentDateChanged={setCurrentDate} + > + <View + type="week" + startDayHour={9} + endDayHour={19} + /> + </Scheduler> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-date-navigator/$migration/uncontrolled.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-date-navigator/$migration/uncontrolled.jsx new file mode 100644 index 0000000000..9efe9e16f3 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-date-navigator/$migration/uncontrolled.jsx @@ -0,0 +1,10 @@ +export default () => { + return ( + <Scheduler + dataSource={data} + textExpr="title" + defaultCurrentDate="2018-07-27" + views={['month']} + /> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/copy-after-dragdrop.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/copy-after-dragdrop.jsx new file mode 100644 index 0000000000..8def135c00 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/copy-after-dragdrop.jsx @@ -0,0 +1,32 @@ +export default () => { + const shouldCopy = useRef(false); + + const onDragEnd = useCallback(({ itemData, toItemData, event }) => { + shouldCopy.current = event.shiftKey && (itemData.startDate !== toItemData.startDate || itemData.endDate !== toItemData.endDate); + }, [shouldCopy.current]); + + const onAppointmentUpdating = useCallback((e) => { + if (shouldCopy.current) { + e.cancel = true; + shouldCopy.current = false; + e.component.addAppointment(e.newData); + } + }, []); + + return ( + <Scheduler + dataSource={data} + height={660} + textExpr="title" + defaultCurrentDate={currentDate} + onAppointmentUpdating={onAppointmentUpdating} + > + <AppointmentDragging onDragEnd={onDragEnd} /> + <View + type="week" + startDayHour={9} + endDayHour={17} + /> + </Scheduler> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/delete-confirmation.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/delete-confirmation.jsx new file mode 100644 index 0000000000..98b67936b6 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/delete-confirmation.jsx @@ -0,0 +1,24 @@ +export default () => { + const onAppointmentEditing = useCallback((e) => { + if(!window.confirm('Are you sure you want to edit/delete this appointment?')) { + e.cancel = true; + } + }, []); + + return ( + <Scheduler + dataSource={data} + height={660} + textExpr="title" + defaultCurrentDate={currentDate} + onAppointmentUpdating={onAppointmentEditing} + onAppointmentDeleting={onAppointmentEditing} + > + <View + type="day" + startDayHour={9} + endDayHour={17} + /> + </Scheduler> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/drag-drop.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/drag-drop.jsx new file mode 100644 index 0000000000..30398bc911 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/drag-drop.jsx @@ -0,0 +1,25 @@ +const dragDisableIds = new Set([3, 8, 10, 12]); + +export default () => { + const onDragStart = useCallback(e => { + if (dragDisableIds.has(e.itemData.id)) { + e.cancel = true; + } + }, []); + + return ( + <Scheduler + dataSource={data} + height={660} + textExpr="title" + defaultCurrentDate={currentDate} + > + <AppointmentDragging onDragStart={onDragStart} /> + <View + type="week" + startDayHour={9} + endDayHour={16} + /> + </Scheduler> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/editing-features.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/editing-features.jsx new file mode 100644 index 0000000000..2cc7640218 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/editing-features.jsx @@ -0,0 +1,52 @@ +export default () => { + const [editingOptions, setEditingOptions] = useState({ + allowAdding: true, + allowDeleting: true, + allowUpdating: true, + allowDragging: true, + allowResizing: true, + }); + + const handleEditingOptionsChange = useCallback(({ target }) => { + const { value } = target; + const { [value]: checked } = editingOptions; + setEditingOptions({ + ...editingOptions, + [value]: !checked, + }); + }); + + const { + allowAdding, allowDeleting, allowUpdating, allowResizing, allowDragging, + } = editingOptions; + + return ( + <React.Fragment> + <EditingOptionsSelector + options={editingOptions} + onOptionsChange={handleEditingOptionsChange} + /> + <Scheduler + dataSource={data} + height={660} + textExpr="title" + defaultCurrentDate={currentDate} + onAppointmentUpdating={onAppointmentEditing} + onAppointmentDeleting={onAppointmentEditing} + > + <Editing + allowAdding={allowAdding} + allowDeleting={allowDeleting} + allowResizing={allowResizing} + allowDragging={allowDragging} + allowUpdating={allowUpdating} + /> + <View + type="week" + startDayHour={9} + endDayHour={19} + /> + </Scheduler> + </React.Fragment> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/form-customization.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/form-customization.jsx new file mode 100644 index 0000000000..4162300db2 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/form-customization.jsx @@ -0,0 +1,32 @@ +export default () => { + const onAppointmentFormOpening = useCallback(e => { + let formItems = e.form.option("items"); + + formItems.push({ + colSpan: 2, + label: { text: "Custom Field" }, + editorType: "dxTextBox", + dataField: "customField" + }); + + formItems = formItems.filter(item => item.label?.text !== 'More Information') + + e.form.option("items", formItems); + }, []); + + return ( + <Scheduler + dataSource={data} + height={660} + textExpr="title" + defaultCurrentDate={currentDate} + onAppointmentFormOpening={onAppointmentFormOpening} + > + <View + type="day" + startDayHour={9} + endDayHour={15} + /> + </Scheduler> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/uncontrolled.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/uncontrolled.jsx new file mode 100644 index 0000000000..0b79a7ad74 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/uncontrolled.jsx @@ -0,0 +1,15 @@ +export default () => { + return ( + <Scheduler + dataSource={data} + height={660} + textExpr="title" + > + <View + type="day" + startDayHour={9} + endDayHour={19} + /> + </Scheduler> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/basic.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/basic.jsx new file mode 100644 index 0000000000..eb96f5777d --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/basic.jsx @@ -0,0 +1,33 @@ +export default () => { + const [groups] = useState(['roomId', 'members']); + + return ( + <React.Fragment> + <Scheduler + dataSource={data} + height={660} + textExpr="title" + groups={groups} + defaultCurrentDate="2017-05-28" + > + <View + type="day" + startDayHour={9} + endDayHour={15} + /> + <Resource + dataSource={owners} + fieldExpr={'members'} + label={'Members'} + allowMultiple={true} + useColorAsDefault={true} + /> + <Resource + dataSource={locaions} + fieldExpr={'roomId'} + label={'Locations'} + /> + </Scheduler> + </React.Fragment> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/custom.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/custom.jsx new file mode 100644 index 0000000000..343d1856d6 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/custom.jsx @@ -0,0 +1,65 @@ +const colors = ['rgba(102, 187, 106, 0.1)', 'rgba(255, 167, 38, 0.15)']; +const iconClasses = ['low-priority-icon', 'high-priority-icon']; + +export default () => { + const dataCellRender = useCallback(({ groupIndex, text }) => { + return ( + <div style={{ backgroundColor: colors[groupIndex] }}> + { text } + </div> + ); + }, []); + + const dateCellRender = useCallback(({ groupIndex, date }) => { + return ( + <div style={{ backgroundColor: colors[groupIndex] }}> + <div className="data-cell-day-name"> + { date.toLocaleString(window.navigator.language, { weekday: 'short' }) } + </div> + <div className="data-cell-day-number"> + { date.getDate() } + </div> + </div> + ); + }, []); + + const resourceCellRender = useCallback(({ id, text }) => { + const Icon = getIconById(id); + + return ( + <div style={{ backgroundColor: colors[id] }}> + <span>{ text }</span> + <Icon /> + </div> + ); + }, []); + + const [groups] = useState(['priorityId']); + const [data] = useState(appointments.filter(appointment => appointment.priorityId < 3)); + + return ( + <React.Fragment> + <Scheduler + dataSource={data} + height={660} + textExpr="title" + groups={groups} + defaultCurrentDate="2018-05-30" + dataCellRender={dataCellRender} + dateCellRender={dateCellRender} + resourceCellRender={resourceCellRender} + > + <View + type="day" + startDayHour={9} + endDayHour={17} + /> + <Resource + dataSource={priorityData} + fieldExpr={'priorityId'} + label={'Priority'} + /> + </Scheduler> + </React.Fragment> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/group-by-dates.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/group-by-dates.jsx new file mode 100644 index 0000000000..9266d24299 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/group-by-dates.jsx @@ -0,0 +1,36 @@ +export default () => { + const [groups] = useState(['priorityId']); + const [groupByDate, setGroupByDate] = useState(true); + + const onGroupOrderChange = useCallback(() => { + setGroupByDate(groupByDate => !groupByDate); + }, []); + + return ( + <React.Fragment> + <GroupOrderSwitcher isGroupByDate={groupByDate} onChange={onGroupOrderChange} /> + <Scheduler + dataSource={data} + height={660} + textExpr="title" + groups={groups} + groupByDate={groupByDate} + defaultCurrentDate="2018-05-30" + > + <View + type="workWeek" + startDayHour={8.5} + endDayHour={17} + /> + <View + type="month" + /> + <Resource + dataSource={priorityData} + fieldExpr={'priorityId'} + label={'Priority'} + /> + </Scheduler> + </React.Fragment> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/group-orientation.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/group-orientation.jsx new file mode 100644 index 0000000000..f0213a2814 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/group-orientation.jsx @@ -0,0 +1,41 @@ +export default () => { + const [priorityInstances] = useState([ + { text: 'Low Priority', id: 1, color: blue }, + { text: 'High Priority', id: 2, color: orange }, + ]); + + const [groups] = useState(['priorityId']); + + return ( + <React.Fragment> + <Scheduler + dataSource={data} + height={660} + textExpr="title" + groups={groups} + defaultCurrentDate="2018-05-30" + > + <View + type="workWeek" + name="Vertical Orientation" + startDayHour={9} + endDayHour={17} + cellDuration={60} + groupOrientation="vertical" + /> + <View + type="workWeek" + name="Horizontal Orientation" + startDayHour={9} + endDayHour={17} + groupOrientation="horizontal" + /> + <Resource + dataSource={priorityInstances} + fieldExpr={'priorityId'} + label={'Priority'} + /> + </Scheduler> + </React.Fragment> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-localization/$migration/custom-formatting.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-localization/$migration/custom-formatting.jsx new file mode 100644 index 0000000000..2486f9a06d --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-localization/$migration/custom-formatting.jsx @@ -0,0 +1,47 @@ +export default () => { + const formatDayScaleDate = useCallback((date) => { + const momentDate = moment(date); + const weekday = momentDate.weekday(); + return momentDate.format(weekday === 6 || weekday === 0 ? 'D' : 'dddd'); + }, []); + + const dateCellRender = useCallback(({ date }) => { + return ( + <div> + <div className="data-cell-day-name"> + { formatDayScaleDate(date) } + </div> + <div className="data-cell-day-number"> + { date.getDate() } + </div> + </div> + ); + }, []); + + const timeCellRender = useCallback(({ date }) => { + return ( + <div className="time-cell"> + { formatTimeScaleDate(date) } + </div> + ); + }, []); + + return ( + <React.Fragment> + <Scheduler + dataSource={data} + height={660} + textExpr="title" + defaultCurrentDate={currentDate} + dateCellRender={dateCellRender} + timeCellRender={timeCellRender} + > + <View + type="week" + startDayHour={9} + endDayHour={19} + /> + </Scheduler> + </React.Fragment> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-localization/$migration/locale.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-localization/$migration/locale.jsx new file mode 100644 index 0000000000..dcfe0109c8 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-localization/$migration/locale.jsx @@ -0,0 +1,43 @@ +import deMessages from 'devextreme/localization/messages/de.json'; +import frMessages from 'devextreme/localization/messages/fr.json'; +import { locale, loadMessages, formatMessage } from 'devextreme/localization'; + +const DEFAULT_LOCALE = 'fr-FR'; + +const getLocale = () => sessionStorage.getItem('locale') || DEFAULT_LOCALE; + +locale(getLocale()); + +loadMessages(deMessages); +loadMessages(frMessages); + +export default () => { + const [locale, setLocale] = useState(getLocale()); + + const onLocaleChange = useCallback(e => { + sessionStorage.setItem('locale', e.target.value); + setLocale(e.target.value); + document.location.reload(); + }, []); + + return ( + <React.Fragment> + <LocaleSwitcher + currentLocale={locale} + onLocaleChange={onLocaleChange} + /> + <Scheduler + dataSource={data} + height={660} + textExpr="title" + defaultCurrentDate={currentDate} + > + <View + type="week" + startDayHour={9} + endDayHour={19} + /> + </Scheduler> + </React.Fragment> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-recurrence/$migration/basic.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-recurrence/$migration/basic.jsx new file mode 100644 index 0000000000..2ceff326b9 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-recurrence/$migration/basic.jsx @@ -0,0 +1,22 @@ +const views = ['week', 'month']; + +export default () => ( + <Scheduler + dataSource={data} + defaultCurrentDate={'2018-06-25'} + views={views} + textExpr="title" + startDayHour={9} + endDayHour={15} + recurrenceRuleExpr="rRule" + recurrenceExceptionExpr="exDate" + > + <Editing + allowAdding={false} + allowDeleting={false} + allowResizing={true} + allowDragging={true} + allowUpdating={true} + /> + </Scheduler> +); \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-resources/$migration/basic.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-resources/$migration/basic.jsx new file mode 100644 index 0000000000..b222f2df21 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-resources/$migration/basic.jsx @@ -0,0 +1,39 @@ +export default () => { + const [mainResourceName, setMainResourceName] = useState(resources[0]); + + const changeMainResource = useCallback((mainResourceName) => { + setMainResourceName(mainResourceName); + }, []); + + return ( + <React.Fragment> + <ResourceSwitcher + resources={resources} + mainResourceName={mainResourceName} + onChange={changeMainResource} + /> + <Scheduler + dataSource={data} + height={660} + textExpr="title" + > + <View + type="week" + startDayHour={11.5} + endDayHour={16} + /> + { + resources.map(resource => ( + <Resource + dataSource={resource.instances} + fieldExpr={resource.fieldName} + label={resource.title} + allowMultiple={resource.allowMultiple ?? false} + useColorAsDefault={mainResourceName === resource.fieldName} + /> + )) + } + </Scheduler> + </React.Fragment> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-resources/$migration/editing.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-resources/$migration/editing.jsx new file mode 100644 index 0000000000..3bfb6b5191 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-resources/$migration/editing.jsx @@ -0,0 +1,26 @@ +export default () => { + return ( + <React.Fragment> + <Scheduler + dataSource={data} + textExpr="title" + defaultCurrentDate="2017-05-25" + > + <View + type="month" + /> + { + resources.map(resource => ( + <Resource + dataSource={resource.instances} + fieldExpr={resource.fieldName} + label={resource.title} + allowMultiple={resource.allowMultiple ?? false} + useColorAsDefault={mainResourceName === resource.fieldName} + /> + )) + } + </Scheduler> + </React.Fragment> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-tooltip/$migration/custom.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-tooltip/$migration/custom.jsx new file mode 100644 index 0000000000..7721000cfb --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-tooltip/$migration/custom.jsx @@ -0,0 +1,31 @@ +/* Lots of code here */ + +const renderAppointmentTooltip = ({ appointmentData }) => { + return ( + <React.Fragment> + <div> + <Header data={appointmentData} commandButtonComponent={CommandButton} /> + </div> + <div> + <Content data={appointmentData} /> + </div> + </React.Fragment> + ); + }; + + export default () => { + return ( + <Scheduler + dataSource={data} + height={660} + textExpr="title" + appointmentTooltipRender={renderAppointmentTooltip} + > + <View + type="week" + startDayHour={9} + endDayHour={19} + /> + </Scheduler> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/controlled.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/controlled.jsx new file mode 100644 index 0000000000..60ba3db474 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/controlled.jsx @@ -0,0 +1,31 @@ +export default () => { + const [currentView, setCurrentView] = useState('workWeek'); + + return ( + <Scheduler + dataSource={appointments} + textExpr="title" + defaultCurrentDate="2018-07-25" + currentView={currentView} + onCurrentViewChanged={setCurrentView} + height={660} + > + <View + type="week" + startDayHour={10} + endDayHour={19} + /> + <View + type="workWeek" + startDayHour={9} + endDayHour={19} + /> + <View + type="month" + /> + <View + type="day" + /> + </Scheduler> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/external-control.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/external-control.jsx new file mode 100644 index 0000000000..908f61f593 --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/external-control.jsx @@ -0,0 +1,57 @@ +const ExternalViewSwitcher = ({ + currentView, + onChange, + }) => ( + <RadioGroup + aria-label="Views" + style={{ flexDirection: 'row' }} + name="views" + value={currentView} + onChange={onChange} + > + <FormControlLabel value="week" control={<Radio />} label="Week" /> + <FormControlLabel value="workWeek" control={<Radio />} label="Work Week" /> + <FormControlLabel value="month" control={<Radio />} label="Month" /> + </RadioGroup> + ); + + export default () => { + const [currentView, setCurrentView] = useState('month'); + + const onOptionChanged = useCallback(e => { + if (e.fullName === 'currentView') { + setCurrentView(e.value); + } + }, []); + + return ( + <React.Fragment> + <ExternalViewSwitcher + currentView={currentView} + onChange={setCurrentView} + /> + + <Scheduler + dataSource={data} + textExpr="title" + defaultCurrentDate="2018-07-25" + currentView={currentView} + height={660} + > + <View + type="week" + startDayHour={10} + endDayHour={19} + /> + <View + type="workWeek" + startDayHour={9} + endDayHour={19} + /> + <View + type="month" + /> + </Scheduler> + </React.Fragment> + ); +}; \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/uncontrolled.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/uncontrolled.jsx new file mode 100644 index 0000000000..fa5f65458b --- /dev/null +++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/uncontrolled.jsx @@ -0,0 +1,20 @@ +export default () => ( + <Scheduler + dataSource={appointments} + textExpr="title" + defaultCurrentDate="2018-07-25" + defaultCurrentView="week" + height={660} + > + <View + type="day" + startDayHour={9} + endDayHour={18} + /> + <View + type="week" + startDayHour={10} + endDayHour={19} + /> + </Scheduler> +); \ No newline at end of file diff --git a/packages/dx-react-scheduler-demos/src/index.jsx b/packages/dx-react-scheduler-demos/src/index.jsx index a656a8d8ac..38c470cb2f 100644 --- a/packages/dx-react-scheduler-demos/src/index.jsx +++ b/packages/dx-react-scheduler-demos/src/index.jsx @@ -2,7 +2,7 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { initialize } from '@devexpress/dx-demo-shell'; import '@devexpress/dx-demo-shell/dist/index.css'; -import { demos } from './demo-registry'; +import { demos, migrationSamples } from './demo-registry'; import { themes } from './theme-registry'; import { themeComponents } from './theme-components-registry'; import { demoData } from './demo-data-registry'; @@ -10,6 +10,7 @@ import './index.css'; initialize({ demoSources: demos, + migrationSamples, themeSources: themes, themeComponents, demoData,