diff --git a/.github/workflows/docker_build_push.sh b/.github/workflows/docker_build_push.sh index 4feea5d802d4f..1c3723611f364 100755 --- a/.github/workflows/docker_build_push.sh +++ b/.github/workflows/docker_build_push.sh @@ -56,6 +56,19 @@ docker build --target lean \ --label "build_actor=${GITHUB_ACTOR}" \ . +# +# Build the "websocket" image +# +docker build \ + -t "${REPO_NAME}-websocket:${SHA}" \ + -t "${REPO_NAME}-websocket:${REFSPEC}" \ + -t "${REPO_NAME}-websocket:${LATEST_TAG}" \ + --label "sha=${SHA}" \ + --label "built_at=$(date)" \ + --label "target=lean" \ + --label "build_actor=${GITHUB_ACTOR}" \ + superset-websocket + # # Build the dev image # diff --git a/RESOURCES/FEATURE_FLAGS.md b/RESOURCES/FEATURE_FLAGS.md index 40db66f80b2cd..aa4d6c635565d 100644 --- a/RESOURCES/FEATURE_FLAGS.md +++ b/RESOURCES/FEATURE_FLAGS.md @@ -51,6 +51,7 @@ These features are **finished** but currently being tested. They are usable, but - ALERT_REPORTS: [(docs)](https://superset.apache.org/docs/installation/alerts-reports) - ALLOW_FULL_CSV_EXPORT - CACHE_IMPERSONATION +- CONFIRM_DASHBOARD_DIFF - DASHBOARD_EDIT_CHART_IN_NEW_TAB - DASHBOARD_FILTERS_EXPERIMENTAL - DASHBOARD_NATIVE_FILTERS diff --git a/UPDATING.md b/UPDATING.md index ddda9e51f6161..65b15f622b813 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -24,12 +24,14 @@ assists people when migrating to a new version. ## Next -- [21895](https://github.com/apache/superset/pull/21895): Markdown components had their security increased by adhering to the same sanitization process enforced by Github. This means that some HTML elements found in markdowns are not allowed anymore due to the security risks they impose. If you're deploying Superset in a trusted environment and wish to use some of the blocked elements, then you can use the HTML_SANITIZATION_SCHEMA_EXTENSIONS configuration to extend the default sanitization schema. There's also the option to disable HTML sanitization using the HTML_SANITIZATION configuration but we do not recommend this approach because of the security risks. Given the provided configurations, we don't view the improved sanitization as a breaking change but as a security patch. +- [22022](https://github.com/apache/superset/pull/22022): HTTP API endpoints `/superset/approve` and `/superset/request_access` have been deprecated and their HTTP methods were changed from GET to POST +- [21895](https://github.com/apache/superset/pull/21895): Markdown components had their security increased by adhering to the same sanitization process enforced by GitHub. This means that some HTML elements found in markdowns are not allowed anymore due to the security risks they impose. If you're deploying Superset in a trusted environment and wish to use some of the blocked elements, then you can use the HTML_SANITIZATION_SCHEMA_EXTENSIONS configuration to extend the default sanitization schema. There's also the option to disable HTML sanitization using the HTML_SANITIZATION configuration but we do not recommend this approach because of the security risks. Given the provided configurations, we don't view the improved sanitization as a breaking change but as a security patch. - [20606](https://github.com/apache/superset/pull/20606): When user clicks on chart title or "Edit chart" button in Dashboard page, Explore opens in the same tab. Clicking while holding cmd/ctrl opens Explore in a new tab. To bring back the old behaviour (always opening Explore in a new tab), flip feature flag `DASHBOARD_EDIT_CHART_IN_NEW_TAB` to `True`. -- [20799](https://github.com/apache/superset/pull/20799): Presto and Trino engine will now display tracking URL for running queries in SQL Lab. If for some reason you don't want to show the tracking URL (for example, when your data warehouse hasn't enable access for to Presto or Trino UI), update `TRACKING_URL_TRANSFORMER` in `config.py` to return `None`. +- [20799](https://github.com/apache/superset/pull/20799): Presto and Trino engine will now display tracking URL for running queries in SQL Lab. If for some reason you don't want to show the tracking URL (for example, when your data warehouse hasn't enabled access for to Presto or Trino UI), update `TRACKING_URL_TRANSFORMER` in `config.py` to return `None`. - [21002](https://github.com/apache/superset/pull/21002): Support Python 3.10 and bump pandas 1.4 and pyarrow 6. -- [21163](https://github.com/apache/superset/pull/21163): When `GENERIC_CHART_AXES` feature flags set to `True`, the Time Grain control will move below the X-Axis control. +- [21163](https://github.com/apache/superset/pull/21163): The time grain will be decoupled from the time filter column and the time grain control will move below the X-Axis control when `GENERIC_CHART_AXES` feature flags set to `True`. The time grain will be applied on the time column in the column-like controls(x axis, dimensions) instead of the time column in the time section. - [21284](https://github.com/apache/superset/pull/21284): The non-functional `MAX_TABLE_NAMES` config key has been removed. +- [21794](https://github.com/apache/superset/pull/21794): Deprecates the undocumented `PRESTO_SPLIT_VIEWS_FROM_TABLES` feature flag. Now for Presto, like other engines, only physical tables are treated as tables. ### Breaking Changes diff --git a/helm/superset/Chart.yaml b/helm/superset/Chart.yaml index cfe3d3fdd92ae..7394d150cafbd 100644 --- a/helm/superset/Chart.yaml +++ b/helm/superset/Chart.yaml @@ -29,7 +29,7 @@ maintainers: - name: craig-rueda email: craig@craigrueda.com url: https://github.com/craig-rueda -version: 0.7.6 +version: 0.7.7 dependencies: - name: postgresql version: 11.1.22 diff --git a/helm/superset/README.md b/helm/superset/README.md index 5b704ab78af5e..3564c205f5e7c 100644 --- a/helm/superset/README.md +++ b/helm/superset/README.md @@ -19,7 +19,7 @@ # superset -![Version: 0.7.6](https://img.shields.io/badge/Version-0.7.6-informational?style=flat-square) +![Version: 0.7.7](https://img.shields.io/badge/Version-0.7.7-informational?style=flat-square) Apache Superset is a modern, enterprise-ready business intelligence web application diff --git a/helm/superset/templates/configmap-superset.yaml b/helm/superset/templates/configmap-superset.yaml index a7d7b09339a0a..eb8564619b187 100644 --- a/helm/superset/templates/configmap-superset.yaml +++ b/helm/superset/templates/configmap-superset.yaml @@ -24,6 +24,7 @@ metadata: chart: {{ template "superset.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + namespace: {{ .Release.Namespace }} data: {{- range $path, $config := .Values.extraConfigs }} {{ $path }}: | diff --git a/helm/superset/templates/deployment-beat.yaml b/helm/superset/templates/deployment-beat.yaml index 2988c7755367a..01e66a83b645a 100644 --- a/helm/superset/templates/deployment-beat.yaml +++ b/helm/superset/templates/deployment-beat.yaml @@ -28,6 +28,7 @@ metadata: annotations: {{- toYaml .Values.supersetCeleryBeat.deploymentAnnotations | nindent 4 }} {{- end }} + namespace: {{ .Release.Namespace }} spec: # This must be a singleton replicas: 1 diff --git a/helm/superset/templates/deployment-flower.yaml b/helm/superset/templates/deployment-flower.yaml index 35b31cf55e238..197aa5822fdcf 100644 --- a/helm/superset/templates/deployment-flower.yaml +++ b/helm/superset/templates/deployment-flower.yaml @@ -28,6 +28,7 @@ metadata: annotations: {{- toYaml .Values.supersetCeleryFlower.deploymentAnnotations | nindent 4 }} {{- end }} + namespace: {{ .Release.Namespace }} spec: replicas: {{ .Values.supersetCeleryFlower.replicaCount }} selector: diff --git a/helm/superset/templates/deployment-worker.yaml b/helm/superset/templates/deployment-worker.yaml index c2e924438e7c0..06b52a7c7c663 100644 --- a/helm/superset/templates/deployment-worker.yaml +++ b/helm/superset/templates/deployment-worker.yaml @@ -27,6 +27,7 @@ metadata: annotations: {{- toYaml .Values.supersetWorker.deploymentAnnotations | nindent 4 }} {{- end }} + namespace: {{ .Release.Namespace }} spec: replicas: {{ .Values.supersetWorker.replicaCount }} selector: diff --git a/helm/superset/templates/deployment-ws.yaml b/helm/superset/templates/deployment-ws.yaml index 735edc8330ffb..1713ee74c5337 100644 --- a/helm/superset/templates/deployment-ws.yaml +++ b/helm/superset/templates/deployment-ws.yaml @@ -28,6 +28,7 @@ metadata: annotations: {{- toYaml .Values.supersetWebsockets.deploymentAnnotations | nindent 4 }} {{- end }} + namespace: {{ .Release.Namespace }} spec: replicas: {{ .Values.supersetWebsockets.replicaCount }} selector: diff --git a/helm/superset/templates/deployment.yaml b/helm/superset/templates/deployment.yaml index a02c9cf293dcf..d668cb7a0b358 100644 --- a/helm/superset/templates/deployment.yaml +++ b/helm/superset/templates/deployment.yaml @@ -27,6 +27,7 @@ metadata: annotations: {{- toYaml .Values.supersetNode.deploymentAnnotations | nindent 4 }} {{- end }} + namespace: {{ .Release.Namespace }} spec: replicas: {{ .Values.supersetNode.replicaCount }} {{- if .Values.supersetNode.strategy }} diff --git a/helm/superset/templates/ingress.yaml b/helm/superset/templates/ingress.yaml index c0df1e90e6f7f..d166149c00ba1 100644 --- a/helm/superset/templates/ingress.yaml +++ b/helm/superset/templates/ingress.yaml @@ -29,6 +29,7 @@ metadata: annotations: {{- toYaml . | nindent 4 }} {{- end }} + namespace: {{ .Release.Namespace }} spec: {{- if .Values.ingress.ingressClassName }} ingressClassName: {{ .Values.ingress.ingressClassName }} diff --git a/helm/superset/templates/init-job.yaml b/helm/superset/templates/init-job.yaml index 878e93095853b..96b063ff4f043 100644 --- a/helm/superset/templates/init-job.yaml +++ b/helm/superset/templates/init-job.yaml @@ -22,6 +22,7 @@ metadata: annotations: "helm.sh/hook": post-install,post-upgrade "helm.sh/hook-delete-policy": "before-hook-creation" + namespace: {{ .Release.Namespace }} spec: template: metadata: diff --git a/helm/superset/templates/secret-env.yaml b/helm/superset/templates/secret-env.yaml index 4126507324439..0164d96a8c129 100644 --- a/helm/superset/templates/secret-env.yaml +++ b/helm/superset/templates/secret-env.yaml @@ -23,6 +23,7 @@ metadata: chart: {{ template "superset.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" + namespace: {{ .Release.Namespace }} type: Opaque stringData: REDIS_HOST: {{ tpl .Values.supersetNode.connections.redis_host . | quote }} diff --git a/helm/superset/templates/secret-superset-config.yaml b/helm/superset/templates/secret-superset-config.yaml index ddf0befcd2f2b..c1f4102858d93 100644 --- a/helm/superset/templates/secret-superset-config.yaml +++ b/helm/superset/templates/secret-superset-config.yaml @@ -23,6 +23,7 @@ metadata: chart: {{ template "superset.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" + namespace: {{ .Release.Namespace }} type: Opaque stringData: superset_config.py: | diff --git a/helm/superset/templates/secret-ws.yaml b/helm/superset/templates/secret-ws.yaml index 0e48e0377e591..c3ac55d96cb07 100644 --- a/helm/superset/templates/secret-ws.yaml +++ b/helm/superset/templates/secret-ws.yaml @@ -24,6 +24,7 @@ metadata: chart: {{ template "superset.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" + namespace: {{ .Release.Namespace }} type: Opaque stringData: config.json: | diff --git a/helm/superset/templates/service-account.yaml b/helm/superset/templates/service-account.yaml index 8d1171fad4445..994ad8333afd8 100755 --- a/helm/superset/templates/service-account.yaml +++ b/helm/superset/templates/service-account.yaml @@ -31,4 +31,5 @@ metadata: {{- if .Values.serviceAccount.annotations }} annotations: {{- toYaml .Values.serviceAccount.annotations | nindent 4 }} {{- end }} + namespace: {{ .Release.Namespace }} {{- end -}} diff --git a/helm/superset/templates/service.yaml b/helm/superset/templates/service.yaml index 431d03704e551..6ac950d1da6b2 100644 --- a/helm/superset/templates/service.yaml +++ b/helm/superset/templates/service.yaml @@ -27,6 +27,7 @@ metadata: annotations: {{- toYaml . | nindent 4 }} {{- end }} + namespace: {{ .Release.Namespace }} spec: type: {{ .Values.service.type }} ports: @@ -55,6 +56,7 @@ metadata: annotations: {{- toYaml . | nindent 4 }} {{- end }} + namespace: {{ .Release.Namespace }} spec: type: {{ .Values.supersetCeleryFlower.service.type }} ports: @@ -84,6 +86,7 @@ metadata: annotations: {{- toYaml . | nindent 4 }} {{- end }} + namespace: {{ .Release.Namespace }} spec: type: {{ .Values.supersetWebsockets.service.type }} ports: diff --git a/requirements/base.txt b/requirements/base.txt index 8387d380bc5ab..30dc9c0a9187c 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -76,7 +76,7 @@ flask==2.0.3 # flask-migrate # flask-sqlalchemy # flask-wtf -flask-appbuilder==4.1.4 +flask-appbuilder==4.1.6 # via apache-superset flask-babel==1.0.0 # via flask-appbuilder @@ -108,8 +108,6 @@ geopy==2.2.0 # via apache-superset graphlib-backport==1.0.3 # via apache-superset -greenlet==1.1.2 - # via sqlalchemy gunicorn==20.1.0 # via apache-superset hashids==1.3.1 diff --git a/requirements/development.txt b/requirements/development.txt index 9990012ab32ee..1bce530eab733 100644 --- a/requirements/development.txt +++ b/requirements/development.txt @@ -78,7 +78,7 @@ pure-eval==0.2.2 # via stack-data pure-sasl==0.6.2 # via thrift-sasl -pydruid==0.6.2 +pydruid==0.6.5 # via apache-superset pygments==2.12.0 # via ipython diff --git a/requirements/docker.txt b/requirements/docker.txt index 0c2d36159e4d0..307064dbdeddf 100644 --- a/requirements/docker.txt +++ b/requirements/docker.txt @@ -12,6 +12,8 @@ # -r requirements/docker.in gevent==21.8.0 # via -r requirements/docker.in +greenlet==1.1.3.post0 + # via gevent psycopg2-binary==2.9.1 # via apache-superset zope-event==4.5.0 diff --git a/requirements/testing.txt b/requirements/testing.txt index 191fa99c07f5a..8068f3718c818 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -130,7 +130,7 @@ rsa==4.7.2 # via google-auth statsd==3.3.0 # via -r requirements/testing.in -trino==0.315.0 +trino==0.319.0 # via apache-superset typing-inspect==0.7.1 # via libcst diff --git a/setup.py b/setup.py index eabea273d8e64..e340d24b1bd77 100644 --- a/setup.py +++ b/setup.py @@ -83,7 +83,7 @@ def get_git_sha() -> str: "cryptography>=3.3.2", "deprecation>=2.1.0, <2.2.0", "flask>=2.0.0, <3.0.0", - "flask-appbuilder>=4.1.4, <5.0.0", + "flask-appbuilder>=4.1.6, <5.0.0", "flask-caching>=1.10.0", "flask-compress", "flask-talisman", @@ -141,7 +141,7 @@ def get_git_sha() -> str: "db2": ["ibm-db-sa>=0.3.5, <0.4"], "dremio": ["sqlalchemy-dremio>=1.1.5, <1.3"], "drill": ["sqlalchemy-drill==0.1.dev"], - "druid": ["pydruid>=0.6.1,<0.7"], + "druid": ["pydruid>=0.6.5,<0.7"], "solr": ["sqlalchemy-solr >= 0.2.0"], "elasticsearch": ["elasticsearch-dbapi>=0.2.9, <0.3.0"], "exasol": ["sqlalchemy-exasol >= 2.4.0, <3.0"], @@ -160,7 +160,7 @@ def get_git_sha() -> str: "pinot": ["pinotdb>=0.3.3, <0.4"], "postgres": ["psycopg2-binary==2.9.1"], "presto": ["pyhive[presto]>=0.6.5"], - "trino": ["trino>=0.313.0"], + "trino": ["trino>=0.319.0"], "prophet": ["prophet>=1.0.1, <1.1", "pystan<3.0"], "redshift": ["sqlalchemy-redshift>=0.8.1, < 0.9"], "rockset": ["rockset>=0.8.10, <0.9"], diff --git a/superset-frontend/.storybook/main.js b/superset-frontend/.storybook/main.js index 8a004ba3e2928..814e53cf58411 100644 --- a/superset-frontend/.storybook/main.js +++ b/superset-frontend/.storybook/main.js @@ -24,7 +24,8 @@ module.exports = { builder: 'webpack5', }, stories: [ - '../src/@(components|common|filters|explore)/**/*.stories.@(tsx|jsx|mdx)', + '../src/@(components|common|filters|explore|views)/**/*.stories.@(tsx|jsx)', + '../src/@(components|common|filters|explore|views)/**/*.*.@(mdx)', ], addons: [ '@storybook/addon-essentials', diff --git a/superset-frontend/.storybook/preview.jsx b/superset-frontend/.storybook/preview.jsx index d98a55506eaca..fa0c9088735a2 100644 --- a/superset-frontend/.storybook/preview.jsx +++ b/superset-frontend/.storybook/preview.jsx @@ -68,7 +68,15 @@ addParameters({ ['Controls', 'Display', 'Feedback', 'Input', '*'], ['Overview', 'Examples', '*'], 'Design System', - ['Foundations', 'Components', 'Patterns', '*'], + [ + 'Introduction', + 'Foundations', + 'Components', + ['Overview', 'Examples', '*'], + 'Patterns', + '*', + ], + ['Overview', 'Examples', '*'], '*', ], }, diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/drilltodetail.test.ts b/superset-frontend/cypress-base/cypress/integration/dashboard/drilltodetail.test.ts index f89435f1bc152..caf938b33cf47 100644 --- a/superset-frontend/cypress-base/cypress/integration/dashboard/drilltodetail.test.ts +++ b/superset-frontend/cypress-base/cypress/integration/dashboard/drilltodetail.test.ts @@ -409,14 +409,14 @@ describe('Drill to detail modal', () => { cy.get("[data-test-viz-type='world_map'] svg").then($canvas => { cy.wrap($canvas).scrollIntoView().rightclick(70, 150); - openModalFromChartContext('Drill to detail by United States'); - cy.getBySel('filter-val').should('contain', 'United States'); + openModalFromChartContext('Drill to detail by USA'); + cy.getBySel('filter-val').should('contain', 'USA'); closeModal(); }); cy.get("[data-test-viz-type='world_map'] svg").then($canvas => { cy.wrap($canvas).scrollIntoView().rightclick(200, 140); - openModalFromChartContext('Drill to detail by Slovakia'); - cy.getBySel('filter-val').should('contain', 'Slovakia'); + openModalFromChartContext('Drill to detail by SVK'); + cy.getBySel('filter-val').should('contain', 'SVK'); }); }); }); diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 2d5debb43583e..cf956ff74d4b2 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -100,12 +100,14 @@ "react-checkbox-tree": "^1.5.1", "react-color": "^2.13.8", "react-datetime": "^3.0.4", + "react-diff-viewer": "^3.1.1", "react-dnd": "^11.1.3", "react-dnd-html5-backend": "^11.1.3", "react-dom": "^16.13.0", "react-draggable": "^4.4.3", "react-gravatar": "^2.6.1", "react-hot-loader": "^4.12.20", + "react-intersection-observer": "^8.26.2", "react-js-cron": "^1.2.0", "react-json-tree": "^0.11.2", "react-jsonschema-form": "^1.2.0", @@ -24790,6 +24792,28 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, + "node_modules/create-emotion": { + "version": "10.0.27", + "resolved": "https://registry.npmjs.org/create-emotion/-/create-emotion-10.0.27.tgz", + "integrity": "sha512-fIK73w82HPPn/RsAij7+Zt8eCE8SptcJ3WoRMfxMtjteYxud8GDTKKld7MYwAX2TVhrw29uR1N/bVGxeStHILg==", + "dependencies": { + "@emotion/cache": "^10.0.27", + "@emotion/serialize": "^0.11.15", + "@emotion/sheet": "0.9.4", + "@emotion/utils": "0.11.3" + } + }, + "node_modules/create-emotion/node_modules/@emotion/cache": { + "version": "10.0.29", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz", + "integrity": "sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==", + "dependencies": { + "@emotion/sheet": "0.9.4", + "@emotion/stylis": "0.8.5", + "@emotion/utils": "0.11.3", + "@emotion/weak-memoize": "0.2.5" + } + }, "node_modules/create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", @@ -27124,7 +27148,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, "engines": { "node": ">=0.3.1" } @@ -27585,6 +27608,15 @@ "node": ">= 4" } }, + "node_modules/emotion": { + "version": "10.0.27", + "resolved": "https://registry.npmjs.org/emotion/-/emotion-10.0.27.tgz", + "integrity": "sha512-2xdDzdWWzue8R8lu4G76uWX5WhyQuzATon9LmNeCy/2BHVC6dsEpfhN1a0qhELgtDVdjyEA6J8Y/VlI5ZnaH0g==", + "dependencies": { + "babel-plugin-emotion": "^10.0.27", + "create-emotion": "^10.0.27" + } + }, "node_modules/emotion-rgba": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/emotion-rgba/-/emotion-rgba-0.0.9.tgz", @@ -45270,6 +45302,26 @@ "react": "^16.5.0" } }, + "node_modules/react-diff-viewer": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/react-diff-viewer/-/react-diff-viewer-3.1.1.tgz", + "integrity": "sha512-rmvwNdcClp6ZWdS11m1m01UnBA4OwYaLG/li0dB781e/bQEzsGyj+qewVd6W5ztBwseQ72pO7nwaCcq5jnlzcw==", + "dependencies": { + "classnames": "^2.2.6", + "create-emotion": "^10.0.14", + "diff": "^4.0.1", + "emotion": "^10.0.14", + "memoize-one": "^5.0.4", + "prop-types": "^15.6.2" + }, + "engines": { + "node": ">= 8" + }, + "peerDependencies": { + "react": "^15.3.0 || ^16.0.0", + "react-dom": "^15.3.0 || ^16.0.0" + } + }, "node_modules/react-dnd": { "version": "11.1.3", "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-11.1.3.tgz", @@ -45505,6 +45557,17 @@ "react": "^16.8.4 || ^17.0.0" } }, + "node_modules/react-intersection-observer": { + "version": "8.26.2", + "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-8.26.2.tgz", + "integrity": "sha512-GmSjLNK+oV7kS+BHfrJSaA4wF61ELA33gizKHmN+tk59UT6/aW8kkqvlrFGPwxGoaIzLKS2evfG5fgkw5MIIsg==", + "dependencies": { + "tiny-invariant": "^1.1.0" + }, + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, "node_modules/react-is": { "version": "16.6.3", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.6.3.tgz", @@ -77238,6 +77301,30 @@ } } }, + "create-emotion": { + "version": "10.0.27", + "resolved": "https://registry.npmjs.org/create-emotion/-/create-emotion-10.0.27.tgz", + "integrity": "sha512-fIK73w82HPPn/RsAij7+Zt8eCE8SptcJ3WoRMfxMtjteYxud8GDTKKld7MYwAX2TVhrw29uR1N/bVGxeStHILg==", + "requires": { + "@emotion/cache": "^10.0.27", + "@emotion/serialize": "^0.11.15", + "@emotion/sheet": "0.9.4", + "@emotion/utils": "0.11.3" + }, + "dependencies": { + "@emotion/cache": { + "version": "10.0.29", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz", + "integrity": "sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==", + "requires": { + "@emotion/sheet": "0.9.4", + "@emotion/stylis": "0.8.5", + "@emotion/utils": "0.11.3", + "@emotion/weak-memoize": "0.2.5" + } + } + } + }, "create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", @@ -79012,8 +79099,7 @@ "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" }, "diff-match-patch": { "version": "1.0.5", @@ -79431,6 +79517,15 @@ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" }, + "emotion": { + "version": "10.0.27", + "resolved": "https://registry.npmjs.org/emotion/-/emotion-10.0.27.tgz", + "integrity": "sha512-2xdDzdWWzue8R8lu4G76uWX5WhyQuzATon9LmNeCy/2BHVC6dsEpfhN1a0qhELgtDVdjyEA6J8Y/VlI5ZnaH0g==", + "requires": { + "babel-plugin-emotion": "^10.0.27", + "create-emotion": "^10.0.27" + } + }, "emotion-rgba": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/emotion-rgba/-/emotion-rgba-0.0.9.tgz", @@ -92970,6 +93065,19 @@ "prop-types": "^15.5.7" } }, + "react-diff-viewer": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/react-diff-viewer/-/react-diff-viewer-3.1.1.tgz", + "integrity": "sha512-rmvwNdcClp6ZWdS11m1m01UnBA4OwYaLG/li0dB781e/bQEzsGyj+qewVd6W5ztBwseQ72pO7nwaCcq5jnlzcw==", + "requires": { + "classnames": "^2.2.6", + "create-emotion": "^10.0.14", + "diff": "^4.0.1", + "emotion": "^10.0.14", + "memoize-one": "^5.0.4", + "prop-types": "^15.6.2" + } + }, "react-dnd": { "version": "11.1.3", "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-11.1.3.tgz", @@ -93154,6 +93262,14 @@ "prop-types": "^15.0.0" } }, + "react-intersection-observer": { + "version": "8.26.2", + "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-8.26.2.tgz", + "integrity": "sha512-GmSjLNK+oV7kS+BHfrJSaA4wF61ELA33gizKHmN+tk59UT6/aW8kkqvlrFGPwxGoaIzLKS2evfG5fgkw5MIIsg==", + "requires": { + "tiny-invariant": "^1.1.0" + } + }, "react-is": { "version": "16.6.3", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.6.3.tgz", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 67f7af9b7c542..d121f296dc5cd 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -164,12 +164,14 @@ "react-checkbox-tree": "^1.5.1", "react-color": "^2.13.8", "react-datetime": "^3.0.4", + "react-diff-viewer": "^3.1.1", "react-dnd": "^11.1.3", "react-dnd-html5-backend": "^11.1.3", "react-dom": "^16.13.0", "react-draggable": "^4.4.3", "react-gravatar": "^2.6.1", "react-hot-loader": "^4.12.20", + "react-intersection-observer": "^8.26.2", "react-js-cron": "^1.2.0", "react-json-tree": "^0.11.2", "react-jsonschema-form": "^1.2.0", diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/operators/pivotOperator.ts b/superset-frontend/packages/superset-ui-chart-controls/src/operators/pivotOperator.ts index 4db7e4125a314..8190c951d68a1 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/operators/pivotOperator.ts +++ b/superset-frontend/packages/superset-ui-chart-controls/src/operators/pivotOperator.ts @@ -30,13 +30,13 @@ export const pivotOperator: PostProcessingFactory = ( queryObject, ) => { const metricLabels = ensureIsArray(queryObject.metrics).map(getMetricLabel); - const xAxis = getXAxisLabel(formData); + const xAxisLabel = getXAxisLabel(formData); - if (xAxis && metricLabels.length) { + if (xAxisLabel && metricLabels.length) { return { operation: 'pivot', options: { - index: [xAxis], + index: [xAxisLabel], columns: ensureIsArray(queryObject.columns).map(getColumnLabel), // Create 'dummy' mean aggregates to assign cell values in pivot table // use the 'mean' aggregates to avoid drop NaN. PR: https://github.com/apache-superset/superset-ui/pull/1231 diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/operators/prophetOperator.ts b/superset-frontend/packages/superset-ui-chart-controls/src/operators/prophetOperator.ts index 274cadb4b654a..269dc1e80169a 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/operators/prophetOperator.ts +++ b/superset-frontend/packages/superset-ui-chart-controls/src/operators/prophetOperator.ts @@ -24,8 +24,8 @@ export const prophetOperator: PostProcessingFactory = ( formData, queryObject, ) => { - const xAxis = getXAxisLabel(formData); - if (formData.forecastEnabled && xAxis) { + const xAxisLabel = getXAxisLabel(formData); + if (formData.forecastEnabled && xAxisLabel) { return { operation: 'prophet', options: { @@ -35,7 +35,7 @@ export const prophetOperator: PostProcessingFactory = ( yearly_seasonality: formData.forecastSeasonalityYearly, weekly_seasonality: formData.forecastSeasonalityWeekly, daily_seasonality: formData.forecastSeasonalityDaily, - index: xAxis, + index: xAxisLabel, }, }; } diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/operators/renameOperator.ts b/superset-frontend/packages/superset-ui-chart-controls/src/operators/renameOperator.ts index fb254e04696a5..34dc0283612d5 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/operators/renameOperator.ts +++ b/superset-frontend/packages/superset-ui-chart-controls/src/operators/renameOperator.ts @@ -34,7 +34,7 @@ export const renameOperator: PostProcessingFactory = ( const metrics = ensureIsArray(queryObject.metrics); const columns = ensureIsArray(queryObject.columns); const { truncate_metric } = formData; - const xAxis = getXAxisLabel(formData); + const xAxisLabel = getXAxisLabel(formData); // remove or rename top level of column name(metric name) in the MultiIndex when // 1) only 1 metric // 2) exist dimentsion @@ -44,7 +44,7 @@ export const renameOperator: PostProcessingFactory = ( if ( metrics.length === 1 && columns.length > 0 && - xAxis && + xAxisLabel && !( // todo: we should provide an approach to handle derived metrics ( diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/operators/timeComparePivotOperator.ts b/superset-frontend/packages/superset-ui-chart-controls/src/operators/timeComparePivotOperator.ts index d2b8d0d81ddaf..c3a2ef074f0a6 100644 --- a/superset-frontend/packages/superset-ui-chart-controls/src/operators/timeComparePivotOperator.ts +++ b/superset-frontend/packages/superset-ui-chart-controls/src/operators/timeComparePivotOperator.ts @@ -30,9 +30,9 @@ import { PostProcessingFactory } from './types'; export const timeComparePivotOperator: PostProcessingFactory = (formData, queryObject) => { const metricOffsetMap = getMetricOffsetsMap(formData, queryObject); - const xAxis = getXAxisLabel(formData); + const xAxisLabel = getXAxisLabel(formData); - if (isTimeComparison(formData, queryObject) && xAxis) { + if (isTimeComparison(formData, queryObject) && xAxisLabel) { const aggregates = Object.fromEntries( [...metricOffsetMap.values(), ...metricOffsetMap.keys()].map(metric => [ metric, @@ -44,7 +44,7 @@ export const timeComparePivotOperator: PostProcessingFactory = (props: P) => string | React.ReactElement; * When defining a new option here, take care to keep any parameters to functions (or components) minimal. * Any removal or alteration to a parameter will be considered a breaking change. */ + +// from src/views/components/Menu, not imported since this is a separate package +interface MenuObjectChildProps { + label: string; + name?: string; + icon?: string; + index?: number; + url?: string; + isFrontendRoute?: boolean; + perm?: string | boolean; + view?: string; + disable?: boolean; +} + type ConfigDetailsProps = { embeddedId: string; }; +type RightMenuItemIconProps = { + menuChild: MenuObjectChildProps; +}; export type Extensions = Partial<{ + 'alertsreports.header.icon': React.ComponentType; 'embedded.documentation.configuration_details': React.ComponentType; 'embedded.documentation.description': ReturningDisplayable; 'embedded.documentation.url': string; 'dashboard.nav.right': React.ComponentType; + 'navbar.right-menu.item.icon': React.ComponentType; 'navbar.right': React.ComponentType; + 'report-modal.dropdown.item.icon': React.ComponentType; 'welcome.message': React.ComponentType; 'welcome.banner': React.ComponentType; 'welcome.main.replacement': React.ComponentType; diff --git a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts index 4eb90ea0afffa..012bb4ebaf9ec 100644 --- a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts +++ b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts @@ -28,6 +28,7 @@ export enum FeatureFlag { DASHBOARD_CROSS_FILTERS = 'DASHBOARD_CROSS_FILTERS', DASHBOARD_EDIT_CHART_IN_NEW_TAB = 'DASHBOARD_EDIT_CHART_IN_NEW_TAB', DASHBOARD_FILTERS_EXPERIMENTAL = 'DASHBOARD_FILTERS_EXPERIMENTAL', + CONFIRM_DASHBOARD_DIFF = 'CONFIRM_DASHBOARD_DIFF', DASHBOARD_NATIVE_FILTERS = 'DASHBOARD_NATIVE_FILTERS', DASHBOARD_NATIVE_FILTERS_SET = 'DASHBOARD_NATIVE_FILTERS_SET', DASHBOARD_VIRTUALIZATION = 'DASHBOARD_VIRTUALIZATION', diff --git a/superset-frontend/plugins/legacy-plugin-chart-world-map/src/WorldMap.js b/superset-frontend/plugins/legacy-plugin-chart-world-map/src/WorldMap.js index c845c20da80b0..7b56d432eaaa7 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-world-map/src/WorldMap.js +++ b/superset-frontend/plugins/legacy-plugin-chart-world-map/src/WorldMap.js @@ -52,6 +52,7 @@ const formatter = getNumberFormatter(); function WorldMap(element, props) { const { + countryFieldtype, entity, data, width, @@ -111,7 +112,7 @@ function WorldMap(element, props) { const pointerEvent = d3.event; pointerEvent.preventDefault(); const key = source.id || source.country; - const val = mapData[key]?.name; + const val = countryFieldtype === 'name' ? mapData[key]?.name : key; if (val) { const filters = [ { diff --git a/superset-frontend/plugins/legacy-plugin-chart-world-map/src/transformProps.js b/superset-frontend/plugins/legacy-plugin-chart-world-map/src/transformProps.js index 71b40e832e815..6348874eaba03 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-world-map/src/transformProps.js +++ b/superset-frontend/plugins/legacy-plugin-chart-world-map/src/transformProps.js @@ -23,6 +23,7 @@ export default function transformProps(chartProps) { chartProps; const { onContextMenu } = hooks; const { + countryFieldtype, entity, maxBubbleSize, showBubbles, @@ -35,6 +36,7 @@ export default function transformProps(chartProps) { const { r, g, b } = colorPicker; return { + countryFieldtype, entity, data: queriesData[0].data, width, diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.ts index 96a7d38e9886c..2d8cc129c0bf4 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.ts @@ -102,11 +102,11 @@ export default function transformProps( const { r, g, b } = colorPicker; const mainColor = `rgb(${r}, ${g}, ${b})`; - const timeColumn = getXAxisLabel(rawFormData) as string; + const xAxisLabel = getXAxisLabel(rawFormData) as string; let trendLineData; let percentChange = 0; let bigNumber = data.length === 0 ? null : data[0][metricName]; - let timestamp = data.length === 0 ? null : data[0][timeColumn]; + let timestamp = data.length === 0 ? null : data[0][xAxisLabel]; let bigNumberFallback; const metricColtypeIndex = colnames.findIndex(name => name === metricName); @@ -115,7 +115,7 @@ export default function transformProps( if (data.length > 0) { const sortedData = (data as BigNumberDatum[]) - .map(d => [d[timeColumn], parseMetricValue(d[metricName])]) + .map(d => [d[xAxisLabel], parseMetricValue(d[metricName])]) // sort in time descending order .sort((a, b) => (a[0] !== null && b[0] !== null ? b[0] - a[0] : 0)); diff --git a/superset-frontend/spec/fixtures/mockDashboardState.js b/superset-frontend/spec/fixtures/mockDashboardState.js index 49b71053710a8..b605443af6b02 100644 --- a/superset-frontend/spec/fixtures/mockDashboardState.js +++ b/superset-frontend/spec/fixtures/mockDashboardState.js @@ -1,3 +1,4 @@ +/* eslint-disable theme-colors/no-literal-colors */ /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -30,3 +31,88 @@ export default { focusedFilterField: null, refreshFrequency: 0, }; + +export const overwriteConfirmMetadata = { + updatedAt: '2022-10-07T16:35:30.924212', + updatedBy: 'Superset Admin', + overwriteConfirmItems: [ + { + keyPath: 'css', + oldValue: '', + newValue: ` + .navbar { + transition: opacity 0.5s ease; + } +`, + }, + { + keyPath: 'json_metadata.filter_scopes', + oldValue: `{ + "122": { + "ethnic_minority": { + "scope": ["ROOT_ID"], + "immune": [] + }, + "gender": { + "scope": ["ROOT_ID"], + "immune": [] + }, + "developer_type": { + "scope": ["ROOT_ID"], + "immune": [] + }, + "lang_at_home": { + "scope": ["ROOT_ID"], + "immune": [] + }, + "country_live": { + "scope": ["ROOT_ID"], + "immune": [] + } + } +}`, + newValue: `{ + "122": { + "ethnic_minority": { + "scope": ["ROOT_ID"], + "immune": [ + 131, + 115, + 123, + 89, + 94, + 71 + ] + }, + "gender": { + "scope": ["ROOT_ID"], + "immune": [] + }, + "developer_type": { + "scope": ["ROOT_ID"], + "immune": [] + }, + "lang_at_home": { + "scope": ["ROOT_ID"], + "immune": [] + }, + "country_live": { + "scope": ["ROOT_ID"], + "immune": [] + } + } +}`, + }, + ], + dashboardId: 9, + data: { + certified_by: '', + certification_details: '', + css: ".navbar {\n transition: opacity 0.5s ease;\n opacity: 0.05;\n}\n.navbar:hover {\n opacity: 1;\n}\n.chart-header .header{\n font-weight: @font-weight-normal;\n font-size: 12px;\n}\n/*\nvar bnbColors = [\n //rausch hackb kazan babu lima beach tirol\n '#ff5a5f', '#7b0051', '#007A87', '#00d1c1', '#8ce071', '#ffb400', '#b4a76c',\n '#ff8083', '#cc0086', '#00a1b3', '#00ffeb', '#bbedab', '#ffd266', '#cbc29a',\n '#ff3339', '#ff1ab1', '#005c66', '#00b3a5', '#55d12e', '#b37e00', '#988b4e',\n ];\n*/\n", + dashboard_title: 'FCC New Coder Survey 2018', + slug: null, + owners: [], + json_metadata: + '{"timed_refresh_immune_slices":[],"expanded_slices":{},"refresh_frequency":0,"default_filters":"{}","color_scheme":"supersetColors","label_colors":{"0":"#FCC700","1":"#A868B7","15":"#3CCCCB","30":"#A38F79","45":"#8FD3E4","age":"#1FA8C9","Yes,":"#1FA8C9","Female":"#454E7C","Prefer":"#5AC189","No,":"#FF7F44","Male":"#666666","Prefer not to say":"#E04355","Ph.D.":"#FCC700","associate\'s degree":"#A868B7","bachelor\'s degree":"#3CCCCB","high school diploma or equivalent (GED)":"#A38F79","master\'s degree (non-professional)":"#8FD3E4","no high school (secondary school)":"#A1A6BD","professional degree (MBA, MD, JD, etc.)":"#ACE1C4","some college credit, no degree":"#FEC0A1","some high school":"#B2B2B2","trade, technical, or vocational training":"#EFA1AA","No, not an ethnic minority":"#1FA8C9","Yes, an ethnic minority":"#454E7C","":"#5AC189","Yes":"#FF7F44","No":"#666666","last_yr_income":"#E04355","More":"#A1A6BD","Less":"#ACE1C4","I":"#FEC0A1","expected_earn":"#B2B2B2","Yes: Willing To":"#EFA1AA","No: Not Willing to":"#FDE380","No Answer":"#D3B3DA","In an Office (with Other Developers)":"#9EE5E5","No Preference":"#D1C6BC","From Home":"#1FA8C9"},"show_native_filters":true,"color_scheme_domain":["#1FA8C9","#454E7C","#5AC189","#FF7F44","#666666","#E04355","#FCC700","#A868B7","#3CCCCB","#A38F79","#8FD3E4","#A1A6BD","#ACE1C4","#FEC0A1","#B2B2B2","#EFA1AA","#FDE380","#D3B3DA","#9EE5E5","#D1C6BC"],"shared_label_colors":{"Male":"#5ac19e","Female":"#1f86c9","":"#5AC189","Prefer not to say":"#47457c","No Answer":"#e05043","Yes, an ethnic minority":"#666666","No, not an ethnic minority":"#ffa444","age":"#1FA8C9"},"filter_scopes":{},"chart_configuration":{},"positions":{}}', + }, +}; diff --git a/superset-frontend/src/SqlLab/actions/sqlLab.js b/superset-frontend/src/SqlLab/actions/sqlLab.js index 0da9295b3a02c..a58630cda155e 100644 --- a/superset-frontend/src/SqlLab/actions/sqlLab.js +++ b/superset-frontend/src/SqlLab/actions/sqlLab.js @@ -1365,6 +1365,7 @@ export function popStoredQuery(urlId) { schema: json.schema ? json.schema : null, autorun: json.autorun ? json.autorun : false, sql: json.sql ? json.sql : 'SELECT ...', + templateParams: json.templateParams, }), ), ) @@ -1409,17 +1410,18 @@ export function popQuery(queryId) { } export function popDatasourceQuery(datasourceKey, sql) { return function (dispatch) { + const datasetId = datasourceKey.split('__')[0]; return SupersetClient.get({ - endpoint: `/superset/fetch_datasource_metadata?datasourceKey=${datasourceKey}`, + endpoint: `/api/v1/dataset/${datasetId}?q=(keys:!(none))`, }) .then(({ json }) => dispatch( addQueryEditor({ - name: `Query ${json.name}`, - dbId: json.database.id, - schema: json.schema, + name: `Query ${json.result.name}`, + dbId: json.result.database.id, + schema: json.result.schema, autorun: sql !== undefined, - sql: sql || json.select_star, + sql: sql || json.result.select_star, }), ), ) diff --git a/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/ShareSqlLabQuery.test.tsx b/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/ShareSqlLabQuery.test.tsx index 2c2038f5c4138..6e9775c3a5bae 100644 --- a/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/ShareSqlLabQuery.test.tsx +++ b/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/ShareSqlLabQuery.test.tsx @@ -72,6 +72,7 @@ const unsavedQueryEditor = { schema: 'query_schema_updated', sql: 'SELECT * FROM Updated Limit 100', autorun: true, + templateParams: '{ "my_value": "foo" }', }; const standardProviderWithUnsaved: React.FC = ({ children }) => ( diff --git a/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx b/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx index f1e6d13c41ac0..a7d88483cacb4 100644 --- a/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx +++ b/superset-frontend/src/SqlLab/components/ShareSqlLabQuery/index.tsx @@ -48,13 +48,19 @@ function ShareSqlLabQuery({ }: ShareSqlLabQueryPropTypes) { const theme = useTheme(); - const { dbId, name, schema, autorun, sql, remoteId } = useQueryEditor( - queryEditorId, - ['dbId', 'name', 'schema', 'autorun', 'sql', 'remoteId'], - ); + const { dbId, name, schema, autorun, sql, remoteId, templateParams } = + useQueryEditor(queryEditorId, [ + 'dbId', + 'name', + 'schema', + 'autorun', + 'sql', + 'remoteId', + 'templateParams', + ]); const getCopyUrlForKvStore = (callback: Function) => { - const sharedQuery = { dbId, name, schema, autorun, sql }; + const sharedQuery = { dbId, name, schema, autorun, sql, templateParams }; return storeQuery(sharedQuery) .then(shortUrl => { diff --git a/superset-frontend/src/assets/images/no-columns.svg b/superset-frontend/src/assets/images/no-columns.svg new file mode 100644 index 0000000000000..2fc8fe0661bfe --- /dev/null +++ b/superset-frontend/src/assets/images/no-columns.svg @@ -0,0 +1,22 @@ + + + + + diff --git a/superset-frontend/src/components/Button/index.tsx b/superset-frontend/src/components/Button/index.tsx index b4152ea98dc17..05a1a3ad79881 100644 --- a/superset-frontend/src/components/Button/index.tsx +++ b/superset-frontend/src/components/Button/index.tsx @@ -39,11 +39,13 @@ export type ButtonStyle = | 'link' | 'dashed'; +export type ButtonSize = 'default' | 'small' | 'xsmall'; + export type ButtonProps = Omit & Pick & { tooltip?: string; className?: string; - buttonSize?: 'default' | 'small' | 'xsmall'; + buttonSize?: ButtonSize; buttonStyle?: ButtonStyle; cta?: boolean; showMarginRight?: boolean; diff --git a/superset-frontend/src/components/DesignSystem.stories.mdx b/superset-frontend/src/components/DesignSystem.stories.mdx new file mode 100644 index 0000000000000..e00612c5be40a --- /dev/null +++ b/superset-frontend/src/components/DesignSystem.stories.mdx @@ -0,0 +1,25 @@ +import { Meta, Source } from '@storybook/addon-docs'; +import AtomicDesign from './atomic-design.png'; + + + +# Superset Design System + +A design system is a complete set of standards intended to manage design at scale using reusable components and patterns. + +You can get an overview of Atomic Design concepts and a link to the full book on the topic here: + + + Intro to Atomic Design + + +While the Superset Design System will use Atomic Design principles, we choose a different language to describe the elements. + +| Atomic Design | Atoms | Molecules | Organisms | Templates | Pages / Screens | +| :-------------- | :---------: | :--------: | :-------: | :-------: | :-------------: | +| Superset Design | Foundations | Components | Patterns | Templates | Features | + +Atoms = Foundations, Molecules = Components, Organisms = Patterns, Templates = Templates, Pages / Screens = Features diff --git a/superset-frontend/src/components/Dropdown/index.tsx b/superset-frontend/src/components/Dropdown/index.tsx index bd01aabb4d558..c40f479579d2e 100644 --- a/superset-frontend/src/components/Dropdown/index.tsx +++ b/superset-frontend/src/components/Dropdown/index.tsx @@ -20,6 +20,7 @@ import React, { RefObject } from 'react'; import { AntdDropdown } from 'src/components'; import { DropDownProps } from 'antd/lib/dropdown'; import { styled } from '@superset-ui/core'; +import Icons from 'src/components/Icons'; const MenuDots = styled.div` width: ${({ theme }) => theme.gridUnit * 0.75}px; @@ -66,14 +67,35 @@ const MenuDotsWrapper = styled.div` padding-left: ${({ theme }) => theme.gridUnit}px; `; +export enum IconOrientation { + VERTICAL = 'vertical', + HORIZONTAL = 'horizontal', +} export interface DropdownProps extends DropDownProps { overlay: React.ReactElement; + iconOrientation?: IconOrientation; } -export const Dropdown = ({ overlay, ...rest }: DropdownProps) => ( +const RenderIcon = ( + iconOrientation: IconOrientation = IconOrientation.VERTICAL, +) => { + const component = + iconOrientation === IconOrientation.HORIZONTAL ? ( + + ) : ( + + ); + return component; +}; + +export const Dropdown = ({ + overlay, + iconOrientation = IconOrientation.VERTICAL, + ...rest +}: DropdownProps) => ( - + {RenderIcon(iconOrientation)} ); diff --git a/superset-frontend/src/components/DropdownContainer/DropdownContainer.stories.tsx b/superset-frontend/src/components/DropdownContainer/DropdownContainer.stories.tsx index e2fe280dd470f..d72b1bdd39736 100644 --- a/superset-frontend/src/components/DropdownContainer/DropdownContainer.stories.tsx +++ b/superset-frontend/src/components/DropdownContainer/DropdownContainer.stories.tsx @@ -31,7 +31,7 @@ export default { const ITEMS_COUNT = 6; const ITEM_OPTIONS = 10; const MIN_WIDTH = 700; -const MAX_WIDTH = 1500; +const MAX_WIDTH = 1300; const HEIGHT = 400; const itemsOptions = Array.from({ length: ITEM_OPTIONS }).map((_, i) => ({ @@ -47,10 +47,10 @@ const generateItems = (overflowingState?: OverflowingState) => Array.from({ length: ITEMS_COUNT }).map((_, i) => ({ id: `el-${i}`, element: ( -
+