You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by mi...@apache.org on 2023/12/27 12:31:18 UTC

(superset) branch 3.1 updated (31bb9a690a -> 3dad685b6e)

This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a change to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git


    from 31bb9a690a chore: Adds 3.1.0 RC3 data to CHANGELOG.md
     new dd68c6e2e5 fix(typings): model_id is a multiple option (#25967)
     new ba9eef0407 chore: update changelog for 2.1.3 (#26287)
     new 9c109700ff chore: Disables minor ticks by default (#26310)
     new b5cb3ec13c chore: Use WEBDRIVER_OPTION_ARGS with Playwright (#26315)
     new 57155fdfc7 fix(sql lab): Use quote_schema instead of quote method to format schema name (#26281)
     new c19447ee88 fix(redshift): convert_dttm method for redshift dataset and tests (#26283)
     new ba4319472d chore: Add downloadAsImage types, change filter selector (#26297)
     new 5b6e9abf00 chore: Adds a tooltip for the alert's SQL input (#26317)
     new 7b969c9450 fix(dashboard): Don't switch to first tab when directPathToChild changes (#26340)
     new 4a8727d8d0 fix(tagging): adding tags containing a “:” to dashboards (#26324)
     new b1b2b57df2 fix(accessibility): Enable tabbing on sort header of table chart (#26326)
     new 5249815fbf fix(logging): Add logging of change_dashboard_filter event for native dashboard filters (#26333)
     new 1c77945980 chore(Embedded): Avoid creating a filter key for guest users (#26312)
     new 3dad685b6e fix(chart): Set max row limit + removed the option to use an empty row limit value (#26151)

The 14 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 CHANGELOG.md                                       | 43 ++++++++++++++++++++++
 superset-frontend/package-lock.json                | 25 ++++++++++---
 superset-frontend/package.json                     |  1 +
 .../superset-ui-chart-controls/src/constants.ts    |  2 +
 .../src/shared-controls/sharedControls.tsx         | 10 ++++-
 .../superset-ui-core/src/validator/index.ts        |  1 +
 .../src/validator/validateMaxValue.ts              |  8 ++++
 ...dateNumber.test.ts => validateMaxValue.test.ts} | 31 ++++++++--------
 .../src/MixedTimeseries/controlPanel.tsx           |  2 +
 .../src/MixedTimeseries/transformProps.ts          |  6 ++-
 .../src/MixedTimeseries/types.ts                   |  1 +
 .../src/Timeseries/Area/controlPanel.tsx           |  2 +
 .../src/Timeseries/Regular/Bar/controlPanel.tsx    |  2 +
 .../src/Timeseries/Regular/Line/controlPanel.tsx   |  2 +
 .../Timeseries/Regular/Scatter/controlPanel.tsx    |  2 +
 .../Timeseries/Regular/SmoothLine/controlPanel.tsx |  2 +
 .../src/Timeseries/Step/controlPanel.tsx           |  2 +
 .../src/Timeseries/transformProps.ts               |  4 +-
 .../plugin-chart-echarts/src/Timeseries/types.ts   |  1 +
 .../plugins/plugin-chart-echarts/src/controls.tsx  | 11 ++++++
 .../plugins/plugin-chart-table/src/TableChart.tsx  | 13 +++++++
 .../DashboardBuilder/DashboardContainer.tsx        | 13 ++++---
 .../dashboard/components/DashboardBuilder/utils.ts | 13 -------
 .../components/nativeFilters/FilterBar/index.tsx   | 13 ++++++-
 .../src/features/alerts/AlertReportModal.tsx       | 14 ++++---
 superset-frontend/src/pages/Tags/index.tsx         |  2 +-
 superset-frontend/src/types/dom-to-image-more.d.ts | 18 +--------
 superset-frontend/src/utils/downloadAsImage.ts     |  7 ++--
 superset/cli/thumbnails.py                         |  8 ++--
 superset/daos/tag.py                               | 14 +------
 superset/db_engine_specs/base.py                   |  3 +-
 superset/db_engine_specs/postgres.py               | 26 ++++++-------
 superset/db_engine_specs/redshift.py               |  6 ++-
 superset/tags/models.py                            |  3 +-
 superset/utils/webdriver.py                        |  3 +-
 tests/integration_tests/tags/dao_tests.py          | 28 +++++++-------
 .../{test_hana.py => test_redshift.py}             |  8 +++-
 37 files changed, 226 insertions(+), 124 deletions(-)
 create mode 100644 superset-frontend/packages/superset-ui-core/src/validator/validateMaxValue.ts
 copy superset-frontend/packages/superset-ui-core/test/validator/{validateNumber.test.ts => validateMaxValue.test.ts} (54%)
 copy tests/unit_tests/db_engine_specs/{test_hana.py => test_redshift.py} (82%)


(superset) 08/14: chore: Adds a tooltip for the alert's SQL input (#26317)

Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 5b6e9abf0035d566a853c6bd9ad3ae4d59211090
Author: Michael S. Molina <70...@users.noreply.github.com>
AuthorDate: Fri Dec 22 08:32:59 2023 -0300

    chore: Adds a tooltip for the alert's SQL input (#26317)
    
    (cherry picked from commit 5bd7fd7990a7f9d236f887e539fe1bce39712461)
---
 superset-frontend/src/features/alerts/AlertReportModal.tsx | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/superset-frontend/src/features/alerts/AlertReportModal.tsx b/superset-frontend/src/features/alerts/AlertReportModal.tsx
index 571c7b1b2a..e371efcf1b 100644
--- a/superset-frontend/src/features/alerts/AlertReportModal.tsx
+++ b/superset-frontend/src/features/alerts/AlertReportModal.tsx
@@ -152,6 +152,10 @@ const StyledModal = styled(Modal)`
   }
 `;
 
+const StyledTooltip = styled(InfoTooltipWithTrigger)`
+  margin-left: ${({ theme }) => theme.gridUnit}px;
+`;
+
 const StyledIcon = (theme: SupersetTheme) => css`
   margin: auto ${theme.gridUnit * 2}px auto 0;
   color: ${theme.colors.grayscale.base};
@@ -397,10 +401,12 @@ export const TRANSLATIONS = {
   ALERT_CONDITION_TEXT: t('Alert condition'),
   DATABASE_TEXT: t('Database'),
   SQL_QUERY_TEXT: t('SQL Query'),
+  SQL_QUERY_TOOLTIP: t(
+    'The result of this query should be a numeric-esque value',
+  ),
   TRIGGER_ALERT_IF_TEXT: t('Trigger Alert If...'),
   CONDITION_TEXT: t('Condition'),
   VALUE_TEXT: t('Value'),
-  VALUE_TOOLTIP: t('Threshold value should be double precision number'),
   REPORT_SCHEDULE_TEXT: t('Report schedule'),
   ALERT_CONDITION_SCHEDULE_TEXT: t('Alert condition schedule'),
   TIMEZONE_TEXT: t('Timezone'),
@@ -1284,6 +1290,7 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
               <StyledInputContainer>
                 <div className="control-label">
                   {TRANSLATIONS.SQL_QUERY_TEXT}
+                  <StyledTooltip tooltip={TRANSLATIONS.SQL_QUERY_TOOLTIP} />
                   <span className="required">*</span>
                 </div>
                 <TextAreaControl
@@ -1319,10 +1326,7 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
                 </StyledInputContainer>
                 <StyledInputContainer>
                   <div className="control-label">
-                    {TRANSLATIONS.VALUE_TEXT}{' '}
-                    <InfoTooltipWithTrigger
-                      tooltip={TRANSLATIONS.VALUE_TOOLTIP}
-                    />
+                    {TRANSLATIONS.VALUE_TEXT}
                     <span className="required">*</span>
                   </div>
                   <div className="input-container">


(superset) 07/14: chore: Add downloadAsImage types, change filter selector (#26297)

Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit ba4319472dc00510f2222bf714f52c16919746f1
Author: Kamil Gabryjelski <ka...@gmail.com>
AuthorDate: Thu Dec 21 08:53:23 2023 +0100

    chore: Add downloadAsImage types, change filter selector (#26297)
    
    (cherry picked from commit 5e85f5c81f66b2da6fa11d9112216004f35170c8)
---
 superset-frontend/package-lock.json                | 25 ++++++++++++++++------
 superset-frontend/package.json                     |  1 +
 superset-frontend/src/types/dom-to-image-more.d.ts | 18 ++--------------
 superset-frontend/src/utils/downloadAsImage.ts     |  7 +++---
 4 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json
index c4e771b259..e308f2aed6 100644
--- a/superset-frontend/package-lock.json
+++ b/superset-frontend/package-lock.json
@@ -186,6 +186,7 @@
         "@testing-library/react-hooks": "^5.0.3",
         "@testing-library/user-event": "^12.7.0",
         "@types/classnames": "^2.2.10",
+        "@types/dom-to-image": "^2.6.7",
         "@types/enzyme": "^3.10.5",
         "@types/enzyme-adapter-react-16": "^1.0.6",
         "@types/fetch-mock": "^7.3.2",
@@ -19248,6 +19249,12 @@
         "@types/ms": "*"
       }
     },
+    "node_modules/@types/dom-to-image": {
+      "version": "2.6.7",
+      "resolved": "https://registry.npmjs.org/@types/dom-to-image/-/dom-to-image-2.6.7.tgz",
+      "integrity": "sha512-me5VbCv+fcXozblWwG13krNBvuEOm6kA5xoa4RrjDJCNFOZSWR3/QLtOXimBHk1Fisq69Gx3JtOoXtg1N1tijg==",
+      "dev": true
+    },
     "node_modules/@types/enzyme": {
       "version": "3.10.10",
       "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.10.10.tgz",
@@ -29511,9 +29518,9 @@
       "license": "MIT"
     },
     "node_modules/dom-to-image-more": {
-      "version": "2.10.1",
-      "resolved": "https://registry.npmjs.org/dom-to-image-more/-/dom-to-image-more-2.10.1.tgz",
-      "integrity": "sha512-gMG28V47WGj5/xvrsbSPJAWSaV7CBh4teLErn1iGD1sa29HsFsHxvnoLj8VxVvfqnjPgsiUGs2IV2VAxLJGb+A=="
+      "version": "2.16.0",
+      "resolved": "https://registry.npmjs.org/dom-to-image-more/-/dom-to-image-more-2.16.0.tgz",
+      "integrity": "sha512-RyjtkaM/zVy90uJ20lT+/G7MwBZx6l/ePliq5CQOeAnPeew7aUGS6IqRWBkHpstU+POmhaKA8A9H9qf476gisQ=="
     },
     "node_modules/dom-to-pdf": {
       "version": "0.3.2",
@@ -79208,6 +79215,12 @@
         "@types/ms": "*"
       }
     },
+    "@types/dom-to-image": {
+      "version": "2.6.7",
+      "resolved": "https://registry.npmjs.org/@types/dom-to-image/-/dom-to-image-2.6.7.tgz",
+      "integrity": "sha512-me5VbCv+fcXozblWwG13krNBvuEOm6kA5xoa4RrjDJCNFOZSWR3/QLtOXimBHk1Fisq69Gx3JtOoXtg1N1tijg==",
+      "dev": true
+    },
     "@types/enzyme": {
       "version": "3.10.10",
       "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.10.10.tgz",
@@ -87324,9 +87337,9 @@
       "from": "dom-to-image@git+https://github.com/dmapper/dom-to-image.git"
     },
     "dom-to-image-more": {
-      "version": "2.10.1",
-      "resolved": "https://registry.npmjs.org/dom-to-image-more/-/dom-to-image-more-2.10.1.tgz",
-      "integrity": "sha512-gMG28V47WGj5/xvrsbSPJAWSaV7CBh4teLErn1iGD1sa29HsFsHxvnoLj8VxVvfqnjPgsiUGs2IV2VAxLJGb+A=="
+      "version": "2.16.0",
+      "resolved": "https://registry.npmjs.org/dom-to-image-more/-/dom-to-image-more-2.16.0.tgz",
+      "integrity": "sha512-RyjtkaM/zVy90uJ20lT+/G7MwBZx6l/ePliq5CQOeAnPeew7aUGS6IqRWBkHpstU+POmhaKA8A9H9qf476gisQ=="
     },
     "dom-to-pdf": {
       "version": "0.3.2",
diff --git a/superset-frontend/package.json b/superset-frontend/package.json
index 6707016b7e..153cdfce68 100644
--- a/superset-frontend/package.json
+++ b/superset-frontend/package.json
@@ -251,6 +251,7 @@
     "@testing-library/react-hooks": "^5.0.3",
     "@testing-library/user-event": "^12.7.0",
     "@types/classnames": "^2.2.10",
+    "@types/dom-to-image": "^2.6.7",
     "@types/enzyme": "^3.10.5",
     "@types/enzyme-adapter-react-16": "^1.0.6",
     "@types/fetch-mock": "^7.3.2",
diff --git a/superset-frontend/src/types/dom-to-image-more.d.ts b/superset-frontend/src/types/dom-to-image-more.d.ts
index c5a93de757..374a41bb04 100644
--- a/superset-frontend/src/types/dom-to-image-more.d.ts
+++ b/superset-frontend/src/types/dom-to-image-more.d.ts
@@ -18,20 +18,6 @@
  */
 
 declare module 'dom-to-image-more' {
-  export interface Options {
-    filter?: ((node: Node) => boolean) | undefined;
-    bgcolor?: string | undefined;
-    width?: number | undefined;
-    height?: number | undefined;
-    style?: {} | undefined;
-    quality?: number | undefined;
-    imagePlaceholder?: string | undefined;
-    cacheBust?: boolean | undefined;
-  }
-
-  class DomToImageMore {
-    static toJpeg(node: Node, options?: Options): Promise<string>;
-  }
-
-  export default DomToImageMore;
+  import domToImage = require('dom-to-image-more');
+  export = domToImage;
 }
diff --git a/superset-frontend/src/utils/downloadAsImage.ts b/superset-frontend/src/utils/downloadAsImage.ts
index 79373cc76a..a6f50926bc 100644
--- a/superset-frontend/src/utils/downloadAsImage.ts
+++ b/superset-frontend/src/utils/downloadAsImage.ts
@@ -62,7 +62,7 @@ export default function downloadAsImage(
       if (typeof node.className === 'string') {
         return (
           node.className !== 'mapboxgl-control-container' &&
-          !node.className.includes('ant-dropdown')
+          !node.className.includes('header-controls')
         );
       }
       return true;
@@ -70,17 +70,16 @@ export default function downloadAsImage(
 
     return domToImage
       .toJpeg(elementToPrint, {
-        quality: 1,
         bgcolor: supersetTheme.colors.grayscale.light4,
         filter,
       })
-      .then(dataUrl => {
+      .then((dataUrl: string) => {
         const link = document.createElement('a');
         link.download = `${generateFileStem(description)}.jpg`;
         link.href = dataUrl;
         link.click();
       })
-      .catch(e => {
+      .catch((e: Error) => {
         console.error('Creating image failed', e);
       });
   };


(superset) 03/14: chore: Disables minor ticks by default (#26310)

Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 9c109700ff4c6e624e8756a137d968623a629b5b
Author: Michael S. Molina <70...@users.noreply.github.com>
AuthorDate: Wed Dec 20 08:34:27 2023 -0300

    chore: Disables minor ticks by default (#26310)
    
    (cherry picked from commit eb65cea971c9c7a184350827ebf37765b4b49863)
---
 .../plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx |  2 ++
 .../src/MixedTimeseries/transformProps.ts                     |  6 ++++--
 .../plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts |  1 +
 .../plugin-chart-echarts/src/Timeseries/Area/controlPanel.tsx |  2 ++
 .../src/Timeseries/Regular/Bar/controlPanel.tsx               |  2 ++
 .../src/Timeseries/Regular/Line/controlPanel.tsx              |  2 ++
 .../src/Timeseries/Regular/Scatter/controlPanel.tsx           |  2 ++
 .../src/Timeseries/Regular/SmoothLine/controlPanel.tsx        |  2 ++
 .../plugin-chart-echarts/src/Timeseries/Step/controlPanel.tsx |  2 ++
 .../plugin-chart-echarts/src/Timeseries/transformProps.ts     |  4 +++-
 .../plugins/plugin-chart-echarts/src/Timeseries/types.ts      |  1 +
 .../plugins/plugin-chart-echarts/src/controls.tsx             | 11 +++++++++++
 12 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx
index c5fed29847..d3fb1fc53e 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/controlPanel.tsx
@@ -34,6 +34,7 @@ import { DEFAULT_FORM_DATA } from './types';
 import { EchartsTimeseriesSeriesType } from '../Timeseries/types';
 import {
   legendSection,
+  minorTicks,
   richTooltipSection,
   truncateXAxis,
   xAxisBounds,
@@ -316,6 +317,7 @@ const config: ControlPanelConfig = {
             },
           },
         ],
+        [minorTicks],
         ...legendSection,
         [<ControlSubSectionHeader>{t('X Axis')}</ControlSubSectionHeader>],
         ['x_axis_time_format'],
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
index 223083ef0c..6c96ab7104 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
@@ -160,6 +160,7 @@ export default function transformProps(
     opacity,
     opacityB,
     minorSplitLine,
+    minorTicks,
     seriesType,
     seriesTypeB,
     showLegend,
@@ -499,6 +500,7 @@ export default function transformProps(
         formatter: xAxisFormatter,
         rotate: xAxisLabelRotation,
       },
+      minorTick: { show: minorTicks },
       minInterval:
         xAxisType === 'time' && timeGrainSqla
           ? TIMEGRAIN_TO_TIMESTAMP[timeGrainSqla]
@@ -520,7 +522,7 @@ export default function transformProps(
         type: logAxis ? 'log' : 'value',
         min: yAxisMin,
         max: yAxisMax,
-        minorTick: { show: true },
+        minorTick: { show: minorTicks },
         minorSplitLine: { show: minorSplitLine },
         axisLabel: {
           formatter: getYAxisFormatter(
@@ -541,7 +543,7 @@ export default function transformProps(
         type: logAxisSecondary ? 'log' : 'value',
         min: minSecondary,
         max: maxSecondary,
-        minorTick: { show: true },
+        minorTick: { show: minorTicks },
         splitLine: { show: false },
         minorSplitLine: { show: minorSplitLine },
         axisLabel: {
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts
index 2e9ba641aa..c027ed7ac4 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts
@@ -45,6 +45,7 @@ export type EchartsMixedTimeseriesFormData = QueryFormData & {
   annotationLayers: AnnotationLayer[];
   // shared properties
   minorSplitLine: boolean;
+  minorTicks: boolean;
   logAxis: boolean;
   logAxisSecondary: boolean;
   yAxisFormat?: string;
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/controlPanel.tsx
index 1ca2805b2f..2d8bf549aa 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Area/controlPanel.tsx
@@ -40,6 +40,7 @@ import {
   xAxisLabelRotation,
   truncateXAxis,
   xAxisBounds,
+  minorTicks,
 } from '../../controls';
 import { AreaChartStackControlOptions } from '../../constants';
 
@@ -169,6 +170,7 @@ const config: ControlPanelConfig = {
             },
           },
         ],
+        [minorTicks],
         [
           {
             name: 'zoomable',
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx
index 1fecf64e6a..23cdae6a39 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx
@@ -32,6 +32,7 @@ import {
 } from '@superset-ui/chart-controls';
 import {
   legendSection,
+  minorTicks,
   richTooltipSection,
   seriesOrderSection,
   showValueSection,
@@ -299,6 +300,7 @@ const config: ControlPanelConfig = {
         ...seriesOrderSection,
         ['color_scheme'],
         ...showValueSection,
+        [minorTicks],
         [
           {
             name: 'zoomable',
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/controlPanel.tsx
index 488dac0738..1b2e7688ea 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Line/controlPanel.tsx
@@ -35,6 +35,7 @@ import {
 } from '../../constants';
 import {
   legendSection,
+  minorTicks,
   richTooltipSection,
   seriesOrderSection,
   showValueSection,
@@ -169,6 +170,7 @@ const config: ControlPanelConfig = {
             },
           },
         ],
+        [minorTicks],
         ...legendSection,
         [<ControlSubSectionHeader>{t('X Axis')}</ControlSubSectionHeader>],
         [
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/controlPanel.tsx
index 436000c62d..334f4438c3 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/Scatter/controlPanel.tsx
@@ -34,6 +34,7 @@ import {
 } from '../../constants';
 import {
   legendSection,
+  minorTicks,
   richTooltipSection,
   seriesOrderSection,
   showValueSection,
@@ -111,6 +112,7 @@ const config: ControlPanelConfig = {
             },
           },
         ],
+        [minorTicks],
         ...legendSection,
         [<ControlSubSectionHeader>{t('X Axis')}</ControlSubSectionHeader>],
 
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/controlPanel.tsx
index 2e05ab8202..24ff0bfa8d 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Regular/SmoothLine/controlPanel.tsx
@@ -34,6 +34,7 @@ import {
 } from '../../constants';
 import {
   legendSection,
+  minorTicks,
   richTooltipSection,
   seriesOrderSection,
   showValueSectionWithoutStack,
@@ -111,6 +112,7 @@ const config: ControlPanelConfig = {
             },
           },
         ],
+        [minorTicks],
         ...legendSection,
         [<ControlSubSectionHeader>{t('X Axis')}</ControlSubSectionHeader>],
         [
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/controlPanel.tsx
index 311b85cac0..36da829576 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/Step/controlPanel.tsx
@@ -32,6 +32,7 @@ import { EchartsTimeseriesSeriesType } from '../../types';
 import { DEFAULT_FORM_DATA, TIME_SERIES_DESCRIPTION_TEXT } from '../constants';
 import {
   legendSection,
+  minorTicks,
   richTooltipSection,
   seriesOrderSection,
   showValueSection,
@@ -163,6 +164,7 @@ const config: ControlPanelConfig = {
             },
           },
         ],
+        [minorTicks],
         ...legendSection,
         [<ControlSubSectionHeader>{t('X Axis')}</ControlSubSectionHeader>],
         [
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
index 0d54fd114c..bbb624c0e0 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
@@ -146,6 +146,7 @@ export default function transformProps(
     markerSize,
     metrics,
     minorSplitLine,
+    minorTicks,
     onlyTotal,
     opacity,
     orientation,
@@ -456,6 +457,7 @@ export default function transformProps(
       formatter: xAxisFormatter,
       rotate: xAxisLabelRotation,
     },
+    minorTick: { show: minorTicks },
     minInterval:
       xAxisType === AxisType.time && timeGrainSqla
         ? TIMEGRAIN_TO_TIMESTAMP[timeGrainSqla]
@@ -474,7 +476,7 @@ export default function transformProps(
     type: logAxis ? AxisType.log : AxisType.value,
     min: yAxisMin,
     max: yAxisMax,
-    minorTick: { show: true },
+    minorTick: { show: minorTicks },
     minorSplitLine: { show: minorSplitLine },
     axisLabel: {
       formatter: getYAxisFormatter(
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/types.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/types.ts
index 65da981e49..751f262ec1 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/types.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/types.ts
@@ -68,6 +68,7 @@ export type EchartsTimeseriesFormData = QueryFormData & {
   markerSize: number;
   metrics: QueryFormMetric[];
   minorSplitLine: boolean;
+  minorTicks: boolean;
   opacity: number;
   orderDesc: boolean;
   rowLimit: number;
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx
index 13fe754d99..21f8c7d97d 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx
@@ -298,3 +298,14 @@ export const xAxisBounds: ControlSetItem = {
       Boolean(controls?.truncateXAxis?.value),
   },
 };
+
+export const minorTicks: ControlSetItem = {
+  name: 'minorTicks',
+  config: {
+    type: 'CheckboxControl',
+    label: t('Minor ticks'),
+    default: false,
+    renderTrigger: true,
+    description: t('Show minor ticks on axes.'),
+  },
+};


(superset) 02/14: chore: update changelog for 2.1.3 (#26287)

Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit ba9eef040707e9a53a07d2a63467aabb160f6c0d
Author: Elizabeth Thompson <es...@gmail.com>
AuthorDate: Mon Dec 18 15:31:58 2023 -0800

    chore: update changelog for 2.1.3 (#26287)
---
 CHANGELOG.md | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index eb15d45438..a9474e9865 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,8 @@ under the License.
 - [3.0.2](#302-mon-nov-20-073838-2023--0500)
 - [3.0.1](#301-tue-oct-13-103221-2023--0700)
 - [3.0.0](#300-thu-aug-24-133627-2023--0600)
+- [2.1.3](#213-fri-dec-8-163651-2023--0700)
+- [2.1.2](#212-wed-oct-18-165930-2023--0700)
 - [2.1.1](#211-sun-apr-23-154421-2023-0100)
 - [2.1.0](#210-thu-mar-16-211305-2023--0700)
 - [2.0.1](#201-fri-nov-4-103402-2022--0400)
@@ -1304,6 +1306,47 @@ under the License.
 - [#23158](https://github.com/apache/superset/pull/23158) chore: Bump cryptography to 39.0.1 (@EugeneTorap)
 - [#23108](https://github.com/apache/superset/pull/23108) chore: Remove yarn.lock from the root folder (@EugeneTorap)
 
+### 2.1.3 (Fri Dec 8 16:36:51 2023 -0700)
+
+**Database Migrations**
+
+**Features**
+
+**Fixes**
+
+- [#25658](https://github.com/apache/superset/pull/25658) fix: improve upload ZIP file validation (@dpgaspar)
+- [#25779](https://github.com/apache/superset/pull/25779) fix: DB-specific quoting in Jinja macro (@betodealmeida)
+- [#25843](https://github.com/apache/superset/pull/25843) fix: remove `update_charts_owners` (@betodealmeida)
+
+**Others**
+
+- [#23862](https://github.com/apache/superset/pull/23862) chore: Use nh3 lib instead of bleach (@EugeneTorap)
+- [#23965](https://github.com/apache/superset/pull/23965) chore: bump werkzeug and Flask (@dpgaspar)
+- [#24033](https://github.com/apache/superset/pull/24033) chore: Update mypy and fix stubs issue (@EugeneTorap)
+- [#24045](https://github.com/apache/superset/pull/24045) chore: Bump sqlparse to 0.4.4 (@EugeneTorap)
+- [#24324](https://github.com/apache/superset/pull/24324) chore: rate limit requests (@betodealmeida)
+
+### 2.1.2 (Wed Oct 18 16:59:30 2023 -0700)
+
+**Database Migrations**
+
+**Features**
+
+**Fixes**
+
+- [#25150](https://github.com/apache/superset/pull/25150) fix: Chart series limit doesn't work for some databases (@KSPT-taylorjohn)
+- [#25014](https://github.com/apache/superset/pull/25014) fix: CTE queries with non-SELECT statements (@dpgaspar)
+- [#24849](https://github.com/apache/superset/pull/24849) fix: validation errors appearing after ssh tunnel switch (@hughhhh)
+- [#24196](https://github.com/apache/superset/pull/24196) fix: SSH Tunnel creation with dynamic form (@hughhhh)
+- [#24821](https://github.com/apache/superset/pull/24821) fix: Allow chart import to update the dataset an existing chart points to (@jfrag1)
+- [#24317](https://github.com/apache/superset/pull/24317) fix: update order of build for testing a release (@eschutho)
+
+**Others**
+
+- [#24826](https://github.com/apache/superset/pull/24826) chore: remove CssTemplate and Annotation access from gamma role (@lilykuang)
+- [#23680](https://github.com/apache/superset/pull/23680) chore: bump wtforms and add missing flask-limiter (@dpgaspar)
+- [#24758](https://github.com/apache/superset/pull/24758) chore(view_api): return application/json as content-type for api/v1/form_data endpoint (@zephyring)
+
 ### 2.1.1 (Sun Apr 23 15:44:21 2023 +0100)
 
 **Database Migrations**


(superset) 13/14: chore(Embedded): Avoid creating a filter key for guest users (#26312)

Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 1c77945980299d6568e5ae33f5fa85678cb9b2ad
Author: Vitor Avila <96...@users.noreply.github.com>
AuthorDate: Tue Dec 26 23:31:51 2023 -0300

    chore(Embedded): Avoid creating a filter key for guest users (#26312)
    
    Co-authored-by: Michael S. Molina <70...@users.noreply.github.com>
    (cherry picked from commit fe9fbadade9b5bfe57a4479adaf0e6a3b53aa6d7)
---
 .../src/dashboard/components/nativeFilters/FilterBar/index.tsx | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx
index 25284126d0..61014a6e0f 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx
@@ -47,6 +47,7 @@ import { useTabId } from 'src/hooks/useTabId';
 import { logEvent } from 'src/logger/actions';
 import { LOG_ACTIONS_CHANGE_DASHBOARD_FILTER } from 'src/logger/LogUtils';
 import { FilterBarOrientation, RootState } from 'src/dashboard/types';
+import { UserWithPermissionsAndRoles } from 'src/types/bootstrapTypes';
 import { checkIsApplyDisabled } from './utils';
 import { FiltersBarProps } from './types';
 import {
@@ -149,6 +150,10 @@ const FilterBar: React.FC<FiltersBarProps> = ({
   const canEdit = useSelector<RootState, boolean>(
     ({ dashboardInfo }) => dashboardInfo.dash_edit_perm,
   );
+  const user: UserWithPermissionsAndRoles = useSelector<
+    RootState,
+    UserWithPermissionsAndRoles
+  >(state => state.user);
 
   const [filtersInScope] = useSelectFiltersInScope(nativeFilterValues);
 
@@ -220,7 +225,10 @@ const FilterBar: React.FC<FiltersBarProps> = ({
   }, [dataMaskAppliedText, setDataMaskSelected]);
 
   useEffect(() => {
-    publishDataMask(history, dashboardId, updateKey, dataMaskApplied, tabId);
+    // embedded users can't persist filter combinations
+    if (user?.userId) {
+      publishDataMask(history, dashboardId, updateKey, dataMaskApplied, tabId);
+    }
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [dashboardId, dataMaskAppliedText, history, updateKey, tabId]);
 


(superset) 11/14: fix(accessibility): Enable tabbing on sort header of table chart (#26326)

Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit b1b2b57df24a00d6942cba09cd57708da7c77955
Author: arun <ar...@gmail.com>
AuthorDate: Sat Dec 23 11:58:41 2023 +0530

    fix(accessibility): Enable tabbing on sort header of table chart (#26326)
    
    (cherry picked from commit b6d433de32cad21c0866ee98fd5ae85b4459c23b)
---
 .../plugins/plugin-chart-table/src/TableChart.tsx           | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx b/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx
index 917abb929a..d106e42a84 100644
--- a/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx
+++ b/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx
@@ -71,6 +71,12 @@ interface TableSize {
   height: number;
 }
 
+const ACTION_KEYS = {
+  enter: 'Enter',
+  spacebar: 'Spacebar',
+  space: ' ',
+};
+
 /**
  * Return sortType based on data type
  */
@@ -591,6 +597,13 @@ export default function TableChart<D extends DataRecord = DataRecord>(
               ...sharedStyle,
               ...style,
             }}
+            tabIndex={0}
+            onKeyDown={(e: React.KeyboardEvent<HTMLElement>) => {
+              // programatically sort column on keypress
+              if (Object.values(ACTION_KEYS).includes(e.key)) {
+                col.toggleSortBy();
+              }
+            }}
             onClick={onClick}
             data-column-name={col.id}
             {...(allowRearrangeColumns && {


(superset) 04/14: chore: Use WEBDRIVER_OPTION_ARGS with Playwright (#26315)

Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit b5cb3ec13c071c28cea90ee9c86973019c60d73d
Author: Kamil Gabryjelski <ka...@gmail.com>
AuthorDate: Wed Dec 20 12:42:12 2023 +0100

    chore: Use WEBDRIVER_OPTION_ARGS with Playwright (#26315)
    
    (cherry picked from commit 3f9183a1628672d22e97284dfe9046d77a09e9fe)
---
 superset/utils/webdriver.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/superset/utils/webdriver.py b/superset/utils/webdriver.py
index f7814bfd3b..4552600fc9 100644
--- a/superset/utils/webdriver.py
+++ b/superset/utils/webdriver.py
@@ -137,7 +137,8 @@ class WebDriverPlaywright(WebDriverProxy):
         self, url: str, element_name: str, user: User
     ) -> bytes | None:
         with sync_playwright() as playwright:
-            browser = playwright.chromium.launch()
+            browser_args = current_app.config["WEBDRIVER_OPTION_ARGS"]
+            browser = playwright.chromium.launch(args=browser_args)
             pixel_density = current_app.config["WEBDRIVER_WINDOW"].get(
                 "pixel_density", 1
             )


(superset) 14/14: fix(chart): Set max row limit + removed the option to use an empty row limit value (#26151)

Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 3dad685b6e99d9aa39fdb8a83273e3faa2c3e018
Author: Corbin Bullard <co...@gmail.com>
AuthorDate: Tue Dec 26 21:32:11 2023 -0500

    fix(chart): Set max row limit + removed the option to use an empty row limit value (#26151)
    
    Co-authored-by: Lily Kuang <li...@preset.io>
    Co-authored-by: Michael S. Molina <70...@users.noreply.github.com>
---
 .../superset-ui-chart-controls/src/constants.ts    |  2 ++
 .../src/shared-controls/sharedControls.tsx         | 10 ++++++++--
 .../superset-ui-core/src/validator/index.ts        |  1 +
 .../src/validator/validateMaxValue.ts              |  8 ++++++++
 .../validator/validateMaxValue.test.ts}            | 23 +++++++++++++++++-----
 5 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/constants.ts b/superset-frontend/packages/superset-ui-chart-controls/src/constants.ts
index cbde46b0ef..ae6dd8f894 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/constants.ts
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/constants.ts
@@ -26,6 +26,8 @@ import {
 } from '@superset-ui/core';
 import { ColumnMeta, SortSeriesData, SortSeriesType } from './types';
 
+export const DEFAULT_MAX_ROW = 100000;
+
 // eslint-disable-next-line import/prefer-default-export
 export const TIME_FILTER_LABELS = {
   time_range: t('Time Range'),
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/sharedControls.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/sharedControls.tsx
index 57419b4918..341aaa0729 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/sharedControls.tsx
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/sharedControls.tsx
@@ -47,6 +47,7 @@ import {
   isDefined,
   hasGenericChartAxes,
   NO_TIME_RANGE,
+  validateMaxValue,
 } from '@superset-ui/core';
 
 import {
@@ -58,7 +59,7 @@ import {
   DEFAULT_TIME_FORMAT,
   DEFAULT_NUMBER_FORMAT,
 } from '../utils';
-import { TIME_FILTER_LABELS } from '../constants';
+import { DEFAULT_MAX_ROW, TIME_FILTER_LABELS } from '../constants';
 import {
   SharedControlConfig,
   Dataset,
@@ -243,7 +244,12 @@ const row_limit: SharedControlConfig<'SelectControl'> = {
   type: 'SelectControl',
   freeForm: true,
   label: t('Row limit'),
-  validators: [legacyValidateInteger],
+  clearable: false,
+  validators: [
+    legacyValidateInteger,
+    (v, state) =>
+      validateMaxValue(v, state?.common?.conf?.SQL_MAX_ROW || DEFAULT_MAX_ROW),
+  ],
   default: 10000,
   choices: formatSelectOptions(ROW_LIMIT_OPTIONS),
   description: t(
diff --git a/superset-frontend/packages/superset-ui-core/src/validator/index.ts b/superset-frontend/packages/superset-ui-core/src/validator/index.ts
index 532efcc959..fb37328c02 100644
--- a/superset-frontend/packages/superset-ui-core/src/validator/index.ts
+++ b/superset-frontend/packages/superset-ui-core/src/validator/index.ts
@@ -22,3 +22,4 @@ export { default as legacyValidateNumber } from './legacyValidateNumber';
 export { default as validateInteger } from './validateInteger';
 export { default as validateNumber } from './validateNumber';
 export { default as validateNonEmpty } from './validateNonEmpty';
+export { default as validateMaxValue } from './validateMaxValue';
diff --git a/superset-frontend/packages/superset-ui-core/src/validator/validateMaxValue.ts b/superset-frontend/packages/superset-ui-core/src/validator/validateMaxValue.ts
new file mode 100644
index 0000000000..24c1da1c79
--- /dev/null
+++ b/superset-frontend/packages/superset-ui-core/src/validator/validateMaxValue.ts
@@ -0,0 +1,8 @@
+import { t } from '../translation';
+
+export default function validateMaxValue(v: unknown, max: Number) {
+  if (Number(v) > +max) {
+    return t('Value cannot exceed %s', max);
+  }
+  return false;
+}
diff --git a/superset-frontend/packages/superset-ui-core/src/validator/index.ts b/superset-frontend/packages/superset-ui-core/test/validator/validateMaxValue.test.ts
similarity index 53%
copy from superset-frontend/packages/superset-ui-core/src/validator/index.ts
copy to superset-frontend/packages/superset-ui-core/test/validator/validateMaxValue.test.ts
index 532efcc959..6a8ed1642e 100644
--- a/superset-frontend/packages/superset-ui-core/src/validator/index.ts
+++ b/superset-frontend/packages/superset-ui-core/test/validator/validateMaxValue.test.ts
@@ -17,8 +17,21 @@
  * under the License.
  */
 
-export { default as legacyValidateInteger } from './legacyValidateInteger';
-export { default as legacyValidateNumber } from './legacyValidateNumber';
-export { default as validateInteger } from './validateInteger';
-export { default as validateNumber } from './validateNumber';
-export { default as validateNonEmpty } from './validateNonEmpty';
+import { validateMaxValue } from '@superset-ui/core';
+import './setup';
+
+test('validateInteger returns the warning message if invalid', () => {
+  expect(validateMaxValue(10.1, 10)).toBeTruthy();
+  expect(validateMaxValue(1, 0)).toBeTruthy();
+  expect(validateMaxValue('2', 1)).toBeTruthy();
+});
+
+test('validateInteger returns false if the input is valid', () => {
+  expect(validateMaxValue(0, 1)).toBeFalsy();
+  expect(validateMaxValue(10, 10)).toBeFalsy();
+  expect(validateMaxValue(undefined, 1)).toBeFalsy();
+  expect(validateMaxValue(NaN, NaN)).toBeFalsy();
+  expect(validateMaxValue(null, 1)).toBeFalsy();
+  expect(validateMaxValue('1', 1)).toBeFalsy();
+  expect(validateMaxValue('a', 1)).toBeFalsy();
+});


(superset) 09/14: fix(dashboard): Don't switch to first tab when directPathToChild changes (#26340)

Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 7b969c94502833bb7fdde902f188cf98599127f2
Author: Kamil Gabryjelski <ka...@gmail.com>
AuthorDate: Fri Dec 22 13:13:35 2023 +0100

    fix(dashboard): Don't switch to first tab when directPathToChild changes (#26340)
    
    (cherry picked from commit 39ac45351bbac5a6ceef26c6279b16ed14b5119b)
---
 .../components/DashboardBuilder/DashboardContainer.tsx      | 13 ++++++++-----
 .../src/dashboard/components/DashboardBuilder/utils.ts      | 13 -------------
 2 files changed, 8 insertions(+), 18 deletions(-)

diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx
index cc4e2db780..f3f214468e 100644
--- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx
+++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardContainer.tsx
@@ -18,7 +18,7 @@
  */
 // ParentSize uses resize observer so the dashboard will update size
 // when its container size changes, due to e.g., builder side panel opening
-import React, { FC, useCallback, useEffect, useMemo } from 'react';
+import React, { FC, useCallback, useEffect, useMemo, useRef } from 'react';
 import { useDispatch, useSelector } from 'react-redux';
 import {
   FeatureFlag,
@@ -51,7 +51,7 @@ import { setColorScheme } from 'src/dashboard/actions/dashboardState';
 import jsonStringify from 'json-stringify-pretty-compact';
 import { NATIVE_FILTER_DIVIDER_PREFIX } from '../nativeFilters/FiltersConfigModal/utils';
 import { findTabsWithChartsInScope } from '../nativeFilters/utils';
-import { getRootLevelTabIndex, getRootLevelTabsComponent } from './utils';
+import { getRootLevelTabsComponent } from './utils';
 
 type DashboardContainerProps = {
   topLevelTabs?: LayoutItem;
@@ -89,15 +89,18 @@ const DashboardContainer: FC<DashboardContainerProps> = ({ topLevelTabs }) => {
     Object.values(state.charts).map(chart => chart.id),
   );
 
+  const prevTabIndexRef = useRef();
   const tabIndex = useMemo(() => {
     const nextTabIndex = findTabIndexByComponentId({
       currentComponent: getRootLevelTabsComponent(dashboardLayout),
       directPathToChild,
     });
 
-    return nextTabIndex > -1
-      ? nextTabIndex
-      : getRootLevelTabIndex(dashboardLayout, directPathToChild);
+    if (nextTabIndex === -1) {
+      return prevTabIndexRef.current ?? 0;
+    }
+    prevTabIndexRef.current = nextTabIndex;
+    return nextTabIndex;
   }, [dashboardLayout, directPathToChild]);
 
   useEffect(() => {
diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/utils.ts b/superset-frontend/src/dashboard/components/DashboardBuilder/utils.ts
index 50aa989c68..8ba5405bf3 100644
--- a/superset-frontend/src/dashboard/components/DashboardBuilder/utils.ts
+++ b/superset-frontend/src/dashboard/components/DashboardBuilder/utils.ts
@@ -21,7 +21,6 @@ import {
   DASHBOARD_ROOT_ID,
 } from 'src/dashboard/util/constants';
 import { DashboardLayout } from 'src/dashboard/types';
-import findTabIndexByComponentId from 'src/dashboard/util/findTabIndexByComponentId';
 
 export const getRootLevelTabsComponent = (dashboardLayout: DashboardLayout) => {
   const dashboardRoot = dashboardLayout[DASHBOARD_ROOT_ID];
@@ -38,15 +37,3 @@ export const shouldFocusTabs = (
   // don't focus the tabs when we click on a tab
   event.target.className === 'ant-tabs-nav-wrap' ||
   container.contains(event.target);
-
-export const getRootLevelTabIndex = (
-  dashboardLayout: DashboardLayout,
-  directPathToChild: string[],
-): number =>
-  Math.max(
-    0,
-    findTabIndexByComponentId({
-      currentComponent: getRootLevelTabsComponent(dashboardLayout),
-      directPathToChild,
-    }),
-  );


(superset) 06/14: fix(redshift): convert_dttm method for redshift dataset and tests (#26283)

Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit c19447ee8839ab01ab6f0f87ccc235a2fe54c907
Author: gaurav7261 <14...@users.noreply.github.com>
AuthorDate: Thu Dec 21 02:25:34 2023 +0530

    fix(redshift): convert_dttm method for redshift dataset and tests (#26283)
    
    Co-authored-by: GauravM <ga...@ip-192-168-0-100.ap-south-1.compute.internal>
    (cherry picked from commit 60abf7e2af476b3b5b15004c943adea2d46a1a08)
---
 superset/db_engine_specs/postgres.py              | 26 ++++++-------
 superset/db_engine_specs/redshift.py              |  6 ++-
 tests/unit_tests/db_engine_specs/test_redshift.py | 47 +++++++++++++++++++++++
 3 files changed, 64 insertions(+), 15 deletions(-)

diff --git a/superset/db_engine_specs/postgres.py b/superset/db_engine_specs/postgres.py
index 7512aac606..b98fce4fe6 100644
--- a/superset/db_engine_specs/postgres.py
+++ b/superset/db_engine_specs/postgres.py
@@ -182,6 +182,19 @@ class PostgresBaseEngineSpec(BaseEngineSpec):
     def epoch_to_dttm(cls) -> str:
         return "(timestamp 'epoch' + {col} * interval '1 second')"
 
+    @classmethod
+    def convert_dttm(
+        cls, target_type: str, dttm: datetime, db_extra: dict[str, Any] | None = None
+    ) -> str | None:
+        sqla_type = cls.get_sqla_column_type(target_type)
+
+        if isinstance(sqla_type, Date):
+            return f"TO_DATE('{dttm.date().isoformat()}', 'YYYY-MM-DD')"
+        if isinstance(sqla_type, DateTime):
+            dttm_formatted = dttm.isoformat(sep=" ", timespec="microseconds")
+            return f"""TO_TIMESTAMP('{dttm_formatted}', 'YYYY-MM-DD HH24:MI:SS.US')"""
+        return None
+
 
 class PostgresEngineSpec(PostgresBaseEngineSpec, BasicParametersMixin):
     engine = "postgresql"
@@ -357,19 +370,6 @@ WHERE datistemplate = false;
             inspector.get_foreign_table_names(schema)
         )
 
-    @classmethod
-    def convert_dttm(
-        cls, target_type: str, dttm: datetime, db_extra: dict[str, Any] | None = None
-    ) -> str | None:
-        sqla_type = cls.get_sqla_column_type(target_type)
-
-        if isinstance(sqla_type, Date):
-            return f"TO_DATE('{dttm.date().isoformat()}', 'YYYY-MM-DD')"
-        if isinstance(sqla_type, DateTime):
-            dttm_formatted = dttm.isoformat(sep=" ", timespec="microseconds")
-            return f"""TO_TIMESTAMP('{dttm_formatted}', 'YYYY-MM-DD HH24:MI:SS.US')"""
-        return None
-
     @staticmethod
     def get_extra_params(database: Database) -> dict[str, Any]:
         """
diff --git a/superset/db_engine_specs/redshift.py b/superset/db_engine_specs/redshift.py
index 2e746a6349..fc21389099 100644
--- a/superset/db_engine_specs/redshift.py
+++ b/superset/db_engine_specs/redshift.py
@@ -14,10 +14,12 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
+from __future__ import annotations
+
 import logging
 import re
 from re import Pattern
-from typing import Any, Optional
+from typing import Any
 
 import pandas as pd
 from flask_babel import gettext as __
@@ -148,7 +150,7 @@ class RedshiftEngineSpec(PostgresBaseEngineSpec, BasicParametersMixin):
         return label.lower()
 
     @classmethod
-    def get_cancel_query_id(cls, cursor: Any, query: Query) -> Optional[str]:
+    def get_cancel_query_id(cls, cursor: Any, query: Query) -> str | None:
         """
         Get Redshift PID that will be used to cancel all other running
         queries in the same session.
diff --git a/tests/unit_tests/db_engine_specs/test_redshift.py b/tests/unit_tests/db_engine_specs/test_redshift.py
new file mode 100644
index 0000000000..ddd2c1a5eb
--- /dev/null
+++ b/tests/unit_tests/db_engine_specs/test_redshift.py
@@ -0,0 +1,47 @@
+# 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.
+
+from datetime import datetime
+from typing import Optional
+
+import pytest
+
+from tests.unit_tests.db_engine_specs.utils import assert_convert_dttm
+from tests.unit_tests.fixtures.common import dttm
+
+
+@pytest.mark.parametrize(
+    "target_type,expected_result",
+    [
+        ("Date", "TO_DATE('2019-01-02', 'YYYY-MM-DD')"),
+        (
+            "DateTime",
+            "TO_TIMESTAMP('2019-01-02 03:04:05.678900', 'YYYY-MM-DD HH24:MI:SS.US')",
+        ),
+        (
+            "TimeStamp",
+            "TO_TIMESTAMP('2019-01-02 03:04:05.678900', 'YYYY-MM-DD HH24:MI:SS.US')",
+        ),
+        ("UnknownType", None),
+    ],
+)
+def test_convert_dttm(
+    target_type: str, expected_result: Optional[str], dttm: datetime
+) -> None:
+    from superset.db_engine_specs.redshift import RedshiftEngineSpec as spec
+
+    assert_convert_dttm(spec, target_type, expected_result, dttm)


(superset) 01/14: fix(typings): model_id is a multiple option (#25967)

Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit dd68c6e2e567ed1c2f8c7697629fb60bd55f0abc
Author: Gnought <16...@users.noreply.github.com>
AuthorDate: Tue Dec 19 02:54:55 2023 +0800

    fix(typings): model_id is a multiple option (#25967)
    
    (cherry picked from commit 04f1c356a51464b49236c0dff379d71cd9a6cd4e)
---
 superset/cli/thumbnails.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/superset/cli/thumbnails.py b/superset/cli/thumbnails.py
index 325fab6853..0dd8edfb13 100755
--- a/superset/cli/thumbnails.py
+++ b/superset/cli/thumbnails.py
@@ -62,7 +62,7 @@ def compute_thumbnails(
     dashboards_only: bool,
     charts_only: bool,
     force: bool,
-    model_id: int,
+    model_id: list[int],
 ) -> None:
     """Compute thumbnails"""
     # pylint: disable=import-outside-toplevel
@@ -76,12 +76,12 @@ def compute_thumbnails(
     def compute_generic_thumbnail(
         friendly_type: str,
         model_cls: Union[type[Dashboard], type[Slice]],
-        model_id: int,
+        model_ids: list[int],
         compute_func: CallableTask,
     ) -> None:
         query = db.session.query(model_cls)
-        if model_id:
-            query = query.filter(model_cls.id.in_(model_id))
+        if model_ids:
+            query = query.filter(model_cls.id.in_(model_ids))
         dashboards = query.all()
         count = len(dashboards)
         for i, model in enumerate(dashboards):


(superset) 10/14: fix(tagging): adding tags containing a “:” to dashboards (#26324)

Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 4a8727d8d0161dbedf1e125972ec36a690cf9647
Author: Lily Kuang <li...@preset.io>
AuthorDate: Fri Dec 22 10:30:08 2023 -0800

    fix(tagging): adding tags containing a “:” to dashboards (#26324)
    
    will add more tests in a separated PR
    
    (cherry picked from commit 3391e290934b61e4a508ddee36ca002bee7e4c64)
---
 superset-frontend/src/pages/Tags/index.tsx |  2 +-
 superset/daos/tag.py                       | 14 +-------------
 superset/tags/models.py                    |  3 ++-
 tests/integration_tests/tags/dao_tests.py  | 28 +++++++++++++---------------
 4 files changed, 17 insertions(+), 30 deletions(-)

diff --git a/superset-frontend/src/pages/Tags/index.tsx b/superset-frontend/src/pages/Tags/index.tsx
index d395ce7cde..b0c998c3f3 100644
--- a/superset-frontend/src/pages/Tags/index.tsx
+++ b/superset-frontend/src/pages/Tags/index.tsx
@@ -353,7 +353,7 @@ function TagList(props: TagListProps) {
                 className="tags-list-view"
                 columns={columns}
                 count={tagCount}
-                data={tags.filter(tag => !tag.name.includes(':'))}
+                data={tags}
                 disableBulkSelect={toggleBulkSelect}
                 refreshData={refreshData}
                 emptyState={emptyState}
diff --git a/superset/daos/tag.py b/superset/daos/tag.py
index 60362bfbbd..e4aa891816 100644
--- a/superset/daos/tag.py
+++ b/superset/daos/tag.py
@@ -24,7 +24,7 @@ from sqlalchemy.exc import SQLAlchemyError
 from superset.commands.tag.exceptions import TagNotFoundError
 from superset.commands.tag.utils import to_object_type
 from superset.daos.base import BaseDAO
-from superset.daos.exceptions import DAOCreateFailedError, DAODeleteFailedError
+from superset.daos.exceptions import DAODeleteFailedError
 from superset.exceptions import MissingUserContextException
 from superset.extensions import db
 from superset.models.dashboard import Dashboard
@@ -46,24 +46,12 @@ logger = logging.getLogger(__name__)
 class TagDAO(BaseDAO[Tag]):
     # base_filter = TagAccessFilter
 
-    @staticmethod
-    def validate_tag_name(tag_name: str) -> bool:
-        invalid_characters = [":", ","]
-        for invalid_character in invalid_characters:
-            if invalid_character in tag_name:
-                return False
-        return True
-
     @staticmethod
     def create_custom_tagged_objects(
         object_type: ObjectType, object_id: int, tag_names: list[str]
     ) -> None:
         tagged_objects = []
         for name in tag_names:
-            if not TagDAO.validate_tag_name(name):
-                raise DAOCreateFailedError(
-                    message="Invalid Tag Name (cannot contain ':' or ',')"
-                )
             type_ = TagType.custom
             tag_name = name.strip()
             tag = TagDAO.get_by_name(tag_name, type_)
diff --git a/superset/tags/models.py b/superset/tags/models.py
index 7a77677a36..bae4417507 100644
--- a/superset/tags/models.py
+++ b/superset/tags/models.py
@@ -19,6 +19,7 @@ from __future__ import annotations
 import enum
 from typing import TYPE_CHECKING
 
+from flask import escape
 from flask_appbuilder import Model
 from sqlalchemy import Column, Enum, ForeignKey, Integer, orm, String, Table, Text
 from sqlalchemy.engine.base import Connection
@@ -115,7 +116,7 @@ def get_tag(name: str, session: orm.Session, type_: TagType) -> Tag:
     tag_name = name.strip()
     tag = session.query(Tag).filter_by(name=tag_name, type=type_).one_or_none()
     if tag is None:
-        tag = Tag(name=tag_name, type=type_)
+        tag = Tag(name=escape(tag_name), type=type_)
         session.add(tag)
         session.commit()
     return tag
diff --git a/tests/integration_tests/tags/dao_tests.py b/tests/integration_tests/tags/dao_tests.py
index 272ba43ed3..38bb4d0904 100644
--- a/tests/integration_tests/tags/dao_tests.py
+++ b/tests/integration_tests/tags/dao_tests.py
@@ -124,13 +124,19 @@ class TestTagsDAO(SupersetTestCase):
     @pytest.mark.usefixtures("with_tagging_system_feature")
     # test create tag
     def test_create_tagged_objects(self):
-        # test that a tag cannot be added if it has ':' in it
-        with pytest.raises(DAOCreateFailedError):
-            TagDAO.create_custom_tagged_objects(
-                object_type=ObjectType.dashboard.name,
-                object_id=1,
-                tag_names=["invalid:example tag 1"],
-            )
+        # test that a tag can be added if it has ':' in it
+        TagDAO.create_custom_tagged_objects(
+            object_type=ObjectType.dashboard.name,
+            object_id=1,
+            tag_names=["valid:example tag 1"],
+        )
+
+        # test that a tag can be added if it has ',' in it
+        TagDAO.create_custom_tagged_objects(
+            object_type=ObjectType.dashboard.name,
+            object_id=1,
+            tag_names=["example,tag,1"],
+        )
 
         # test that a tag can be added if it has a valid name
         TagDAO.create_custom_tagged_objects(
@@ -320,11 +326,3 @@ class TestTagsDAO(SupersetTestCase):
             .first()
         )
         assert tagged_object is None
-
-    @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices")
-    @pytest.mark.usefixtures("with_tagging_system_feature")
-    def test_validate_tag_name(self):
-        assert TagDAO.validate_tag_name("example_tag_name") is True
-        assert TagDAO.validate_tag_name("invalid:tag_name") is False
-        db.session.query(TaggedObject).delete()
-        db.session.query(Tag).delete()


(superset) 12/14: fix(logging): Add logging of change_dashboard_filter event for native dashboard filters (#26333)

Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 5249815fbf9e7c8b66c2986fb8b860e03188b80f
Author: John Bodley <45...@users.noreply.github.com>
AuthorDate: Wed Dec 27 08:48:55 2023 +1300

    fix(logging): Add logging of change_dashboard_filter event for native dashboard filters (#26333)
    
    (cherry picked from commit 5f5a656835d3cc133e38fa156b8bc8fd3ee0c4f6)
---
 .../src/dashboard/components/nativeFilters/FilterBar/index.tsx         | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx
index 546742c6dd..25284126d0 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx
@@ -44,6 +44,8 @@ import { getInitialDataMask } from 'src/dataMask/reducer';
 import { URL_PARAMS } from 'src/constants';
 import { getUrlParam } from 'src/utils/urlUtils';
 import { useTabId } from 'src/hooks/useTabId';
+import { logEvent } from 'src/logger/actions';
+import { LOG_ACTIONS_CHANGE_DASHBOARD_FILTER } from 'src/logger/LogUtils';
 import { FilterBarOrientation, RootState } from 'src/dashboard/types';
 import { checkIsApplyDisabled } from './utils';
 import { FiltersBarProps } from './types';
@@ -223,6 +225,7 @@ const FilterBar: React.FC<FiltersBarProps> = ({
   }, [dashboardId, dataMaskAppliedText, history, updateKey, tabId]);
 
   const handleApply = useCallback(() => {
+    dispatch(logEvent(LOG_ACTIONS_CHANGE_DASHBOARD_FILTER, {}));
     const filterIds = Object.keys(dataMaskSelected);
     setUpdateKey(1);
     filterIds.forEach(filterId => {


(superset) 05/14: fix(sql lab): Use quote_schema instead of quote method to format schema name (#26281)

Posted by mi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

michaelsmolina pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 57155fdfc780189e9385bc30fbeb911039e2388c
Author: Guen Prawiroatmodjo <gu...@gmail.com>
AuthorDate: Wed Dec 20 12:52:39 2023 -0500

    fix(sql lab): Use quote_schema instead of quote method to format schema name (#26281)
    
    (cherry picked from commit 9d3796828c102b5a93d2ad936d493820a9828f9d)
---
 superset/db_engine_specs/base.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/superset/db_engine_specs/base.py b/superset/db_engine_specs/base.py
index 9894232ab1..6bc8c444d6 100644
--- a/superset/db_engine_specs/base.py
+++ b/superset/db_engine_specs/base.py
@@ -1433,8 +1433,9 @@ class BaseEngineSpec:  # pylint: disable=too-many-public-methods
         if show_cols:
             fields = cls._get_fields(cols)
         quote = engine.dialect.identifier_preparer.quote
+        quote_schema = engine.dialect.identifier_preparer.quote_schema
         if schema:
-            full_table_name = quote(schema) + "." + quote(table_name)
+            full_table_name = quote_schema(schema) + "." + quote(table_name)
         else:
             full_table_name = quote(table_name)