diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000000..89395fb3d197e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,47 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + +A clear and concise description of what the bug is. + +### Expected results + +what you expected to happen. + +### Actual results + +what actually happens. + +#### Screenshots + +If applicable, add screenshots to help explain your problem. + +#### How to reproduce the bug + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +### Environment + +(please complete the following information): + +- superset version: [e.g. `v0.29`, `master`, `commit`] +- python version: `python --version` +- node.js version: `node -v` +- npm version: `npm -v` + +### Checklist + +Make sure these boxes are checked before submitting your issue - thank you! + +- [ ] I have checked the superset logs for python stacktraces and included it here as text if there are any. +- [ ] I have reproduced the issue with at least the latest released version of superset. +- [ ] I have checked the issue tracker for the same issue and I haven't found one similar. + +### Additional context + +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000000..066b2d920a28d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/sip.md b/.github/ISSUE_TEMPLATE/sip.md new file mode 100644 index 0000000000000..4e668b3366932 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/sip.md @@ -0,0 +1,31 @@ +--- +name: SIP +about: Superset Improvement Proposal + +--- + +## [SIP] Proposal for XXX + +### Motivation + +Description of the problem to be solved. + +### Proposed Change + +Describe how the feature will be implemented, or the problem will be solved. If possible, include mocks, screenshots, or screencasts (even if from different tools). + +### New or Changed Public Interfaces + +Describe any new additions to the model, views or `REST` endpoints. Describe any changes to existing visualizations, dashboards and React components. Describe changes that affect the Superset CLI and how Superset is deployed. + +### New dependencies + +Describe any `npm`/`PyPI` packages that are required. Are they actively maintained? What are their licenses? + +### Migration Plan and Compatibility + +Describe any database migrations that are necessary, or updates to stored URLs. + +### Rejected Alternatives + +Describe alternative approaches that were considered and rejected. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000000..d0984a7aaff6d --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,31 @@ +### CATEGORY + +Choose one + +- [ ] Bug Fix +- [ ] Enhancement (new features, refinement) +- [ ] Refactor +- [ ] Add tests +- [ ] Build / Development Environment +- [ ] Documentation + +### SUMMARY + + +### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF + + +### TEST PLAN + + +### ADDITIONAL INFORMATION + + +- [ ] Has associated issue: +- [ ] Changes UI +- [ ] Requires DB Migration. +- [ ] Confirm DB Migration upgrade and downgrade tested. +- [ ] Introduces new feature or API +- [ ] Removes existing feature or API + +### REVIEWERS diff --git a/.github/config.yml b/.github/config.yml new file mode 100644 index 0000000000000..23c1258d54058 --- /dev/null +++ b/.github/config.yml @@ -0,0 +1,15 @@ +# Configuration for request-info - https://github.com/behaviorbot/request-info + +# *Required* Comment to reply with +requestInfoReplyComment: > + We would appreciate it if you could provide us with more info about this issue/pr! + Please do not leave the `title` or `description` empty. + +# *OPTIONAL* default titles to check against for lack of descriptiveness +# MUST BE ALL LOWERCASE +requestInfoDefaultTitles: + - update readme.md + - updates + +# *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given +requestInfoLabelToAdd: "need:more-info" diff --git a/.github/issue_label_bot.yaml b/.github/issue_label_bot.yaml new file mode 100644 index 0000000000000..8af21514c3d9c --- /dev/null +++ b/.github/issue_label_bot.yaml @@ -0,0 +1,5 @@ +# for Issue Label Bot https://github.com/marketplace/issue-label-bot +label-alias: + bug: '#bug' + feature_request: '#enhancement' + question: '#question' diff --git a/.github/move.yml b/.github/move.yml new file mode 100644 index 0000000000000..3c4320b5cd024 --- /dev/null +++ b/.github/move.yml @@ -0,0 +1,27 @@ +# Configuration for Move Issues - https://github.com/dessant/move-issues + +# Delete the command comment when it contains no other content +deleteCommand: true + +# Close the source issue after moving +closeSourceIssue: true + +# Lock the source issue after moving +lockSourceIssue: false + +# Mention issue and comment authors +mentionAuthors: true + +# Preserve mentions in the issue content +keepContentMentions: false + +# Move labels that also exist on the target repository +moveLabels: true + +# Set custom aliases for targets +# aliases: +# r: repo +# or: owner/repo + +# Repository to extend settings from +# _extends: repo diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000000000..bf5e23ad2fe2b --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,19 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 +# Issues with these labels will never be considered stale +exemptLabels: + - "#SIP" + - ".pinned" + - ".security" +# Label to use when marking an issue as stale +staleLabel: inactive +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. + Thank you for your contributions. For admin, please label this issue `.pinned` + to prevent stale bot from closing the issue. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false diff --git a/.rat-excludes b/.rat-excludes index 46a5af02e5a3b..61d68b54dbb05 100644 --- a/.rat-excludes +++ b/.rat-excludes @@ -38,3 +38,5 @@ searchindex.js requirements.txt # vendorized vendor/* +# github configuration +.github/* diff --git a/.travis.yml b/.travis.yml index 32af2be1f4d64..9d4c523ed67e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,8 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # -cache: - pip: true jobs: include: - language: python diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 36ed5733763ed..cdca9cbe242d1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -385,9 +385,6 @@ npm run dev # Compile the Javascript and CSS in production/optimized mode for official releases npm run prod - -# Copy a conf file from the frontend to the backend -npm run sync-backend ``` #### Updating NPM packages diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md deleted file mode 100644 index 5de6cb6b0a799..0000000000000 --- a/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,37 +0,0 @@ - -Make sure these boxes are checked before submitting your issue - thank you! - -- [ ] I have checked the superset logs for python stacktraces and included it here as text if there are any. -- [ ] I have reproduced the issue with at least the latest released version of superset. -- [ ] I have checked the issue tracker for the same issue and I haven't found one similar. - - -### Superset version - - -### Expected results - - -### Actual results - - -### Steps to reproduce - - diff --git a/LICENSE.txt b/LICENSE.txt index 7c902fb0c0cc5..ff54f7b4211d6 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -231,5 +231,3 @@ BSD 3-Clause licenses ======================================================================== Creative Commons Attribution 4.0 ======================================================================== - - (Creative Commons Attribution 4.0) diva-gis (http://www.diva-gis.org/Data) \ No newline at end of file diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 012fb23efd75c..0000000000000 --- a/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,41 +0,0 @@ - -##### SUMMARY - - -##### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF - - -##### TEST PLAN - - -##### ADDITIONAL INFORMATION - - - [ ] Has associated issue: - [ ] Changes UI - [ ] Requires DB Migration. Confirm DB Migration upgrade and downgrade tested. - [ ] Introduces new feature or API - [ ] Removes existing feature or API - [ ] Fixes bug - [ ] Refactors code - [ ] Adds test(s) - -##### REVIEWERS - diff --git a/RELEASING.md b/RELEASING.md index 45db9e20f592e..4783ba6ddccc8 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -51,6 +51,8 @@ git push origin master You'll probably want to run these commands manually and understand what they do prior to doing so. +## Release setup + First you need to setup a few things. This is a one-off and doesn't need to be done at every release. @@ -59,7 +61,10 @@ need to be done at every release. gpg --gen-key # Checkout ASF dist repo - svn checkout https://dist.apache.org/repos/dist/dev/incubator/superset/ ~/svn/superset + + svn checkout https://dist.apache.org/repos/dist/dev/incubator/superset/ ~/svn/superset_dev + + svn checkout https://dist.apache.org/repos/dist/incubator/superset/ ~/svn/superset cd ~/svn/superset @@ -72,6 +77,8 @@ need to be done at every release. svn commit -m "Add PGP keys of new Superset committer" ``` +## Crafting tarball and signatures + Now let's craft a source release ```bash # Assuming these commands are executed from the root of the repo @@ -87,23 +94,46 @@ Now let's craft a source release # Alternatively you could clone the repo into another location as in # git clone git@github.com:apache/incubator-superset.git superset-releases git clean -fxd + # Create the target folder + mkdir -p ~/svn/superset_dev/${VERSION}/ git archive \ --format=tar.gz ${VERSION} \ --prefix=apache-superset-${VERSION}/ \ - -o apache-superset-${VERSION}-source.tar.gz + -o ~/svn/superset_dev/${VERSION}/apache-superset-${VERSION}-source.tar.gz + cd ~/svn/superset_dev/ scripts/sign.sh apache-superset-${VERSION}-source.tar.gz ``` -Now let's ship this into svn +## Shipping to SVN + +Now let's ship this RC into svn's dev folder ```bash # cp or mv the files over to the svn repo - mkdir ~/svn/superset/${VERSION}/ - cp apache-superset-${VERSION}* ~/svn/superset/${VERSION}/ + mkdir ~/svn/superset_dev/${VERSION}/ + cp apache-superset-${VERSION}* ~/svn/superset_dev/${VERSION}/ + cd ~/svn/superset_dev/ + svn add ${VERSION} + svn commit +``` + +Now you're ready to start the VOTE thread. + +## Validating a release + +https://www.apache.org/info/verification.html + +## Publishing a successful release + +Upon a successful vote, you'll have to copy the folder into the non-"dev/" +folder. +```bash + cp -r ~/svn/superset_dev/${VERSION}/ ~/svn/superset/${VERSION}/ cd ~/svn/superset/ svn add ${VERSION} svn commit ``` -Now you're ready to announce the release on the mailing list +Now you can announce the release on the mailing list, make sure to use the +proper template diff --git a/UPDATING.md b/UPDATING.md index 27ea5716eb70f..f8d64ab48ec9a 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -21,10 +21,27 @@ under the License. This file documents any backwards-incompatible changes in Superset and assists people when migrating to a new version. +## Superset 0.34.0 + +* [5451](https://github.com/apache/incubator-superset/pull/5451): a change +which adds missing non-nullable fields to the `datasources` table. Depending on +the integrity of the data, manual intervention may be required. + +* [5452](https://github.com/apache/incubator-superset/pull/5452): a change +which adds missing non-nullable fields and uniqueness constraints to the +`columns`and `table_columns` tables. Depending on the integrity of the data, +manual intervention may be required. + +* [5453](https://github.com/apache/incubator-superset/pull/5453): a change +which adds missing non-nullable fields and uniqueness constraints to the metrics +and sql_metrics tables. Depending on the integrity of the data, manual +intervention may be required. + ## Superset 0.32.0 -* [5445](https://github.com/apache/incubator-superset/pull/5445) : a change -which prevents encoding of empty string from form data in the datanbase. +* `npm run backend-sync` is deprecated and no longer needed, will fail if called +* [5445](https://github.com/apache/incubator-superset/pull/5445): a change +which prevents encoding of empty string from form data in the database. This involves a non-schema changing migration which does potentially impact a large number of records. Scheduled downtime may be advised. diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index da3a9b1bd33c9..becfb00b2668f 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -FROM python:3.6 +FROM python:3.6-jessie RUN useradd --user-group --create-home --no-log-init --shell /bin/bash superset @@ -59,7 +59,6 @@ USER superset RUN cd superset/assets \ && npm ci \ - && npm run sync-backend \ && npm run build \ && rm -rf node_modules diff --git a/contrib/docker/docker-compose.yml b/contrib/docker/docker-compose.yml index b4d3f1836a53c..cd9b31e074951 100644 --- a/contrib/docker/docker-compose.yml +++ b/contrib/docker/docker-compose.yml @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -version: '3' +version: '2' services: redis: image: redis:3.2 diff --git a/contrib/docker/docker-entrypoint.sh b/contrib/docker/docker-entrypoint.sh index 24bdb974479c6..474a5836b2604 100755 --- a/contrib/docker/docker-entrypoint.sh +++ b/contrib/docker/docker-entrypoint.sh @@ -22,7 +22,7 @@ if [ "$#" -ne 0 ]; then elif [ "$SUPERSET_ENV" = "development" ]; then celery worker --app=superset.sql_lab:celery_app --pool=gevent -Ofair & # needed by superset runserver - (cd superset/assets/ && npm ci && npm run sync-backend) + (cd superset/assets/ && npm ci) (cd superset/assets/ && npm run dev) & FLASK_ENV=development FLASK_APP=superset:app flask run -p 8088 --with-threads --reload --debugger --host=0.0.0.0 elif [ "$SUPERSET_ENV" = "production" ]; then diff --git a/docs/conf.py b/docs/conf.py index 186b790eb5f5b..80d6de17cbeb4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -65,7 +65,7 @@ # General information about the project. project = "Apache Superset" -copyright = 'Copyright © 2018 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.' +copyright = 'Copyright © 2019 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.' author = u'Apache Superset Dev' # The version info for the project you're documenting, acts as replacement for @@ -194,7 +194,7 @@ html_show_sphinx = False # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -html_show_copyright = True +html_show_copyright = False # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the diff --git a/superset/__init__.py b/superset/__init__.py index 69ad1f54d1489..7d0df26e039e7 100644 --- a/superset/__init__.py +++ b/superset/__init__.py @@ -45,9 +45,6 @@ if not os.path.exists(config.DATA_DIR): os.makedirs(config.DATA_DIR) -with open(APP_DIR + '/static/assets/backendSync.json', 'r', encoding='utf-8') as f: - frontend_config = json.load(f) - app = Flask(__name__) app.config.from_object(CONFIG_MODULE) conf = app.config diff --git a/superset/assets/backendSync.json b/superset/assets/backendSync.json deleted file mode 100644 index 2285f50ba6159..0000000000000 --- a/superset/assets/backendSync.json +++ /dev/null @@ -1,3796 +0,0 @@ -{ - "controls": { - "metrics": { - "type": "MetricsControl", - "multi": true, - "label": "Metrics", - "validators": [ - null - ], - "description": "One or many metrics to display" - }, - "metric": { - "type": "MetricsControl", - "multi": false, - "label": "Metric", - "validators": [ - null - ], - "description": "One or many metrics to display" - }, - "datasource": { - "type": "DatasourceControl", - "label": "Datasource", - "default": null, - "description": null - }, - "viz_type": { - "type": "VizTypeControl", - "label": "Visualization Type", - "default": "table", - "description": "The type of visualization to display" - }, - "percent_metrics": { - "type": "MetricsControl", - "multi": true, - "label": "Percentage Metrics", - "validators": [], - "default": [], - "description": "Metrics for which percentage of total are to be displayed" - }, - "y_axis_bounds": { - "type": "BoundsControl", - "label": "Y Axis Bounds", - "renderTrigger": true, - "default": [ - null, - null - ], - "description": "Bounds for the Y-axis. When left empty, the bounds are dynamically defined based on the min/max of the data. Note that this feature will only expand the axis range. It won't narrow the data's extent." - }, - "order_by_cols": { - "type": "SelectControl", - "multi": true, - "label": "Ordering", - "default": [], - "description": "One or many metrics to display" - }, - "color_picker": { - "label": "Fixed Color", - "description": "Use this to define a static color for all circles", - "type": "ColorPickerControl", - "default": { - "r": 0, - "g": 122, - "b": 135, - "a": 1 - }, - "renderTrigger": true - }, - "target_color_picker": { - "label": "Target Color", - "description": "Color of the target location", - "type": "ColorPickerControl", - "default": { - "r": 0, - "g": 122, - "b": 135, - "a": 1 - }, - "renderTrigger": true - }, - "legend_position": { - "label": "Legend Position", - "description": "Choose the position of the legend", - "type": "SelectControl", - "clearable": false, - "default": "tr", - "choices": [ - [ - null, - "None" - ], - [ - "tl", - "Top left" - ], - [ - "tr", - "Top right" - ], - [ - "bl", - "Bottom left" - ], - [ - "br", - "Bottom right" - ] - ], - "renderTrigger": true - }, - "fill_color_picker": { - "label": "Fill Color", - "description": " Set the opacity to 0 if you do not want to override the color specified in the GeoJSON", - "type": "ColorPickerControl", - "default": { - "r": 0, - "g": 122, - "b": 135, - "a": 1 - }, - "renderTrigger": true - }, - "stroke_color_picker": { - "label": "Stroke Color", - "description": " Set the opacity to 0 if you do not want to override the color specified in the GeoJSON", - "type": "ColorPickerControl", - "default": { - "r": 0, - "g": 122, - "b": 135, - "a": 1 - }, - "renderTrigger": true - }, - "metric_2": { - "type": "MetricsControl", - "multi": false, - "label": "Right Axis Metric", - "validators": [ - null - ], - "description": "Choose a metric for right axis", - "clearable": true - }, - "stacked_style": { - "type": "SelectControl", - "label": "Stacked Style", - "renderTrigger": true, - "choices": [ - [ - "stack", - "stack" - ], - [ - "stream", - "stream" - ], - [ - "expand", - "expand" - ] - ], - "default": "stack", - "description": "" - }, - "sort_x_axis": { - "type": "SelectControl", - "label": "Sort X Axis", - "choices": [ - [ - "alpha_asc", - "Axis ascending" - ], - [ - "alpha_desc", - "Axis descending" - ], - [ - "value_asc", - "sum(value) ascending" - ], - [ - "value_desc", - "sum(value) descending" - ] - ], - "clearable": false, - "default": "alpha_asc" - }, - "sort_y_axis": { - "type": "SelectControl", - "label": "Sort Y Axis", - "choices": [ - [ - "alpha_asc", - "Axis ascending" - ], - [ - "alpha_desc", - "Axis descending" - ], - [ - "value_asc", - "sum(value) ascending" - ], - [ - "value_desc", - "sum(value) descending" - ] - ], - "clearable": false, - "default": "alpha_asc" - }, - "linear_color_scheme": { - "type": "ColorSchemeControl", - "label": "Linear Color Scheme", - "default": "blue_white_yellow", - "clearable": false, - "description": "", - "renderTrigger": true, - "isLinear": true - }, - "normalize_across": { - "type": "SelectControl", - "label": "Normalize Across", - "choices": [ - [ - "heatmap", - "heatmap" - ], - [ - "x", - "x" - ], - [ - "y", - "y" - ] - ], - "default": "heatmap", - "description": "Color will be rendered based on a ratio of the cell against the sum of across this criteria" - }, - "horizon_color_scale": { - "type": "SelectControl", - "renderTrigger": true, - "label": "Value Domain", - "choices": [ - [ - "series", - "series" - ], - [ - "overall", - "overall" - ], - [ - "change", - "change" - ] - ], - "default": "series", - "description": "series: Treat each series independently; overall: All series use the same scale; change: Show changes compared to the first data point in each series" - }, - "canvas_image_rendering": { - "type": "SelectControl", - "label": "Rendering", - "renderTrigger": true, - "choices": [ - [ - "pixelated", - "pixelated (Sharp)" - ], - [ - "auto", - "auto (Smooth)" - ] - ], - "default": "pixelated", - "description": "image-rendering CSS attribute of the canvas object that defines how the browser scales up the image" - }, - "xscale_interval": { - "type": "SelectControl", - "label": "XScale Interval", - "renderTrigger": true, - "choices": [ - [ - 1, - "1" - ], - [ - 2, - "2" - ], - [ - 3, - "3" - ], - [ - 4, - "4" - ], - [ - 5, - "5" - ], - [ - 6, - "6" - ], - [ - 7, - "7" - ], - [ - 8, - "8" - ], - [ - 9, - "9" - ], - [ - 10, - "10" - ], - [ - 11, - "11" - ], - [ - 12, - "12" - ], - [ - 13, - "13" - ], - [ - 14, - "14" - ], - [ - 15, - "15" - ], - [ - 16, - "16" - ], - [ - 17, - "17" - ], - [ - 18, - "18" - ], - [ - 19, - "19" - ], - [ - 20, - "20" - ], - [ - 21, - "21" - ], - [ - 22, - "22" - ], - [ - 23, - "23" - ], - [ - 24, - "24" - ], - [ - 25, - "25" - ], - [ - 26, - "26" - ], - [ - 27, - "27" - ], - [ - 28, - "28" - ], - [ - 29, - "29" - ], - [ - 30, - "30" - ], - [ - 31, - "31" - ], - [ - 32, - "32" - ], - [ - 33, - "33" - ], - [ - 34, - "34" - ], - [ - 35, - "35" - ], - [ - 36, - "36" - ], - [ - 37, - "37" - ], - [ - 38, - "38" - ], - [ - 39, - "39" - ], - [ - 40, - "40" - ], - [ - 41, - "41" - ], - [ - 42, - "42" - ], - [ - 43, - "43" - ], - [ - 44, - "44" - ], - [ - 45, - "45" - ], - [ - 46, - "46" - ], - [ - 47, - "47" - ], - [ - 48, - "48" - ], - [ - 49, - "49" - ], - [ - 50, - "50" - ] - ], - "default": "1", - "clearable": false, - "description": "Number of steps to take between ticks when displaying the X scale" - }, - "yscale_interval": { - "type": "SelectControl", - "label": "YScale Interval", - "choices": [ - [ - 1, - "1" - ], - [ - 2, - "2" - ], - [ - 3, - "3" - ], - [ - 4, - "4" - ], - [ - 5, - "5" - ], - [ - 6, - "6" - ], - [ - 7, - "7" - ], - [ - 8, - "8" - ], - [ - 9, - "9" - ], - [ - 10, - "10" - ], - [ - 11, - "11" - ], - [ - 12, - "12" - ], - [ - 13, - "13" - ], - [ - 14, - "14" - ], - [ - 15, - "15" - ], - [ - 16, - "16" - ], - [ - 17, - "17" - ], - [ - 18, - "18" - ], - [ - 19, - "19" - ], - [ - 20, - "20" - ], - [ - 21, - "21" - ], - [ - 22, - "22" - ], - [ - 23, - "23" - ], - [ - 24, - "24" - ], - [ - 25, - "25" - ], - [ - 26, - "26" - ], - [ - 27, - "27" - ], - [ - 28, - "28" - ], - [ - 29, - "29" - ], - [ - 30, - "30" - ], - [ - 31, - "31" - ], - [ - 32, - "32" - ], - [ - 33, - "33" - ], - [ - 34, - "34" - ], - [ - 35, - "35" - ], - [ - 36, - "36" - ], - [ - 37, - "37" - ], - [ - 38, - "38" - ], - [ - 39, - "39" - ], - [ - 40, - "40" - ], - [ - 41, - "41" - ], - [ - 42, - "42" - ], - [ - 43, - "43" - ], - [ - 44, - "44" - ], - [ - 45, - "45" - ], - [ - 46, - "46" - ], - [ - 47, - "47" - ], - [ - 48, - "48" - ], - [ - 49, - "49" - ], - [ - 50, - "50" - ] - ], - "default": "1", - "clearable": false, - "renderTrigger": true, - "description": "Number of steps to take between ticks when displaying the Y scale" - }, - "include_time": { - "type": "CheckboxControl", - "label": "Include Time", - "description": "Whether to include the time granularity as defined in the time section", - "default": false - }, - "autozoom": { - "type": "CheckboxControl", - "label": "Auto Zoom", - "default": true, - "renderTrigger": true, - "description": "When checked, the map will zoom to your data after each query" - }, - "show_perc": { - "type": "CheckboxControl", - "label": "Show percentage", - "renderTrigger": true, - "description": "Whether to include the percentage in the tooltip", - "default": true - }, - "bar_stacked": { - "type": "CheckboxControl", - "label": "Stacked Bars", - "renderTrigger": true, - "default": false, - "description": null - }, - "pivot_margins": { - "type": "CheckboxControl", - "label": "Show totals", - "renderTrigger": false, - "default": true, - "description": "Display total row/column" - }, - "show_markers": { - "type": "CheckboxControl", - "label": "Show Markers", - "renderTrigger": true, - "default": false, - "description": "Show data points as circle markers on the lines" - }, - "show_bar_value": { - "type": "CheckboxControl", - "label": "Bar Values", - "default": false, - "renderTrigger": true, - "description": "Show the value on top of the bar" - }, - "order_bars": { - "type": "CheckboxControl", - "label": "Sort Bars", - "default": false, - "renderTrigger": true, - "description": "Sort bars by x labels." - }, - "combine_metric": { - "type": "CheckboxControl", - "label": "Combine Metrics", - "default": false, - "description": "Display metrics side by side within each column, as opposed to each column being displayed side by side for each metric." - }, - "show_controls": { - "type": "CheckboxControl", - "label": "Extra Controls", - "renderTrigger": true, - "default": false, - "description": "Whether to show extra controls or not. Extra controls include things like making mulitBar charts stacked or side by side." - }, - "reduce_x_ticks": { - "type": "CheckboxControl", - "label": "Reduce X ticks", - "renderTrigger": true, - "default": false, - "description": "Reduces the number of X-axis ticks to be rendered. If true, the x-axis will not overflow and labels may be missing. If false, a minimum width will be applied to columns and the width may overflow into an horizontal scroll." - }, - "include_series": { - "type": "CheckboxControl", - "label": "Include Series", - "renderTrigger": true, - "default": false, - "description": "Include series name as an axis" - }, - "secondary_metric": { - "type": "MetricsControl", - "multi": false, - "label": "Color Metric", - "validators": [], - "default": null, - "description": "A metric to use for color" - }, - "select_country": { - "type": "SelectControl", - "label": "Country Name", - "default": "France", - "choices": [ - [ - "Belgium", - "Belgium" - ], - [ - "Brazil", - "Brazil" - ], - [ - "Bulgaria", - "Bulgaria" - ], - [ - "China", - "China" - ], - [ - "Egypt", - "Egypt" - ], - [ - "France", - "France" - ], - [ - "Germany", - "Germany" - ], - [ - "Italy", - "Italy" - ], - [ - "Japan", - "Japan" - ], - [ - "Morocco", - "Morocco" - ], - [ - "Myanmar", - "Myanmar" - ], - [ - "Netherlands", - "Netherlands" - ], - [ - "Portugal", - "Portugal" - ], - [ - "Russia", - "Russia" - ], - [ - "Singapore", - "Singapore" - ], - [ - "Spain", - "Spain" - ], - [ - "Thailand", - "Thailand" - ], - [ - "Timorleste", - "Timorleste" - ], - [ - "Uk", - "Uk" - ], - [ - "Ukraine", - "Ukraine" - ], - [ - "Usa", - "Usa" - ], - [ - "Zambia", - "Zambia" - ] - ], - "description": "The name of the country that Superset should display" - }, - "country_fieldtype": { - "type": "SelectControl", - "label": "Country Field Type", - "default": "cca2", - "choices": [ - [ - "name", - "Full name" - ], - [ - "cioc", - "code International Olympic Committee (cioc)" - ], - [ - "cca2", - "code ISO 3166-1 alpha-2 (cca2)" - ], - [ - "cca3", - "code ISO 3166-1 alpha-3 (cca3)" - ] - ], - "description": "The country code standard that Superset should expect to find in the [country] column" - }, - "freq": { - "type": "SelectControl", - "label": "Frequency", - "default": "W-MON", - "freeForm": true, - "clearable": false, - "choices": [ - [ - "AS", - "Year (freq=AS)" - ], - [ - "52W-MON", - "52 weeks starting Monday (freq=52W-MON)" - ], - [ - "W-SUN", - "1 week starting Sunday (freq=W-SUN)" - ], - [ - "W-MON", - "1 week starting Monday (freq=W-MON)" - ], - [ - "D", - "Day (freq=D)" - ], - [ - "4W-MON", - "4 weeks (freq=4W-MON)" - ] - ], - "description": "The periodicity over which to pivot time. Users can provide\n \"Pandas\" offset alias.\n Click on the info bubble for more details on accepted \"freq\" expressions." - }, - "groupby": { - "type": "SelectControl", - "multi": true, - "label": "Group by", - "default": [], - "includeTime": false, - "description": "One or many controls to group by", - "valueKey": "column_name" - }, - "dimension": { - "type": "SelectControl", - "multi": false, - "label": "Dimension", - "default": null, - "includeTime": false, - "description": "Select a dimension", - "valueKey": "column_name" - }, - "columns": { - "type": "SelectControl", - "multi": true, - "label": "Columns", - "default": [], - "includeTime": false, - "description": "One or many controls to pivot as columns", - "valueKey": "column_name" - }, - "all_columns": { - "type": "SelectControl", - "multi": true, - "label": "Columns", - "default": [], - "description": "Columns to display", - "valueKey": "column_name" - }, - "spatial": { - "type": "SpatialControl", - "label": "Longitude & Latitude", - "validators": [ - null - ], - "description": "Point to your spatial columns" - }, - "start_spatial": { - "type": "SpatialControl", - "label": "Start Longitude & Latitude", - "validators": [ - null - ], - "description": "Point to your spatial columns" - }, - "end_spatial": { - "type": "SpatialControl", - "label": "End Longitude & Latitude", - "validators": [ - null - ], - "description": "Point to your spatial columns" - }, - "longitude": { - "type": "SelectControl", - "label": "Longitude", - "default": 1, - "validators": [ - null - ], - "description": "Select the longitude column" - }, - "latitude": { - "type": "SelectControl", - "label": "Latitude", - "default": 1, - "validators": [ - null - ], - "description": "Select the latitude column" - }, - "filter_nulls": { - "type": "CheckboxControl", - "label": "Ignore null locations", - "default": true, - "description": "Whether to ignore locations that are null" - }, - "geojson": { - "type": "SelectControl", - "label": "GeoJson Column", - "validators": [ - null - ], - "description": "Select the geojson column" - }, - "polygon": { - "type": "SelectControl", - "label": "Polygon Column", - "validators": [ - null - ], - "description": "Select the polygon column. Each row should contain JSON.array(N) of [longitude, latitude] points" - }, - "point_radius_scale": { - "type": "SelectControl", - "freeForm": true, - "label": "Point Radius Scale", - "validators": [ - null - ], - "default": null, - "choices": [ - [ - 0, - "0" - ], - [ - 100, - "100" - ], - [ - 200, - "200" - ], - [ - 300, - "300" - ], - [ - 500, - "500" - ] - ] - }, - "stroke_width": { - "type": "SelectControl", - "freeForm": true, - "label": "Stroke Width", - "validators": [ - null - ], - "default": null, - "renderTrigger": true, - "choices": [ - [ - 1, - "1" - ], - [ - 2, - "2" - ], - [ - 3, - "3" - ], - [ - 4, - "4" - ], - [ - 5, - "5" - ] - ] - }, - "all_columns_x": { - "type": "SelectControl", - "label": "X", - "default": null, - "description": "Columns to display" - }, - "all_columns_y": { - "type": "SelectControl", - "label": "Y", - "default": null, - "description": "Columns to display" - }, - "druid_time_origin": { - "type": "SelectControl", - "freeForm": true, - "label": "Origin", - "choices": [ - [ - "", - "default" - ], - [ - "now", - "now" - ] - ], - "default": null, - "description": "Defines the origin where time buckets start, accepts natural dates as in `now`, `sunday` or `1970-01-01`" - }, - "bottom_margin": { - "type": "SelectControl", - "clearable": false, - "freeForm": true, - "label": "Bottom Margin", - "choices": [ - [ - "auto", - "auto" - ], - [ - 50, - "50" - ], - [ - 75, - "75" - ], - [ - 100, - "100" - ], - [ - 125, - "125" - ], - [ - 150, - "150" - ], - [ - 200, - "200" - ] - ], - "default": "auto", - "renderTrigger": true, - "description": "Bottom margin, in pixels, allowing for more room for axis labels" - }, - "x_ticks_layout": { - "type": "SelectControl", - "label": "X Tick Layout", - "choices": [ - [ - "auto", - "auto" - ], - [ - "flat", - "flat" - ], - [ - "45°", - "45°" - ], - [ - "staggered", - "staggered" - ] - ], - "default": "auto", - "clearable": false, - "renderTrigger": true, - "description": "The way the ticks are laid out on the X-axis" - }, - "left_margin": { - "type": "SelectControl", - "freeForm": true, - "clearable": false, - "label": "Left Margin", - "choices": [ - [ - "auto", - "auto" - ], - [ - 50, - "50" - ], - [ - 75, - "75" - ], - [ - 100, - "100" - ], - [ - 125, - "125" - ], - [ - 150, - "150" - ], - [ - 200, - "200" - ] - ], - "default": "auto", - "renderTrigger": true, - "description": "Left margin, in pixels, allowing for more room for axis labels" - }, - "granularity": { - "type": "SelectControl", - "freeForm": true, - "label": "Time Granularity", - "default": "one day", - "choices": [ - [ - null, - "all" - ], - [ - "PT5S", - "5 seconds" - ], - [ - "PT30S", - "30 seconds" - ], - [ - "PT1M", - "1 minute" - ], - [ - "PT5M", - "5 minutes" - ], - [ - "PT30M", - "30 minutes" - ], - [ - "PT1H", - "1 hour" - ], - [ - "PT6H", - "6 hour" - ], - [ - "P1D", - "1 day" - ], - [ - "P7D", - "7 days" - ], - [ - "P1W", - "week" - ], - [ - "week_starting_sunday", - "week starting Sunday" - ], - [ - "week_ending_saturday", - "week ending Saturday" - ], - [ - "P1M", - "month" - ], - [ - "P3M", - "quarter" - ], - [ - "P1Y", - "year" - ] - ], - "description": "The time granularity for the visualization. Note that you can type and use simple natural language as in `10 seconds`, `1 day` or `56 weeks`" - }, - "domain_granularity": { - "type": "SelectControl", - "label": "Domain", - "default": "month", - "choices": [ - [ - "hour", - "hour" - ], - [ - "day", - "day" - ], - [ - "week", - "week" - ], - [ - "month", - "month" - ], - [ - "year", - "year" - ] - ], - "description": "The time unit used for the grouping of blocks" - }, - "subdomain_granularity": { - "type": "SelectControl", - "label": "Subdomain", - "default": "day", - "choices": [ - [ - "min", - "min" - ], - [ - "hour", - "hour" - ], - [ - "day", - "day" - ], - [ - "week", - "week" - ], - [ - "month", - "month" - ] - ], - "description": "The time unit for each block. Should be a smaller unit than domain_granularity. Should be larger or equal to Time Grain" - }, - "link_length": { - "type": "SelectControl", - "renderTrigger": true, - "freeForm": true, - "label": "Link Length", - "default": "200", - "choices": [ - [ - "10", - "10" - ], - [ - "25", - "25" - ], - [ - "50", - "50" - ], - [ - "75", - "75" - ], - [ - "100", - "100" - ], - [ - "150", - "150" - ], - [ - "200", - "200" - ], - [ - "250", - "250" - ] - ], - "description": "Link length in the force layout" - }, - "charge": { - "type": "SelectControl", - "renderTrigger": true, - "freeForm": true, - "label": "Charge", - "default": "-500", - "choices": [ - [ - "-50", - "-50" - ], - [ - "-75", - "-75" - ], - [ - "-100", - "-100" - ], - [ - "-150", - "-150" - ], - [ - "-200", - "-200" - ], - [ - "-250", - "-250" - ], - [ - "-500", - "-500" - ], - [ - "-1000", - "-1000" - ], - [ - "-2500", - "-2500" - ], - [ - "-5000", - "-5000" - ] - ], - "description": "Charge in the force layout" - }, - "granularity_sqla": { - "type": "SelectControl", - "label": "Time Column", - "description": "The time column for the visualization. Note that you can define arbitrary expression that return a DATETIME column in the table. Also note that the filter below is applied against this column or expression", - "clearable": false, - "valueKey": "column_name" - }, - "time_grain_sqla": { - "type": "SelectControl", - "label": "Time Grain", - "default": "P1D", - "description": "The time granularity for the visualization. This applies a date transformation to alter your time column and defines a new time granularity. The options here are defined on a per database engine basis in the Superset source code." - }, - "resample_rule": { - "type": "SelectControl", - "freeForm": true, - "label": "Rule", - "default": null, - "choices": [ - [ - "", - "" - ], - [ - "1T", - "1T" - ], - [ - "1H", - "1H" - ], - [ - "1D", - "1D" - ], - [ - "7D", - "7D" - ], - [ - "1M", - "1M" - ], - [ - "1AS", - "1AS" - ] - ], - "description": "Pandas resample rule" - }, - "resample_how": { - "type": "SelectControl", - "freeForm": true, - "label": "How", - "default": null, - "choices": [ - [ - "", - "" - ], - [ - "mean", - "mean" - ], - [ - "sum", - "sum" - ], - [ - "median", - "median" - ] - ], - "description": "Pandas resample how" - }, - "resample_fillmethod": { - "type": "SelectControl", - "freeForm": true, - "label": "Fill Method", - "default": null, - "choices": [ - [ - "", - "" - ], - [ - "ffill", - "ffill" - ], - [ - "bfill", - "bfill" - ] - ], - "description": "Pandas resample fill method" - }, - "time_range": { - "type": "DateFilterControl", - "freeForm": true, - "label": "Time range", - "default": "Last week" - }, - "max_bubble_size": { - "type": "SelectControl", - "freeForm": true, - "label": "Max Bubble Size", - "default": "25", - "choices": [ - [ - "5", - "5" - ], - [ - "10", - "10" - ], - [ - "15", - "15" - ], - [ - "25", - "25" - ], - [ - "50", - "50" - ], - [ - "75", - "75" - ], - [ - "100", - "100" - ] - ] - }, - "whisker_options": { - "type": "SelectControl", - "freeForm": true, - "label": "Whisker/outlier options", - "default": "Tukey", - "description": "Determines how whiskers and outliers are calculated.", - "choices": [ - [ - "Tukey", - "Tukey" - ], - [ - "Min/max (no outliers)", - "Min/max (no outliers)" - ], - [ - "2/98 percentiles", - "2/98 percentiles" - ], - [ - "9/91 percentiles", - "9/91 percentiles" - ] - ] - }, - "treemap_ratio": { - "type": "TextControl", - "label": "Ratio", - "renderTrigger": true, - "isFloat": true, - "default": 1.618033988749895, - "description": "Target aspect ratio for treemap tiles." - }, - "number_format": { - "type": "SelectControl", - "freeForm": true, - "label": "Number format", - "renderTrigger": true, - "default": "SMART_NUMBER", - "choices": [ - [ - ".1s", - ".1s (12345.432 => 10k)" - ], - [ - ".3s", - ".3s (12345.432 => 12.3k)" - ], - [ - ",.1%", - ",.1% (12345.432 => 1,234,543.2%)" - ], - [ - ".3%", - ".3% (12345.432 => 1234543.200%)" - ], - [ - ".4r", - ".4r (12345.432 => 12350)" - ], - [ - ",.3f", - ",.3f (12345.432 => 12,345.432)" - ], - [ - "+,", - "+, (12345.432 => +12,345.432)" - ], - [ - "$,.2f", - "$,.2f (12345.432 => $12,345.43)" - ] - ], - "description": "D3 format syntax: https://github.com/d3/d3-format" - }, - "row_limit": { - "type": "SelectControl", - "freeForm": true, - "label": "Row limit", - "validators": [ - null - ], - "default": 10000, - "choices": [ - [ - 10, - "10" - ], - [ - 50, - "50" - ], - [ - 100, - "100" - ], - [ - 250, - "250" - ], - [ - 500, - "500" - ], - [ - 1000, - "1000" - ], - [ - 5000, - "5000" - ], - [ - 10000, - "10000" - ], - [ - 50000, - "50000" - ] - ] - }, - "limit": { - "type": "SelectControl", - "freeForm": true, - "label": "Series limit", - "validators": [ - null - ], - "choices": [ - [ - 0, - "0" - ], - [ - 5, - "5" - ], - [ - 10, - "10" - ], - [ - 25, - "25" - ], - [ - 50, - "50" - ], - [ - 100, - "100" - ], - [ - 500, - "500" - ] - ], - "description": "Limits the number of time series that get displayed. A sub query (or an extra phase where sub queries are not supported) is applied to limit the number of time series that get fetched and displayed. This feature is useful when grouping by high cardinality dimension(s)." - }, - "timeseries_limit_metric": { - "type": "MetricsControl", - "label": "Sort By", - "default": null, - "description": "Metric used to define the top series" - }, - "order_desc": { - "type": "CheckboxControl", - "label": "Sort Descending", - "default": true, - "description": "Whether to sort descending or ascending" - }, - "rolling_type": { - "type": "SelectControl", - "label": "Rolling", - "default": "None", - "choices": [ - [ - "None", - "None" - ], - [ - "mean", - "mean" - ], - [ - "sum", - "sum" - ], - [ - "std", - "std" - ], - [ - "cumsum", - "cumsum" - ] - ], - "description": "Defines a rolling window function to apply, works along with the [Periods] text box" - }, - "multiplier": { - "type": "TextControl", - "label": "Multiplier", - "isFloat": true, - "renderTrigger": true, - "default": 1, - "description": "Factor to multiply the metric by" - }, - "rolling_periods": { - "type": "TextControl", - "label": "Periods", - "isInt": true, - "description": "Defines the size of the rolling window function, relative to the time granularity selected" - }, - "cell_size": { - "type": "TextControl", - "isInt": true, - "default": 10, - "validators": [ - null - ], - "renderTrigger": true, - "label": "Cell Size", - "description": "The size of the square cell, in pixels" - }, - "cell_padding": { - "type": "TextControl", - "isInt": true, - "validators": [ - null - ], - "renderTrigger": true, - "default": 2, - "label": "Cell Padding", - "description": "The distance between cells, in pixels" - }, - "cell_radius": { - "type": "TextControl", - "isInt": true, - "validators": [ - null - ], - "renderTrigger": true, - "default": 0, - "label": "Cell Radius", - "description": "The pixel radius" - }, - "steps": { - "type": "TextControl", - "isInt": true, - "validators": [ - null - ], - "renderTrigger": true, - "default": 10, - "label": "Color Steps", - "description": "The number color \"steps\"" - }, - "grid_size": { - "type": "TextControl", - "label": "Grid Size", - "renderTrigger": true, - "default": 20, - "isInt": true, - "description": "Defines the grid size in pixels" - }, - "min_periods": { - "type": "TextControl", - "label": "Min Periods", - "isInt": true, - "description": "The minimum number of rolling periods required to show a value. For instance if you do a cumulative sum on 7 days you may want your \"Min Period\" to be 7, so that all data points shown are the total of 7 periods. This will hide the \"ramp up\" taking place over the first 7 periods" - }, - "series": { - "type": "SelectControl", - "multi": false, - "label": "Series", - "default": null, - "includeTime": false, - "description": "Defines the grouping of entities. Each series is shown as a specific color on the chart and has a legend toggle", - "valueKey": "column_name" - }, - "entity": { - "type": "SelectControl", - "multi": false, - "label": "Entity", - "default": null, - "includeTime": false, - "description": "This defines the element to be plotted on the chart", - "valueKey": "column_name", - "validators": [ - null - ] - }, - "x": { - "type": "MetricsControl", - "multi": false, - "label": "X Axis", - "validators": [ - null - ], - "default": null, - "description": "Metric assigned to the [X] axis" - }, - "y": { - "type": "MetricsControl", - "multi": false, - "label": "Y Axis", - "validators": [ - null - ], - "default": null, - "description": "Metric assigned to the [Y] axis" - }, - "size": { - "type": "MetricsControl", - "multi": false, - "label": "Bubble Size", - "validators": [ - null - ], - "default": null, - "description": "One or many metrics to display" - }, - "url": { - "type": "TextControl", - "label": "URL", - "description": "The URL, this control is templated, so you can integrate {{ width }} and/or {{ height }} in your URL string.", - "default": "https://www.youtube.com/embed/AdSZJzb-aX8" - }, - "x_axis_label": { - "type": "TextControl", - "label": "X Axis Label", - "renderTrigger": true, - "default": "" - }, - "y_axis_label": { - "type": "TextControl", - "label": "Y Axis Label", - "renderTrigger": true, - "default": "" - }, - "compare_lag": { - "type": "TextControl", - "label": "Comparison Period Lag", - "isInt": true, - "description": "Based on granularity, number of time periods to compare against" - }, - "compare_suffix": { - "type": "TextControl", - "label": "Comparison suffix", - "description": "Suffix to apply after the percentage display" - }, - "table_timestamp_format": { - "type": "SelectControl", - "freeForm": true, - "label": "Table Timestamp Format", - "default": "%Y-%m-%d %H:%M:%S", - "renderTrigger": true, - "validators": [ - null - ], - "clearable": false, - "choices": [ - [ - "smart_date", - "Adaptative formating" - ], - [ - "%d/%m/%Y", - "%d/%m/%Y | 14/01/2019" - ], - [ - "%m/%d/%Y", - "%m/%d/%Y | 01/14/2019" - ], - [ - "%Y-%m-%d", - "%Y-%m-%d | 2019-01-14" - ], - [ - "%Y-%m-%d %H:%M:%S", - "%Y-%m-%d %H:%M:%S | 2019-01-14 01:32:10" - ], - [ - "%d-%m-%Y %H:%M:%S", - "%Y-%m-%d %H:%M:%S | 14-01-2019 01:32:10" - ], - [ - "%H:%M:%S", - "%H:%M:%S | 01:32:10" - ] - ], - "description": "Timestamp Format" - }, - "series_height": { - "type": "SelectControl", - "renderTrigger": true, - "freeForm": true, - "label": "Series Height", - "default": "25", - "choices": [ - [ - "10", - "10" - ], - [ - "25", - "25" - ], - [ - "40", - "40" - ], - [ - "50", - "50" - ], - [ - "75", - "75" - ], - [ - "100", - "100" - ], - [ - "150", - "150" - ], - [ - "200", - "200" - ] - ], - "description": "Pixel height of each series" - }, - "page_length": { - "type": "SelectControl", - "freeForm": true, - "renderTrigger": true, - "label": "Page Length", - "default": 0, - "choices": [ - [ - 0, - "0" - ], - [ - 10, - "10" - ], - [ - 25, - "25" - ], - [ - 40, - "40" - ], - [ - 50, - "50" - ], - [ - 75, - "75" - ], - [ - 100, - "100" - ], - [ - 150, - "150" - ], - [ - 200, - "200" - ] - ], - "description": "Rows per page, 0 means no pagination" - }, - "x_axis_format": { - "type": "SelectControl", - "freeForm": true, - "label": "X Axis Format", - "renderTrigger": true, - "default": "SMART_NUMBER", - "choices": [ - [ - ".1s", - ".1s (12345.432 => 10k)" - ], - [ - ".3s", - ".3s (12345.432 => 12.3k)" - ], - [ - ",.1%", - ",.1% (12345.432 => 1,234,543.2%)" - ], - [ - ".3%", - ".3% (12345.432 => 1234543.200%)" - ], - [ - ".4r", - ".4r (12345.432 => 12350)" - ], - [ - ",.3f", - ",.3f (12345.432 => 12,345.432)" - ], - [ - "+,", - "+, (12345.432 => +12,345.432)" - ], - [ - "$,.2f", - "$,.2f (12345.432 => $12,345.43)" - ] - ], - "description": "D3 format syntax: https://github.com/d3/d3-format" - }, - "x_axis_time_format": { - "type": "SelectControl", - "freeForm": true, - "label": "X Axis Format", - "renderTrigger": true, - "default": "smart_date", - "choices": [ - [ - "smart_date", - "Adaptative formating" - ], - [ - "%d/%m/%Y", - "%d/%m/%Y | 14/01/2019" - ], - [ - "%m/%d/%Y", - "%m/%d/%Y | 01/14/2019" - ], - [ - "%Y-%m-%d", - "%Y-%m-%d | 2019-01-14" - ], - [ - "%Y-%m-%d %H:%M:%S", - "%Y-%m-%d %H:%M:%S | 2019-01-14 01:32:10" - ], - [ - "%d-%m-%Y %H:%M:%S", - "%Y-%m-%d %H:%M:%S | 14-01-2019 01:32:10" - ], - [ - "%H:%M:%S", - "%H:%M:%S | 01:32:10" - ] - ], - "description": "D3 format syntax: https://github.com/d3/d3-format" - }, - "y_axis_format": { - "type": "SelectControl", - "freeForm": true, - "label": "Y Axis Format", - "renderTrigger": true, - "default": "SMART_NUMBER", - "choices": [ - [ - ".1s", - ".1s (12345.432 => 10k)" - ], - [ - ".3s", - ".3s (12345.432 => 12.3k)" - ], - [ - ",.1%", - ",.1% (12345.432 => 1,234,543.2%)" - ], - [ - ".3%", - ".3% (12345.432 => 1234543.200%)" - ], - [ - ".4r", - ".4r (12345.432 => 12350)" - ], - [ - ",.3f", - ",.3f (12345.432 => 12,345.432)" - ], - [ - "+,", - "+, (12345.432 => +12,345.432)" - ], - [ - "$,.2f", - "$,.2f (12345.432 => $12,345.43)" - ] - ], - "description": "D3 format syntax: https://github.com/d3/d3-format" - }, - "y_axis_2_format": { - "type": "SelectControl", - "freeForm": true, - "label": "Right Axis Format", - "default": "SMART_NUMBER", - "choices": [ - [ - ".1s", - ".1s (12345.432 => 10k)" - ], - [ - ".3s", - ".3s (12345.432 => 12.3k)" - ], - [ - ",.1%", - ",.1% (12345.432 => 1,234,543.2%)" - ], - [ - ".3%", - ".3% (12345.432 => 1234543.200%)" - ], - [ - ".4r", - ".4r (12345.432 => 12350)" - ], - [ - ",.3f", - ",.3f (12345.432 => 12,345.432)" - ], - [ - "+,", - "+, (12345.432 => +12,345.432)" - ], - [ - "$,.2f", - "$,.2f (12345.432 => $12,345.43)" - ] - ], - "description": "D3 format syntax: https://github.com/d3/d3-format" - }, - "date_time_format": { - "type": "SelectControl", - "freeForm": true, - "label": "Date Time Format", - "renderTrigger": true, - "default": "smart_date", - "choices": [ - [ - "smart_date", - "Adaptative formating" - ], - [ - "%d/%m/%Y", - "%d/%m/%Y | 14/01/2019" - ], - [ - "%m/%d/%Y", - "%m/%d/%Y | 01/14/2019" - ], - [ - "%Y-%m-%d", - "%Y-%m-%d | 2019-01-14" - ], - [ - "%Y-%m-%d %H:%M:%S", - "%Y-%m-%d %H:%M:%S | 2019-01-14 01:32:10" - ], - [ - "%d-%m-%Y %H:%M:%S", - "%Y-%m-%d %H:%M:%S | 14-01-2019 01:32:10" - ], - [ - "%H:%M:%S", - "%H:%M:%S | 01:32:10" - ] - ], - "description": "D3 format syntax: https://github.com/d3/d3-format" - }, - "markup_type": { - "type": "SelectControl", - "label": "Markup Type", - "clearable": false, - "choices": [ - [ - "markdown", - "markdown" - ], - [ - "html", - "html" - ] - ], - "default": "markdown", - "validators": [ - null - ], - "description": "Pick your favorite markup language" - }, - "rotation": { - "type": "SelectControl", - "label": "Rotation", - "choices": [ - [ - "random", - "random" - ], - [ - "flat", - "flat" - ], - [ - "square", - "square" - ] - ], - "renderTrigger": true, - "default": "flat", - "description": "Rotation to apply to words in the cloud" - }, - "line_interpolation": { - "type": "SelectControl", - "label": "Line Style", - "renderTrigger": true, - "choices": [ - [ - "linear", - "linear" - ], - [ - "basis", - "basis" - ], - [ - "cardinal", - "cardinal" - ], - [ - "monotone", - "monotone" - ], - [ - "step-before", - "step-before" - ], - [ - "step-after", - "step-after" - ] - ], - "default": "linear", - "description": "Line interpolation as defined by d3.js" - }, - "pie_label_type": { - "type": "SelectControl", - "label": "Label Type", - "default": "key", - "renderTrigger": true, - "choices": [ - [ - "key", - "Category Name" - ], - [ - "value", - "Value" - ], - [ - "percent", - "Percentage" - ], - [ - "key_value", - "Category and Value" - ], - [ - "key_percent", - "Category and Percentage" - ] - ], - "description": "What should be shown on the label?" - }, - "code": { - "type": "TextAreaControl", - "label": "Code", - "description": "Put your code here", - "default": "" - }, - "pandas_aggfunc": { - "type": "SelectControl", - "label": "Aggregation function", - "clearable": false, - "choices": [ - [ - "sum", - "sum" - ], - [ - "mean", - "mean" - ], - [ - "min", - "min" - ], - [ - "max", - "max" - ], - [ - "stdev", - "stdev" - ], - [ - "var", - "var" - ] - ], - "default": "sum", - "description": "Aggregate function to apply when pivoting and computing the total rows and columns" - }, - "js_agg_function": { - "type": "SelectControl", - "label": "Dynamic Aggregation Function", - "description": "The function to use when aggregating points into groups", - "default": "sum", - "clearable": false, - "renderTrigger": true, - "choices": [ - [ - "sum", - "sum" - ], - [ - "min", - "min" - ], - [ - "max", - "max" - ], - [ - "mean", - "mean" - ], - [ - "median", - "median" - ], - [ - "count", - "count" - ], - [ - "variance", - "variance" - ], - [ - "deviation", - "deviation" - ], - [ - "p1", - "p1" - ], - [ - "p5", - "p5" - ], - [ - "p95", - "p95" - ], - [ - "p99", - "p99" - ] - ] - }, - "size_from": { - "type": "TextControl", - "isInt": true, - "label": "Font Size From", - "renderTrigger": true, - "default": "20", - "description": "Font size for the smallest value in the list" - }, - "size_to": { - "type": "TextControl", - "isInt": true, - "label": "Font Size To", - "renderTrigger": true, - "default": "150", - "description": "Font size for the biggest value in the list" - }, - "header_font_size": { - "type": "SelectControl", - "label": "Header Font Size", - "renderTrigger": true, - "clearable": false, - "default": 0.3, - "options": [ - { - "label": "Tiny", - "value": 0.125 - }, - { - "label": "Small", - "value": 0.2 - }, - { - "label": "Normal", - "value": 0.3 - }, - { - "label": "Large", - "value": 0.4 - }, - { - "label": "Huge", - "value": 0.5 - } - ] - }, - "subheader_font_size": { - "type": "SelectControl", - "label": "Subheader Font Size", - "renderTrigger": true, - "clearable": false, - "default": 0.125, - "options": [ - { - "label": "Tiny", - "value": 0.125 - }, - { - "label": "Small", - "value": 0.2 - }, - { - "label": "Normal", - "value": 0.3 - }, - { - "label": "Large", - "value": 0.4 - }, - { - "label": "Huge", - "value": 0.5 - } - ] - }, - "instant_filtering": { - "type": "CheckboxControl", - "label": "Instant Filtering", - "renderTrigger": true, - "default": true, - "description": "Whether to apply filters as they change, or wait forusers to hit an [Apply] button" - }, - "extruded": { - "type": "CheckboxControl", - "label": "Extruded", - "renderTrigger": true, - "default": true, - "description": "Whether to make the grid 3D" - }, - "show_brush": { - "type": "SelectControl", - "label": "Show Range Filter", - "renderTrigger": true, - "clearable": false, - "default": "auto", - "choices": [ - [ - "yes", - "Yes" - ], - [ - "no", - "No" - ], - [ - "auto", - "Auto" - ] - ], - "description": "Whether to display the time range interactive selector" - }, - "date_filter": { - "type": "CheckboxControl", - "label": "Date Filter", - "default": true, - "description": "Whether to include a time filter" - }, - "show_sqla_time_granularity": { - "type": "CheckboxControl", - "label": "Show SQL Granularity Dropdown", - "default": false, - "description": "Check to include SQL Granularity dropdown" - }, - "show_sqla_time_column": { - "type": "CheckboxControl", - "label": "Show SQL Time Column", - "default": false, - "description": "Check to include Time Column dropdown" - }, - "show_druid_time_granularity": { - "type": "CheckboxControl", - "label": "Show Druid Granularity Dropdown", - "default": false, - "description": "Check to include Druid Granularity dropdown" - }, - "show_druid_time_origin": { - "type": "CheckboxControl", - "label": "Show Druid Time Origin", - "default": false, - "description": "Check to include Time Origin dropdown" - }, - "show_datatable": { - "type": "CheckboxControl", - "label": "Data Table", - "default": false, - "renderTrigger": true, - "description": "Whether to display the interactive data table" - }, - "include_search": { - "type": "CheckboxControl", - "label": "Search Box", - "renderTrigger": true, - "default": false, - "description": "Whether to include a client-side search box" - }, - "table_filter": { - "type": "CheckboxControl", - "label": "Emit Filter Events", - "renderTrigger": true, - "default": false, - "description": "Whether to apply filter when items are clicked" - }, - "align_pn": { - "type": "CheckboxControl", - "label": "Align +/-", - "renderTrigger": true, - "default": false, - "description": "Whether to align the background chart for +/- values" - }, - "color_pn": { - "type": "CheckboxControl", - "label": "Color +/-", - "renderTrigger": true, - "default": true, - "description": "Whether to color +/- values" - }, - "show_bubbles": { - "type": "CheckboxControl", - "label": "Show Bubbles", - "default": false, - "renderTrigger": true, - "description": "Whether to display bubbles on top of countries" - }, - "show_legend": { - "type": "CheckboxControl", - "label": "Legend", - "renderTrigger": true, - "default": true, - "description": "Whether to display the legend (toggles)" - }, - "send_time_range": { - "type": "CheckboxControl", - "label": "Propagate", - "renderTrigger": true, - "default": false, - "description": "Send range filter events to other charts" - }, - "toggle_polygons": { - "type": "CheckboxControl", - "label": "Multiple filtering", - "renderTrigger": true, - "default": true, - "description": "Allow sending multiple polygons as a filter event" - }, - "num_buckets": { - "type": "SelectControl", - "multi": false, - "freeForm": true, - "label": "Number of buckets to group data", - "default": 5, - "choices": [ - [ - 2, - "2" - ], - [ - 3, - "3" - ], - [ - 5, - "5" - ], - [ - 10, - "10" - ] - ], - "description": "How many buckets should the data be grouped in.", - "renderTrigger": true - }, - "break_points": { - "type": "SelectControl", - "multi": true, - "freeForm": true, - "label": "Bucket break points", - "choices": [], - "description": "List of n+1 values for bucketing metric into n buckets.", - "renderTrigger": true - }, - "show_labels": { - "type": "CheckboxControl", - "label": "Show Labels", - "renderTrigger": true, - "default": true, - "description": "Whether to display the labels. Note that the label only displays when the the 5% threshold." - }, - "show_values": { - "type": "CheckboxControl", - "label": "Show Values", - "renderTrigger": true, - "default": false, - "description": "Whether to display the numerical values within the cells" - }, - "show_metric_name": { - "type": "CheckboxControl", - "label": "Show Metric Names", - "renderTrigger": true, - "default": true, - "description": "Whether to display the metric name as a title" - }, - "show_trend_line": { - "type": "CheckboxControl", - "label": "Show Trend Line", - "renderTrigger": true, - "default": true, - "description": "Whether to display the trend line" - }, - "start_y_axis_at_zero": { - "type": "CheckboxControl", - "label": "Start y-axis at 0", - "renderTrigger": true, - "default": true, - "description": "Start y-axis at zero. Uncheck to start y-axis at minimum value in the data." - }, - "x_axis_showminmax": { - "type": "CheckboxControl", - "label": "X bounds", - "renderTrigger": true, - "default": false, - "description": "Whether to display the min and max values of the X-axis" - }, - "y_axis_showminmax": { - "type": "CheckboxControl", - "label": "Y bounds", - "renderTrigger": true, - "default": false, - "description": "Whether to display the min and max values of the Y-axis" - }, - "rich_tooltip": { - "type": "CheckboxControl", - "label": "Rich Tooltip", - "renderTrigger": true, - "default": true, - "description": "The rich tooltip shows a list of all series for that point in time" - }, - "y_log_scale": { - "type": "CheckboxControl", - "label": "Y Log Scale", - "default": false, - "renderTrigger": true, - "description": "Use a log scale for the Y-axis" - }, - "x_log_scale": { - "type": "CheckboxControl", - "label": "X Log Scale", - "default": false, - "renderTrigger": true, - "description": "Use a log scale for the X-axis" - }, - "log_scale": { - "type": "CheckboxControl", - "label": "Log Scale", - "default": false, - "renderTrigger": true, - "description": "Use a log scale" - }, - "donut": { - "type": "CheckboxControl", - "label": "Donut", - "default": false, - "renderTrigger": true, - "description": "Do you want a donut or a pie?" - }, - "labels_outside": { - "type": "CheckboxControl", - "label": "Put labels outside", - "default": true, - "renderTrigger": true, - "description": "Put the labels outside the pie?" - }, - "contribution": { - "type": "CheckboxControl", - "label": "Contribution", - "default": false, - "description": "Compute the contribution to the total" - }, - "time_compare": { - "type": "SelectControl", - "multi": true, - "freeForm": true, - "label": "Time Shift", - "choices": [ - [ - "1 day", - "1 day" - ], - [ - "1 week", - "1 week" - ], - [ - "28 days", - "28 days" - ], - [ - "30 days", - "30 days" - ], - [ - "52 weeks", - "52 weeks" - ], - [ - "1 year", - "1 year" - ] - ], - "description": "Overlay one or more timeseries from a relative time period. Expects relative time deltas in natural language (example: 24 hours, 7 days, 56 weeks, 365 days)" - }, - "comparison_type": { - "type": "SelectControl", - "label": "Calculation type", - "default": "values", - "choices": [ - [ - "values", - "Actual Values" - ], - [ - "absolute", - "Absolute difference" - ], - [ - "percentage", - "Percentage change" - ], - [ - "ratio", - "Ratio" - ] - ], - "description": "How to display time shifts: as individual lines; as the absolute difference between the main time series and each time shift; as the percentage change; or as the ratio between series and time shifts." - }, - "subheader": { - "type": "TextControl", - "label": "Subheader", - "description": "Description text that shows up below your Big Number" - }, - "mapbox_label": { - "type": "SelectControl", - "multi": true, - "label": "label", - "default": [], - "description": "`count` is COUNT(*) if a group by is used. Numerical columns will be aggregated with the aggregator. Non-numerical columns will be used to label points. Leave empty to get a count of points in each cluster." - }, - "mapbox_style": { - "type": "SelectControl", - "label": "Map Style", - "clearable": false, - "renderTrigger": true, - "choices": [ - [ - "mapbox://styles/mapbox/streets-v9", - "Streets" - ], - [ - "mapbox://styles/mapbox/dark-v9", - "Dark" - ], - [ - "mapbox://styles/mapbox/light-v9", - "Light" - ], - [ - "mapbox://styles/mapbox/satellite-streets-v9", - "Satellite Streets" - ], - [ - "mapbox://styles/mapbox/satellite-v9", - "Satellite" - ], - [ - "mapbox://styles/mapbox/outdoors-v9", - "Outdoors" - ] - ], - "default": "mapbox://styles/mapbox/light-v9", - "description": "Base layer map style" - }, - "clustering_radius": { - "type": "SelectControl", - "freeForm": true, - "label": "Clustering Radius", - "default": "60", - "choices": [ - [ - "0", - "0" - ], - [ - "20", - "20" - ], - [ - "40", - "40" - ], - [ - "60", - "60" - ], - [ - "80", - "80" - ], - [ - "100", - "100" - ], - [ - "200", - "200" - ], - [ - "500", - "500" - ], - [ - "1000", - "1000" - ] - ], - "description": "The radius (in pixels) the algorithm uses to define a cluster. Choose 0 to turn off clustering, but beware that a large number of points (>1000) will cause lag." - }, - "point_radius_fixed": { - "type": "FixedOrMetricControl", - "label": "Point Size", - "default": { - "type": "fix", - "value": 1000 - }, - "description": "Fixed point radius" - }, - "point_radius": { - "type": "SelectControl", - "label": "Point Radius", - "default": "Auto", - "description": "The radius of individual points (ones that are not in a cluster). Either a numerical column or `Auto`, which scales the point based on the largest cluster" - }, - "point_radius_unit": { - "type": "SelectControl", - "label": "Point Radius Unit", - "default": "Pixels", - "choices": [ - [ - "Pixels", - "Pixels" - ], - [ - "Miles", - "Miles" - ], - [ - "Kilometers", - "Kilometers" - ] - ], - "description": "The unit of measure for the specified point radius" - }, - "point_unit": { - "type": "SelectControl", - "label": "Point Unit", - "default": "square_m", - "clearable": false, - "choices": [ - [ - "square_m", - "Square meters" - ], - [ - "square_km", - "Square kilometers" - ], - [ - "square_miles", - "Square miles" - ], - [ - "radius_m", - "Radius in meters" - ], - [ - "radius_km", - "Radius in kilometers" - ], - [ - "radius_miles", - "Radius in miles" - ] - ], - "description": "The unit of measure for the specified point radius" - }, - "global_opacity": { - "type": "TextControl", - "label": "Opacity", - "default": 1, - "isFloat": true, - "description": "Opacity of all clusters, points, and labels. Between 0 and 1." - }, - "opacity": { - "type": "SliderControl", - "label": "Opacity", - "default": 80, - "step": 1, - "min": 0, - "max": 100, - "renderTrigger": true, - "description": "Opacity, expects values between 0 and 100" - }, - "viewport": { - "type": "ViewportControl", - "label": "Viewport", - "renderTrigger": false, - "description": "Parameters related to the view and perspective on the map", - "default": { - "longitude": 6.85236157047845, - "latitude": 31.222656842808707, - "zoom": 1, - "bearing": 0, - "pitch": 0 - }, - "dontRefreshOnChange": true - }, - "viewport_zoom": { - "type": "TextControl", - "label": "Zoom", - "renderTrigger": true, - "isFloat": true, - "default": 11, - "description": "Zoom level of the map", - "places": 8, - "dontRefreshOnChange": true - }, - "viewport_latitude": { - "type": "TextControl", - "label": "Default latitude", - "renderTrigger": true, - "default": 37.772123, - "isFloat": true, - "description": "Latitude of default viewport", - "places": 8, - "dontRefreshOnChange": true - }, - "viewport_longitude": { - "type": "TextControl", - "label": "Default longitude", - "renderTrigger": true, - "default": -122.405293, - "isFloat": true, - "description": "Longitude of default viewport", - "places": 8, - "dontRefreshOnChange": true - }, - "render_while_dragging": { - "type": "CheckboxControl", - "label": "Live render", - "default": true, - "description": "Points and clusters will update as the viewport is being changed" - }, - "mapbox_color": { - "type": "SelectControl", - "freeForm": true, - "label": "RGB Color", - "default": "rgb(0, 122, 135)", - "choices": [ - [ - "rgb(0, 139, 139)", - "Dark Cyan" - ], - [ - "rgb(128, 0, 128)", - "Purple" - ], - [ - "rgb(255, 215, 0)", - "Gold" - ], - [ - "rgb(69, 69, 69)", - "Dim Gray" - ], - [ - "rgb(220, 20, 60)", - "Crimson" - ], - [ - "rgb(34, 139, 34)", - "Forest Green" - ] - ], - "description": "The color for points and clusters in RGB" - }, - "color": { - "type": "ColorPickerControl", - "label": "Color", - "default": { - "r": 0, - "g": 122, - "b": 135, - "a": 1 - }, - "description": "Pick a color" - }, - "ranges": { - "type": "TextControl", - "label": "Ranges", - "default": "", - "description": "Ranges to highlight with shading" - }, - "range_labels": { - "type": "TextControl", - "label": "Range labels", - "default": "", - "description": "Labels for the ranges" - }, - "markers": { - "type": "TextControl", - "label": "Markers", - "default": "", - "description": "List of values to mark with triangles" - }, - "marker_labels": { - "type": "TextControl", - "label": "Marker labels", - "default": "", - "description": "Labels for the markers" - }, - "marker_lines": { - "type": "TextControl", - "label": "Marker lines", - "default": "", - "description": "List of values to mark with lines" - }, - "marker_line_labels": { - "type": "TextControl", - "label": "Marker line labels", - "default": "", - "description": "Labels for the marker lines" - }, - "annotation_layers": { - "type": "AnnotationLayerControl", - "label": "", - "default": [], - "description": "Annotation Layers", - "renderTrigger": true, - "tabOverride": "data" - }, - "adhoc_filters": { - "type": "AdhocFilterControl", - "label": "Filters", - "default": null, - "description": "", - "provideFormDataToProps": true - }, - "filters": { - "type": "FilterPanel" - }, - "slice_id": { - "type": "HiddenControl", - "label": "Chart ID", - "hidden": true, - "description": "The id of the active chart" - }, - "cache_timeout": { - "type": "HiddenControl", - "label": "Cache Timeout (seconds)", - "hidden": true, - "description": "The number of seconds before expiring the cache" - }, - "url_params": { - "type": "HiddenControl", - "label": "URL Parameters", - "hidden": true, - "description": "Extra parameters for use in jinja templated queries" - }, - "order_by_entity": { - "type": "CheckboxControl", - "label": "Order by entity id", - "description": "Important! Select this if the table is not already sorted by entity id, else there is no guarantee that all events for each entity are returned.", - "default": true - }, - "min_leaf_node_event_count": { - "type": "SelectControl", - "freeForm": false, - "label": "Minimum leaf node event count", - "default": 1, - "choices": [ - [ - 1, - "1" - ], - [ - 2, - "2" - ], - [ - 3, - "3" - ], - [ - 4, - "4" - ], - [ - 5, - "5" - ], - [ - 6, - "6" - ], - [ - 7, - "7" - ], - [ - 8, - "8" - ], - [ - 9, - "9" - ], - [ - 10, - "10" - ] - ], - "description": "Leaf nodes that represent fewer than this number of events will be initially hidden in the visualization" - }, - "color_scheme": { - "type": "ColorSchemeControl", - "label": "Color Scheme", - "default": "bnbColors", - "renderTrigger": true, - "description": "The color scheme for rendering chart" - }, - "label_colors": { - "type": "ColorMapControl", - "label": "Color Map", - "default": {} - }, - "significance_level": { - "type": "TextControl", - "label": "Significance Level", - "default": 0.05, - "description": "Threshold alpha level for determining significance" - }, - "pvalue_precision": { - "type": "TextControl", - "label": "p-value precision", - "default": 6, - "description": "Number of decimal places with which to display p-values" - }, - "liftvalue_precision": { - "type": "TextControl", - "label": "Lift percent precision", - "default": 4, - "description": "Number of decimal places with which to display lift values" - }, - "column_collection": { - "type": "CollectionControl", - "label": "Time Series Columns", - "validators": [ - null - ], - "controlName": "TimeSeriesColumnControl" - }, - "rose_area_proportion": { - "type": "CheckboxControl", - "label": "Use Area Proportions", - "description": "Check if the Rose Chart should use segment area instead of segment radius for proportioning", - "default": false, - "renderTrigger": true - }, - "time_series_option": { - "type": "SelectControl", - "label": "Options", - "validators": [ - null - ], - "default": "not_time", - "valueKey": "value", - "options": [ - { - "label": "Not Time Series", - "value": "not_time", - "description": "Ignore time" - }, - { - "label": "Time Series", - "value": "time_series", - "description": "Standard time series" - }, - { - "label": "Aggregate Mean", - "value": "agg_mean", - "description": "Mean of values over specified period" - }, - { - "label": "Aggregate Sum", - "value": "agg_sum", - "description": "Sum of values over specified period" - }, - { - "label": "Difference", - "value": "point_diff", - "description": "Metric change in value from `since` to `until`" - }, - { - "label": "Percent Change", - "value": "point_percent", - "description": "Metric percent change in value from `since` to `until`" - }, - { - "label": "Factor", - "value": "point_factor", - "description": "Metric factor change from `since` to `until`" - }, - { - "label": "Advanced Analytics", - "value": "adv_anal", - "description": "Use the Advanced Analytics options below" - } - ], - "description": "Settings for time series" - }, - "equal_date_size": { - "type": "CheckboxControl", - "label": "Equal Date Sizes", - "default": true, - "renderTrigger": true, - "description": "Check to force date partitions to have the same height" - }, - "partition_limit": { - "type": "TextControl", - "label": "Partition Limit", - "isInt": true, - "default": "5", - "description": "The maximum number of subdivisions of each group; lower values are pruned first" - }, - "min_radius": { - "type": "TextControl", - "label": "Minimum Radius", - "isFloat": true, - "validators": [ - null - ], - "renderTrigger": true, - "default": 2, - "description": "Minimum radius size of the circle, in pixels. As the zoom level changes, this insures that the circle respects this minimum radius." - }, - "max_radius": { - "type": "TextControl", - "label": "Maximum Radius", - "isFloat": true, - "validators": [ - null - ], - "renderTrigger": true, - "default": 250, - "description": "Maxium radius size of the circle, in pixels. As the zoom level changes, this insures that the circle respects this maximum radius." - }, - "partition_threshold": { - "type": "TextControl", - "label": "Partition Threshold", - "isFloat": true, - "default": "0.05", - "description": "Partitions whose height to parent height proportions are below this value are pruned" - }, - "line_column": { - "type": "SelectControl", - "label": "Lines column", - "default": null, - "description": "The database columns that contains lines information", - "validators": [ - null - ] - }, - "line_type": { - "type": "SelectControl", - "label": "Lines encoding", - "clearable": false, - "default": "json", - "description": "The encoding format of the lines", - "choices": [ - [ - "polyline", - "Polyline" - ], - [ - "json", - "JSON" - ], - [ - "geohash", - "geohash (square)" - ] - ] - }, - "line_width": { - "type": "TextControl", - "label": "Line width", - "renderTrigger": true, - "isInt": true, - "default": 10, - "description": "The width of the lines" - }, - "line_charts": { - "type": "SelectAsyncControl", - "multi": true, - "label": "Line charts", - "validators": [ - null - ], - "default": [], - "description": "Pick a set of line charts to layer on top of one another", - "dataEndpoint": "/sliceasync/api/read?_flt_0_viz_type=line&_flt_7_viz_type=line_multi", - "placeholder": "Select charts", - "onAsyncErrorMessage": "Error while fetching charts" - }, - "line_charts_2": { - "type": "SelectAsyncControl", - "multi": true, - "label": "Right Axis chart(s)", - "validators": [], - "default": [], - "description": "Choose one or more charts for right axis", - "dataEndpoint": "/sliceasync/api/read?_flt_0_viz_type=line&_flt_7_viz_type=line_multi", - "placeholder": "Select charts", - "onAsyncErrorMessage": "Error while fetching charts" - }, - "prefix_metric_with_slice_name": { - "type": "CheckboxControl", - "label": "Prefix metric name with slice name", - "default": false, - "renderTrigger": true - }, - "reverse_long_lat": { - "type": "CheckboxControl", - "label": "Reverse Lat & Long", - "default": false - }, - "deck_slices": { - "type": "SelectAsyncControl", - "multi": true, - "label": "deck.gl charts", - "validators": [ - null - ], - "default": [], - "description": "Pick a set of deck.gl charts to layer on top of one another", - "dataEndpoint": "/sliceasync/api/read?_flt_0_viz_type=deck_&_flt_7_viz_type=deck_multi", - "placeholder": "Select charts", - "onAsyncErrorMessage": "Error while fetching charts" - }, - "js_data_mutator": { - "type": "TextAreaControl", - "language": "javascript", - "label": "Javascript data interceptor", - "description": "Define a javascript function that receives the data array used in the visualization and is expected to return a modified version of that array. This can be used to alter properties of the data, filter, or enrich the array.", - "height": 100, - "default": "", - "aboveEditorSection": { - "type": "div", - "key": null, - "ref": null, - "props": { - "children": [ - { - "type": "p", - "key": null, - "ref": null, - "props": { - "children": "Define a javascript function that receives the data array used in the visualization and is expected to return a modified version of that array. This can be used to alter properties of the data, filter, or enrich the array." - }, - "_owner": null, - "_store": {} - }, - { - "type": "p", - "key": null, - "ref": null, - "props": { - "children": { - "type": "div", - "key": null, - "ref": null, - "props": { - "children": [ - "For more information about objects are in context in the scope of this function, refer to the", - { - "type": "a", - "key": null, - "ref": null, - "props": { - "href": "https://github.com/apache/incubator-superset/blob/master/superset/assets/src/modules/sandbox.js", - "children": [ - " source code of Superset's sandboxed parser", - "." - ] - }, - "_owner": null, - "_store": {} - }, - "." - ] - }, - "_owner": null, - "_store": {} - } - }, - "_owner": null, - "_store": {} - }, - null - ] - }, - "_owner": null, - "_store": {} - } - }, - "js_data": { - "type": "TextAreaControl", - "language": "javascript", - "label": "Javascript data mutator", - "description": "Define a function that receives intercepts the data objects and can mutate it", - "height": 100, - "default": "", - "aboveEditorSection": { - "type": "div", - "key": null, - "ref": null, - "props": { - "children": [ - { - "type": "p", - "key": null, - "ref": null, - "props": { - "children": "Define a function that receives intercepts the data objects and can mutate it" - }, - "_owner": null, - "_store": {} - }, - { - "type": "p", - "key": null, - "ref": null, - "props": { - "children": { - "type": "div", - "key": null, - "ref": null, - "props": { - "children": [ - "For more information about objects are in context in the scope of this function, refer to the", - { - "type": "a", - "key": null, - "ref": null, - "props": { - "href": "https://github.com/apache/incubator-superset/blob/master/superset/assets/src/modules/sandbox.js", - "children": [ - " source code of Superset's sandboxed parser", - "." - ] - }, - "_owner": null, - "_store": {} - }, - "." - ] - }, - "_owner": null, - "_store": {} - } - }, - "_owner": null, - "_store": {} - }, - null - ] - }, - "_owner": null, - "_store": {} - } - }, - "js_tooltip": { - "type": "TextAreaControl", - "language": "javascript", - "label": "Javascript tooltip generator", - "description": "Define a function that receives the input and outputs the content for a tooltip", - "height": 100, - "default": "", - "aboveEditorSection": { - "type": "div", - "key": null, - "ref": null, - "props": { - "children": [ - { - "type": "p", - "key": null, - "ref": null, - "props": { - "children": "Define a function that receives the input and outputs the content for a tooltip" - }, - "_owner": null, - "_store": {} - }, - { - "type": "p", - "key": null, - "ref": null, - "props": { - "children": { - "type": "div", - "key": null, - "ref": null, - "props": { - "children": [ - "For more information about objects are in context in the scope of this function, refer to the", - { - "type": "a", - "key": null, - "ref": null, - "props": { - "href": "https://github.com/apache/incubator-superset/blob/master/superset/assets/src/modules/sandbox.js", - "children": [ - " source code of Superset's sandboxed parser", - "." - ] - }, - "_owner": null, - "_store": {} - }, - "." - ] - }, - "_owner": null, - "_store": {} - } - }, - "_owner": null, - "_store": {} - }, - null - ] - }, - "_owner": null, - "_store": {} - } - }, - "js_onclick_href": { - "type": "TextAreaControl", - "language": "javascript", - "label": "Javascript onClick href", - "description": "Define a function that returns a URL to navigate to when user clicks", - "height": 100, - "default": "", - "aboveEditorSection": { - "type": "div", - "key": null, - "ref": null, - "props": { - "children": [ - { - "type": "p", - "key": null, - "ref": null, - "props": { - "children": "Define a function that returns a URL to navigate to when user clicks" - }, - "_owner": null, - "_store": {} - }, - { - "type": "p", - "key": null, - "ref": null, - "props": { - "children": { - "type": "div", - "key": null, - "ref": null, - "props": { - "children": [ - "For more information about objects are in context in the scope of this function, refer to the", - { - "type": "a", - "key": null, - "ref": null, - "props": { - "href": "https://github.com/apache/incubator-superset/blob/master/superset/assets/src/modules/sandbox.js", - "children": [ - " source code of Superset's sandboxed parser", - "." - ] - }, - "_owner": null, - "_store": {} - }, - "." - ] - }, - "_owner": null, - "_store": {} - } - }, - "_owner": null, - "_store": {} - }, - null - ] - }, - "_owner": null, - "_store": {} - } - }, - "js_columns": { - "type": "SelectControl", - "multi": true, - "label": "Extra data for JS", - "default": [], - "includeTime": false, - "description": "List of extra columns made available in Javascript functions", - "valueKey": "column_name" - }, - "stroked": { - "type": "CheckboxControl", - "label": "Stroked", - "renderTrigger": true, - "description": "Whether to display the stroke", - "default": false - }, - "filled": { - "type": "CheckboxControl", - "label": "Filled", - "renderTrigger": true, - "description": "Whether to fill the objects", - "default": true - }, - "normalized": { - "type": "CheckboxControl", - "label": "Normalized", - "renderTrigger": true, - "description": "Whether to normalize the histogram", - "default": false - } - } -} - diff --git a/superset/assets/branding/FullLockupWithText.svg b/superset/assets/branding/FullLockupWithText.svg deleted file mode 100644 index fbb4ae5ce6fae..0000000000000 --- a/superset/assets/branding/FullLockupWithText.svg +++ /dev/null @@ -1,63 +0,0 @@ - - - - - Full Lockup With Text - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - - Superset - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/superset/assets/branding/FullLockupWithText@2x.png b/superset/assets/branding/FullLockupWithText@2x.png deleted file mode 100644 index 3ee10514f3ae9..0000000000000 Binary files a/superset/assets/branding/FullLockupWithText@2x.png and /dev/null differ diff --git a/superset/assets/branding/FullLockupWithoutText@1x.svg b/superset/assets/branding/FullLockupWithoutText@1x.svg deleted file mode 100644 index d2df026d9911d..0000000000000 --- a/superset/assets/branding/FullLockupWithoutText@1x.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - Full Lockup Without Text@1x - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/superset/assets/branding/FullLockupWithoutText@2x.png b/superset/assets/branding/FullLockupWithoutText@2x.png deleted file mode 100644 index 03c52d111bf98..0000000000000 Binary files a/superset/assets/branding/FullLockupWithoutText@2x.png and /dev/null differ diff --git a/superset/assets/branding/Horizontal.svg b/superset/assets/branding/Horizontal.svg deleted file mode 100644 index ecda32d0abbef..0000000000000 --- a/superset/assets/branding/Horizontal.svg +++ /dev/null @@ -1,53 +0,0 @@ - - - - - Horizontal - Created with Sketch. - - - - - - - - - - - - - Superse - t - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/superset/assets/branding/Horizontal@2x.png b/superset/assets/branding/Horizontal@2x.png deleted file mode 100644 index 7e1e465223c37..0000000000000 Binary files a/superset/assets/branding/Horizontal@2x.png and /dev/null differ diff --git a/superset/assets/branding/SoloMark.png b/superset/assets/branding/SoloMark.png deleted file mode 100644 index 2031b86a9f522..0000000000000 Binary files a/superset/assets/branding/SoloMark.png and /dev/null differ diff --git a/superset/assets/branding/SoloMark@1x.svg b/superset/assets/branding/SoloMark@1x.svg deleted file mode 100644 index 49e565b56bec9..0000000000000 --- a/superset/assets/branding/SoloMark@1x.svg +++ /dev/null @@ -1,45 +0,0 @@ - - - - - Solo Mark@1x - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/superset/assets/branding/Superset_Logo_Gradient_Text.png b/superset/assets/branding/Superset_Logo_Gradient_Text.png deleted file mode 100644 index 4d198d4261b9d..0000000000000 Binary files a/superset/assets/branding/Superset_Logo_Gradient_Text.png and /dev/null differ diff --git a/superset/assets/branding/Superset_Logo_Gradient_Text.svg b/superset/assets/branding/Superset_Logo_Gradient_Text.svg deleted file mode 100644 index 658ac2ac74b64..0000000000000 --- a/superset/assets/branding/Superset_Logo_Gradient_Text.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/superset/assets/branding/Superset_Logo_Gradient_Text@2x.png b/superset/assets/branding/Superset_Logo_Gradient_Text@2x.png deleted file mode 100644 index 32ed8c0e77659..0000000000000 Binary files a/superset/assets/branding/Superset_Logo_Gradient_Text@2x.png and /dev/null differ diff --git a/superset/assets/branding/Superset_Logo_Horizontal_Lockup.png b/superset/assets/branding/Superset_Logo_Horizontal_Lockup.png deleted file mode 100644 index 6ebe4115e710d..0000000000000 Binary files a/superset/assets/branding/Superset_Logo_Horizontal_Lockup.png and /dev/null differ diff --git a/superset/assets/branding/Superset_Logo_Horizontal_Lockup.svg b/superset/assets/branding/Superset_Logo_Horizontal_Lockup.svg deleted file mode 100644 index d2beb0e2ccba3..0000000000000 --- a/superset/assets/branding/Superset_Logo_Horizontal_Lockup.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/superset/assets/branding/Superset_Logo_Horizontal_Lockup@2x.png b/superset/assets/branding/Superset_Logo_Horizontal_Lockup@2x.png deleted file mode 100644 index 95443ab4b8933..0000000000000 Binary files a/superset/assets/branding/Superset_Logo_Horizontal_Lockup@2x.png and /dev/null differ diff --git a/superset/assets/branding/Superset_Logo_No_Text.png b/superset/assets/branding/Superset_Logo_No_Text.png deleted file mode 100644 index 0d3fc43499184..0000000000000 Binary files a/superset/assets/branding/Superset_Logo_No_Text.png and /dev/null differ diff --git a/superset/assets/branding/Superset_Logo_No_Text.svg b/superset/assets/branding/Superset_Logo_No_Text.svg deleted file mode 100644 index 83a9a08281e9d..0000000000000 --- a/superset/assets/branding/Superset_Logo_No_Text.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/superset/assets/branding/Superset_Logo_No_Text@2x.png b/superset/assets/branding/Superset_Logo_No_Text@2x.png deleted file mode 100644 index 56abe266023ed..0000000000000 Binary files a/superset/assets/branding/Superset_Logo_No_Text@2x.png and /dev/null differ diff --git a/superset/assets/branding/Superset_Logo_Vertical_Lockup.png b/superset/assets/branding/Superset_Logo_Vertical_Lockup.png deleted file mode 100644 index 4f17f115f81d0..0000000000000 Binary files a/superset/assets/branding/Superset_Logo_Vertical_Lockup.png and /dev/null differ diff --git a/superset/assets/branding/Superset_Logo_Vertical_Lockup.svg b/superset/assets/branding/Superset_Logo_Vertical_Lockup.svg deleted file mode 100644 index 7df0dcc6a9fef..0000000000000 --- a/superset/assets/branding/Superset_Logo_Vertical_Lockup.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/superset/assets/branding/Superset_Logo_Vertical_Lockup@2x.png b/superset/assets/branding/Superset_Logo_Vertical_Lockup@2x.png deleted file mode 100644 index 6cd44b5c81f07..0000000000000 Binary files a/superset/assets/branding/Superset_Logo_Vertical_Lockup@2x.png and /dev/null differ diff --git a/superset/assets/branding/superset-logo-horiz-apache.png b/superset/assets/branding/superset-logo-horiz-apache.png new file mode 100644 index 0000000000000..fc56574edbb3e Binary files /dev/null and b/superset/assets/branding/superset-logo-horiz-apache.png differ diff --git a/superset/assets/branding/superset-logo-horiz-apache.svg b/superset/assets/branding/superset-logo-horiz-apache.svg new file mode 100644 index 0000000000000..5b76ad84a7891 --- /dev/null +++ b/superset/assets/branding/superset-logo-horiz-apache.svg @@ -0,0 +1,19 @@ + +superset-logo-horiz-apache diff --git a/superset/assets/branding/superset-logo-horiz.png b/superset/assets/branding/superset-logo-horiz.png new file mode 100644 index 0000000000000..abca7f3ff0963 Binary files /dev/null and b/superset/assets/branding/superset-logo-horiz.png differ diff --git a/superset/assets/branding/superset-logo-horiz.svg b/superset/assets/branding/superset-logo-horiz.svg new file mode 100644 index 0000000000000..ecd79f8eada22 --- /dev/null +++ b/superset/assets/branding/superset-logo-horiz.svg @@ -0,0 +1,19 @@ + +superset-logo-horiz diff --git a/superset/assets/branding/superset-logo-stacked-apache.png b/superset/assets/branding/superset-logo-stacked-apache.png new file mode 100644 index 0000000000000..3ea0ddfa8a925 Binary files /dev/null and b/superset/assets/branding/superset-logo-stacked-apache.png differ diff --git a/superset/assets/branding/superset-logo-stacked-apache.svg b/superset/assets/branding/superset-logo-stacked-apache.svg new file mode 100644 index 0000000000000..0c3071c75e7de --- /dev/null +++ b/superset/assets/branding/superset-logo-stacked-apache.svg @@ -0,0 +1,19 @@ + +superset-logo-stacked-apache diff --git a/superset/assets/branding/superset-logo-stacked.png b/superset/assets/branding/superset-logo-stacked.png new file mode 100644 index 0000000000000..300924bfd5c4b Binary files /dev/null and b/superset/assets/branding/superset-logo-stacked.png differ diff --git a/superset/assets/branding/superset-logo-stacked.svg b/superset/assets/branding/superset-logo-stacked.svg new file mode 100644 index 0000000000000..015b9599b74ab --- /dev/null +++ b/superset/assets/branding/superset-logo-stacked.svg @@ -0,0 +1,19 @@ + +superset-logo-stacked diff --git a/superset/assets/cypress/integration/dashboard/controls.js b/superset/assets/cypress/integration/dashboard/controls.js index fe5581590c83c..77974a0b8c16d 100644 --- a/superset/assets/cypress/integration/dashboard/controls.js +++ b/superset/assets/cypress/integration/dashboard/controls.js @@ -38,8 +38,8 @@ export default () => describe('top-level controls', () => { .forEach((slice) => { const sliceRequest = `getJson_${slice.slice_id}`; sliceRequests.push(`@${sliceRequest}`); - const formData = `{"slice_id":${slice.slice_id},"viz_type":"${slice.form_data.viz_type}"}`; - cy.route('GET', `/superset/explore_json/?form_data=${formData}`).as(sliceRequest); + const formData = `{"slice_id":${slice.slice_id}}`; + cy.route('POST', `/superset/explore_json/?form_data=${formData}`).as(sliceRequest); const forceRefresh = `postJson_${slice.slice_id}_force`; forceRefreshRequests.push(`@${forceRefresh}`); diff --git a/superset/assets/cypress/integration/dashboard/edit_mode.js b/superset/assets/cypress/integration/dashboard/edit_mode.js index 280b6aae41f03..79198e60af3c3 100644 --- a/superset/assets/cypress/integration/dashboard/edit_mode.js +++ b/superset/assets/cypress/integration/dashboard/edit_mode.js @@ -28,9 +28,9 @@ export default () => describe('edit mode', () => { const bootstrapData = JSON.parse(data[0].dataset.bootstrap); const dashboard = bootstrapData.dashboard_data; const boxplotChartId = dashboard.slices.find(slice => (slice.form_data.viz_type === 'box_plot')).slice_id; - const formData = `{"slice_id":${boxplotChartId},"viz_type":"box_plot"}`; + const formData = `{"slice_id":${boxplotChartId}}`; const boxplotRequest = `/superset/explore_json/?form_data=${formData}`; - cy.route('GET', boxplotRequest).as('boxplotRequest'); + cy.route('POST', boxplotRequest).as('boxplotRequest'); }); cy.get('.dashboard-header').contains('Edit dashboard').click(); diff --git a/superset/assets/cypress/integration/dashboard/filter.js b/superset/assets/cypress/integration/dashboard/filter.js index f37c8c849eec6..97b40a4150c3d 100644 --- a/superset/assets/cypress/integration/dashboard/filter.js +++ b/superset/assets/cypress/integration/dashboard/filter.js @@ -39,9 +39,9 @@ export default () => describe('dashboard filter', () => { it('should apply filter', () => { const aliases = []; - const formData = `{"slice_id":${filterId},"viz_type":"filter_box"}`; + const formData = `{"slice_id":${filterId}}`; const filterRoute = `/superset/explore_json/?form_data=${formData}`; - cy.route('GET', filterRoute).as('fetchFilter'); + cy.route('POST', filterRoute).as('fetchFilter'); cy.wait('@fetchFilter'); sliceIds .filter(id => (parseInt(id, 10) !== filterId)) diff --git a/superset/assets/cypress/integration/dashboard/load.js b/superset/assets/cypress/integration/dashboard/load.js index 79daa30422563..c6427c7320afa 100644 --- a/superset/assets/cypress/integration/dashboard/load.js +++ b/superset/assets/cypress/integration/dashboard/load.js @@ -34,8 +34,8 @@ export default () => describe('load', () => { // then define routes and create alias for each requests slices.forEach((slice) => { const alias = `getJson_${slice.slice_id}`; - const formData = `{"slice_id":${slice.slice_id},"viz_type":"${slice.form_data.viz_type}"}`; - cy.route('GET', `/superset/explore_json/?form_data=${formData}`).as(alias); + const formData = `{"slice_id":${slice.slice_id}}`; + cy.route('POST', `/superset/explore_json/?form_data=${formData}`).as(alias); aliases.push(`@${alias}`); }); }); diff --git a/superset/assets/cypress/integration/dashboard/save.js b/superset/assets/cypress/integration/dashboard/save.js index 1d26ac219a085..772862d5b87e3 100644 --- a/superset/assets/cypress/integration/dashboard/save.js +++ b/superset/assets/cypress/integration/dashboard/save.js @@ -56,9 +56,9 @@ export default () => describe('save', () => { cy.wait('@copyRequest'); // should have box_plot chart - const formData = `{"slice_id":${boxplotChartId},"viz_type":"box_plot"}`; + const formData = `{"slice_id":${boxplotChartId}}`; const boxplotRequest = `/superset/explore_json/?form_data=${formData}`; - cy.route('GET', boxplotRequest).as('boxplotRequest'); + cy.route('POST', boxplotRequest).as('boxplotRequest'); cy.wait('@boxplotRequest'); cy.get('.grid-container .box_plot').should('be.exist'); diff --git a/superset/assets/package-lock.json b/superset/assets/package-lock.json index 2390fd509854d..bc5b57b30c23a 100644 --- a/superset/assets/package-lock.json +++ b/superset/assets/package-lock.json @@ -1366,6 +1366,16 @@ "to-fast-properties": "^2.0.0" } }, + "@cnakazawa/watch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", + "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", + "dev": true, + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } + }, "@data-ui/event-flow": { "version": "0.0.54", "resolved": "http://registry.npmjs.org/@data-ui/event-flow/-/event-flow-0.0.54.tgz", @@ -2139,19 +2149,6 @@ "prop-types": "^15.6.0" } }, - "@mapbox/extent": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@mapbox/extent/-/extent-0.4.0.tgz", - "integrity": "sha1-PlkfMuHww5gchkI597CsBuYQ+Kk=" - }, - "@mapbox/geo-viewport": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@mapbox/geo-viewport/-/geo-viewport-0.2.2.tgz", - "integrity": "sha1-kyBsBEI4whpg/KfpBkyM5j6AJ7Q=", - "requires": { - "@mapbox/sphericalmercator": "~1.0.2" - } - }, "@mapbox/geojson-area": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/@mapbox/geojson-area/-/geojson-area-0.2.2.tgz", @@ -2270,9 +2267,9 @@ } }, "@superset-ui/chart": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/@superset-ui/chart/-/chart-0.11.1.tgz", - "integrity": "sha512-TnXRn/FrlWuTQbpM3TLnSirNn7rKu43TceMt6hcnxbAlLYDIs75YQvBkkjtDYjeuIbkNrpZdfaIQuuTXV3InRw==", + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/@superset-ui/chart/-/chart-0.11.3.tgz", + "integrity": "sha512-uEk3h8pgxpYGr5rEVV3BgVG4uDsVJMQlqfii0kHjvq0y3LV+ba/GyYdMgqcTfF6agcqJVWlbfPdq9znDtvhOcg==", "requires": { "@types/react": "^16.7.17", "@types/react-loadable": "^5.4.2", @@ -2282,9 +2279,9 @@ } }, "@superset-ui/color": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@superset-ui/color/-/color-0.11.0.tgz", - "integrity": "sha512-/eAYiUSu9GuEVTxylfOC0GV8OyJ3d6oEMIMGLfAztMOFu/5LFHEWPjJJS9D1eA9h1EaEo3nfPi0cSAtqE8oI5w==", + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/@superset-ui/color/-/color-0.11.3.tgz", + "integrity": "sha512-1rJzimtkd7M5iRW2PDFHNGqU8EW5SQHywMygGdd+Oxk4jmlmJgpRMP1Igx//ghX+nS2c+k3VTDfYEHs7ozgyxA==", "requires": { "@types/d3-scale": "^2.0.2", "d3-scale": "^2.1.2" @@ -2662,18 +2659,18 @@ } }, "@superset-ui/number-format": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@superset-ui/number-format/-/number-format-0.11.0.tgz", - "integrity": "sha512-DDK0opkYXOL42M2ONzrQVauAAO/15cP08dNy5DAP0x7O7vLQQ/DrhXbGW/GwHsL8tMRdCXyJn7gN7rodtBkDJg==", + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/@superset-ui/number-format/-/number-format-0.11.3.tgz", + "integrity": "sha512-xGQ4PTis5dNmTfcVSYJpQD/hGE00Jo9SrBVeZY3lodGDkyAPvTlpaEBOCJY3VWwfnpn1WzNDrz0+ca+pKx6eeA==", "requires": { "@types/d3-format": "^1.3.0", "d3-format": "^1.3.2" } }, "@superset-ui/time-format": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/@superset-ui/time-format/-/time-format-0.11.2.tgz", - "integrity": "sha512-9VSdOyLmcj6v7HConYhuh1/r+nJAtGJzaJRgIGYIE+0j7hu6XAr8u4JOwJO/KUXY7oT7ppqy3hN4UJqN9w25ZA==", + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/@superset-ui/time-format/-/time-format-0.11.3.tgz", + "integrity": "sha512-+9ybQEmnRgA4wirrPxZ1tWIfnlA6QAemgZsG3wam4Vjw2CMldrTiWmgYT3CvTzvFab3fZ3M4FSNN5N+GavZDHQ==", "requires": { "@types/d3-time": "^1.0.9", "@types/d3-time-format": "^2.1.0", @@ -2694,6 +2691,60 @@ "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==" }, + "@types/babel__core": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.1.tgz", + "integrity": "sha512-+hjBtgcFPYyCTo0A15+nxrCVJL7aC6Acg87TXd5OW3QhHswdrOLoles+ldL2Uk8q++7yIfl4tURtztccdeeyOw==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.0.2.tgz", + "integrity": "sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", + "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.6.tgz", + "integrity": "sha512-XYVgHF2sQ0YblLRMLNPB3CkFMewzFmlDsH/TneZFHUXDlABQgh88uOxuez7ZcXxayLFrqLwtDH1t+FmlFwNZxw==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz", + "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + } + } + }, "@types/d3": { "version": "3.5.38", "resolved": "https://registry.npmjs.org/@types/d3/-/d3-3.5.38.tgz", @@ -2722,6 +2773,12 @@ "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-2.1.1.tgz", "integrity": "sha512-tJSyXta8ZyJ52wDDHA96JEsvkbL6jl7wowGmuf45+fAkj5Y+SQOnz0N7/H68OWmPshPsAaWMQh+GAws44IzH3g==" }, + "@types/istanbul-lib-coverage": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.0.tgz", + "integrity": "sha512-eAtOAFZefEnfJiRFQBGw1eYqa5GTLCZ1y86N0XSI/D6EB+E8z6VPV/UL7Gi5UEclFqoQk+6NRqEDsfmDLXn8sg==", + "dev": true + }, "@types/jest": { "version": "23.3.10", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-23.3.10.tgz", @@ -2739,9 +2796,9 @@ "integrity": "sha512-3AQoUxQcQtLHsK25wtTWIoIpgYjH3vSDroZOUr7PpCHw/jLY1RB9z9E8dBT/OSmwStVgkRNvdh+ZHNiomRieaw==" }, "@types/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.1.tgz", - "integrity": "sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", + "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==", "dev": true }, "@types/react": { @@ -2771,6 +2828,12 @@ "@types/webpack": "*" } }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "dev": true + }, "@types/tapable": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.4.tgz", @@ -2815,6 +2878,12 @@ } } }, + "@types/yargs": { + "version": "12.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.12.tgz", + "integrity": "sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==", + "dev": true + }, "@vx/axis": { "version": "0.0.140", "resolved": "https://registry.npmjs.org/@vx/axis/-/axis-0.0.140.tgz", @@ -3338,9 +3407,9 @@ } }, "acorn-globals": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", - "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.1.tgz", + "integrity": "sha512-gJSiKY8dBIjV/0jagZIFBdVMtfQyA5QHCvAT48H2q8REQoW8Fs5AOjqBql1LgSXgrMWdevcE+8cdZ33NtVbIBA==", "dev": true, "requires": { "acorn": "^6.0.1", @@ -3348,9 +3417,9 @@ }, "dependencies": { "acorn": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.0.tgz", - "integrity": "sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", "dev": true } } @@ -3421,6 +3490,12 @@ "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", "dev": true }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, "ansi-html": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", @@ -4370,9 +4445,9 @@ } }, "p-limit": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", - "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -4388,9 +4463,9 @@ } }, "p-try": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", - "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true } } @@ -4798,7 +4873,7 @@ "dependencies": { "resolve": { "version": "1.1.7", - "resolved": "http://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true } @@ -4875,6 +4950,40 @@ "pako": "~1.0.5" } }, + "browserslist": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.4.tgz", + "integrity": "sha512-rAjx494LMjqKnMPhFkuLmLp8JWEX0o8ADTGeAbOqaF+XCvYLreZrG5uVjnPBlAQ8REZK4pzXGvp0bWgrFtKaag==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000955", + "electron-to-chromium": "^1.3.122", + "node-releases": "^1.1.13" + }, + "dependencies": { + "caniuse-lite": { + "version": "1.0.30000957", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000957.tgz", + "integrity": "sha512-8wxNrjAzyiHcLXN/iunskqQnJquQQ6VX8JHfW5kLgAPRSiSuKZiNfmIkP5j7jgyXqAQBSoXyJxfnbCFS0ThSiQ==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.124", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.124.tgz", + "integrity": "sha512-glecGr/kFdfeXUHOHAWvGcXrxNU+1wSO/t5B23tT1dtlvYB26GY8aHzZSWD7HqhqC800Lr+w/hQul6C5AF542w==", + "dev": true + }, + "node-releases": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.13.tgz", + "integrity": "sha512-fKZGviSXR6YvVPyc011NHuJDSD8gFQvLPmc2d2V3BS4gr52ycyQ1Xzs7a8B+Ax3Ni/W+5h1h4SqmzeoA8WZRmA==", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + } + } + }, "bs-logger": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", @@ -5027,7 +5136,7 @@ "dependencies": { "callsites": { "version": "2.0.0", - "resolved": "http://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", "dev": true } @@ -5069,19 +5178,6 @@ "caniuse-lite": "^1.0.0", "lodash.memoize": "^4.1.2", "lodash.uniq": "^4.5.0" - }, - "dependencies": { - "browserslist": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.6.tgz", - "integrity": "sha512-kMGKs4BTzRWviZ8yru18xBpx+CyHG9eqgRbj9XbE3IMgtczf4aiA0Y1YCpVdvUieKGZ03kolSPXqTcscBCb9qw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000921", - "electron-to-chromium": "^1.3.92", - "node-releases": "^1.1.1" - } - } } }, "caniuse-lite": { @@ -5091,12 +5187,12 @@ "dev": true }, "capture-exit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-1.2.0.tgz", - "integrity": "sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", "dev": true, "requires": { - "rsvp": "^3.3.3" + "rsvp": "^4.8.4" } }, "capture-stack-trace": { @@ -5308,6 +5404,12 @@ "tslib": "^1.9.0" } }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -5458,9 +5560,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -5763,14 +5865,14 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cosmiconfig": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.7.tgz", - "integrity": "sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.0.tgz", + "integrity": "sha512-nxt+Nfc3JAqf4WIWd0jXLjTJZmsPLrA9DDc4nRw2KFJQJK7DNooqSXrNI7tzLG50CF8axczly5UV929tBmh/7g==", "dev": true, "requires": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", - "js-yaml": "^3.9.0", + "js-yaml": "^3.13.0", "parse-json": "^4.0.0" }, "dependencies": { @@ -5895,7 +5997,7 @@ }, "css-color-names": { "version": "0.0.4", - "resolved": "http://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", "dev": true }, @@ -5919,25 +6021,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -5947,9 +6060,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -6094,13 +6207,13 @@ "dev": true }, "cssnano": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.7.tgz", - "integrity": "sha512-AiXL90l+MDuQmRNyypG2P7ux7K4XklxYzNNUd5HXZCNcH8/N9bHPcpN97v8tXgRVeFL/Ed8iP8mVmAAu0ZpT7A==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", + "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", "dev": true, "requires": { "cosmiconfig": "^5.0.0", - "cssnano-preset-default": "^4.0.5", + "cssnano-preset-default": "^4.0.7", "is-resolvable": "^1.0.0", "postcss": "^7.0.0" }, @@ -6115,25 +6228,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -6143,9 +6267,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -6154,40 +6278,40 @@ } }, "cssnano-preset-default": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.5.tgz", - "integrity": "sha512-f1uhya0ZAjPYtDD58QkBB0R+uYdzHPei7cDxJyQQIHt5acdhyGXaSXl2nDLzWHLwGFbZcHxQtkJS8mmNwnxTvw==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", + "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", "dev": true, "requires": { "css-declaration-sorter": "^4.0.1", "cssnano-util-raw-cache": "^4.0.1", "postcss": "^7.0.0", - "postcss-calc": "^7.0.0", - "postcss-colormin": "^4.0.2", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", "postcss-convert-values": "^4.0.1", - "postcss-discard-comments": "^4.0.1", + "postcss-discard-comments": "^4.0.2", "postcss-discard-duplicates": "^4.0.2", "postcss-discard-empty": "^4.0.1", "postcss-discard-overridden": "^4.0.1", - "postcss-merge-longhand": "^4.0.9", - "postcss-merge-rules": "^4.0.2", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", "postcss-minify-font-values": "^4.0.2", - "postcss-minify-gradients": "^4.0.1", - "postcss-minify-params": "^4.0.1", - "postcss-minify-selectors": "^4.0.1", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", "postcss-normalize-charset": "^4.0.1", - "postcss-normalize-display-values": "^4.0.1", - "postcss-normalize-positions": "^4.0.1", - "postcss-normalize-repeat-style": "^4.0.1", - "postcss-normalize-string": "^4.0.1", - "postcss-normalize-timing-functions": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", "postcss-normalize-unicode": "^4.0.1", "postcss-normalize-url": "^4.0.1", - "postcss-normalize-whitespace": "^4.0.1", - "postcss-ordered-values": "^4.1.1", - "postcss-reduce-initial": "^4.0.2", - "postcss-reduce-transforms": "^4.0.1", - "postcss-svgo": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.2", "postcss-unique-selectors": "^4.0.1" }, "dependencies": { @@ -6201,25 +6325,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -6229,9 +6364,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -6270,25 +6405,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -6298,9 +6444,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -6342,9 +6488,9 @@ "dev": true }, "cssstyle": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.1.tgz", - "integrity": "sha512-7DYm8qe+gPx/h77QlCyFmX80+fGaE/6A/Ekl0zaszYOubvySO2saYFdQ78P29D0UsULxFKCetDGNaNRUdSF+2A==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.2.tgz", + "integrity": "sha512-43wY3kl1CVQSvL7wUY1qXkxVGkStjpkDmVjiIKX8R97uhajy8Bybay78uOtqvh7Q5GK75dNPfW0geWjE6qQQow==", "dev": true, "requires": { "cssom": "0.3.x" @@ -6882,9 +7028,9 @@ "dev": true }, "diff-sequences": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.0.0.tgz", - "integrity": "sha512-46OkIuVGBBnrC0soO/4LHu5LHGHx0uhP65OVz8XOrAJpqiCB2aVIuESvjI1F9oqebuvY8lekS1pt6TN7vt7qsw==", + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.3.0.tgz", + "integrity": "sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==", "dev": true }, "diffie-hellman": { @@ -7829,13 +7975,10 @@ } }, "exec-sh": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz", - "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==", - "dev": true, - "requires": { - "merge": "^1.2.0" - } + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.2.tgz", + "integrity": "sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==", + "dev": true }, "execa": { "version": "0.10.0", @@ -7895,16 +8038,17 @@ } }, "expect": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-24.1.0.tgz", - "integrity": "sha512-lVcAPhaYkQcIyMS+F8RVwzbm1jro20IG8OkvxQ6f1JfqhVZyyudCwYogQ7wnktlf14iF3ii7ArIUO/mqvrW9Gw==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.7.1.tgz", + "integrity": "sha512-mGfvMTPduksV3xoI0xur56pQsg2vJjNf5+a+bXOjqCkiCBbmCayrBbHS/75y9K430cfqyocPr2ZjiNiRx4SRKw==", "dev": true, "requires": { + "@jest/types": "^24.7.0", "ansi-styles": "^3.2.0", - "jest-get-type": "^24.0.0", - "jest-matcher-utils": "^24.0.0", - "jest-message-util": "^24.0.0", - "jest-regex-util": "^24.0.0" + "jest-get-type": "^24.3.0", + "jest-matcher-utils": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-regex-util": "^24.3.0" }, "dependencies": { "ansi-styles": { @@ -8846,6 +8990,16 @@ "readable-stream": "^2.0.0" } }, + "fs-minipass": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, "fs-readdir-recursive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", @@ -8870,9 +9024,9 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", + "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", "dev": true, "optional": true, "requires": { @@ -8929,10 +9083,8 @@ }, "chownr": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", - "dev": true, - "optional": true + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" }, "code-point-at": { "version": "1.1.0", @@ -9121,22 +9273,10 @@ "dev": true, "optional": true }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" - } - }, "minizlib": { "version": "1.1.0", "resolved": false, "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", - "dev": true, - "optional": true, "requires": { "minipass": "^2.2.1" } @@ -9340,7 +9480,7 @@ } }, "safe-buffer": { - "version": "5.1.1", + "version": "5.1.2", "bundled": true, "dev": true, "optional": true @@ -9455,12 +9595,6 @@ "bundled": true, "dev": true, "optional": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true } } }, @@ -9773,29 +9907,20 @@ "dev": true }, "handlebars": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.0.tgz", - "integrity": "sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", "dev": true, "requires": { - "async": "^2.5.0", + "neo-async": "^2.6.0", "optimist": "^0.6.1", "source-map": "^0.6.1", "uglify-js": "^3.1.4" }, "dependencies": { - "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, "minimist": { "version": "0.0.10", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -10904,6 +11029,15 @@ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, "is-color-stop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", @@ -10989,9 +11123,9 @@ "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" }, "is-generator-fn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.0.0.tgz", - "integrity": "sha512-elzyIdM7iKoFHzcrndIqjYomImhxrFRnGP3galODoII4TB9gI7mZ+FnlLQmmjf27SxHS2gKEeyhX5/+YRS6H9g==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true }, "is-hexadecimal": { @@ -11031,8 +11165,9 @@ }, "is-obj": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true }, "is-path-cwd": { "version": "1.0.0", @@ -11343,16 +11478,10 @@ "jest-cli": "^24.1.0" }, "dependencies": { - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, "ansi-regex": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", - "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { @@ -11364,85 +11493,262 @@ "color-convert": "^1.9.0" } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "babel-jest": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.7.1.tgz", + "integrity": "sha512-GPnLqfk8Mtt0i4OemjWkChi73A3ALs4w2/QbG64uAj8b5mmwzxc7jbJVRZt8NJkxi6FopVHog9S3xX6UJKb2qg==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "@jest/transform": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.6.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" } }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "babel-plugin-jest-hoist": { + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.6.0.tgz", + "integrity": "sha512-3pKNH6hMt9SbOv0F3WVmy5CWQ4uogS3k0GY5XLyQHJ9EGpAT9XWkFd2ZiXXtkwFHdAHa5j7w7kfxSP5lAIwu7w==", "dev": true, "requires": { - "ci-info": "^2.0.0" + "@types/babel__traverse": "^7.0.6" } }, - "jest-cli": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.1.0.tgz", - "integrity": "sha512-U/iyWPwOI0T1CIxVLtk/2uviOTJ/OiSWJSe8qt6X1VkbbgP+nrtLJlmT9lPBe4lK78VNFJtrJ7pttcNv/s7yCw==", + "babel-preset-jest": { + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.6.0.tgz", + "integrity": "sha512-pdZqLEdmy1ZK5kyRUfvBb2IfTPb2BUvIJczlPspS8fWmBQslNNDBqVfh7BW5leOVJMDZKzjD8XEyABTk6gQ5yw==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.6.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "jest-cli": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.7.1.tgz", + "integrity": "sha512-32OBoSCVPzcTslGFl6yVCMzB2SqX3IrWwZCY5mZYkb0D2WsogmU3eV2o8z7+gRQa4o4sZPX/k7GU+II7CxM6WQ==", + "dev": true, + "requires": { + "@jest/core": "^24.7.1", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "chalk": "^2.0.1", "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.1.15", "import-local": "^2.0.0", "is-ci": "^2.0.0", - "istanbul-api": "^2.0.8", - "istanbul-lib-coverage": "^2.0.2", - "istanbul-lib-instrument": "^3.0.1", - "istanbul-lib-source-maps": "^3.0.1", - "jest-changed-files": "^24.0.0", - "jest-config": "^24.1.0", - "jest-environment-jsdom": "^24.0.0", - "jest-get-type": "^24.0.0", - "jest-haste-map": "^24.0.0", - "jest-message-util": "^24.0.0", - "jest-regex-util": "^24.0.0", - "jest-resolve-dependencies": "^24.1.0", - "jest-runner": "^24.1.0", - "jest-runtime": "^24.1.0", - "jest-snapshot": "^24.1.0", - "jest-util": "^24.0.0", - "jest-validate": "^24.0.0", - "jest-watcher": "^24.0.0", - "jest-worker": "^24.0.0", - "micromatch": "^3.1.10", - "node-notifier": "^5.2.1", - "p-each-series": "^1.0.0", - "pirates": "^4.0.0", + "jest-config": "^24.7.1", + "jest-util": "^24.7.1", + "jest-validate": "^24.7.0", "prompts": "^2.0.1", - "realpath-native": "^1.0.0", - "rimraf": "^2.5.4", - "slash": "^2.0.0", - "string-length": "^2.0.0", - "strip-ansi": "^5.0.0", - "which": "^1.2.12", + "realpath-native": "^1.1.0", "yargs": "^12.0.2" + }, + "dependencies": { + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "jest-config": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.7.1.tgz", + "integrity": "sha512-8FlJNLI+X+MU37j7j8RE4DnJkvAghXmBWdArVzypW6WxfGuxiL/CCkzBg0gHtXhD2rxla3IMOSUAHylSKYJ83g==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.7.1", + "@jest/types": "^24.7.0", + "babel-jest": "^24.7.1", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.7.1", + "jest-environment-node": "^24.7.1", + "jest-get-type": "^24.3.0", + "jest-jasmine2": "^24.7.1", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.7.1", + "jest-util": "^24.7.1", + "jest-validate": "^24.7.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.7.0", + "realpath-native": "^1.1.0" + } + }, + "jest-util": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.7.1.tgz", + "integrity": "sha512-/KilOue2n2rZ5AnEBYoxOXkeTu6vi7cjgQ8MXEkih0oeAXT6JkS3fr7/j8+engCjciOU1Nq5loMSKe0A1oeX0A==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/fake-timers": "^24.7.1", + "@jest/source-map": "^24.3.0", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + } + }, + "jest-validate": { + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.7.0.tgz", + "integrity": "sha512-cgai/gts9B2chz1rqVdmLhzYxQbgQurh1PEQSvSgPZ8KGa1AqXsqC45W5wKEwzxKrWqypuQrQxnF4+G9VejJJA==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0", + "camelcase": "^5.0.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.3.0", + "leven": "^2.1.0", + "pretty-format": "^24.7.0" + } + }, + "prompts": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.0.4.tgz", + "integrity": "sha512-HTzM3UWp/99A0gk51gAegwo1QRYA7xjcZufMNe33rCclFszUYAuHe1fIN/3ZmiHeGPkUsNaRyQm1hHOfM0PKxA==", + "dev": true, + "requires": { + "kleur": "^3.0.2", + "sisteransi": "^1.0.0" + } + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "strip-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", - "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^4.0.0" + "ansi-regex": "^3.0.0" } }, "supports-color": { @@ -11457,11 +11763,12 @@ } }, "jest-changed-files": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.0.0.tgz", - "integrity": "sha512-nnuU510R9U+UX0WNb5XFEcsrMqriSiRLeO9KWDFgPrpToaQm60prfQYpxsXigdClpvNot5bekDY440x9dNGnsQ==", + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.7.0.tgz", + "integrity": "sha512-33BgewurnwSfJrW7T5/ZAXGE44o7swLslwh8aUckzq2e17/2Os1V0QU506ZNik3hjs8MgnEMKNkcud442NCDTw==", "dev": true, "requires": { + "@jest/types": "^24.7.0", "execa": "^1.0.0", "throat": "^4.0.0" }, @@ -11493,26 +11800,28 @@ } }, "jest-config": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.1.0.tgz", - "integrity": "sha512-FbbRzRqtFC6eGjG5VwsbW4E5dW3zqJKLWYiZWhB0/4E5fgsMw8GODLbGSrY5t17kKOtCWb/Z7nsIThRoDpuVyg==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.7.1.tgz", + "integrity": "sha512-8FlJNLI+X+MU37j7j8RE4DnJkvAghXmBWdArVzypW6WxfGuxiL/CCkzBg0gHtXhD2rxla3IMOSUAHylSKYJ83g==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "babel-jest": "^24.1.0", + "@jest/test-sequencer": "^24.7.1", + "@jest/types": "^24.7.0", + "babel-jest": "^24.7.1", "chalk": "^2.0.1", "glob": "^7.1.1", - "jest-environment-jsdom": "^24.0.0", - "jest-environment-node": "^24.0.0", - "jest-get-type": "^24.0.0", - "jest-jasmine2": "^24.1.0", - "jest-regex-util": "^24.0.0", - "jest-resolve": "^24.1.0", - "jest-util": "^24.0.0", - "jest-validate": "^24.0.0", + "jest-environment-jsdom": "^24.7.1", + "jest-environment-node": "^24.7.1", + "jest-get-type": "^24.3.0", + "jest-jasmine2": "^24.7.1", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.7.1", + "jest-util": "^24.7.1", + "jest-validate": "^24.7.0", "micromatch": "^3.1.10", - "pretty-format": "^24.0.0", - "realpath-native": "^1.0.2" + "pretty-format": "^24.7.0", + "realpath-native": "^1.1.0" }, "dependencies": { "ansi-styles": { @@ -11524,6 +11833,40 @@ "color-convert": "^1.9.0" } }, + "babel-jest": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.7.1.tgz", + "integrity": "sha512-GPnLqfk8Mtt0i4OemjWkChi73A3ALs4w2/QbG64uAj8b5mmwzxc7jbJVRZt8NJkxi6FopVHog9S3xX6UJKb2qg==", + "dev": true, + "requires": { + "@jest/transform": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.6.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.6.0.tgz", + "integrity": "sha512-3pKNH6hMt9SbOv0F3WVmy5CWQ4uogS3k0GY5XLyQHJ9EGpAT9XWkFd2ZiXXtkwFHdAHa5j7w7kfxSP5lAIwu7w==", + "dev": true, + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.6.0.tgz", + "integrity": "sha512-pdZqLEdmy1ZK5kyRUfvBb2IfTPb2BUvIJczlPspS8fWmBQslNNDBqVfh7BW5leOVJMDZKzjD8XEyABTk6gQ5yw==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.6.0" + } + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -11547,15 +11890,15 @@ } }, "jest-diff": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.0.0.tgz", - "integrity": "sha512-XY5wMpRaTsuMoU+1/B2zQSKQ9RdE9gsLkGydx3nvApeyPijLA8GtEvIcPwISRCer+VDf9W1mStTYYq6fPt8ryA==", + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.7.0.tgz", + "integrity": "sha512-ULQZ5B1lWpH70O4xsANC4tf4Ko6RrpwhE3PtG6ERjMg1TiYTC2Wp4IntJVGro6a8HG9luYHhhmF4grF0Pltckg==", "dev": true, "requires": { "chalk": "^2.0.1", - "diff-sequences": "^24.0.0", - "jest-get-type": "^24.0.0", - "pretty-format": "^24.0.0" + "diff-sequences": "^24.3.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" }, "dependencies": { "ansi-styles": { @@ -11596,15 +11939,16 @@ "dev": true }, "jest-each": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.0.0.tgz", - "integrity": "sha512-gFcbY4Cu55yxExXMkjrnLXov3bWO3dbPAW7HXb31h/DNWdNc/6X8MtxGff8nh3/MjkF9DpVqnj0KsPKuPK0cpA==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.7.1.tgz", + "integrity": "sha512-4fsS8fEfLa3lfnI1Jw6NxjhyRTgfpuOVTeUZZFyVYqeTa4hPhr2YkToUhouuLTrL2eMGOfpbdMyRx0GQ/VooKA==", "dev": true, "requires": { + "@jest/types": "^24.7.0", "chalk": "^2.0.1", - "jest-get-type": "^24.0.0", - "jest-util": "^24.0.0", - "pretty-format": "^24.0.0" + "jest-get-type": "^24.3.0", + "jest-util": "^24.7.1", + "pretty-format": "^24.7.0" }, "dependencies": { "ansi-styles": { @@ -11639,13 +11983,16 @@ } }, "jest-environment-jsdom": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.0.0.tgz", - "integrity": "sha512-1YNp7xtxajTRaxbylDc2pWvFnfDTH5BJJGyVzyGAKNt/lEULohwEV9zFqTgG4bXRcq7xzdd+sGFws+LxThXXOw==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.7.1.tgz", + "integrity": "sha512-Gnhb+RqE2JuQGb3kJsLF8vfqjt3PHKSstq4Xc8ic+ax7QKo4Z0RWGucU3YV+DwKR3T9SYc+3YCUQEJs8r7+Jxg==", "dev": true, "requires": { - "jest-mock": "^24.0.0", - "jest-util": "^24.0.0", + "@jest/environment": "^24.7.1", + "@jest/fake-timers": "^24.7.1", + "@jest/types": "^24.7.0", + "jest-mock": "^24.7.0", + "jest-util": "^24.7.1", "jsdom": "^11.5.1" }, "dependencies": { @@ -11692,98 +12039,65 @@ } }, "jest-environment-node": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.0.0.tgz", - "integrity": "sha512-62fOFcaEdU0VLaq8JL90TqwI7hLn0cOKOl8vY2n477vRkCJRojiRRtJVRzzCcgFvs6gqU97DNqX5R0BrBP6Rxg==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.7.1.tgz", + "integrity": "sha512-GJJQt1p9/C6aj6yNZMvovZuxTUd+BEJprETdvTKSb4kHcw4mFj8777USQV0FJoJ4V3djpOwA5eWyPwfq//PFBA==", "dev": true, "requires": { - "jest-mock": "^24.0.0", - "jest-util": "^24.0.0" + "@jest/environment": "^24.7.1", + "@jest/fake-timers": "^24.7.1", + "@jest/types": "^24.7.0", + "jest-mock": "^24.7.0", + "jest-util": "^24.7.1" } }, "jest-get-type": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.0.0.tgz", - "integrity": "sha512-z6/Eyf6s9ZDGz7eOvl+fzpuJmN9i0KyTt1no37/dHu8galssxz5ZEgnc1KaV8R31q1khxyhB4ui/X5ZjjPk77w==", + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz", + "integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==", "dev": true }, "jest-haste-map": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.0.0.tgz", - "integrity": "sha512-CcViJyUo41IQqttLxXVdI41YErkzBKbE6cS6dRAploCeutePYfUimWd3C9rQEWhX0YBOQzvNsC0O9nYxK2nnxQ==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.7.1.tgz", + "integrity": "sha512-g0tWkzjpHD2qa03mTKhlydbmmYiA2KdcJe762SbfFo/7NIMgBWAA0XqQlApPwkWOF7Cxoi/gUqL0i6DIoLpMBw==", "dev": true, "requires": { + "@jest/types": "^24.7.0", + "anymatch": "^2.0.0", "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", "graceful-fs": "^4.1.15", "invariant": "^2.2.4", - "jest-serializer": "^24.0.0", - "jest-util": "^24.0.0", - "jest-worker": "^24.0.0", + "jest-serializer": "^24.4.0", + "jest-util": "^24.7.1", + "jest-worker": "^24.6.0", "micromatch": "^3.1.10", - "sane": "^3.0.0" - }, - "dependencies": { - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "sane": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/sane/-/sane-3.1.0.tgz", - "integrity": "sha512-G5GClRRxT1cELXfdAq7UKtUsv8q/ZC5k8lQGmjEm4HcAl3HzBy68iglyNCmw4+0tiXPCBZntslHlRhbnsSws+Q==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "capture-exit": "^1.2.0", - "exec-sh": "^0.2.0", - "execa": "^1.0.0", - "fb-watchman": "^2.0.0", - "fsevents": "^1.2.3", - "micromatch": "^3.1.4", - "minimist": "^1.1.1", - "walker": "~1.0.5", - "watch": "~0.18.0" - } - } + "sane": "^4.0.3", + "walker": "^1.0.7" } }, "jest-jasmine2": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.1.0.tgz", - "integrity": "sha512-H+o76SdSNyCh9fM5K8upK45YTo/DiFx5w2YAzblQebSQmukDcoVBVeXynyr7DDnxh+0NTHYRCLwJVf3tC518wg==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.7.1.tgz", + "integrity": "sha512-Y/9AOJDV1XS44wNwCaThq4Pw3gBPiOv/s6NcbOAkVRRUEPu+36L2xoPsqQXsDrxoBerqeyslpn2TpCI8Zr6J2w==", "dev": true, "requires": { "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.7.1", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", "chalk": "^2.0.1", "co": "^4.6.0", - "expect": "^24.1.0", + "expect": "^24.7.1", "is-generator-fn": "^2.0.0", - "jest-each": "^24.0.0", - "jest-matcher-utils": "^24.0.0", - "jest-message-util": "^24.0.0", - "jest-snapshot": "^24.1.0", - "jest-util": "^24.0.0", - "pretty-format": "^24.0.0", + "jest-each": "^24.7.1", + "jest-matcher-utils": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-runtime": "^24.7.1", + "jest-snapshot": "^24.7.1", + "jest-util": "^24.7.1", + "pretty-format": "^24.7.0", "throat": "^4.0.0" }, "dependencies": { @@ -11819,24 +12133,24 @@ } }, "jest-leak-detector": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.0.0.tgz", - "integrity": "sha512-ZYHJYFeibxfsDSKowjDP332pStuiFT2xfc5R67Rjm/l+HFJWJgNIOCOlQGeXLCtyUn3A23+VVDdiCcnB6dTTrg==", + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.7.0.tgz", + "integrity": "sha512-zV0qHKZGXtmPVVzT99CVEcHE9XDf+8LwiE0Ob7jjezERiGVljmqKFWpV2IkG+rkFIEUHFEkMiICu7wnoPM/RoQ==", "dev": true, "requires": { - "pretty-format": "^24.0.0" + "pretty-format": "^24.7.0" } }, "jest-matcher-utils": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.0.0.tgz", - "integrity": "sha512-LQTDmO+aWRz1Tf9HJg+HlPHhDh1E1c65kVwRFo5mwCVp5aQDzlkz4+vCvXhOKFjitV2f0kMdHxnODrXVoi+rlA==", + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.7.0.tgz", + "integrity": "sha512-158ieSgk3LNXeUhbVJYRXyTPSCqNgVXOp/GT7O94mYd3pk/8+odKTyR1JLtNOQSPzNi8NFYVONtvSWA/e1RDXg==", "dev": true, "requires": { "chalk": "^2.0.1", - "jest-diff": "^24.0.0", - "jest-get-type": "^24.0.0", - "pretty-format": "^24.0.0" + "jest-diff": "^24.7.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.7.0" }, "dependencies": { "ansi-styles": { @@ -11871,12 +12185,15 @@ } }, "jest-message-util": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.0.0.tgz", - "integrity": "sha512-J9ROJIwz/IeC+eV1XSwnRK4oAwPuhmxEyYx1+K5UI+pIYwFZDSrfZaiWTdq0d2xYFw4Xiu+0KQWsdsQpgJMf3Q==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.7.1.tgz", + "integrity": "sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/stack-utils": "^1.0.1", "chalk": "^2.0.1", "micromatch": "^3.1.10", "slash": "^2.0.0", @@ -11915,26 +12232,37 @@ } }, "jest-mock": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.0.0.tgz", - "integrity": "sha512-sQp0Hu5fcf5NZEh1U9eIW2qD0BwJZjb63Yqd98PQJFvf/zzUTBoUAwv/Dc/HFeNHIw1f3hl/48vNn+j3STaI7A==", + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.7.0.tgz", + "integrity": "sha512-6taW4B4WUcEiT2V9BbOmwyGuwuAFT2G8yghF7nyNW1/2gq5+6aTqSPcS9lS6ArvEkX55vbPAS/Jarx5LSm4Fng==", + "dev": true, + "requires": { + "@jest/types": "^24.7.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", + "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", "dev": true }, "jest-regex-util": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.0.0.tgz", - "integrity": "sha512-Jv/uOTCuC+PY7WpJl2mpoI+WbY2ut73qwwO9ByJJNwOCwr1qWhEW2Lyi2S9ZewUdJqeVpEBisdEVZSI+Zxo58Q==", + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.3.0.tgz", + "integrity": "sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg==", "dev": true }, "jest-resolve": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.1.0.tgz", - "integrity": "sha512-TPiAIVp3TG6zAxH28u/6eogbwrvZjBMWroSLBDkwkHKrqxB/RIdwkWDye4uqPlZIXWIaHtifY3L0/eO5Z0f2wg==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.7.1.tgz", + "integrity": "sha512-Bgrc+/UUZpGJ4323sQyj85hV9d+ANyPNu6XfRDUcyFNX1QrZpSoM0kE4Mb2vZMAYTJZsBFzYe8X1UaOkOELSbw==", "dev": true, "requires": { + "@jest/types": "^24.7.0", "browser-resolve": "^1.11.3", "chalk": "^2.0.1", - "realpath-native": "^1.0.0" + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" }, "dependencies": { "ansi-styles": { @@ -11969,33 +12297,39 @@ } }, "jest-resolve-dependencies": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.1.0.tgz", - "integrity": "sha512-2VwPsjd3kRPu7qe2cpytAgowCObk5AKeizfXuuiwgm1a9sijJDZe8Kh1sFj6FKvSaNEfCPlBVkZEJa2482m/Uw==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.7.1.tgz", + "integrity": "sha512-2Eyh5LJB2liNzfk4eo7bD1ZyBbqEJIyyrFtZG555cSWW9xVHxII2NuOkSl1yUYTAYCAmM2f2aIT5A7HzNmubyg==", "dev": true, "requires": { - "jest-regex-util": "^24.0.0", - "jest-snapshot": "^24.1.0" + "@jest/types": "^24.7.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.7.1" } }, "jest-runner": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.1.0.tgz", - "integrity": "sha512-CDGOkT3AIFl16BLL/OdbtYgYvbAprwJ+ExKuLZmGSCSldwsuU2dEGauqkpvd9nphVdAnJUcP12e/EIlnTX0QXg==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.7.1.tgz", + "integrity": "sha512-aNFc9liWU/xt+G9pobdKZ4qTeG/wnJrJna3VqunziDNsWT3EBpmxXZRBMKCsNMyfy+A/XHiV+tsMLufdsNdgCw==", "dev": true, "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.7.1", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", "chalk": "^2.4.2", "exit": "^0.1.2", "graceful-fs": "^4.1.15", - "jest-config": "^24.1.0", - "jest-docblock": "^24.0.0", - "jest-haste-map": "^24.0.0", - "jest-jasmine2": "^24.1.0", - "jest-leak-detector": "^24.0.0", - "jest-message-util": "^24.0.0", - "jest-runtime": "^24.1.0", - "jest-util": "^24.0.0", - "jest-worker": "^24.0.0", + "jest-config": "^24.7.1", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.7.1", + "jest-jasmine2": "^24.7.1", + "jest-leak-detector": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-resolve": "^24.7.1", + "jest-runtime": "^24.7.1", + "jest-util": "^24.7.1", + "jest-worker": "^24.6.0", "source-map-support": "^0.5.6", "throat": "^4.0.0" }, @@ -12021,9 +12355,9 @@ } }, "jest-docblock": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.0.0.tgz", - "integrity": "sha512-KfAKZ4SN7CFOZpWg4i7g7MSlY0M+mq7K0aMqENaG2vHuhC9fc3vkpU/iNN9sOus7v3h3Y48uEjqz3+Gdn2iptA==", + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.3.0.tgz", + "integrity": "sha512-nlANmF9Yq1dufhFlKG9rasfQlrY7wINJbo3q01tu56Jv5eBU5jirylhF2O5ZBnLxzOVBGRDz/9NAwNyBtG4Nyg==", "dev": true, "requires": { "detect-newline": "^2.1.0" @@ -12041,32 +12375,33 @@ } }, "jest-runtime": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.1.0.tgz", - "integrity": "sha512-59/BY6OCuTXxGeDhEMU7+N33dpMQyXq7MLK07cNSIY/QYt2QZgJ7Tjx+rykBI0skAoigFl0A5tmT8UdwX92YuQ==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.7.1.tgz", + "integrity": "sha512-0VAbyBy7tll3R+82IPJpf6QZkokzXPIS71aDeqh+WzPRXRCNz6StQ45otFariPdJ4FmXpDiArdhZrzNAC3sj6A==", "dev": true, "requires": { - "@babel/core": "^7.1.0", - "babel-plugin-istanbul": "^5.1.0", + "@jest/console": "^24.7.1", + "@jest/environment": "^24.7.1", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/yargs": "^12.0.2", "chalk": "^2.0.1", - "convert-source-map": "^1.4.0", "exit": "^0.1.2", - "fast-json-stable-stringify": "^2.0.0", "glob": "^7.1.3", "graceful-fs": "^4.1.15", - "jest-config": "^24.1.0", - "jest-haste-map": "^24.0.0", - "jest-message-util": "^24.0.0", - "jest-regex-util": "^24.0.0", - "jest-resolve": "^24.1.0", - "jest-snapshot": "^24.1.0", - "jest-util": "^24.0.0", - "jest-validate": "^24.0.0", - "micromatch": "^3.1.10", - "realpath-native": "^1.0.0", + "jest-config": "^24.7.1", + "jest-haste-map": "^24.7.1", + "jest-message-util": "^24.7.1", + "jest-mock": "^24.7.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.7.1", + "jest-snapshot": "^24.7.1", + "jest-util": "^24.7.1", + "jest-validate": "^24.7.0", + "realpath-native": "^1.1.0", "slash": "^2.0.0", "strip-bom": "^3.0.0", - "write-file-atomic": "2.4.1", "yargs": "^12.0.2" }, "dependencies": { @@ -12102,26 +12437,28 @@ } }, "jest-serializer": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.0.0.tgz", - "integrity": "sha512-9FKxQyrFgHtx3ozU+1a8v938ILBE7S8Ko3uiAVjT8Yfi2o91j/fj81jacCQZ/Ihjiff/VsUCXVgQ+iF1XdImOw==", + "version": "24.4.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.4.0.tgz", + "integrity": "sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q==", "dev": true }, "jest-snapshot": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.1.0.tgz", - "integrity": "sha512-th6TDfFqEmXvuViacU1ikD7xFb7lQsPn2rJl7OEmnfIVpnrx3QNY2t3PE88meeg0u/mQ0nkyvmC05PBqO4USFA==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.7.1.tgz", + "integrity": "sha512-8Xk5O4p+JsZZn4RCNUS3pxA+ORKpEKepE+a5ejIKrId9CwrVN0NY+vkqEkXqlstA5NMBkNahXkR/4qEBy0t5yA==", "dev": true, "requires": { "@babel/types": "^7.0.0", + "@jest/types": "^24.7.0", "chalk": "^2.0.1", - "jest-diff": "^24.0.0", - "jest-matcher-utils": "^24.0.0", - "jest-message-util": "^24.0.0", - "jest-resolve": "^24.1.0", + "expect": "^24.7.1", + "jest-diff": "^24.7.0", + "jest-matcher-utils": "^24.7.0", + "jest-message-util": "^24.7.1", + "jest-resolve": "^24.7.1", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "pretty-format": "^24.0.0", + "pretty-format": "^24.7.0", "semver": "^5.5.0" }, "dependencies": { @@ -12157,16 +12494,20 @@ } }, "jest-util": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.0.0.tgz", - "integrity": "sha512-QxsALc4wguYS7cfjdQSOr5HTkmjzkHgmZvIDkcmPfl1ib8PNV8QUWLwbKefCudWS0PRKioV+VbQ0oCUPC691fQ==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.7.1.tgz", + "integrity": "sha512-/KilOue2n2rZ5AnEBYoxOXkeTu6vi7cjgQ8MXEkih0oeAXT6JkS3fr7/j8+engCjciOU1Nq5loMSKe0A1oeX0A==", "dev": true, "requires": { + "@jest/console": "^24.7.1", + "@jest/fake-timers": "^24.7.1", + "@jest/source-map": "^24.3.0", + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", "callsites": "^3.0.0", "chalk": "^2.0.1", "graceful-fs": "^4.1.15", "is-ci": "^2.0.0", - "jest-message-util": "^24.0.0", "mkdirp": "^0.5.1", "slash": "^2.0.0", "source-map": "^0.6.0" @@ -12182,9 +12523,9 @@ } }, "callsites": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz", - "integrity": "sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, "chalk": { @@ -12198,21 +12539,6 @@ "supports-color": "^5.3.0" } }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -12231,16 +12557,17 @@ } }, "jest-validate": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.0.0.tgz", - "integrity": "sha512-vMrKrTOP4BBFIeOWsjpsDgVXATxCspC9S1gqvbJ3Tnn/b9ACsJmteYeVx9830UMV28Cob1RX55x96Qq3Tfad4g==", + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.7.0.tgz", + "integrity": "sha512-cgai/gts9B2chz1rqVdmLhzYxQbgQurh1PEQSvSgPZ8KGa1AqXsqC45W5wKEwzxKrWqypuQrQxnF4+G9VejJJA==", "dev": true, "requires": { + "@jest/types": "^24.7.0", "camelcase": "^5.0.0", "chalk": "^2.0.1", - "jest-get-type": "^24.0.0", + "jest-get-type": "^24.3.0", "leven": "^2.1.0", - "pretty-format": "^24.0.0" + "pretty-format": "^24.7.0" }, "dependencies": { "ansi-styles": { @@ -12253,9 +12580,9 @@ } }, "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "chalk": { @@ -12281,23 +12608,20 @@ } }, "jest-watcher": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.0.0.tgz", - "integrity": "sha512-GxkW2QrZ4YxmW1GUWER05McjVDunBlKMFfExu+VsGmXJmpej1saTEKvONdx5RJBlVdpPI5x6E3+EDQSIGgl53g==", + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.7.1.tgz", + "integrity": "sha512-Wd6TepHLRHVKLNPacEsBwlp9raeBIO+01xrN24Dek4ggTS8HHnOzYSFnvp+6MtkkJ3KfMzy220KTi95e2rRkrw==", "dev": true, "requires": { + "@jest/test-result": "^24.7.1", + "@jest/types": "^24.7.0", + "@types/yargs": "^12.0.9", "ansi-escapes": "^3.0.0", "chalk": "^2.0.1", - "jest-util": "^24.0.0", + "jest-util": "^24.7.1", "string-length": "^2.0.0" }, "dependencies": { - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -12330,9 +12654,9 @@ } }, "jest-worker": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.0.0.tgz", - "integrity": "sha512-s64/OThpfQvoCeHG963MiEZOAAxu8kHsaL/rCMF7lpdzo7vgF0CtPml9hfguOMgykgH/eOm4jFP4ibfHLruytg==", + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.6.0.tgz", + "integrity": "sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ==", "dev": true, "requires": { "merge-stream": "^1.0.1", @@ -12400,9 +12724,9 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -12832,11 +13156,6 @@ "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz", "integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ=" }, - "keymirror": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/keymirror/-/keymirror-0.1.1.tgz", - "integrity": "sha1-kYiJ6hP40KQufFVyUO7nE63JXDU=" - }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -12846,7 +13165,8 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true }, "kleur": { "version": "3.0.2", @@ -13041,17 +13361,20 @@ "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true }, "lodash.escape": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=" + "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=", + "dev": true }, "lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=" + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true }, "lodash.get": { "version": "4.4.2", @@ -13397,20 +13720,26 @@ "dev": true }, "mem": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.1.0.tgz", - "integrity": "sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, "requires": { "map-age-cleaner": "^0.1.1", - "mimic-fn": "^1.0.0", + "mimic-fn": "^2.0.0", "p-is-promise": "^2.0.0" }, "dependencies": { + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, "p-is-promise": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", - "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", "dev": true } } @@ -13421,12 +13750,6 @@ "integrity": "sha1-8rslNovBIeORwlIN6Slpyu4KApA=", "dev": true }, - "merge": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", - "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", - "dev": true - }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -13595,6 +13918,32 @@ "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, + "minipass": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", + "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": { + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + } + } + }, + "minizlib": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", + "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, "mississippi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", @@ -13722,9 +14071,9 @@ "dev": true }, "nan": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.0.tgz", - "integrity": "sha512-zT5nC0JhbljmyEf+Z456nvm7iO7XgRV2hYxoBtPpnyp+0Q4aCoP6uWNn76v/I6k2kCYNLWqWbwBWQcjsNI/bjw==", + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", "dev": true, "optional": true }, @@ -14041,9 +14390,9 @@ "dev": true }, "nwsapi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.0.tgz", - "integrity": "sha512-ZG3bLAvdHmhIjaQ/Db1qvBxsGvFMLIRpQszyqbg31VJ53UP++uZX1/gf3Ut96pdwN9AuDwlMqIYLm0UPCdUeHg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.3.tgz", + "integrity": "sha512-RowAaJGEgYXEZfQ7tvvdtAQUKPyTR6T6wNu0fwlNsGQYr/h3yQc6oI8WnVZh3Y/Sylwc+dtAlvPqfFZjhTyk3A==", "dev": true }, "oauth-sign": { @@ -14807,25 +15156,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" - } - }, + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -14835,9 +15195,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -14846,9 +15206,9 @@ } }, "postcss-colormin": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.2.tgz", - "integrity": "sha512-1QJc2coIehnVFsz0otges8kQLsryi4lo19WD+U5xCWvXd0uw/Z+KKYnbiNDCnO9GP+PvErPHCG0jNvWTngk9Rw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", "dev": true, "requires": { "browserslist": "^4.0.0", @@ -14867,37 +15227,37 @@ "color-convert": "^1.9.0" } }, - "browserslist": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.6.tgz", - "integrity": "sha512-kMGKs4BTzRWviZ8yru18xBpx+CyHG9eqgRbj9XbE3IMgtczf4aiA0Y1YCpVdvUieKGZ03kolSPXqTcscBCb9qw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000921", - "electron-to-chromium": "^1.3.92", - "node-releases": "^1.1.1" - } - }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -14907,9 +15267,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -14937,25 +15297,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -14965,9 +15336,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -14976,9 +15347,9 @@ } }, "postcss-discard-comments": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.1.tgz", - "integrity": "sha512-Ay+rZu1Sz6g8IdzRjUgG2NafSNpp2MSMOQUb+9kkzzzP+kh07fP0yNbhtFejURnyVXSX3FYy2nVNW1QTnNjgBQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", "dev": true, "requires": { "postcss": "^7.0.0" @@ -14994,25 +15365,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -15022,9 +15404,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15051,25 +15433,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -15079,9 +15472,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15108,25 +15501,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -15136,9 +15540,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15165,25 +15569,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -15193,9 +15608,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15204,9 +15619,9 @@ } }, "postcss-merge-longhand": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.9.tgz", - "integrity": "sha512-UVMXrXF5K/kIwUbK/crPFCytpWbNX2Q3dZSc8+nQUgfOHrCT4+MHncpdxVphUlQeZxlLXUJbDyXc5NBhTnS2tA==", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", "dev": true, "requires": { "css-color-names": "0.0.4", @@ -15225,25 +15640,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -15253,9 +15679,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15264,9 +15690,9 @@ } }, "postcss-merge-rules": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.2.tgz", - "integrity": "sha512-UiuXwCCJtQy9tAIxsnurfF0mrNHKc4NnNx6NxqmzNNjXpQwLSukUxELHTRF0Rg1pAmcoKLih8PwvZbiordchag==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", "dev": true, "requires": { "browserslist": "^4.0.0", @@ -15286,37 +15712,37 @@ "color-convert": "^1.9.0" } }, - "browserslist": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.6.tgz", - "integrity": "sha512-kMGKs4BTzRWviZ8yru18xBpx+CyHG9eqgRbj9XbE3IMgtczf4aiA0Y1YCpVdvUieKGZ03kolSPXqTcscBCb9qw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000921", - "electron-to-chromium": "^1.3.92", - "node-releases": "^1.1.1" - } - }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "postcss-selector-parser": { @@ -15337,9 +15763,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15367,25 +15793,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -15395,9 +15832,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15406,9 +15843,9 @@ } }, "postcss-minify-gradients": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.1.tgz", - "integrity": "sha512-pySEW3E6Ly5mHm18rekbWiAjVi/Wj8KKt2vwSfVFAWdW6wOIekgqxKxLU7vJfb107o3FDNPkaYFCxGAJBFyogA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", "dev": true, "requires": { "cssnano-util-get-arguments": "^4.0.0", @@ -15427,25 +15864,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -15455,9 +15903,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15466,9 +15914,9 @@ } }, "postcss-minify-params": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.1.tgz", - "integrity": "sha512-h4W0FEMEzBLxpxIVelRtMheskOKKp52ND6rJv+nBS33G1twu2tCyurYj/YtgU76+UDCvWeNs0hs8HFAWE2OUFg==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", "dev": true, "requires": { "alphanum-sort": "^1.0.0", @@ -15488,37 +15936,37 @@ "color-convert": "^1.9.0" } }, - "browserslist": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.6.tgz", - "integrity": "sha512-kMGKs4BTzRWviZ8yru18xBpx+CyHG9eqgRbj9XbE3IMgtczf4aiA0Y1YCpVdvUieKGZ03kolSPXqTcscBCb9qw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000921", - "electron-to-chromium": "^1.3.92", - "node-releases": "^1.1.1" - } - }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -15528,9 +15976,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15539,9 +15987,9 @@ } }, "postcss-minify-selectors": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.1.tgz", - "integrity": "sha512-8+plQkomve3G+CodLCgbhAKrb5lekAnLYuL1d7Nz+/7RANpBEVdgBkPNwljfSKvZ9xkkZTZITd04KP+zeJTJqg==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", "dev": true, "requires": { "alphanum-sort": "^1.0.0", @@ -15560,25 +16008,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "postcss-selector-parser": { @@ -15599,9 +16058,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15678,25 +16137,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -15706,9 +16176,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15717,9 +16187,9 @@ } }, "postcss-normalize-display-values": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.1.tgz", - "integrity": "sha512-R5mC4vaDdvsrku96yXP7zak+O3Mm9Y8IslUobk7IMP+u/g+lXvcN4jngmHY5zeJnrQvE13dfAg5ViU05ZFDwdg==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", "dev": true, "requires": { "cssnano-util-get-match": "^4.0.0", @@ -15737,25 +16207,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -15765,9 +16246,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15776,9 +16257,9 @@ } }, "postcss-normalize-positions": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.1.tgz", - "integrity": "sha512-GNoOaLRBM0gvH+ZRb2vKCIujzz4aclli64MBwDuYGU2EY53LwiP7MxOZGE46UGtotrSnmarPPZ69l2S/uxdaWA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", "dev": true, "requires": { "cssnano-util-get-arguments": "^4.0.0", @@ -15797,25 +16278,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -15825,9 +16317,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15836,9 +16328,9 @@ } }, "postcss-normalize-repeat-style": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.1.tgz", - "integrity": "sha512-fFHPGIjBUyUiswY2rd9rsFcC0t3oRta4wxE1h3lpwfQZwFeFjXFSiDtdJ7APCmHQOnUZnqYBADNRPKPwFAONgA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", "dev": true, "requires": { "cssnano-util-get-arguments": "^4.0.0", @@ -15857,25 +16349,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -15885,9 +16388,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15896,9 +16399,9 @@ } }, "postcss-normalize-string": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.1.tgz", - "integrity": "sha512-IJoexFTkAvAq5UZVxWXAGE0yLoNN/012v7TQh5nDo6imZJl2Fwgbhy3J2qnIoaDBrtUP0H7JrXlX1jjn2YcvCQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", "dev": true, "requires": { "has": "^1.0.0", @@ -15916,25 +16419,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -15944,9 +16458,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -15955,9 +16469,9 @@ } }, "postcss-normalize-timing-functions": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.1.tgz", - "integrity": "sha512-1nOtk7ze36+63ONWD8RCaRDYsnzorrj+Q6fxkQV+mlY5+471Qx9kspqv0O/qQNMeApg8KNrRf496zHwJ3tBZ7w==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", "dev": true, "requires": { "cssnano-util-get-match": "^4.0.0", @@ -15975,25 +16489,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -16003,9 +16528,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -16033,37 +16558,37 @@ "color-convert": "^1.9.0" } }, - "browserslist": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.6.tgz", - "integrity": "sha512-kMGKs4BTzRWviZ8yru18xBpx+CyHG9eqgRbj9XbE3IMgtczf4aiA0Y1YCpVdvUieKGZ03kolSPXqTcscBCb9qw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000921", - "electron-to-chromium": "^1.3.92", - "node-releases": "^1.1.1" - } - }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -16073,9 +16598,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -16105,25 +16630,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -16133,9 +16669,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -16144,9 +16680,9 @@ } }, "postcss-normalize-whitespace": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.1.tgz", - "integrity": "sha512-U8MBODMB2L+nStzOk6VvWWjZgi5kQNShCyjRhMT3s+W9Jw93yIjOnrEkKYD3Ul7ChWbEcjDWmXq0qOL9MIAnAw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", "dev": true, "requires": { "postcss": "^7.0.0", @@ -16163,25 +16699,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -16191,9 +16738,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -16202,9 +16749,9 @@ } }, "postcss-ordered-values": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.1.tgz", - "integrity": "sha512-PeJiLgJWPzkVF8JuKSBcylaU+hDJ/TX3zqAMIjlghgn1JBi6QwQaDZoDIlqWRcCAI8SxKrt3FCPSRmOgKRB97Q==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", "dev": true, "requires": { "cssnano-util-get-arguments": "^4.0.0", @@ -16222,25 +16769,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -16250,9 +16808,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -16261,9 +16819,9 @@ } }, "postcss-reduce-initial": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.2.tgz", - "integrity": "sha512-epUiC39NonKUKG+P3eAOKKZtm5OtAtQJL7Ye0CBN1f+UQTHzqotudp+hki7zxXm7tT0ZAKDMBj1uihpPjP25ug==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", "dev": true, "requires": { "browserslist": "^4.0.0", @@ -16281,37 +16839,37 @@ "color-convert": "^1.9.0" } }, - "browserslist": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.6.tgz", - "integrity": "sha512-kMGKs4BTzRWviZ8yru18xBpx+CyHG9eqgRbj9XbE3IMgtczf4aiA0Y1YCpVdvUieKGZ03kolSPXqTcscBCb9qw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000921", - "electron-to-chromium": "^1.3.92", - "node-releases": "^1.1.1" - } - }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -16321,9 +16879,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -16332,9 +16890,9 @@ } }, "postcss-reduce-transforms": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.1.tgz", - "integrity": "sha512-sZVr3QlGs0pjh6JAIe6DzWvBaqYw05V1t3d9Tp+VnFRT5j+rsqoWsysh/iSD7YNsULjq9IAylCznIwVd5oU/zA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", "dev": true, "requires": { "cssnano-util-get-match": "^4.0.0", @@ -16353,25 +16911,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -16381,9 +16950,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -16392,9 +16961,9 @@ } }, "postcss-selector-parser": { - "version": "5.0.0-rc.4", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0-rc.4.tgz", - "integrity": "sha512-0XvfYuShrKlTk1ooUrVzMCFQRcypsdEIsGqh5IxC5rdtBi4/M/tDAJeSONwC2MTqEFsmPZYAV7Dd4X8rgAfV0A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", "dev": true, "requires": { "cssesc": "^2.0.0", @@ -16411,9 +16980,9 @@ } }, "postcss-svgo": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.1.tgz", - "integrity": "sha512-YD5uIk5NDRySy0hcI+ZJHwqemv2WiqqzDgtvgMzO8EGSkK5aONyX8HMVFRFJSdO8wUWTuisUFn/d7yRRbBr5Qw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", + "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", "dev": true, "requires": { "is-svg": "^3.0.0", @@ -16432,25 +17001,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -16460,9 +17040,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -16491,25 +17071,36 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "source-map": { @@ -16519,9 +17110,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -16556,19 +17147,21 @@ "dev": true }, "pretty-format": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.0.0.tgz", - "integrity": "sha512-LszZaKG665djUcqg5ZQq+XzezHLKrxsA86ZABTozp+oNhkdqa+tG2dX4qa6ERl5c/sRDrAa3lHmwnvKoP+OG/g==", + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.7.0.tgz", + "integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==", "dev": true, "requires": { + "@jest/types": "^24.7.0", "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0" + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" }, "dependencies": { "ansi-regex": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", - "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "ansi-styles": { @@ -16579,6 +17172,12 @@ "requires": { "color-convert": "^1.9.0" } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "dev": true } } }, @@ -16634,16 +17233,6 @@ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, - "prompts": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.0.3.tgz", - "integrity": "sha512-H8oWEoRZpybm6NV4to9/1limhttEo13xK62pNvn2JzY0MA03p7s0OjtmhXyon3uJmxiJJVSuUwEJFFssI3eBiQ==", - "dev": true, - "requires": { - "kleur": "^3.0.2", - "sisteransi": "^1.0.0" - } - }, "prop-types": { "version": "15.6.2", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", @@ -17624,9 +18213,9 @@ } }, "p-limit": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", - "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -17642,9 +18231,9 @@ } }, "p-try": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", - "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true } } @@ -18364,7 +18953,7 @@ }, "rgba-regex": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", "dev": true }, @@ -18397,9 +18986,9 @@ } }, "rsvp": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", - "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.4.tgz", + "integrity": "sha512-6FomvYPfs+Jy9TfXmBpBuMWNH94SgCsZmJKcanySzgNNP6LjWxBvyLTa9KaMfDDM5oxRfrKDB0r/qeRsLwnBfA==", "dev": true }, "run-async": { @@ -18464,6 +19053,49 @@ "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", "dev": true }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "dev": true, + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + }, + "dependencies": { + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + } + } + }, "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", @@ -18953,9 +19585,9 @@ } }, "source-map-support": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", - "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -19169,7 +19801,7 @@ }, "sprintf-js": { "version": "1.0.3", - "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, @@ -19498,9 +20130,9 @@ } }, "stylehacks": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.1.tgz", - "integrity": "sha512-TK5zEPeD9NyC1uPIdjikzsgWxdQQN/ry1X3d1iOz1UkYDCmcr928gWD1KHgyC27F50UnE0xCTrBOO1l6KR8M4w==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", "dev": true, "requires": { "browserslist": "^4.0.0", @@ -19517,37 +20149,37 @@ "color-convert": "^1.9.0" } }, - "browserslist": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.6.tgz", - "integrity": "sha512-kMGKs4BTzRWviZ8yru18xBpx+CyHG9eqgRbj9XbE3IMgtczf4aiA0Y1YCpVdvUieKGZ03kolSPXqTcscBCb9qw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000921", - "electron-to-chromium": "^1.3.92", - "node-releases": "^1.1.1" - } - }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "postcss": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz", - "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" } }, "postcss-selector-parser": { @@ -19568,9 +20200,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -19604,32 +20236,46 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, "svgo": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.1.1.tgz", - "integrity": "sha512-GBkJbnTuFpM4jFbiERHDWhZc/S/kpHToqmZag3aEBjPYK44JAN2QBjvrGIxLOoCyMZjuFQIfTO2eJd8uwLY/9g==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.2.1.tgz", + "integrity": "sha512-Y1+LyT4/y1ms4/0yxPMSlvx6dIbgklE9w8CIOnfeoFGB74MEkq8inSfEr6NhocTaFbyYp0a1dvNgRKGRmEBlzA==", "dev": true, "requires": { - "coa": "~2.0.1", - "colors": "~1.1.2", + "chalk": "^2.4.1", + "coa": "^2.0.2", "css-select": "^2.0.0", - "css-select-base-adapter": "~0.1.0", + "css-select-base-adapter": "^0.1.1", "css-tree": "1.0.0-alpha.28", "css-url-regex": "^1.1.0", - "csso": "^3.5.0", - "js-yaml": "^3.12.0", + "csso": "^3.5.1", + "js-yaml": "^3.13.0", "mkdirp": "~0.5.1", - "object.values": "^1.0.4", + "object.values": "^1.1.0", "sax": "~1.2.4", - "stable": "~0.1.6", + "stable": "^0.1.8", "unquote": "~1.1.1", "util.promisify": "~1.0.0" }, "dependencies": { - "colors": { - "version": "1.1.2", - "resolved": "http://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } }, "css-select": { "version": "2.0.2", @@ -19652,6 +20298,27 @@ "dom-serializer": "0", "domelementtype": "1" } + }, + "object.values": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -19787,6 +20454,31 @@ "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", "dev": true }, + "tar": { + "version": "4.4.8", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", + "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true, + "optional": true + } + } + }, "terminal-char-width": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/terminal-char-width/-/terminal-char-width-1.0.8.tgz", @@ -20780,20 +21472,20 @@ } }, "uglify-js": { - "version": "3.4.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", - "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.4.tgz", + "integrity": "sha512-GpKo28q/7Bm5BcX9vOu4S46FwisbPbAmkkqPnGIpKvKTM96I85N6XHQV+k4I6FA2wxgLhcsSyHoNhzucwCflvA==", "dev": true, "optional": true, "requires": { - "commander": "~2.17.1", + "commander": "~2.20.0", "source-map": "~0.6.1" }, "dependencies": { "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", "dev": true, "optional": true }, @@ -21308,16 +22000,6 @@ "loose-envify": "^1.0.0" } }, - "watch": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz", - "integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=", - "dev": true, - "requires": { - "exec-sh": "^0.2.0", - "minimist": "^1.2.0" - } - }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", @@ -23075,9 +23757,9 @@ } }, "p-limit": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", - "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -23093,9 +23775,9 @@ } }, "p-try": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", - "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "string-width": { @@ -23130,9 +23812,9 @@ }, "dependencies": { "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true } } diff --git a/superset/assets/package.json b/superset/assets/package.json index 6985b7cb7611f..ecbf07af6d2ce 100644 --- a/superset/assets/package.json +++ b/superset/assets/package.json @@ -17,7 +17,6 @@ "build": "NODE_ENV=production webpack --mode=production --colors --progress", "lint": "eslint --ignore-path=.eslintignore --ext .js,.jsx . && tslint -c tslint.json ./{src,spec}/**/*.ts{,x}", "lint-fix": "eslint --fix --ignore-path=.eslintignore --ext .js,.jsx . && tslint -c tslint.json --fix ./{src,spec}/**/*.ts{,x}", - "sync-backend": "babel-node --preset=@babel/preset-env src/syncBackend.js", "cypress": "cypress", "cypress-debug": "cypress open --config watchForFileChanges=true", "install-cypress": "npm install cypress@3.1.5" @@ -48,8 +47,8 @@ "homepage": "https://superset.apache.org/", "dependencies": { "@data-ui/sparkline": "^0.0.54", - "@superset-ui/chart": "^0.11.1", - "@superset-ui/color": "^0.11.0", + "@superset-ui/chart": "^0.11.3", + "@superset-ui/color": "^0.11.3", "@superset-ui/connection": "^0.11.0", "@superset-ui/core": "^0.11.0", "@superset-ui/dimension": "^0.11.0", @@ -77,8 +76,8 @@ "@superset-ui/legacy-plugin-chart-world-map": "^0.10.11", "@superset-ui/legacy-preset-chart-big-number": "^0.10.11", "@superset-ui/legacy-preset-chart-nvd3": "^0.10.11", - "@superset-ui/number-format": "^0.11.0", - "@superset-ui/time-format": "^0.11.2", + "@superset-ui/number-format": "^0.11.3", + "@superset-ui/time-format": "^0.11.3", "@superset-ui/translation": "^0.11.0", "@vx/responsive": "0.0.172", "abortcontroller-polyfill": "^1.1.9", diff --git a/superset/assets/spec/javascripts/components/AnchorLink_spec.jsx b/superset/assets/spec/javascripts/components/AnchorLink_spec.jsx new file mode 100644 index 0000000000000..42811094592df --- /dev/null +++ b/superset/assets/spec/javascripts/components/AnchorLink_spec.jsx @@ -0,0 +1,63 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; + +import AnchorLink from '../../../src/components/AnchorLink'; +import URLShortLinkButton from '../../../src/components/URLShortLinkButton'; + +describe('AnchorLink', () => { + const props = { + anchorLinkId: 'CHART-123', + }; + + it('should scroll the AnchorLink into view upon mount', () => { + const callback = sinon.spy(); + const clock = sinon.useFakeTimers(); + const stub = sinon.stub(document, 'getElementById').returns({ + scrollIntoView: callback, + }); + + const wrapper = shallow(); + wrapper.instance().getLocationHash = () => (props.anchorLinkId); + wrapper.update(); + + wrapper.instance().componentDidMount(); + clock.tick(2000); + expect(callback.callCount).toEqual(1); + stub.restore(); + }); + + it('should render anchor link with id', () => { + const wrapper = shallow(); + expect(wrapper.find(`#${props.anchorLinkId}`)).toHaveLength(1); + expect(wrapper.find(URLShortLinkButton)).toHaveLength(0); + }); + + it('should render URLShortLinkButton', () => { + const wrapper = shallow(); + expect(wrapper.find(URLShortLinkButton)).toHaveLength(1); + expect(wrapper.find(URLShortLinkButton).prop('placement')).toBe('right'); + + const targetUrl = wrapper.find(URLShortLinkButton).prop('url'); + const hash = targetUrl.slice(targetUrl.indexOf('#') + 1); + expect(hash).toBe(props.anchorLinkId); + }); +}); diff --git a/superset/assets/spec/javascripts/dashboard/actions/dashboardState_spec.js b/superset/assets/spec/javascripts/dashboard/actions/dashboardState_spec.js new file mode 100644 index 0000000000000..8ba499e32107c --- /dev/null +++ b/superset/assets/spec/javascripts/dashboard/actions/dashboardState_spec.js @@ -0,0 +1,100 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import sinon from 'sinon'; +import { SupersetClient } from '@superset-ui/connection'; + +import { saveDashboardRequest } from '../../../../src/dashboard/actions/dashboardState'; +import { UPDATE_COMPONENTS_PARENTS_LIST } from '../../../../src/dashboard/actions/dashboardLayout'; +import mockDashboardData from '../fixtures/mockDashboardData'; +import { DASHBOARD_GRID_ID } from '../../../../src/dashboard/util/constants'; + +describe('dashboardState actions', () => { + const mockState = { + dashboardState: { + hasUnsavedChanges: true, + }, + dashboardInfo: {}, + dashboardLayout: { + past: [], + present: mockDashboardData.positions, + future: {}, + }, + }; + const newDashboardData = mockDashboardData; + + let postStub; + beforeEach(() => { + postStub = sinon + .stub(SupersetClient, 'post') + .resolves('the value you want to return'); + }); + afterEach(() => { + postStub.restore(); + }); + + function setup(stateOverrides) { + const state = { ...mockState, ...stateOverrides }; + const getState = sinon.spy(() => state); + const dispatch = sinon.stub(); + return { getState, dispatch, state }; + } + + describe('saveDashboardRequest', () => { + it('should dispatch UPDATE_COMPONENTS_PARENTS_LIST action', () => { + const { getState, dispatch } = setup({ + dashboardState: { hasUnsavedChanges: false }, + }); + const thunk = saveDashboardRequest(newDashboardData, 1, 'save_dash'); + thunk(dispatch, getState); + expect(dispatch.callCount).toBe(1); + expect(dispatch.getCall(0).args[0].type).toBe( + UPDATE_COMPONENTS_PARENTS_LIST, + ); + }); + + it('should post dashboard data with updated redux state', () => { + const { getState, dispatch } = setup({ + dashboardState: { hasUnsavedChanges: false }, + }); + + // start with mockDashboardData, it didn't have parents attr + expect( + newDashboardData.positions[DASHBOARD_GRID_ID].parents, + ).not.toBeDefined(); + + // mock redux work: dispatch an event, cause modify redux state + const mockParentsList = ['ROOT_ID']; + dispatch.callsFake(() => { + mockState.dashboardLayout.present[ + DASHBOARD_GRID_ID + ].parents = mockParentsList; + }); + + // call saveDashboardRequest, it should post dashboard data with updated + // layout object (with parents attribute) + const thunk = saveDashboardRequest(newDashboardData, 1, 'save_dash'); + thunk(dispatch, getState); + expect(postStub.callCount).toBe(1); + const postPayload = postStub.getCall(0).args[0].postPayload; + expect(postPayload.data.positions[DASHBOARD_GRID_ID].parents).toBe( + mockParentsList, + ); + }); + }); +}); diff --git a/superset/assets/spec/javascripts/dashboard/components/gridComponents/Header_spec.jsx b/superset/assets/spec/javascripts/dashboard/components/gridComponents/Header_spec.jsx index b206184529ac0..30121f28a791c 100644 --- a/superset/assets/spec/javascripts/dashboard/components/gridComponents/Header_spec.jsx +++ b/superset/assets/spec/javascripts/dashboard/components/gridComponents/Header_spec.jsx @@ -17,6 +17,7 @@ * under the License. */ import React from 'react'; +import { Provider } from 'react-redux'; import { mount } from 'enzyme'; import sinon from 'sinon'; @@ -33,6 +34,7 @@ import { } from '../../../../../src/dashboard/util/componentTypes'; import WithDragDropContext from '../../helpers/WithDragDropContext'; +import { mockStoreWithTabs } from '../../fixtures/mockStore'; describe('Header', () => { const props = { @@ -43,6 +45,7 @@ describe('Header', () => { parentComponent: newComponentFactory(DASHBOARD_GRID_TYPE), index: 0, editMode: false, + filters: {}, handleComponentDrop() {}, deleteComponent() {}, updateComponents() {}, @@ -52,9 +55,11 @@ describe('Header', () => { // We have to wrap provide DragDropContext for the underlying DragDroppable // otherwise we cannot assert on DragDroppable children const wrapper = mount( - -
- , + + +
+ + , ); return wrapper; } diff --git a/superset/assets/spec/javascripts/dashboard/components/gridComponents/Tabs_spec.jsx b/superset/assets/spec/javascripts/dashboard/components/gridComponents/Tabs_spec.jsx index 59b067c67217e..72d3a03600a88 100644 --- a/superset/assets/spec/javascripts/dashboard/components/gridComponents/Tabs_spec.jsx +++ b/superset/assets/spec/javascripts/dashboard/components/gridComponents/Tabs_spec.jsx @@ -18,7 +18,7 @@ */ import { Provider } from 'react-redux'; import React from 'react'; -import { mount } from 'enzyme'; +import { mount, shallow } from 'enzyme'; import sinon from 'sinon'; import { Tabs as BootstrapTabs, Tab as BootstrapTab } from 'react-bootstrap'; @@ -154,4 +154,20 @@ describe('Tabs', () => { expect(deleteComponent.callCount).toBe(1); }); + + it('should direct display direct-link tab', () => { + let wrapper = shallow(); + // default show first tab child + expect(wrapper.state('tabIndex')).toBe(0); + + // display child in directPathToChild list + const directPathToChild = dashboardLayoutWithTabs.present.ROW_ID2.parents.slice(); + const directLinkProps = { + ...props, + directPathToChild, + }; + + wrapper = shallow(); + expect(wrapper.state('tabIndex')).toBe(1); + }); }); diff --git a/superset/assets/spec/javascripts/dashboard/fixtures/mockDashboardData.js b/superset/assets/spec/javascripts/dashboard/fixtures/mockDashboardData.js new file mode 100644 index 0000000000000..8fcc4d57c8c4c --- /dev/null +++ b/superset/assets/spec/javascripts/dashboard/fixtures/mockDashboardData.js @@ -0,0 +1,28 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { dashboardLayout } from './mockDashboardLayout'; + +// mock the object to be posted to save_dash or copy_dash API +export default { + css: '', + dashboard_title: 'Test 1', + default_filters: {}, + expanded_slices: {}, + positions: dashboardLayout.present, +}; diff --git a/superset/assets/spec/javascripts/dashboard/fixtures/mockDashboardLayout.js b/superset/assets/spec/javascripts/dashboard/fixtures/mockDashboardLayout.js index e4187b9265552..f2f965ca085bb 100644 --- a/superset/assets/spec/javascripts/dashboard/fixtures/mockDashboardLayout.js +++ b/superset/assets/spec/javascripts/dashboard/fixtures/mockDashboardLayout.js @@ -108,12 +108,14 @@ export const dashboardLayoutWithTabs = { id: 'TABS_ID', type: TABS_TYPE, children: ['TAB_ID', 'TAB_ID2'], + parents: ['ROOT_ID'], }, TAB_ID: { id: 'TAB_ID', type: TAB_TYPE, children: ['ROW_ID'], + parents: ['ROOT_ID', 'TABS_ID'], meta: { text: 'tab1', }, @@ -122,7 +124,8 @@ export const dashboardLayoutWithTabs = { TAB_ID2: { id: 'TAB_ID2', type: TAB_TYPE, - children: [], + children: ['ROW_ID2'], + parents: ['ROOT_ID', 'TABS_ID'], meta: { text: 'tab2', }, @@ -131,6 +134,7 @@ export const dashboardLayoutWithTabs = { CHART_ID: { ...newComponentFactory(CHART_TYPE), id: 'CHART_ID', + parents: ['ROOT_ID', 'TABS_ID', 'TAB_ID', 'ROW_ID'], meta: { chartId, width: 3, @@ -143,12 +147,33 @@ export const dashboardLayoutWithTabs = { ...newComponentFactory(ROW_TYPE), id: 'ROW_ID', children: ['CHART_ID'], + parents: ['ROOT_ID', 'TABS_ID', 'TAB_ID'], + }, + + CHART_ID2: { + ...newComponentFactory(CHART_TYPE), + id: 'CHART_ID2', + parents: ['ROOT_ID', 'TABS_ID', 'TAB_ID2', 'ROW_ID2'], + meta: { + chartId, + width: 3, + height: 10, + chartName: 'Mock chart name 2', + }, + }, + + ROW_ID2: { + ...newComponentFactory(ROW_TYPE), + id: 'ROW_ID2', + children: ['CHART_ID2'], + parents: ['ROOT_ID', 'TABS_ID', 'TAB_ID2'], }, [DASHBOARD_GRID_ID]: { type: DASHBOARD_GRID_TYPE, id: DASHBOARD_GRID_ID, children: [], + parents: ['ROOT_ID'], meta: {}, }, diff --git a/superset/assets/spec/javascripts/dashboard/util/findTabIndexByComponentId_spec.js b/superset/assets/spec/javascripts/dashboard/util/findTabIndexByComponentId_spec.js new file mode 100644 index 0000000000000..3e3d0f7b9d648 --- /dev/null +++ b/superset/assets/spec/javascripts/dashboard/util/findTabIndexByComponentId_spec.js @@ -0,0 +1,85 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * 'License'); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import findTabIndexByComponentId from '../../../../src/dashboard/util/findTabIndexByComponentId'; + +describe('findTabIndexByComponentId', () => { + const topLevelTabsComponent = { + children: ['TAB-0g-5l347I2', 'TAB-qrwN_9VB5'], + id: 'TABS-MNQQSW-kyd', + meta: {}, + parents: ['ROOT_ID'], + type: 'TABS', + }; + const rowLevelTabsComponent = { + children: [ + 'TAB-TwyUUGp2Bg', + 'TAB-Zl1BQAUvN', + 'TAB-P0DllxzTU', + 'TAB---e53RNei', + ], + id: 'TABS-Oduxop1L7I', + meta: {}, + parents: ['ROOT_ID', 'TABS-MNQQSW-kyd', 'TAB-qrwN_9VB5'], + type: 'TABS', + }; + const goodPathToChild = [ + 'ROOT_ID', + 'TABS-MNQQSW-kyd', + 'TAB-qrwN_9VB5', + 'TABS-Oduxop1L7I', + 'TAB-P0DllxzTU', + 'ROW-JXhrFnVP8', + 'CHART-dUIVg-ENq6', + ]; + const badPath = ['ROOT_ID', 'TABS-MNQQSW-kyd', 'TAB-ABC', 'TABS-Oduxop1L7I']; + + it('should return 0 if no directPathToChild', () => { + expect( + findTabIndexByComponentId({ + currentComponent: topLevelTabsComponent, + directPathToChild: [], + }), + ).toBe(0); + }); + + it('should return 0 if not found tab id', () => { + expect( + findTabIndexByComponentId({ + currentComponent: topLevelTabsComponent, + directPathToChild: badPath, + }), + ).toBe(0); + }); + + it('should return children index if matched an id in the path', () => { + expect( + findTabIndexByComponentId({ + currentComponent: topLevelTabsComponent, + directPathToChild: goodPathToChild, + }), + ).toBe(1); + + expect( + findTabIndexByComponentId({ + currentComponent: rowLevelTabsComponent, + directPathToChild: goodPathToChild, + }), + ).toBe(2); + }); +}); diff --git a/superset/assets/spec/javascripts/dashboard/util/updateComponentParentsList_spec.js b/superset/assets/spec/javascripts/dashboard/util/updateComponentParentsList_spec.js new file mode 100644 index 0000000000000..d435f0df5ac20 --- /dev/null +++ b/superset/assets/spec/javascripts/dashboard/util/updateComponentParentsList_spec.js @@ -0,0 +1,97 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * 'License'); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import updateComponentParentsList from '../../../../src/dashboard/util/updateComponentParentsList'; +import { DASHBOARD_ROOT_ID } from '../../../../src/dashboard/util/constants'; +import { + dashboardLayout, + dashboardLayoutWithTabs, +} from '../fixtures/mockDashboardLayout'; + +describe('updateComponentParentsList', () => { + const emptyLayout = { + DASHBOARD_VERSION_KEY: 'v2', + GRID_ID: { + children: [], + id: 'GRID_ID', + type: 'GRID', + }, + ROOT_ID: { + children: ['GRID_ID'], + id: 'ROOT_ID', + type: 'ROOT', + }, + }; + const gridLayout = { + ...dashboardLayout.present, + }; + const tabsLayout = { + ...dashboardLayoutWithTabs.present, + }; + + it('should handle empty layout', () => { + const nextState = { + ...emptyLayout, + }; + + updateComponentParentsList({ + currentComponent: nextState[DASHBOARD_ROOT_ID], + layout: nextState, + }); + + expect(nextState.GRID_ID.parents).toEqual(['ROOT_ID']); + }); + + it('should handle grid layout', () => { + const nextState = { + ...gridLayout, + }; + + updateComponentParentsList({ + currentComponent: nextState[DASHBOARD_ROOT_ID], + layout: nextState, + }); + + expect(nextState.GRID_ID.parents).toEqual(['ROOT_ID']); + expect(nextState.CHART_ID.parents).toEqual([ + 'ROOT_ID', + 'GRID_ID', + 'ROW_ID', + 'COLUMN_ID', + ]); + }); + + it('should handle root level tabs', () => { + const nextState = { + ...tabsLayout, + }; + + updateComponentParentsList({ + currentComponent: nextState[DASHBOARD_ROOT_ID], + layout: nextState, + }); + + expect(nextState.GRID_ID.parents).toEqual(['ROOT_ID']); + expect(nextState.CHART_ID2.parents).toEqual([ + 'ROOT_ID', + 'TABS_ID', + 'TAB_ID2', + 'ROW_ID2', + ]); + }); +}); diff --git a/superset/assets/spec/javascripts/explore/components/SaveModal_spec.jsx b/superset/assets/spec/javascripts/explore/components/SaveModal_spec.jsx index e7be94db967b9..d334688a4d018 100644 --- a/superset/assets/spec/javascripts/explore/components/SaveModal_spec.jsx +++ b/superset/assets/spec/javascripts/explore/components/SaveModal_spec.jsx @@ -19,6 +19,7 @@ import React from 'react'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; +import { bindActionCreators } from 'redux'; import { shallow, mount } from 'enzyme'; import { Modal, Button, Radio } from 'react-bootstrap'; @@ -52,7 +53,12 @@ describe('SaveModal', () => { const defaultProps = { onHide: () => ({}), - actions: saveModalActions, + actions: bindActionCreators(saveModalActions, (arg) => { + if (typeof arg === 'function') { + return arg(jest.fn); + } + return arg; + }), form_data: { datasource: '107__table' }, }; const mockEvent = { @@ -108,15 +114,15 @@ describe('SaveModal', () => { it('componentDidMount', () => { sinon.spy(SaveModal.prototype, 'componentDidMount'); - sinon.spy(saveModalActions, 'fetchDashboards'); + sinon.spy(defaultProps.actions, 'fetchDashboards'); mount(, { context: { store }, }); expect(SaveModal.prototype.componentDidMount.calledOnce).toBe(true); - expect(saveModalActions.fetchDashboards.calledOnce).toBe(true); + expect(defaultProps.actions.fetchDashboards.calledOnce).toBe(true); SaveModal.prototype.componentDidMount.restore(); - saveModalActions.fetchDashboards.restore(); + defaultProps.actions.fetchDashboards.restore(); }); it('onChange', () => { @@ -139,7 +145,7 @@ describe('SaveModal', () => { .callsFake(() => ({ url: 'mockURL', payload: defaultProps.form_data })); sinon - .stub(saveModalActions, 'saveSlice') + .stub(defaultProps.actions, 'saveSlice') .callsFake(() => Promise.resolve({ data: { dashboard: '/mock/', slice: { slice_url: '/mock/' } } }), ); @@ -147,13 +153,13 @@ describe('SaveModal', () => { afterEach(() => { exploreUtils.getExploreUrlAndPayload.restore(); - saveModalActions.saveSlice.restore(); + defaultProps.actions.saveSlice.restore(); }); it('should save slice', () => { const wrapper = getWrapper(); wrapper.instance().saveOrOverwrite(true); - const args = saveModalActions.saveSlice.getCall(0).args; + const args = defaultProps.actions.saveSlice.getCall(0).args; expect(args[0]).toEqual(defaultProps.form_data); }); @@ -167,7 +173,7 @@ describe('SaveModal', () => { wrapper.setState({ saveToDashboardId }); wrapper.instance().saveOrOverwrite(true); - const args = saveModalActions.saveSlice.getCall(0).args; + const args = defaultProps.actions.saveSlice.getCall(0).args; expect(args[1].save_to_dashboard_id).toBe(saveToDashboardId); }); @@ -181,7 +187,7 @@ describe('SaveModal', () => { wrapper.setState({ newDashboardName }); wrapper.instance().saveOrOverwrite(true); - const args = saveModalActions.saveSlice.getCall(0).args; + const args = defaultProps.actions.saveSlice.getCall(0).args; expect(args[1].new_dashboard_name).toBe(newDashboardName); }); }); @@ -251,13 +257,13 @@ describe('SaveModal', () => { }); it('removeAlert', () => { - sinon.spy(saveModalActions, 'removeSaveModalAlert'); + sinon.spy(defaultProps.actions, 'removeSaveModalAlert'); const wrapper = getWrapper(); wrapper.setProps({ alert: 'old alert' }); wrapper.instance().removeAlert(); - expect(saveModalActions.removeSaveModalAlert.callCount).toBe(1); + expect(defaultProps.actions.removeSaveModalAlert.callCount).toBe(1); expect(wrapper.state().alert).toBeNull(); - saveModalActions.removeSaveModalAlert.restore(); + defaultProps.actions.removeSaveModalAlert.restore(); }); }); diff --git a/superset/assets/spec/javascripts/sqllab/actions/sqlLab_spec.js b/superset/assets/spec/javascripts/sqllab/actions/sqlLab_spec.js index 004eb9e74fe23..2e514b7c19c17 100644 --- a/superset/assets/spec/javascripts/sqllab/actions/sqlLab_spec.js +++ b/superset/assets/spec/javascripts/sqllab/actions/sqlLab_spec.js @@ -85,7 +85,7 @@ describe('async actions', () => { }); }); - it('parses large number result without losing precision', () => + xit('parses large number result without losing precision', () => makeRequest().then(() => { expect(fetchMock.calls(fetchQueryEndpoint)).toHaveLength(1); expect(dispatch.callCount).toBe(2); @@ -138,7 +138,7 @@ describe('async actions', () => { }); }); - it('parses large number result without losing precision', () => + xit('parses large number result without losing precision', () => makeRequest().then(() => { expect(fetchMock.calls(runQueryEndpoint)).toHaveLength(1); expect(dispatch.callCount).toBe(2); diff --git a/superset/assets/src/SqlLab/components/AceEditorWrapper.jsx b/superset/assets/src/SqlLab/components/AceEditorWrapper.jsx index 4b01b51ac8faf..14a9775d902d1 100644 --- a/superset/assets/src/SqlLab/components/AceEditorWrapper.jsx +++ b/superset/assets/src/SqlLab/components/AceEditorWrapper.jsx @@ -29,7 +29,7 @@ const langTools = ace.acequire('ace/ext/language_tools'); const keywords = ( 'SELECT|INSERT|UPDATE|DELETE|FROM|WHERE|AND|OR|GROUP|BY|ORDER|LIMIT|OFFSET|HAVING|AS|CASE|' + - 'WHEN|ELSE|END|TYPE|LEFT|RIGHT|JOIN|ON|OUTER|DESC|ASC|UNION|CREATE|TABLE|PRIMARY|KEY|IF|' + + 'WHEN|THEN|ELSE|END|TYPE|LEFT|RIGHT|JOIN|ON|OUTER|DESC|ASC|UNION|CREATE|TABLE|PRIMARY|KEY|IF|' + 'FOREIGN|NOT|REFERENCES|DEFAULT|NULL|INNER|CROSS|NATURAL|DATABASE|DROP|GRANT|SUM|MAX|MIN|COUNT|' + 'AVG|DISTINCT' ); diff --git a/superset/assets/src/SqlLab/components/TableElement.jsx b/superset/assets/src/SqlLab/components/TableElement.jsx index 96027a926b07c..ce8847eb74d4f 100644 --- a/superset/assets/src/SqlLab/components/TableElement.jsx +++ b/superset/assets/src/SqlLab/components/TableElement.jsx @@ -190,7 +190,11 @@ class TableElement extends React.PureComponent {
{table.isMetadataLoading || table.isExtraMetadataLoading ? - + : this.renderControls() } @@ -239,7 +243,6 @@ class TableElement extends React.PureComponent {
diff --git a/superset/assets/src/chart/Chart.jsx b/superset/assets/src/chart/Chart.jsx index c0d391673fc7a..cfc6ce8a97053 100644 --- a/superset/assets/src/chart/Chart.jsx +++ b/superset/assets/src/chart/Chart.jsx @@ -20,6 +20,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { Alert } from 'react-bootstrap'; +import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags'; import { Logger, LOG_ACTIONS_RENDER_CHART_CONTAINER } from '../logger/LogUtils'; import Loading from '../components/Loading'; import RefreshChartOverlay from '../components/RefreshChartOverlay'; @@ -70,7 +71,7 @@ class Chart extends React.PureComponent { } componentDidMount() { if (this.props.triggerQuery) { - if (this.props.chartId > 0) { + if (this.props.chartId > 0 && isFeatureEnabled(FeatureFlag.CLIENT_CACHE)) { // Load saved chart with a GET request this.props.actions.getSavedChart( this.props.formData, diff --git a/superset/assets/src/chart/chartAction.js b/superset/assets/src/chart/chartAction.js index 3909dadd85967..dc9eb322d4cf1 100644 --- a/superset/assets/src/chart/chartAction.js +++ b/superset/assets/src/chart/chartAction.js @@ -21,6 +21,7 @@ /* eslint no-param-reassign: ["error", { "props": false }] */ import { t } from '@superset-ui/translation'; import { SupersetClient } from '@superset-ui/connection'; +import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags'; import { getExploreUrlAndPayload, getAnnotationJsonUrl } from '../explore/exploreUtils'; import { requiresQuery, ANNOTATION_SOURCE_TYPES } from '../modules/AnnotationTypes'; import { addDangerToast } from '../messageToasts/actions'; @@ -194,7 +195,9 @@ export function exploreJSON(formData, force = false, timeout = 60, key, method) }; } - const clientMethod = method === 'GET' ? SupersetClient.get : SupersetClient.post; + const clientMethod = method === 'GET' && isFeatureEnabled(FeatureFlag.CLIENT_CACHE) + ? SupersetClient.get + : SupersetClient.post; const queryPromise = clientMethod(querySettings) .then(({ json }) => { dispatch(logEvent(LOG_ACTIONS_LOAD_CHART, { diff --git a/superset/assets/src/components/AnchorLink.jsx b/superset/assets/src/components/AnchorLink.jsx new file mode 100644 index 0000000000000..b33ee605cd444 --- /dev/null +++ b/superset/assets/src/components/AnchorLink.jsx @@ -0,0 +1,99 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React from 'react'; +import PropTypes from 'prop-types'; +import { t } from '@superset-ui/translation'; + +import URLShortLinkButton from './URLShortLinkButton'; +import getDashboardUrl from '../dashboard/util/getDashboardUrl'; + +const propTypes = { + anchorLinkId: PropTypes.string.isRequired, + filters: PropTypes.object, + showShortLinkButton: PropTypes.bool, + placement: PropTypes.oneOf(['right', 'left', 'top', 'bottom']), +}; + +const defaultProps = { + showShortLinkButton: false, + placement: 'right', + filters: {}, +}; + + +class AnchorLink extends React.PureComponent { + constructor(props) { + super(props); + + this.handleClickAnchorLink = this.handleClickAnchorLink.bind(this); + } + + componentDidMount() { + const hash = this.getLocationHash(); + const { anchorLinkId } = this.props; + + if (hash && anchorLinkId === hash) { + const directLinkComponent = document.getElementById(anchorLinkId); + if (directLinkComponent) { + setTimeout(() => { + directLinkComponent.scrollIntoView({ + block: 'center', + behavior: 'smooth', + }); + }, 1000); + } + } + } + + getLocationHash() { + return (window.location.hash || '').substring(1); + } + + handleClickAnchorLink(ev) { + ev.preventDefault(); + history.pushState(null, null, `#${this.props.anchorLinkId}`); + } + + render() { + const { anchorLinkId, filters, showShortLinkButton, placement } = this.props; + return ( + + {showShortLinkButton && + } + + ); + } +} + +AnchorLink.propTypes = propTypes; +AnchorLink.defaultProps = defaultProps; + +export default AnchorLink; diff --git a/superset/assets/src/components/Hotkeys.jsx b/superset/assets/src/components/Hotkeys.jsx index 36e7d572d34ab..0d455244cd777 100644 --- a/superset/assets/src/components/Hotkeys.jsx +++ b/superset/assets/src/components/Hotkeys.jsx @@ -25,7 +25,7 @@ const propTypes = { hotkeys: PropTypes.arrayOf(PropTypes.shape({ key: PropTypes.string.isRequired, descr: PropTypes.string.isRequired, - func: PropTypes.func.isRequired, + func: PropTypes.func, })).isRequired, header: PropTypes.string, placement: PropTypes.string, @@ -38,7 +38,9 @@ const defaultProps = { export default class Hotkeys extends React.PureComponent { componentDidMount() { this.props.hotkeys.forEach((keyConfig) => { - Mousetrap.bind([keyConfig.key], keyConfig.func); + if (keyConfig.func) { + Mousetrap.bind([keyConfig.key], keyConfig.func); + } }); } renderPopover() { diff --git a/superset/assets/src/components/Loading.css b/superset/assets/src/components/Loading.css new file mode 100644 index 0000000000000..411896272701c --- /dev/null +++ b/superset/assets/src/components/Loading.css @@ -0,0 +1,21 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +img.loading.margin-zero { + margin: 0px; +} diff --git a/superset/assets/src/components/Loading.jsx b/superset/assets/src/components/Loading.jsx index a7d8f40b05074..5c132d9c1bccc 100644 --- a/superset/assets/src/components/Loading.jsx +++ b/superset/assets/src/components/Loading.jsx @@ -19,13 +19,17 @@ import React from 'react'; import PropTypes from 'prop-types'; +import './Loading.css'; + const propTypes = { size: PropTypes.number, position: PropTypes.oneOf(['floating', 'normal']), + className: PropTypes.string, }; const defaultProps = { size: 50, position: 'floating', + className: '', }; const FLOATING_STYLE = { @@ -37,7 +41,7 @@ const FLOATING_STYLE = { transform: 'translate(-50%, -50%)', }; -export default function Loading({ size, position }) { +export default function Loading({ size, position, className }) { const style = position === 'floating' ? FLOATING_STYLE : {}; const styleWithWidth = { ...style, @@ -45,7 +49,7 @@ export default function Loading({ size, position }) { }; return ( Loading... @@ -87,6 +88,7 @@ class URLShortLinkButton extends React.Component { URLShortLinkButton.defaultProps = { url: window.location.href.substring(window.location.origin.length), + placement: 'left', emailSubject: '', emailContent: '', }; diff --git a/superset/assets/src/components/URLShortLinkModal.jsx b/superset/assets/src/components/URLShortLinkModal.jsx index 2fc01c60eddeb..d6bf3f67224ec 100644 --- a/superset/assets/src/components/URLShortLinkModal.jsx +++ b/superset/assets/src/components/URLShortLinkModal.jsx @@ -30,6 +30,7 @@ const propTypes = { emailContent: PropTypes.string, addDangerToast: PropTypes.func.isRequired, isMenuItem: PropTypes.bool, + title: PropTypes.string, triggerNode: PropTypes.node.isRequired, }; @@ -65,7 +66,7 @@ class URLShortLinkModal extends React.Component { isMenuItem={this.props.isMenuItem} triggerNode={this.props.triggerNode} beforeOpen={this.getCopyUrl} - modalTitle={t('Share Dashboard')} + modalTitle={this.props.title || t('Share Dashboard')} modalBody={
- SupersetClient.post({ + return dispatch => { + dispatch({ type: UPDATE_COMPONENTS_PARENTS_LIST }); + + return SupersetClient.post({ endpoint: `/superset/${path}/${id}/`, postPayload: { data }, }) - .then(response => - Promise.all([ - dispatch(saveDashboardRequestSuccess()), - dispatch( - addSuccessToast(t('This dashboard was saved successfully.')), - ), - ]).then(() => Promise.resolve(response)), - ) + .then(response => { + dispatch(saveDashboardRequestSuccess()); + dispatch(addSuccessToast(t('This dashboard was saved successfully.'))); + return response; + }) .catch(response => getClientErrorObject(response).then(({ error }) => dispatch( @@ -163,6 +163,7 @@ export function saveDashboardRequest(data, id, saveType) { ), ), ); + }; } export function fetchCharts(chartList = [], force = false, interval = 0) { diff --git a/superset/assets/src/dashboard/actions/sliceEntities.js b/superset/assets/src/dashboard/actions/sliceEntities.js index e98d28bcc457d..efee23eec3509 100644 --- a/superset/assets/src/dashboard/actions/sliceEntities.js +++ b/superset/assets/src/dashboard/actions/sliceEntities.js @@ -77,6 +77,7 @@ export function fetchAllSlices(userId) { description_markdown: slice.description_markeddown, viz_type: slice.viz_type, modified: slice.modified, + changed_on_humanized: slice.changed_on_humanized, }; } }); diff --git a/superset/assets/src/dashboard/components/DashboardBuilder.jsx b/superset/assets/src/dashboard/components/DashboardBuilder.jsx index 7bd6f6f39b373..12c8ff3368cbd 100644 --- a/superset/assets/src/dashboard/components/DashboardBuilder.jsx +++ b/superset/assets/src/dashboard/components/DashboardBuilder.jsx @@ -36,6 +36,7 @@ import ToastPresenter from '../../messageToasts/containers/ToastPresenter'; import WithPopoverMenu from './menu/WithPopoverMenu'; import getDragDropManager from '../util/getDragDropManager'; +import findTabIndexByComponentId from '../util/findTabIndexByComponentId'; import { BUILDER_PANE_TYPE, @@ -57,9 +58,13 @@ const propTypes = { setColorSchemeAndUnsavedChanges: PropTypes.func.isRequired, colorScheme: PropTypes.string, handleComponentDrop: PropTypes.func.isRequired, + toggleBuilderPane: PropTypes.func.isRequired, + directPathToChild: PropTypes.arrayOf(PropTypes.string), }; const defaultProps = { + showBuilderPane: false, + directPathToChild: [], colorScheme: undefined, }; @@ -75,8 +80,19 @@ class DashboardBuilder extends React.Component { constructor(props) { super(props); + + const { dashboardLayout, directPathToChild } = props; + const dashboardRoot = dashboardLayout[DASHBOARD_ROOT_ID]; + const rootChildId = dashboardRoot.children[0]; + const topLevelTabs = + rootChildId !== DASHBOARD_GRID_ID && dashboardLayout[rootChildId]; + const tabIndex = findTabIndexByComponentId({ + currentComponent: topLevelTabs || dashboardLayout[DASHBOARD_ROOT_ID], + directPathToChild, + }); + this.state = { - tabIndex: 0, // top-level tabs + tabIndex, }; this.handleChangeTab = this.handleChangeTab.bind(this); this.handleDeleteTopLevelTabs = this.handleDeleteTopLevelTabs.bind(this); diff --git a/superset/assets/src/dashboard/components/HeaderActionsDropdown.jsx b/superset/assets/src/dashboard/components/HeaderActionsDropdown.jsx index 5aa468b742aa3..b96096517964c 100644 --- a/superset/assets/src/dashboard/components/HeaderActionsDropdown.jsx +++ b/superset/assets/src/dashboard/components/HeaderActionsDropdown.jsx @@ -191,7 +191,11 @@ class HeaderActionsDropdown extends React.PureComponent { )} )}
diff --git a/superset/assets/src/dashboard/components/SliceHeaderControls.jsx b/superset/assets/src/dashboard/components/SliceHeaderControls.jsx index 18a92071f9d1a..65565f07cb29d 100644 --- a/superset/assets/src/dashboard/components/SliceHeaderControls.jsx +++ b/superset/assets/src/dashboard/components/SliceHeaderControls.jsx @@ -21,9 +21,14 @@ import PropTypes from 'prop-types'; import moment from 'moment'; import { Dropdown, MenuItem } from 'react-bootstrap'; import { t } from '@superset-ui/translation'; +import URLShortLinkModal from '../../components/URLShortLinkModal'; +import getDashboardUrl from '../util/getDashboardUrl'; const propTypes = { slice: PropTypes.object.isRequired, + componentId: PropTypes.string.isRequired, + filters: PropTypes.object.isRequired, + addDangerToast: PropTypes.func.isRequired, isCached: PropTypes.bool, isExpanded: PropTypes.bool, cachedDttm: PropTypes.string, @@ -97,7 +102,15 @@ class SliceHeaderControls extends React.PureComponent { } render() { - const { slice, isCached, cachedDttm, updatedDttm } = this.props; + const { + slice, + isCached, + cachedDttm, + updatedDttm, + filters, + componentId, + addDangerToast, + } = this.props; const cachedWhen = moment.utc(cachedDttm).fromNow(); const updatedWhen = updatedDttm ? moment.utc(updatedDttm).fromNow() : ''; const refreshTooltip = isCached @@ -145,6 +158,18 @@ class SliceHeaderControls extends React.PureComponent { {t('Explore chart')} )} + + {t('Share chart')}} + /> ); diff --git a/superset/assets/src/dashboard/components/gridComponents/Chart.jsx b/superset/assets/src/dashboard/components/gridComponents/Chart.jsx index d8b01d011beab..ff1120835534e 100644 --- a/superset/assets/src/dashboard/components/gridComponents/Chart.jsx +++ b/superset/assets/src/dashboard/components/gridComponents/Chart.jsx @@ -33,6 +33,7 @@ import { const propTypes = { id: PropTypes.number.isRequired, + componentId: PropTypes.string.isRequired, width: PropTypes.number.isRequired, height: PropTypes.number.isRequired, updateSliceName: PropTypes.func.isRequired, @@ -55,6 +56,7 @@ const propTypes = { supersetCanExplore: PropTypes.bool.isRequired, supersetCanCSV: PropTypes.bool.isRequired, sliceCanEdit: PropTypes.bool.isRequired, + addDangerToast: PropTypes.func.isRequired, }; const defaultProps = { @@ -184,6 +186,7 @@ class Chart extends React.Component { render() { const { id, + componentId, chart, slice, datasource, @@ -198,6 +201,7 @@ class Chart extends React.Component { supersetCanExplore, supersetCanCSV, sliceCanEdit, + addDangerToast, } = this.props; const { width } = this.state; @@ -233,6 +237,9 @@ class Chart extends React.Component { supersetCanExplore={supersetCanExplore} supersetCanCSV={supersetCanCSV} sliceCanEdit={sliceCanEdit} + componentId={componentId} + filters={filters} + addDangerToast={addDangerToast} /> {/* diff --git a/superset/assets/src/dashboard/components/gridComponents/ChartHolder.jsx b/superset/assets/src/dashboard/components/gridComponents/ChartHolder.jsx index 56e2918b35833..836c0e726d5de 100644 --- a/superset/assets/src/dashboard/components/gridComponents/ChartHolder.jsx +++ b/superset/assets/src/dashboard/components/gridComponents/ChartHolder.jsx @@ -20,6 +20,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import Chart from '../../containers/Chart'; +import AnchorLink from '../../../components/AnchorLink'; import DeleteComponentButton from '../DeleteComponentButton'; import DragDroppable from '../dnd/DragDroppable'; import HoverMenu from '../menu/HoverMenu'; @@ -148,7 +149,9 @@ class ChartHolder extends React.Component { ref={dragSourceRef} className="dashboard-component dashboard-component-chart-holder" > + {!editMode && } + {!editMode && ( + + )}
diff --git a/superset/assets/src/dashboard/components/gridComponents/Tab.jsx b/superset/assets/src/dashboard/components/gridComponents/Tab.jsx index 764702d06b548..49a0f187fb5d7 100644 --- a/superset/assets/src/dashboard/components/gridComponents/Tab.jsx +++ b/superset/assets/src/dashboard/components/gridComponents/Tab.jsx @@ -22,6 +22,7 @@ import PropTypes from 'prop-types'; import DashboardComponent from '../../containers/DashboardComponent'; import DragDroppable from '../dnd/DragDroppable'; import EditableTitle from '../../../components/EditableTitle'; +import AnchorLink from '../../../components/AnchorLink'; import DeleteComponentModal from '../DeleteComponentModal'; import WithPopoverMenu from '../menu/WithPopoverMenu'; import { componentShape } from '../../util/propShapes'; @@ -41,6 +42,7 @@ const propTypes = { onDropOnTab: PropTypes.func, onDeleteTab: PropTypes.func, editMode: PropTypes.bool.isRequired, + filters: PropTypes.object.isRequired, // grid related availableColumnCount: PropTypes.number, @@ -195,7 +197,14 @@ export default class Tab extends React.PureComponent { renderTab() { const { isFocused } = this.state; - const { component, parentComponent, index, depth, editMode } = this.props; + const { + component, + parentComponent, + index, + depth, + editMode, + filters, + } = this.props; const deleteTabIcon = (
@@ -238,6 +247,14 @@ export default class Tab extends React.PureComponent { onSaveTitle={this.handleChangeText} showTooltip={false} /> + {!editMode && ( + = 5 ? 'left' : 'right'} + /> + )} {dropIndicatorProps &&
} diff --git a/superset/assets/src/dashboard/components/gridComponents/Tabs.jsx b/superset/assets/src/dashboard/components/gridComponents/Tabs.jsx index dc9d59939a0db..2b8934e9f668c 100644 --- a/superset/assets/src/dashboard/components/gridComponents/Tabs.jsx +++ b/superset/assets/src/dashboard/components/gridComponents/Tabs.jsx @@ -25,6 +25,7 @@ import DragHandle from '../dnd/DragHandle'; import DashboardComponent from '../../containers/DashboardComponent'; import DeleteComponentButton from '../DeleteComponentButton'; import HoverMenu from '../menu/HoverMenu'; +import findTabIndexByComponentId from '../../util/findTabIndexByComponentId'; import { componentShape } from '../../util/propShapes'; import { NEW_TAB_ID, DASHBOARD_ROOT_ID } from '../../util/constants'; import { RENDER_TAB, RENDER_TAB_CONTENT } from './Tab'; @@ -45,6 +46,7 @@ const propTypes = { editMode: PropTypes.bool.isRequired, renderHoverMenu: PropTypes.bool, logEvent: PropTypes.func.isRequired, + directPathToChild: PropTypes.arrayOf(PropTypes.string), // grid related availableColumnCount: PropTypes.number, @@ -67,6 +69,7 @@ const defaultProps = { renderHoverMenu: true, availableColumnCount: 0, columnWidth: 0, + directPathToChild: [], onChangeTab() {}, onResizeStart() {}, onResize() {}, @@ -76,8 +79,13 @@ const defaultProps = { class Tabs extends React.PureComponent { constructor(props) { super(props); + const tabIndex = findTabIndexByComponentId({ + currentComponent: props.component, + directPathToChild: props.directPathToChild, + }); + this.state = { - tabIndex: 0, + tabIndex, }; this.handleClickTab = this.handleClickTab.bind(this); this.handleDeleteComponent = this.handleDeleteComponent.bind(this); diff --git a/superset/assets/src/dashboard/containers/Chart.jsx b/superset/assets/src/dashboard/containers/Chart.jsx index 5b14c1bade1b0..d47c7c97ac5bf 100644 --- a/superset/assets/src/dashboard/containers/Chart.jsx +++ b/superset/assets/src/dashboard/containers/Chart.jsx @@ -23,10 +23,11 @@ import { changeFilter as addFilter, toggleExpandSlice, } from '../actions/dashboardState'; +import { updateComponents } from '../actions/dashboardLayout'; +import { addDangerToast } from '../../messageToasts/actions'; import { refreshChart } from '../../chart/chartAction'; import { logEvent } from '../../logger/actions'; import getFormDataWithExtraFilters from '../util/charts/getFormDataWithExtraFilters'; -import { updateComponents } from '../actions/dashboardLayout'; import Chart from '../components/gridComponents/Chart'; const EMPTY_FILTERS = {}; @@ -74,6 +75,7 @@ function mapDispatchToProps(dispatch) { return bindActionCreators( { updateComponents, + addDangerToast, toggleExpandSlice, addFilter, refreshChart, diff --git a/superset/assets/src/dashboard/containers/DashboardBuilder.jsx b/superset/assets/src/dashboard/containers/DashboardBuilder.jsx index 3c6514a2f736c..cb3ca3ee898a2 100644 --- a/superset/assets/src/dashboard/containers/DashboardBuilder.jsx +++ b/superset/assets/src/dashboard/containers/DashboardBuilder.jsx @@ -33,6 +33,8 @@ function mapStateToProps({ dashboardLayout: undoableLayout, dashboardState }) { return { dashboardLayout: undoableLayout.present, editMode: dashboardState.editMode, + showBuilderPane: dashboardState.showBuilderPane, + directPathToChild: dashboardState.directPathToChild, builderPaneType: dashboardState.builderPaneType, colorScheme: dashboardState.colorScheme, }; diff --git a/superset/assets/src/dashboard/containers/DashboardComponent.jsx b/superset/assets/src/dashboard/containers/DashboardComponent.jsx index 180fcd3c93709..a1a1c375e957c 100644 --- a/superset/assets/src/dashboard/containers/DashboardComponent.jsx +++ b/superset/assets/src/dashboard/containers/DashboardComponent.jsx @@ -43,6 +43,11 @@ const propTypes = { updateComponents: PropTypes.func.isRequired, handleComponentDrop: PropTypes.func.isRequired, logEvent: PropTypes.func.isRequired, + directPathToChild: PropTypes.arrayOf(PropTypes.string), +}; + +const defaultProps = { + directPathToChild: [], }; function mapStateToProps( @@ -56,6 +61,8 @@ function mapStateToProps( component, parentComponent: dashboardLayout[parentId], editMode: dashboardState.editMode, + filters: dashboardState.filters, + directPathToChild: dashboardState.directPathToChild, }; // rows and columns need more data about their child dimensions @@ -98,6 +105,7 @@ class DashboardComponent extends React.PureComponent { } DashboardComponent.propTypes = propTypes; +DashboardComponent.defaultProps = defaultProps; export default connect( mapStateToProps, diff --git a/superset/assets/src/dashboard/fixtures/emptyDashboardLayout.js b/superset/assets/src/dashboard/fixtures/emptyDashboardLayout.js index f5799b0171f14..d693aca878c17 100644 --- a/superset/assets/src/dashboard/fixtures/emptyDashboardLayout.js +++ b/superset/assets/src/dashboard/fixtures/emptyDashboardLayout.js @@ -39,6 +39,7 @@ export default { type: DASHBOARD_GRID_TYPE, id: DASHBOARD_GRID_ID, children: [], + parents: [DASHBOARD_ROOT_ID], meta: {}, }, diff --git a/superset/assets/src/dashboard/reducers/dashboardLayout.js b/superset/assets/src/dashboard/reducers/dashboardLayout.js index c880a24c78659..23459e029f87d 100644 --- a/superset/assets/src/dashboard/reducers/dashboardLayout.js +++ b/superset/assets/src/dashboard/reducers/dashboardLayout.js @@ -24,6 +24,7 @@ import { import componentIsResizable from '../util/componentIsResizable'; import findParentId from '../util/findParentId'; import getComponentWidthFromDrop from '../util/getComponentWidthFromDrop'; +import updateComponentParentsList from '../util/updateComponentParentsList'; import newComponentFactory from '../util/newComponentFactory'; import newEntitiesFromDrop from '../util/newEntitiesFromDrop'; import reorderItem from '../util/dnd-reorder'; @@ -32,6 +33,7 @@ import { ROW_TYPE, TAB_TYPE, TABS_TYPE } from '../util/componentTypes'; import { UPDATE_COMPONENTS, + UPDATE_COMPONENTS_PARENTS_LIST, DELETE_COMPONENT, CREATE_COMPONENT, MOVE_COMPONENT, @@ -255,6 +257,21 @@ const actionHandlers = { return nextEntities; }, + + [UPDATE_COMPONENTS_PARENTS_LIST](state) { + const nextState = { + ...state, + }; + + updateComponentParentsList({ + currentComponent: nextState[DASHBOARD_ROOT_ID], + layout: nextState, + }); + + return { + ...nextState, + }; + }, }; export default function layoutReducer(state = {}, action) { diff --git a/superset/assets/src/dashboard/reducers/getInitialState.js b/superset/assets/src/dashboard/reducers/getInitialState.js index 69396de786fb2..fb5ff75239fab 100644 --- a/superset/assets/src/dashboard/reducers/getInitialState.js +++ b/superset/assets/src/dashboard/reducers/getInitialState.js @@ -72,7 +72,11 @@ export default function(bootstrapData) { // dashboard layout const { position_json: positionJson } = dashboard; - const layout = positionJson || getEmptyLayout(); + // new dash: positionJson could be {} or null + const layout = + positionJson && Object.keys(positionJson).length > 0 + ? positionJson + : getEmptyLayout(); // create a lookup to sync layout names with slice names const chartIdToLayoutId = {}; @@ -164,6 +168,14 @@ export default function(bootstrapData) { future: [], }; + // find direct link component and path from root + const directLinkComponentId = (window.location.hash || '#').substring(1); + let directPathToChild = []; + if (layout[directLinkComponentId]) { + directPathToChild = (layout[directLinkComponentId].parents || []).slice(); + directPathToChild.push(directLinkComponentId); + } + return { datasources, sliceEntities: { ...initSliceEntities, slices, isLoading: false }, @@ -194,6 +206,7 @@ export default function(bootstrapData) { sliceIds: Array.from(sliceIds), refresh: false, filters, + directPathToChild, expandedSlices: dashboard.metadata.expanded_slices || {}, refreshFrequency: dashboard.metadata.refresh_frequency || 0, css: dashboard.css || '', diff --git a/superset/assets/src/syncBackend.js b/superset/assets/src/dashboard/util/findTabIndexByComponentId.js similarity index 55% rename from superset/assets/src/syncBackend.js rename to superset/assets/src/dashboard/util/findTabIndexByComponentId.js index ae61bf3b370ab..eed141e44f585 100644 --- a/superset/assets/src/syncBackend.js +++ b/superset/assets/src/dashboard/util/findTabIndexByComponentId.js @@ -16,28 +16,26 @@ * specific language governing permissions and limitations * under the License. */ -/* eslint no-console: 0 */ -import fs from 'fs'; -import path from 'path'; -import { controls } from './explore/controls'; - -function exportFile(fileLocation, content) { - fs.writeFile(fileLocation, content, function (err) { - if (err) { - console.log(`File ${fileLocation} was not saved... :(`); - } else { - console.log(`File ${fileLocation} was saved!`); - } - }); -} +export default function findTabIndexByComponentId({ + currentComponent, + directPathToChild = [], +}) { + if ( + !currentComponent || + directPathToChild.length === 0 || + directPathToChild.indexOf(currentComponent.id) === -1 + ) { + return 0; + } -function main() { - const APP_DIR = path.resolve(__dirname, './'); - const dir = APP_DIR + '/../dist/'; - if (!fs.existsSync(dir)) { - fs.mkdirSync(dir); + const currentComponentIdx = directPathToChild.findIndex( + id => id === currentComponent.id, + ); + const nextParentId = directPathToChild[currentComponentIdx + 1]; + if (currentComponent.children.indexOf(nextParentId) >= 0) { + return currentComponent.children.findIndex( + childId => childId === nextParentId, + ); } - const blob = { controls }; - exportFile(APP_DIR + '/../backendSync.json', JSON.stringify(blob, null, 2)); + return 0; } -main(); diff --git a/superset/assets/src/dashboard/util/getDashboardUrl.js b/superset/assets/src/dashboard/util/getDashboardUrl.js index 9b8cada1d386f..243c8cbe65f81 100644 --- a/superset/assets/src/dashboard/util/getDashboardUrl.js +++ b/superset/assets/src/dashboard/util/getDashboardUrl.js @@ -18,7 +18,8 @@ */ /* eslint camelcase: 0 */ -export default function getDashboardUrl(pathname, filters = {}) { +export default function getDashboardUrl(pathname, filters = {}, hash = '') { const preselect_filters = encodeURIComponent(JSON.stringify(filters)); - return `${pathname}?preselect_filters=${preselect_filters}`; + const hashSection = hash ? `#${hash}` : ''; + return `${pathname}?preselect_filters=${preselect_filters}${hashSection}`; } diff --git a/superset/assets/src/dashboard/util/getEmptyLayout.js b/superset/assets/src/dashboard/util/getEmptyLayout.js index 28d3187c806c1..a58866cd350a0 100644 --- a/superset/assets/src/dashboard/util/getEmptyLayout.js +++ b/superset/assets/src/dashboard/util/getEmptyLayout.js @@ -36,6 +36,7 @@ export default function() { type: DASHBOARD_GRID_TYPE, id: DASHBOARD_GRID_ID, children: [], + parents: [DASHBOARD_ROOT_ID], }, }; } diff --git a/superset/assets/src/dashboard/util/updateComponentParentsList.js b/superset/assets/src/dashboard/util/updateComponentParentsList.js new file mode 100644 index 0000000000000..48f01e20a61d5 --- /dev/null +++ b/superset/assets/src/dashboard/util/updateComponentParentsList.js @@ -0,0 +1,35 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +export default function updateComponentParentsList({ + currentComponent, + layout = {}, +}) { + if (currentComponent && layout[currentComponent.id]) { + const parentsList = (currentComponent.parents || []).slice(); + parentsList.push(currentComponent.id); + + currentComponent.children.forEach(childId => { + layout[childId].parents = parentsList; // eslint-disable-line no-param-reassign + updateComponentParentsList({ + currentComponent: layout[childId], + layout, + }); + }); + } +} diff --git a/superset/assets/src/explore/components/ExploreChartHeader.jsx b/superset/assets/src/explore/components/ExploreChartHeader.jsx index 6a30a197ba85c..4acd88095dbcf 100644 --- a/superset/assets/src/explore/components/ExploreChartHeader.jsx +++ b/superset/assets/src/explore/components/ExploreChartHeader.jsx @@ -123,7 +123,7 @@ class ExploreChartHeader extends React.PureComponent { chartUpdateStartTime, latestQueryFormData, queryResponse } = this.props.chart; - const chartSucceeded = ['success', 'rendered'].indexOf(this.props.chart.chartStatus) > 0; + const chartFinished = ['failed', 'rendered', 'success'].includes(this.props.chart.chartStatus); return (
- {chartSucceeded && queryResponse && + {chartFinished && queryResponse && } - {chartSucceeded && queryResponse && queryResponse.is_cached && + {chartFinished && queryResponse && queryResponse.is_cached && { - const d = []; - Object.keys(keymap).forEach((k) => { - d.push({ - name: k, - descr: keymap[k], - key: k, - }); - }); - return d; -}; +const getHotKeys = () => Object.keys(keymap).map(k => ({ + name: k, + descr: keymap[k], + key: k, +})); const propTypes = { actions: PropTypes.object.isRequired, @@ -330,7 +324,7 @@ class ExploreViewContainer extends React.Component { )}
-
+
-
+
{ + const dashboardIds = this.props.dashboards.map(dashboard => dashboard.value); + let recentDashboard = sessionStorage.getItem('save_chart_recent_dashboard'); + recentDashboard = recentDashboard && parseInt(recentDashboard, 10); + if (recentDashboard !== null && dashboardIds.indexOf(recentDashboard) !== -1) { + this.setState({ saveToDashboardId: recentDashboard, addToDash: 'existing' }); + } + }); } onChange(name, event) { switch (name) { @@ -125,6 +132,11 @@ class SaveModal extends React.Component { sliceParams.goto_dash = gotodash; this.props.actions.saveSlice(this.props.form_data, sliceParams).then(({ data }) => { + if (data.dashboard_id === null) { + sessionStorage.removeItem('save_chart_recent_dashboard'); + } else { + sessionStorage.setItem('save_chart_recent_dashboard', data.dashboard_id); + } // Go to new slice url or dashboard url if (gotodash) { window.location = supersetURL(data.dashboard); diff --git a/superset/assets/src/explore/controlPanels/WordCloud.js b/superset/assets/src/explore/controlPanels/WordCloud.js index d7dd43de063bf..79c8fc1aed07f 100644 --- a/superset/assets/src/explore/controlPanels/WordCloud.js +++ b/superset/assets/src/explore/controlPanels/WordCloud.js @@ -17,6 +17,7 @@ * under the License. */ import { t } from '@superset-ui/translation'; +import { nonEmpty } from '../validators'; export default { controlPanelSections: [ @@ -32,6 +33,7 @@ export default { }, { label: t('Options'), + expanded: true, controlSetRows: [ ['size_from', 'size_to'], ['rotation'], @@ -39,4 +41,19 @@ export default { ], }, ], + controlOverrides: { + series: { + validators: [nonEmpty], + clearable: false, + }, + row_limit: { + default: 100, + }, + size_from: { + default: 10, + }, + size_to: { + default: 70, + }, + }, }; diff --git a/superset/assets/src/explore/controls.jsx b/superset/assets/src/explore/controls.jsx index 3b75d63b9d3b7..6f2e5e904476c 100644 --- a/superset/assets/src/explore/controls.jsx +++ b/superset/assets/src/explore/controls.jsx @@ -1309,10 +1309,11 @@ export const controls = { rotation: { type: 'SelectControl', - label: t('Rotation'), + label: t('Word Rotation'), choices: formatSelectOptions(['random', 'flat', 'square']), renderTrigger: true, - default: 'flat', + default: 'square', + clearable: false, description: t('Rotation to apply to words in the cloud'), }, @@ -1402,7 +1403,7 @@ export const controls = { size_from: { type: 'TextControl', isInt: true, - label: t('Font Size From'), + label: t('Minimum Font Size'), renderTrigger: true, default: '20', description: t('Font size for the smallest value in the list'), @@ -1411,7 +1412,7 @@ export const controls = { size_to: { type: 'TextControl', isInt: true, - label: t('Font Size To'), + label: t('Maximum Font Size'), renderTrigger: true, default: '150', description: t('Font size for the biggest value in the list'), diff --git a/superset/assets/src/featureFlags.ts b/superset/assets/src/featureFlags.ts index 54eee94829ae6..8638a5471f7c9 100644 --- a/superset/assets/src/featureFlags.ts +++ b/superset/assets/src/featureFlags.ts @@ -21,6 +21,7 @@ export enum FeatureFlag { SCOPED_FILTER = 'SCOPED_FILTER', OMNIBAR = 'OMNIBAR', + CLIENT_CACHE = 'CLIENT_CACHE', } export type FeatureFlagMap = { diff --git a/superset/assets/stylesheets/superset.less b/superset/assets/stylesheets/superset.less index 587851ea00e8d..d25dc6b73ccfc 100644 --- a/superset/assets/stylesheets/superset.less +++ b/superset/assets/stylesheets/superset.less @@ -291,6 +291,51 @@ table.table-no-hover tr:hover { cursor: text; } +.anchor-link-container { + position: absolute; + z-index: 5; + + .btn.btn-sm, .btn.btn-sm:active { + border: none; + padding-top: 0; + padding-bottom: 0; + background: none; + box-shadow: none; + } + + .fa.fa-link { + position: relative; + top: 2px; + right: 0; + visibility: hidden; + font-size: 11px; + text-align: center; + vertical-align: middle; + } +} + +.nav.nav-tabs li .anchor-link-container { + top: 0; + right: -32px; +} + +.dashboard-component.dashboard-component-header .anchor-link-container { + .fa.fa-link { + font-size: 16px; + } +} + +.nav.nav-tabs li:hover, +.dashboard-component.dashboard-component-header:hover { + .anchor-link-container { + cursor: pointer; + + .fa.fa-link { + visibility: visible; + } + } +} + .m-r-5 { margin-right: 5px; } @@ -535,3 +580,6 @@ tr.reactable-column-header th.reactable-header-sortable { .align-right { text-align: right; } +td.filtered { + background-color: lighten(desaturate(@brand-primary, 50%), 50%); +} diff --git a/superset/config.py b/superset/config.py index 8781d3d04286b..241d0396eddf2 100644 --- a/superset/config.py +++ b/superset/config.py @@ -200,7 +200,10 @@ # For example, DEFAULT_FEATURE_FLAGS = { 'FOO': True, 'BAR': False } here # and FEATURE_FLAGS = { 'BAR': True, 'BAZ': True } in superset_config.py # will result in combined feature flags of { 'FOO': True, 'BAR': True, 'BAZ': True } -DEFAULT_FEATURE_FLAGS = {} +DEFAULT_FEATURE_FLAGS = { + # Experimental feature introducing a client (browser) cache + 'CLIENT_CACHE': False, +} # A function that receives a dict of all feature flags # (DEFAULT_FEATURE_FLAGS merged with FEATURE_FLAGS) diff --git a/superset/connectors/base/models.py b/superset/connectors/base/models.py index eed92a688e88d..57db0ad4684d1 100644 --- a/superset/connectors/base/models.py +++ b/superset/connectors/base/models.py @@ -347,7 +347,7 @@ class BaseColumn(AuditMixinNullable, ImportMixin): __tablename__ = None # {connector_name}_column id = Column(Integer, primary_key=True) - column_name = Column(String(255)) + column_name = Column(String(255), nullable=False) verbose_name = Column(String(1024)) is_active = Column(Boolean, default=True) type = Column(String(32)) @@ -411,7 +411,7 @@ class BaseMetric(AuditMixinNullable, ImportMixin): __tablename__ = None # {connector_name}_metric id = Column(Integer, primary_key=True) - metric_name = Column(String(512)) + metric_name = Column(String(255), nullable=False) verbose_name = Column(String(1024)) metric_type = Column(String(32)) description = Column(Text) diff --git a/superset/connectors/druid/models.py b/superset/connectors/druid/models.py index 8440a25099a35..43a092c20c548 100644 --- a/superset/connectors/druid/models.py +++ b/superset/connectors/druid/models.py @@ -269,9 +269,7 @@ class DruidColumn(Model, BaseColumn): __tablename__ = 'columns' __table_args__ = (UniqueConstraint('column_name', 'datasource_id'),) - datasource_id = Column( - Integer, - ForeignKey('datasources.id')) + datasource_id = Column(Integer, ForeignKey('datasources.id')) # Setting enable_typechecks=False disables polymorphic inheritance. datasource = relationship( 'DruidDatasource', @@ -343,15 +341,14 @@ class DruidMetric(Model, BaseMetric): __tablename__ = 'metrics' __table_args__ = (UniqueConstraint('metric_name', 'datasource_id'),) - datasource_id = Column( - Integer, - ForeignKey('datasources.id')) + datasource_id = Column(Integer, ForeignKey('datasources.id')) + # Setting enable_typechecks=False disables polymorphic inheritance. datasource = relationship( 'DruidDatasource', backref=backref('metrics', cascade='all, delete-orphan'), enable_typechecks=False) - json = Column(Text) + json = Column(Text, nullable=False) export_fields = ( 'metric_name', 'verbose_name', 'metric_type', 'datasource_id', @@ -417,7 +414,7 @@ class DruidDatasource(Model, BaseDatasource): baselink = 'druiddatasourcemodelview' # Columns - datasource_name = Column(String(255)) + datasource_name = Column(String(255), nullable=False) is_hidden = Column(Boolean, default=False) filter_select_enabled = Column(Boolean, default=True) # override default fetch_values_from = Column(String(100)) @@ -427,7 +424,6 @@ class DruidDatasource(Model, BaseDatasource): 'DruidCluster', backref='datasources', foreign_keys=[cluster_name]) owners = relationship(owner_class, secondary=druiddatasource_user, backref='druiddatasources') - UniqueConstraint('cluster_name', 'datasource_name') export_fields = ( 'datasource_name', 'is_hidden', 'description', 'default_endpoint', diff --git a/superset/connectors/sqla/models.py b/superset/connectors/sqla/models.py index 64933708db6b1..f178db458bbf1 100644 --- a/superset/connectors/sqla/models.py +++ b/superset/connectors/sqla/models.py @@ -100,7 +100,7 @@ class TableColumn(Model, BaseColumn): backref=backref('columns', cascade='all, delete-orphan'), foreign_keys=[table_id]) is_dttm = Column(Boolean, default=False) - expression = Column(Text, default='') + expression = Column(Text) python_date_format = Column(String(255)) database_expression = Column(String(255)) @@ -209,7 +209,7 @@ class SqlMetric(Model, BaseMetric): 'SqlaTable', backref=backref('metrics', cascade='all, delete-orphan'), foreign_keys=[table_id]) - expression = Column(Text) + expression = Column(Text, nullable=False) export_fields = ( 'metric_name', 'verbose_name', 'metric_type', 'table_id', 'expression', diff --git a/superset/data/airports.csv.gz b/superset/data/airports.csv.gz deleted file mode 100644 index 3043486664476..0000000000000 Binary files a/superset/data/airports.csv.gz and /dev/null differ diff --git a/superset/data/bart-lines.json.gz b/superset/data/bart-lines.json.gz deleted file mode 100644 index 91f50fbe6accc..0000000000000 Binary files a/superset/data/bart-lines.json.gz and /dev/null differ diff --git a/superset/data/bart_lines.py b/superset/data/bart_lines.py index 3244a0a9cba23..f4e0b1f09cfca 100644 --- a/superset/data/bart_lines.py +++ b/superset/data/bart_lines.py @@ -14,9 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -import gzip import json -import os import pandas as pd import polyline @@ -24,16 +22,17 @@ from superset import db from superset.utils.core import get_or_create_main_db -from .helpers import DATA_FOLDER, TBL +from .helpers import TBL, get_example_data def load_bart_lines(): tbl_name = 'bart_lines' - with gzip.open(os.path.join(DATA_FOLDER, 'bart-lines.json.gz')) as f: - df = pd.read_json(f, encoding='latin-1') - df['path_json'] = df.path.map(json.dumps) - df['polyline'] = df.path.map(polyline.encode) - del df['path'] + content = get_example_data('bart-lines.json.gz') + df = pd.read_json(content, encoding='latin-1') + df['path_json'] = df.path.map(json.dumps) + df['polyline'] = df.path.map(polyline.encode) + del df['path'] + df.to_sql( tbl_name, db.engine, diff --git a/superset/data/birth_france_data_for_country_map.csv b/superset/data/birth_france_data_for_country_map.csv deleted file mode 100644 index 5de8d4551fa0d..0000000000000 --- a/superset/data/birth_france_data_for_country_map.csv +++ /dev/null @@ -1,97 +0,0 @@ -DEPT_ID,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014 -FR-01,6866,6706,6976,7228,6949,7323,7157,7282,7265,7242,7296,7354 -FR-02,6841,6761,6889,7041,6847,7012,6941,7050,6939,6755,6559,6468 -FR-03,3391,3335,3363,3503,3277,3289,3308,3402,3196,3288,3198,3152 -FR-04,1460,1522,1514,1536,1569,1569,1513,1547,1578,1561,1629,1538 -FR-05,1408,1403,1395,1461,1448,1441,1513,1470,1399,1441,1406,1383 -FR-06,11144,11514,11631,11754,11633,12275,11949,12257,11999,12087,12149,12170 -FR-07,3367,3176,3414,3484,3484,3447,3307,3380,3360,3405,3179,3254 -FR-08,3532,3422,3420,3343,3552,3522,3312,3254,3137,3258,3021,2966 -FR-09,1350,1412,1389,1499,1570,1493,1452,1473,1404,1425,1413,1364 -FR-10,3428,3553,3692,3685,3619,3721,3745,3722,3635,3587,3436,3377 -FR-11,3421,3321,3502,3661,3723,3778,3797,3770,3789,3669,3618,3516 -FR-12,2558,2614,2701,2829,2769,2748,2640,2694,2682,2615,2475,2555 -FR-13,23908,24056,24411,25371,25126,25412,25547,26410,25889,26328,26762,26384 -FR-14,8231,8257,8251,8531,8310,8183,8304,8111,8041,7833,7644,7466 -FR-15,1344,1396,1391,1398,1357,1300,1377,1274,1237,1230,1290,1214 -FR-16,3401,3514,3570,3653,3618,3666,3408,3564,3459,3490,3472,3378 -FR-17,5935,5900,6069,6089,5903,6136,6209,6185,6065,5916,5778,5846 -FR-18,3301,3271,3313,3231,3341,3303,3229,3341,3159,3120,3128,3097 -FR-19,2133,2250,2319,2327,2245,2263,2231,2247,2196,2163,2055,2094 -FR-21,6079,6052,5844,5986,6015,5960,5852,5963,5906,5905,5769,5779 -FR-22,6413,6317,6287,6743,6473,6494,6559,6438,6221,6184,5927,5790 -FR-23,1011,957,1054,1038,1013,1029,1044,919,967,998,897,879 -FR-24,3607,3690,3662,3758,3760,3832,3672,3665,3645,3547,3486,3479 -FR-25,6529,6798,6782,6993,6804,7097,6914,7105,6826,6778,6732,6659 -FR-26,5525,5703,5579,5945,5833,5927,5846,5915,5978,5912,6026,5965 -FR-27,7213,7220,7386,7402,7471,7717,7714,7715,7738,7676,7352,7242 -FR-28,5370,5363,5585,5632,5440,5677,5573,5716,5540,5548,5312,5295 -FR-29,9900,9963,9851,10184,9962,10040,9733,9823,9615,9597,9277,9088 -FR-2A,1232,1228,1348,1337,1284,1370,1422,1408,1422,1398,1317,1371 -FR-2B,1455,1444,1525,1474,1564,1569,1580,1591,1662,1612,1599,1616 -FR-30,7446,7777,7901,8384,8190,8449,8354,8494,8467,8196,8427,8216 -FR-31,13989,13900,14233,14957,14968,15415,15317,15770,16031,16347,16290,16641 -FR-32,1635,1625,1666,1580,1669,1689,1718,1671,1587,1668,1648,1643 -FR-33,15610,15819,15722,16539,16514,16636,17072,17271,17098,17097,17265,17303 -FR-34,11380,11562,11636,12191,12252,12564,12531,12658,13000,12902,12899,13008 -FR-35,12134,12072,12405,12687,12606,12837,12917,12876,13033,12892,12729,12555 -FR-36,2312,2314,2394,2283,2341,2371,2178,2221,2137,2136,2006,2030 -FR-37,6620,6594,6644,6813,6434,6811,6828,6886,6696,6796,6594,6718 -FR-38,14885,15356,15447,15830,15646,15999,15916,16136,15739,15948,15724,15664 -FR-39,2964,3017,2924,3021,3037,3045,2897,2865,2758,2741,2675,2637 -FR-40,3477,3621,3574,3755,3953,3862,3914,3993,3853,3880,3864,3696 -FR-41,3617,3678,3724,3815,3752,3847,3786,3777,3667,3704,3581,3517 -FR-42,8804,8906,8975,9184,9222,9357,9174,9403,9357,9473,9086,9183 -FR-43,2458,2416,2485,2426,2301,2398,2390,2348,2300,2244,2247,2157 -FR-44,15795,15988,16301,16530,16664,16763,16766,17159,16747,16821,16822,16700 -FR-45,8265,8424,8200,8635,8644,8524,8499,8757,8686,8689,8526,8355 -FR-46,1537,1430,1477,1563,1511,1555,1435,1506,1423,1487,1345,1415 -FR-47,3173,3245,3341,3426,3399,3378,3445,3359,3397,3332,3361,3347 -FR-48,768,772,760,784,781,779,798,736,695,711,663,651 -FR-49,10018,10085,10148,10548,10227,10270,10165,10312,10320,10061,10016,9781 -FR-50,5490,5487,5538,5448,5356,5384,5231,5238,5193,5282,4998,4911 -FR-51,6916,6979,7108,7118,6932,7065,7061,7182,7070,6761,7000,6887 -FR-52,2100,2095,2029,2104,2062,2037,1944,1889,1916,1847,1923,1881 -FR-53,3846,3932,3981,4118,3835,3912,3897,3962,3733,3750,3656,3456 -FR-54,8398,8671,8542,8743,8421,8559,8487,8536,8499,8387,8197,8135 -FR-55,2218,2287,2158,2294,2296,2220,2122,2221,2119,2107,2070,1928 -FR-56,7817,8036,7802,8221,7968,8288,7942,8029,7894,7909,7645,7554 -FR-57,11710,11970,12048,12114,11853,12012,11831,11856,11474,11579,11421,11385 -FR-58,2123,2181,2115,2137,2151,2049,1986,1982,1999,1942,1850,1801 -FR-59,36099,36257,35960,36858,36531,36572,36508,36703,36678,36513,36354,35923 -FR-60,10696,10630,10753,11144,11097,11162,11013,10960,11032,10941,10814,10802 -FR-61,3323,3243,3117,3276,3316,3185,3248,3192,3105,2933,2834,2810 -FR-62,18888,19304,19407,19780,19668,19902,19661,19784,19720,19017,19054,18809 -FR-63,6576,6632,6701,6902,6896,6865,6774,7131,6828,6933,6699,6908 -FR-64,6436,6338,6395,6680,6288,6455,6652,6569,6459,6490,6269,6497 -FR-65,2144,2186,2095,2284,2266,2095,2161,2149,2110,2201,2057,2111 -FR-66,4456,4320,4563,4779,4638,4756,4837,4869,4843,4943,4914,4800 -FR-67,13024,12828,13195,13388,13152,13231,13218,13346,13030,12895,13043,13262 -FR-68,9045,8945,8912,9324,8941,8909,8938,9177,8927,8818,8713,8826 -FR-69,23376,23796,24270,24808,24465,25120,25528,25973,25921,26294,25914,26712 -FR-70,2675,2773,2827,2975,2888,2755,2785,2761,2643,2609,2510,2458 -FR-71,5717,5709,5789,5876,5736,5860,5838,5865,5811,5752,5514,5552 -FR-72,6871,6935,6770,7133,6808,6909,6957,6942,6810,6703,6645,6664 -FR-73,4687,4736,4795,4903,5000,4971,4863,5074,4917,4786,4762,4798 -FR-74,8839,8753,8967,9124,8939,9333,9271,9521,9476,9829,9893,9982 -FR-75,31493,31817,31378,31748,30820,30623,31063,31447,30094,29291,28945,29134 -FR-76,15862,15650,15691,16004,16066,16041,15947,16338,16146,16014,15574,15199 -FR-77,17501,17729,18317,18986,18978,19240,19331,19712,19824,19678,19331,19708 -FR-78,19937,19431,19766,20438,19899,19895,19868,20312,19886,19827,19886,19525 -FR-79,3994,4100,4191,4057,4037,4331,4157,4060,4006,4029,3986,3718 -FR-80,7134,7035,7024,7021,6939,7094,6838,7103,6989,6843,6743,6506 -FR-81,3579,3611,3837,3933,3869,4056,4030,3925,4006,3939,3829,3831 -FR-82,2398,2591,2590,2823,2858,2932,2935,2926,2978,2940,2827,2829 -FR-83,10388,10622,10646,10889,10938,11131,10955,11159,11146,11240,10917,11123 -FR-84,6547,6629,6608,6805,6694,7000,7014,6967,7008,7107,7171,7058 -FR-85,6874,7062,7299,7589,7647,7629,7718,7601,7442,7436,7164,7070 -FR-86,4594,4568,4725,4850,4753,4909,4953,5006,4885,4880,4708,4686 -FR-87,3449,3659,3834,3754,3829,3891,3985,3848,3907,3825,3723,3724 -FR-88,4291,4264,4310,4416,4274,4215,4252,4057,3883,3715,3796,3679 -FR-89,3710,3844,3821,3929,3917,4045,3991,3842,3699,3729,3780,3621 -FR-90,1896,1766,1837,1888,1880,1818,1822,1802,1794,1763,1675,1707 -FR-91,17122,17614,17753,18281,17932,18134,18040,18509,18493,18506,18510,18903 -FR-92,24607,24649,24588,25426,24937,25217,25192,25194,25083,24790,24614,24675 -FR-93,25868,26313,26760,27916,27743,28062,28313,28513,28362,28675,28687,29471 -FR-94,19637,19866,19947,20948,20331,20736,21022,21391,20991,20967,20748,21566 -FR-95,17346,17863,18012,19015,18624,18761,18728,19506,19551,19495,19550,19737 \ No newline at end of file diff --git a/superset/data/birth_names.json.gz b/superset/data/birth_names.json.gz deleted file mode 100644 index 2652cf7242a91..0000000000000 Binary files a/superset/data/birth_names.json.gz and /dev/null differ diff --git a/superset/data/birth_names.py b/superset/data/birth_names.py index 379fdc806c346..4f11ac5b7dd92 100644 --- a/superset/data/birth_names.py +++ b/superset/data/birth_names.py @@ -14,9 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -import gzip import json -import os import textwrap import pandas as pd @@ -28,7 +26,7 @@ from .helpers import ( config, Dash, - DATA_FOLDER, + get_example_data, get_slice_json, merge_slice, Slice, @@ -39,8 +37,8 @@ def load_birth_names(): """Loading birth name dataset from a zip file in the repo""" - with gzip.open(os.path.join(DATA_FOLDER, 'birth_names.json.gz')) as f: - pdf = pd.read_json(f) + data = get_example_data('birth_names.json.gz') + pdf = pd.read_json(data) pdf.ds = pd.to_datetime(pdf.ds, unit='ms') pdf.to_sql( 'birth_names', diff --git a/superset/data/countries.json.gz b/superset/data/countries.json.gz deleted file mode 100644 index 6c71c0c43232c..0000000000000 Binary files a/superset/data/countries.json.gz and /dev/null differ diff --git a/superset/data/country_map.py b/superset/data/country_map.py index c1c2b417b5858..e74638bfbc713 100644 --- a/superset/data/country_map.py +++ b/superset/data/country_map.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. import datetime -import os import pandas as pd from sqlalchemy import BigInteger, Date, String @@ -24,7 +23,7 @@ from superset.connectors.sqla.models import SqlMetric from superset.utils import core as utils from .helpers import ( - DATA_FOLDER, + get_example_data, get_slice_json, merge_slice, misc_dash_slices, @@ -35,8 +34,9 @@ def load_country_map_data(): """Loading data for map with country map""" - csv_path = os.path.join(DATA_FOLDER, 'birth_france_data_for_country_map.csv') - data = pd.read_csv(csv_path, encoding='utf-8') + csv_bytes = get_example_data( + 'birth_france_data_for_country_map.csv', is_gzip=False, make_bytes=True) + data = pd.read_csv(csv_bytes, encoding='utf-8') data['dttm'] = datetime.datetime.now().date() data.to_sql( # pylint: disable=no-member 'birth_france_by_region', diff --git a/superset/data/energy.json.gz b/superset/data/energy.json.gz deleted file mode 100644 index 624d71db683a9..0000000000000 Binary files a/superset/data/energy.json.gz and /dev/null differ diff --git a/superset/data/energy.py b/superset/data/energy.py index c04eb46c489dd..e1d48e76a75af 100644 --- a/superset/data/energy.py +++ b/superset/data/energy.py @@ -16,8 +16,6 @@ # under the License. """Loads datasets, dashboards and slices in a new superset instance""" # pylint: disable=C,R,W -import gzip -import os import textwrap import pandas as pd @@ -26,14 +24,16 @@ from superset import db from superset.connectors.sqla.models import SqlMetric from superset.utils import core as utils -from .helpers import DATA_FOLDER, merge_slice, misc_dash_slices, Slice, TBL +from .helpers import ( + DATA_FOLDER, get_example_data, merge_slice, misc_dash_slices, Slice, TBL, +) def load_energy(): """Loads an energy related dataset to use with sankey and graphs""" tbl_name = 'energy_usage' - with gzip.open(os.path.join(DATA_FOLDER, 'energy.json.gz')) as f: - pdf = pd.read_json(f) + data = get_example_data('energy.json.gz') + pdf = pd.read_json(data) pdf.to_sql( tbl_name, db.engine, diff --git a/superset/data/flight_data.csv.gz b/superset/data/flight_data.csv.gz deleted file mode 100644 index bbdebdfafcba7..0000000000000 Binary files a/superset/data/flight_data.csv.gz and /dev/null differ diff --git a/superset/data/flights.py b/superset/data/flights.py index 1ed575b44d777..25112444fc29d 100644 --- a/superset/data/flights.py +++ b/superset/data/flights.py @@ -14,26 +14,23 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -import gzip -import os - import pandas as pd from sqlalchemy import DateTime from superset import db from superset.utils import core as utils -from .helpers import DATA_FOLDER, TBL +from .helpers import get_example_data, TBL def load_flights(): """Loading random time series data from a zip file in the repo""" tbl_name = 'flights' - with gzip.open(os.path.join(DATA_FOLDER, 'flight_data.csv.gz')) as f: - pdf = pd.read_csv(f, encoding='latin-1') + data = get_example_data('flight_data.csv.gz', make_bytes=True) + pdf = pd.read_csv(data, encoding='latin-1') # Loading airports info to join and get lat/long - with gzip.open(os.path.join(DATA_FOLDER, 'airports.csv.gz')) as f: - airports = pd.read_csv(f, encoding='latin-1') + airports_bytes = get_example_data('airports.csv.gz', make_bytes=True) + airports = pd.read_csv(airports_bytes, encoding='latin-1') airports = airports.set_index('IATA_CODE') pdf['ds'] = pdf.YEAR.map(str) + '-0' + pdf.MONTH.map(str) + '-0' + pdf.DAY.map(str) diff --git a/superset/data/helpers.py b/superset/data/helpers.py index d6192b64eb320..f876dc9105ada 100644 --- a/superset/data/helpers.py +++ b/superset/data/helpers.py @@ -16,13 +16,19 @@ # under the License. """Loads datasets, dashboards and slices in a new superset instance""" # pylint: disable=C,R,W +from io import BytesIO import json import os +import zlib + +import requests from superset import app, db from superset.connectors.connector_registry import ConnectorRegistry from superset.models import core as models +BASE_URL = 'https://github.com/apache-superset/examples-data/blob/master/' + # Shortcuts DB = models.Database Slice = models.Slice @@ -60,3 +66,12 @@ def get_slice_json(defaults, **kwargs): d = defaults.copy() d.update(kwargs) return json.dumps(d, indent=4, sort_keys=True) + + +def get_example_data(filepath, is_gzip=True, make_bytes=False): + content = requests.get(f'{BASE_URL}{filepath}?raw=true').content + if is_gzip: + content = zlib.decompress(content, zlib.MAX_WBITS|16) + if make_bytes: + content = BytesIO(content) + return content diff --git a/superset/data/long_lat.py b/superset/data/long_lat.py index 40895d540459f..18f477cfa4045 100644 --- a/superset/data/long_lat.py +++ b/superset/data/long_lat.py @@ -15,8 +15,6 @@ # specific language governing permissions and limitations # under the License. import datetime -import gzip -import os import random import geohash @@ -26,7 +24,7 @@ from superset import db from superset.utils import core as utils from .helpers import ( - DATA_FOLDER, + get_example_data, get_slice_json, merge_slice, misc_dash_slices, @@ -37,8 +35,8 @@ def load_long_lat_data(): """Loading lat/long data from a csv file in the repo""" - with gzip.open(os.path.join(DATA_FOLDER, 'san_francisco.csv.gz')) as f: - pdf = pd.read_csv(f, encoding='utf-8') + data = get_example_data('san_francisco.csv.gz', make_bytes=True) + pdf = pd.read_csv(data, encoding='utf-8') start = datetime.datetime.now().replace( hour=0, minute=0, second=0, microsecond=0) pdf['datetime'] = [ diff --git a/superset/data/multiformat_time_series.json.gz b/superset/data/multiformat_time_series.json.gz deleted file mode 100644 index e0877b707dcd4..0000000000000 Binary files a/superset/data/multiformat_time_series.json.gz and /dev/null differ diff --git a/superset/data/multiformat_time_series.py b/superset/data/multiformat_time_series.py index 5dec85ab01a13..58ff7fbb0d32b 100644 --- a/superset/data/multiformat_time_series.py +++ b/superset/data/multiformat_time_series.py @@ -14,8 +14,6 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -import gzip -import os import pandas as pd from sqlalchemy import BigInteger, Date, DateTime, String @@ -24,7 +22,7 @@ from superset.utils import core as utils from .helpers import ( config, - DATA_FOLDER, + get_example_data, get_slice_json, merge_slice, misc_dash_slices, @@ -35,8 +33,9 @@ def load_multiformat_time_series(): """Loading time series data from a zip file in the repo""" - with gzip.open(os.path.join(DATA_FOLDER, 'multiformat_time_series.json.gz')) as f: - pdf = pd.read_json(f) + data = get_example_data('multiformat_time_series.json.gz') + pdf = pd.read_json(data) + pdf.ds = pd.to_datetime(pdf.ds, unit='s') pdf.ds2 = pd.to_datetime(pdf.ds2, unit='s') pdf.to_sql( diff --git a/superset/data/paris.py b/superset/data/paris.py index e32588da1c740..2ed3f8eaea075 100644 --- a/superset/data/paris.py +++ b/superset/data/paris.py @@ -14,24 +14,22 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -import gzip import json -import os import pandas as pd from sqlalchemy import String, Text from superset import db from superset.utils import core as utils -from .helpers import DATA_FOLDER, TBL +from .helpers import TBL, get_example_data def load_paris_iris_geojson(): tbl_name = 'paris_iris_mapping' - with gzip.open(os.path.join(DATA_FOLDER, 'paris_iris.json.gz')) as f: - df = pd.read_json(f) - df['features'] = df.features.map(json.dumps) + data = get_example_data('paris_iris.json.gz') + df = pd.read_json(data) + df['features'] = df.features.map(json.dumps) df.to_sql( tbl_name, diff --git a/superset/data/paris_iris.json.gz b/superset/data/paris_iris.json.gz deleted file mode 100644 index 4a964c94f74dd..0000000000000 Binary files a/superset/data/paris_iris.json.gz and /dev/null differ diff --git a/superset/data/random_time_series.json.gz b/superset/data/random_time_series.json.gz deleted file mode 100644 index 5275d5571d5f4..0000000000000 Binary files a/superset/data/random_time_series.json.gz and /dev/null differ diff --git a/superset/data/random_time_series.py b/superset/data/random_time_series.py index cfc13e131ef03..ee7450a634050 100644 --- a/superset/data/random_time_series.py +++ b/superset/data/random_time_series.py @@ -14,8 +14,6 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -import gzip -import os import pandas as pd from sqlalchemy import DateTime @@ -24,7 +22,7 @@ from superset.utils import core as utils from .helpers import ( config, - DATA_FOLDER, + get_example_data, get_slice_json, merge_slice, Slice, @@ -34,8 +32,8 @@ def load_random_time_series_data(): """Loading random time series data from a zip file in the repo""" - with gzip.open(os.path.join(DATA_FOLDER, 'random_time_series.json.gz')) as f: - pdf = pd.read_json(f) + data = get_example_data('random_time_series.json.gz') + pdf = pd.read_json(data) pdf.ds = pd.to_datetime(pdf.ds, unit='s') pdf.to_sql( 'random_time_series', diff --git a/superset/data/san_francisco.csv.gz b/superset/data/san_francisco.csv.gz deleted file mode 100644 index 1d977a4a1a803..0000000000000 Binary files a/superset/data/san_francisco.csv.gz and /dev/null differ diff --git a/superset/data/sf_population.json.gz b/superset/data/sf_population.json.gz deleted file mode 100644 index 53ba13acd7802..0000000000000 Binary files a/superset/data/sf_population.json.gz and /dev/null differ diff --git a/superset/data/sf_population_polygons.py b/superset/data/sf_population_polygons.py index 6da85f728bb73..2248a48dafece 100644 --- a/superset/data/sf_population_polygons.py +++ b/superset/data/sf_population_polygons.py @@ -14,24 +14,22 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -import gzip import json -import os import pandas as pd from sqlalchemy import BigInteger, Text from superset import db from superset.utils import core as utils -from .helpers import DATA_FOLDER, TBL +from .helpers import TBL, get_example_data def load_sf_population_polygons(): tbl_name = 'sf_population_polygons' - with gzip.open(os.path.join(DATA_FOLDER, 'sf_population.json.gz')) as f: - df = pd.read_json(f) - df['contour'] = df.contour.map(json.dumps) + data = get_example_data('sf_population.json.gz') + df = pd.read_json(data) + df['contour'] = df.contour.map(json.dumps) df.to_sql( tbl_name, diff --git a/superset/data/unicode_test_data.py b/superset/data/unicode_test_data.py index 42e6bdb1e3699..03c00a7b07fce 100644 --- a/superset/data/unicode_test_data.py +++ b/superset/data/unicode_test_data.py @@ -16,7 +16,6 @@ # under the License. import datetime import json -import os import random import pandas as pd @@ -27,7 +26,7 @@ from .helpers import ( config, Dash, - DATA_FOLDER, + get_example_data, get_slice_json, merge_slice, Slice, @@ -38,8 +37,9 @@ def load_unicode_test_data(): """Loading unicode test dataset from a csv file in the repo""" - df = pd.read_csv(os.path.join(DATA_FOLDER, 'unicode_utf8_unixnl_test.csv'), - encoding='utf-8') + data = get_example_data( + 'unicode_utf8_unixnl_test.csv', is_gzip=False, make_bytes=True) + df = pd.read_csv(data, encoding='utf-8') # generate date/numeric data df['dttm'] = datetime.datetime.now().date() df['value'] = [random.randint(1, 100) for _ in range(len(df))] diff --git a/superset/data/unicode_utf8_unixnl_test.csv b/superset/data/unicode_utf8_unixnl_test.csv deleted file mode 100644 index 9b0235b0ddd0b..0000000000000 --- a/superset/data/unicode_utf8_unixnl_test.csv +++ /dev/null @@ -1,42 +0,0 @@ -phrase,short_phrase,with_missing -"Под южно дърво, цъфтящо в синьо, бягаше малко пухкаво зайче.",Под южно д,Fam hx-cardiovas dis NEC -Příliš žluťoučký kůň úpěl ďábelské ódy.,Příliš žlu, -視野無限廣,窗外有藍天,視野無限廣,窗外有藍,Sparganosis -微風迎客,軟語伴茶,微風迎客,軟語伴茶,Var mgr NEC wo ntc mgr -中国智造,慧及全球,中国智造,慧及全球,Mech prob w internal org -"Quizdeltagerne spiste jordbær med fløde, mens cirkusklovnen Walther spillede på xylofon.",Quizdeltag,Corneal dystrophy NOS -Pa’s wijze lynx bezag vroom het fikse aquaduct.,Pa’s wijze,Edema in preg-unspec -Eĥoŝanĝo ĉiuĵaŭde.,Eĥoŝanĝo ĉ, -See väike mölder jõuab rongile hüpata,See väike ,Twin NOS-nonhosp -Viekas kettu punaturkki laiskan koiran takaa kurkki.,Viekas ket,Postgastric surgery synd -Voix ambiguë d’un cœur qui au zéphyr préfère les jattes de kiwis.,Voix ambig,Loose body-mult joints -Portez ce vieux whisky au juge blond qui fume.,Portez ce ,Late eff acc poisoning -Zwölf Boxkämpfer jagen Viktor quer über den großen Sylter Deich,Zwölf Boxk,Opn brain inj w/o coma -Franz jagt im komplett verwahrlosten Taxi quer durch Bayern.,Franz jagt,TB of ear-unspec -Θέλει αρετή και τόλμη η ελευθερία. (Ανδρέας Κάλβος),Θέλει αρετ,Chr peptic ulcer w perf -Ο καλύμνιος σφουγγαράς ψιθύρισε πως θα βουτήξει χωρίς να διστάζει.,Ο καλύμνιο,Cns TB NEC-cult dx -דג סקרן שט לו בים זך אך לפתע פגש חבורה נחמדה שצצה כך.,דג סקרן שט,Polyhydramnios-delivered -Árvíztűrő tükörfúrógép,Árvíztűrő ,Malign neopl scrotum -"Egy hűtlen vejét fülöncsípő, dühös mexikói úr Wesselényinél mázol Quitóban.",Egy hűtlen,Tubal/broad lig anom NOS -Saya lihat foto Hamengkubuwono XV bersama enam zebra purba cantik yang jatuh dari Al Quranmu.,Saya lihat,Ben carcinoid duodenum -"Ma la volpe, col suo balzo, ha raggiunto il quieto Fido.",Ma la volp,Ch leu un cl wo ach rmsn -いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさきゆめみし ゑひもせす,いろはにほへと ちり,Mycotic arthritis-pelvis -다람쥐 헌 쳇바퀴에 타고파,다람쥐 헌 쳇바퀴에,Paral polio NEC-type 1 -Sarkanās jūrascūciņas peld pa jūru.,Sarkanās j,Fx larynx/trachea-open -En god stil må først og fremst være klar. Den må være passende. Aristoteles.,En god sti,Dermatophytosis site NOS -Pchnąć w tę łódź jeża lub ośm skrzyń fig,Pchnąć w t,Anxiety disorder oth dis -A rápida raposa castanha salta por cima do cão lento.,A rápida r,Adenoid vegetations -A ligeira raposa marrom ataca o cão preguiçoso.,A ligeira ,Consanguinity -Zebras caolhas de Java querem passar fax para moças gigantes de New York,Zebras cao,"Hypotony NOS, eye" -Agera vulpe maronie sare peste câinele cel leneş.,Agera vulp,Urethral syndrome NOS -Съешь ещё этих мягких французских булок да выпей же чаю,Съешь ещё ,Coccidioidomycosis NOS -Чешће цeђење мрeжастим џаком побољшава фертилизацију генских хибрида.,Чешће цeђе, -Češće ceđenje mrežastim džakom poboljšava fertilizaciju genskih hibrida.,Češće ceđe,Scrn-hemoglobinopath NEC -Kŕdeľ šťastných ďatľov učí pri ústí Váhu mĺkveho koňa obhrýzať kôru a žrať čerstvé mäso.,Kŕdeľ šťas, -V kožuščku hudobnega fanta stopiclja mizar in kliče 0619872345.,V kožuščku, -El veloz murciélago hindú comía feliz cardillo y kiwi. La cigüeña tocaba el saxofón detrás del palenque de paja.,El veloz m,Cervical syndrome NEC -Flygande bäckasiner söka hwila på mjuka tuvor,Flygande b,Letterer-siwe dis abdom -เป็นมนุษย์สุดประเสริฐเลิศคุณค่า กว่าบรรดาฝูงสัตว์เดรัจฉาน จงฝ่าฟันพัฒนาวิชาการ อย่าล้างผลาญฤๅเข่นฆ่าบีฑาใคร ไม่ถือโทษโกรธแช่งซัดฮึดฮัดด่า หัดอภัยเหมือนกีฬาอัชฌาสัย ปฏิบัติประพฤติกฎกำหนดใจ พูดจาให้จ๊ะ ๆ จ๋า ๆ น่าฟังเอยฯ,เป็นมนุษย์,Balantidiasis -"Pijamalı hasta, yağız şoföre çabucak güvendi",Pijamalı h,Epilepsy-delivered w p/p -زۆھرەگۈل ئابدۇۋاجىت فرانسىيەنىڭ پارىژدىكى خېلى بىشەم ئوقۇغۇچى.,زۆھرەگۈل ئ,Fit/adj non-vsc cath NEC -ئاۋۇ بىر جۈپ خوراز فرانسىيەنىڭ پارىژ شەھرىگە يېقىن تاغقا كۆچەلمىدى.,ئاۋۇ بىر ج,Sat cerv smr-no trnsfrm diff --git a/superset/data/world_bank.py b/superset/data/world_bank.py index 910b3389e575c..16aa0cb24c656 100644 --- a/superset/data/world_bank.py +++ b/superset/data/world_bank.py @@ -16,7 +16,6 @@ # under the License. """Loads datasets, dashboards and slices in a new superset instance""" # pylint: disable=C,R,W -import gzip import json import os import textwrap @@ -31,6 +30,7 @@ config, Dash, DATA_FOLDER, + get_example_data, get_slice_json, merge_slice, misc_dash_slices, @@ -43,8 +43,8 @@ def load_world_bank_health_n_pop(): """Loads the world bank health dataset, slices and a dashboard""" tbl_name = 'wb_health_population' - with gzip.open(os.path.join(DATA_FOLDER, 'countries.json.gz')) as f: - pdf = pd.read_json(f) + data = get_example_data('countries.json.gz') + pdf = pd.read_json(data) pdf.columns = [col.replace('.', '_') for col in pdf.columns] pdf.year = pd.to_datetime(pdf.year) pdf.to_sql( diff --git a/superset/legacy.py b/superset/legacy.py index c066cb6da0949..955a486a185dd 100644 --- a/superset/legacy.py +++ b/superset/legacy.py @@ -16,82 +16,6 @@ # under the License. # pylint: disable=C,R,W """Code related with dealing with legacy / change management""" -import re - -from superset import frontend_config - -FORM_DATA_KEY_WHITELIST = list(frontend_config.get('controls').keys()) + ['slice_id'] - - -def cast_filter_data(form_data): - """Used by cast_form_data to parse the filters""" - flts = [] - having_flts = [] - fd = form_data - filter_pattern = re.compile(r"""((?:[^,"']|"[^"]*"|'[^']*')+)""") - for i in range(0, 10): - for prefix in ['flt', 'having']: - col_str = '{}_col_{}'.format(prefix, i) - op_str = '{}_op_{}'.format(prefix, i) - val_str = '{}_eq_{}'.format(prefix, i) - if col_str in fd and op_str in fd and val_str in fd \ - and len(fd[val_str]) > 0: - f = {} - f['col'] = fd[col_str] - f['op'] = fd[op_str] - if prefix == 'flt': - # transfer old strings in filter value to list - splitted = filter_pattern.split(fd[val_str])[1::2] - values = [types.replace("'", '').strip() for types in splitted] - f['val'] = values - flts.append(f) - if prefix == 'having': - f['val'] = fd[val_str] - having_flts.append(f) - if col_str in fd: - del fd[col_str] - if op_str in fd: - del fd[op_str] - if val_str in fd: - del fd[val_str] - fd['filters'] = flts - fd['having_filters'] = having_flts - return fd - - -def cast_form_data(form_data): - """Translates old to new form_data""" - d = {} - fields = frontend_config.get('controls', {}) - for k, v in form_data.items(): - field_config = fields.get(k, {}) - ft = field_config.get('type') - if ft == 'CheckboxControl': - # bug in some urls with dups on bools - if isinstance(v, list): - v = 'y' in v - else: - v = True if v in ('true', 'y') or v is True else False - elif v and ft == 'TextControl' and field_config.get('isInt'): - v = int(v) if v != '' else None - elif v and ft == 'TextControl' and field_config.get('isFloat'): - v = float(v) if v != '' else None - elif v and ft == 'SelectControl': - if field_config.get('multi'): - if type(form_data).__name__ == 'ImmutableMultiDict': - v = form_data.getlist(k) - elif not isinstance(v, list): - v = [v] - if d.get('slice_id'): - d['slice_id'] = int(d['slice_id']) - - d[k] = v - if 'filters' not in d: - d = cast_filter_data(d) - for k in list(d.keys()): - if k not in FORM_DATA_KEY_WHITELIST: - del d[k] - return d def update_time_range(form_data): diff --git a/superset/migrations/versions/7f2635b51f5d_update_base_columns.py b/superset/migrations/versions/7f2635b51f5d_update_base_columns.py new file mode 100644 index 0000000000000..7087c6a5ab19e --- /dev/null +++ b/superset/migrations/versions/7f2635b51f5d_update_base_columns.py @@ -0,0 +1,137 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +"""update base columns + +Note that the columns table was previously partially modifed by revision +f231d82b9b26. + +Revision ID: 7f2635b51f5d +Revises: 937d04c16b64 +Create Date: 2018-07-20 15:31:05.058050 + +""" + +# revision identifiers, used by Alembic. +revision = '7f2635b51f5d' +down_revision = '937d04c16b64' + +from alembic import op +from sqlalchemy import Column, engine, Integer, String +from sqlalchemy.ext.declarative import declarative_base + +from superset import db +from superset.utils.core import generic_find_uq_constraint_name + +Base = declarative_base() + +conv = { + 'uq': 'uq_%(table_name)s_%(column_0_name)s', +} + + +class BaseColumnMixin: + id = Column(Integer, primary_key=True) + + +class DruidColumn(BaseColumnMixin, Base): + __tablename__ = 'columns' + + datasource_id = Column(Integer) + + +class TableColumn(BaseColumnMixin, Base): + __tablename__ = 'table_columns' + + table_id = Column(Integer) + + +def upgrade(): + bind = op.get_bind() + session = db.Session(bind=bind) + + # Delete the orphaned columns records. + for record in session.query(DruidColumn).all(): + if record.datasource_id is None: + session.delete(record) + + session.commit() + + # Enforce that the columns.column_name column be non-nullable. + with op.batch_alter_table('columns') as batch_op: + batch_op.alter_column( + 'column_name', + existing_type=String(255), + nullable=False, + ) + + # Delete the orphaned table_columns records. + for record in session.query(TableColumn).all(): + if record.table_id is None: + session.delete(record) + + session.commit() + + # Reduce the size of the table_columns.column_name column for constraint + # viability and enforce that it be non-nullable. + with op.batch_alter_table('table_columns') as batch_op: + batch_op.alter_column( + 'column_name', + existing_type=String(256), + nullable=False, + type_=String(255), + ) + + # Add the missing uniqueness constraint to the table_columns table. + with op.batch_alter_table('table_columns', naming_convention=conv) as batch_op: + batch_op.create_unique_constraint( + 'uq_table_columns_column_name', + ['column_name', 'table_id'], + ) + + +def downgrade(): + bind = op.get_bind() + insp = engine.reflection.Inspector.from_engine(bind) + + # Remove the missing uniqueness constraint from the table_columns table. + with op.batch_alter_table('table_columns', naming_convention=conv) as batch_op: + batch_op.drop_constraint( + generic_find_uq_constraint_name( + 'table_columns', + {'column_name', 'table_id'}, + insp, + ) or 'uq_table_columns_column_name', + type_='unique', + ) + + # Restore the size of the table_columns.column_name column and forego that + # it be non-nullable. + with op.batch_alter_table('table_columns') as batch_op: + batch_op.alter_column( + 'column_name', + existing_type=String(255), + nullable=True, + type_=String(256), + ) + + # Forego that the columns.column_name be non-nullable. + with op.batch_alter_table('columns') as batch_op: + batch_op.alter_column( + 'column_name', + existing_type=String(255), + nullable=True, + ) diff --git a/superset/migrations/versions/80aa3f04bc82_add_parent_ids_in_dashboard_layout.py b/superset/migrations/versions/80aa3f04bc82_add_parent_ids_in_dashboard_layout.py new file mode 100644 index 0000000000000..dd975386d3537 --- /dev/null +++ b/superset/migrations/versions/80aa3f04bc82_add_parent_ids_in_dashboard_layout.py @@ -0,0 +1,120 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +"""Add Parent ids in dashboard layout metadata + +Revision ID: 80aa3f04bc82 +Revises: 45e7da7cfeba +Create Date: 2019-04-09 16:27:03.392872 + +""" +import json +import logging + +from alembic import op +from sqlalchemy import ( + Column, + Integer, + Text, +) +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship +from alembic import op +import sqlalchemy as sa + +from superset import db + +# revision identifiers, used by Alembic. +revision = '80aa3f04bc82' +down_revision = '45e7da7cfeba' + +Base = declarative_base() + + +class Dashboard(Base): + """Declarative class to do query in upgrade""" + __tablename__ = 'dashboards' + id = Column(Integer, primary_key=True) + position_json = Column(Text) + + +def add_parent_ids(node, layout): + if node: + current_id = node.get('id') + parents = list(node.get('parents') or []) + child_ids = node.get('children') + + if child_ids and len(child_ids) > 0: + parents.append(current_id) + for child_id in child_ids: + child_node = layout.get(child_id) + child_node['parents'] = parents + add_parent_ids(child_node, layout) + + +def upgrade(): + bind = op.get_bind() + session = db.Session(bind=bind) + + dashboards = session.query(Dashboard).all() + for i, dashboard in enumerate(dashboards): + print('adding parents for dashboard layout, id = {} ({}/{}) >>>>'.format( + dashboard.id, + i + 1, + len(dashboards), + )) + try: + layout = json.loads(dashboard.position_json or '{}') + if layout and layout['ROOT_ID']: + add_parent_ids(layout['ROOT_ID'], layout) + + dashboard.position_json = json.dumps( + layout, indent=None, separators=(',', ':'), sort_keys=True) + session.merge(dashboard) + except Exception as e: + logging.exception(e) + + session.commit() + session.close() + + +def downgrade(): + bind = op.get_bind() + session = db.Session(bind=bind) + + dashboards = session.query(Dashboard).all() + for i, dashboard in enumerate(dashboards): + print('remove parents from dashboard layout, id = {} ({}/{}) >>>>'.format( + dashboard.id, + i + 1, + len(dashboards), + )) + try: + layout = json.loads(dashboard.position_json or '{}') + for key, item in layout.items(): + if not isinstance(item, dict): + continue + item.pop('parents', None) + layout[key] = item + + dashboard.position_json = json.dumps( + layout, indent=None, separators=(',', ':'), sort_keys=True) + session.merge(dashboard) + except Exception as e: + logging.exception(e) + + session.commit() + session.close() diff --git a/superset/migrations/versions/937d04c16b64_update_datasources.py b/superset/migrations/versions/937d04c16b64_update_datasources.py new file mode 100644 index 0000000000000..a233a442eb4e8 --- /dev/null +++ b/superset/migrations/versions/937d04c16b64_update_datasources.py @@ -0,0 +1,52 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +"""update datasources + +Revision ID: 937d04c16b64 +Revises: d94d33dbe938 +Create Date: 2018-07-20 16:08:10.195843 + +""" + +# revision identifiers, used by Alembic. +revision = '937d04c16b64' +down_revision = 'd94d33dbe938' + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + + # Enforce that the datasource_name column be non-nullable. + with op.batch_alter_table('datasources') as batch_op: + batch_op.alter_column( + 'datasource_name', + existing_type=sa.String(255), + nullable=False, + ) + + +def downgrade(): + + # Forego that the datasource_name column be non-nullable. + with op.batch_alter_table('datasources') as batch_op: + batch_op.alter_column( + 'datasource_name', + existing_type=sa.String(255), + nullable=True, + ) diff --git a/superset/migrations/versions/a99f2f7c195a_rewriting_url_from_shortner_with_new_.py b/superset/migrations/versions/a99f2f7c195a_rewriting_url_from_shortner_with_new_.py index 4cc432fb1b000..05e7de8ce55be 100644 --- a/superset/migrations/versions/a99f2f7c195a_rewriting_url_from_shortner_with_new_.py +++ b/superset/migrations/versions/a99f2f7c195a_rewriting_url_from_shortner_with_new_.py @@ -30,7 +30,6 @@ import json import sqlalchemy as sa from superset import db -from superset.legacy import cast_form_data from sqlalchemy.ext.declarative import declarative_base from urllib import parse @@ -72,7 +71,6 @@ def upgrade(): d = parse_querystring(url.url.split('?')[1]) split = url.url.split('/') d['datasource'] = split[5] + '__' + split[4] - d = cast_form_data(d) newurl = '/'.join(split[:-1]) + '/?form_data=' + parse.quote_plus(json.dumps(d)) url.url = newurl session.merge(url) diff --git a/superset/migrations/versions/d94d33dbe938_form_strip.py b/superset/migrations/versions/d94d33dbe938_form_strip.py new file mode 100644 index 0000000000000..b34bbaacb85ca --- /dev/null +++ b/superset/migrations/versions/d94d33dbe938_form_strip.py @@ -0,0 +1,193 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +"""form strip + +Revision ID: d94d33dbe938 +Revises: 80aa3f04bc82 +Create Date: 2019-03-21 10:22:01.610217 + +""" + +# revision identifiers, used by Alembic. +revision = 'd94d33dbe938' +down_revision = '80aa3f04bc82' + +from alembic import op +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy import Column, Integer, String, Text + +from superset import db +from superset.utils.core import MediumText + +Base = declarative_base() + + +class BaseColumnMixin(object): + id = Column(Integer, primary_key=True) + column_name = Column(String(255)) + description = Column(Text) + type = Column(String(32)) + verbose_name = Column(String(1024)) + + +class BaseDatasourceMixin(object): + id = Column(Integer, primary_key=True) + description = Column(Text) + + +class BaseMetricMixin(object): + id = Column(Integer, primary_key=True) + d3format = Column(String(128)) + description = Column(Text) + metric_name = Column(String(512)) + metric_type = Column(String(32)) + verbose_name = Column(String(1024)) + warning_text = Column(Text) + + +class Annotation(Base): + __tablename__ = 'annotation' + + id = Column(Integer, primary_key=True) + long_descr = Column(Text) + json_metadata = Column(Text) + short_descr = Column(String(500)) + + +class Dashboard(Base): + __tablename__ = 'dashboards' + + id = Column(Integer, primary_key=True) + css = Column(Text) + dashboard_title = Column(String(500)) + description = Column(Text) + json_metadata = Column(Text) + position_json = Column(MediumText()) + slug = Column(String(255)) + + +class Database(Base): + __tablename__ = 'dbs' + + id = Column(Integer, primary_key=True) + database_name = Column(String(250)) + extra = Column(Text) + force_ctas_schema = Column(String(250)) + sqlalchemy_uri = Column(String(1024)) + verbose_name = Column(String(250)) + + +class DruidCluster(Base): + __tablename__ = 'clusters' + + id = Column(Integer, primary_key=True) + broker_host = Column(String(255)) + broker_endpoint = Column(String(255)) + cluster_name = Column(String(250)) + verbose_name = Column(String(250)) + + +class DruidColumn(BaseColumnMixin, Base): + __tablename__ = 'columns' + + dimension_spec_json = Column(Text) + + +class DruidDatasource(BaseDatasourceMixin, Base): + __tablename__ = 'datasources' + + datasource_name = Column(String(255)) + default_endpoint = Column(Text) + fetch_values_from = Column(String(100)) + + +class DruidMetric(BaseMetricMixin, Base): + __tablename__ = 'metrics' + + json = Column(Text) + + +class Slice(Base): + __tablename__ = 'slices' + + id = Column(Integer, primary_key=True) + description = Column(Text) + params = Column(Text) + slice_name = Column(String(250)) + viz_type = Column(String(250)) + + +class SqlaTable(BaseDatasourceMixin, Base): + __tablename__ = 'tables' + + default_endpoint = Column(MediumText()) + fetch_values_predicate = Column(String(1000)) + main_dttm_col = Column(String(250)) + schema = Column(String(255)) + sql = Column(Text) + table_name = Column(String(250)) + template_params = Column(Text) + + +class SqlMetric(BaseMetricMixin, Base): + __tablename__ = 'sql_metrics' + + expression = Column(Text) + + +class TableColumn(BaseColumnMixin, Base): + __tablename__ = 'table_columns' + + database_expression = Column(String(255)) + expression = Column(Text) + python_date_format = Column(String(255)) + + +def upgrade(): + bind = op.get_bind() + session = db.Session(bind=bind) + + tables = [ + Annotation, + Dashboard, + Database, + DruidCluster, + DruidColumn, + DruidDatasource, + DruidMetric, + Slice, + SqlaTable, + SqlMetric, + TableColumn, + ] + + for table in tables: + for record in session.query(table).all(): + for col in record.__table__.columns.values(): + if not col.primary_key: + value = getattr(record, col.name) + + if value is not None and value.strip() == '': + setattr(record, col.name, None) + + session.commit() + + session.close() + + +def downgrade(): + pass diff --git a/superset/migrations/versions/db0c65b146bd_update_slice_model_json.py b/superset/migrations/versions/db0c65b146bd_update_slice_model_json.py index 642f5b5aefb21..760945f0f6074 100644 --- a/superset/migrations/versions/db0c65b146bd_update_slice_model_json.py +++ b/superset/migrations/versions/db0c65b146bd_update_slice_model_json.py @@ -32,7 +32,6 @@ from sqlalchemy import Column, Integer, String, Text from superset import db -from superset.legacy import cast_form_data Base = declarative_base() @@ -55,7 +54,6 @@ def upgrade(): for i, slc in enumerate(slices): try: d = json.loads(slc.params or '{}') - d = cast_form_data(d) slc.params = json.dumps(d, indent=2, sort_keys=True) session.merge(slc) session.commit() diff --git a/superset/migrations/versions/e9df189e5c7e_update_base_metrics.py b/superset/migrations/versions/e9df189e5c7e_update_base_metrics.py new file mode 100644 index 0000000000000..07a6c4d571767 --- /dev/null +++ b/superset/migrations/versions/e9df189e5c7e_update_base_metrics.py @@ -0,0 +1,169 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +"""update base metrics + +Note that the metrics table was previously partially modifed by revision +f231d82b9b26. + +Revision ID: e9df189e5c7e +Revises: 7f2635b51f5d +Create Date: 2018-07-20 15:57:48.118304 + +""" + +# revision identifiers, used by Alembic. +revision = 'e9df189e5c7e' +down_revision = '7f2635b51f5d' + +from alembic import op +from sqlalchemy import Column, engine, Integer, String, Text +from sqlalchemy.ext.declarative import declarative_base + +from superset import db +from superset.utils.core import generic_find_uq_constraint_name + +Base = declarative_base() + +conv = { + 'uq': 'uq_%(table_name)s_%(column_0_name)s', +} + + +class BaseMetricMixin: + id = Column(Integer, primary_key=True) + + +class DruidMetric(BaseMetricMixin, Base): + __tablename__ = 'metrics' + + datasource_id = Column(Integer) + + +class SqlMetric(BaseMetricMixin, Base): + __tablename__ = 'sql_metrics' + + table_id = Column(Integer) + + +def upgrade(): + bind = op.get_bind() + session = db.Session(bind=bind) + + # Delete the orphaned metrics records. + for record in session.query(DruidMetric).all(): + if record.datasource_id is None: + session.delete(record) + + session.commit() + + # Enforce that metrics.metric_name column be non-nullable. + with op.batch_alter_table('metrics') as batch_op: + batch_op.alter_column( + 'metric_name', + existing_type=String(255), + nullable=False, + ) + + # Enforce that metrics.json column be non-nullable. + with op.batch_alter_table('metrics') as batch_op: + batch_op.alter_column( + 'json', + existing_type=Text, + nullable=False, + ) + + # Delete the orphaned sql_metrics records. + for record in session.query(SqlMetric).all(): + if record.table_id is None: + session.delete(record) + + session.commit() + + # Reduce the size of the sql_metrics.metric_name column for constraint + # viability and enforce that it to be non-nullable. + with op.batch_alter_table('sql_metrics') as batch_op: + batch_op.alter_column( + 'metric_name', + existing_type=String(512), + nullable=False, + type_=String(255), + ) + + # Enforce that sql_metrics.expression column be non-nullable. + with op.batch_alter_table('sql_metrics') as batch_op: + batch_op.alter_column( + 'expression', + existing_type=Text, + nullable=False, + ) + + # Add the missing uniqueness constraint to the sql_metrics table. + with op.batch_alter_table('sql_metrics', naming_convention=conv) as batch_op: + batch_op.create_unique_constraint( + 'uq_sql_metrics_metric_name', + ['metric_name', 'table_id'], + ) + + +def downgrade(): + bind = op.get_bind() + insp = engine.reflection.Inspector.from_engine(bind) + + # Remove the missing uniqueness constraint from the sql_metrics table. + with op.batch_alter_table('sql_metrics', naming_convention=conv) as batch_op: + batch_op.drop_constraint( + generic_find_uq_constraint_name( + 'sql_metrics', + {'metric_name', 'table_id'}, + insp, + ) or 'uq_sql_metrics_table_id', + type_='unique', + ) + + # Restore the size of the sql_metrics.metric_name column and forego that it + # be non-nullable. + with op.batch_alter_table('sql_metrics') as batch_op: + batch_op.alter_column( + 'metric_name', + existing_type=String(255), + nullable=True, + type_=String(512), + ) + + # Forego that the sql_metrics.expression column be non-nullable. + with op.batch_alter_table('sql_metrics') as batch_op: + batch_op.alter_column( + 'expression', + existing_type=Text, + nullable=True, + ) + + # Forego that the metrics.metric_name column be non-nullable. + with op.batch_alter_table('metrics') as batch_op: + batch_op.alter_column( + 'metric_name', + existing_type=String(255), + nullable=True, + ) + + # Forego that the metrics.json column be non-nullable. + with op.batch_alter_table('metrics') as batch_op: + batch_op.alter_column( + 'json', + existing_type=Text, + nullable=True, + ) diff --git a/superset/models/core.py b/superset/models/core.py index 0486245a9f0df..fb5850c0fa1b0 100644 --- a/superset/models/core.py +++ b/superset/models/core.py @@ -243,6 +243,7 @@ def data(self): 'slice_name': self.slice_name, 'slice_url': self.slice_url, 'modified': self.modified(), + 'changed_on_humanized': self.changed_on_humanized, 'changed_on': self.changed_on.isoformat(), } diff --git a/superset/models/helpers.py b/superset/models/helpers.py index a1e9b3c61aadb..78b438d9f8f17 100644 --- a/superset/models/helpers.py +++ b/superset/models/helpers.py @@ -288,10 +288,13 @@ def changed_by_(self): def changed_on_(self): return Markup(f'{self.changed_on}') + @property + def changed_on_humanized(self): + return humanize.naturaltime(datetime.now() - self.changed_on) + @renders('changed_on') def modified(self): - time_str = humanize.naturaltime(datetime.now() - self.changed_on) - return Markup(f'{time_str}') + return Markup(f'{self.changed_on_humanized}') class QueryResult(object): diff --git a/superset/models/sql_lab.py b/superset/models/sql_lab.py index 93eae2fcfce53..2d23a6400536e 100644 --- a/superset/models/sql_lab.py +++ b/superset/models/sql_lab.py @@ -138,6 +138,14 @@ def name(self): tab = re.sub(r'\W+', '', tab) return f'sqllab_{tab}_{ts}' + @property + def database_name(self): + return self.database.name + + @property + def username(self): + return self.user.username + class SavedQuery(Model, AuditMixinNullable, ExtraJSONMixin): """ORM model for SQL query""" diff --git a/superset/security.py b/superset/security.py index 35545f22e0447..b30b2e516cbaa 100644 --- a/superset/security.py +++ b/superset/security.py @@ -68,7 +68,6 @@ class SupersetSecurityManager(SecurityManager): } ADMIN_ONLY_PERMISSIONS = { - 'all_database_access', 'can_sql_json', # TODO: move can_sql_json to sql_lab role 'can_override_role_permissions', 'can_sync_druid_source', @@ -82,17 +81,23 @@ class SupersetSecurityManager(SecurityManager): 'can_list', } - ALPHA_ONLY_PERMISSIONS = set([ + ALPHA_ONLY_PERMISSIONS = { 'muldelete', + 'all_database_access', 'all_datasource_access', - ]) + } - OBJECT_SPEC_PERMISSIONS = set([ + OBJECT_SPEC_PERMISSIONS = { 'database_access', 'schema_access', 'datasource_access', 'metric_access', - ]) + 'can_only_access_owned_queries', + } + + ACCESSIBLE_PERMS = { + 'can_userinfo', + } def get_schema_perm(self, database, schema): if schema: @@ -105,6 +110,17 @@ def can_access(self, permission_name, view_name): return self.is_item_public(permission_name, view_name) return self._has_view_access(user, permission_name, view_name) + def can_only_access_owned_queries(self) -> bool: + """ + can_access check for custom can_only_access_owned_queries permissions. + + :returns: True if current user can access custom permissions + """ + return self.can_access( + 'can_only_access_owned_queries', + 'can_only_access_owned_queries', + ) + def all_datasource_access(self): return self.can_access( 'all_datasource_access', 'all_datasource_access') @@ -266,6 +282,7 @@ def create_custom_permissions(self): # Global perms self.merge_perm('all_datasource_access', 'all_datasource_access') self.merge_perm('all_database_access', 'all_database_access') + self.merge_perm('can_only_access_owned_queries', 'can_only_access_owned_queries') def create_missing_perms(self): """Creates missing perms for datasources, schemas and metrics""" @@ -373,15 +390,21 @@ def is_alpha_only(self, pvm): pvm.permission.name in self.ALPHA_ONLY_PERMISSIONS ) + def is_accessible_to_all(self, pvm): + return pvm.permission.name in self.ACCESSIBLE_PERMS + def is_admin_pvm(self, pvm): return not self.is_user_defined_permission(pvm) def is_alpha_pvm(self, pvm): - return not (self.is_user_defined_permission(pvm) or self.is_admin_only(pvm)) + return ( + not (self.is_user_defined_permission(pvm) or self.is_admin_only(pvm)) or + self.is_accessible_to_all(pvm) + ) def is_gamma_pvm(self, pvm): return not (self.is_user_defined_permission(pvm) or self.is_admin_only(pvm) or - self.is_alpha_only(pvm)) + self.is_alpha_only(pvm)) or self.is_accessible_to_all(pvm) def is_sql_lab_pvm(self, pvm): return ( diff --git a/superset/translations/es/LC_MESSAGES/messages.mo b/superset/translations/es/LC_MESSAGES/messages.mo index f180b282c93d2..854495d3a6a9b 100644 Binary files a/superset/translations/es/LC_MESSAGES/messages.mo and b/superset/translations/es/LC_MESSAGES/messages.mo differ diff --git a/superset/translations/es/LC_MESSAGES/messages.po b/superset/translations/es/LC_MESSAGES/messages.po index 8277a9e005673..3c40e93569d31 100644 --- a/superset/translations/es/LC_MESSAGES/messages.po +++ b/superset/translations/es/LC_MESSAGES/messages.po @@ -767,7 +767,7 @@ msgstr "Claves de la tabla" #: superset/assets/javascripts/SqlLab/components/TableElement.jsx:119 #, python-format msgid "View keys & indexes (%s)" -msgstr "Ver claves e índices ($s)" +msgstr "Ver claves e índices (%s)" #: superset/assets/javascripts/SqlLab/components/TableElement.jsx:135 msgid "Sort columns alphabetically" diff --git a/superset/translations/pt_BR/LC_MESSAGES/messages.json b/superset/translations/pt_BR/LC_MESSAGES/messages.json index f2c675df55299..db0878e998d73 100644 --- a/superset/translations/pt_BR/LC_MESSAGES/messages.json +++ b/superset/translations/pt_BR/LC_MESSAGES/messages.json @@ -289,7 +289,7 @@ "Consulta sem título" ], "Copy of %s": [ - "Cópia de% s" + "Cópia de %s" ], "share query": [ "compartilhar consulta" @@ -592,7 +592,7 @@ "Erro" ], "Sorry, there was an error adding slices to this dashboard: %s": [ - "Desculpe, houve um erro ao adicionar fatias a este painel:% s" + "Desculpe, houve um erro ao adicionar fatias a este painel: %s" ], "Active Dashboard Filters": [ "Filtros Active Dashboard" @@ -709,7 +709,7 @@ "não pode estar vazio" ], "%s - untitled": [ - "% s - sem título" + "%s - sem título" ], "Edit slice properties": [ "Editar propriedades da fatia" @@ -823,7 +823,7 @@ "Erro ao buscar dados" ], "Select %s": [ - "Selecione% s" + "Selecione %s" ], "textarea": [ "textarea" @@ -841,7 +841,7 @@ "O mapa de atualização foi interrompido" ], "An error occurred while rendering the visualization: %s": [ - "Ocorreu um erro ao renderizar a visualização:% s" + "Ocorreu um erro ao renderizar a visualização: %s" ], "Perhaps your data has grown, your database is under unusual load, or you are simply querying a data source that is to large to be processed within the timeout range. If that is the case, we recommend that you summarize your data further.": [ "Talvez seus dados tenham crescido, seu banco de dados está sob carga incomum, ou você está simplesmente consultando uma fonte de dados que seja grande para ser processada dentro do intervalo de tempo limite. Se for esse o caso, recomendamos que você sintetize seus dados ainda mais." @@ -1966,7 +1966,7 @@ "O servidor não pôde ser alcançado. Você pode querer verificar sua conexão e tentar novamente." ], "An unknown error occurred. (Status: %s )": [ - "Ocorreu um erro desconhecido. (Status:% s)" + "Ocorreu um erro desconhecido. (Status: %s)" ], "Favorites": [ "" @@ -2020,7 +2020,7 @@ "" ], "Select [%s]": [ - "Selecione [% s]" + "Selecione [%s]" ], "No data was returned.": [ "Nenhum dado foi retornado." @@ -2630,4 +2630,4 @@ ] } } -} \ No newline at end of file +} diff --git a/superset/translations/pt_BR/LC_MESSAGES/messages.mo b/superset/translations/pt_BR/LC_MESSAGES/messages.mo index fb982333c6980..81fed17561b5f 100644 Binary files a/superset/translations/pt_BR/LC_MESSAGES/messages.mo and b/superset/translations/pt_BR/LC_MESSAGES/messages.mo differ diff --git a/superset/translations/pt_BR/LC_MESSAGES/messages.po b/superset/translations/pt_BR/LC_MESSAGES/messages.po index ca91b9640b9d1..fab78c6080829 100644 --- a/superset/translations/pt_BR/LC_MESSAGES/messages.po +++ b/superset/translations/pt_BR/LC_MESSAGES/messages.po @@ -497,7 +497,7 @@ msgstr "Consulta sem título" #: superset/assets/javascripts/SqlLab/reducers.js:44 #, python-format msgid "Copy of %s" -msgstr "Cópia de% s" +msgstr "Cópia de %s" #: superset/assets/javascripts/SqlLab/components/CopyQueryTabUrl.jsx:30 msgid "share query" @@ -937,7 +937,7 @@ msgstr "Erro" #: superset/assets/javascripts/dashboard/Dashboard.jsx:359 #, python-format msgid "Sorry, there was an error adding slices to this dashboard: %s" -msgstr "Desculpe, houve um erro ao adicionar fatias a este painel:% s" +msgstr "Desculpe, houve um erro ao adicionar fatias a este painel: %s" #: superset/assets/javascripts/dashboard/components/CodeModal.jsx:35 msgid "Active Dashboard Filters" @@ -1101,7 +1101,7 @@ msgstr "não pode estar vazio" #: superset/assets/javascripts/explore/components/ChartContainer.jsx:180 #, python-format msgid "%s - untitled" -msgstr "% s - sem título" +msgstr "%s - sem título" #: superset/assets/javascripts/explore/components/ChartContainer.jsx:287 msgid "Edit slice properties" @@ -1283,7 +1283,7 @@ msgstr "Erro ao buscar dados" #: superset/assets/javascripts/explore/components/controls/SelectControl.jsx:155 #, python-format msgid "Select %s" -msgstr "Selecione% s" +msgstr "Selecione %s" #: superset/assets/javascripts/explore/components/controls/TextAreaControl.jsx:63 msgid "textarea" @@ -1309,7 +1309,7 @@ msgstr "O mapa de atualização foi interrompido" #: superset/assets/javascripts/modules/superset.js:226 #, python-format msgid "An error occurred while rendering the visualization: %s" -msgstr "Ocorreu um erro ao renderizar a visualização:% s" +msgstr "Ocorreu um erro ao renderizar a visualização: %s" #: superset/assets/javascripts/explore/reducers/chartReducer.js:47 msgid "" @@ -3071,7 +3071,7 @@ msgstr "" #: superset/assets/javascripts/modules/superset.js:135 #, python-format msgid "An unknown error occurred. (Status: %s )" -msgstr "Ocorreu um erro desconhecido. (Status:% s)" +msgstr "Ocorreu um erro desconhecido. (Status: %s)" #: superset/assets/javascripts/profile/components/App.jsx:24 msgid "Favorites" @@ -3150,7 +3150,7 @@ msgstr "" #: superset/assets/visualizations/filter_box.jsx:181 #, python-format msgid "Select [%s]" -msgstr "Selecione [% s]" +msgstr "Selecione [%s]" #: superset/connectors/druid/models.py:1073 msgid "No data was returned." diff --git a/superset/utils/cache.py b/superset/utils/cache.py index 569e39728c2b5..4c44d421f0613 100644 --- a/superset/utils/cache.py +++ b/superset/utils/cache.py @@ -20,7 +20,7 @@ from superset import tables_cache -def view_cache_key(*unused_args, **unused_kwargs): +def view_cache_key(*unused_args, **unused_kwargs) -> str: args_hash = hash(frozenset(request.args.items())) return 'view/{}/{}'.format(request.path, args_hash) diff --git a/superset/utils/core.py b/superset/utils/core.py index be8bc08b3e7b0..122998e2fea0e 100644 --- a/superset/utils/core.py +++ b/superset/utils/core.py @@ -31,7 +31,8 @@ import signal import smtplib import sys -from typing import Optional, Tuple +from time import struct_time +from typing import List, Optional, Tuple import uuid import zlib @@ -39,7 +40,8 @@ import celery from dateutil.parser import parse from dateutil.relativedelta import relativedelta -from flask import flash, g, Markup, render_template +from flask import flash, Flask, g, Markup, render_template +from flask_appbuilder.security.sqla.models import User from flask_babel import gettext as __ from flask_babel import lazy_gettext as _ from flask_caching import Cache @@ -51,6 +53,7 @@ import sqlalchemy as sa from sqlalchemy import event, exc, select, Text from sqlalchemy.dialects.mysql import MEDIUMTEXT +from sqlalchemy.sql.type_api import Variant from sqlalchemy.types import TEXT, TypeDecorator from superset.exceptions import SupersetException, SupersetTimeoutException @@ -138,11 +141,11 @@ def wrapper(f): return wrapper -def js_string_to_python(item): +def js_string_to_python(item: str) -> Optional[str]: return None if item in ('null', 'undefined') else item -def string_to_num(s): +def string_to_num(s: str): """Converts a string to an int/float Returns ``None`` if it can't be converted @@ -182,7 +185,7 @@ def __init__(self, **args): } -def list_minus(l, minus): +def list_minus(l: List, minus: List) -> List: """Returns l without what is in minus >>> list_minus([1, 2, 3], [2]) @@ -230,7 +233,7 @@ def parse_human_datetime(s): return dttm -def dttm_from_timtuple(d): +def dttm_from_timtuple(d: struct_time) -> datetime: return datetime( d.tm_year, d.tm_mon, d.tm_mday, d.tm_hour, d.tm_min, d.tm_sec) @@ -284,7 +287,7 @@ def default(self, o): return json.JSONEncoder.default(self, o) -def parse_human_timedelta(s): +def parse_human_timedelta(s: str): """ Returns ``datetime.datetime`` from natural language time deltas @@ -349,7 +352,7 @@ def base_json_conv(obj): return '[bytes]' -def json_iso_dttm_ser(obj, pessimistic=False): +def json_iso_dttm_ser(obj, pessimistic: Optional[bool] = False): """ json serializer that deals with dates @@ -420,7 +423,7 @@ def error_msg_from_exception(e): return msg or '{}'.format(e) -def markdown(s, markup_wrap=False): +def markdown(s: str, markup_wrap: Optional[bool] = False) -> str: safe_markdown_tags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'b', 'i', 'strong', 'em', 'tt', 'p', 'br', 'span', 'div', 'blockquote', 'code', 'hr', 'ul', 'ol', @@ -438,7 +441,7 @@ def markdown(s, markup_wrap=False): return s -def readfile(file_path): +def readfile(file_path: str) -> Optional[str]: with open(file_path) as f: content = f.read() return content @@ -677,17 +680,18 @@ def send_MIME_email(e_from, e_to, mime_msg, config, dryrun=False): logging.info(mime_msg.as_string()) -def get_email_address_list(address_string): +def get_email_address_list(address_string: str) -> List[str]: + address_string_list: List[str] = [] if isinstance(address_string, str): if ',' in address_string: - address_string = address_string.split(',') + address_string_list = address_string.split(',') elif '\n' in address_string: - address_string = address_string.split('\n') + address_string_list = address_string.split('\n') elif ';' in address_string: - address_string = address_string.split(';') + address_string_list = address_string.split(';') else: - address_string = [address_string] - return [x.strip() for x in address_string if x.strip()] + address_string_list = [address_string] + return [x.strip() for x in address_string_list if x.strip()] def choicify(values): @@ -695,11 +699,13 @@ def choicify(values): return [(v, v) for v in values] -def setup_cache(app, cache_config): +def setup_cache(app: Flask, cache_config) -> Optional[Cache]: """Setup the flask-cache on a flask app""" if cache_config and cache_config.get('CACHE_TYPE') != 'null': return Cache(app, config=cache_config) + return None + def zlib_compress(data): """ @@ -766,7 +772,7 @@ def to_adhoc(filt, expressionType='SIMPLE', clause='where'): return result -def merge_extra_filters(form_data): +def merge_extra_filters(form_data: dict): # extra_filters are temporary/contextual filters (using the legacy constructs) # that are external to the slice definition. We use those for dynamic # interactive filters like the ones emitted by the "Filter Box" visualization. @@ -837,7 +843,7 @@ def get_filter_key(f): del form_data['extra_filters'] -def merge_request_params(form_data, params): +def merge_request_params(form_data: dict, params: dict): url_params = {} for key, value in params.items(): if key in ('form_data', 'r'): @@ -846,12 +852,12 @@ def merge_request_params(form_data, params): form_data['url_params'] = url_params -def get_update_perms_flag(): +def get_update_perms_flag() -> bool: val = os.environ.get('SUPERSET_UPDATE_PERMS') return val.lower() not in ('0', 'false', 'no') if val else True -def user_label(user): +def user_label(user: User) -> Optional[str]: """Given a user ORM FAB object, returns a label""" if user: if user.first_name and user.last_name: @@ -859,6 +865,8 @@ def user_label(user): else: return user.username + return None + def get_or_create_main_db(): from superset import conf, db @@ -887,7 +895,7 @@ def get_main_database(session): ) -def is_adhoc_metric(metric): +def is_adhoc_metric(metric) -> bool: return ( isinstance(metric, dict) and ( @@ -913,7 +921,7 @@ def get_metric_names(metrics): return [get_metric_name(metric) for metric in metrics] -def ensure_path_exists(path): +def ensure_path_exists(path: str): try: os.makedirs(path) except OSError as exc: @@ -997,7 +1005,7 @@ def get_since_until(time_range: Optional[str] = None, return since, until # noqa: T400 -def add_ago_to_since(since): +def add_ago_to_since(since: str) -> str: """ Backwards compatibility hack. Without this slices with since: 7 days will be treated as 7 days in the future. @@ -1072,17 +1080,17 @@ def split_adhoc_filters_into_base_filters(fd): fd['filters'] = simple_where_filters -def get_username(): +def get_username() -> Optional[str]: """Get username if within the flask context, otherwise return noffin'""" try: return g.user.username except Exception: - pass + return None -def MediumText(): +def MediumText() -> Variant: return Text().with_variant(MEDIUMTEXT(), 'mysql') -def shortid(): +def shortid() -> str: return '{}'.format(uuid.uuid4())[-12:] diff --git a/superset/views/base.py b/superset/views/base.py index 071f2b335b658..113b9c68e3975 100644 --- a/superset/views/base.py +++ b/superset/views/base.py @@ -19,16 +19,20 @@ import functools import logging import traceback +from typing import Any, Dict from flask import abort, flash, g, get_flashed_messages, redirect, Response from flask_appbuilder import BaseView, ModelView from flask_appbuilder.actions import action +from flask_appbuilder.forms import DynamicForm from flask_appbuilder.models.sqla.filters import BaseFilter from flask_appbuilder.widgets import ListWidget from flask_babel import get_locale from flask_babel import gettext as __ from flask_babel import lazy_gettext as _ +from flask_wtf.form import FlaskForm import simplejson as json +from wtforms.fields.core import Field, UnboundField import yaml from superset import conf, db, get_feature_flags, security_manager @@ -368,3 +372,26 @@ def check_ownership(obj, raise_if_false=True): raise security_exception else: return False + + +def bind_field( + self, + form: DynamicForm, + unbound_field: UnboundField, + options: Dict[Any, Any], + ) -> Field: + """ + Customize how fields are bound by stripping all whitespace. + + :param form: The form + :param unbound_field: The unbound field + :param options: The field options + :returns: The bound field + """ + + filters = unbound_field.kwargs.get('filters', []) + filters.append(lambda x: x.strip() if isinstance(x, str) else x) + return unbound_field.bind(form=form, filters=filters, **options) + + +FlaskForm.Meta.bind_field = bind_field diff --git a/superset/views/core.py b/superset/views/core.py index 2e3980f894e7c..f5de14673df2c 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -22,6 +22,7 @@ import re import time import traceback +from typing import List # noqa: F401 from urllib import parse from flask import ( @@ -50,6 +51,7 @@ from superset.exceptions import SupersetException from superset.forms import CsvToDatabaseForm from superset.jinja_context import get_template_processor +from superset.legacy import update_time_range import superset.models.core as models from superset.models.sql_lab import Query from superset.models.user_attributes import UserAttribute @@ -82,7 +84,7 @@ 'The access requests seem to have been deleted') USER_MISSING_ERR = __('The user seems to have been deleted') -FORM_DATA_KEY_BLACKLIST = [] +FORM_DATA_KEY_BLACKLIST: List[str] = [] if not config.get('ENABLE_JAVASCRIPT_CONTROLS'): FORM_DATA_KEY_BLACKLIST = [ 'js_tooltip', @@ -498,9 +500,6 @@ class SliceModelView(SupersetModelView, DeleteMixin): # noqa edit_title = _('Edit Chart') can_add = False - label_columns = { - 'datasource_link': _('Datasource'), - } search_columns = ( 'slice_name', 'description', 'viz_type', 'datasource_name', 'owners', ) @@ -582,7 +581,8 @@ class SliceAsync(SliceModelView): # noqa route_base = '/sliceasync' list_columns = [ 'id', 'slice_link', 'viz_type', 'slice_name', - 'creator', 'modified', 'icons'] + 'creator', 'modified', 'icons', 'changed_on_humanized', + ] label_columns = { 'icons': ' ', 'slice_link': _('Chart'), @@ -598,7 +598,8 @@ class SliceAddView(SliceModelView): # noqa 'id', 'slice_name', 'slice_url', 'edit_url', 'viz_type', 'params', 'description', 'description_markeddown', 'datasource_id', 'datasource_type', 'datasource_name_text', 'datasource_link', - 'owners', 'modified', 'changed_on'] + 'owners', 'modified', 'changed_on', 'changed_on_humanized', + ] appbuilder.add_view_no_menu(SliceAddView) @@ -1049,6 +1050,81 @@ def clean_fulfilled_requests(session): session.commit() return redirect('/accessrequestsmodelview/list/') + def get_form_data(self, slice_id=None, use_slice_data=False): + form_data = {} + post_data = request.form.get('form_data') + request_args_data = request.args.get('form_data') + # Supporting POST + if post_data: + form_data.update(json.loads(post_data)) + # request params can overwrite post body + if request_args_data: + form_data.update(json.loads(request_args_data)) + + url_id = request.args.get('r') + if url_id: + saved_url = db.session.query(models.Url).filter_by(id=url_id).first() + if saved_url: + url_str = parse.unquote_plus( + saved_url.url.split('?')[1][10:], encoding='utf-8', errors=None) + url_form_data = json.loads(url_str) + # allow form_date in request override saved url + url_form_data.update(form_data) + form_data = url_form_data + + form_data = { + k: v + for k, v in form_data.items() + if k not in FORM_DATA_KEY_BLACKLIST + } + + # When a slice_id is present, load from DB and override + # the form_data from the DB with the other form_data provided + slice_id = form_data.get('slice_id') or slice_id + slc = None + + # Check if form data only contains slice_id + contains_only_slc_id = not any(key != 'slice_id' for key in form_data) + + # Include the slice_form_data if request from explore or slice calls + # or if form_data only contains slice_id + if slice_id and (use_slice_data or contains_only_slc_id): + slc = db.session.query(models.Slice).filter_by(id=slice_id).one_or_none() + if slc: + slice_form_data = slc.form_data.copy() + slice_form_data.update(form_data) + form_data = slice_form_data + + update_time_range(form_data) + + return form_data, slc + + def get_viz( + self, + slice_id=None, + form_data=None, + datasource_type=None, + datasource_id=None, + force=False, + ): + if slice_id: + slc = ( + db.session.query(models.Slice) + .filter_by(id=slice_id) + .one() + ) + return slc.get_viz() + else: + viz_type = form_data.get('viz_type', 'table') + datasource = ConnectorRegistry.get_datasource( + datasource_type, datasource_id, db.session) + viz_obj = viz.viz_types[viz_type]( + datasource, + form_data=form_data, + force=force, + ) + return viz_obj + @has_access @expose('/slice//') def slice(self, slice_id): @@ -1418,6 +1494,7 @@ def save_or_overwrite_slice( 'can_overwrite': is_owner(slc, g.user), 'form_data': slc.form_data, 'slice': slc.data, + 'dashboard_id': dash.id if dash else None, } if request.args.get('goto_dash') == 'true': @@ -2705,10 +2782,21 @@ def queries_call(self, last_updated_ms): @has_access @expose('/search_queries') @log_this - def search_queries(self): - """Search for queries.""" + def search_queries(self) -> Response: + """ + Search for previously run sqllab queries. Used for Sqllab Query Search + page /superset/sqllab#search. + + Custom permission can_only_search_queries_owned restricts queries + to only queries run by current user. + + :returns: Response with list of sql query dicts + """ query = db.session.query(Query) - search_user_id = request.args.get('user_id') + if security_manager.can_only_access_owned_queries(): + search_user_id = g.user.get_user_id() + else: + search_user_id = request.args.get('user_id') database_id = request.args.get('database_id') search_text = request.args.get('search_text') status = request.args.get('status') @@ -2717,7 +2805,7 @@ def search_queries(self): to_time = request.args.get('to') if search_user_id: - # Filter on db Id + # Filter on user_id query = query.filter(Query.user_id == search_user_id) if database_id: diff --git a/superset/views/schedules.py b/superset/views/schedules.py index 4dae3cbfb7292..6fdae77265219 100644 --- a/superset/views/schedules.py +++ b/superset/views/schedules.py @@ -90,9 +90,12 @@ class EmailScheduleView(SupersetModelView, DeleteMixin): edit_form_extra_fields = add_form_extra_fields def process_form(self, form, is_created): - recipients = form.test_email_recipients.data.strip() or None + if form.test_email_recipients.data: + test_email_recipients = form.test_email_recipients.data.strip() + else: + test_email_recipients = None self._extra_data['test_email'] = form.test_email.data - self._extra_data['test_email_recipients'] = recipients + self._extra_data['test_email_recipients'] = test_email_recipients def pre_add(self, obj): try: @@ -111,7 +114,7 @@ def pre_update(self, obj): def post_add(self, obj): # Schedule a test mail if the user requested for it. if self._extra_data['test_email']: - recipients = self._extra_data['test_email_recipients'] + recipients = self._extra_data['test_email_recipients'] or obj.recipients args = (self.schedule_type, obj.id) kwargs = dict(recipients=recipients) schedule_email_report.apply_async(args=args, kwargs=kwargs) diff --git a/superset/views/sql_lab.py b/superset/views/sql_lab.py index 0c8e87f168e7c..adbdd46c6dfde 100644 --- a/superset/views/sql_lab.py +++ b/superset/views/sql_lab.py @@ -15,16 +15,38 @@ # specific language governing permissions and limitations # under the License. # pylint: disable=C,R,W +from typing import Callable + from flask import g, redirect from flask_appbuilder import expose from flask_appbuilder.models.sqla.interface import SQLAInterface from flask_appbuilder.security.decorators import has_access from flask_babel import gettext as __ from flask_babel import lazy_gettext as _ +from flask_sqlalchemy import BaseQuery -from superset import appbuilder +from superset import appbuilder, security_manager from superset.models.sql_lab import Query, SavedQuery -from .base import BaseSupersetView, DeleteMixin, SupersetModelView +from .base import BaseSupersetView, DeleteMixin, SupersetFilter, SupersetModelView + + +class QueryFilter(SupersetFilter): + def apply( + self, + query: BaseQuery, + func: Callable) -> BaseQuery: + """ + Filter queries to only those owned by current user if + can_only_access_owned_queries permission is set. + + :returns: query + """ + if security_manager.can_only_access_owned_queries(): + query = ( + query + .filter(Query.user_id == g.user.get_user_id()) + ) + return query class QueryView(SupersetModelView): @@ -35,10 +57,12 @@ class QueryView(SupersetModelView): add_title = _('Add Query') edit_title = _('Edit Query') - list_columns = ['user', 'database', 'status', 'start_time', 'end_time'] + list_columns = ['username', 'database_name', 'status', 'start_time', 'end_time'] + base_filters = [['id', QueryFilter, lambda: []]] label_columns = { 'user': _('User'), - 'database': _('Database'), + 'username': _('User'), + 'database_name': _('Database'), 'status': _('Status'), 'start_time': _('Start Time'), 'end_time': _('End Time'), diff --git a/superset/views/utils.py b/superset/views/utils.py index 74171d1e48a98..bb934a11260ba 100644 --- a/superset/views/utils.py +++ b/superset/views/utils.py @@ -24,7 +24,7 @@ from superset import app, db, viz from superset.connectors.connector_registry import ConnectorRegistry -from superset.legacy import cast_form_data, update_time_range +from superset.legacy import update_time_range import superset.models.core as models @@ -138,10 +138,6 @@ def get_form_data(slice_id=None, use_slice_data=False): url_form_data.update(form_data) form_data = url_form_data - if request.args.get('viz_type'): - # Converting old URLs - form_data = cast_form_data(form_data) - form_data = { k: v for k, v in form_data.items() diff --git a/superset/viz.py b/superset/viz.py index ce8c720342f3b..3e2e838c58321 100644 --- a/superset/viz.py +++ b/superset/viz.py @@ -518,7 +518,7 @@ def should_be_timeseries(self): return fd.get('include_time') def query_obj(self): - d = super(TableViz, self).query_obj() + d = super().query_obj() fd = self.form_data if fd.get('all_columns') and (fd.get('groupby') or fd.get('metrics')): @@ -610,7 +610,7 @@ class TimeTableViz(BaseViz): is_timeseries = True def query_obj(self): - d = super(TimeTableViz, self).query_obj() + d = super().query_obj() fd = self.form_data if not fd.get('metrics'): @@ -653,7 +653,7 @@ class PivotTableViz(BaseViz): is_timeseries = False def query_obj(self): - d = super(PivotTableViz, self).query_obj() + d = super().query_obj() groupby = self.form_data.get('groupby') columns = self.form_data.get('columns') metrics = self.form_data.get('metrics') @@ -747,7 +747,7 @@ class WordCloudViz(BaseViz): is_timeseries = False def query_obj(self): - d = super(WordCloudViz, self).query_obj() + d = super().query_obj() d['groupby'] = [self.form_data.get('series')] return d @@ -832,7 +832,7 @@ def get_data(self, df): } def query_obj(self): - d = super(CalHeatmapViz, self).query_obj() + d = super().query_obj() fd = self.form_data d['metrics'] = fd.get('metrics') return d @@ -943,7 +943,7 @@ class BubbleViz(NVD3Viz): def query_obj(self): form_data = self.form_data - d = super(BubbleViz, self).query_obj() + d = super().query_obj() d['groupby'] = [ form_data.get('entity'), ] @@ -956,11 +956,11 @@ def query_obj(self): self.series = form_data.get('series') or self.entity d['row_limit'] = form_data.get('limit') - d['metrics'] = [ + d['metrics'] = list(set([ self.z_metric, self.x_metric, self.y_metric, - ] + ])) if not all(d['metrics'] + [self.entity]): raise Exception(_('Pick a metric for x, y and size')) return d @@ -993,7 +993,7 @@ class BulletViz(NVD3Viz): def query_obj(self): form_data = self.form_data - d = super(BulletViz, self).query_obj() + d = super().query_obj() self.metric = form_data.get('metric') def as_strings(field): @@ -1041,7 +1041,7 @@ class BigNumberViz(BaseViz): is_timeseries = True def query_obj(self): - d = super(BigNumberViz, self).query_obj() + d = super().query_obj() metric = self.form_data.get('metric') if not metric: raise Exception(_('Pick a metric!')) @@ -1060,7 +1060,7 @@ class BigNumberTotalViz(BaseViz): is_timeseries = False def query_obj(self): - d = super(BigNumberTotalViz, self).query_obj() + d = super().query_obj() metric = self.form_data.get('metric') if not metric: raise Exception(_('Pick a metric!')) @@ -1309,7 +1309,7 @@ class NVD3DualLineViz(NVD3Viz): is_timeseries = True def query_obj(self): - d = super(NVD3DualLineViz, self).query_obj() + d = super().query_obj() m1 = self.form_data.get('metric') m2 = self.form_data.get('metric_2') d['metrics'] = [m1, m2] @@ -1393,7 +1393,7 @@ class NVD3TimePivotViz(NVD3TimeSeriesViz): verbose_name = _('Time Series - Period Pivot') def query_obj(self): - d = super(NVD3TimePivotViz, self).query_obj() + d = super().query_obj() d['metrics'] = [self.form_data.get('metric')] return d @@ -1475,7 +1475,7 @@ class HistogramViz(BaseViz): def query_obj(self): """Returns the query object for this visualization""" - d = super(HistogramViz, self).query_obj() + d = super().query_obj() d['row_limit'] = self.form_data.get( 'row_limit', int(config.get('VIZ_ROW_LIMIT'))) numeric_columns = self.form_data.get('all_columns_x') @@ -1521,7 +1521,7 @@ class DistributionBarViz(DistributionPieViz): is_timeseries = False def query_obj(self): - d = super(DistributionBarViz, self).query_obj() # noqa + d = super().query_obj() # noqa fd = self.form_data if ( len(d['groupby']) < @@ -1602,7 +1602,7 @@ def get_data(self, df): return json.loads(df.to_json(orient='values')) def query_obj(self): - qry = super(SunburstViz, self).query_obj() + qry = super().query_obj() fd = self.form_data qry['metrics'] = [fd['metric']] secondary_metric = fd.get('secondary_metric') @@ -1621,7 +1621,7 @@ class SankeyViz(BaseViz): credits = 'd3-sankey on npm' def query_obj(self): - qry = super(SankeyViz, self).query_obj() + qry = super().query_obj() if len(qry['groupby']) != 2: raise Exception(_('Pick exactly 2 columns as [Source / Target]')) qry['metrics'] = [ @@ -1672,7 +1672,7 @@ class DirectedForceViz(BaseViz): is_timeseries = False def query_obj(self): - qry = super(DirectedForceViz, self).query_obj() + qry = super().query_obj() if len(self.form_data['groupby']) != 2: raise Exception(_("Pick exactly 2 columns to 'Group By'")) qry['metrics'] = [self.form_data['metric']] @@ -1693,7 +1693,7 @@ class ChordViz(BaseViz): is_timeseries = False def query_obj(self): - qry = super(ChordViz, self).query_obj() + qry = super().query_obj() fd = self.form_data qry['groupby'] = [fd.get('groupby'), fd.get('columns')] qry['metrics'] = [utils.get_metric_name(fd.get('metric'))] @@ -1726,7 +1726,7 @@ class CountryMapViz(BaseViz): credits = 'From bl.ocks.org By john-guerra' def query_obj(self): - qry = super(CountryMapViz, self).query_obj() + qry = super().query_obj() qry['metrics'] = [ self.form_data['metric']] qry['groupby'] = [self.form_data['entity']] @@ -1754,7 +1754,7 @@ class WorldMapViz(BaseViz): credits = 'datamaps on npm' def query_obj(self): - qry = super(WorldMapViz, self).query_obj() + qry = super().query_obj() qry['groupby'] = [self.form_data['entity']] return qry @@ -1812,7 +1812,7 @@ def query_obj(self): return None def run_extra_queries(self): - qry = super(FilterBoxViz, self).query_obj() + qry = super().query_obj() filters = self.form_data.get('filter_configs') or [] qry['row_limit'] = self.filter_row_limit self.dataframes = {} @@ -1890,7 +1890,7 @@ class ParallelCoordinatesViz(BaseViz): is_timeseries = False def query_obj(self): - d = super(ParallelCoordinatesViz, self).query_obj() + d = super().query_obj() fd = self.form_data d['groupby'] = [fd.get('series')] return d @@ -1911,7 +1911,7 @@ class HeatmapViz(BaseViz): 'bl.ocks.org') def query_obj(self): - d = super(HeatmapViz, self).query_obj() + d = super().query_obj() fd = self.form_data d['metrics'] = [fd.get('metric')] d['groupby'] = [fd.get('all_columns_x'), fd.get('all_columns_y')] @@ -1977,7 +1977,7 @@ class MapboxViz(BaseViz): 'Mapbox GL JS') def query_obj(self): - d = super(MapboxViz, self).query_obj() + d = super().query_obj() fd = self.form_data label_col = fd.get('mapbox_label') @@ -2235,7 +2235,7 @@ def query_obj(self): if fd.get('filter_nulls', True): self.add_null_filters() - d = super(BaseDeckGLViz, self).query_obj() + d = super().query_obj() gb = [] for key in self.spatial_control_keys: @@ -2301,7 +2301,7 @@ def query_obj(self): fd.get('time_grain_sqla') or fd.get('granularity')) self.point_radius_fixed = ( fd.get('point_radius_fixed') or {'type': 'fix', 'value': 500}) - return super(DeckScatterViz, self).query_obj() + return super().query_obj() def get_metrics(self): self.metric = None @@ -2328,7 +2328,7 @@ def get_data(self, df): self.dim = self.form_data.get('dimension') if self.point_radius_fixed.get('type') != 'metric': self.fixed_value = self.point_radius_fixed.get('value') - return super(DeckScatterViz, self).get_data(df) + return super().get_data(df) class DeckScreengrid(BaseDeckGLViz): @@ -2343,7 +2343,7 @@ class DeckScreengrid(BaseDeckGLViz): def query_obj(self): fd = self.form_data self.is_timeseries = fd.get('time_grain_sqla') or fd.get('granularity') - return super(DeckScreengrid, self).query_obj() + return super().query_obj() def get_properties(self, d): return { @@ -2354,7 +2354,7 @@ def get_properties(self, d): def get_data(self, df): self.metric_label = utils.get_metric_name(self.metric) - return super(DeckScreengrid, self).get_data(df) + return super().get_data(df) class DeckGrid(BaseDeckGLViz): @@ -2373,7 +2373,7 @@ def get_properties(self, d): def get_data(self, df): self.metric_label = utils.get_metric_name(self.metric) - return super(DeckGrid, self).get_data(df) + return super().get_data(df) def geohash_to_json(geohash_code): @@ -2504,7 +2504,7 @@ class DeckPathViz(BaseDeckGLViz): def query_obj(self): fd = self.form_data self.is_timeseries = fd.get('time_grain_sqla') or fd.get('granularity') - d = super(DeckPathViz, self).query_obj() + d = super().query_obj() self.metric = fd.get('metric') line_col = fd.get('line_column') if d['metrics']: @@ -2555,7 +2555,7 @@ def query_obj(self): fd = self.form_data self.elevation = ( fd.get('point_radius_fixed') or {'type': 'fix', 'value': 500}) - return super(DeckPolygon, self).query_obj() + return super().query_obj() def get_metrics(self): metrics = [self.form_data.get('metric')] @@ -2564,7 +2564,7 @@ def get_metrics(self): return [metric for metric in metrics if metric] def get_properties(self, d): - super(DeckPolygon, self).get_properties(d) + super().get_properties(d) fd = self.form_data elevation = fd['point_radius_fixed']['value'] type_ = fd['point_radius_fixed']['type'] @@ -2599,7 +2599,7 @@ class DeckGeoJson(BaseDeckGLViz): verbose_name = _('Deck.gl - GeoJSON') def query_obj(self): - d = super(DeckGeoJson, self).query_obj() + d = super().query_obj() d['columns'] += [self.form_data.get('geojson')] d['metrics'] = [] d['groupby'] = [] @@ -2623,7 +2623,7 @@ def query_obj(self): fd = self.form_data self.is_timeseries = bool( fd.get('time_grain_sqla') or fd.get('granularity')) - return super(DeckArc, self).query_obj() + return super().query_obj() def get_properties(self, d): dim = self.form_data.get('dimension') @@ -2635,7 +2635,7 @@ def get_properties(self, d): } def get_data(self, df): - d = super(DeckArc, self).get_data(df) + d = super().get_data(df) return { 'features': d['features'], @@ -2653,7 +2653,7 @@ class EventFlowViz(BaseViz): is_timeseries = True def query_obj(self): - query = super(EventFlowViz, self).query_obj() + query = super().query_obj() form_data = self.form_data event_key = form_data.get('all_columns_x') @@ -2723,7 +2723,7 @@ def get_data(self, df): """ fd = self.form_data groups = fd.get('groupby') - metrics = fd.get('metrics') + metrics = self.metric_labels df = df.pivot_table( index=DTTM_ALIAS, columns=groups, @@ -2768,7 +2768,7 @@ class RoseViz(NVD3TimeSeriesViz): is_timeseries = True def get_data(self, df): - data = super(RoseViz, self).get_data(df) + data = super().get_data(df) result = {} for datum in data: key = datum['key'] @@ -2796,7 +2796,7 @@ class PartitionViz(NVD3TimeSeriesViz): verbose_name = _('Partition Diagram') def query_obj(self): - query_obj = super(PartitionViz, self).query_obj() + query_obj = super().query_obj() time_op = self.form_data.get('time_series_option', 'not_time') # Return time series data if the user specifies so query_obj['is_timeseries'] = time_op != 'not_time' diff --git a/tests/core_tests.py b/tests/core_tests.py index 00e83ace58fae..f021e9267a1e4 100644 --- a/tests/core_tests.py +++ b/tests/core_tests.py @@ -189,7 +189,6 @@ def assert_admin_view_menus_in(role_name, assert_func): assert_func('ResetPasswordView', view_menus) assert_func('RoleModelView', view_menus) assert_func('Security', view_menus) - assert_func('UserDBModelView', view_menus) assert_func('SQL Lab', view_menus) diff --git a/tests/dict_import_export_tests.py b/tests/dict_import_export_tests.py index 50cb0f7cbdc8d..f1f93fa64f89e 100644 --- a/tests/dict_import_export_tests.py +++ b/tests/dict_import_export_tests.py @@ -72,7 +72,7 @@ def create_table( 'params': json.dumps(params), 'columns': [{'column_name': c} for c in cols_names], - 'metrics': [{'metric_name': c} for c in metric_names], + 'metrics': [{'metric_name': c, 'expression': ''} for c in metric_names], } table = SqlaTable( @@ -84,7 +84,7 @@ def create_table( for col_name in cols_names: table.columns.append(TableColumn(column_name=col_name)) for metric_name in metric_names: - table.metrics.append(SqlMetric(metric_name=metric_name)) + table.metrics.append(SqlMetric(metric_name=metric_name, expression='')) return table, dict_rep def create_druid_datasource( @@ -98,7 +98,7 @@ def create_druid_datasource( 'id': id, 'params': json.dumps(params), 'columns': [{'column_name': c} for c in cols_names], - 'metrics': [{'metric_name': c} for c in metric_names], + 'metrics': [{'metric_name': c, 'json': '{}'} for c in metric_names], } datasource = DruidDatasource( diff --git a/tests/import_export_tests.py b/tests/import_export_tests.py index ad1aa908682f0..f6d04426d73ff 100644 --- a/tests/import_export_tests.py +++ b/tests/import_export_tests.py @@ -113,7 +113,7 @@ def create_table( table.columns.append( TableColumn(column_name=col_name)) for metric_name in metric_names: - table.metrics.append(SqlMetric(metric_name=metric_name)) + table.metrics.append(SqlMetric(metric_name=metric_name, expression='')) return table def create_druid_datasource( @@ -130,7 +130,7 @@ def create_druid_datasource( DruidColumn(column_name=col_name)) for metric_name in metric_names: datasource.metrics.append(DruidMetric( - metric_name=metric_name)) + metric_name=metric_name, json='{}')) return datasource def get_slice(self, slc_id): diff --git a/tests/security_tests.py b/tests/security_tests.py index 3530cf86e4ee4..868a8b53ae66d 100644 --- a/tests/security_tests.py +++ b/tests/security_tests.py @@ -76,6 +76,7 @@ def assert_can_gamma(self, perm_set): self.assertIn(('can_slice', 'Superset'), perm_set) self.assertIn(('can_explore', 'Superset'), perm_set) self.assertIn(('can_explore_json', 'Superset'), perm_set) + self.assertIn(('can_userinfo', 'UserDBModelView'), perm_set) def assert_can_alpha(self, perm_set): self.assert_can_all('SqlMetricInlineView', perm_set) @@ -129,9 +130,6 @@ def test_is_admin_only(self): self.assertTrue(security_manager.is_admin_only( security_manager.find_permission_view_menu( 'can_approve', 'Superset'))) - self.assertTrue(security_manager.is_admin_only( - security_manager.find_permission_view_menu( - 'all_database_access', 'all_database_access'))) def test_is_alpha_only(self): self.assertFalse(security_manager.is_alpha_only( @@ -148,6 +146,9 @@ def test_is_alpha_only(self): self.assertTrue(security_manager.is_alpha_only( security_manager.find_permission_view_menu( 'can_delete', 'DruidMetricInlineView'))) + self.assertTrue(security_manager.is_alpha_only( + security_manager.find_permission_view_menu( + 'all_database_access', 'all_database_access'))) def test_is_gamma_pvm(self): self.assertTrue(security_manager.is_gamma_pvm( @@ -231,6 +232,7 @@ def assert_can_all(view_menu): self.assertIn(('can_fave_slices', 'Superset'), gamma_perm_set) self.assertIn(('can_save_dash', 'Superset'), gamma_perm_set) self.assertIn(('can_slice', 'Superset'), gamma_perm_set) + self.assertIn(('can_userinfo', 'UserDBModelView'), gamma_perm_set) def test_views_are_secured(self): """Preventing the addition of unsecured views without has_access decorator""" diff --git a/tests/sqllab_tests.py b/tests/sqllab_tests.py index d54601ce0d599..dc86866a9960a 100644 --- a/tests/sqllab_tests.py +++ b/tests/sqllab_tests.py @@ -53,9 +53,10 @@ def run_some_queries(self): self.logout() def tearDown(self): + self.logout() db.session.query(Query).delete() db.session.commit() - self.logout() + db.session.close() def test_sql_json(self): self.login('admin') @@ -223,6 +224,46 @@ def test_search_query_on_time(self): data = json.loads(resp) self.assertEquals(2, len(data)) + def test_search_query_with_owner_only_perms(self) -> None: + """ + Test a search query with can_only_access_owned_queries perm added to + Admin and make sure only Admin queries show up. + """ + session = db.session + + # Add can_only_access_owned_queries perm to Admin user + owned_queries_view = security_manager.find_permission_view_menu( + 'can_only_access_owned_queries', + 'can_only_access_owned_queries', + ) + security_manager.add_permission_role( + security_manager.find_role('Admin'), + owned_queries_view, + ) + session.commit() + + # Test search_queries for Admin user + self.run_some_queries() + self.login('admin') + + user_id = security_manager.find_user('admin').id + data = self.get_json_resp('/superset/search_queries') + self.assertEquals(2, len(data)) + user_ids = {k['userId'] for k in data} + self.assertEquals(set([user_id]), user_ids) + + # Remove can_only_access_owned_queries from Admin + owned_queries_view = security_manager.find_permission_view_menu( + 'can_only_access_owned_queries', + 'can_only_access_owned_queries', + ) + security_manager.del_permission_role( + security_manager.find_role('Admin'), + owned_queries_view, + ) + + session.commit() + def test_alias_duplicate(self): self.run_sql( 'SELECT username as col, id as col, username FROM ab_user', @@ -266,7 +307,7 @@ def test_sqllab_viz(self): 'columns': [{ 'is_date': False, 'type': 'STRING', - 'nam:qe': 'viz_type', + 'name': 'viz_type', 'is_dim': True, }, { 'is_date': False, @@ -309,6 +350,68 @@ def test_sql_limit(self): query_limit=test_limit) self.assertEquals(len(data['data']), test_limit) + def test_queryview_filter(self) -> None: + """ + Test queryview api without can_only_access_owned_queries perm added to + Admin and make sure all queries show up. + """ + self.run_some_queries() + self.login(username='admin') + + url = '/queryview/api/read' + data = self.get_json_resp(url) + admin = security_manager.find_user('admin') + gamma_sqllab = security_manager.find_user('gamma_sqllab') + self.assertEquals(3, len(data['result'])) + user_queries = [ + result.get('username') for result in data['result'] + ] + assert admin.username in user_queries + assert gamma_sqllab.username in user_queries + + def test_queryview_filter_owner_only(self) -> None: + """ + Test queryview api with can_only_access_owned_queries perm added to + Admin and make sure only Admin queries show up. + """ + session = db.session + + # Add can_only_access_owned_queries perm to Admin user + owned_queries_view = security_manager.find_permission_view_menu( + 'can_only_access_owned_queries', + 'can_only_access_owned_queries', + ) + security_manager.add_permission_role( + security_manager.find_role('Admin'), + owned_queries_view, + ) + session.commit() + + # Test search_queries for Admin user + self.run_some_queries() + self.login('admin') + + url = '/queryview/api/read' + data = self.get_json_resp(url) + admin = security_manager.find_user('admin') + self.assertEquals(2, len(data['result'])) + all_admin_user_queries = all([ + result.get('username') == admin.username for result in data['result'] + ]) + assert all_admin_user_queries is True + + # Remove can_only_access_owned_queries from Admin + owned_queries_view = security_manager.find_permission_view_menu( + 'can_only_access_owned_queries', + 'can_only_access_owned_queries', + ) + security_manager.del_permission_role( + security_manager.find_role('Admin'), + owned_queries_view, + ) + + session.commit() + if __name__ == '__main__': unittest.main() diff --git a/tox.ini b/tox.ini index 5eb9db5df7624..dbe2baaca3aff 100644 --- a/tox.ini +++ b/tox.ini @@ -29,6 +29,8 @@ exclude = superset/templates venv ignore = + E121 + E125 FI12 FI15 FI16