From f754da6873cfd2c5fabce8ddc5bfc48bdb87b256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 22 Aug 2019 17:31:41 -0400 Subject: [PATCH 01/41] experimental lazy loading for the table --- .config/webpack/base.js | 26 ++++++++++- .config/webpack/base.preprocessing.js | 7 +++ ...experimental-dash-dynamic-import-plugin.js | 25 +++++++++++ dash_table/__init__.py | 32 ++++++++++++++ package.json | 1 + src/dash-table/components/Export/index.tsx | 13 +++--- src/dash-table/components/Export/utils.tsx | 20 ++++----- src/dash-table/dash/DataTable.js | 40 +++-------------- src/dash-table/dash/LazyDataTable.js | 43 +++++++++++++++++++ 9 files changed, 156 insertions(+), 51 deletions(-) create mode 100644 .config/webpack/base.preprocessing.js create mode 100644 .config/webpack/experimental-dash-dynamic-import-plugin.js create mode 100644 src/dash-table/dash/LazyDataTable.js diff --git a/.config/webpack/base.js b/.config/webpack/base.js index 34e2f9887..d1525236f 100644 --- a/.config/webpack/base.js +++ b/.config/webpack/base.js @@ -1,12 +1,19 @@ const path = require('path'); +const webpack = require('webpack'); +const WebpackDashDynamicImport = require("./experimental-dash-dynamic-import-plugin"); + +const basePreprocessing = require('./base.preprocessing'); const packagejson = require('./../../package.json'); const dashLibraryName = packagejson.name.replace(/-/g, '_'); + module.exports = (options = {}) => { const babel = options.babel || undefined; - const preprocessor = options.preprocessor || {}; + const preprocessor = basePreprocessing(options.preprocessor); + console.log('*********************'); + console.log(preprocessor); const mode = options.mode || 'development'; const ts = options.ts || {}; @@ -24,6 +31,7 @@ module.exports = (options = {}) => { mode: mode, output: { path: path.resolve(__dirname, `./../../${dashLibraryName}`), + chunkFilename: '[name].js', filename: '[name].js', library: dashLibraryName, libraryTarget: 'window' @@ -87,6 +95,20 @@ module.exports = (options = {}) => { tests: path.resolve('./tests') }, extensions: ['.js', '.ts', '.tsx'] - } + }, + optimization: { + splitChunks: { + chunks: 'async', + name: true, + cacheGroups: { + async: { + + } + } + } + }, + plugins: [ + new WebpackDashDynamicImport() + ] }; }; \ No newline at end of file diff --git a/.config/webpack/base.preprocessing.js b/.config/webpack/base.preprocessing.js new file mode 100644 index 000000000..fdd1a0114 --- /dev/null +++ b/.config/webpack/base.preprocessing.js @@ -0,0 +1,7 @@ +module.exports = ({ definitions, variables, ...options } = {}) => ({ + ...options, + definitions: definitions || [], + variables: Object.assign({ + + }, variables || {}) +}); \ No newline at end of file diff --git a/.config/webpack/experimental-dash-dynamic-import-plugin.js b/.config/webpack/experimental-dash-dynamic-import-plugin.js new file mode 100644 index 000000000..41add4252 --- /dev/null +++ b/.config/webpack/experimental-dash-dynamic-import-plugin.js @@ -0,0 +1,25 @@ +const resolveImportSource = `\ +Object.defineProperty(__webpack_require__, 'p', { + get: (function () { + var url = Array.from(document.getElementsByTagName('script')).slice(-1)[0].src.split('/').slice(0, -1).join('/') + '/'; + + return function() { + return url; + }; + })() +});` + +class WebpackDashDynamicImport { + apply(compiler) { + compiler.hooks.compilation.tap('WebpackDashDynamicImport', compilation => { + compilation.mainTemplate.hooks.requireExtensions.tap('WebpackDashDynamicImport > RequireExtensions', (source, chunk, hash) => { + return [ + source, + resolveImportSource + ] + }); + }); + } +} + +module.exports = WebpackDashDynamicImport; \ No newline at end of file diff --git a/dash_table/__init__.py b/dash_table/__init__.py index 66baed638..dbea5dbb7 100644 --- a/dash_table/__init__.py +++ b/dash_table/__init__.py @@ -44,6 +44,38 @@ ).format(__version__), 'namespace': package_name, 'dynamic': True + }, + { + 'relative_package_path': 'async~dash-table.js', + 'external_url': ( + 'https://unpkg.com/dash-table@{}/dash_table/async~dash-table.js' + ).format(__version__), + 'namespace': package_name, + 'dynamic': True + }, + { + 'relative_package_path': 'async~dash-table.js.map', + 'external_url': ( + 'https://unpkg.com/dash-table@{}/dash_table/async~dash-table.js.map' + ).format(__version__), + 'namespace': package_name, + 'dynamic': True + }, + { + 'relative_package_path': 'async~export.js', + 'external_url': ( + 'https://unpkg.com/dash-table@{}/dash_table/async~export.js' + ).format(__version__), + 'namespace': package_name, + 'dynamic': True + }, + { + 'relative_package_path': 'async~export.js.map', + 'external_url': ( + 'https://unpkg.com/dash-table@{}/dash_table/async~export.js.map' + ).format(__version__), + 'namespace': package_name, + 'dynamic': True } ] diff --git a/package.json b/package.json index 5347ebac1..df5a3ed43 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "devDependencies": { "@babel/cli": "^7.5.5", "@babel/core": "^7.5.5", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/polyfill": "^7.4.4", "@babel/preset-env": "^7.5.5", "@babel/preset-react": "^7.0.0", diff --git a/src/dash-table/components/Export/index.tsx b/src/dash-table/components/Export/index.tsx index 4e8bf1f24..b92828285 100644 --- a/src/dash-table/components/Export/index.tsx +++ b/src/dash-table/components/Export/index.tsx @@ -1,7 +1,6 @@ -import XLSX from 'xlsx'; import React from 'react'; import { IDerivedData, Columns } from 'dash-table/components/Table/props'; -import { createWorkbook, createHeadings, createWorksheet } from './utils'; +import { createWorkbook, createHeadings } from './utils'; import getHeaderRows from 'dash-table/derived/header/headerRows'; interface IExportButtonProps { @@ -18,13 +17,16 @@ export default React.memo((props: IExportButtonProps) => { const { columns, export_format, virtual_data, export_headers, visibleColumns, merge_duplicate_headers } = props; const isFormatSupported = export_format === 'csv' || export_format === 'xlsx'; - const handleExport = () => { + const handleExport = async () => { + const XLSX = await import(/* webpackChunkName: "export" */ 'xlsx'); + const columnID = visibleColumns.map(column => column.id); const columnHeaders = visibleColumns.map(column => column.name); const maxLength = getHeaderRows(columns); const heading = (export_headers !== 'none') ? createHeadings(columnHeaders, maxLength) : []; - const ws = createWorksheet(heading, virtual_data.data, columnID, export_headers, merge_duplicate_headers); - const wb = createWorkbook(ws); + + const wb = await createWorkbook(heading, virtual_data.data, columnID, export_headers, merge_duplicate_headers); + if (export_format === 'xlsx') { XLSX.writeFile(wb, 'Data.xlsx', {bookType: 'xlsx', type: 'buffer'}); } else if (export_format === 'csv') { @@ -32,6 +34,7 @@ export default React.memo((props: IExportButtonProps) => { } }; + console.log('hello'); return (
{!isFormatSupported ? null : ( diff --git a/src/dash-table/components/Export/utils.tsx b/src/dash-table/components/Export/utils.tsx index b322f97df..9198695cb 100644 --- a/src/dash-table/components/Export/utils.tsx +++ b/src/dash-table/components/Export/utils.tsx @@ -1,5 +1,4 @@ import * as R from 'ramda'; -import XLSX from 'xlsx'; import { Data } from 'dash-table/components/Table/props'; interface IMergeObject { @@ -7,7 +6,7 @@ interface IMergeObject { e: {r: number, c: number}; } -export function transformMultDimArray(array: (string | string[])[], maxLength: number): string[][] { +function transformMultiDimArray(array: (string | string[])[], maxLength: number): string[][] { const newArray: string[][] = array.map(row => { if (row instanceof Array && row.length < maxLength) { return row.concat(Array(maxLength - row.length).fill('')); @@ -23,7 +22,7 @@ export function transformMultDimArray(array: (string | string[])[], maxLength: n return newArray; } -export function getMergeRanges(array: string[][]) { +function getMergeRanges(array: string[][]) { let apiMergeArray: IMergeObject[] = []; const iForEachOuter = R.addIndex<(string[]), void>(R.forEach); const iForEachInner = R.addIndex<(string), void>(R.forEach); @@ -47,13 +46,9 @@ export function getMergeRanges(array: string[][]) { return R.filter((item: IMergeObject) => item.s.c !== item.e.c || item.s.r !== item.e.r, apiMergeArray); } -export function createWorkbook(ws: XLSX.WorkSheet) { - const wb = XLSX.utils.book_new(); - XLSX.utils.book_append_sheet(wb, ws, 'SheetJS'); - return wb; -} +export async function createWorkbook(heading: string[][], data: Data, columnID: string[], exportHeader: string, mergeDuplicateHeaders: boolean) { + const XLSX = await import(/* webpackChunkName: "export" */ 'xlsx'); -export function createWorksheet(heading: string[][], data: Data, columnID: string[], exportHeader: string, mergeDuplicateHeaders: boolean ) { const ws = XLSX.utils.aoa_to_sheet(heading); if (exportHeader === 'display' || exportHeader === 'names' || exportHeader === 'none') { XLSX.utils.sheet_add_json(ws, data, { @@ -67,10 +62,13 @@ export function createWorksheet(heading: string[][], data: Data, columnID: strin } else if (exportHeader === 'ids') { XLSX.utils.sheet_add_json(ws, data, { header: columnID }); } - return ws; + + const wb = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(wb, ws, 'SheetJS'); + return wb; } export function createHeadings(columnHeaders: (string | string[])[], maxLength: number) { - const transformedArray = transformMultDimArray(columnHeaders, maxLength); + const transformedArray = transformMultiDimArray(columnHeaders, maxLength); return R.transpose(transformedArray); } \ No newline at end of file diff --git a/src/dash-table/dash/DataTable.js b/src/dash-table/dash/DataTable.js index bc156aba2..d4ba05846 100644 --- a/src/dash-table/dash/DataTable.js +++ b/src/dash-table/dash/DataTable.js @@ -1,41 +1,15 @@ -import * as R from 'ramda'; -import React, { Component } from 'react'; +import React, { Component, Suspense, lazy } from 'react'; import PropTypes from 'prop-types'; -import RealTable from 'dash-table/components/Table'; +const LazyDataTable = lazy(() => import(/* webpackChunkName: "dash-table" */ 'dash-table/dash/LazyDataTable')); -import Logger from 'core/Logger'; - -import genRandomId from 'dash-table/utils/generate'; -import isValidProps from './validate'; -import Sanitizer from './Sanitizer'; - -/** - * Dash DataTable is an interactive table component designed for - * designed for viewing, editing, and exploring large datasets. - * DataTable is rendered with standard, semantic HTML markup, - * which makes it accessible, responsive, and easy to style. This - * component was written from scratch in React.js specifically for the - * Dash community. Its API was designed to be ergonomic and its behavior - * is completely customizable through its properties. - */ export default class DataTable extends Component { - constructor(props) { - super(props); - let id; - this.getId = () => (id = id || genRandomId('table-')); - this.sanitizer = new Sanitizer(); - } - render() { - if (!isValidProps(this.props)) { - return (
Invalid props combination
); - } - - const sanitizedProps = this.sanitizer.sanitize(this.props); - return this.props.id ? - () : - (); + return ( + + ); } } diff --git a/src/dash-table/dash/LazyDataTable.js b/src/dash-table/dash/LazyDataTable.js new file mode 100644 index 000000000..d8dcd7e68 --- /dev/null +++ b/src/dash-table/dash/LazyDataTable.js @@ -0,0 +1,43 @@ +import * as R from 'ramda'; +import React, { Component } from 'react'; + +import RealTable from 'dash-table/components/Table'; + +import Logger from 'core/Logger'; + +import genRandomId from 'dash-table/utils/generate'; +import isValidProps from './validate'; +import Sanitizer from './Sanitizer'; +import { defaultProps, propTypes } from 'dash-table/dash/DataTable'; + +/** + * Dash DataTable is an interactive table component designed for + * designed for viewing, editing, and exploring large datasets. + * DataTable is rendered with standard, semantic HTML
markup, + * which makes it accessible, responsive, and easy to style. This + * component was written from scratch in React.js specifically for the + * Dash community. Its API was designed to be ergonomic and its behavior + * is completely customizable through its properties. + */ +export default class DataTable extends Component { + constructor(props) { + super(props); + let id; + this.getId = () => (id = id || genRandomId('table-')); + this.sanitizer = new Sanitizer(); + } + + render() { + if (!isValidProps(this.props)) { + return (
Invalid props combination
); + } + + const sanitizedProps = this.sanitizer.sanitize(this.props); + return this.props.id ? + () : + (); + } +} + +DataTable.defaultProps = defaultProps; +DataTable.propTypes = propTypes; From b931f02b9b2f886fa186badadcf14c0ceb50177b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 22 Aug 2019 17:33:06 -0400 Subject: [PATCH 02/41] clean up --- .config/webpack/base.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/.config/webpack/base.js b/.config/webpack/base.js index d1525236f..4f14aa5f4 100644 --- a/.config/webpack/base.js +++ b/.config/webpack/base.js @@ -12,8 +12,6 @@ const dashLibraryName = packagejson.name.replace(/-/g, '_'); module.exports = (options = {}) => { const babel = options.babel || undefined; const preprocessor = basePreprocessing(options.preprocessor); - console.log('*********************'); - console.log(preprocessor); const mode = options.mode || 'development'; const ts = options.ts || {}; From 2a1d90afbebeddce445a34f0310d25d4c4ca5453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 22 Aug 2019 17:39:04 -0400 Subject: [PATCH 03/41] clean up --- src/dash-table/components/Export/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dash-table/components/Export/index.tsx b/src/dash-table/components/Export/index.tsx index b92828285..f0a0d1314 100644 --- a/src/dash-table/components/Export/index.tsx +++ b/src/dash-table/components/Export/index.tsx @@ -34,7 +34,6 @@ export default React.memo((props: IExportButtonProps) => { } }; - console.log('hello'); return (
{!isFormatSupported ? null : ( From f26b1395ac78d2339c5e37059246a046536b0c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 22 Aug 2019 17:45:15 -0400 Subject: [PATCH 04/41] dev/test - don't use the dash plugin --- webpack.dev.config.js | 5 ++++- webpack.test.config.js | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/webpack.dev.config.js b/webpack.dev.config.js index 856ff0cb0..e9b24747f 100644 --- a/webpack.dev.config.js +++ b/webpack.dev.config.js @@ -5,4 +5,7 @@ const options = { mode: 'development' }; -module.exports = require('./.config/webpack/base.js')(options); \ No newline at end of file +let config = require('./.config/webpack/base.js')(options); +delete config.plugins; + +module.exports = config; \ No newline at end of file diff --git a/webpack.test.config.js b/webpack.test.config.js index cbd73489b..e6f73fc8e 100644 --- a/webpack.test.config.js +++ b/webpack.test.config.js @@ -8,4 +8,7 @@ const options = { mode: 'development' }; -module.exports = require('./.config/webpack/base.js')(options); \ No newline at end of file +let config = require('./.config/webpack/base.js')(options); +delete config.plugins; + +module.exports = config; \ No newline at end of file From 27e8165a3e2d8eeca0acdc2e29364fb8d2cb9445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 23 Aug 2019 12:21:31 -0400 Subject: [PATCH 05/41] tests --- package.json | 4 ++-- src/dash-table/dash/DataTable.js | 2 +- webpack.test.config.js | 1 - webpack.test.standalone.config.js | 4 ++++ 4 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 webpack.test.standalone.config.js diff --git a/package.json b/package.json index df5a3ed43..86e5d3a3a 100644 --- a/package.json +++ b/package.json @@ -15,11 +15,11 @@ "preprivate::opentests": "run-s private::wait*", "preprivate::test.server": "run-s private::wait_dash*", "preprivate::test.standalone": "run-s private::wait_js", - "pretest.standalone": "run-s private::build:js-test", + "pretest.standalone": "run-s private::build:js-test-standalone", "private::build": "node --max_old_space_size=4096 node_modules/webpack/bin/webpack --display-reasons --bail", "private::build:js": "run-s \"private::build -- --mode production\"", - "private::build:js-dev": "run-s \"private::build -- --mode development --config webpack.dev.config.js\"", "private::build:js-test": "run-s \"private::build -- --mode development --config webpack.test.config.js\"", + "private::build:js-test-standalone": "run-s \"private::build -- --mode development --config webpack.test.standalone.config.js\"", "private::build:js-test-watch": "run-s \"private::build -- --mode development --config webpack.test.config.js --watch\"", "private::build:py": "dash-generate-components src/dash-table/dash/DataTable.js dash_table -p package-info.json", "private::host_dash8081": "python tests/cypress/dash/v_be_page.py", diff --git a/src/dash-table/dash/DataTable.js b/src/dash-table/dash/DataTable.js index d1840aed0..73eb8d06d 100644 --- a/src/dash-table/dash/DataTable.js +++ b/src/dash-table/dash/DataTable.js @@ -8,7 +8,7 @@ export default class DataTable extends Component { return ( - + ); } } diff --git a/webpack.test.config.js b/webpack.test.config.js index e6f73fc8e..4d381c983 100644 --- a/webpack.test.config.js +++ b/webpack.test.config.js @@ -9,6 +9,5 @@ const options = { }; let config = require('./.config/webpack/base.js')(options); -delete config.plugins; module.exports = config; \ No newline at end of file diff --git a/webpack.test.standalone.config.js b/webpack.test.standalone.config.js new file mode 100644 index 000000000..5ea554aed --- /dev/null +++ b/webpack.test.standalone.config.js @@ -0,0 +1,4 @@ +let config = require('./webpack.test.config.js'); +delete config.plugins; + +module.exports = config; \ No newline at end of file From 1b512465b4f12575a2af310b98168d0233950965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 23 Aug 2019 12:40:13 -0400 Subject: [PATCH 06/41] visual tests --- .storybook/webpack.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js index 1da256ced..6b184c710 100644 --- a/.storybook/webpack.config.js +++ b/.storybook/webpack.config.js @@ -4,5 +4,6 @@ let config = require('./../.config/webpack/base.js')({ }); config.externals = {}; +delete config.plugins; module.exports = config; \ No newline at end of file From b3311b81897003a2401b547bf3004573fed3f94d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 23 Aug 2019 13:17:09 -0400 Subject: [PATCH 07/41] unit tests --- src/dash-table/components/Export/utils.tsx | 4 +- tests/cypress/tests/unit/exportUtils_tests.ts | 48 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/dash-table/components/Export/utils.tsx b/src/dash-table/components/Export/utils.tsx index 9198695cb..cd1a5daa6 100644 --- a/src/dash-table/components/Export/utils.tsx +++ b/src/dash-table/components/Export/utils.tsx @@ -6,7 +6,7 @@ interface IMergeObject { e: {r: number, c: number}; } -function transformMultiDimArray(array: (string | string[])[], maxLength: number): string[][] { +export function transformMultiDimArray(array: (string | string[])[], maxLength: number): string[][] { const newArray: string[][] = array.map(row => { if (row instanceof Array && row.length < maxLength) { return row.concat(Array(maxLength - row.length).fill('')); @@ -22,7 +22,7 @@ function transformMultiDimArray(array: (string | string[])[], maxLength: number) return newArray; } -function getMergeRanges(array: string[][]) { +export function getMergeRanges(array: string[][]) { let apiMergeArray: IMergeObject[] = []; const iForEachOuter = R.addIndex<(string[]), void>(R.forEach); const iForEachInner = R.addIndex<(string), void>(R.forEach); diff --git a/tests/cypress/tests/unit/exportUtils_tests.ts b/tests/cypress/tests/unit/exportUtils_tests.ts index e635cfb19..57b163a17 100644 --- a/tests/cypress/tests/unit/exportUtils_tests.ts +++ b/tests/cypress/tests/unit/exportUtils_tests.ts @@ -1,44 +1,44 @@ -import { transformMultDimArray, getMergeRanges, createHeadings, createWorksheet } from 'dash-table/components/Export/utils'; +import { transformMultiDimArray, getMergeRanges, createHeadings, createWorkbook } from 'dash-table/components/Export/utils'; import * as R from 'ramda'; describe('export', () => { - describe('transformMultDimArray', () => { + describe('transformMultiDimArray', () => { it('array with only strings', () => { const testedArray = []; - const transformedArray = transformMultDimArray(testedArray, 0); + const transformedArray = transformMultiDimArray(testedArray, 0); const expectedArray = []; expect(transformedArray).to.deep.equal(expectedArray); }); it('array with only strings', () => { const testedArray = ['a', 'b', 'c', 'd']; - const transformedArray = transformMultDimArray(testedArray, 0); + const transformedArray = transformMultiDimArray(testedArray, 0); const expectedArray = [['a'], ['b'], ['c'], ['d']]; expect(transformedArray).to.deep.equal(expectedArray); }); it ('array with strings and strings array with same length', () => { const testedArray = ['a', ['b', 'c'], ['b', 'd']]; - const transformedArray = transformMultDimArray(testedArray, 2); + const transformedArray = transformMultiDimArray(testedArray, 2); const expectedArray = [['a', 'a'], ['b', 'c'], ['b', 'd']]; expect(transformedArray).to.deep.equal(expectedArray); }); it ('2D strings array', () => { const testedArray = [['a', 'b', 'c'], ['b', 'c', 'd'], ['b', 'd', 'a']]; - const transformedArray = transformMultDimArray(testedArray, 3); + const transformedArray = transformMultiDimArray(testedArray, 3); const expectedArray = [['a', 'b', 'c'], ['b', 'c', 'd'], ['b', 'd', 'a']]; expect(transformedArray).to.deep.equal(expectedArray); }); it ('multidimensional array', () => { const testedArray = [['a', 'b'], ['b', 'c', 'd'], ['a', 'b', 'd', 'a']]; - const transformedArray = transformMultDimArray(testedArray, 4); + const transformedArray = transformMultiDimArray(testedArray, 4); const expectedArray = [['a', 'b', '', ''], ['b', 'c', 'd', ''], ['a', 'b', 'd', 'a']]; expect(transformedArray).to.deep.equal(expectedArray); }); it ('multidimensional array with strings', () => { const testedArray = ['rows', ['a', 'b'], ['b', 'c', 'd'], ['a', 'b', 'd', 'a']]; - const transformedArray = transformMultDimArray(testedArray, 4); + const transformedArray = transformMultiDimArray(testedArray, 4); const expectedArray = [['rows', 'rows', 'rows', 'rows'], ['a', 'b', '', ''], ['b', 'c', 'd', ''], ['a', 'b', 'd', 'a']]; expect(transformedArray).to.deep.equal(expectedArray); }); @@ -220,10 +220,10 @@ describe('export', () => { {col1: 1, col2: 2, col3: 3} ]; const columnID = ['col1', 'col2', 'col3']; - it('create sheet with column names as headers for name or display header mode', () => { - const wsName = createWorksheet(Headings, data, columnID, 'names', true); - const wsDisplay = createWorksheet(Headings, data, columnID, 'display', true); - const wsDisplayNoMerge = createWorksheet(Headings, data, columnID, 'display', false); + it('create sheet with column names as headers for name or display header mode', async () => { + const wsName = await createWorkbook(Headings, data, columnID, 'names', true); + const wsDisplay = await createWorkbook(Headings, data, columnID, 'display', true); + const wsDisplayNoMerge = await createWorkbook(Headings, data, columnID, 'display', false); const expectedWS = { A1: {t: 's', v: 'rows'}, A2: {t: 's', v: 'rows'}, @@ -251,12 +251,12 @@ describe('export', () => { expectedWSDisplay['!merges'] = [ {s: {r: 0, c: 0}, e: {r: 0, c: 1}}, {s: {r: 1, c: 1}, e: {r: 1, c: 2}}, {s: {r: 3, c: 0}, e: {r: 3, c: 2}} ]; - expect(wsName).to.deep.equal(expectedWS); - expect(wsDisplayNoMerge).to.deep.equal(expectedWS); - expect(wsDisplay).to.deep.equal(expectedWSDisplay); + expect(wsName.Sheets.SheetJS).to.deep.equal(expectedWS); + expect(wsDisplayNoMerge.Sheets.SheetJS).to.deep.equal(expectedWS); + expect(wsDisplay.Sheets.SheetJS).to.deep.equal(expectedWSDisplay); }); - it('create sheet with column ids as headers', () => { - const ws = createWorksheet(Headings, data, columnID, 'ids', true); + it('create sheet with column ids as headers', async () => { + const ws = await createWorkbook(Headings, data, columnID, 'ids', true); const expectedWS = { A1: {t: 's', v: 'col1'}, A2: {t: 'n', v: 1}, @@ -271,10 +271,10 @@ describe('export', () => { C3: {t: 'n', v: 4}, C4: {t: 'n', v: 3}}; expectedWS['!ref'] = 'A1:C4'; - expect(ws).to.deep.equal(expectedWS); + expect(ws.Sheets.SheetJS).to.deep.equal(expectedWS); }); - it('create sheet with no headers', () => { - const ws = createWorksheet([], data, columnID, 'none', true); + it('create sheet with no headers', async () => { + const ws = await createWorkbook([], data, columnID, 'none', true); const expectedWS = { A1: {t: 'n', v: 1}, A2: {t: 'n', v: 2}, @@ -286,15 +286,15 @@ describe('export', () => { C2: {t: 'n', v: 4}, C3: {t: 'n', v: 3}}; expectedWS['!ref'] = 'A1:C3'; - expect(ws).to.deep.equal(expectedWS); + expect(ws.Sheets.SheetJS).to.deep.equal(expectedWS); }); - it('create sheet with undefined column for clearable columns', () => { + it('create sheet with undefined column for clearable columns', async () => { const newData = [ {col2: 2, col3: 3}, {col2: 3, col3: 4}, {col2: 2, col3: 3} ]; - const ws = createWorksheet(Headings, newData, columnID, 'display', false); + const ws = await createWorkbook(Headings, newData, columnID, 'display', false); const expectedWS = {A1: {t: 's', v: 'rows'}, A2: {t: 's', v: 'rows'}, A3: {t: 's', v: 'rows'}, @@ -314,7 +314,7 @@ describe('export', () => { C6: {t: 'n', v: 4}, C7: {t: 'n', v: 3}}; expectedWS['!ref'] = 'A1:C7'; - expect(ws).to.deep.equal(expectedWS); + expect(ws.Sheets.SheetJS).to.deep.equal(expectedWS); }); }); From 82e1f379bfd07aaecd8e5f544f4f18e2a09ea408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 23 Aug 2019 13:59:32 -0400 Subject: [PATCH 08/41] unit test --- tests/cypress/tests/unit/exportUtils_tests.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/cypress/tests/unit/exportUtils_tests.ts b/tests/cypress/tests/unit/exportUtils_tests.ts index 57b163a17..03afefef6 100644 --- a/tests/cypress/tests/unit/exportUtils_tests.ts +++ b/tests/cypress/tests/unit/exportUtils_tests.ts @@ -1,6 +1,8 @@ -import { transformMultiDimArray, getMergeRanges, createHeadings, createWorkbook } from 'dash-table/components/Export/utils'; +import 'xlsx'; import * as R from 'ramda'; +import { transformMultiDimArray, getMergeRanges, createHeadings, createWorkbook } from 'dash-table/components/Export/utils'; + describe('export', () => { describe('transformMultiDimArray', () => { From 6b53f6d2d88c33eac2c9b14796e8e201db6b8368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 23 Aug 2019 14:04:44 -0400 Subject: [PATCH 09/41] unit tests --- tests/cypress/plugins/index.js | 2 +- tests/cypress/tests/unit/exportUtils_tests.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/cypress/plugins/index.js b/tests/cypress/plugins/index.js index a943f34c3..9c2541b07 100644 --- a/tests/cypress/plugins/index.js +++ b/tests/cypress/plugins/index.js @@ -2,7 +2,7 @@ const wp = require('@cypress/webpack-preprocessor'); module.exports = on => { const options = { - webpackOptions: require('../../../webpack.test.config.js') + webpackOptions: require('../../../webpack.test.standalone.config.js') }; on('file:preprocessor', wp(options)); diff --git a/tests/cypress/tests/unit/exportUtils_tests.ts b/tests/cypress/tests/unit/exportUtils_tests.ts index 03afefef6..95f7862bd 100644 --- a/tests/cypress/tests/unit/exportUtils_tests.ts +++ b/tests/cypress/tests/unit/exportUtils_tests.ts @@ -1,4 +1,3 @@ -import 'xlsx'; import * as R from 'ramda'; import { transformMultiDimArray, getMergeRanges, createHeadings, createWorkbook } from 'dash-table/components/Export/utils'; From 726ebab199a82e71cea207003267e25d9695f6bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 23 Aug 2019 14:30:35 -0400 Subject: [PATCH 10/41] webpackMode for async chunks --- .config/webpack/base.preprocessing.js | 2 +- src/dash-table/components/Export/index.tsx | 2 +- src/dash-table/components/Export/utils.tsx | 2 +- src/dash-table/dash/DataTable.js | 2 +- webpack.test.standalone.config.js | 15 ++++++++++++++- 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/.config/webpack/base.preprocessing.js b/.config/webpack/base.preprocessing.js index fdd1a0114..84323524a 100644 --- a/.config/webpack/base.preprocessing.js +++ b/.config/webpack/base.preprocessing.js @@ -2,6 +2,6 @@ module.exports = ({ definitions, variables, ...options } = {}) => ({ ...options, definitions: definitions || [], variables: Object.assign({ - + mode: 'lazy' }, variables || {}) }); \ No newline at end of file diff --git a/src/dash-table/components/Export/index.tsx b/src/dash-table/components/Export/index.tsx index f0a0d1314..1027e2dab 100644 --- a/src/dash-table/components/Export/index.tsx +++ b/src/dash-table/components/Export/index.tsx @@ -18,7 +18,7 @@ export default React.memo((props: IExportButtonProps) => { const isFormatSupported = export_format === 'csv' || export_format === 'xlsx'; const handleExport = async () => { - const XLSX = await import(/* webpackChunkName: "export" */ 'xlsx'); + const XLSX = await import(/* webpackChunkName: "export", webpackMode: "$${{mode}}" */ 'xlsx'); const columnID = visibleColumns.map(column => column.id); const columnHeaders = visibleColumns.map(column => column.name); diff --git a/src/dash-table/components/Export/utils.tsx b/src/dash-table/components/Export/utils.tsx index cd1a5daa6..12efa835b 100644 --- a/src/dash-table/components/Export/utils.tsx +++ b/src/dash-table/components/Export/utils.tsx @@ -47,7 +47,7 @@ export function getMergeRanges(array: string[][]) { } export async function createWorkbook(heading: string[][], data: Data, columnID: string[], exportHeader: string, mergeDuplicateHeaders: boolean) { - const XLSX = await import(/* webpackChunkName: "export" */ 'xlsx'); + const XLSX = await import(/* webpackChunkName: "export", webpackMode: "$${{mode}}" */ 'xlsx'); const ws = XLSX.utils.aoa_to_sheet(heading); if (exportHeader === 'display' || exportHeader === 'names' || exportHeader === 'none') { diff --git a/src/dash-table/dash/DataTable.js b/src/dash-table/dash/DataTable.js index 73eb8d06d..387247b24 100644 --- a/src/dash-table/dash/DataTable.js +++ b/src/dash-table/dash/DataTable.js @@ -1,7 +1,7 @@ import React, { Component, Suspense, lazy } from 'react'; import PropTypes from 'prop-types'; -const LazyDataTable = lazy(() => import(/* webpackChunkName: "dash-table" */ 'dash-table/dash/LazyDataTable')); +const LazyDataTable = lazy(() => import(/* webpackChunkName: "dash-table", webpackMode: "$${{mode}}" */ 'dash-table/dash/LazyDataTable')); export default class DataTable extends Component { render() { diff --git a/webpack.test.standalone.config.js b/webpack.test.standalone.config.js index 5ea554aed..67f2d692d 100644 --- a/webpack.test.standalone.config.js +++ b/webpack.test.standalone.config.js @@ -1,4 +1,17 @@ -let config = require('./webpack.test.config.js'); +const options = { + ts: { + transpileOnly: true + }, + preprocessor: { + variables: { + mode: 'eager' + }, + definitions: ['TEST', 'TEST_COPY_PASTE'] + }, + mode: 'development' +}; + +let config = require('./.config/webpack/base.js')(options); delete config.plugins; module.exports = config; \ No newline at end of file From 24514f8cbc69f58cce5f001da2469ed03a4a9905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 23 Aug 2019 14:40:55 -0400 Subject: [PATCH 11/41] update storybook config --- .storybook/webpack.config.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js index 6b184c710..ae78b43c1 100644 --- a/.storybook/webpack.config.js +++ b/.storybook/webpack.config.js @@ -1,9 +1,13 @@ let babel = require('./babel.config.js'); let config = require('./../.config/webpack/base.js')({ - babel + babel, + preprocessor: { + variables: { + mode: 'eager' + } + } }); config.externals = {}; -delete config.plugins; module.exports = config; \ No newline at end of file From e8f038df63f4d6f7fcaf602e49a3ad5ec8bd0100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 23 Aug 2019 14:50:50 -0400 Subject: [PATCH 12/41] storybook --- .storybook/webpack.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js index ae78b43c1..c9239abe9 100644 --- a/.storybook/webpack.config.js +++ b/.storybook/webpack.config.js @@ -9,5 +9,6 @@ let config = require('./../.config/webpack/base.js')({ }); config.externals = {}; +delete config.plugins; module.exports = config; \ No newline at end of file From 4af76194dea764480bb461d6598f15df1998afb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 23 Aug 2019 15:06:08 -0400 Subject: [PATCH 13/41] use plugin repo instead of experiment --- .config/webpack/base.js | 2 +- ...experimental-dash-dynamic-import-plugin.js | 25 ------------------- package.json | 1 + 3 files changed, 2 insertions(+), 26 deletions(-) delete mode 100644 .config/webpack/experimental-dash-dynamic-import-plugin.js diff --git a/.config/webpack/base.js b/.config/webpack/base.js index 4f14aa5f4..cb6840437 100644 --- a/.config/webpack/base.js +++ b/.config/webpack/base.js @@ -1,7 +1,7 @@ const path = require('path'); const webpack = require('webpack'); -const WebpackDashDynamicImport = require("./experimental-dash-dynamic-import-plugin"); +const WebpackDashDynamicImport = require('webpack-dash-dynamic-import'); const basePreprocessing = require('./base.preprocessing'); const packagejson = require('./../../package.json'); diff --git a/.config/webpack/experimental-dash-dynamic-import-plugin.js b/.config/webpack/experimental-dash-dynamic-import-plugin.js deleted file mode 100644 index 41add4252..000000000 --- a/.config/webpack/experimental-dash-dynamic-import-plugin.js +++ /dev/null @@ -1,25 +0,0 @@ -const resolveImportSource = `\ -Object.defineProperty(__webpack_require__, 'p', { - get: (function () { - var url = Array.from(document.getElementsByTagName('script')).slice(-1)[0].src.split('/').slice(0, -1).join('/') + '/'; - - return function() { - return url; - }; - })() -});` - -class WebpackDashDynamicImport { - apply(compiler) { - compiler.hooks.compilation.tap('WebpackDashDynamicImport', compilation => { - compilation.mainTemplate.hooks.requireExtensions.tap('WebpackDashDynamicImport > RequireExtensions', (source, chunk, hash) => { - return [ - source, - resolveImportSource - ] - }); - }); - } -} - -module.exports = WebpackDashDynamicImport; \ No newline at end of file diff --git a/package.json b/package.json index 86e5d3a3a..9f4513282 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,7 @@ "wait-on": "^3.3.0", "webpack": "^4.37.0", "webpack-cli": "^3.3.6", + "webpack-dash-dynamic-import": "github:plotly/webpack-dash-dynamic-import", "webpack-dev-server": "^3.7.2", "webpack-preprocessor": "^0.1.12", "xlsx": "^0.14.4" From c97ab9852bd8dde51f5194712f54459b1d1de157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 23 Aug 2019 15:08:47 -0400 Subject: [PATCH 14/41] clean up --- .config/webpack/base.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/.config/webpack/base.js b/.config/webpack/base.js index cb6840437..2b9e072f7 100644 --- a/.config/webpack/base.js +++ b/.config/webpack/base.js @@ -1,6 +1,4 @@ - const path = require('path'); -const webpack = require('webpack'); const WebpackDashDynamicImport = require('webpack-dash-dynamic-import'); const basePreprocessing = require('./base.preprocessing'); From e3d0fbcdeaa899ff2f8b574983184a2c4d91b619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Mon, 26 Aug 2019 13:14:16 -0400 Subject: [PATCH 15/41] clean up xlsx usage --- src/dash-table/components/Export/index.tsx | 10 ++-------- src/dash-table/components/Export/utils.tsx | 11 +++++++++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/dash-table/components/Export/index.tsx b/src/dash-table/components/Export/index.tsx index 1027e2dab..117a1214d 100644 --- a/src/dash-table/components/Export/index.tsx +++ b/src/dash-table/components/Export/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { IDerivedData, Columns } from 'dash-table/components/Table/props'; -import { createWorkbook, createHeadings } from './utils'; +import { createWorkbook, createHeadings, exportWorkbook } from './utils'; import getHeaderRows from 'dash-table/derived/header/headerRows'; interface IExportButtonProps { @@ -18,8 +18,6 @@ export default React.memo((props: IExportButtonProps) => { const isFormatSupported = export_format === 'csv' || export_format === 'xlsx'; const handleExport = async () => { - const XLSX = await import(/* webpackChunkName: "export", webpackMode: "$${{mode}}" */ 'xlsx'); - const columnID = visibleColumns.map(column => column.id); const columnHeaders = visibleColumns.map(column => column.name); const maxLength = getHeaderRows(columns); @@ -27,11 +25,7 @@ export default React.memo((props: IExportButtonProps) => { const wb = await createWorkbook(heading, virtual_data.data, columnID, export_headers, merge_duplicate_headers); - if (export_format === 'xlsx') { - XLSX.writeFile(wb, 'Data.xlsx', {bookType: 'xlsx', type: 'buffer'}); - } else if (export_format === 'csv') { - XLSX.writeFile(wb, 'Data.csv', {bookType: 'csv', type: 'buffer'}); - } + await exportWorkbook(wb, export_format); }; return (
diff --git a/src/dash-table/components/Export/utils.tsx b/src/dash-table/components/Export/utils.tsx index 12efa835b..1c3b657ea 100644 --- a/src/dash-table/components/Export/utils.tsx +++ b/src/dash-table/components/Export/utils.tsx @@ -1,5 +1,6 @@ import * as R from 'ramda'; import { Data } from 'dash-table/components/Table/props'; +import { WorkBook } from 'xlsx/types'; interface IMergeObject { s: {r: number, c: number}; @@ -68,6 +69,16 @@ export async function createWorkbook(heading: string[][], data: Data, columnID: return wb; } +export async function exportWorkbook (wb: WorkBook, format: string) { + const XLSX = await import(/* webpackChunkName: "export", webpackMode: "$${{mode}}" */ 'xlsx'); + + if (format === 'xlsx') { + XLSX.writeFile(wb, 'Data.xlsx', { bookType: 'xlsx', type: 'buffer' }); + } else if (format === 'csv') { + XLSX.writeFile(wb, 'Data.csv', { bookType: 'csv', type: 'buffer' }); + } +} + export function createHeadings(columnHeaders: (string | string[])[], maxLength: number) { const transformedArray = transformMultiDimArray(columnHeaders, maxLength); return R.transpose(transformedArray); From dbcdb31b13d934e5c0f22015005e765b53905dfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Mon, 26 Aug 2019 13:49:29 -0400 Subject: [PATCH 16/41] abstract lazy load --- src/dash-table/LazyLoader.ts | 9 +++++++++ src/dash-table/components/Export/utils.tsx | 8 +++++--- src/dash-table/dash/DataTable.js | 3 ++- 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 src/dash-table/LazyLoader.ts diff --git a/src/dash-table/LazyLoader.ts b/src/dash-table/LazyLoader.ts new file mode 100644 index 000000000..2bbf14bec --- /dev/null +++ b/src/dash-table/LazyLoader.ts @@ -0,0 +1,9 @@ +export default class LazyLoader { + public static get dataTable() { + return import(/* webpackChunkName: "dash-table", webpackMode: "$${{mode}}" */ 'dash-table/dash/LazyDataTable'); + } + + public static get xlsx() { + return import(/* webpackChunkName: "export", webpackMode: "$${{mode}}" */ 'xlsx'); + } +} \ No newline at end of file diff --git a/src/dash-table/components/Export/utils.tsx b/src/dash-table/components/Export/utils.tsx index 1c3b657ea..95621298a 100644 --- a/src/dash-table/components/Export/utils.tsx +++ b/src/dash-table/components/Export/utils.tsx @@ -1,7 +1,9 @@ import * as R from 'ramda'; -import { Data } from 'dash-table/components/Table/props'; import { WorkBook } from 'xlsx/types'; +import { Data } from 'dash-table/components/Table/props'; +import LazyLoader from 'dash-table/LazyLoader'; + interface IMergeObject { s: {r: number, c: number}; e: {r: number, c: number}; @@ -48,7 +50,7 @@ export function getMergeRanges(array: string[][]) { } export async function createWorkbook(heading: string[][], data: Data, columnID: string[], exportHeader: string, mergeDuplicateHeaders: boolean) { - const XLSX = await import(/* webpackChunkName: "export", webpackMode: "$${{mode}}" */ 'xlsx'); + const XLSX = await LazyLoader.xlsx; const ws = XLSX.utils.aoa_to_sheet(heading); if (exportHeader === 'display' || exportHeader === 'names' || exportHeader === 'none') { @@ -70,7 +72,7 @@ export async function createWorkbook(heading: string[][], data: Data, columnID: } export async function exportWorkbook (wb: WorkBook, format: string) { - const XLSX = await import(/* webpackChunkName: "export", webpackMode: "$${{mode}}" */ 'xlsx'); + const XLSX = await LazyLoader.xlsx; if (format === 'xlsx') { XLSX.writeFile(wb, 'Data.xlsx', { bookType: 'xlsx', type: 'buffer' }); diff --git a/src/dash-table/dash/DataTable.js b/src/dash-table/dash/DataTable.js index 387247b24..5bbb1a6db 100644 --- a/src/dash-table/dash/DataTable.js +++ b/src/dash-table/dash/DataTable.js @@ -1,7 +1,8 @@ import React, { Component, Suspense, lazy } from 'react'; import PropTypes from 'prop-types'; +import LazyLoader from 'dash-table/LazyLoader'; -const LazyDataTable = lazy(() => import(/* webpackChunkName: "dash-table", webpackMode: "$${{mode}}" */ 'dash-table/dash/LazyDataTable')); +const LazyDataTable = lazy(() => LazyLoader.dataTable); export default class DataTable extends Component { render() { From 84528dd98e85c2cc3f496cab1a0ecdedb16fa3d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Wed, 28 Aug 2019 15:02:02 -0400 Subject: [PATCH 17/41] async~* in manifest --- MANIFEST.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MANIFEST.in b/MANIFEST.in index efff6afda..3201355c4 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,7 @@ include dash_table/bundle.js include dash_table/bundle.js.map +include dash_table/async~*.js +include dash_table/async~*.js.map include dash_table/metadata.json include dash_table/package-info.json include LICENSE From e769eed80604c8d6497864ae973cfd70a624e9dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 29 Aug 2019 16:28:48 -0400 Subject: [PATCH 18/41] Instrumented lazy loading --- src/dash-table/dash/DataTable.js | 25 ++++++++++++-------- src/dash-table/dash/LazyFactory.ts | 37 ++++++++++++++++++++++++++++++ tsconfig.base.json | 2 +- 3 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 src/dash-table/dash/LazyFactory.ts diff --git a/src/dash-table/dash/DataTable.js b/src/dash-table/dash/DataTable.js index 5bbb1a6db..d10aba05f 100644 --- a/src/dash-table/dash/DataTable.js +++ b/src/dash-table/dash/DataTable.js @@ -1,19 +1,26 @@ import React, { Component, Suspense, lazy } from 'react'; import PropTypes from 'prop-types'; import LazyLoader from 'dash-table/LazyLoader'; +import LazyFactory from './LazyFactory'; -const LazyDataTable = lazy(() => LazyLoader.dataTable); +const LazyDataTable = LazyFactory(DataTable, () => LazyLoader.dataTable); -export default class DataTable extends Component { - render() { - return ( - - ); - } +function DataTable(props) { + return ( + + ); } +if (DataTable._dashprivate_isLazyComponentReady) { + Promise.resolve(DataTable._dashprivate_isLazyComponentReady).then(() => { + console.log('LazyDataTable ready', LazyDataTable); + }); +} + +export default DataTable; + export const defaultProps = { page_action: 'native', page_current: 0, diff --git a/src/dash-table/dash/LazyFactory.ts b/src/dash-table/dash/LazyFactory.ts new file mode 100644 index 000000000..83175f0da --- /dev/null +++ b/src/dash-table/dash/LazyFactory.ts @@ -0,0 +1,37 @@ +import { lazy } from 'react'; + +type Boolean = Promise | boolean; +type LazyComponent = React.LazyExoticComponent>; + +interface IResult { + isReady: Boolean, + get: LazyComponent +} + +export default ( + target: () => JSX.Element, + promise: () => Promise<{ default: React.ComponentType }> +): LazyComponent => { + let resolve: (value: Boolean) => void; + let isReady = new Promise(r => { + resolve = r; + }); + + const state: IResult = { + isReady, + get: lazy(async () => { + const component = await promise(); + + await resolve(true); + state.isReady = true; + + return component; + }) + }; + + Object.defineProperty(target, '_dashprivate_isLazyComponentReady', { + get: () => state.isReady + }); + + return state.get; +} \ No newline at end of file diff --git a/tsconfig.base.json b/tsconfig.base.json index 9b6cfed5b..00915963c 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -5,7 +5,7 @@ "emitDecoratorMetadata": false, "experimentalDecorators": true, "jsx": "react", - "lib": ["esnext", "dom"], + "lib": ["esnext", "dom", "es2018.promise"], "module": "esnext", "moduleResolution": "node", "noImplicitAny": true, From dca40d068ed5fd8d40fa099e1ade524686175f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 30 Aug 2019 14:29:40 -0400 Subject: [PATCH 19/41] clean up --- .circleci/config.yml | 6 +++--- src/dash-table/dash/DataTable.js | 8 +------- src/dash-table/dash/LazyFactory.ts | 17 ++++++++++++----- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bb8619ee5..92ffd8e4e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,7 +31,7 @@ jobs: python -m venv venv || virtualenv venv . venv/bin/activate pip install -r dev-requirements.txt --quiet - git clone --depth 1 git@github.com:plotly/dash.git dash-main + git clone --depth 1 -b exp-dynamic git@github.com:plotly/dash.git dash-main pip install -e ./dash-main[dev] --quiet - run: @@ -107,7 +107,7 @@ jobs: python -m venv venv || virtualenv venv . venv/bin/activate pip install -r dev-requirements.txt --quiet - git clone --depth 1 git@github.com:plotly/dash.git dash-main + git clone --depth 1 -b exp-dynamic git@github.com:plotly/dash.git dash-main pip install -e ./dash-main[dev] --quiet - run: @@ -211,7 +211,7 @@ jobs: name: Install dependencies (dash) command: | . venv/bin/activate - git clone --depth 1 git@github.com:plotly/dash.git dash-main + git clone --depth 1 -b exp-dynamic git@github.com:plotly/dash.git dash-main pip install -e ./dash-main[dev,testing] --quiet cd dash-main/dash-renderer && npm run build && pip install -e . && cd ../.. diff --git a/src/dash-table/dash/DataTable.js b/src/dash-table/dash/DataTable.js index d10aba05f..30b0ad63f 100644 --- a/src/dash-table/dash/DataTable.js +++ b/src/dash-table/dash/DataTable.js @@ -1,4 +1,4 @@ -import React, { Component, Suspense, lazy } from 'react'; +import React, { Component, Suspense } from 'react'; import PropTypes from 'prop-types'; import LazyLoader from 'dash-table/LazyLoader'; import LazyFactory from './LazyFactory'; @@ -13,12 +13,6 @@ function DataTable(props) { ); } -if (DataTable._dashprivate_isLazyComponentReady) { - Promise.resolve(DataTable._dashprivate_isLazyComponentReady).then(() => { - console.log('LazyDataTable ready', LazyDataTable); - }); -} - export default DataTable; export const defaultProps = { diff --git a/src/dash-table/dash/LazyFactory.ts b/src/dash-table/dash/LazyFactory.ts index 83175f0da..eec5ed3c6 100644 --- a/src/dash-table/dash/LazyFactory.ts +++ b/src/dash-table/dash/LazyFactory.ts @@ -13,19 +13,26 @@ export default ( promise: () => Promise<{ default: React.ComponentType }> ): LazyComponent => { let resolve: (value: Boolean) => void; - let isReady = new Promise(r => { + const isReady = new Promise(r => { resolve = r; }); const state: IResult = { isReady, get: lazy(async () => { - const component = await promise(); + // let __r: any; + // const p = new Promise(_r => __r = _r); + // setTimeout(() => __r(), 10000); - await resolve(true); - state.isReady = true; + // await p; - return component; + // delay `isReady` + setTimeout(async () => { + await resolve(true); + state.isReady = true; + }, 0); + + return await promise(); }) }; From 815f6e2f713742edaad238b108760dc3f64bff79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 30 Aug 2019 15:25:48 -0400 Subject: [PATCH 20/41] update lazy factory ordering --- src/dash-table/dash/LazyFactory.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dash-table/dash/LazyFactory.ts b/src/dash-table/dash/LazyFactory.ts index eec5ed3c6..7105f1c7a 100644 --- a/src/dash-table/dash/LazyFactory.ts +++ b/src/dash-table/dash/LazyFactory.ts @@ -20,6 +20,7 @@ export default ( const state: IResult = { isReady, get: lazy(async () => { + const res = await promise(); // let __r: any; // const p = new Promise(_r => __r = _r); // setTimeout(() => __r(), 10000); @@ -32,7 +33,7 @@ export default ( state.isReady = true; }, 0); - return await promise(); + return res; }) }; From e1aefca87c98853cf0ca08bba84953a956fc098d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 30 Aug 2019 15:31:44 -0400 Subject: [PATCH 21/41] lint --- src/dash-table/dash/LazyFactory.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dash-table/dash/LazyFactory.ts b/src/dash-table/dash/LazyFactory.ts index 7105f1c7a..ccb0651b4 100644 --- a/src/dash-table/dash/LazyFactory.ts +++ b/src/dash-table/dash/LazyFactory.ts @@ -4,8 +4,8 @@ type Boolean = Promise | boolean; type LazyComponent = React.LazyExoticComponent>; interface IResult { - isReady: Boolean, - get: LazyComponent + isReady: Boolean; + get: LazyComponent; } export default ( @@ -42,4 +42,4 @@ export default ( }); return state.get; -} \ No newline at end of file +}; \ No newline at end of file From 1833bc8d5ef978018e34a753fb9cbab9a32b30a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Tue, 17 Sep 2019 19:27:25 -0400 Subject: [PATCH 22/41] update tests --- tests/visual/percy-storybook/Border.defaults.percy.tsx | 2 +- tests/visual/percy-storybook/Border.style.percy.tsx | 2 +- tests/visual/percy-storybook/DashTable.percy.tsx | 2 +- tests/visual/percy-storybook/Dropdown.percy.tsx | 2 +- tests/visual/percy-storybook/Filters.percy.tsx | 2 +- tests/visual/percy-storybook/Header.actions.percy.tsx | 2 +- tests/visual/percy-storybook/Header.percy.tsx | 2 +- tests/visual/percy-storybook/Hideable.percy.tsx | 2 +- tests/visual/percy-storybook/LoadingState.percy.tsx | 4 +--- tests/visual/percy-storybook/Sizing.percy.tsx | 2 +- tests/visual/percy-storybook/Style.percy.tsx | 2 +- tests/visual/percy-storybook/TriadValidation.percy.tsx | 2 +- tests/visual/percy-storybook/Virtualization.percy.tsx | 2 +- tests/visual/percy-storybook/Width.all.percy.tsx | 2 +- tests/visual/percy-storybook/Width.defaults.percy.tsx | 2 +- tests/visual/percy-storybook/Width.empty.percy.tsx | 2 +- tests/visual/percy-storybook/Width.max.percy.tsx | 2 +- tests/visual/percy-storybook/Width.min.percy.tsx | 2 +- tests/visual/percy-storybook/Width.percentages.percy.tsx | 3 ++- tests/visual/percy-storybook/Width.width.percy.tsx | 2 +- 20 files changed, 21 insertions(+), 22 deletions(-) diff --git a/tests/visual/percy-storybook/Border.defaults.percy.tsx b/tests/visual/percy-storybook/Border.defaults.percy.tsx index bf3e2998c..24cdd3946 100644 --- a/tests/visual/percy-storybook/Border.defaults.percy.tsx +++ b/tests/visual/percy-storybook/Border.defaults.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Border.style.percy.tsx b/tests/visual/percy-storybook/Border.style.percy.tsx index 65687918d..4c038d302 100644 --- a/tests/visual/percy-storybook/Border.style.percy.tsx +++ b/tests/visual/percy-storybook/Border.style.percy.tsx @@ -1,7 +1,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; import { BORDER_PROPS_DEFAULTS } from './Border.defaults.percy'; import { TableAction, SortMode } from 'dash-table/components/Table/props'; diff --git a/tests/visual/percy-storybook/DashTable.percy.tsx b/tests/visual/percy-storybook/DashTable.percy.tsx index 2458a444c..7c78c07ad 100644 --- a/tests/visual/percy-storybook/DashTable.percy.tsx +++ b/tests/visual/percy-storybook/DashTable.percy.tsx @@ -4,7 +4,7 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; import fixtures from './fixtures'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Dropdown.percy.tsx b/tests/visual/percy-storybook/Dropdown.percy.tsx index 7569b4ae3..e6e98b1d0 100644 --- a/tests/visual/percy-storybook/Dropdown.percy.tsx +++ b/tests/visual/percy-storybook/Dropdown.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Filters.percy.tsx b/tests/visual/percy-storybook/Filters.percy.tsx index c551959bc..e46bbada3 100644 --- a/tests/visual/percy-storybook/Filters.percy.tsx +++ b/tests/visual/percy-storybook/Filters.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; import { TableAction } from 'dash-table/components/Table/props'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Header.actions.percy.tsx b/tests/visual/percy-storybook/Header.actions.percy.tsx index 7db9ab188..d449654b5 100644 --- a/tests/visual/percy-storybook/Header.actions.percy.tsx +++ b/tests/visual/percy-storybook/Header.actions.percy.tsx @@ -1,7 +1,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Header.percy.tsx b/tests/visual/percy-storybook/Header.percy.tsx index 1335e0481..35ce17536 100644 --- a/tests/visual/percy-storybook/Header.percy.tsx +++ b/tests/visual/percy-storybook/Header.percy.tsx @@ -1,7 +1,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Hideable.percy.tsx b/tests/visual/percy-storybook/Hideable.percy.tsx index e93fd417e..b56871ad3 100644 --- a/tests/visual/percy-storybook/Hideable.percy.tsx +++ b/tests/visual/percy-storybook/Hideable.percy.tsx @@ -3,7 +3,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; import dataset from './../../assets/gapminder.csv'; const result = parser.parse(dataset, { delimiter: ',', header: true }); diff --git a/tests/visual/percy-storybook/LoadingState.percy.tsx b/tests/visual/percy-storybook/LoadingState.percy.tsx index da8e5b3d5..5caf0952f 100644 --- a/tests/visual/percy-storybook/LoadingState.percy.tsx +++ b/tests/visual/percy-storybook/LoadingState.percy.tsx @@ -2,18 +2,16 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; const setProps = () => { }; - const data = [ { City: 'NYC', Neighborhood: 'Brooklyn', 'Temperature (F)': 70 }, { City: 'Montreal', Neighborhood: 'Mile End', 'Temperature (F)': 60 }, { City: 'Los Angeles', Neighborhood: 'Venice', 'Temperature (F)': 90 } ]; - const columns = R.map( i => ({ name: i, id: i, presentation: 'dropdown' }), ['City', 'Neighborhood', 'Temperature (F)'] diff --git a/tests/visual/percy-storybook/Sizing.percy.tsx b/tests/visual/percy-storybook/Sizing.percy.tsx index c7dd959f6..44a4dcc98 100644 --- a/tests/visual/percy-storybook/Sizing.percy.tsx +++ b/tests/visual/percy-storybook/Sizing.percy.tsx @@ -1,7 +1,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Style.percy.tsx b/tests/visual/percy-storybook/Style.percy.tsx index 0c76a64fb..7bcd53555 100644 --- a/tests/visual/percy-storybook/Style.percy.tsx +++ b/tests/visual/percy-storybook/Style.percy.tsx @@ -1,7 +1,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; import { ColumnType } from 'dash-table/components/Table/props'; import { generateMockData } from '../../../demo/data'; diff --git a/tests/visual/percy-storybook/TriadValidation.percy.tsx b/tests/visual/percy-storybook/TriadValidation.percy.tsx index d51b5e08d..d99541977 100644 --- a/tests/visual/percy-storybook/TriadValidation.percy.tsx +++ b/tests/visual/percy-storybook/TriadValidation.percy.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; import { TableAction } from 'dash-table/components/Table/props'; const actions = [TableAction.Native, TableAction.Custom]; diff --git a/tests/visual/percy-storybook/Virtualization.percy.tsx b/tests/visual/percy-storybook/Virtualization.percy.tsx index 99aa6af80..7d5c1f36b 100644 --- a/tests/visual/percy-storybook/Virtualization.percy.tsx +++ b/tests/visual/percy-storybook/Virtualization.percy.tsx @@ -5,7 +5,7 @@ import { storiesOf } from '@storybook/react'; import dataset from './../../assets/16zpallagi-25cols-100klines.csv'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; import { TableAction } from 'dash-table/components/Table/props'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Width.all.percy.tsx b/tests/visual/percy-storybook/Width.all.percy.tsx index bbcd3fe78..efb249caa 100644 --- a/tests/visual/percy-storybook/Width.all.percy.tsx +++ b/tests/visual/percy-storybook/Width.all.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Width.defaults.percy.tsx b/tests/visual/percy-storybook/Width.defaults.percy.tsx index 05bd2c6df..a6d6774f6 100644 --- a/tests/visual/percy-storybook/Width.defaults.percy.tsx +++ b/tests/visual/percy-storybook/Width.defaults.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Width.empty.percy.tsx b/tests/visual/percy-storybook/Width.empty.percy.tsx index a1617933e..a87a83e16 100644 --- a/tests/visual/percy-storybook/Width.empty.percy.tsx +++ b/tests/visual/percy-storybook/Width.empty.percy.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; import { TableAction } from 'dash-table/components/Table/props'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Width.max.percy.tsx b/tests/visual/percy-storybook/Width.max.percy.tsx index b49f5a17b..e11b410fe 100644 --- a/tests/visual/percy-storybook/Width.max.percy.tsx +++ b/tests/visual/percy-storybook/Width.max.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Width.min.percy.tsx b/tests/visual/percy-storybook/Width.min.percy.tsx index cb8ec3f48..d61270f2f 100644 --- a/tests/visual/percy-storybook/Width.min.percy.tsx +++ b/tests/visual/percy-storybook/Width.min.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Width.percentages.percy.tsx b/tests/visual/percy-storybook/Width.percentages.percy.tsx index 609a4989c..abe72f27f 100644 --- a/tests/visual/percy-storybook/Width.percentages.percy.tsx +++ b/tests/visual/percy-storybook/Width.percentages.percy.tsx @@ -2,7 +2,8 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; + const setProps = () => { }; const columns = ['a', 'b', 'c']; diff --git a/tests/visual/percy-storybook/Width.width.percy.tsx b/tests/visual/percy-storybook/Width.width.percy.tsx index 1656c2259..aab97ac41 100644 --- a/tests/visual/percy-storybook/Width.width.percy.tsx +++ b/tests/visual/percy-storybook/Width.width.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; const setProps = () => { }; From 399fa836567971cdef6f9b3655517385f956827c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Mon, 23 Sep 2019 12:31:01 -0400 Subject: [PATCH 23/41] typo --- tests/cypress/tests/unit/exportUtils_tests.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cypress/tests/unit/exportUtils_tests.ts b/tests/cypress/tests/unit/exportUtils_tests.ts index e28f74028..74c437e25 100644 --- a/tests/cypress/tests/unit/exportUtils_tests.ts +++ b/tests/cypress/tests/unit/exportUtils_tests.ts @@ -300,7 +300,7 @@ describe('export', () => { {col2: 3, col4: 4}, {col2: 2, col4: 3} ]; - const ws = await createWorkbook(Headings, newData, columnID, ExportHeaders.Display', false); + const ws = await createWorkbook(Headings, newData, columnID, ExportHeaders.Display, false); const expectedWS = {A1: {t: 's', v: 'rows'}, A2: {t: 's', v: 'rows'}, A3: {t: 's', v: 'rows'}, From 166f4f0fe535b46d50e0dfccc08bad4edf29d5dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Tue, 24 Sep 2019 11:41:44 -0400 Subject: [PATCH 24/41] (wip) Add _dashprivate_isLazyComponentReady --- src/dash-table/dash/DataTable.js | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/dash-table/dash/DataTable.js b/src/dash-table/dash/DataTable.js index c69d93fb3..79c26fedd 100644 --- a/src/dash-table/dash/DataTable.js +++ b/src/dash-table/dash/DataTable.js @@ -3,7 +3,34 @@ import PropTypes from 'prop-types'; import LazyLoader from 'dash-table/LazyLoader'; import LazyFactory from './LazyFactory'; -const LazyDataTable = LazyFactory(DataTable, () => LazyLoader.dataTable); +const isLazyComponentReady = (target, promise) => { + let resolve; + const isReady = new Promise(r => { + resolve = r; + }); + + const state = { + isReady, + get: lazy(() => { + return Promise.resolve(promise()).then(res => { + setTimeout(async () => { + await resolve(true); + state.isReady = true; + }, 0); + + return res; + }); + }) + }; + + Object.defineProperty(target, '_dashprivate_isLazyComponentReady', { + get: () => state.isReady + }); + + return state.get; +}; + +const LazyDataTable = isLazyComponentReady(DataTable, () => LazyLoader.dataTable); function DataTable(props) { return ( Date: Tue, 24 Sep 2019 11:47:43 -0400 Subject: [PATCH 25/41] lazy --- src/dash-table/dash/DataTable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dash-table/dash/DataTable.js b/src/dash-table/dash/DataTable.js index 79c26fedd..40ef37fb5 100644 --- a/src/dash-table/dash/DataTable.js +++ b/src/dash-table/dash/DataTable.js @@ -1,4 +1,4 @@ -import React, { Component, Suspense } from 'react'; +import React, { Component, lazy, Suspense } from 'react'; import PropTypes from 'prop-types'; import LazyLoader from 'dash-table/LazyLoader'; import LazyFactory from './LazyFactory'; From 4a372e1f7b45b9dd2a0e97213f80e6c280dc50bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Tue, 24 Sep 2019 12:39:16 -0400 Subject: [PATCH 26/41] percy error --- tests/visual/percy-storybook/Types.percy.tsx | 102 +++++++++---------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/tests/visual/percy-storybook/Types.percy.tsx b/tests/visual/percy-storybook/Types.percy.tsx index 83d635ffb..8c790811d 100644 --- a/tests/visual/percy-storybook/Types.percy.tsx +++ b/tests/visual/percy-storybook/Types.percy.tsx @@ -1,18 +1,18 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/DataTable'; +import DataTable from 'dash-table/dash/LazyDataTable'; const setProps = () => { }; const columns: { name: string[]; id: string; presentation?: string }[] = [ - { name: ['String'], id: 'string' }, - { name: ['Number'], id: 'number' }, - { name: ['Date'], id: 'date' }, - { name: ['Boolean'], id: 'boolean' }, - { name: ['Any'], id: 'any' }, + { name: ['String'], id: 'string' }, + { name: ['Number'], id: 'number' }, + { name: ['Date'], id: 'date' }, + { name: ['Boolean'], id: 'boolean' }, + { name: ['Any'], id: 'any' }, ]; -const columns_dd = columns.map(i => ({...i, presentation: 'dropdown'})); +const columns_dd = columns.map(i => ({ ...i, presentation: 'dropdown' })); storiesOf('DashTable/Types', module) .add('types input', () => ()) .add('types dropdown', () => ( ({ label: `label: ${i}`, value: i }), - ['Montreal', 'Vermont', 'New York City', 'Boston'] - ) - }, - number: { - options: R.map( - i => ({ label: `label: ${i}`, value: i }), - [1, 2, 3, 4] - ) - }, - date: { - options: R.map( - i => ({ label: `label: ${i}`, value: i }), - ['2015-01-01', '2015-10-24', '2016-05-10', '2017-11-11'] - ) - }, - boolean: { - options: R.map( - i => ({ label: `label: ${i}`, value: i }), - [true, false] - ) - }, - any: { - options: R.map( - i => ({ label: `label: ${i}`, value: i }), - ['Montreal', 1, '2015-01-01', true] - ) - } - }} - />)); \ No newline at end of file + setProps={setProps} + id='types dropdown' + data={[ + { string: 'Montreal', number: 1, date: '2015-01-01', boolean: true, any: 'Montreal' }, + { string: 'Vermont', number: 2, date: '2015-10-24', boolean: false, any: 1 }, + { string: 'New York City', number: 3, date: '2016-05-10', boolean: true, any: '2015-01-01' }, + { string: 'Boston', number: 4, date: '2017-11-11', boolean: false, any: true }, + ]} + columns={columns_dd} + editable={false} + dropdown={{ + string: { + options: R.map( + i => ({ label: `label: ${i}`, value: i }), + ['Montreal', 'Vermont', 'New York City', 'Boston'] + ) + }, + number: { + options: R.map( + i => ({ label: `label: ${i}`, value: i }), + [1, 2, 3, 4] + ) + }, + date: { + options: R.map( + i => ({ label: `label: ${i}`, value: i }), + ['2015-01-01', '2015-10-24', '2016-05-10', '2017-11-11'] + ) + }, + boolean: { + options: R.map( + i => ({ label: `label: ${i}`, value: i }), + [true, false] + ) + }, + any: { + options: R.map( + i => ({ label: `label: ${i}`, value: i }), + ['Montreal', 1, '2015-01-01', true] + ) + } + }} + />)); \ No newline at end of file From 287448930eb0e85cb116d363d47210417481a956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Tue, 24 Sep 2019 13:24:18 -0400 Subject: [PATCH 27/41] LazyFactory --- src/dash-table/dash/DataTable.js | 29 +---------------------------- src/dash-table/dash/LazyFactory.ts | 6 ------ 2 files changed, 1 insertion(+), 34 deletions(-) diff --git a/src/dash-table/dash/DataTable.js b/src/dash-table/dash/DataTable.js index 633cf4d4f..800851f40 100644 --- a/src/dash-table/dash/DataTable.js +++ b/src/dash-table/dash/DataTable.js @@ -3,34 +3,7 @@ import PropTypes from 'prop-types'; import LazyLoader from 'dash-table/LazyLoader'; import LazyFactory from './LazyFactory'; -const isLazyComponentReady = (target, promise) => { - let resolve; - const isReady = new Promise(r => { - resolve = r; - }); - - const state = { - isReady, - get: lazy(() => { - return Promise.resolve(promise()).then(res => { - setTimeout(async () => { - await resolve(true); - state.isReady = true; - }, 0); - - return res; - }); - }) - }; - - Object.defineProperty(target, '_dashprivate_isLazyComponentReady', { - get: () => state.isReady - }); - - return state.get; -}; - -const LazyDataTable = isLazyComponentReady(DataTable, () => LazyLoader.dataTable); +const LazyDataTable = LazyFactory(DataTable, () => LazyLoader.dataTable); function DataTable(props) { return ( { const res = await promise(); - // let __r: any; - // const p = new Promise(_r => __r = _r); - // setTimeout(() => __r(), 10000); - // await p; - - // delay `isReady` setTimeout(async () => { await resolve(true); state.isReady = true; From 89dca90428ecc1f252ef6e905fb0c0af40920fa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 26 Sep 2019 18:26:01 -0400 Subject: [PATCH 28/41] add back async~dash-table to __init__ --- dash_table_base/__init__.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/dash_table_base/__init__.py b/dash_table_base/__init__.py index 66baed638..b1e272efa 100644 --- a/dash_table_base/__init__.py +++ b/dash_table_base/__init__.py @@ -44,6 +44,22 @@ ).format(__version__), 'namespace': package_name, 'dynamic': True + }, + { + 'relative_package_path': 'async~dash-table.js', + 'external_url': ( + 'https://unpkg.com/dash-table@{}/dash_table/async~dash-table.js' + ).format(__version__), + 'namespace': package_name, + 'dynamic': True + }, + { + 'relative_package_path': 'async~dash-table.js.map', + 'external_url': ( + 'https://unpkg.com/dash-table@{}/dash_table/async~dash-table.js.map' + ).format(__version__), + 'namespace': package_name, + 'dynamic': True } ] From 92eab96af2deeb72579736d9273977a5babe5eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 26 Sep 2019 18:34:27 -0400 Subject: [PATCH 29/41] add back async~export.js --- dash_table_base/__init__.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/dash_table_base/__init__.py b/dash_table_base/__init__.py index b1e272efa..dbea5dbb7 100644 --- a/dash_table_base/__init__.py +++ b/dash_table_base/__init__.py @@ -60,6 +60,22 @@ ).format(__version__), 'namespace': package_name, 'dynamic': True + }, + { + 'relative_package_path': 'async~export.js', + 'external_url': ( + 'https://unpkg.com/dash-table@{}/dash_table/async~export.js' + ).format(__version__), + 'namespace': package_name, + 'dynamic': True + }, + { + 'relative_package_path': 'async~export.js.map', + 'external_url': ( + 'https://unpkg.com/dash-table@{}/dash_table/async~export.js.map' + ).format(__version__), + 'namespace': package_name, + 'dynamic': True } ] From 89fee8cdad7163cab804c29922c995b3909d57b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 26 Sep 2019 19:22:46 -0400 Subject: [PATCH 30/41] [wip] Use `async` for dash eager/lazy support --- dash_table_base/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dash_table_base/__init__.py b/dash_table_base/__init__.py index dbea5dbb7..e1428cca2 100644 --- a/dash_table_base/__init__.py +++ b/dash_table_base/__init__.py @@ -51,7 +51,7 @@ 'https://unpkg.com/dash-table@{}/dash_table/async~dash-table.js' ).format(__version__), 'namespace': package_name, - 'dynamic': True + 'async': True }, { 'relative_package_path': 'async~dash-table.js.map', @@ -67,7 +67,7 @@ 'https://unpkg.com/dash-table@{}/dash_table/async~export.js' ).format(__version__), 'namespace': package_name, - 'dynamic': True + 'async': True }, { 'relative_package_path': 'async~export.js.map', From 85bcdb66e37e924319b0e0fa6a723b311d19190a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 26 Sep 2019 19:45:54 -0400 Subject: [PATCH 31/41] not sure why this is still here --- dash_table/__init__.py | 87 ------------------------------------------ 1 file changed, 87 deletions(-) delete mode 100644 dash_table/__init__.py diff --git a/dash_table/__init__.py b/dash_table/__init__.py deleted file mode 100644 index dbea5dbb7..000000000 --- a/dash_table/__init__.py +++ /dev/null @@ -1,87 +0,0 @@ -from __future__ import print_function as _ - -import os as _os -import sys as _sys -import json - -import dash as _dash - -# noinspection PyUnresolvedReferences -from ._imports_ import * -from ._imports_ import __all__ - -if not hasattr(_dash, 'development'): - print('Dash was not successfully imported. ' - 'Make sure you don\'t have a file ' - 'named \n"dash.py" in your current directory.', file=_sys.stderr) - _sys.exit(1) - -_basepath = _os.path.dirname(__file__) -_filepath = _os.path.abspath(_os.path.join(_basepath, 'package-info.json')) -with open(_filepath) as f: - package = json.load(f) - -package_name = package['name'].replace(' ', '_').replace('-', '_') -__version__ = package['version'] - -_current_path = _os.path.dirname(_os.path.abspath(__file__)) - -_this_module = _sys.modules[__name__] - - -_js_dist = [ - { - 'relative_package_path': 'bundle.js', - 'external_url': ( - 'https://unpkg.com/dash-table@{}/dash_table/bundle.js' - ).format(__version__), - 'namespace': package_name - }, - { - 'relative_package_path': 'bundle.js.map', - 'external_url': ( - 'https://unpkg.com/dash-table@{}/dash_table/bundle.js.map' - ).format(__version__), - 'namespace': package_name, - 'dynamic': True - }, - { - 'relative_package_path': 'async~dash-table.js', - 'external_url': ( - 'https://unpkg.com/dash-table@{}/dash_table/async~dash-table.js' - ).format(__version__), - 'namespace': package_name, - 'dynamic': True - }, - { - 'relative_package_path': 'async~dash-table.js.map', - 'external_url': ( - 'https://unpkg.com/dash-table@{}/dash_table/async~dash-table.js.map' - ).format(__version__), - 'namespace': package_name, - 'dynamic': True - }, - { - 'relative_package_path': 'async~export.js', - 'external_url': ( - 'https://unpkg.com/dash-table@{}/dash_table/async~export.js' - ).format(__version__), - 'namespace': package_name, - 'dynamic': True - }, - { - 'relative_package_path': 'async~export.js.map', - 'external_url': ( - 'https://unpkg.com/dash-table@{}/dash_table/async~export.js.map' - ).format(__version__), - 'namespace': package_name, - 'dynamic': True - } -] - -_css_dist = [] - - -for _component in __all__: - setattr(locals()[_component], '_js_dist', _js_dist) - setattr(locals()[_component], '_css_dist', _css_dist) From c71c357a019040b971b83e5f7ac20697e32cff5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Tue, 1 Oct 2019 16:43:20 -0400 Subject: [PATCH 32/41] remove lazy table, only keep lazy xlsx for now --- dash_table_base/__init__.py | 16 --------- src/dash-table/LazyLoader.ts | 4 --- src/dash-table/dash/DataTable.js | 50 ++++++++++++++++++++-------- src/dash-table/dash/LazyDataTable.js | 43 ------------------------ 4 files changed, 37 insertions(+), 76 deletions(-) delete mode 100644 src/dash-table/dash/LazyDataTable.js diff --git a/dash_table_base/__init__.py b/dash_table_base/__init__.py index e1428cca2..7f4e7219b 100644 --- a/dash_table_base/__init__.py +++ b/dash_table_base/__init__.py @@ -45,22 +45,6 @@ 'namespace': package_name, 'dynamic': True }, - { - 'relative_package_path': 'async~dash-table.js', - 'external_url': ( - 'https://unpkg.com/dash-table@{}/dash_table/async~dash-table.js' - ).format(__version__), - 'namespace': package_name, - 'async': True - }, - { - 'relative_package_path': 'async~dash-table.js.map', - 'external_url': ( - 'https://unpkg.com/dash-table@{}/dash_table/async~dash-table.js.map' - ).format(__version__), - 'namespace': package_name, - 'dynamic': True - }, { 'relative_package_path': 'async~export.js', 'external_url': ( diff --git a/src/dash-table/LazyLoader.ts b/src/dash-table/LazyLoader.ts index 2bbf14bec..a8d89e941 100644 --- a/src/dash-table/LazyLoader.ts +++ b/src/dash-table/LazyLoader.ts @@ -1,8 +1,4 @@ export default class LazyLoader { - public static get dataTable() { - return import(/* webpackChunkName: "dash-table", webpackMode: "$${{mode}}" */ 'dash-table/dash/LazyDataTable'); - } - public static get xlsx() { return import(/* webpackChunkName: "export", webpackMode: "$${{mode}}" */ 'xlsx'); } diff --git a/src/dash-table/dash/DataTable.js b/src/dash-table/dash/DataTable.js index 800851f40..e26bc7a30 100644 --- a/src/dash-table/dash/DataTable.js +++ b/src/dash-table/dash/DataTable.js @@ -1,19 +1,43 @@ -import React, { Component, lazy, Suspense } from 'react'; +import * as R from 'ramda'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import LazyLoader from 'dash-table/LazyLoader'; -import LazyFactory from './LazyFactory'; -const LazyDataTable = LazyFactory(DataTable, () => LazyLoader.dataTable); +import RealTable from 'dash-table/components/Table'; + +import Logger from 'core/Logger'; + +import genRandomId from 'dash-table/utils/generate'; +import isValidProps from './validate'; +import Sanitizer from './Sanitizer'; + +/** + * Dash DataTable is an interactive table component designed for + * designed for viewing, editing, and exploring large datasets. + * DataTable is rendered with standard, semantic HTML
markup, + * which makes it accessible, responsive, and easy to style. This + * component was written from scratch in React.js specifically for the + * Dash community. Its API was designed to be ergonomic and its behavior + * is completely customizable through its properties. + */ +export default class DataTable extends Component { + constructor(props) { + super(props); + let id; + this.getId = () => (id = id || genRandomId('table-')); + this.sanitizer = new Sanitizer(); + } -function DataTable(props) { - return ( - - ); -} + render() { + if (!isValidProps(this.props)) { + return (
Invalid props combination
); + } -export default DataTable; + const sanitizedProps = this.sanitizer.sanitize(this.props); + return this.props.id ? + () : + (); + } +} export const defaultProps = { page_action: 'native', @@ -1272,4 +1296,4 @@ DataTable.persistenceTransforms = { }; DataTable.defaultProps = defaultProps; -DataTable.propTypes = propTypes; +DataTable.propTypes = propTypes; \ No newline at end of file diff --git a/src/dash-table/dash/LazyDataTable.js b/src/dash-table/dash/LazyDataTable.js deleted file mode 100644 index d8dcd7e68..000000000 --- a/src/dash-table/dash/LazyDataTable.js +++ /dev/null @@ -1,43 +0,0 @@ -import * as R from 'ramda'; -import React, { Component } from 'react'; - -import RealTable from 'dash-table/components/Table'; - -import Logger from 'core/Logger'; - -import genRandomId from 'dash-table/utils/generate'; -import isValidProps from './validate'; -import Sanitizer from './Sanitizer'; -import { defaultProps, propTypes } from 'dash-table/dash/DataTable'; - -/** - * Dash DataTable is an interactive table component designed for - * designed for viewing, editing, and exploring large datasets. - * DataTable is rendered with standard, semantic HTML
markup, - * which makes it accessible, responsive, and easy to style. This - * component was written from scratch in React.js specifically for the - * Dash community. Its API was designed to be ergonomic and its behavior - * is completely customizable through its properties. - */ -export default class DataTable extends Component { - constructor(props) { - super(props); - let id; - this.getId = () => (id = id || genRandomId('table-')); - this.sanitizer = new Sanitizer(); - } - - render() { - if (!isValidProps(this.props)) { - return (
Invalid props combination
); - } - - const sanitizedProps = this.sanitizer.sanitize(this.props); - return this.props.id ? - () : - (); - } -} - -DataTable.defaultProps = defaultProps; -DataTable.propTypes = propTypes; From 454270bb9df49c47552365e77e3f4137d2cedcb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Tue, 1 Oct 2019 16:46:39 -0400 Subject: [PATCH 33/41] undo lazy change in tests --- .../percy-storybook/Border.defaults.percy.tsx | 4 +- .../percy-storybook/Border.style.percy.tsx | 18 +++--- .../percy-storybook/DashTable.percy.tsx | 62 +++++++++---------- .../visual/percy-storybook/Dropdown.percy.tsx | 2 +- .../visual/percy-storybook/Filters.percy.tsx | 2 +- .../percy-storybook/Header.actions.percy.tsx | 2 +- tests/visual/percy-storybook/Header.percy.tsx | 2 +- .../visual/percy-storybook/Hideable.percy.tsx | 2 +- .../percy-storybook/LoadingState.percy.tsx | 2 +- tests/visual/percy-storybook/Sizing.percy.tsx | 2 +- tests/visual/percy-storybook/Style.percy.tsx | 16 ++--- .../percy-storybook/TriadValidation.percy.tsx | 2 +- tests/visual/percy-storybook/Types.percy.tsx | 2 +- .../percy-storybook/Virtualization.percy.tsx | 2 +- .../percy-storybook/Width.all.percy.tsx | 2 +- .../percy-storybook/Width.defaults.percy.tsx | 2 +- .../percy-storybook/Width.empty.percy.tsx | 2 +- .../percy-storybook/Width.max.percy.tsx | 2 +- .../percy-storybook/Width.min.percy.tsx | 2 +- .../Width.percentages.percy.tsx | 14 ++--- .../percy-storybook/Width.width.percy.tsx | 2 +- 21 files changed, 73 insertions(+), 73 deletions(-) diff --git a/tests/visual/percy-storybook/Border.defaults.percy.tsx b/tests/visual/percy-storybook/Border.defaults.percy.tsx index 24cdd3946..9d3a2888b 100644 --- a/tests/visual/percy-storybook/Border.defaults.percy.tsx +++ b/tests/visual/percy-storybook/Border.defaults.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; @@ -93,7 +93,7 @@ storiesOf('DashTable/Border (available space filled)', module) fixed_rows={{ headers: true }} />)) .add('with no frozen rows and frozen columns', () => ()) .add('with frozen rows and frozen columns', () => ( { }; @@ -30,7 +30,7 @@ function makeSelection(coords: any[], data: any[], columns: any[]) { const fixtureStories = storiesOf('DashTable/Fixtures', module); fixtures.forEach(fixture => { // update active and selected cells for the new cell object format - const {data, columns, active_cell, selected_cells} = fixture.props; + const { data, columns, active_cell, selected_cells } = fixture.props; if (Array.isArray(active_cell)) { fixture.props.active_cell = makeCell( active_cell[0], active_cell[1], data as any[], columns as any[] @@ -309,7 +309,7 @@ storiesOf('DashTable/Without id', module) fixed_rows={{ headers: true }} row_deletable={true} row_selectable={true} - style_table={{height: 500, width: 200}} + style_table={{ height: 500, width: 200 }} style_data_conditional={style_data_conditional} />)) .add('with set height and width and colors', () => ()) @@ -335,7 +335,7 @@ storiesOf('DashTable/Without id', module) fixed_rows={{ headers: true }} row_deletable={true} row_selectable={true} - style_table={{height: 500, width: 400}} + style_table={{ height: 500, width: 400 }} css={[{ selector: '.dash-spreadsheet', rule: 'border: 4px solid hotpink' @@ -349,7 +349,7 @@ storiesOf('DashTable/Without id', module) fixed_rows={{ headers: true }} row_deletable={true} row_selectable={true} - style_table={{height: 500, width: 400}} + style_table={{ height: 500, width: 400 }} css={[{ selector: '.dash-spreadsheet', rule: 'border: 4px solid cyan' @@ -359,27 +359,27 @@ storiesOf('DashTable/Without id', module) ); storiesOf('DashTable/Export', module) - .add('Export Button for xlsx file', () => ()) - .add('Export Button for csv file', () => ()) - .add('No export Button for file formatted not supported', () => ()) - .add('No export Button', () => ()); + .add('Export Button for xlsx file', () => ()) + .add('Export Button for csv file', () => ()) + .add('No export Button for file formatted not supported', () => ()) + .add('No export Button', () => ()); diff --git a/tests/visual/percy-storybook/Dropdown.percy.tsx b/tests/visual/percy-storybook/Dropdown.percy.tsx index e6e98b1d0..7569b4ae3 100644 --- a/tests/visual/percy-storybook/Dropdown.percy.tsx +++ b/tests/visual/percy-storybook/Dropdown.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Filters.percy.tsx b/tests/visual/percy-storybook/Filters.percy.tsx index e46bbada3..c551959bc 100644 --- a/tests/visual/percy-storybook/Filters.percy.tsx +++ b/tests/visual/percy-storybook/Filters.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; import { TableAction } from 'dash-table/components/Table/props'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Header.actions.percy.tsx b/tests/visual/percy-storybook/Header.actions.percy.tsx index d449654b5..7db9ab188 100644 --- a/tests/visual/percy-storybook/Header.actions.percy.tsx +++ b/tests/visual/percy-storybook/Header.actions.percy.tsx @@ -1,7 +1,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Header.percy.tsx b/tests/visual/percy-storybook/Header.percy.tsx index 35ce17536..1335e0481 100644 --- a/tests/visual/percy-storybook/Header.percy.tsx +++ b/tests/visual/percy-storybook/Header.percy.tsx @@ -1,7 +1,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Hideable.percy.tsx b/tests/visual/percy-storybook/Hideable.percy.tsx index b56871ad3..e93fd417e 100644 --- a/tests/visual/percy-storybook/Hideable.percy.tsx +++ b/tests/visual/percy-storybook/Hideable.percy.tsx @@ -3,7 +3,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; import dataset from './../../assets/gapminder.csv'; const result = parser.parse(dataset, { delimiter: ',', header: true }); diff --git a/tests/visual/percy-storybook/LoadingState.percy.tsx b/tests/visual/percy-storybook/LoadingState.percy.tsx index 5caf0952f..96633cdb3 100644 --- a/tests/visual/percy-storybook/LoadingState.percy.tsx +++ b/tests/visual/percy-storybook/LoadingState.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Sizing.percy.tsx b/tests/visual/percy-storybook/Sizing.percy.tsx index 44a4dcc98..c7dd959f6 100644 --- a/tests/visual/percy-storybook/Sizing.percy.tsx +++ b/tests/visual/percy-storybook/Sizing.percy.tsx @@ -1,7 +1,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Style.percy.tsx b/tests/visual/percy-storybook/Style.percy.tsx index 7bcd53555..6499c775c 100644 --- a/tests/visual/percy-storybook/Style.percy.tsx +++ b/tests/visual/percy-storybook/Style.percy.tsx @@ -1,7 +1,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; import { ColumnType } from 'dash-table/components/Table/props'; import { generateMockData } from '../../../demo/data'; @@ -136,8 +136,8 @@ storiesOf('DashTable/Style type condition', module) .add('single selected cells on dark themes', () => ( ({ name: i, id: i }), R.keysIn(data[0])) @@ -155,8 +155,8 @@ storiesOf('DashTable/Style type condition', module) .add('multiple selected cells on dark themes', () => ( ({ name: i, id: i }), R.keysIn(data[0])) @@ -356,8 +356,8 @@ storiesOf('DashTable/Style type condition', module) />)) .add('paging', () => ( R.merge(col, { + data={mock.data} + columns={mock.columns.map((col: any) => R.merge(col, { name: col.name, deletable: true }))} @@ -366,7 +366,7 @@ storiesOf('DashTable/Style type condition', module) }} row_deletable={true} row_selectable={true} - pagination_mode= {'fe'} + pagination_mode={'fe'} style_data_conditional={[{ if: { column_editable: true }, background_color: 'MediumPurple' }]} diff --git a/tests/visual/percy-storybook/TriadValidation.percy.tsx b/tests/visual/percy-storybook/TriadValidation.percy.tsx index d99541977..d51b5e08d 100644 --- a/tests/visual/percy-storybook/TriadValidation.percy.tsx +++ b/tests/visual/percy-storybook/TriadValidation.percy.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; import { TableAction } from 'dash-table/components/Table/props'; const actions = [TableAction.Native, TableAction.Custom]; diff --git a/tests/visual/percy-storybook/Types.percy.tsx b/tests/visual/percy-storybook/Types.percy.tsx index 8c790811d..5c957c6e5 100644 --- a/tests/visual/percy-storybook/Types.percy.tsx +++ b/tests/visual/percy-storybook/Types.percy.tsx @@ -1,7 +1,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; const columns: { name: string[]; id: string; presentation?: string }[] = [ diff --git a/tests/visual/percy-storybook/Virtualization.percy.tsx b/tests/visual/percy-storybook/Virtualization.percy.tsx index 7d5c1f36b..99aa6af80 100644 --- a/tests/visual/percy-storybook/Virtualization.percy.tsx +++ b/tests/visual/percy-storybook/Virtualization.percy.tsx @@ -5,7 +5,7 @@ import { storiesOf } from '@storybook/react'; import dataset from './../../assets/16zpallagi-25cols-100klines.csv'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; import { TableAction } from 'dash-table/components/Table/props'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Width.all.percy.tsx b/tests/visual/percy-storybook/Width.all.percy.tsx index efb249caa..bbcd3fe78 100644 --- a/tests/visual/percy-storybook/Width.all.percy.tsx +++ b/tests/visual/percy-storybook/Width.all.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Width.defaults.percy.tsx b/tests/visual/percy-storybook/Width.defaults.percy.tsx index a6d6774f6..05bd2c6df 100644 --- a/tests/visual/percy-storybook/Width.defaults.percy.tsx +++ b/tests/visual/percy-storybook/Width.defaults.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Width.empty.percy.tsx b/tests/visual/percy-storybook/Width.empty.percy.tsx index a87a83e16..a1617933e 100644 --- a/tests/visual/percy-storybook/Width.empty.percy.tsx +++ b/tests/visual/percy-storybook/Width.empty.percy.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; import { TableAction } from 'dash-table/components/Table/props'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Width.max.percy.tsx b/tests/visual/percy-storybook/Width.max.percy.tsx index e11b410fe..b49f5a17b 100644 --- a/tests/visual/percy-storybook/Width.max.percy.tsx +++ b/tests/visual/percy-storybook/Width.max.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Width.min.percy.tsx b/tests/visual/percy-storybook/Width.min.percy.tsx index d61270f2f..cb8ec3f48 100644 --- a/tests/visual/percy-storybook/Width.min.percy.tsx +++ b/tests/visual/percy-storybook/Width.min.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; diff --git a/tests/visual/percy-storybook/Width.percentages.percy.tsx b/tests/visual/percy-storybook/Width.percentages.percy.tsx index abe72f27f..f88c6633e 100644 --- a/tests/visual/percy-storybook/Width.percentages.percy.tsx +++ b/tests/visual/percy-storybook/Width.percentages.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; @@ -43,18 +43,18 @@ const props = Object.assign({}, baseProps, { storiesOf('DashTable/Width percentages', module) .add('without frozen columns or rows', () => ()) + {...props} + />)) .add('with frozen rows', () => ()) + />)) .add('with frozen columns', () => ()) .add('with frozen rows and frozen columns', () => ()); \ No newline at end of file diff --git a/tests/visual/percy-storybook/Width.width.percy.tsx b/tests/visual/percy-storybook/Width.width.percy.tsx index aab97ac41..1656c2259 100644 --- a/tests/visual/percy-storybook/Width.width.percy.tsx +++ b/tests/visual/percy-storybook/Width.width.percy.tsx @@ -2,7 +2,7 @@ import * as R from 'ramda'; import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; -import DataTable from 'dash-table/dash/LazyDataTable'; +import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; From 314b51884abe719844ba2dd0a481930437e99b1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Wed, 2 Oct 2019 11:44:14 -0400 Subject: [PATCH 34/41] webpack-dash-dynamic-import alpha --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c953f5ce4..a8f00c7da 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "wait-on": "^3.3.0", "webpack": "^4.40.0", "webpack-cli": "^3.3.8", - "webpack-dash-dynamic-import": "github:plotly/webpack-dash-dynamic-import", + "webpack-dash-dynamic-import": "^1.0.0-alpha.1", "webpack-dev-server": "^3.8.0", "webpack-preprocessor": "^0.1.12", "xlsx": "^0.15.1" @@ -122,4 +122,4 @@ "node": ">=8.11.0", "npm": ">=6.1.0" } -} \ No newline at end of file +} From 2547bb8c963ce05af17dd65f618856ebcbe87c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 3 Oct 2019 14:31:09 -0400 Subject: [PATCH 35/41] new packages --- .config/webpack/base.js | 2 +- package.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.config/webpack/base.js b/.config/webpack/base.js index 2b9e072f7..ba471c134 100644 --- a/.config/webpack/base.js +++ b/.config/webpack/base.js @@ -1,5 +1,5 @@ const path = require('path'); -const WebpackDashDynamicImport = require('webpack-dash-dynamic-import'); +const WebpackDashDynamicImport = require('@plotly/webpack-dash-dynamic-import'); const basePreprocessing = require('./base.preprocessing'); const packagejson = require('./../../package.json'); diff --git a/package.json b/package.json index a8f00c7da..f2b0b4ebf 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "@fortawesome/free-solid-svg-icons": "^5.10.2", "@fortawesome/react-fontawesome": "^0.1.4", "@percy-io/percy-storybook": "^2.1.0", + "@plotly/webpack-dash-dynamic-import": "^1.0.0-alpha.1", "@storybook/cli": "^5.1.11", "@storybook/react": "^5.1.11", "@types/d3-format": "^1.3.1", From cdca967eb6d6250cd3bb2b11f1618cae44e0be39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 3 Oct 2019 14:35:07 -0400 Subject: [PATCH 36/41] packages --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index f2b0b4ebf..291545185 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,6 @@ "wait-on": "^3.3.0", "webpack": "^4.40.0", "webpack-cli": "^3.3.8", - "webpack-dash-dynamic-import": "^1.0.0-alpha.1", "webpack-dev-server": "^3.8.0", "webpack-preprocessor": "^0.1.12", "xlsx": "^0.15.1" @@ -123,4 +122,4 @@ "node": ">=8.11.0", "npm": ">=6.1.0" } -} +} \ No newline at end of file From 72be9b1bbd6dbe4c3d2d3b3177e8c7e2acd70aac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 3 Oct 2019 15:37:52 -0400 Subject: [PATCH 37/41] update usage --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 291545185..2a4d9ceda 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "@fortawesome/free-solid-svg-icons": "^5.10.2", "@fortawesome/react-fontawesome": "^0.1.4", "@percy-io/percy-storybook": "^2.1.0", - "@plotly/webpack-dash-dynamic-import": "^1.0.0-alpha.1", + "@plotly/webpack-dash-dynamic-import": "^1.0.0", "@storybook/cli": "^5.1.11", "@storybook/react": "^5.1.11", "@types/d3-format": "^1.3.1", From 1a0a5d11f1d73a899766766b92595afcb7f93e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 3 Oct 2019 15:48:50 -0400 Subject: [PATCH 38/41] changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index edd2c2078..24f10440f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). [#597](https://github.com/plotly/dash-table/issues/597) - Add `is blank` unary operator. Returns true for `undefined`, `null` and `''`. +[#554](https://github.com/plotly/dash-table/pull/554) +- Async loading of `xlsx` library on export + ### Changed [#598](https://github.com/plotly/dash-table/issues/598) - Allow values with whitespaces in column filters From b76e26a407abc4daf2968bab2b4bc3855e5ec837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 17 Oct 2019 15:35:53 -0400 Subject: [PATCH 39/41] fix merge / version --- package-lock.json | 8 +++++++- package.json | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5305fb71b..fc76a417c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "dash-table", - "version": "4.4.0", + "version": "4.4.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2246,6 +2246,12 @@ } } }, + "@plotly/webpack-dash-dynamic-import": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@plotly/webpack-dash-dynamic-import/-/webpack-dash-dynamic-import-1.0.0.tgz", + "integrity": "sha512-ZkK0rwzAeKuYroBLWh7wHevWBG3Ljg2Tp9yrArXfxj75c2OlXpOlJEZgji9VHZZj0VvNEuBwxeG182fIK5FA4Q==", + "dev": true + }, "@reach/router": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@reach/router/-/router-1.2.1.tgz", diff --git a/package.json b/package.json index b27a3ba16..2dfa97972 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dash-table", - "version": "4.4.0", + "version": "4.4.1", "description": "Dash table", "repository": { "type": "git", @@ -124,4 +124,4 @@ "node": ">=8.11.0", "npm": ">=6.1.0" } -} \ No newline at end of file +} From 0c67d003adff6869a62e924aad065c33b316f302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Sat, 19 Oct 2019 12:08:20 -0400 Subject: [PATCH 40/41] cleanup --- src/dash-table/dash/LazyFactory.ts | 39 ------------------------------ 1 file changed, 39 deletions(-) delete mode 100644 src/dash-table/dash/LazyFactory.ts diff --git a/src/dash-table/dash/LazyFactory.ts b/src/dash-table/dash/LazyFactory.ts deleted file mode 100644 index 9bd964d47..000000000 --- a/src/dash-table/dash/LazyFactory.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { lazy } from 'react'; - -type Boolean = Promise | boolean; -type LazyComponent = React.LazyExoticComponent>; - -interface IResult { - isReady: Boolean; - get: LazyComponent; -} - -export default ( - target: () => JSX.Element, - promise: () => Promise<{ default: React.ComponentType }> -): LazyComponent => { - let resolve: (value: Boolean) => void; - const isReady = new Promise(r => { - resolve = r; - }); - - const state: IResult = { - isReady, - get: lazy(async () => { - const res = await promise(); - - setTimeout(async () => { - await resolve(true); - state.isReady = true; - }, 0); - - return res; - }) - }; - - Object.defineProperty(target, '_dashprivate_isLazyComponentReady', { - get: () => state.isReady - }); - - return state.get; -}; \ No newline at end of file From e0fc646ef13c9542dcfc6bc724b596ac9b51f5f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Sat, 19 Oct 2019 12:08:50 -0400 Subject: [PATCH 41/41] unreleased ordering --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 054501960..01778c50d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## Unreleased +### Changed +- [#554](https://github.com/plotly/dash-table/pull/554) Async loading of `xlsx` library on export + ## [4.4.1] - 2019-08-17 ### Fixed - [#618](https://github.com/plotly/dash-table/issues/618) Fix a bug with keyboard navigation not working correctly in certain circumstances when the table contains `readonly` columns. @@ -9,10 +13,6 @@ This project adheres to [Semantic Versioning](http://semver.org/). - [#561](https://github.com/plotly/dash-table/issues/561) Fix an incorrect React PureComponent usage causing warnings in DevTools. - [#611](https://github.com/plotly/dash-table/issues/611) Fix a bug with copy/paste causing hidden columns to be removed from the table -## Unreleased -### Changed -- [#554](https://github.com/plotly/dash-table/pull/554) Async loading of `xlsx` library on export - ## [4.4.0] - 2019-10-08 ### Added [#546](https://github.com/plotly/dash-table/issues/546)