diff --git a/CHANGELOG.md b/CHANGELOG.md index cf6d350d73..bfc0a95eb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,12 @@ This project adheres to [Semantic Versioning](https://semver.org/). - Adds `ticklabelstep` to axes to reduce tick labels while still showing all ticks. - Displays the plotly.js version when hovering on the modebar. This helps debugging situations where there might be multiple sources of plotly.js, for example `/assets` vs the versions built into `dcc` or `ddk`. +### Fixed +- [#1932](https://github.com/plotly/dash/pull/1932) Fixes several bugs: + - Restores compatibility with IE11 [#1925](https://github.com/plotly/dash/issues/1925) + - Restores `style_header` text alignment in Dash Table [#1914](https://github.com/plotly/dash/issues/1914) + - Clears the unneeded `webdriver-manager` requirement from `dash[testing]` [#1919](https://github.com/plotly/dash/issues/1925) + ## [2.1.0] - 2022-01-22 ### Changed diff --git a/components/dash-core-components/package-lock.json b/components/dash-core-components/package-lock.json index b690a467e6..36b1be31ed 100644 --- a/components/dash-core-components/package-lock.json +++ b/components/dash-core-components/package-lock.json @@ -9,9 +9,9 @@ "version": "2.1.0", "license": "MIT", "dependencies": { - "@fortawesome/fontawesome-svg-core": "^1.3.0", - "@fortawesome/free-regular-svg-icons": "^6.0.0", - "@fortawesome/free-solid-svg-icons": "^6.0.0", + "@fortawesome/fontawesome-svg-core": "1.2.36", + "@fortawesome/free-regular-svg-icons": "^5.15.4", + "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.17", "base64-js": "^1.5.1", "color": "^4.2.1", @@ -1894,45 +1894,45 @@ } }, "node_modules/@fortawesome/fontawesome-common-types": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.3.0.tgz", - "integrity": "sha512-CA3MAZBTxVsF6SkfkHXDerkhcQs0QPofy43eFdbWJJkZiq3SfiaH1msOkac59rQaqto5EqWnASboY1dBuKen5w==", + "version": "0.2.36", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", + "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==", "hasInstallScript": true, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.3.0.tgz", - "integrity": "sha512-UIL6crBWhjTNQcONt96ExjUnKt1D68foe3xjEensLDclqQ6YagwCRYVQdrp/hW0ALRp/5Fv/VKw+MqTUWYYvPg==", + "version": "1.2.36", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz", + "integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "^0.2.36" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-regular-svg-icons": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.0.0.tgz", - "integrity": "sha512-lYK6oyQL8HwZUAVWGqF7TGuwQBVfphNBVTdvPSD3h4gmQfGazm/xcwg3kmtcRycu3y6QspOC7hPXSoJbVqSYCw==", + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz", + "integrity": "sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "^0.2.36" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.0.0.tgz", - "integrity": "sha512-o4FZ1XbndcgeWNb8Wh0y+Hgf73CjmyOQowUSaqQCtgIIdS+XliSBSOwCl330wER+I6CGYE96hT27bHBPmzX2Gg==", + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz", + "integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "^0.2.36" }, "engines": { "node": ">=6" @@ -11117,32 +11117,32 @@ } }, "@fortawesome/fontawesome-common-types": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.3.0.tgz", - "integrity": "sha512-CA3MAZBTxVsF6SkfkHXDerkhcQs0QPofy43eFdbWJJkZiq3SfiaH1msOkac59rQaqto5EqWnASboY1dBuKen5w==" + "version": "0.2.36", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", + "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==" }, "@fortawesome/fontawesome-svg-core": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.3.0.tgz", - "integrity": "sha512-UIL6crBWhjTNQcONt96ExjUnKt1D68foe3xjEensLDclqQ6YagwCRYVQdrp/hW0ALRp/5Fv/VKw+MqTUWYYvPg==", + "version": "1.2.36", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz", + "integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==", "requires": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "^0.2.36" } }, "@fortawesome/free-regular-svg-icons": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.0.0.tgz", - "integrity": "sha512-lYK6oyQL8HwZUAVWGqF7TGuwQBVfphNBVTdvPSD3h4gmQfGazm/xcwg3kmtcRycu3y6QspOC7hPXSoJbVqSYCw==", + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz", + "integrity": "sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==", "requires": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "^0.2.36" } }, "@fortawesome/free-solid-svg-icons": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.0.0.tgz", - "integrity": "sha512-o4FZ1XbndcgeWNb8Wh0y+Hgf73CjmyOQowUSaqQCtgIIdS+XliSBSOwCl330wER+I6CGYE96hT27bHBPmzX2Gg==", + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz", + "integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==", "requires": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "^0.2.36" } }, "@fortawesome/react-fontawesome": { diff --git a/components/dash-core-components/package.json b/components/dash-core-components/package.json index 53e36291a8..c5f7b4fb9a 100644 --- a/components/dash-core-components/package.json +++ b/components/dash-core-components/package.json @@ -36,9 +36,9 @@ "maintainer": "Alex Johnson ", "license": "MIT", "dependencies": { - "@fortawesome/fontawesome-svg-core": "^1.3.0", - "@fortawesome/free-regular-svg-icons": "^6.0.0", - "@fortawesome/free-solid-svg-icons": "^6.0.0", + "@fortawesome/fontawesome-svg-core": "1.2.36", + "@fortawesome/free-regular-svg-icons": "^5.15.4", + "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.17", "base64-js": "^1.5.1", "color": "^4.2.1", diff --git a/components/dash-core-components/src/fragments/Graph.react.js b/components/dash-core-components/src/fragments/Graph.react.js index 7cb415fd13..0205b9190a 100644 --- a/components/dash-core-components/src/fragments/Graph.react.js +++ b/components/dash-core-components/src/fragments/Graph.react.js @@ -1,5 +1,6 @@ import React, {Component} from 'react'; -import ResizeDetector from 'react-resize-detector'; +// /build/withPolyfill for IE11 support - https://github.com/maslianok/react-resize-detector/issues/144 +import ResizeDetector from 'react-resize-detector/build/withPolyfill'; import { equals, filter, diff --git a/components/dash-table/package-lock.json b/components/dash-table/package-lock.json index 236c6bb046..a8bf1767cc 100644 --- a/components/dash-table/package-lock.json +++ b/components/dash-table/package-lock.json @@ -16,9 +16,9 @@ "@babel/polyfill": "^7.12.1", "@babel/preset-env": "^7.16.11", "@babel/preset-react": "^7.16.7", - "@fortawesome/fontawesome-svg-core": "^1.3.0", - "@fortawesome/free-regular-svg-icons": "^6.0.0", - "@fortawesome/free-solid-svg-icons": "^6.0.0", + "@fortawesome/fontawesome-svg-core": "1.2.36", + "@fortawesome/free-regular-svg-icons": "^5.15.4", + "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.17", "@percy/storybook": "^3.3.1", "@plotly/dash-component-plugins": "^1.2.2", @@ -2407,9 +2407,9 @@ } }, "node_modules/@fortawesome/fontawesome-common-types": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.3.0.tgz", - "integrity": "sha512-CA3MAZBTxVsF6SkfkHXDerkhcQs0QPofy43eFdbWJJkZiq3SfiaH1msOkac59rQaqto5EqWnASboY1dBuKen5w==", + "version": "0.2.36", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", + "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==", "dev": true, "hasInstallScript": true, "engines": { @@ -2417,39 +2417,39 @@ } }, "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.3.0.tgz", - "integrity": "sha512-UIL6crBWhjTNQcONt96ExjUnKt1D68foe3xjEensLDclqQ6YagwCRYVQdrp/hW0ALRp/5Fv/VKw+MqTUWYYvPg==", + "version": "1.2.36", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz", + "integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==", "dev": true, "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "^0.2.36" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-regular-svg-icons": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.0.0.tgz", - "integrity": "sha512-lYK6oyQL8HwZUAVWGqF7TGuwQBVfphNBVTdvPSD3h4gmQfGazm/xcwg3kmtcRycu3y6QspOC7hPXSoJbVqSYCw==", + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz", + "integrity": "sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==", "dev": true, "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "^0.2.36" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.0.0.tgz", - "integrity": "sha512-o4FZ1XbndcgeWNb8Wh0y+Hgf73CjmyOQowUSaqQCtgIIdS+XliSBSOwCl330wER+I6CGYE96hT27bHBPmzX2Gg==", + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz", + "integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==", "dev": true, "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "^0.2.36" }, "engines": { "node": ">=6" @@ -37219,36 +37219,36 @@ } }, "@fortawesome/fontawesome-common-types": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.3.0.tgz", - "integrity": "sha512-CA3MAZBTxVsF6SkfkHXDerkhcQs0QPofy43eFdbWJJkZiq3SfiaH1msOkac59rQaqto5EqWnASboY1dBuKen5w==", + "version": "0.2.36", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", + "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==", "dev": true }, "@fortawesome/fontawesome-svg-core": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.3.0.tgz", - "integrity": "sha512-UIL6crBWhjTNQcONt96ExjUnKt1D68foe3xjEensLDclqQ6YagwCRYVQdrp/hW0ALRp/5Fv/VKw+MqTUWYYvPg==", + "version": "1.2.36", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz", + "integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==", "dev": true, "requires": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "^0.2.36" } }, "@fortawesome/free-regular-svg-icons": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.0.0.tgz", - "integrity": "sha512-lYK6oyQL8HwZUAVWGqF7TGuwQBVfphNBVTdvPSD3h4gmQfGazm/xcwg3kmtcRycu3y6QspOC7hPXSoJbVqSYCw==", + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz", + "integrity": "sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==", "dev": true, "requires": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "^0.2.36" } }, "@fortawesome/free-solid-svg-icons": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.0.0.tgz", - "integrity": "sha512-o4FZ1XbndcgeWNb8Wh0y+Hgf73CjmyOQowUSaqQCtgIIdS+XliSBSOwCl330wER+I6CGYE96hT27bHBPmzX2Gg==", + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz", + "integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==", "dev": true, "requires": { - "@fortawesome/fontawesome-common-types": "^0.3.0" + "@fortawesome/fontawesome-common-types": "^0.2.36" } }, "@fortawesome/react-fontawesome": { diff --git a/components/dash-table/package.json b/components/dash-table/package.json index 8b04d102c5..f6c1267944 100644 --- a/components/dash-table/package.json +++ b/components/dash-table/package.json @@ -48,9 +48,9 @@ "@babel/polyfill": "^7.12.1", "@babel/preset-env": "^7.16.11", "@babel/preset-react": "^7.16.7", - "@fortawesome/fontawesome-svg-core": "^1.3.0", - "@fortawesome/free-regular-svg-icons": "^6.0.0", - "@fortawesome/free-solid-svg-icons": "^6.0.0", + "@fortawesome/fontawesome-svg-core": "1.2.36", + "@fortawesome/free-regular-svg-icons": "^5.15.4", + "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.17", "@percy/storybook": "^3.3.1", "@plotly/dash-component-plugins": "^1.2.2", diff --git a/components/dash-table/src/dash-table/components/Table/Table.less b/components/dash-table/src/dash-table/components/Table/Table.less index 48c6aa0757..4677d77c05 100644 --- a/components/dash-table/src/dash-table/components/Table/Table.less +++ b/components/dash-table/src/dash-table/components/Table/Table.less @@ -703,11 +703,10 @@ } .column-actions { display: flex; - flex-wrap: wrap; } .column-header-name { - margin-left: auto; + flex-grow: 1; } [class^='column-header--'], [class^='dash-filter--'] { diff --git a/components/dash-table/src/dash-table/components/Table/style.ts b/components/dash-table/src/dash-table/components/Table/style.ts index dcb1253b77..5589e9487d 100644 --- a/components/dash-table/src/dash-table/components/Table/style.ts +++ b/components/dash-table/src/dash-table/components/Table/style.ts @@ -1,3 +1,5 @@ +// NOTE: need to pin fontawesome-svg-core to <1.3 and free-*-svg-icons to <6 +// or we break IE11 import {library} from '@fortawesome/fontawesome-svg-core'; import {faEyeSlash, faTrashAlt} from '@fortawesome/free-regular-svg-icons'; import { diff --git a/components/dash-table/tests/selenium/test_column.py b/components/dash-table/tests/selenium/test_column.py index 15e140bade..3b9e305f8c 100644 --- a/components/dash-table/tests/selenium/test_column.py +++ b/components/dash-table/tests/selenium/test_column.py @@ -20,6 +20,9 @@ def get_app(props=dict()): baseProps["filter_action"] = "native" baseProps["merge_duplicate_headers"] = True + # first col is normally only 60px, make it wider since we're adding + # all these actions and need to interact with them + baseProps["style_cell_conditional"][0].update(width=120, maxWidth=120, minWidth=120) baseProps.update(props) app.layout = DataTable(**baseProps) diff --git a/components/dash-table/tests/visual/percy-storybook/Header.percy.tsx b/components/dash-table/tests/visual/percy-storybook/Header.percy.tsx index 37fc4d8015..558380acb1 100644 --- a/components/dash-table/tests/visual/percy-storybook/Header.percy.tsx +++ b/components/dash-table/tests/visual/percy-storybook/Header.percy.tsx @@ -5,30 +5,78 @@ import DataTable from 'dash-table/dash/DataTable'; const setProps = () => {}; -storiesOf('DashTable/Headers', module).add('multi header', () => ( - ({ - year: i, - montreal: i * 10, - toronto: i * 100, - ottawa: i * -1, - vancouver: i * -10, - temp: i * -100, - humidity: i * 0.1 - }), - R.range(0, 100) - )} - columns={[ - {name: ['Year', ''], id: 'year'}, - {name: ['City', 'Montreal'], id: 'montreal'}, - {name: ['City', 'Toronto'], id: 'toronto'}, - {name: ['City', 'Ottawa'], id: 'ottawa'}, - {name: ['City', 'Vancouver'], id: 'vancouver'}, - {name: ['Climate', 'Temperature'], id: 'temp'}, - {name: ['Climate', 'Humidity'], id: 'humidity'} - ]} - /> -)); +const data = [ + { + a: 'A', + b: 'BBBBB', + c: 'CCCCCCCCCC', + d: 'DDDDDDDDDDDDDDD', + e: 'EEEEEEEEEEEEEEEEEEEE', + f: 'FFFFFFFFFFFFFFFFFFFFFFFFF' + } +]; +const cols = ['a', 'b', 'c', 'd', 'e', 'f'].map(i => ({ + name: `Column ${i.toUpperCase()}`, + id: i, + selectable: true +})); +const colsEditable = cols.map(col => ({ + editable: true, + renamable: true, + deletable: true, + ...col +})); +const common = {style_table: {width: 'auto', marginBottom: '10px'}}; +const allActions = { + sort_action: 'native', + column_selectable: 'single', + editable: true +}; + +const alignments: [React.ReactNode?] = []; + +[{}, {sort_action: 'native'}, allActions].forEach(actionProps => { + ['left', 'center', 'right'].forEach(alignment => { + alignments.push( + + ); + }); +}); + +storiesOf('DashTable/Headers', module) + .add('multi header', () => ( + ({ + year: i, + montreal: i * 10, + toronto: i * 100, + ottawa: i * -1, + vancouver: i * -10, + temp: i * -100, + humidity: i * 0.1 + }), + R.range(0, 100) + )} + columns={[ + {name: ['Year', ''], id: 'year'}, + {name: ['City', 'Montreal'], id: 'montreal'}, + {name: ['City', 'Toronto'], id: 'toronto'}, + {name: ['City', 'Ottawa'], id: 'ottawa'}, + {name: ['City', 'Vancouver'], id: 'vancouver'}, + {name: ['Climate', 'Temperature'], id: 'temp'}, + {name: ['Climate', 'Humidity'], id: 'humidity'} + ]} + /> + )) + .add('alignment and actions', () => ( +
{alignments}
+ )); diff --git a/components/dash-table/tests/visual/percy-storybook/TriadValidation.percy.tsx b/components/dash-table/tests/visual/percy-storybook/TriadValidation.percy.tsx index 8ea9b8c79b..712c36a61e 100644 --- a/components/dash-table/tests/visual/percy-storybook/TriadValidation.percy.tsx +++ b/components/dash-table/tests/visual/percy-storybook/TriadValidation.percy.tsx @@ -8,22 +8,33 @@ const actions = [TableAction.Native, TableAction.Custom]; const setProps = () => {}; -let stories = storiesOf('DashTable/Props Validation', module); +const elements: [React.ReactNode?] = []; actions.forEach(filter => { actions.forEach(sort => { actions.forEach(page => { - stories = stories.add( - `filter=${filter}, sorting=${sort}, pagination=${page}`, - () => ( - - ) + elements.push( +
{`filter=${filter}, sorting=${sort}, pagination=${page}`}
+ ); + elements.push( + ); }); }); }); + +storiesOf('DashTable/Props Validation', module).add('all variants', () => ( +
{elements}
+)); diff --git a/components/dash-table/tests/visual/percy-storybook/Types.percy.tsx b/components/dash-table/tests/visual/percy-storybook/Types.percy.tsx index 02a585e3bf..fb20807f4b 100644 --- a/components/dash-table/tests/visual/percy-storybook/Types.percy.tsx +++ b/components/dash-table/tests/visual/percy-storybook/Types.percy.tsx @@ -14,8 +14,8 @@ const columns: {name: string[]; id: string; presentation?: string}[] = [ const columns_dd = columns.map(i => ({...i, presentation: 'dropdown'})); -storiesOf('DashTable/Types', module) - .add('types input', () => ( +storiesOf('DashTable/Types', module).add('types input & dropdown', () => ( +
- )) - .add('types dropdown', () => ( - )); +
+)); diff --git a/components/dash-table/tests/visual/percy-storybook/Width.all.percy.tsx b/components/dash-table/tests/visual/percy-storybook/Width.all.percy.tsx index cc74b39e26..74a3aaf161 100644 --- a/components/dash-table/tests/visual/percy-storybook/Width.all.percy.tsx +++ b/components/dash-table/tests/visual/percy-storybook/Width.all.percy.tsx @@ -19,7 +19,53 @@ const data = (() => { ); })(); -const baseProps = { +const basePropsDflts = { + setProps, + fill_width: false, + id: 'table', + data +}; + +const propsDflts = Object.assign({}, basePropsDflts, { + columns: columns.map(id => ({id: id, name: id.toUpperCase()})) +}); + +const basePropsWidth = { + setProps, + fill_width: false, + id: 'table', + data +}; + +const propsWidth = Object.assign({}, basePropsWidth, { + columns: columns.map(id => ({id: id, name: id.toUpperCase(), width: 20})) +}); + +const basePropsMax = { + setProps, + fill_width: false, + id: 'table', + data, + style_data_conditional: [{max_width: 10}] +}; + +const propsMax = Object.assign({}, basePropsMax, { + columns: columns.map(id => ({id: id, name: id.toUpperCase()})) +}); + +const basePropsMin = { + setProps, + fill_width: false, + id: 'table', + data +}; + +const propsMin = Object.assign({}, basePropsMin, { + columns: columns.map(id => ({id: id, name: id.toUpperCase()})), + style_data_conditional: [{min_width: 100}] +}); + +const basePropsAll = { setProps, id: 'table', data, @@ -29,22 +75,80 @@ const baseProps = { ] }; -const props = Object.assign({}, baseProps, { +const propsAll = Object.assign({}, basePropsAll, { columns: columns.map(id => ({id: id, name: id.toUpperCase()})) }); -storiesOf('DashTable/Width width, minWidth, maxWidth', module) - .add('without frozen columns or rows', () => ) - .add('with frozen rows', () => ( - - )) - .add('with frozen columns', () => ( - - )) - .add('with frozen rows and frozen columns', () => ( - - )); +const basePropsPct = { + setProps, + id: 'table', + data +}; + +const propsPct = Object.assign({}, basePropsPct, { + columns: columns.map(id => ({id: id, name: id.toUpperCase()})), + style_cell: { + width: '33%' + }, + style_table: { + width: '100%', + min_width: '100%', + max_width: '100%' + }, + css: [ + { + selector: '.dash-fixed-column', + rule: 'width: 33%;' + } + ] +}); + +const makeVariants = + ( + title: string, + props: + | ({ + setProps: () => void; + id: string; + data: any[]; + fill_width: boolean; + style_data_conditional: { + width: string; + min_width: string; + max_width: string; + }[]; + } & {columns: {id: string; name: string}[]}) + | (JSX.IntrinsicAttributes & + JSX.IntrinsicClassAttributes & + Readonly & + Readonly<{children?: React.ReactNode}>) + ) => + () => + ( +
+
{title}
+
without frozen columns or rows
+ +
with frozen rows
+ +
with frozen columns
+ +
with frozen rows and frozen columns
+ +
+ ); + +storiesOf('DashTable/Width -', module) + .add('defaults', makeVariants('defaults', propsDflts)) + .add('width only', makeVariants('width only', propsWidth)) + .add('maxWidth only', makeVariants('maxWidth only', propsMax)) + .add('minWidth only', makeVariants('minWidth only', propsMin)) + .add( + 'width, minWidth, maxWidth', + makeVariants('width, minWidth, maxWidth', propsAll) + ) + .add('percentage', makeVariants('percentage', propsPct)); diff --git a/components/dash-table/tests/visual/percy-storybook/Width.defaults.percy.tsx b/components/dash-table/tests/visual/percy-storybook/Width.defaults.percy.tsx deleted file mode 100644 index fc68664dff..0000000000 --- a/components/dash-table/tests/visual/percy-storybook/Width.defaults.percy.tsx +++ /dev/null @@ -1,47 +0,0 @@ -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'; - -const setProps = () => {}; - -const columns = ['a', 'b', 'c']; - -const data = (() => { - const r = random(1); - - return R.range(0, 5).map(() => - ['a', 'b', 'c'].reduce((obj: any, key) => { - obj[key] = Math.floor(r() * 1000); - return obj; - }, {}) - ); -})(); - -const baseProps = { - setProps, - fill_width: false, - id: 'table', - data -}; - -const props = Object.assign({}, baseProps, { - columns: columns.map(id => ({id: id, name: id.toUpperCase()})) -}); - -storiesOf('DashTable/Width defaults', module) - .add('without frozen columns or rows', () => ) - .add('with frozen rows', () => ( - - )) - .add('with frozen columns', () => ( - - )) - .add('with frozen rows and frozen columns', () => ( - - )); diff --git a/components/dash-table/tests/visual/percy-storybook/Width.empty.percy.tsx b/components/dash-table/tests/visual/percy-storybook/Width.empty.percy.tsx index 20b8a54341..559309a0e2 100644 --- a/components/dash-table/tests/visual/percy-storybook/Width.empty.percy.tsx +++ b/components/dash-table/tests/visual/percy-storybook/Width.empty.percy.tsx @@ -34,33 +34,33 @@ const props = Object.assign({}, baseProps, { columns: columns.map(id => ({id: id, name: id.toUpperCase()})) }); -storiesOf('DashTable/Empty', module) - .add('with column filters -- no query', () => ) - .add('with column filters -- invalid query', () => ( +storiesOf('DashTable/Empty', module).add('all variants', () => ( +
+
with column filters -- no query
+ +
with column filters -- invalid query
- )) - .add('with column filters -- single query', () => ( +
with column filters -- single query
- )) - .add('with column filters -- multi query', () => ( +
with column filters -- multi query
- )) - .add('with column filters -- multi query, no data', () => ( +
with column filters -- multi query, no data
- )); +
+)); diff --git a/components/dash-table/tests/visual/percy-storybook/Width.max.percy.tsx b/components/dash-table/tests/visual/percy-storybook/Width.max.percy.tsx deleted file mode 100644 index 8b46672ffb..0000000000 --- a/components/dash-table/tests/visual/percy-storybook/Width.max.percy.tsx +++ /dev/null @@ -1,48 +0,0 @@ -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'; - -const setProps = () => {}; - -const columns = ['a', 'b', 'c']; - -const data = (() => { - const r = random(1); - - return R.range(0, 5).map(() => - ['a', 'b', 'c'].reduce((obj: any, key) => { - obj[key] = Math.floor(r() * 1000); - return obj; - }, {}) - ); -})(); - -const baseProps = { - setProps, - fill_width: false, - id: 'table', - data, - style_data_conditional: [{max_width: 10}] -}; - -const props = Object.assign({}, baseProps, { - columns: columns.map(id => ({id: id, name: id.toUpperCase()})) -}); - -storiesOf('DashTable/Width maxWidth only', module) - .add('without frozen columns or rows', () => ) - .add('with frozen rows', () => ( - - )) - .add('with frozen columns', () => ( - - )) - .add('with frozen rows and frozen columns', () => ( - - )); diff --git a/components/dash-table/tests/visual/percy-storybook/Width.min.percy.tsx b/components/dash-table/tests/visual/percy-storybook/Width.min.percy.tsx deleted file mode 100644 index a26e0a7c8f..0000000000 --- a/components/dash-table/tests/visual/percy-storybook/Width.min.percy.tsx +++ /dev/null @@ -1,48 +0,0 @@ -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'; - -const setProps = () => {}; - -const columns = ['a', 'b', 'c']; - -const data = (() => { - const r = random(1); - - return R.range(0, 5).map(() => - ['a', 'b', 'c'].reduce((obj: any, key) => { - obj[key] = Math.floor(r() * 1000); - return obj; - }, {}) - ); -})(); - -const baseProps = { - setProps, - fill_width: false, - id: 'table', - data -}; - -const props = Object.assign({}, baseProps, { - columns: columns.map(id => ({id: id, name: id.toUpperCase()})), - style_data_conditional: [{min_width: 100}] -}); - -storiesOf('DashTable/Width minWidth only', module) - .add('without frozen columns or rows', () => ) - .add('with frozen rows', () => ( - - )) - .add('with frozen columns', () => ( - - )) - .add('with frozen rows and frozen columns', () => ( - - )); diff --git a/components/dash-table/tests/visual/percy-storybook/Width.percentages.percy.tsx b/components/dash-table/tests/visual/percy-storybook/Width.percentages.percy.tsx deleted file mode 100644 index 072ab7071b..0000000000 --- a/components/dash-table/tests/visual/percy-storybook/Width.percentages.percy.tsx +++ /dev/null @@ -1,60 +0,0 @@ -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'; - -const setProps = () => {}; - -const columns = ['a', 'b', 'c']; - -const data = (() => { - const r = random(1); - - return R.range(0, 5).map(() => - ['a', 'b', 'c'].reduce((obj: any, key) => { - obj[key] = Math.floor(r() * 1000); - return obj; - }, {}) - ); -})(); - -const baseProps = { - setProps, - id: 'table', - data -}; - -const props = Object.assign({}, baseProps, { - columns: columns.map(id => ({id: id, name: id.toUpperCase()})), - style_cell: { - width: '33%' - }, - style_table: { - width: '100%', - min_width: '100%', - max_width: '100%' - }, - css: [ - { - selector: '.dash-fixed-column', - rule: 'width: 33%;' - } - ] -}); - -storiesOf('DashTable/Width percentages', module) - .add('without frozen columns or rows', () => ) - .add('with frozen rows', () => ( - - )) - .add('with frozen columns', () => ( - - )) - .add('with frozen rows and frozen columns', () => ( - - )); diff --git a/components/dash-table/tests/visual/percy-storybook/Width.width.percy.tsx b/components/dash-table/tests/visual/percy-storybook/Width.width.percy.tsx deleted file mode 100644 index 6928bf450f..0000000000 --- a/components/dash-table/tests/visual/percy-storybook/Width.width.percy.tsx +++ /dev/null @@ -1,47 +0,0 @@ -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'; - -const setProps = () => {}; - -const columns = ['a', 'b', 'c']; - -const data = (() => { - const r = random(1); - - return R.range(0, 5).map(() => - ['a', 'b', 'c'].reduce((obj: any, key) => { - obj[key] = Math.floor(r() * 1000); - return obj; - }, {}) - ); -})(); - -const baseProps = { - setProps, - fill_width: false, - id: 'table', - data -}; - -const props = Object.assign({}, baseProps, { - columns: columns.map(id => ({id: id, name: id.toUpperCase(), width: 20})) -}); - -storiesOf('DashTable/Width width only', module) - .add('without frozen columns or rows', () => ) - .add('with frozen rows', () => ( - - )) - .add('with frozen columns', () => ( - - )) - .add('with frozen rows and frozen columns', () => ( - - )); diff --git a/dash/dash-renderer/package.json b/dash/dash-renderer/package.json index 36e7d0d0ee..6f8f19d510 100644 --- a/dash/dash-renderer/package.json +++ b/dash/dash-renderer/package.json @@ -13,7 +13,7 @@ "build:dev": "webpack", "build:local": "renderer build local", "build": "renderer build && npm run prepublishOnly", - "postbuild": "es-check es5 ../deps/*.js", + "postbuild": "es-check es5 ../deps/*.js build/*.js", "test": "karma start karma.conf.js --single-run", "format": "run-s private::format.*", "lint": "run-s private::lint.*" diff --git a/dash/dash-renderer/webpack.base.config.js b/dash/dash-renderer/webpack.base.config.js index 0952601440..67dc2fa91b 100644 --- a/dash/dash-renderer/webpack.base.config.js +++ b/dash/dash-renderer/webpack.base.config.js @@ -14,6 +14,20 @@ const defaults = { loader: 'babel-loader', }, }, + { + test: /\.jsx?$/, + include: /node_modules[\\\/](cytoscape-fcose)[\\\/]/, + use: { + loader: 'babel-loader', + options: { + babelrc: false, + configFile: false, + presets: [ + '@babel/preset-env' + ] + } + } + }, { test: /\.ts(x?)$/, exclude: /node_modules/, @@ -56,7 +70,11 @@ const rendererOptions = { module.exports = options => [ R.mergeAll([ options, - rendererOptions + rendererOptions, + { + // with default eval sourcemap we can't es-check the dev bundle + devtool: 'inline-source-map' + } ]), R.mergeAll([ options, diff --git a/dash/development/update_components.py b/dash/development/update_components.py index 8e85be0e51..26c0170c76 100644 --- a/dash/development/update_components.py +++ b/dash/development/update_components.py @@ -42,20 +42,17 @@ def booststrap_components(components_source): status = proc.poll() if err: - print(err.decode(), file=sys.stderr) + print(("🛑 " if status else "") + err.decode(), file=sys.stderr) - if status == 0: + if status or not out: print( - "🟢 Finished installing npm dependencies for the following component packages: {} (status={}) 🟢".format( - source_glob, status - ), + "🚨 Failed installing npm dependencies for component packages: {source_glob} (status={status}) 🚨", file=sys.stderr, ) - if not out: + sys.exit(1) + else: print( - "Failed installing npm dependencies for the following component packages {} (status={})".format( - source_glob, status - ), + f"🟢 Finished installing npm dependencies for component packages: {source_glob} 🟢", file=sys.stderr, ) @@ -82,13 +79,11 @@ def build_components(components_source): status = proc.poll() if err: - print(err.decode(), file=sys.stderr) + print(("🛑 " if status else "") + err.decode(), file=sys.stderr) - if not out: + if status or not out: print( - "🟢 Finished updating the following component packages {} (status={}) 🟢".format( - source_glob, status - ), + f"🚨 Finished updating component packages: {source_glob} (status={status}) 🚨", file=sys.stderr, ) sys.exit(1) @@ -117,21 +112,18 @@ def build_components(components_source): if not os.path.exists(build_directory): print( - "Could not locate build artifacts. Check that the npm build process completed successfully for the given package: {}".format( - package - ) + "🚨 Could not locate build artifacts." + + " Check that the npm build process completed" + + f" successfully for package: {package} 🚨" ) + sys.exit(1) else: - print("🚚 Moving build artifacts from " + build_directory + " to Dash 🚚") + print(f"🚚 Moving build artifacts from {build_directory} to Dash 🚚") shutil.rmtree(dest_path) shutil.copytree(build_directory, dest_path) with open(os.path.join(dest_path, ".gitkeep"), "w"): pass - print( - "🟢 Finished moving build artifacts from " - + build_directory - + " to Dash 🟢" - ) + print(f"🟢 Finished moving build artifacts from {build_directory} to Dash 🟢") def cli(): @@ -143,7 +135,9 @@ def cli(): ) parser.add_argument( "components_source", - help="A glob string that matches the Dash component libraries to be updated (eg.'dash-table' // 'dash-core-components|dash-html-components' // 'all'). The default argument is 'all'.", + help="A glob string that matches the Dash component libraries to be updated" + " (eg.'dash-table' // 'dash-core-components|dash-html-components' // 'all')." + " The default argument is 'all'.", default="all", ) @@ -153,4 +147,5 @@ def cli(): build_components(args.components_source) -cli() +if __name__ == "__main__": + cli() diff --git a/dash/testing/browser.py b/dash/testing/browser.py index 30104c7582..d639a74cb4 100644 --- a/dash/testing/browser.py +++ b/dash/testing/browser.py @@ -20,10 +20,6 @@ MoveTargetOutOfBoundsException, ) -from webdriver_manager.chrome import ChromeDriverManager -from webdriver_manager.utils import ChromeType -from webdriver_manager.firefox import GeckoDriverManager - from dash.testing.wait import text_to_equal, style_to_equal, contains_text, until from dash.testing.dash_page import DashPageMixin from dash.testing.errors import DashAppLoadingError, BrowserError, TestingTimeoutError @@ -477,11 +473,7 @@ def _get_chrome(self): desired_capabilities=capabilities, ) if self._remote - else webdriver.Chrome( - ChromeDriverManager(chrome_type=ChromeType.GOOGLE).install(), - options=options, - desired_capabilities=capabilities, - ) + else webdriver.Chrome(options=options, desired_capabilities=capabilities) ) # https://bugs.chromium.org/p/chromium/issues/detail?id=696481 @@ -524,10 +516,7 @@ def _get_firefox(self): ) if self._remote else webdriver.Firefox( - executable_path=GeckoDriverManager().install(), - firefox_profile=fp, - options=options, - capabilities=capabilities, + firefox_profile=fp, options=options, capabilities=capabilities ) ) diff --git a/requires-testing.txt b/requires-testing.txt index 13973accb1..ee5aa609c4 100644 --- a/requires-testing.txt +++ b/requires-testing.txt @@ -7,4 +7,3 @@ pytest>=6.0.2 requests[security]>=2.21.0 selenium>=3.141.0 waitress>=1.4.4 -webdriver-manager>=3.5.1