- )}
);
}
diff --git a/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChart.tsx b/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChart.tsx
index 473a3506a..b29890d4a 100644
--- a/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChart.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/chart/components/SuperChart.tsx
@@ -25,11 +25,12 @@ import {
Fragment,
} from 'react';
-import ErrorBoundary, {
+import {
+ ErrorBoundary,
ErrorBoundaryProps,
FallbackProps,
} from 'react-error-boundary';
-import { ParentSize } from '@vx/responsive';
+import { ParentSize } from '@visx/responsive';
import { createSelector } from 'reselect';
import { withTheme } from '@emotion/react';
import { parseLength, Dimension } from '../../dimension';
@@ -232,7 +233,7 @@ class SuperChart extends PureComponent {
chart
) : (
(
+ FallbackComponent={props => (
)}
onError={onErrorBoundary}
diff --git a/superset-frontend/packages/superset-ui-core/src/chart/types/VizType.ts b/superset-frontend/packages/superset-ui-core/src/chart/types/VizType.ts
index 58e17e787..110d44f8f 100644
--- a/superset-frontend/packages/superset-ui-core/src/chart/types/VizType.ts
+++ b/superset-frontend/packages/superset-ui-core/src/chart/types/VizType.ts
@@ -26,11 +26,10 @@ export enum VizType {
Bubble = 'bubble_v2',
Bullet = 'bullet',
Calendar = 'cal_heatmap',
+ Cartodiagram = 'cartodiagram',
Chord = 'chord',
Compare = 'compare',
CountryMap = 'country_map',
- DistBar = 'dist_bar',
- EventFlow = 'event_flow',
Funnel = 'funnel',
Gauge = 'gauge_chart',
Graph = 'graph_chart',
@@ -38,13 +37,7 @@ export enum VizType {
Heatmap = 'heatmap_v2',
Histogram = 'histogram_v2',
Horizon = 'horizon',
- LegacyArea = 'area',
- LegacyBar = 'bar',
LegacyBubble = 'bubble',
- LegacyHeatmap = 'heatmap',
- LegacyHistogram = 'histogram',
- LegacyLine = 'line',
- LegacySankey = 'sankey',
Line = 'echarts_timeseries_line',
MapBox = 'mapbox',
MixedTimeseries = 'mixed_timeseries',
diff --git a/superset-frontend/packages/superset-ui-core/src/color/CategoricalColorScale.ts b/superset-frontend/packages/superset-ui-core/src/color/CategoricalColorScale.ts
index 707ae3d4a..53a5b855b 100644
--- a/superset-frontend/packages/superset-ui-core/src/color/CategoricalColorScale.ts
+++ b/superset-frontend/packages/superset-ui-core/src/color/CategoricalColorScale.ts
@@ -65,7 +65,7 @@ class CategoricalColorScale extends ExtensibleFunction {
);
// holds original color scheme colors
this.originColors = colors;
- // holds the extended color range (includes analagous colors)
+ // holds the extended color range (includes analogous colors)
this.colors = colors;
// holds the values of this specific slice (label+color)
this.chartLabelsColorMap = new Map();
@@ -139,7 +139,7 @@ class CategoricalColorScale extends ExtensibleFunction {
// a forced color will always be used independently of the usage count
if (!forcedColor && !isExistingLabel) {
- if (isFeatureEnabled(FeatureFlag.UseAnalagousColors)) {
+ if (isFeatureEnabled(FeatureFlag.UseAnalogousColors)) {
this.incrementColorRange();
}
if (
diff --git a/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx b/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx
index 02db7dadb..d35c2160e 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/components/SafeMarkdown.tsx
@@ -19,7 +19,7 @@
import { useEffect, useMemo, useState } from 'react';
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
import remarkGfm from 'remark-gfm';
-import { mergeWith, isArray } from 'lodash';
+import { mergeWith } from 'lodash';
import { FeatureFlag, isFeatureEnabled } from '../utils';
interface SafeMarkdownProps {
@@ -33,7 +33,7 @@ export function getOverrideHtmlSchema(
htmlSchemaOverrides: SafeMarkdownProps['htmlSchemaOverrides'],
) {
return mergeWith(originalSchema, htmlSchemaOverrides, (objValue, srcValue) =>
- isArray(objValue) ? objValue.concat(srcValue) : undefined,
+ Array.isArray(objValue) ? objValue.concat(srcValue) : undefined,
);
}
diff --git a/superset-frontend/packages/superset-ui-core/src/models/Registry.ts b/superset-frontend/packages/superset-ui-core/src/models/Registry.ts
index 53aff08c4..7488ab824 100644
--- a/superset-frontend/packages/superset-ui-core/src/models/Registry.ts
+++ b/superset-frontend/packages/superset-ui-core/src/models/Registry.ts
@@ -22,11 +22,11 @@ export enum OverwritePolicy {
Warn = 'WARN',
}
-interface ItemWithValue {
+export interface ItemWithValue {
value: T;
}
-interface ItemWithLoader {
+export interface ItemWithLoader {
loader: () => T;
}
diff --git a/superset-frontend/packages/superset-ui-core/src/query/getClientErrorObject.ts b/superset-frontend/packages/superset-ui-core/src/query/getClientErrorObject.ts
index dd26aec61..8097134e6 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/getClientErrorObject.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/getClientErrorObject.ts
@@ -105,7 +105,7 @@ export function parseStringResponse(str: string): string {
}
export function getErrorFromStatusCode(status: number): string | null {
- return ERROR_CODE_LOOKUP[status] || null;
+ return ERROR_CODE_LOOKUP[status as keyof typeof ERROR_CODE_LOOKUP] || null;
}
export function retrieveErrorMessage(
diff --git a/superset-frontend/packages/superset-ui-core/src/query/normalizeOrderBy.ts b/superset-frontend/packages/superset-ui-core/src/query/normalizeOrderBy.ts
index b07338781..840cf4c1a 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/normalizeOrderBy.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/normalizeOrderBy.ts
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { isEmpty, isBoolean } from 'lodash';
+import { isEmpty } from 'lodash';
import { QueryObject } from './types';
@@ -30,7 +30,7 @@ export default function normalizeOrderBy(
Array.isArray(orderbyClause) &&
orderbyClause.length === 2 &&
!isEmpty(orderbyClause[0]) &&
- isBoolean(orderbyClause[1])
+ typeof orderbyClause[1] === 'boolean'
) {
return queryObject;
}
diff --git a/superset-frontend/packages/superset-ui-core/src/query/types/Filter.ts b/superset-frontend/packages/superset-ui-core/src/query/types/Filter.ts
index bd7983f73..a9aa7b653 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/types/Filter.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/types/Filter.ts
@@ -62,6 +62,10 @@ export interface FreeFormAdhocFilter extends BaseAdhocFilter {
sqlExpression: string;
}
+export interface LatestPartitionAdhocFilter extends BaseAdhocFilter {
+ datasource?: { schema?: string; datasource_name?: string };
+}
+
export type AdhocFilter = SimpleAdhocFilter | FreeFormAdhocFilter;
//---------------------------------------------------
diff --git a/superset-frontend/packages/superset-ui-core/src/query/types/Metric.ts b/superset-frontend/packages/superset-ui-core/src/query/types/Metric.ts
index 227ca6e71..229852373 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/types/Metric.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/types/Metric.ts
@@ -17,7 +17,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Maybe, QueryFormMetric } from '../../types';
+import { Currency, Maybe, QueryFormMetric } from '../../types';
import { Column } from './Column';
export type Aggregate =
@@ -65,7 +65,7 @@ export interface Metric {
certification_details?: Maybe;
certified_by?: Maybe;
d3format?: Maybe;
- currency?: Maybe;
+ currency?: Maybe;
description?: Maybe;
is_certified?: boolean;
verbose_name?: string;
diff --git a/superset-frontend/packages/superset-ui-core/src/query/types/Query.ts b/superset-frontend/packages/superset-ui-core/src/query/types/Query.ts
index a83d17a93..4a5f2a685 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/types/Query.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/types/Query.ts
@@ -349,15 +349,17 @@ export type Query = {
};
export type QueryResults = {
- results: {
- displayLimitReached: boolean;
- columns: QueryColumn[];
- data: Record[];
- expanded_columns: QueryColumn[];
- selected_columns: QueryColumn[];
- query: { limit: number };
- query_id?: number;
- };
+ results: InnerQueryResults;
+};
+
+export type InnerQueryResults = {
+ displayLimitReached: boolean;
+ columns: QueryColumn[];
+ data: Record[];
+ expanded_columns: QueryColumn[];
+ selected_columns: QueryColumn[];
+ query: { limit: number };
+ query_id?: number;
};
export type QueryResponse = Query & QueryResults;
diff --git a/superset-frontend/packages/superset-ui-core/src/query/types/QueryResponse.ts b/superset-frontend/packages/superset-ui-core/src/query/types/QueryResponse.ts
index 93c7475d4..b2a3c08cd 100644
--- a/superset-frontend/packages/superset-ui-core/src/query/types/QueryResponse.ts
+++ b/superset-frontend/packages/superset-ui-core/src/query/types/QueryResponse.ts
@@ -79,6 +79,9 @@ export interface ChartDataResponseResult {
| 'timed_out';
from_dttm: number | null;
to_dttm: number | null;
+ // TODO(hainenber): define proper type for below attributes
+ rejected_filters?: any[];
+ applied_filters?: any[];
}
export interface TimeseriesChartDataResponseResult
diff --git a/superset-frontend/packages/superset-ui-core/src/style/index.tsx b/superset-frontend/packages/superset-ui-core/src/style/index.tsx
index ee0b6e10a..d448b81e7 100644
--- a/superset-frontend/packages/superset-ui-core/src/style/index.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/style/index.tsx
@@ -27,6 +27,7 @@ export {
ThemeProvider,
CacheProvider as EmotionCacheProvider,
withTheme,
+ type SerializedStyles,
} from '@emotion/react';
export { default as createEmotionCache } from '@emotion/cache';
@@ -98,13 +99,6 @@ const defaultTheme = {
light2: '#FAEDEE',
},
warning: {
- base: '#FF7F44',
- dark1: '#BF5E33',
- dark2: '#7F3F21',
- light1: '#FEC0A1',
- light2: '#FFF2EC',
- },
- alert: {
base: '#FCC700',
dark1: '#BC9501',
dark2: '#7D6300',
diff --git a/superset-frontend/packages/superset-ui-core/src/ui-overrides/types.ts b/superset-frontend/packages/superset-ui-core/src/ui-overrides/types.ts
index 775e2c129..6583bee73 100644
--- a/superset-frontend/packages/superset-ui-core/src/ui-overrides/types.ts
+++ b/superset-frontend/packages/superset-ui-core/src/ui-overrides/types.ts
@@ -134,13 +134,21 @@ export interface SQLFormExtensionProps {
startQuery: (ctasArg?: any, ctas_method?: any) => void;
}
-export interface SQLResultTableExtentionProps {
+export interface SQLResultTableExtensionProps {
queryId: string;
orderedColumnKeys: string[];
data: Record[];
height: number;
filterText?: string;
expandedColumns?: string[];
+ allowHTML?: boolean;
+}
+
+export interface SQLTablePreviewExtensionProps {
+ dbId: number;
+ catalog?: string;
+ schema: string;
+ tableName: string;
}
/**
@@ -223,9 +231,13 @@ export type Extensions = Partial<{
'database.delete.related': ComponentType;
'dataset.delete.related': ComponentType;
'sqleditor.extension.form': ComponentType;
- 'sqleditor.extension.resultTable': ComponentType;
+ 'sqleditor.extension.resultTable': ComponentType;
'dashboard.slice.header': ComponentType;
'sqleditor.extension.customAutocomplete': (
args: CustomAutoCompleteArgs,
) => CustomAutocomplete[] | undefined;
+ 'sqleditor.extension.tablePreview': [
+ string,
+ 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 be28944a9..7c6041d00 100644
--- a/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts
+++ b/superset-frontend/packages/superset-ui-core/src/utils/featureFlags.ts
@@ -30,12 +30,10 @@ export enum FeatureFlag {
AvoidColorsCollision = 'AVOID_COLORS_COLLISION',
ChartPluginsExperimental = 'CHART_PLUGINS_EXPERIMENTAL',
ConfirmDashboardDiff = 'CONFIRM_DASHBOARD_DIFF',
- /** @deprecated */
- DashboardCrossFilters = 'DASHBOARD_CROSS_FILTERS',
DashboardVirtualization = 'DASHBOARD_VIRTUALIZATION',
DashboardRbac = 'DASHBOARD_RBAC',
DatapanelClosedByDefault = 'DATAPANEL_CLOSED_BY_DEFAULT',
- DisableLegacyDatasourceEditor = 'DISABLE_LEGACY_DATASOURCE_EDITOR',
+ /** @deprecated */
DrillToDetail = 'DRILL_TO_DETAIL',
DrillBy = 'DRILL_BY',
DynamicPlugins = 'DYNAMIC_PLUGINS',
@@ -51,13 +49,12 @@ export enum FeatureFlag {
HorizontalFilterBar = 'HORIZONTAL_FILTER_BAR',
ListviewsDefaultCardView = 'LISTVIEWS_DEFAULT_CARD_VIEW',
ScheduledQueries = 'SCHEDULED_QUERIES',
- ShareQueriesViaKvStore = 'SHARE_QUERIES_VIA_KV_STORE',
SqllabBackendPersistence = 'SQLLAB_BACKEND_PERSISTENCE',
SqlValidatorsByEngine = 'SQL_VALIDATORS_BY_ENGINE',
SshTunneling = 'SSH_TUNNELING',
TaggingSystem = 'TAGGING_SYSTEM',
Thumbnails = 'THUMBNAILS',
- UseAnalagousColors = 'USE_ANALAGOUS_COLORS',
+ UseAnalogousColors = 'USE_ANALOGOUS_COLORS',
ForceSqlLabRunAsync = 'SQLLAB_FORCE_RUN_ASYNC',
SlackEnableAvatars = 'SLACK_ENABLE_AVATARS',
EnableDashboardScreenshotEndpoints = 'ENABLE_DASHBOARD_SCREENSHOT_ENDPOINTS',
@@ -96,7 +93,7 @@ export function initFeatureFlags(featureFlags?: FeatureFlagMap) {
export function isFeatureEnabled(feature: FeatureFlag): boolean {
try {
- return !!window.featureFlags[feature];
+ return !!window.featureFlags[feature as keyof FeatureFlagMap];
} catch (error) {
logger.error(`Failed to query feature flag ${feature}`);
}
diff --git a/superset-frontend/packages/superset-ui-core/src/validator/validateNumber.ts b/superset-frontend/packages/superset-ui-core/src/validator/validateNumber.ts
index 7de5f3f27..3775a56cb 100644
--- a/superset-frontend/packages/superset-ui-core/src/validator/validateNumber.ts
+++ b/superset-frontend/packages/superset-ui-core/src/validator/validateNumber.ts
@@ -19,7 +19,7 @@
import { t } from '../translation';
-export default function validateInteger(v: unknown) {
+export default function validateInteger(v: any) {
if (
(typeof v === 'string' &&
v.trim().length > 0 &&
diff --git a/superset-frontend/packages/superset-ui-core/test/chart-composition/legend/WithLegend.test.tsx b/superset-frontend/packages/superset-ui-core/test/chart-composition/legend/WithLegend.test.tsx
index 4f6f909f9..9d660a28a 100644
--- a/superset-frontend/packages/superset-ui-core/test/chart-composition/legend/WithLegend.test.tsx
+++ b/superset-frontend/packages/superset-ui-core/test/chart-composition/legend/WithLegend.test.tsx
@@ -24,7 +24,8 @@ import { promiseTimeout, WithLegend } from '@superset-ui/core';
let renderChart = jest.fn();
let renderLegend = jest.fn();
-describe('WithLegend', () => {
+// TODO: rewrite to rtl
+describe.skip('WithLegend', () => {
beforeEach(() => {
renderChart = jest.fn(() => );
renderLegend = jest.fn(() => );
diff --git a/superset-frontend/packages/superset-ui-core/test/chart/clients/ChartClient.test.ts b/superset-frontend/packages/superset-ui-core/test/chart/clients/ChartClient.test.ts
index 50238d3d7..f34c4b84e 100644
--- a/superset-frontend/packages/superset-ui-core/test/chart/clients/ChartClient.test.ts
+++ b/superset-frontend/packages/superset-ui-core/test/chart/clients/ChartClient.test.ts
@@ -87,13 +87,13 @@ describe('ChartClient', () => {
sliceId,
formData: {
granularity: 'second',
- viz_type: VizType.LegacyBar,
+ viz_type: VizType.Bar,
},
}),
).resolves.toEqual({
...sankeyFormData,
granularity: 'second',
- viz_type: VizType.LegacyBar,
+ viz_type: VizType.Bar,
});
});
it('returns promise of formData if only formData was given', () =>
@@ -102,13 +102,13 @@ describe('ChartClient', () => {
formData: {
datasource: '1__table',
granularity: 'minute',
- viz_type: VizType.LegacyLine,
+ viz_type: VizType.Line,
},
}),
).resolves.toEqual({
datasource: '1__table',
granularity: 'minute',
- viz_type: VizType.LegacyLine,
+ viz_type: VizType.Line,
}));
it('rejects if none of sliceId or formData is specified', () =>
expect(
@@ -256,7 +256,7 @@ describe('ChartClient', () => {
it('loadAllDataNecessaryForAChart', () => {
fetchMock.get(`glob:*/api/v1/form_data/?slice_id=${sliceId}`, {
granularity: 'minute',
- viz_type: VizType.LegacyLine,
+ viz_type: VizType.Line,
datasource: '1__table',
color: 'living-coral',
});
@@ -276,12 +276,12 @@ describe('ChartClient', () => {
});
getChartMetadataRegistry().registerValue(
- VizType.LegacyLine,
+ VizType.Line,
new ChartMetadata({ name: 'Line', thumbnail: '.gif' }),
);
getChartBuildQueryRegistry().registerValue(
- VizType.LegacyLine,
+ VizType.Line,
(formData: QueryFormData) => buildQueryContext(formData),
);
@@ -297,7 +297,7 @@ describe('ChartClient', () => {
},
formData: {
granularity: 'minute',
- viz_type: VizType.LegacyLine,
+ viz_type: VizType.Line,
datasource: '1__table',
color: 'living-coral',
},
diff --git a/superset-frontend/packages/superset-ui-core/test/chart/components/FallbackComponent.test.tsx b/superset-frontend/packages/superset-ui-core/test/chart/components/FallbackComponent.test.tsx
index 2a52c62e5..638e5b17b 100644
--- a/superset-frontend/packages/superset-ui-core/test/chart/components/FallbackComponent.test.tsx
+++ b/superset-frontend/packages/superset-ui-core/test/chart/components/FallbackComponent.test.tsx
@@ -24,7 +24,9 @@ import { ThemeProvider, supersetTheme } from '../../../src/style';
import FallbackComponent from '../../../src/chart/components/FallbackComponent';
-const renderWithTheme = (props: FallbackProps) =>
+const renderWithTheme = (
+ props: Partial & FallbackProps['error'],
+) =>
render(
@@ -32,28 +34,12 @@ const renderWithTheme = (props: FallbackProps) =>
);
const ERROR = new Error('CaffeineOverLoadException');
-const STACK_TRACE = 'Error at line 1: x.drink(coffee)';
-
-test('renders error and stack trace', () => {
- const { getByText } = renderWithTheme({
- componentStack: STACK_TRACE,
- error: ERROR,
- });
- expect(getByText('Error: CaffeineOverLoadException')).toBeInTheDocument();
- expect(getByText('Error at line 1: x.drink(coffee)')).toBeInTheDocument();
-});
test('renders error only', () => {
const { getByText } = renderWithTheme({ error: ERROR });
expect(getByText('Error: CaffeineOverLoadException')).toBeInTheDocument();
});
-test('renders stacktrace only', () => {
- const { getByText } = renderWithTheme({ componentStack: STACK_TRACE });
- expect(getByText('Unknown Error')).toBeInTheDocument();
- expect(getByText('Error at line 1: x.drink(coffee)')).toBeInTheDocument();
-});
-
test('renders when nothing is given', () => {
const { getByText } = renderWithTheme({});
expect(getByText('Unknown Error')).toBeInTheDocument();
diff --git a/superset-frontend/packages/superset-ui-core/test/chart/components/SuperChart.test.tsx b/superset-frontend/packages/superset-ui-core/test/chart/components/SuperChart.test.tsx
index a602279ba..542867cfd 100644
--- a/superset-frontend/packages/superset-ui-core/test/chart/components/SuperChart.test.tsx
+++ b/superset-frontend/packages/superset-ui-core/test/chart/components/SuperChart.test.tsx
@@ -45,7 +45,7 @@ const DEFAULT_QUERIES_DATA = [
];
function expectDimension(
- renderedWrapper: Cheerio,
+ renderedWrapper: cheerio.Cheerio,
width: number,
height: number,
) {
@@ -60,7 +60,8 @@ const mount = (component: ReactElement) =>
wrappingComponentProps: { theme: supersetTheme },
});
-describe('SuperChart', () => {
+// TODO: rewrite to rtl
+describe.skip('SuperChart', () => {
const plugins = [
new DiligentChartPlugin().configure({ key: ChartKeys.DILIGENT }),
new BuggyChartPlugin().configure({ key: ChartKeys.BUGGY }),
@@ -165,6 +166,7 @@ describe('SuperChart', () => {
const inactiveErrorHandler = jest.fn();
const activeErrorHandler = jest.fn();
mount(
+ // @ts-ignore
{
});
it('get analogous colors when number of items exceed available colors', () => {
window.featureFlags = {
- [FeatureFlag.UseAnalagousColors]: true,
+ [FeatureFlag.UseAnalogousColors]: true,
};
const scale = new CategoricalColorScale(['blue', 'red', 'green']);
scale.getColor('pig');
diff --git a/superset-frontend/packages/superset-ui-core/test/color/LabelsColorMapSingleton.test.ts b/superset-frontend/packages/superset-ui-core/test/color/LabelsColorMapSingleton.test.ts
index 24521d2d9..c4ac0e4ff 100644
--- a/superset-frontend/packages/superset-ui-core/test/color/LabelsColorMapSingleton.test.ts
+++ b/superset-frontend/packages/superset-ui-core/test/color/LabelsColorMapSingleton.test.ts
@@ -212,7 +212,7 @@ describe('LabelsColorMap', () => {
it('should use recycle colors', () => {
window.featureFlags = {
- [FeatureFlag.UseAnalagousColors]: false,
+ [FeatureFlag.UseAnalogousColors]: false,
};
labelsColorMap.addSlice('a', 'red', 1);
labelsColorMap.addSlice('b', 'blue', 2);
@@ -224,9 +224,9 @@ describe('LabelsColorMap', () => {
expect(getAnalogousColorsSpy).not.toHaveBeenCalled();
});
- it('should use analagous colors', () => {
+ it('should use analogous colors', () => {
window.featureFlags = {
- [FeatureFlag.UseAnalagousColors]: true,
+ [FeatureFlag.UseAnalogousColors]: true,
};
labelsColorMap.addSlice('a', 'red', 1);
diff --git a/superset-frontend/packages/superset-ui-core/test/query/api/legacy/getFormData.test.ts b/superset-frontend/packages/superset-ui-core/test/query/api/legacy/getFormData.test.ts
index 5d46f1a35..4987d8b91 100644
--- a/superset-frontend/packages/superset-ui-core/test/query/api/legacy/getFormData.test.ts
+++ b/superset-frontend/packages/superset-ui-core/test/query/api/legacy/getFormData.test.ts
@@ -29,7 +29,7 @@ describe('getFormData()', () => {
const mockData = {
datasource: '1__table',
- viz_type: VizType.LegacySankey,
+ viz_type: VizType.Sankey,
slice_id: 1,
url_params: {},
granularity_sqla: null,
diff --git a/superset-frontend/packages/superset-ui-core/test/time-comparison/customTimeRangeDecode.test.ts b/superset-frontend/packages/superset-ui-core/test/time-comparison/customTimeRangeDecode.test.ts
index d5342098a..b33841134 100644
--- a/superset-frontend/packages/superset-ui-core/test/time-comparison/customTimeRangeDecode.test.ts
+++ b/superset-frontend/packages/superset-ui-core/test/time-comparison/customTimeRangeDecode.test.ts
@@ -202,4 +202,82 @@ describe('customTimeRangeDecode', () => {
matchedFlag: false,
});
});
+
+ it('9) empty string returns default', () => {
+ const SEVEN_DAYS_AGO = new Date();
+ SEVEN_DAYS_AGO.setHours(0, 0, 0, 0);
+
+ const MIDNIGHT = new Date();
+ MIDNIGHT.setHours(0, 0, 0, 0);
+
+ expect(customTimeRangeDecode('')).toEqual({
+ customRange: {
+ sinceDatetime: SEVEN_DAYS_AGO.setDate(
+ SEVEN_DAYS_AGO.getDate() - 7,
+ ).toString(),
+ sinceMode: 'relative',
+ sinceGrain: 'day',
+ sinceGrainValue: -7,
+ untilDatetime: MIDNIGHT.toString(),
+ untilMode: 'specific',
+ untilGrain: 'day',
+ untilGrainValue: 7,
+ anchorMode: 'now',
+ anchorValue: 'now',
+ },
+ matchedFlag: false,
+ });
+ });
+
+ it('10) both undefined returns default', () => {
+ const SEVEN_DAYS_AGO = new Date();
+ SEVEN_DAYS_AGO.setHours(0, 0, 0, 0);
+
+ const MIDNIGHT = new Date();
+ MIDNIGHT.setHours(0, 0, 0, 0);
+
+ expect(customTimeRangeDecode('undefined : undefined')).toEqual({
+ customRange: {
+ sinceDatetime: SEVEN_DAYS_AGO.setDate(
+ SEVEN_DAYS_AGO.getDate() - 7,
+ ).toString(),
+ sinceMode: 'relative',
+ sinceGrain: 'day',
+ sinceGrainValue: -7,
+ untilDatetime: MIDNIGHT.toString(),
+ untilMode: 'specific',
+ untilGrain: 'day',
+ untilGrainValue: 7,
+ anchorMode: 'now',
+ anchorValue: 'now',
+ },
+ matchedFlag: false,
+ });
+ });
+
+ it('11) 1 side undefined returns default', () => {
+ const SEVEN_DAYS_AGO = new Date();
+ SEVEN_DAYS_AGO.setHours(0, 0, 0, 0);
+
+ const MIDNIGHT = new Date();
+ MIDNIGHT.setHours(0, 0, 0, 0);
+
+ expect(customTimeRangeDecode('undefined : now')).toEqual({
+ customRange: {
+ sinceDatetime: SEVEN_DAYS_AGO.setDate(
+ SEVEN_DAYS_AGO.getDate() - 7,
+ ).toString(),
+ sinceMode: 'relative',
+ sinceGrain: 'day',
+ sinceGrainValue: -7,
+ untilDatetime: MIDNIGHT.toString(),
+ untilMode: 'specific',
+ untilGrain: 'day',
+ untilGrainValue: 7,
+ anchorMode: 'now',
+ anchorValue: 'now',
+ },
+ matchedFlag: false,
+ });
+ });
});
diff --git a/superset-frontend/packages/superset-ui-demo/package.json b/superset-frontend/packages/superset-ui-demo/package.json
index 80c3dcf46..526c9a6ad 100644
--- a/superset-frontend/packages/superset-ui-demo/package.json
+++ b/superset-frontend/packages/superset-ui-demo/package.json
@@ -31,9 +31,8 @@
"storybook": "storybook dev -p 9001"
},
"dependencies": {
- "@data-ui/event-flow": "^0.0.84",
- "@emotion/cache": "^11.4.0",
- "@emotion/react": "^11.13.3",
+ "@emotion/cache": "^11.14.0",
+ "@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"@mihkeleidast/storybook-addon-source": "^1.0.1",
"@react-icons/all-files": "^4.1.0",
@@ -44,17 +43,17 @@
"@storybook/types": "8.4.7",
"@types/react-loadable": "^5.5.11",
"antd": "4.10.3",
- "core-js": "3.38.1",
+ "core-js": "3.39.0",
"gh-pages": "^6.2.0",
"jquery": "^3.7.1",
"memoize-one": "^5.2.1",
- "react": "^16.13.1",
- "react-dom": "^16.13.1",
+ "react": "^17.0.2",
+ "react-dom": "^17.0.2",
"react-loadable": "^5.5.0",
"react-resizable": "^3.0.5"
},
"devDependencies": {
- "@babel/core": "^7.23.9",
+ "@babel/core": "^7.26.0",
"@babel/preset-env": "^7.23.9",
"@babel/preset-react": "^7.26.3",
"@babel/preset-typescript": "^7.23.3",
@@ -70,18 +69,12 @@
"@superset-ui/legacy-plugin-chart-calendar": "*",
"@superset-ui/legacy-plugin-chart-chord": "*",
"@superset-ui/legacy-plugin-chart-country-map": "*",
- "@superset-ui/legacy-plugin-chart-event-flow": "*",
- "@superset-ui/legacy-plugin-chart-heatmap": "*",
- "@superset-ui/legacy-plugin-chart-histogram": "*",
"@superset-ui/legacy-plugin-chart-horizon": "*",
"@superset-ui/legacy-plugin-chart-map-box": "*",
"@superset-ui/legacy-plugin-chart-paired-t-test": "*",
"@superset-ui/legacy-plugin-chart-parallel-coordinates": "*",
"@superset-ui/legacy-plugin-chart-partition": "*",
"@superset-ui/legacy-plugin-chart-rose": "*",
- "@superset-ui/legacy-plugin-chart-sankey": "*",
- "@superset-ui/legacy-plugin-chart-sankey-loop": "*",
- "@superset-ui/legacy-plugin-chart-time-table": "*",
"@superset-ui/legacy-plugin-chart-world-map": "*",
"@superset-ui/legacy-preset-chart-deckgl": "*",
"@superset-ui/legacy-preset-chart-nvd3": "*",
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-heatmap/Heatmap.stories.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-heatmap/Heatmap.stories.tsx
deleted file mode 100644
index c45ea21a5..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-heatmap/Heatmap.stories.tsx
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import HeatmapChartPlugin from '@superset-ui/legacy-plugin-chart-heatmap';
-import ResizableChartDemo from '../../../shared/components/ResizableChartDemo';
-import data from './data';
-
-new HeatmapChartPlugin().configure({ key: VizType.LegacyHeatmap }).register();
-
-export default {
- title: 'Legacy Chart Plugins/legacy-plugin-chart-heatmap',
-};
-
-export const basic = () => (
-
-);
-
-export const resizable = () => (
-
- {({ width, height }) => (
-
- )}
-
-);
-
-export const withNullData = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-heatmap/data.ts b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-heatmap/data.ts
deleted file mode 100644
index 4a1a6f6f3..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-heatmap/data.ts
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export default [
- {
- x: 'Energy',
- y: 'Electricity and heat',
- v: 24.9,
- perc: 1.0,
- rank: 1.0,
- },
- {
- x: 'Energy',
- y: 'Industry',
- v: 14.7,
- perc: 0.5887096774193549,
- rank: 0.9882352941176471,
- },
- {
- x: 'Energy',
- y: 'Transportation',
- v: 14.3,
- perc: 0.5725806451612905,
- rank: 0.9764705882352941,
- },
- {
- x: 'Deforestation',
- y: 'Carbon Dioxide',
- v: 10.9,
- perc: 0.435483870967742,
- rank: 0.9588235294117647,
- },
- {
- x: 'Land Use Change',
- y: 'Deforestation',
- v: 10.9,
- perc: 0.435483870967742,
- rank: 0.9588235294117647,
- },
- {
- x: 'Road',
- y: 'Carbon Dioxide',
- v: 10.5,
- perc: 0.4193548387096775,
- rank: 0.9352941176470588,
- },
- {
- x: 'Transportation',
- y: 'Road',
- v: 10.5,
- perc: 0.4193548387096775,
- rank: 0.9352941176470588,
- },
- {
- x: 'Residential Buildings',
- y: 'Carbon Dioxide',
- v: 10.2,
- perc: 0.40725806451612906,
- rank: 0.9176470588235294,
- },
- {
- x: 'Energy',
- y: 'Other Fuel Combustion',
- v: 8.6,
- perc: 0.342741935483871,
- rank: 0.9058823529411765,
- },
- {
- x: 'Other Industry',
- y: 'Carbon Dioxide',
- v: 6.6,
- perc: 0.26209677419354843,
- rank: 0.8941176470588236,
- },
- {
- x: 'Commercial Buildings',
- y: 'Carbon Dioxide',
- v: 6.3,
- perc: 0.25000000000000006,
- rank: 0.8823529411764706,
- },
- {
- x: 'Agriculture',
- y: 'Livestock and Manure',
- v: 5.4,
- perc: 0.2137096774193549,
- rank: 0.8705882352941177,
- },
- {
- x: 'Agriculture',
- y: 'Agriculture Soils',
- v: 5.2,
- perc: 0.20564516129032262,
- rank: 0.8470588235294118,
- },
- {
- x: 'Agriculture Soils',
- y: 'Nitrous Oxide',
- v: 5.2,
- perc: 0.20564516129032262,
- rank: 0.8470588235294118,
- },
- {
- x: 'Oil and Gas Processing',
- y: 'Methane',
- v: 2.8,
- perc: 0.10887096774193548,
- rank: 0.6705882352941176,
- },
- {
- x: 'Electricity and heat',
- y: 'Other Industry',
- v: 2.7,
- perc: 0.10483870967741937,
- rank: 0.6470588235294118,
- },
- {
- x: 'Rail - Ship and Other Transport',
- y: 'Carbon Dioxide',
- v: 2.5,
- perc: 0.09677419354838711,
- rank: 0.6294117647058823,
- },
- {
- x: 'Transportation',
- y: 'Rail - Ship and Other Transport',
- v: 2.5,
- perc: 0.09677419354838711,
- rank: 0.6294117647058823,
- },
- {
- x: 'Electricity and heat',
- y: 'T and D Losses',
- v: 2.2,
- perc: 0.08467741935483872,
- rank: 0.6058823529411764,
- },
- {
- x: 'T and D Losses',
- y: 'Carbon Dioxide',
- v: 2.2,
- perc: 0.08467741935483872,
- rank: 0.6058823529411764,
- },
- {
- x: 'Electricity and heat',
- y: 'Unallocated Fuel Combustion',
- v: 2.0,
- perc: 0.07661290322580645,
- rank: 0.5882352941176471,
- },
- {
- x: 'Industry',
- y: 'Cement',
- v: 1.9,
- perc: 0.07258064516129033,
- rank: 0.5764705882352941,
- },
- {
- x: 'Other Fuel Combustion',
- y: 'Unallocated Fuel Combustion',
- v: 1.8,
- perc: 0.0685483870967742,
- rank: 0.5647058823529412,
- },
-];
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-histogram/Histogram.stories.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-histogram/Histogram.stories.tsx
deleted file mode 100644
index c6f3badcd..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-histogram/Histogram.stories.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.
- */
-
-/* eslint-disable no-magic-numbers */
-import { SuperChart, VizType } from '@superset-ui/core';
-import HistogramChartPlugin from '@superset-ui/legacy-plugin-chart-histogram';
-import data from './data';
-
-new HistogramChartPlugin()
- .configure({ key: VizType.LegacyHistogram })
- .register();
-
-export default {
- title: 'Legacy Chart Plugins/legacy-plugin-chart-histogram',
-};
-
-export const basic = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-histogram/data.ts b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-histogram/data.ts
deleted file mode 100644
index 21ac39d50..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-histogram/data.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-/* eslint-disable sort-keys, no-magic-numbers */
-export default [
- {
- key: 'Entrance exam',
- values: [
- 0.87, 0.944, 1.0, 0.879, 0.69, 0.667, 0.794, 0.838, 0.875, 0.385, 0.968,
- 0.804, 1.0, 0.943, 0.96, 0.333, 0.5, 0.929, 0.863, 0.75, 0.957, 0.914,
- 1.0, 0.909, 0.742, 0.964, 0.25, 0.75, 0.5, 0.867, 0.909, 0.333, 0.867,
- 0.952, 0.857, 0.949, 0.857, 0.333, 0.8, 0.707, 0.833, 0.75, 0.88, 0.771,
- 1.0, 1.0, 0.769, 1.0, 0.769, 0.622, 0.909, 0.725, 0.951, 1.0,
- ],
- },
-];
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sankey-loop/SankeyLoop.stories.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sankey-loop/SankeyLoop.stories.tsx
deleted file mode 100644
index 97ec3f05e..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sankey-loop/SankeyLoop.stories.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-
-/* eslint-disable no-magic-numbers */
-import { SuperChart } from '@superset-ui/core';
-import SankeyLoopChartPlugin from '@superset-ui/legacy-plugin-chart-sankey-loop';
-import data from './data';
-
-new SankeyLoopChartPlugin().configure({ key: 'sankey-loop' }).register();
-
-export default {
- title: 'Legacy Chart Plugins/legacy-plugin-chart-sankey-loop',
-};
-
-export const basic = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sankey-loop/data.ts b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sankey-loop/data.ts
deleted file mode 100644
index b310af21b..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sankey-loop/data.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.
- */
-
-/* eslint-disable sort-keys, no-magic-numbers */
-export default [
- {
- source: 'Lisdoonvarna',
- target: 'Cliffs of Moher',
- value: 50,
- },
- {
- source: 'Cliffs of Moher',
- target: 'Lisdoonvarna',
- value: 35,
- },
- {
- source: 'Cliffs of Moher',
- target: 'Killarney',
- value: 25,
- },
- {
- source: 'Lisdoonvarna',
- target: 'Killarney',
- value: 25,
- },
- {
- source: 'Lisdoonvarna',
- target: 'Kinvarra',
- value: 25,
- },
- {
- source: 'Kinvarra',
- target: 'Lisdoonvarna',
- value: 25,
- },
-];
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sankey/Sankey.stories.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sankey/Sankey.stories.tsx
deleted file mode 100644
index dcc9f5c44..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sankey/Sankey.stories.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.
- */
-
-/* eslint-disable no-magic-numbers */
-import { SuperChart, VizType } from '@superset-ui/core';
-import SankeyChartPlugin from '@superset-ui/legacy-plugin-chart-sankey';
-import ResizableChartDemo from '../../../shared/components/ResizableChartDemo';
-import data from './data';
-
-new SankeyChartPlugin().configure({ key: VizType.LegacySankey }).register();
-
-export default {
- title: 'Legacy Chart Plugins/legacy-plugin-chart-sankey',
-};
-
-export const basic = () => (
-
-);
-
-export const resizable = () => (
-
- {({ width, height }) => (
-
- )}
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sankey/data.ts b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sankey/data.ts
deleted file mode 100644
index df04dff32..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-plugin-chart-sankey/data.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.
- */
-
-/* eslint-disable sort-keys, no-magic-numbers */
-export default [
- {
- source: 'Energy',
- target: 'Electricity and heat',
- value: 24.9,
- },
- {
- source: 'Energy',
- target: 'Industry',
- value: 14.7,
- },
- {
- source: 'Energy',
- target: 'Transportation',
- value: 14.3,
- },
- {
- source: 'Deforestation',
- target: 'Carbon Dioxide',
- value: 10.9,
- },
- {
- source: 'Land Use Change',
- target: 'Deforestation',
- value: 10.9,
- },
- {
- source: 'Road',
- target: 'Carbon Dioxide',
- value: 10.5,
- },
- {
- source: 'Transportation',
- target: 'Road',
- value: 10.5,
- },
- {
- source: 'Residential Buildings',
- target: 'Carbon Dioxide',
- value: 10.2,
- },
- {
- source: 'Energy',
- target: 'Other Fuel Combustion',
- value: 8.6,
- },
- {
- source: 'Other Industry',
- target: 'Carbon Dioxide',
- value: 6.6,
- },
-];
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/NVD3Area.stories.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/NVD3Area.stories.tsx
deleted file mode 100644
index b1f4a9ebe..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/NVD3Area.stories.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { VizType } from '@superset-ui/core';
-import { AreaChartPlugin } from '@superset-ui/legacy-preset-chart-nvd3';
-
-new AreaChartPlugin().configure({ key: VizType.LegacyArea }).register();
-
-export default {
- title: 'Legacy Chart Plugins/legacy-preset-chart-nvd3/Area',
-};
-
-export { stacked } from './stories/stacked';
-export {
- stackedWithYAxisBounds,
- stackedWithYAxisBoundsMinOnly,
-} from './stories/stackedWithBounds';
-export { expanded } from './stories/expanded';
-export { controlsShown } from './stories/controlsShown';
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/data.ts b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/data.ts
deleted file mode 100644
index 9372f798b..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/data.ts
+++ /dev/null
@@ -1,1147 +0,0 @@
-/*
- * 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.
- */
-
-/* eslint-disable sort-keys */
-export default [
- {
- key: ['East Asia & Pacific'],
- values: [
- {
- x: -315619200000.0,
- y: 1031863394.0,
- },
- {
- x: -283996800000.0,
- y: 1034767718.0,
- },
- {
- x: -252460800000.0,
- y: 1048537618.0,
- },
- {
- x: -220924800000.0,
- y: 1073600747.0,
- },
- {
- x: -189388800000.0,
- y: 1098305025.0,
- },
- {
- x: -157766400000.0,
- y: 1124077872.0,
- },
- {
- x: -126230400000.0,
- y: 1153296196.0,
- },
- {
- x: -94694400000.0,
- y: 1181582226.0,
- },
- {
- x: -63158400000.0,
- y: 1210302481.0,
- },
- {
- x: -31536000000.0,
- y: 1242569208.0,
- },
- {
- x: 0.0,
- y: 1274888198.0,
- },
- {
- x: 31536000000.0,
- y: 1308215425.0,
- },
- {
- x: 63072000000.0,
- y: 1339781984.0,
- },
- {
- x: 94694400000.0,
- y: 1369814002.0,
- },
- {
- x: 126230400000.0,
- y: 1399636343.0,
- },
- {
- x: 157766400000.0,
- y: 1426562368.0,
- },
- {
- x: 189302400000.0,
- y: 1450503110.0,
- },
- {
- x: 220924800000.0,
- y: 1473091499.0,
- },
- {
- x: 252460800000.0,
- y: 1495573053.0,
- },
- {
- x: 283996800000.0,
- y: 1518439245.0,
- },
- {
- x: 315532800000.0,
- y: 1540823440.0,
- },
- {
- x: 347155200000.0,
- y: 1563926423.0,
- },
- {
- x: 378691200000.0,
- y: 1589245249.0,
- },
- {
- x: 410227200000.0,
- y: 1614538807.0,
- },
- {
- x: 441763200000.0,
- y: 1638618355.0,
- },
- {
- x: 473385600000.0,
- y: 1663385538.0,
- },
- {
- x: 504921600000.0,
- y: 1689894237.0,
- },
- {
- x: 536457600000.0,
- y: 1717904169.0,
- },
- {
- x: 567993600000.0,
- y: 1746140324.0,
- },
- {
- x: 599616000000.0,
- y: 1773743982.0,
- },
- {
- x: 631152000000.0,
- y: 1800365903.0,
- },
- {
- x: 662688000000.0,
- y: 1825955698.0,
- },
- {
- x: 694224000000.0,
- y: 1849800435.0,
- },
- {
- x: 725846400000.0,
- y: 1872809684.0,
- },
- {
- x: 757382400000.0,
- y: 1895892806.0,
- },
- {
- x: 788918400000.0,
- y: 1918680993.0,
- },
- {
- x: 820454400000.0,
- y: 1941199188.0,
- },
- {
- x: 852076800000.0,
- y: 1963227851.0,
- },
- {
- x: 883612800000.0,
- y: 1984508261.0,
- },
- {
- x: 915148800000.0,
- y: 2004495631.0,
- },
- {
- x: 946684800000.0,
- y: 2023534787.0,
- },
- {
- x: 978307200000.0,
- y: 2041915058.0,
- },
- {
- x: 1009843200000.0,
- y: 2059375225.0,
- },
- {
- x: 1041379200000.0,
- y: 2076029083.0,
- },
- {
- x: 1072915200000.0,
- y: 2092086887.0,
- },
- {
- x: 1104537600000.0,
- y: 2107802765.0,
- },
- {
- x: 1136073600000.0,
- y: 2123180222.0,
- },
- {
- x: 1167609600000.0,
- y: 2137834848.0,
- },
- {
- x: 1199145600000.0,
- y: 2152663168.0,
- },
- {
- x: 1230768000000.0,
- y: 2167098541.0,
- },
- {
- x: 1262304000000.0,
- y: 2181465325.0,
- },
- {
- x: 1293840000000.0,
- y: 2195899073.0,
- },
- {
- x: 1325376000000.0,
- y: 2210627396.0,
- },
- {
- x: 1356998400000.0,
- y: 2225523116.0,
- },
- {
- x: 1388534400000.0,
- y: 2240687901.0,
- },
- ],
- },
- {
- key: ['South Asia'],
- values: [
- {
- x: -315619200000.0,
- y: 572036107.0,
- },
- {
- x: -283996800000.0,
- y: 584143236.0,
- },
- {
- x: -252460800000.0,
- y: 596701125.0,
- },
- {
- x: -220924800000.0,
- y: 609571502.0,
- },
- {
- x: -189388800000.0,
- y: 623073110.0,
- },
- {
- x: -157766400000.0,
- y: 636963781.0,
- },
- {
- x: -126230400000.0,
- y: 651325994.0,
- },
- {
- x: -94694400000.0,
- y: 666134328.0,
- },
- {
- x: -63158400000.0,
- y: 681405837.0,
- },
- {
- x: -31536000000.0,
- y: 697060567.0,
- },
- {
- x: 0.0,
- y: 713115397.0,
- },
- {
- x: 31536000000.0,
- y: 729469562.0,
- },
- {
- x: 63072000000.0,
- y: 746222138.0,
- },
- {
- x: 94694400000.0,
- y: 763491289.0,
- },
- {
- x: 126230400000.0,
- y: 781254784.0,
- },
- {
- x: 157766400000.0,
- y: 799620311.0,
- },
- {
- x: 189302400000.0,
- y: 818590962.0,
- },
- {
- x: 220924800000.0,
- y: 838141522.0,
- },
- {
- x: 252460800000.0,
- y: 858266916.0,
- },
- {
- x: 283996800000.0,
- y: 878939779.0,
- },
- {
- x: 315532800000.0,
- y: 900085240.0,
- },
- {
- x: 347155200000.0,
- y: 921521635.0,
- },
- {
- x: 378691200000.0,
- y: 943662470.0,
- },
- {
- x: 410227200000.0,
- y: 966101576.0,
- },
- {
- x: 441763200000.0,
- y: 988898603.0,
- },
- {
- x: 473385600000.0,
- y: 1012110768.0,
- },
- {
- x: 504921600000.0,
- y: 1035703508.0,
- },
- {
- x: 536457600000.0,
- y: 1059570231.0,
- },
- {
- x: 567993600000.0,
- y: 1083711645.0,
- },
- {
- x: 599616000000.0,
- y: 1108132042.0,
- },
- {
- x: 631152000000.0,
- y: 1132775493.0,
- },
- {
- x: 662688000000.0,
- y: 1157716007.0,
- },
- {
- x: 694224000000.0,
- y: 1182766320.0,
- },
- {
- x: 725846400000.0,
- y: 1208041749.0,
- },
- {
- x: 757382400000.0,
- y: 1233462879.0,
- },
- {
- x: 788918400000.0,
- y: 1258964893.0,
- },
- {
- x: 820454400000.0,
- y: 1284467586.0,
- },
- {
- x: 852076800000.0,
- y: 1310020410.0,
- },
- {
- x: 883612800000.0,
- y: 1335551944.0,
- },
- {
- x: 915148800000.0,
- y: 1361114276.0,
- },
- {
- x: 946684800000.0,
- y: 1386400954.0,
- },
- {
- x: 978307200000.0,
- y: 1411281514.0,
- },
- {
- x: 1009843200000.0,
- y: 1436503016.0,
- },
- {
- x: 1041379200000.0,
- y: 1461682019.0,
- },
- {
- x: 1072915200000.0,
- y: 1486598228.0,
- },
- {
- x: 1104537600000.0,
- y: 1511119581.0,
- },
- {
- x: 1136073600000.0,
- y: 1535264779.0,
- },
- {
- x: 1167609600000.0,
- y: 1559023139.0,
- },
- {
- x: 1199145600000.0,
- y: 1582535507.0,
- },
- {
- x: 1230768000000.0,
- y: 1605893501.0,
- },
- {
- x: 1262304000000.0,
- y: 1629189137.0,
- },
- {
- x: 1293840000000.0,
- y: 1652449539.0,
- },
- {
- x: 1325376000000.0,
- y: 1674883124.0,
- },
- {
- x: 1356998400000.0,
- y: 1697955143.0,
- },
- {
- x: 1388534400000.0,
- y: 1720976995.0,
- },
- ],
- },
- {
- key: ['Europe & Central Asia'],
- values: [
- {
- x: -315619200000.0,
- y: 660881033.0,
- },
- {
- x: -283996800000.0,
- y: 668526708.0,
- },
- {
- x: -252460800000.0,
- y: 676418331.0,
- },
- {
- x: -220924800000.0,
- y: 684369825.0,
- },
- {
- x: -189388800000.0,
- y: 692233988.0,
- },
- {
- x: -157766400000.0,
- y: 699849949.0,
- },
- {
- x: -126230400000.0,
- y: 706459925.0,
- },
- {
- x: -94694400000.0,
- y: 712871897.0,
- },
- {
- x: -63158400000.0,
- y: 719034272.0,
- },
- {
- x: -31536000000.0,
- y: 725099571.0,
- },
- {
- x: 0.0,
- y: 730528170.0,
- },
- {
- x: 31536000000.0,
- y: 736135494.0,
- },
- {
- x: 63072000000.0,
- y: 742450677.0,
- },
- {
- x: 94694400000.0,
- y: 748475832.0,
- },
- {
- x: 126230400000.0,
- y: 754297089.0,
- },
- {
- x: 157766400000.0,
- y: 759928297.0,
- },
- {
- x: 189302400000.0,
- y: 765417984.0,
- },
- {
- x: 220924800000.0,
- y: 770663924.0,
- },
- {
- x: 252460800000.0,
- y: 775939424.0,
- },
- {
- x: 283996800000.0,
- y: 781099684.0,
- },
- {
- x: 315532800000.0,
- y: 786407417.0,
- },
- {
- x: 347155200000.0,
- y: 791686169.0,
- },
- {
- x: 378691200000.0,
- y: 796410256.0,
- },
- {
- x: 410227200000.0,
- y: 800966617.0,
- },
- {
- x: 441763200000.0,
- y: 805742116.0,
- },
- {
- x: 473385600000.0,
- y: 810633713.0,
- },
- {
- x: 504921600000.0,
- y: 815649358.0,
- },
- {
- x: 536457600000.0,
- y: 820716895.0,
- },
- {
- x: 567993600000.0,
- y: 825834599.0,
- },
- {
- x: 599616000000.0,
- y: 830998751.0,
- },
- {
- x: 631152000000.0,
- y: 842907397.0,
- },
- {
- x: 662688000000.0,
- y: 846199873.0,
- },
- {
- x: 694224000000.0,
- y: 849633122.0,
- },
- {
- x: 725846400000.0,
- y: 852664422.0,
- },
- {
- x: 757382400000.0,
- y: 854549337.0,
- },
- {
- x: 788918400000.0,
- y: 856102195.0,
- },
- {
- x: 820454400000.0,
- y: 857333424.0,
- },
- {
- x: 852076800000.0,
- y: 858726155.0,
- },
- {
- x: 883612800000.0,
- y: 859806214.0,
- },
- {
- x: 915148800000.0,
- y: 860985079.0,
- },
- {
- x: 946684800000.0,
- y: 862073997.0,
- },
- {
- x: 978307200000.0,
- y: 863554388.0,
- },
- {
- x: 1009843200000.0,
- y: 865246750.0,
- },
- {
- x: 1041379200000.0,
- y: 867562844.0,
- },
- {
- x: 1072915200000.0,
- y: 870213016.0,
- },
- {
- x: 1104537600000.0,
- y: 872968147.0,
- },
- {
- x: 1136073600000.0,
- y: 875755753.0,
- },
- {
- x: 1167609600000.0,
- y: 878819656.0,
- },
- {
- x: 1199145600000.0,
- y: 882358214.0,
- },
- {
- x: 1230768000000.0,
- y: 886063249.0,
- },
- {
- x: 1262304000000.0,
- y: 889630390.0,
- },
- {
- x: 1293840000000.0,
- y: 893094109.0,
- },
- {
- x: 1325376000000.0,
- y: 894962840.0,
- },
- {
- x: 1356998400000.0,
- y: 898837065.0,
- },
- {
- x: 1388534400000.0,
- y: 903095786.0,
- },
- ],
- },
- {
- key: ['Sub-Saharan Africa'],
- values: [
- {
- x: -315619200000.0,
- y: 228268752.0,
- },
- {
- x: -283996800000.0,
- y: 233759990.0,
- },
- {
- x: -252460800000.0,
- y: 239403621.0,
- },
- {
- x: -220924800000.0,
- y: 245217050.0,
- },
- {
- x: -189388800000.0,
- y: 251215851.0,
- },
- {
- x: -157766400000.0,
- y: 257414930.0,
- },
- {
- x: -126230400000.0,
- y: 263830697.0,
- },
- {
- x: -94694400000.0,
- y: 270477558.0,
- },
- {
- x: -63158400000.0,
- y: 277365472.0,
- },
- {
- x: -31536000000.0,
- y: 284502453.0,
- },
- {
- x: 0.0,
- y: 291897883.0,
- },
- {
- x: 31536000000.0,
- y: 299578724.0,
- },
- {
- x: 63072000000.0,
- y: 307524082.0,
- },
- {
- x: 94694400000.0,
- y: 315758889.0,
- },
- {
- x: 126230400000.0,
- y: 324316627.0,
- },
- {
- x: 157766400000.0,
- y: 333222446.0,
- },
- {
- x: 189302400000.0,
- y: 342489556.0,
- },
- {
- x: 220924800000.0,
- y: 352109622.0,
- },
- {
- x: 252460800000.0,
- y: 362076216.0,
- },
- {
- x: 283996800000.0,
- y: 372390972.0,
- },
- {
- x: 315532800000.0,
- y: 383043891.0,
- },
- {
- x: 347155200000.0,
- y: 394021126.0,
- },
- {
- x: 378691200000.0,
- y: 405328909.0,
- },
- {
- x: 410227200000.0,
- y: 416982682.0,
- },
- {
- x: 441763200000.0,
- y: 429008541.0,
- },
- {
- x: 473385600000.0,
- y: 441414277.0,
- },
- {
- x: 504921600000.0,
- y: 454197298.0,
- },
- {
- x: 536457600000.0,
- y: 467337821.0,
- },
- {
- x: 567993600000.0,
- y: 480809661.0,
- },
- {
- x: 599616000000.0,
- y: 494580339.0,
- },
- {
- x: 631152000000.0,
- y: 508616039.0,
- },
- {
- x: 662688000000.0,
- y: 523007873.0,
- },
- {
- x: 694224000000.0,
- y: 537759561.0,
- },
- {
- x: 725846400000.0,
- y: 552842678.0,
- },
- {
- x: 757382400000.0,
- y: 568228356.0,
- },
- {
- x: 788918400000.0,
- y: 583892679.0,
- },
- {
- x: 820454400000.0,
- y: 599858645.0,
- },
- {
- x: 852076800000.0,
- y: 616161312.0,
- },
- {
- x: 883612800000.0,
- y: 632857149.0,
- },
- {
- x: 915148800000.0,
- y: 650030484.0,
- },
- {
- x: 946684800000.0,
- y: 667742098.0,
- },
- {
- x: 978307200000.0,
- y: 685795280.0,
- },
- {
- x: 1009843200000.0,
- y: 704102354.0,
- },
- {
- x: 1041379200000.0,
- y: 722925207.0,
- },
- {
- x: 1072915200000.0,
- y: 742396040.0,
- },
- {
- x: 1104537600000.0,
- y: 762555740.0,
- },
- {
- x: 1136073600000.0,
- y: 783427658.0,
- },
- {
- x: 1167609600000.0,
- y: 805010175.0,
- },
- {
- x: 1199145600000.0,
- y: 827287676.0,
- },
- {
- x: 1230768000000.0,
- y: 850225069.0,
- },
- {
- x: 1262304000000.0,
- y: 873800152.0,
- },
- {
- x: 1293840000000.0,
- y: 898002051.0,
- },
- {
- x: 1325376000000.0,
- y: 922840423.0,
- },
- {
- x: 1356998400000.0,
- y: 948287652.0,
- },
- {
- x: 1388534400000.0,
- y: 974315323.0,
- },
- ],
- },
- {
- key: ['Latin America & Caribbean'],
- values: [
- {
- x: -315619200000.0,
- y: 220564224.0,
- },
- {
- x: -283996800000.0,
- y: 226764342.0,
- },
- {
- x: -252460800000.0,
- y: 233183206.0,
- },
- {
- x: -220924800000.0,
- y: 239771182.0,
- },
- {
- x: -189388800000.0,
- y: 246458356.0,
- },
- {
- x: -157766400000.0,
- y: 253195267.0,
- },
- {
- x: -126230400000.0,
- y: 259965218.0,
- },
- {
- x: -94694400000.0,
- y: 266776414.0,
- },
- {
- x: -63158400000.0,
- y: 273654630.0,
- },
- {
- x: -31536000000.0,
- y: 280641049.0,
- },
- {
- x: 0.0,
- y: 287763515.0,
- },
- {
- x: 31536000000.0,
- y: 295026304.0,
- },
- {
- x: 63072000000.0,
- y: 302408883.0,
- },
- {
- x: 94694400000.0,
- y: 309902169.0,
- },
- {
- x: 126230400000.0,
- y: 317479496.0,
- },
- {
- x: 157766400000.0,
- y: 325120067.0,
- },
- {
- x: 189302400000.0,
- y: 332817916.0,
- },
- {
- x: 220924800000.0,
- y: 340569396.0,
- },
- {
- x: 252460800000.0,
- y: 348391181.0,
- },
- {
- x: 283996800000.0,
- y: 356288443.0,
- },
- {
- x: 315532800000.0,
- y: 364270961.0,
- },
- {
- x: 347155200000.0,
- y: 372330102.0,
- },
- {
- x: 378691200000.0,
- y: 380466998.0,
- },
- {
- x: 410227200000.0,
- y: 388654061.0,
- },
- {
- x: 441763200000.0,
- y: 396869481.0,
- },
- {
- x: 473385600000.0,
- y: 405083115.0,
- },
- {
- x: 504921600000.0,
- y: 413292690.0,
- },
- {
- x: 536457600000.0,
- y: 421490233.0,
- },
- {
- x: 567993600000.0,
- y: 429668211.0,
- },
- {
- x: 599616000000.0,
- y: 437843614.0,
- },
- {
- x: 631152000000.0,
- y: 445998222.0,
- },
- {
- x: 662688000000.0,
- y: 454117634.0,
- },
- {
- x: 694224000000.0,
- y: 462201058.0,
- },
- {
- x: 725846400000.0,
- y: 470263697.0,
- },
- {
- x: 757382400000.0,
- y: 478310786.0,
- },
- {
- x: 788918400000.0,
- y: 486343677.0,
- },
- {
- x: 820454400000.0,
- y: 494384205.0,
- },
- {
- x: 852076800000.0,
- y: 502390020.0,
- },
- {
- x: 883612800000.0,
- y: 510356845.0,
- },
- {
- x: 915148800000.0,
- y: 518188225.0,
- },
- {
- x: 946684800000.0,
- y: 525886558.0,
- },
- {
- x: 978307200000.0,
- y: 533449671.0,
- },
- {
- x: 1009843200000.0,
- y: 540884684.0,
- },
- {
- x: 1041379200000.0,
- y: 548225528.0,
- },
- {
- x: 1072915200000.0,
- y: 555515431.0,
- },
- {
- x: 1104537600000.0,
- y: 562783235.0,
- },
- {
- x: 1136073600000.0,
- y: 570029991.0,
- },
- {
- x: 1167609600000.0,
- y: 577248307.0,
- },
- {
- x: 1199145600000.0,
- y: 584435842.0,
- },
- {
- x: 1230768000000.0,
- y: 591577623.0,
- },
- {
- x: 1262304000000.0,
- y: 598662941.0,
- },
- {
- x: 1293840000000.0,
- y: 605674766.0,
- },
- {
- x: 1325376000000.0,
- y: 612617659.0,
- },
- {
- x: 1356998400000.0,
- y: 619487273.0,
- },
- {
- x: 1388534400000.0,
- y: 626270167.0,
- },
- ],
- },
-];
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/stories/controlsShown.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/stories/controlsShown.tsx
deleted file mode 100644
index 659b1636a..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/stories/controlsShown.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-import data from '../data';
-
-export const controlsShown = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/stories/expanded.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/stories/expanded.tsx
deleted file mode 100644
index 980d4360e..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/stories/expanded.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-import data from '../data';
-
-export const expanded = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/stories/stacked.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/stories/stacked.tsx
deleted file mode 100644
index a161ed68f..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/stories/stacked.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-import data from '../data';
-
-export const stacked = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/stories/stackedWithBounds.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/stories/stackedWithBounds.tsx
deleted file mode 100644
index a7104b60a..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Area/stories/stackedWithBounds.tsx
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-import data from '../data';
-
-export const stackedWithYAxisBounds = () => (
-
-);
-
-stackedWithYAxisBounds.storyName = 'Stacked with yAxisBounds';
-
-export const stackedWithYAxisBoundsMinOnly = () => (
-
-);
-
-stackedWithYAxisBoundsMinOnly.storyName = 'Stacked with yAxisBounds min only';
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/data.ts b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/data.ts
deleted file mode 100644
index ef8338b65..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/data.ts
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * 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.
- */
-
-/* eslint-disable sort-keys */
-export default [
- {
- key: ['East Asia & Pacific'],
- values: [
- {
- x: -315619200000.0,
- y: 1031863394.0,
- },
- {
- x: -283996800000.0,
- y: 1034767718.0,
- },
- {
- x: -252460800000.0,
- y: 1048537618.0,
- },
- {
- x: -220924800000.0,
- y: 1073600747.0,
- },
- {
- x: -189388800000.0,
- y: 1098305025.0,
- },
- {
- x: -157766400000.0,
- y: 1124077872.0,
- },
- {
- x: -126230400000.0,
- y: 1153296196.0,
- },
- {
- x: -94694400000.0,
- y: 1181582226.0,
- },
- {
- x: -63158400000.0,
- y: 1210302481.0,
- },
- {
- x: -31536000000.0,
- y: 1242569208.0,
- },
- ],
- },
- {
- key: ['South Asia'],
- values: [
- {
- x: -315619200000.0,
- y: 572036107.0,
- },
- {
- x: -283996800000.0,
- y: 584143236.0,
- },
- {
- x: -252460800000.0,
- y: 596701125.0,
- },
- {
- x: -220924800000.0,
- y: 609571502.0,
- },
- {
- x: -189388800000.0,
- y: 623073110.0,
- },
- {
- x: -157766400000.0,
- y: 636963781.0,
- },
- {
- x: -126230400000.0,
- y: 651325994.0,
- },
- {
- x: -94694400000.0,
- y: 666134328.0,
- },
- {
- x: -63158400000.0,
- y: 681405837.0,
- },
- {
- x: -31536000000.0,
- y: 697060567.0,
- },
- ],
- },
- {
- key: ['Europe & Central Asia'],
- values: [
- {
- x: -315619200000.0,
- y: 660881033.0,
- },
- {
- x: -283996800000.0,
- y: 668526708.0,
- },
- {
- x: -252460800000.0,
- y: 676418331.0,
- },
- {
- x: -220924800000.0,
- y: 684369825.0,
- },
- {
- x: -189388800000.0,
- y: 692233988.0,
- },
- {
- x: -157766400000.0,
- y: 699849949.0,
- },
- {
- x: -126230400000.0,
- y: 706459925.0,
- },
- {
- x: -94694400000.0,
- y: 712871897.0,
- },
- {
- x: -63158400000.0,
- y: 719034272.0,
- },
- {
- x: -31536000000.0,
- y: 725099571.0,
- },
- ],
- },
- {
- key: ['Sub-Saharan Africa'],
- values: [
- {
- x: -315619200000.0,
- y: 228268752.0,
- },
- {
- x: -283996800000.0,
- y: 233759990.0,
- },
- {
- x: -252460800000.0,
- y: 239403621.0,
- },
- {
- x: -220924800000.0,
- y: 245217050.0,
- },
- {
- x: -189388800000.0,
- y: 251215851.0,
- },
- {
- x: -157766400000.0,
- y: 257414930.0,
- },
- {
- x: -126230400000.0,
- y: 263830697.0,
- },
- {
- x: -94694400000.0,
- y: 270477558.0,
- },
- {
- x: -63158400000.0,
- y: 277365472.0,
- },
- {
- x: -31536000000.0,
- y: 284502453.0,
- },
- ],
- },
- {
- key: ['Latin America & Caribbean'],
- values: [
- {
- x: -315619200000.0,
- y: 220564224.0,
- },
- {
- x: -283996800000.0,
- y: 226764342.0,
- },
- {
- x: -252460800000.0,
- y: 233183206.0,
- },
- {
- x: -220924800000.0,
- y: 239771182.0,
- },
- {
- x: -189388800000.0,
- y: 246458356.0,
- },
- {
- x: -157766400000.0,
- y: 253195267.0,
- },
- {
- x: -126230400000.0,
- y: 259965218.0,
- },
- {
- x: -94694400000.0,
- y: 266776414.0,
- },
- {
- x: -63158400000.0,
- y: 273654630.0,
- },
- {
- x: -31536000000.0,
- y: 280641049.0,
- },
- ],
- },
-];
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/stories/barWithPositiveAndNegativeValues.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/stories/barWithPositiveAndNegativeValues.tsx
deleted file mode 100644
index 449a54f6c..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/stories/barWithPositiveAndNegativeValues.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-import data from '../data';
-
-export const barWithPositiveAndNegativeValues = () => (
- ({
- ...group,
- values: group.values.map(pair => ({
- ...pair,
- y: (i % 2 === 0 ? 1 : -1) * pair.y,
- })),
- })),
- },
- ]}
- formData={{
- bottomMargin: 'auto',
- colorScheme: 'd3Category10',
- contribution: false,
- groupby: ['region'],
- lineInterpolation: 'linear',
- metrics: ['sum__SP_POP_TOTL'],
- richTooltip: true,
- showBarValue: true,
- showBrush: 'auto',
- showControls: false,
- showLegend: true,
- stackedStyle: 'stack',
- vizType: VizType.LegacyBar,
- xAxisFormat: '%Y',
- xAxisLabel: '',
- xAxisShowminmax: false,
- xTicksLayout: 'auto',
- yAxisBounds: [null, null],
- yAxisFormat: '.3s',
- yLogScale: false,
- }}
- />
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/stories/barWithValues.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/stories/barWithValues.tsx
deleted file mode 100644
index 5679050f6..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/stories/barWithValues.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-import data from '../data';
-
-export const barWithValues = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/stories/basic.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/stories/basic.tsx
deleted file mode 100644
index 00ad09b51..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/stories/basic.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-import data from '../data';
-
-export const basic = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/stories/stackedBarWithValues.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/stories/stackedBarWithValues.tsx
deleted file mode 100644
index fb931e396..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Bar/stories/stackedBarWithValues.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-import data from '../data';
-
-export const stackedBarWithValues = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/DistBar/data.ts b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/DistBar/data.ts
deleted file mode 100644
index a5cc5b534..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/DistBar/data.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.
- */
-
-/* eslint-disable sort-keys, no-magic-numbers */
-export default [
- {
- key: 'sum__sum_boys',
- values: [
- {
- x: 'CA',
- y: 5430796,
- },
- {
- x: 'TX',
- y: 3311985,
- },
- {
- x: 'NY',
- y: 3543961,
- },
- {
- x: 'OH',
- y: 2376385,
- },
- {
- x: 'PA',
- y: 2390275,
- },
- {
- x: 'IL',
- y: 2357411,
- },
- {
- x: 'MI',
- y: 1938321,
- },
- {
- x: 'FL',
- y: 1968060,
- },
- {
- x: 'NJ',
- y: 1486126,
- },
- {
- x: 'MA',
- y: 1285126,
- },
- ],
- },
- {
- key: 'sum__sum_girls',
- values: [
- {
- x: 'CA',
- y: 3567754,
- },
- {
- x: 'TX',
- y: 2313186,
- },
- {
- x: 'NY',
- y: 2280733,
- },
- {
- x: 'OH',
- y: 1622814,
- },
- {
- x: 'PA',
- y: 1615383,
- },
- {
- x: 'IL',
- y: 1614427,
- },
- {
- x: 'MI',
- y: 1326229,
- },
- {
- x: 'FL',
- y: 1312593,
- },
- {
- x: 'NJ',
- y: 992702,
- },
- {
- x: 'MA',
- y: 842146,
- },
- ],
- },
-];
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/DistBar/stories/basic.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/DistBar/stories/basic.tsx
deleted file mode 100644
index c262c2cc2..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/DistBar/stories/basic.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-import data from '../data';
-
-export const basic = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/DistBar/stories/manyBars.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/DistBar/stories/manyBars.tsx
deleted file mode 100644
index 246b590c0..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/DistBar/stories/manyBars.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType, seedRandom } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-
-const data: {
- key: string;
- values: {
- x: string;
- y: number;
- }[];
-}[] = [{ key: 'sth', values: [] }];
-const LONG_LABEL =
- 'some extremely ridiculously extremely extremely extremely ridiculously extremely extremely ridiculously extremely extremely ridiculously extremely long category';
-
-for (let i = 0; i < 50; i += 1) {
- data[0].values.push({
- x: `${LONG_LABEL.substring(
- 0,
- Math.round(seedRandom() * LONG_LABEL.length),
- )} ${i + 1}`,
- y: Math.round(seedRandom() * 10000),
- });
-}
-
-export const manyBars = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/data.ts b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/data.ts
deleted file mode 100644
index 5d43d8e4b..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/data.ts
+++ /dev/null
@@ -1,927 +0,0 @@
-/*
- * 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.
- */
-
-/* eslint-disable sort-keys, no-magic-numbers */
-export default [
- {
- key: ['Christopher'],
- values: [
- {
- x: -157766400000.0,
- y: 24703,
- },
- {
- x: -126230400000.0,
- y: 27861,
- },
- {
- x: -94694400000.0,
- y: 29436,
- },
- {
- x: -63158400000.0,
- y: 31463,
- },
- {
- x: -31536000000.0,
- y: 35718,
- },
- {
- x: 0.0,
- y: 41758,
- },
- {
- x: 31536000000.0,
- y: 48172,
- },
- {
- x: 63072000000.0,
- y: 52092,
- },
- {
- x: 94694400000.0,
- y: 48217,
- },
- {
- x: 126230400000.0,
- y: 48476,
- },
- {
- x: 157766400000.0,
- y: 46438,
- },
- {
- x: 189302400000.0,
- y: 45086,
- },
- {
- x: 220924800000.0,
- y: 46610,
- },
- {
- x: 252460800000.0,
- y: 47107,
- },
- {
- x: 283996800000.0,
- y: 50514,
- },
- {
- x: 315532800000.0,
- y: 48969,
- },
- {
- x: 347155200000.0,
- y: 50108,
- },
- {
- x: 378691200000.0,
- y: 59055,
- },
- {
- x: 410227200000.0,
- y: 59188,
- },
- {
- x: 441763200000.0,
- y: 59859,
- },
- {
- x: 473385600000.0,
- y: 59516,
- },
- {
- x: 504921600000.0,
- y: 56633,
- },
- {
- x: 536457600000.0,
- y: 54466,
- },
- {
- x: 567993600000.0,
- y: 52996,
- },
- {
- x: 599616000000.0,
- y: 53205,
- },
- {
- x: 631152000000.0,
- y: 52322,
- },
- {
- x: 662688000000.0,
- y: 47109,
- },
- {
- x: 694224000000.0,
- y: 42470,
- },
- {
- x: 725846400000.0,
- y: 38257,
- },
- {
- x: 757382400000.0,
- y: 34823,
- },
- {
- x: 788918400000.0,
- y: 32728,
- },
- {
- x: 820454400000.0,
- y: 30988,
- },
- {
- x: 852076800000.0,
- y: 29179,
- },
- {
- x: 883612800000.0,
- y: 27083,
- },
- {
- x: 915148800000.0,
- y: 25700,
- },
- {
- x: 946684800000.0,
- y: 24959,
- },
- {
- x: 978307200000.0,
- y: 23180,
- },
- {
- x: 1009843200000.0,
- y: 21731,
- },
- {
- x: 1041379200000.0,
- y: 20793,
- },
- {
- x: 1072915200000.0,
- y: 19739,
- },
- {
- x: 1104537600000.0,
- y: 19190,
- },
- {
- x: 1136073600000.0,
- y: 19674,
- },
- {
- x: 1167609600000.0,
- y: 19986,
- },
- {
- x: 1199145600000.0,
- y: 17771,
- },
- ],
- },
- {
- key: ['David'],
- values: [
- {
- x: -157766400000.0,
- y: 67646,
- },
- {
- x: -126230400000.0,
- y: 66207,
- },
- {
- x: -94694400000.0,
- y: 66581,
- },
- {
- x: -63158400000.0,
- y: 63531,
- },
- {
- x: -31536000000.0,
- y: 63502,
- },
- {
- x: 0.0,
- y: 61570,
- },
- {
- x: 31536000000.0,
- y: 52948,
- },
- {
- x: 63072000000.0,
- y: 46218,
- },
- {
- x: 94694400000.0,
- y: 40968,
- },
- {
- x: 126230400000.0,
- y: 41654,
- },
- {
- x: 157766400000.0,
- y: 39019,
- },
- {
- x: 189302400000.0,
- y: 39165,
- },
- {
- x: 220924800000.0,
- y: 40407,
- },
- {
- x: 252460800000.0,
- y: 40533,
- },
- {
- x: 283996800000.0,
- y: 41898,
- },
- {
- x: 315532800000.0,
- y: 41743,
- },
- {
- x: 347155200000.0,
- y: 40486,
- },
- {
- x: 378691200000.0,
- y: 40283,
- },
- {
- x: 410227200000.0,
- y: 39048,
- },
- {
- x: 441763200000.0,
- y: 38346,
- },
- {
- x: 473385600000.0,
- y: 38395,
- },
- {
- x: 504921600000.0,
- y: 37021,
- },
- {
- x: 536457600000.0,
- y: 36672,
- },
- {
- x: 567993600000.0,
- y: 35214,
- },
- {
- x: 599616000000.0,
- y: 35139,
- },
- {
- x: 631152000000.0,
- y: 33661,
- },
- {
- x: 662688000000.0,
- y: 30347,
- },
- {
- x: 694224000000.0,
- y: 28344,
- },
- {
- x: 725846400000.0,
- y: 26947,
- },
- {
- x: 757382400000.0,
- y: 24784,
- },
- {
- x: 788918400000.0,
- y: 22967,
- },
- {
- x: 820454400000.0,
- y: 22941,
- },
- {
- x: 852076800000.0,
- y: 21824,
- },
- {
- x: 883612800000.0,
- y: 20816,
- },
- {
- x: 915148800000.0,
- y: 20267,
- },
- {
- x: 946684800000.0,
- y: 19695,
- },
- {
- x: 978307200000.0,
- y: 19281,
- },
- {
- x: 1009843200000.0,
- y: 18600,
- },
- {
- x: 1041379200000.0,
- y: 18557,
- },
- {
- x: 1072915200000.0,
- y: 18315,
- },
- {
- x: 1104537600000.0,
- y: 18017,
- },
- {
- x: 1136073600000.0,
- y: 17510,
- },
- {
- x: 1167609600000.0,
- y: 17400,
- },
- {
- x: 1199145600000.0,
- y: 16049,
- },
- ],
- },
- {
- key: ['James'],
- values: [
- {
- x: -157766400000.0,
- y: 67506,
- },
- {
- x: -126230400000.0,
- y: 65036,
- },
- {
- x: -94694400000.0,
- y: 61554,
- },
- {
- x: -63158400000.0,
- y: 60584,
- },
- {
- x: -31536000000.0,
- y: 59824,
- },
- {
- x: 0.0,
- y: 61597,
- },
- {
- x: 31536000000.0,
- y: 54463,
- },
- {
- x: 63072000000.0,
- y: 46960,
- },
- {
- x: 94694400000.0,
- y: 42782,
- },
- {
- x: 126230400000.0,
- y: 41258,
- },
- {
- x: 157766400000.0,
- y: 39471,
- },
- {
- x: 189302400000.0,
- y: 38203,
- },
- {
- x: 220924800000.0,
- y: 39916,
- },
- {
- x: 252460800000.0,
- y: 39783,
- },
- {
- x: 283996800000.0,
- y: 39237,
- },
- {
- x: 315532800000.0,
- y: 39185,
- },
- {
- x: 347155200000.0,
- y: 38176,
- },
- {
- x: 378691200000.0,
- y: 38750,
- },
- {
- x: 410227200000.0,
- y: 36228,
- },
- {
- x: 441763200000.0,
- y: 35728,
- },
- {
- x: 473385600000.0,
- y: 35750,
- },
- {
- x: 504921600000.0,
- y: 33955,
- },
- {
- x: 536457600000.0,
- y: 32552,
- },
- {
- x: 567993600000.0,
- y: 32418,
- },
- {
- x: 599616000000.0,
- y: 32658,
- },
- {
- x: 631152000000.0,
- y: 32288,
- },
- {
- x: 662688000000.0,
- y: 30460,
- },
- {
- x: 694224000000.0,
- y: 28450,
- },
- {
- x: 725846400000.0,
- y: 26193,
- },
- {
- x: 757382400000.0,
- y: 24706,
- },
- {
- x: 788918400000.0,
- y: 22691,
- },
- {
- x: 820454400000.0,
- y: 21122,
- },
- {
- x: 852076800000.0,
- y: 20368,
- },
- {
- x: 883612800000.0,
- y: 19651,
- },
- {
- x: 915148800000.0,
- y: 18508,
- },
- {
- x: 946684800000.0,
- y: 17939,
- },
- {
- x: 978307200000.0,
- y: 17023,
- },
- {
- x: 1009843200000.0,
- y: 16905,
- },
- {
- x: 1041379200000.0,
- y: 16832,
- },
- {
- x: 1072915200000.0,
- y: 16459,
- },
- {
- x: 1104537600000.0,
- y: 16046,
- },
- {
- x: 1136073600000.0,
- y: 16139,
- },
- {
- x: 1167609600000.0,
- y: 15821,
- },
- {
- x: 1199145600000.0,
- y: 14920,
- },
- ],
- },
- {
- key: ['John'],
- values: [
- {
- x: -157766400000.0,
- y: 71390,
- },
- {
- x: -126230400000.0,
- y: 64858,
- },
- {
- x: -94694400000.0,
- y: 61480,
- },
- {
- x: -63158400000.0,
- y: 60754,
- },
- {
- x: -31536000000.0,
- y: 58644,
- },
- {
- x: 0.0,
- y: 58348,
- },
- {
- x: 31536000000.0,
- y: 51382,
- },
- {
- x: 63072000000.0,
- y: 43028,
- },
- {
- x: 94694400000.0,
- y: 39061,
- },
- {
- x: 126230400000.0,
- y: 37553,
- },
- {
- x: 157766400000.0,
- y: 34970,
- },
- {
- x: 189302400000.0,
- y: 33876,
- },
- {
- x: 220924800000.0,
- y: 34103,
- },
- {
- x: 252460800000.0,
- y: 33895,
- },
- {
- x: 283996800000.0,
- y: 35305,
- },
- {
- x: 315532800000.0,
- y: 35131,
- },
- {
- x: 347155200000.0,
- y: 34761,
- },
- {
- x: 378691200000.0,
- y: 34560,
- },
- {
- x: 410227200000.0,
- y: 33047,
- },
- {
- x: 441763200000.0,
- y: 32484,
- },
- {
- x: 473385600000.0,
- y: 31397,
- },
- {
- x: 504921600000.0,
- y: 30103,
- },
- {
- x: 536457600000.0,
- y: 29462,
- },
- {
- x: 567993600000.0,
- y: 29301,
- },
- {
- x: 599616000000.0,
- y: 29751,
- },
- {
- x: 631152000000.0,
- y: 29011,
- },
- {
- x: 662688000000.0,
- y: 27727,
- },
- {
- x: 694224000000.0,
- y: 26156,
- },
- {
- x: 725846400000.0,
- y: 24918,
- },
- {
- x: 757382400000.0,
- y: 24119,
- },
- {
- x: 788918400000.0,
- y: 23174,
- },
- {
- x: 820454400000.0,
- y: 22104,
- },
- {
- x: 852076800000.0,
- y: 21330,
- },
- {
- x: 883612800000.0,
- y: 20556,
- },
- {
- x: 915148800000.0,
- y: 20280,
- },
- {
- x: 946684800000.0,
- y: 20032,
- },
- {
- x: 978307200000.0,
- y: 18839,
- },
- {
- x: 1009843200000.0,
- y: 17400,
- },
- {
- x: 1041379200000.0,
- y: 17170,
- },
- {
- x: 1072915200000.0,
- y: 16381,
- },
- {
- x: 1104537600000.0,
- y: 15692,
- },
- {
- x: 1136073600000.0,
- y: 15083,
- },
- {
- x: 1167609600000.0,
- y: 14348,
- },
- {
- x: 1199145600000.0,
- y: 13110,
- },
- ],
- },
- {
- key: ['Michael'],
- values: [
- {
- x: -157766400000.0,
- y: 80812,
- },
- {
- x: -126230400000.0,
- y: 79709,
- },
- {
- x: -94694400000.0,
- y: 82204,
- },
- {
- x: -63158400000.0,
- y: 81785,
- },
- {
- x: -31536000000.0,
- y: 84893,
- },
- {
- x: 0.0,
- y: 85015,
- },
- {
- x: 31536000000.0,
- y: 77321,
- },
- {
- x: 63072000000.0,
- y: 71197,
- },
- {
- x: 94694400000.0,
- y: 67598,
- },
- {
- x: 126230400000.0,
- y: 67304,
- },
- {
- x: 157766400000.0,
- y: 68149,
- },
- {
- x: 189302400000.0,
- y: 66686,
- },
- {
- x: 220924800000.0,
- y: 67344,
- },
- {
- x: 252460800000.0,
- y: 66875,
- },
- {
- x: 283996800000.0,
- y: 67473,
- },
- {
- x: 315532800000.0,
- y: 68375,
- },
- {
- x: 347155200000.0,
- y: 68467,
- },
- {
- x: 378691200000.0,
- y: 67904,
- },
- {
- x: 410227200000.0,
- y: 67708,
- },
- {
- x: 441763200000.0,
- y: 67457,
- },
- {
- x: 473385600000.0,
- y: 64667,
- },
- {
- x: 504921600000.0,
- y: 63959,
- },
- {
- x: 536457600000.0,
- y: 63442,
- },
- {
- x: 567993600000.0,
- y: 63924,
- },
- {
- x: 599616000000.0,
- y: 65233,
- },
- {
- x: 631152000000.0,
- y: 65138,
- },
- {
- x: 662688000000.0,
- y: 60646,
- },
- {
- x: 694224000000.0,
- y: 54216,
- },
- {
- x: 725846400000.0,
- y: 49443,
- },
- {
- x: 757382400000.0,
- y: 44361,
- },
- {
- x: 788918400000.0,
- y: 41311,
- },
- {
- x: 820454400000.0,
- y: 38284,
- },
- {
- x: 852076800000.0,
- y: 37459,
- },
- {
- x: 883612800000.0,
- y: 36525,
- },
- {
- x: 915148800000.0,
- y: 33820,
- },
- {
- x: 946684800000.0,
- y: 31956,
- },
- {
- x: 978307200000.0,
- y: 29612,
- },
- {
- x: 1009843200000.0,
- y: 28156,
- },
- {
- x: 1041379200000.0,
- y: 27031,
- },
- {
- x: 1072915200000.0,
- y: 25418,
- },
- {
- x: 1104537600000.0,
- y: 23678,
- },
- {
- x: 1136073600000.0,
- y: 22498,
- },
- {
- x: 1167609600000.0,
- y: 21805,
- },
- {
- x: 1199145600000.0,
- y: 20271,
- },
- ],
- },
-];
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/stories/basic.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/stories/basic.tsx
deleted file mode 100644
index 3aea91e7f..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/stories/basic.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-import data from '../data';
-
-export const basic = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/stories/logScale.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/stories/logScale.tsx
deleted file mode 100644
index f93109f73..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/stories/logScale.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-import data from '../data';
-
-export const logScale = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/stories/markers.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/stories/markers.tsx
deleted file mode 100644
index c2a83b8eb..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/stories/markers.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-import data from '../data';
-
-export const markers = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/stories/yAxisBounds.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/stories/yAxisBounds.tsx
deleted file mode 100644
index c705c0b2b..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Line/stories/yAxisBounds.tsx
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-import data from '../data';
-
-export const yAxisBounds = () => (
-
-
yAxisBounds
-
yAxisBounds=undefined
-
-
yAxisBounds=[0, 60000]
-
-
yAxisBounds=[null, 60000]
-
-
yAxisBounds=[40000, null]
-
-
yAxisBounds=[40000, null] with Legend
-
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Pie/stories/basic.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Pie/stories/basic.tsx
deleted file mode 100644
index 0fd34b6ec..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Pie/stories/basic.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-import data from '../data';
-
-export const basic = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Pie/stories/noData.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Pie/stories/noData.tsx
deleted file mode 100644
index 028305901..000000000
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Pie/stories/noData.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SuperChart, VizType } from '@superset-ui/core';
-import dummyDatasource from '../../../../../shared/dummyDatasource';
-
-export const noData = () => (
-
-);
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/plugin-chart-table/birthNames.json b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/plugin-chart-table/birthNames.json
index c35d3a806..bce7fca54 100644
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/plugin-chart-table/birthNames.json
+++ b/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/plugin-chart-table/birthNames.json
@@ -30,7 +30,6 @@
"cache_timeout": null,
"params": null,
"perm": "[examples].[birth_names](id:3)",
- "edit_url": "/tablemodelview/edit/3",
"sql": null,
"columns": [
{
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-chart/ChartDataProvider.stories.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-chart/ChartDataProvider.stories.tsx
index f05381963..ca3ef6187 100644
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-chart/ChartDataProvider.stories.tsx
+++ b/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-chart/ChartDataProvider.stories.tsx
@@ -23,7 +23,6 @@ import {
SupersetClient,
} from '@superset-ui/core';
import { BigNumberChartPlugin } from '@superset-ui/plugin-chart-echarts';
-import LegacySankeyPlugin from '@superset-ui/legacy-plugin-chart-sankey';
import { WordCloudChartPlugin } from '@superset-ui/plugin-chart-word-cloud';
import {
@@ -44,8 +43,6 @@ const WORD_CLOUD = 'new_word_cloud';
new BigNumberChartPlugin().configure({ key: BIG_NUMBER }).register();
// eslint-disable-next-line
-new LegacySankeyPlugin().configure({ key: SANKEY }).register();
-// eslint-disable-next-line
new WordCloudChartPlugin().configure({ key: WORD_CLOUD }).register();
const VIS_TYPES = [BIG_NUMBER, SANKEY, SUNBURST, WORD_CLOUD, WORD_CLOUD_LEGACY];
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-style/Theme.stories.tsx b/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-style/Theme.stories.tsx
index 63ede4a8a..b46c9dfb8 100644
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-style/Theme.stories.tsx
+++ b/superset-frontend/packages/superset-ui-demo/storybook/stories/superset-ui-style/Theme.stories.tsx
@@ -25,23 +25,96 @@ export default {
export const ThemeColors = () => {
const { colors } = supersetTheme;
- return Object.keys(colors).map(collection => (
+
+ // Define tones to be displayed in columns
+ const tones = [
+ 'dark2',
+ 'dark1',
+ 'base',
+ 'light1',
+ 'light2',
+ 'light3',
+ 'light4',
+ 'light5',
+ ];
+ const colorTypes = [
+ 'primary',
+ 'secondary',
+ 'grayscale',
+ 'error',
+ 'warning',
+ 'alert',
+ 'success',
+ 'info',
+ ];
+ return (
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
+ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
+ commodo consequat.
+
+
+ text.help: {colors.text.help}
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
+ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
+ commodo consequat.
+
+
The supersetTheme object
+
+
{JSON.stringify(supersetTheme, null, 2)}
+
- ));
+ );
};
diff --git a/superset-frontend/plugins/legacy-plugin-chart-calendar/package.json b/superset-frontend/plugins/legacy-plugin-chart-calendar/package.json
index e89df2f83..f4107ccfa 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-calendar/package.json
+++ b/superset-frontend/plugins/legacy-plugin-chart-calendar/package.json
@@ -32,7 +32,7 @@
"@emotion/react": "^11.4.1",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
- "react": "^16.13.1"
+ "react": "^17.0.2"
},
"publishConfig": {
"access": "public"
diff --git a/superset-frontend/plugins/legacy-plugin-chart-calendar/src/ReactCalendar.jsx b/superset-frontend/plugins/legacy-plugin-chart-calendar/src/ReactCalendar.jsx
index f3fcc807d..46cb1de85 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-calendar/src/ReactCalendar.jsx
+++ b/superset-frontend/plugins/legacy-plugin-chart-calendar/src/ReactCalendar.jsx
@@ -157,13 +157,13 @@ export default styled(Calendar)`
}
.cal-heatmap-container .q1 {
- background-color: ${theme.colors.alert.light2};
- fill: ${theme.colors.alert.light2};
+ background-color: ${theme.colors.warning.light2};
+ fill: ${theme.colors.warning.light2};
}
.cal-heatmap-container .q2 {
- background-color: ${theme.colors.alert.light1};
- fill: ${theme.colors.alert.light1};
+ background-color: ${theme.colors.warning.light1};
+ fill: ${theme.colors.warning.light1};
}
.cal-heatmap-container .q3 {
diff --git a/superset-frontend/plugins/legacy-plugin-chart-chord/package.json b/superset-frontend/plugins/legacy-plugin-chart-chord/package.json
index 6dda71cd6..aebdff5b9 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-chord/package.json
+++ b/superset-frontend/plugins/legacy-plugin-chart-chord/package.json
@@ -31,7 +31,7 @@
"dependencies": {
"d3": "^3.5.17",
"prop-types": "^15.8.1",
- "react": "^16.13.1"
+ "react": "^17.0.2"
},
"peerDependencies": {
"@superset-ui/chart-controls": "*",
diff --git a/superset-frontend/plugins/legacy-plugin-chart-country-map/package.json b/superset-frontend/plugins/legacy-plugin-chart-country-map/package.json
index 1420ef351..6f3385ae0 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-country-map/package.json
+++ b/superset-frontend/plugins/legacy-plugin-chart-country-map/package.json
@@ -33,6 +33,6 @@
"peerDependencies": {
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
- "react": "^16.13.1"
+ "react": "^17.0.2"
}
}
diff --git a/superset-frontend/plugins/legacy-plugin-chart-event-flow/CHANGELOG.md b/superset-frontend/plugins/legacy-plugin-chart-event-flow/CHANGELOG.md
deleted file mode 100644
index c2cec75e6..000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-event-flow/CHANGELOG.md
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-# Change Log
-
-All notable changes to this project will be documented in this file.
-See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
-
-# [0.20.0](https://github.com/apache/superset/compare/v2021.41.0...v0.20.0) (2024-09-09)
-
-### Bug Fixes
-
-- **generic-chart-axes:** set x-axis if unset and ff is enabled ([#20107](https://github.com/apache/superset/issues/20107)) ([0b3d3dd](https://github.com/apache/superset/commit/0b3d3dd4caa7f4c31c1ba7229966a40ba0469e85))
-
-### Features
-
-- **explore:** Frontend implementation of dataset creation from infobox ([#19855](https://github.com/apache/superset/issues/19855)) ([ba0c37d](https://github.com/apache/superset/commit/ba0c37d3df85b1af39404af1d578daeb0ff2d278))
-
-# [0.19.0](https://github.com/apache/superset/compare/v2021.41.0...v0.19.0) (2024-09-07)
-
-### Bug Fixes
-
-- **generic-chart-axes:** set x-axis if unset and ff is enabled ([#20107](https://github.com/apache/superset/issues/20107)) ([0b3d3dd](https://github.com/apache/superset/commit/0b3d3dd4caa7f4c31c1ba7229966a40ba0469e85))
-
-### Features
-
-- **explore:** Frontend implementation of dataset creation from infobox ([#19855](https://github.com/apache/superset/issues/19855)) ([ba0c37d](https://github.com/apache/superset/commit/ba0c37d3df85b1af39404af1d578daeb0ff2d278))
-
-# [0.18.0](https://github.com/apache-superset/superset-ui/compare/v0.17.87...v0.18.0) (2021-08-30)
-
-**Note:** Version bump only for package @superset-ui/legacy-plugin-chart-event-flow
-
-## [0.17.61](https://github.com/apache-superset/superset-ui/compare/v0.17.60...v0.17.61) (2021-07-02)
-
-**Note:** Version bump only for package @superset-ui/legacy-plugin-chart-event-flow
diff --git a/superset-frontend/plugins/legacy-plugin-chart-event-flow/README.md b/superset-frontend/plugins/legacy-plugin-chart-event-flow/README.md
deleted file mode 100644
index 4d6ab3356..000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-event-flow/README.md
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-## @superset-ui/legacy-plugin-chart-event-flow
-
-[](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-event-flow)
-[](https://libraries.io/npm/@superset-ui%2Flegacy-plugin-chart-event-flow)
-
-This plugin provides Event Flow for Superset.
-
-### Usage
-
-Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to
-lookup this chart throughout the app.
-
-```js
-import EventFlowChartPlugin from '@superset-ui/legacy-plugin-chart-event-flow';
-
-new EventFlowChartPlugin().configure({ key: 'event-flow' }).register();
-```
-
-Then use it via `SuperChart`. See
-[storybook](https://apache-superset.github.io/superset-ui-plugins/?selectedKind=plugin-chart-event-flow)
-for more details.
-
-```js
-
-```
diff --git a/superset-frontend/plugins/legacy-plugin-chart-event-flow/package.json b/superset-frontend/plugins/legacy-plugin-chart-event-flow/package.json
deleted file mode 100644
index ead0d994f..000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-event-flow/package.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "name": "@superset-ui/legacy-plugin-chart-event-flow",
- "version": "0.20.3",
- "description": "Superset Legacy Chart - Event Flow",
- "sideEffects": [
- "*.css"
- ],
- "main": "lib/index.js",
- "module": "esm/index.js",
- "files": [
- "esm",
- "lib"
- ],
- "repository": {
- "type": "git",
- "url": "https://github.com/apache/superset.git",
- "directory": "superset-frontend/plugins/legacy-plugin-chart-event-flow"
- },
- "keywords": [
- "superset"
- ],
- "author": "Superset",
- "license": "Apache-2.0",
- "bugs": {
- "url": "https://github.com/apache/superset/issues"
- },
- "homepage": "https://github.com/apache/superset/tree/master/superset-frontend/plugins/legacy-plugin-chart-event-flow#readme",
- "publishConfig": {
- "access": "public"
- },
- "dependencies": {
- "@data-ui/event-flow": "^0.0.84",
- "prop-types": "^15.8.1"
- },
- "peerDependencies": {
- "@superset-ui/chart-controls": "*",
- "@superset-ui/core": "*",
- "react": "^15 || ^16"
- }
-}
diff --git a/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/controlPanel.tsx b/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/controlPanel.tsx
deleted file mode 100644
index 32ed9969b..000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/controlPanel.tsx
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import { t, validateNonEmpty } from '@superset-ui/core';
-import {
- columnChoices,
- ColumnOption,
- ColumnMeta,
- ControlPanelConfig,
- ControlState,
- formatSelectOptionsForRange,
- SelectControlConfig,
-} from '@superset-ui/chart-controls';
-
-const config: ControlPanelConfig = {
- controlPanelSections: [
- {
- label: t('Event definition'),
- controlSetRows: [
- ['entity'],
- [
- {
- name: 'all_columns_x',
- config: {
- type: 'SelectControl',
- label: t('Event Names'),
- description: t('Columns to display'),
- mapStateToProps: state => ({
- choices: columnChoices(state?.datasource),
- }),
- // choices is from `mapStateToProps`
- default: (control: ControlState) =>
- control.choices?.[0]?.[0] || null,
- validators: [validateNonEmpty],
- },
- },
- ],
- ['row_limit'],
- [
- {
- name: 'order_by_entity',
- config: {
- type: 'CheckboxControl',
- label: t('Order by entity id'),
- description: t(
- 'Important! Select this if the table is not already sorted by entity id, ' +
- 'else there is no guarantee that all events for each entity are returned.',
- ),
- default: true,
- },
- },
- ],
- [
- {
- name: 'min_leaf_node_event_count',
- config: {
- type: 'SelectControl',
- freeForm: false,
- label: t('Minimum leaf node event count'),
- default: 1,
- choices: formatSelectOptionsForRange(1, 10),
- description: t(
- 'Leaf nodes that represent fewer than this number of events will be initially ' +
- 'hidden in the visualization',
- ),
- },
- },
- ],
- ],
- },
- {
- label: t('Query'),
- expanded: true,
- controlSetRows: [['adhoc_filters']],
- },
- {
- label: t('Additional metadata'),
- controlSetRows: [
- [
- {
- name: 'all_columns',
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
- config: {
- type: 'SelectControl',
- multi: true,
- label: t('Metadata'),
- default: [],
- description: t('Select any columns for metadata inspection'),
- optionRenderer: c => ,
- valueRenderer: c => ,
- valueKey: 'column_name',
- allowAll: true,
- mapStateToProps: state => ({
- options: state.datasource?.columns || [],
- }),
- commaChoosesOption: false,
- freeForm: true,
- } as SelectControlConfig,
- },
- ],
- ],
- },
- ],
- controlOverrides: {
- entity: {
- label: t('Entity ID'),
- description: t('e.g., a "user id" column'),
- },
- row_limit: {
- label: t('Max Events'),
- description: t(
- 'The maximum number of events to return, equivalent to the number of rows',
- ),
- },
- },
-};
-
-export default config;
diff --git a/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/images/example.jpg b/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/images/example.jpg
deleted file mode 100644
index e2cfb0222..000000000
Binary files a/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/images/example.jpg and /dev/null differ
diff --git a/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/images/thumbnail.png b/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/images/thumbnail.png
deleted file mode 100644
index de10a4d19..000000000
Binary files a/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/images/thumbnail.png and /dev/null differ
diff --git a/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/images/thumbnailLarge.png b/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/images/thumbnailLarge.png
deleted file mode 100644
index 0edb53563..000000000
Binary files a/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/images/thumbnailLarge.png and /dev/null differ
diff --git a/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/index.ts b/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/index.ts
deleted file mode 100644
index 824f8f3db..000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/index.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import { t, ChartMetadata, ChartPlugin } from '@superset-ui/core';
-import thumbnail from './images/thumbnail.png';
-import example from './images/example.jpg';
-import controlPanel from './controlPanel';
-
-const metadata = new ChartMetadata({
- category: t('Flow'),
- credits: ['https://github.com/williaster/data-ui'],
- description: t(
- 'Compares the lengths of time different activities take in a shared timeline view.',
- ),
- exampleGallery: [{ url: example }],
- name: t('Event Flow'),
- tags: [t('Legacy'), t('Progressive')],
- thumbnail,
- useLegacyApi: true,
-});
-
-export default class EventFlowChartPlugin extends ChartPlugin {
- constructor() {
- super({
- loadChart: () => import('./EventFlow'),
- loadTransformProps: () => import('./transformProps'),
- metadata,
- controlPanel,
- });
- }
-}
diff --git a/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/transformProps.ts b/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/transformProps.ts
deleted file mode 100644
index c738ca6eb..000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/transformProps.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import { ChartProps, TimeseriesDataRecord } from '@superset-ui/core';
-import { cleanEvents, TS, EVENT_NAME, ENTITY_ID } from '@data-ui/event-flow';
-
-export interface EventFlowFormData {
- allColumnsX: string;
- entity: string;
- minLeafNodeEventCount: number;
-}
-
-export interface EventFlowChartProps extends ChartProps {
- formData: EventFlowFormData;
- queriesData: {
- data: TimeseriesDataRecord[];
- }[];
-}
-
-export default function transformProps(chartProps: ChartProps) {
- const { formData, queriesData, width, height } =
- chartProps as EventFlowChartProps;
- const { allColumnsX, entity, minLeafNodeEventCount } = formData;
- const { data } = queriesData[0];
-
- const hasData = data && data.length > 0;
- if (hasData) {
- const userKey = entity;
- const eventNameKey = allColumnsX;
-
- // map from the Superset form fields to 's expected data keys
- const accessorFunctions = {
- [ENTITY_ID]: (datum: TimeseriesDataRecord) => String(datum[userKey]),
- [EVENT_NAME]: (datum: TimeseriesDataRecord) =>
- datum[eventNameKey] as string,
- [TS]: (datum: TimeseriesDataRecord): Date | null =>
- // eslint-disable-next-line no-underscore-dangle
- datum.__timestamp || datum.__timestamp === 0
- ? // eslint-disable-next-line no-underscore-dangle
- new Date(datum.__timestamp)
- : null,
- };
-
- const cleanData = cleanEvents(data, accessorFunctions);
-
- return {
- data: cleanData,
- height,
- initialMinEventCount: minLeafNodeEventCount,
- width,
- };
- }
-
- return { data: null, height, width };
-}
diff --git a/superset-frontend/plugins/legacy-plugin-chart-heatmap/CHANGELOG.md b/superset-frontend/plugins/legacy-plugin-chart-heatmap/CHANGELOG.md
deleted file mode 100644
index 1cedf14e9..000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-heatmap/CHANGELOG.md
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-# Change Log
-
-All notable changes to this project will be documented in this file.
-See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
-
-# [0.20.0](https://github.com/apache/superset/compare/v2021.41.0...v0.20.0) (2024-09-09)
-
-### Bug Fixes
-
-- **chart & heatmap:** make to fix that y label is rendering out of bounds ([#20011](https://github.com/apache/superset/issues/20011)) ([56e9695](https://github.com/apache/superset/commit/56e96950c17ec65ef18cedfb2ed6591796a96cfc))
-- Date column in Heatmap is displayed as unix timestamp ([#25009](https://github.com/apache/superset/issues/25009)) ([35eb66a](https://github.com/apache/superset/commit/35eb66a322f7938f840778633a4aea11c7f24dce))
-- **explore:** Prevent shared controls from checking feature flags outside React render ([#21315](https://github.com/apache/superset/issues/21315)) ([2285ebe](https://github.com/apache/superset/commit/2285ebe72ec4edded6d195052740b7f9f13d1f1b))
-- Heatmap numeric sorting ([#27360](https://github.com/apache/superset/issues/27360)) ([fe2f5a7](https://github.com/apache/superset/commit/fe2f5a7be9fb6218aa72ab9173481fd21fa40b20))
-- **heatmap:** add detail descriptions for heatmap 'normalize across' ([#20566](https://github.com/apache/superset/issues/20566)) ([d925b0c](https://github.com/apache/superset/commit/d925b0c8835fb1773b80298a3de1bdc368c88850))
-- **legacy-plugin-chart-heatmap:** fix adhoc column tooltip ([#23507](https://github.com/apache/superset/issues/23507)) ([0cebe8b](https://github.com/apache/superset/commit/0cebe8bf18204d17f311345744e67c4bf5961083))
-- **select:** select component sort functionality on certain options ([#17638](https://github.com/apache/superset/issues/17638)) ([f476ba2](https://github.com/apache/superset/commit/f476ba23a279cb87a94ad3075e035cad0ae264b6))
-- Timeseries Y-axis format with contribution mode ([#27106](https://github.com/apache/superset/issues/27106)) ([af577d6](https://github.com/apache/superset/commit/af577d64b17a9730e28e9021376318326fe31437))
-- Tooltips don't disappear on the Heatmap chart ([#24959](https://github.com/apache/superset/issues/24959)) ([9703490](https://github.com/apache/superset/commit/97034901291420af844257fc76ac107d4a891f18))
-
-### Features
-
-- Add currencies controls in control panels ([#24718](https://github.com/apache/superset/issues/24718)) ([f7e76d0](https://github.com/apache/superset/commit/f7e76d02b7cbe4940946673590bb979984ace9f5))
-- Adds the ECharts Heatmap chart ([#25353](https://github.com/apache/superset/issues/25353)) ([546d48a](https://github.com/apache/superset/commit/546d48adbb84b1354d6a3d4ae88dbeba0ad14d44))
-- **chart & legend:** make to enable show legend by default ([#19927](https://github.com/apache/superset/issues/19927)) ([7b3d0f0](https://github.com/apache/superset/commit/7b3d0f040b050905f7d0901d0227f1cd6b761b56))
-- **explore:** Apply denormalization to tier 2 charts form data ([#20524](https://github.com/apache/superset/issues/20524)) ([e12ee59](https://github.com/apache/superset/commit/e12ee59b13822241dca8d8015f1222c477edd4f3))
-- Implement support for currencies in more charts ([#24594](https://github.com/apache/superset/issues/24594)) ([d74d7ec](https://github.com/apache/superset/commit/d74d7eca23a3c94bc48af082c115d34c103e815d))
-
-### Reverts
-
-- Revert "chore(deps): bump d3-svg-legend in /superset-frontend (#19846)" (#19972) ([f144de4](https://github.com/apache/superset/commit/f144de4ee2bf213bb7e17f903bd3975d504c4136)), closes [#19846](https://github.com/apache/superset/issues/19846) [#19972](https://github.com/apache/superset/issues/19972)
-
-# [0.19.0](https://github.com/apache/superset/compare/v2021.41.0...v0.19.0) (2024-09-07)
-
-### Bug Fixes
-
-- **chart & heatmap:** make to fix that y label is rendering out of bounds ([#20011](https://github.com/apache/superset/issues/20011)) ([56e9695](https://github.com/apache/superset/commit/56e96950c17ec65ef18cedfb2ed6591796a96cfc))
-- Date column in Heatmap is displayed as unix timestamp ([#25009](https://github.com/apache/superset/issues/25009)) ([35eb66a](https://github.com/apache/superset/commit/35eb66a322f7938f840778633a4aea11c7f24dce))
-- **explore:** Prevent shared controls from checking feature flags outside React render ([#21315](https://github.com/apache/superset/issues/21315)) ([2285ebe](https://github.com/apache/superset/commit/2285ebe72ec4edded6d195052740b7f9f13d1f1b))
-- Heatmap numeric sorting ([#27360](https://github.com/apache/superset/issues/27360)) ([fe2f5a7](https://github.com/apache/superset/commit/fe2f5a7be9fb6218aa72ab9173481fd21fa40b20))
-- **heatmap:** add detail descriptions for heatmap 'normalize across' ([#20566](https://github.com/apache/superset/issues/20566)) ([d925b0c](https://github.com/apache/superset/commit/d925b0c8835fb1773b80298a3de1bdc368c88850))
-- **legacy-plugin-chart-heatmap:** fix adhoc column tooltip ([#23507](https://github.com/apache/superset/issues/23507)) ([0cebe8b](https://github.com/apache/superset/commit/0cebe8bf18204d17f311345744e67c4bf5961083))
-- **select:** select component sort functionality on certain options ([#17638](https://github.com/apache/superset/issues/17638)) ([f476ba2](https://github.com/apache/superset/commit/f476ba23a279cb87a94ad3075e035cad0ae264b6))
-- Timeseries Y-axis format with contribution mode ([#27106](https://github.com/apache/superset/issues/27106)) ([af577d6](https://github.com/apache/superset/commit/af577d64b17a9730e28e9021376318326fe31437))
-- Tooltips don't disappear on the Heatmap chart ([#24959](https://github.com/apache/superset/issues/24959)) ([9703490](https://github.com/apache/superset/commit/97034901291420af844257fc76ac107d4a891f18))
-
-### Features
-
-- Add currencies controls in control panels ([#24718](https://github.com/apache/superset/issues/24718)) ([f7e76d0](https://github.com/apache/superset/commit/f7e76d02b7cbe4940946673590bb979984ace9f5))
-- Adds the ECharts Heatmap chart ([#25353](https://github.com/apache/superset/issues/25353)) ([546d48a](https://github.com/apache/superset/commit/546d48adbb84b1354d6a3d4ae88dbeba0ad14d44))
-- **chart & legend:** make to enable show legend by default ([#19927](https://github.com/apache/superset/issues/19927)) ([7b3d0f0](https://github.com/apache/superset/commit/7b3d0f040b050905f7d0901d0227f1cd6b761b56))
-- **explore:** Apply denormalization to tier 2 charts form data ([#20524](https://github.com/apache/superset/issues/20524)) ([e12ee59](https://github.com/apache/superset/commit/e12ee59b13822241dca8d8015f1222c477edd4f3))
-- Implement support for currencies in more charts ([#24594](https://github.com/apache/superset/issues/24594)) ([d74d7ec](https://github.com/apache/superset/commit/d74d7eca23a3c94bc48af082c115d34c103e815d))
-
-### Reverts
-
-- Revert "chore(deps): bump d3-svg-legend in /superset-frontend (#19846)" (#19972) ([f144de4](https://github.com/apache/superset/commit/f144de4ee2bf213bb7e17f903bd3975d504c4136)), closes [#19846](https://github.com/apache/superset/issues/19846) [#19972](https://github.com/apache/superset/issues/19972)
-
-# [0.18.0](https://github.com/apache-superset/superset-ui/compare/v0.17.87...v0.18.0) (2021-08-30)
-
-**Note:** Version bump only for package @superset-ui/legacy-plugin-chart-heatmap
-
-## [0.17.61](https://github.com/apache-superset/superset-ui/compare/v0.17.60...v0.17.61) (2021-07-02)
-
-**Note:** Version bump only for package @superset-ui/legacy-plugin-chart-heatmap
diff --git a/superset-frontend/plugins/legacy-plugin-chart-heatmap/README.md b/superset-frontend/plugins/legacy-plugin-chart-heatmap/README.md
deleted file mode 100644
index 2843c8f2a..000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-heatmap/README.md
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-## @superset-ui/legacy-plugin-chart-heatmap
-
-[](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-heatmap)
-[](https://libraries.io/npm/@superset-ui%2Flegacy-plugin-chart-heatmap)
-
-This plugin provides Heatmap for Superset.
-
-### Usage
-
-Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to
-lookup this chart throughout the app.
-
-```js
-import HeatmapChartPlugin from '@superset-ui/legacy-plugin-chart-heatmap';
-
-new HeatmapChartPlugin().configure({ key: 'heatmap' }).register();
-```
-
-Then use it via `SuperChart`. See
-[storybook](https://apache-superset.github.io/superset-ui-plugins/?selectedKind=plugin-chart-heatmap)
-for more details.
-
-```js
-
-```
diff --git a/superset-frontend/plugins/legacy-plugin-chart-heatmap/package.json b/superset-frontend/plugins/legacy-plugin-chart-heatmap/package.json
deleted file mode 100644
index e6cc1a824..000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-heatmap/package.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "name": "@superset-ui/legacy-plugin-chart-heatmap",
- "version": "0.20.3",
- "description": "Superset Legacy Chart - Heatmap",
- "keywords": [
- "superset"
- ],
- "homepage": "https://github.com/apache/superset/tree/master/superset-frontend/plugins/legacy-plugin-chart-heatmap#readme",
- "bugs": {
- "url": "https://github.com/apache/superset/issues"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/apache/superset.git",
- "directory": "superset-frontend/plugins/legacy-plugin-chart-heatmap"
- },
- "license": "Apache-2.0",
- "author": "Superset",
- "main": "lib/index.js",
- "module": "esm/index.js",
- "files": [
- "esm",
- "lib"
- ],
- "dependencies": {
- "d3": "^3.5.17",
- "d3-svg-legend": "^1.x",
- "d3-tip": "^0.9.1",
- "prop-types": "^15.8.1"
- },
- "peerDependencies": {
- "@emotion/react": "^11.4.1",
- "@superset-ui/chart-controls": "*",
- "@superset-ui/core": "*",
- "react": "^16.13.1"
- },
- "publishConfig": {
- "access": "public"
- }
-}
diff --git a/superset-frontend/plugins/legacy-plugin-chart-heatmap/src/Heatmap.js b/superset-frontend/plugins/legacy-plugin-chart-heatmap/src/Heatmap.js
deleted file mode 100644
index ef2c76ad6..000000000
--- a/superset-frontend/plugins/legacy-plugin-chart-heatmap/src/Heatmap.js
+++ /dev/null
@@ -1,458 +0,0 @@
-/**
- * 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.
- */
-/* eslint-disable func-names, react/sort-prop-types */
-import d3 from 'd3';
-import PropTypes from 'prop-types';
-import 'd3-svg-legend';
-import d3tip from 'd3-tip';
-import {
- getColumnLabel,
- getMetricLabel,
- getNumberFormatter,
- NumberFormats,
- getSequentialSchemeRegistry,
-} from '@superset-ui/core';
-
-const propTypes = {
- data: PropTypes.shape({
- records: PropTypes.arrayOf(
- PropTypes.shape({
- x: PropTypes.string,
- y: PropTypes.string,
- v: PropTypes.number,
- perc: PropTypes.number,
- rank: PropTypes.number,
- }),
- ),
- extents: PropTypes.arrayOf(PropTypes.number),
- }),
- width: PropTypes.number,
- height: PropTypes.number,
- bottomMargin: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
- colorScheme: PropTypes.string,
- columnX: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
- columnY: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
- leftMargin: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
- metric: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
- normalized: PropTypes.bool,
- valueFormatter: PropTypes.object,
- showLegend: PropTypes.bool,
- showPercentage: PropTypes.bool,
- showValues: PropTypes.bool,
- sortXAxis: PropTypes.string,
- sortYAxis: PropTypes.string,
- xScaleInterval: PropTypes.number,
- yScaleInterval: PropTypes.number,
- yAxisBounds: PropTypes.arrayOf(PropTypes.number),
-};
-
-function cmp(a, b) {
- return a > b ? 1 : -1;
-}
-
-const DEFAULT_PROPERTIES = {
- minChartWidth: 150,
- minChartHeight: 150,
- marginLeft: 35,
- marginBottom: 35,
- marginTop: 10,
- marginRight: 10,
-};
-
-// Inspired from http://bl.ocks.org/mbostock/3074470
-// https://jsfiddle.net/cyril123/h0reyumq/
-function Heatmap(element, props) {
- const {
- data,
- width,
- height,
- bottomMargin,
- canvasImageRendering,
- colorScheme,
- columnX,
- columnY,
- leftMargin,
- metric,
- normalized,
- valueFormatter,
- showLegend,
- showPercentage,
- showValues,
- sortXAxis,
- sortYAxis,
- xScaleInterval,
- yScaleInterval,
- yAxisBounds,
- xAxisFormatter,
- yAxisFormatter,
- } = props;
-
- const { extents } = data;
- const records = data.records.map(record => ({
- ...record,
- x: xAxisFormatter(record.x),
- y: yAxisFormatter(record.y),
- }));
-
- const margin = {
- top: 10,
- right: 10,
- bottom: 35,
- left: 35,
- };
-
- let showY = true;
- let showX = true;
- const pixelsPerCharX = 4.5; // approx, depends on font size
- let pixelsPerCharY = 6; // approx, depends on font size
-
- // Dynamically adjusts based on max x / y category lengths
- function adjustMargins() {
- let longestX = 1;
- let longestY = 1;
-
- records.forEach(datum => {
- if (typeof datum.y === 'number') pixelsPerCharY = 7;
- longestX = Math.max(
- longestX,
- (datum.x && datum.x.toString().length) || 1,
- );
- longestY = Math.max(
- longestY,
- (datum.y && datum.y.toString().length) || 1,
- );
- });
-
- if (leftMargin === 'auto') {
- margin.left = Math.ceil(Math.max(margin.left, pixelsPerCharY * longestY));
- } else {
- margin.left = leftMargin;
- }
-
- if (showLegend) {
- margin.right += 40;
- }
-
- margin.bottom =
- bottomMargin === 'auto'
- ? Math.ceil(Math.max(margin.bottom, pixelsPerCharX * longestX))
- : bottomMargin;
- }
-
- // Check if x axis "x" position is outside of the container and rotate labels 90deg
- function checkLabelPosition(container) {
- const xAxisNode = container.select('.x.axis').node();
-
- if (!xAxisNode) {
- return;
- }
-
- if (
- xAxisNode.getBoundingClientRect().x + 4 <
- container.node().getBoundingClientRect().x
- ) {
- container
- .selectAll('.x.axis')
- .selectAll('text')
- .attr('transform', 'rotate(-90)')
- .attr('x', -6)
- .attr('y', 0)
- .attr('dy', '0.3em');
- }
- }
-
- function ordScale(k, rangeBands, sortMethod, formatter) {
- let domain = {};
- records.forEach(d => {
- domain[d[k]] = (domain[d[k]] || 0) + d.v;
- });
- const keys = Object.keys(domain).map(k => formatter(k));
- if (sortMethod === 'alpha_asc') {
- domain = keys.sort(cmp);
- } else if (sortMethod === 'alpha_desc') {
- domain = keys.sort(cmp).reverse();
- } else if (sortMethod === 'value_desc') {
- domain = Object.keys(domain).sort((a, b) =>
- domain[a] > domain[b] ? -1 : 1,
- );
- } else if (sortMethod === 'value_asc') {
- domain = Object.keys(domain).sort((a, b) =>
- domain[b] > domain[a] ? -1 : 1,
- );
- }
-
- if (k === 'y' && rangeBands) {
- domain.reverse();
- }
-
- if (rangeBands) {
- return d3.scale.ordinal().domain(domain).rangeBands(rangeBands);
- }
-
- return d3.scale.ordinal().domain(domain).range(d3.range(domain.length));
- }
-
- // eslint-disable-next-line no-param-reassign
- element.innerHTML = '';
- const matrix = {};
-
- adjustMargins();
-
- let hmWidth = width - (margin.left + margin.right);
- let hmHeight = height - (margin.bottom + margin.top);
- const hideYLabel = () => {
- margin.left =
- leftMargin === 'auto' ? DEFAULT_PROPERTIES.marginLeft : leftMargin;
- hmWidth = width - (margin.left + margin.right);
- showY = false;
- };
-
- const hideXLabel = () => {
- margin.bottom =
- bottomMargin === 'auto' ? DEFAULT_PROPERTIES.marginBottom : bottomMargin;
- hmHeight = height - (margin.bottom + margin.top);
- showX = false;
- };
-
- // Hide Y Labels
- if (hmWidth < DEFAULT_PROPERTIES.minChartWidth) {
- hideYLabel();
- }
-
- // Hide X Labels
- if (
- hmHeight < DEFAULT_PROPERTIES.minChartHeight ||
- hmWidth < DEFAULT_PROPERTIES.minChartWidth
- ) {
- hideXLabel();
- }
-
- if (showY && hmHeight < DEFAULT_PROPERTIES.minChartHeight) {
- hideYLabel();
- }
-
- const fp = getNumberFormatter(NumberFormats.PERCENT_2_POINT);
-
- const xScale = ordScale('x', null, sortXAxis, xAxisFormatter);
- const yScale = ordScale('y', null, sortYAxis, yAxisFormatter);
- const xRbScale = ordScale('x', [0, hmWidth], sortXAxis, xAxisFormatter);
- const yRbScale = ordScale('y', [hmHeight, 0], sortYAxis, yAxisFormatter);
- const X = 0;
- const Y = 1;
- const heatmapDim = [xRbScale.domain().length, yRbScale.domain().length];
-
- const minBound = yAxisBounds[0] || 0;
- const maxBound = yAxisBounds[1] || 1;
- const colorScale = getSequentialSchemeRegistry()
- .get(colorScheme)
- .createLinearScale([minBound, maxBound]);
-
- const scale = [
- d3.scale.linear().domain([0, heatmapDim[X]]).range([0, hmWidth]),
- d3.scale.linear().domain([0, heatmapDim[Y]]).range([0, hmHeight]),
- ];
-
- const container = d3.select(element);
- container.classed('superset-legacy-chart-heatmap', true);
-
- const canvas = container
- .append('canvas')
- .attr('width', heatmapDim[X])
- .attr('height', heatmapDim[Y])
- .style('width', `${hmWidth}px`)
- .style('height', `${hmHeight}px`)
- .style('image-rendering', canvasImageRendering)
- .style('left', `${margin.left}px`)
- .style('top', `${margin.top}px`)
- .style('position', 'absolute');
-
- const svg = container
- .append('svg')
- .attr('width', width)
- .attr('height', height)
- .attr('class', 'heatmap-container')
- .style('position', 'relative');
-
- if (showValues) {
- const cells = svg
- .selectAll('rect')
- .data(records)
- .enter()
- .append('g')
- .attr('transform', `translate(${margin.left}, ${margin.top})`);
-
- cells
- .append('text')
- .attr('transform', d => `translate(${xRbScale(d.x)}, ${yRbScale(d.y)})`)
- .attr('y', yRbScale.rangeBand() / 2)
- .attr('x', xRbScale.rangeBand() / 2)
- .attr('text-anchor', 'middle')
- .attr('dy', '.35em')
- .text(d => valueFormatter(d.v))
- .attr(
- 'font-size',
- `${Math.min(yRbScale.rangeBand(), xRbScale.rangeBand()) / 3}px`,
- )
- .attr('fill', d => (d.v >= extents[1] / 2 ? 'white' : 'black'));
- }
-
- if (showLegend) {
- const colorLegend = d3.legend
- .color()
- .labelFormat(valueFormatter)
- .scale(colorScale)
- .shapePadding(0)
- .cells(10)
- .shapeWidth(10)
- .shapeHeight(10)
- .labelOffset(3);
-
- svg
- .append('g')
- .attr('transform', `translate(${width - 40}, ${margin.top})`)
- .call(colorLegend);
- }
-
- const tip = d3tip()
- .attr('class', 'd3-tip')
- .offset(function () {
- const k = d3.mouse(this);
- const x = k[0] - hmWidth / 2;
-
- return [k[1] - 20, x];
- })
- .html(function () {
- let s = '';
- const k = d3.mouse(this);
- const m = Math.floor(scale[0].invert(k[0]));
- const n = Math.floor(scale[1].invert(k[1]));
- if (m in matrix && n in matrix[m]) {
- const obj = matrix[m][n];
- s += `
${valueFormatter(isTotal ? total : series?.point?.y)}
` +
- `
${((100 * series.value) / total).toFixed(2)}%
` +
- '
';
- });
- tooltip += '
';
-
- return dompurify.sanitize(tooltip);
-}
-
export function generateMultiLineTooltipContent(d, xFormatter, yFormatters) {
const tooltipTitle = xFormatter(d.value);
let tooltip = '';
@@ -392,25 +317,6 @@ export function formatLabel(input, verboseMap = {}) {
: verboseLookup(input);
}
-const MIN_BAR_WIDTH = 18;
-
-export function computeBarChartWidth(data, stacked, maxWidth) {
- const barCount = stacked
- ? d3.max(data, d => d.values.length)
- : d3.sum(data, d => d.values.length);
-
- const barWidth = barCount * MIN_BAR_WIDTH;
-
- return Math.max(barWidth, maxWidth);
-}
-
-export function tryNumify(s) {
- // Attempts casting to Number, returns string when failing
- const n = Number(s);
-
- return Number.isNaN(n) ? s : n;
-}
-
export function stringifyTimeRange(extent) {
if (extent.some(d => d.toISOString === undefined)) {
return null;
@@ -438,18 +344,3 @@ export function computeYDomain(data) {
return [0, 1];
}
-
-export function computeStackedYDomain(data) {
- if (Array.isArray(data) && data.length > 0 && Array.isArray(data[0].values)) {
- const series = data
- .filter(d => !d.disabled)
- .map(d => d.values.map(v => v.y));
- const stackedValues = series[0].map((_, i) =>
- series.reduce((acc, cur) => acc + cur[i], 0),
- );
-
- return [Math.min(0, ...stackedValues), Math.max(0, ...stackedValues)];
- }
-
- return [0, 1];
-}
diff --git a/superset-frontend/plugins/legacy-preset-chart-nvd3/test/utils.test.js b/superset-frontend/plugins/legacy-preset-chart-nvd3/test/utils.test.js
index c4bb078fc..137a20e62 100644
--- a/superset-frontend/plugins/legacy-preset-chart-nvd3/test/utils.test.js
+++ b/superset-frontend/plugins/legacy-preset-chart-nvd3/test/utils.test.js
@@ -23,11 +23,9 @@ import {
} from '@superset-ui/core';
import {
- computeStackedYDomain,
computeYDomain,
getTimeOrNumberFormatter,
formatLabel,
- tryNumify,
} from '../src/utils';
const DATA = [
@@ -167,15 +165,6 @@ describe('nvd3/utils', () => {
});
});
- describe('tryNumify()', () => {
- it('tryNumify works as expected', () => {
- expect(tryNumify(5)).toBe(5);
- expect(tryNumify('5')).toBe(5);
- expect(tryNumify('5.1')).toBe(5.1);
- expect(tryNumify('a string')).toBe('a string');
- });
- });
-
describe('computeYDomain()', () => {
it('works with invalid data', () => {
expect(computeYDomain('foo')).toEqual([0, 1]);
@@ -191,20 +180,4 @@ describe('nvd3/utils', () => {
]);
});
});
-
- describe('computeStackedYDomain()', () => {
- it('works with invalid data', () => {
- expect(computeStackedYDomain('foo')).toEqual([0, 1]);
- });
-
- it('works with all series enabled', () => {
- expect(computeStackedYDomain(DATA)).toEqual([0, 2287437662.0]);
- });
-
- it('works with some series disabled', () => {
- expect(computeStackedYDomain(DATA_WITH_DISABLED_SERIES)).toEqual([
- 0, 668526708.0,
- ]);
- });
- });
});
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/README.md b/superset-frontend/plugins/plugin-chart-cartodiagram/README.md
new file mode 100644
index 000000000..803729623
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/README.md
@@ -0,0 +1,67 @@
+
+
+## @superset-ui/plugin-chart-cartodiagram
+
+This plugin allows visualizing charts on a map. To do so, the plugin makes use of existing charts and renders them on the
+provided locations.
+
+Configuring the charts: Charts will be configured in their respective editors. So all configuration options of any chart are supported.
+
+Configuring the map: For the map, an arbitrary number of background layers (WMS, WFS, XYZ), the initial map extent, the chart background color and border radius, as well as the chart size (per zoom level) can be configured.
+
+### Usage
+
+The plugin is configured in `superset-frontend/src/visualizations/presets/MainPreset.js`.
+
+```js
+import { CartodiagramPlugin } from '@superset-ui/plugin-chart-cartodiagram';
+
+new CartodiagramPlugin().configure({ key: 'cartodiagram' }).register();
+```
+
+Default layers can be added to the constructor. These layers will be added to each chart by default (but can be removed by editors). See also `./src/types.ts` for the definitions of types `WmsLayerConf`, `WfsLayerConf` and `XyzLayerConf`.
+
+Example for an XYZ default layer:
+
+```js
+import { CartodiagramPlugin } from '@superset-ui/plugin-chart-cartodiagram';
+
+const opts = {
+ defaultLayers: [
+ {
+ type: 'XYZ',
+ url: 'example.com/path/to/xyz/layer',
+ title: 'my default layer title',
+ attribution: 'my default layer attribution',
+ },
+ ],
+};
+
+new CartodiagramPlugin(opts).configure({ key: 'cartodiagram' }).register();
+```
+
+Please note that by default, Superset rejects requests to third-party domains. If you want to include
+layers from those, you have to adjust the CSP settings. See also docs/docs/security/security.mdx.
+
+### Geometry Column
+
+The plugin requires the selection of a geometry column for a dataset.
+This is expected to be a GeoJSON-Point-Geometry string in WGS 84/Pseudo-Mercator (EPSG:3857). Other formats and projections
+will be supported in the future.
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/package.json b/superset-frontend/plugins/plugin-chart-cartodiagram/package.json
new file mode 100644
index 000000000..ffa652ac8
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/package.json
@@ -0,0 +1,51 @@
+{
+ "name": "@superset-ui/plugin-chart-cartodiagram",
+ "version": "0.0.1",
+ "description": "An OpenLayers map that displays charts for single features.",
+ "sideEffects": false,
+ "main": "lib/index.js",
+ "module": "esm/index.js",
+ "files": [
+ "esm",
+ "lib"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/apache-superset/superset-ui.git"
+ },
+ "keywords": [
+ "superset"
+ ],
+ "license": "Apache-2.0",
+ "bugs": {
+ "url": "https://github.com/apache-superset/superset-ui/issues"
+ },
+ "homepage": "https://github.com/apache-superset/superset-ui#readme",
+ "contributors": [
+ "terrestris GmbH & Co. KG (https://www.terrestris.de)",
+ "meggsimum - Büro für Geoinformatik (https://meggsimum.de)"
+ ],
+ "publishConfig": {
+ "access": "public"
+ },
+ "dependencies": {
+ "@types/geojson": "^7946.0.10",
+ "geojson": "^0.5.0",
+ "lodash": "^4.17.21"
+ },
+ "peerDependencies": {
+ "@ant-design/icons": "^5.2.6",
+ "@superset-ui/chart-controls": "*",
+ "@superset-ui/core": "*",
+ "antd": "^4.10.3",
+ "geostyler": "^12.0.0",
+ "geostyler-data": "^1.0.0",
+ "geostyler-openlayers-parser": "^4.0.0",
+ "geostyler-style": "^7.2.0",
+ "geostyler-wfs-parser": "^2.0.0",
+ "ol": "^7.1.0",
+ "polished": "*",
+ "react": "^17.0.2",
+ "react-dom": "^17.0.2"
+ }
+}
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/CartodiagramPlugin.tsx b/superset-frontend/plugins/plugin-chart-cartodiagram/src/CartodiagramPlugin.tsx
new file mode 100644
index 000000000..0fc871917
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/CartodiagramPlugin.tsx
@@ -0,0 +1,59 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { createRef, useState } from 'react';
+import { styled, useTheme } from '@superset-ui/core';
+import OlMap from 'ol/Map';
+import {
+ CartodiagramPluginProps,
+ CartodiagramPluginStylesProps,
+} from './types';
+
+import OlChartMap from './components/OlChartMap';
+
+import 'ol/ol.css';
+
+// The following Styles component is a
element, which has been styled using Emotion
+// For docs, visit https://emotion.sh/docs/styled
+
+// Theming variables are provided for your use via a ThemeProvider
+// imported from @superset-ui/core. For variables available, please visit
+// https://github.com/apache-superset/superset-ui/blob/master/packages/superset-ui-core/src/style/index.ts
+
+const Styles = styled.div`
+ height: ${({ height }) => height}px;
+ width: ${({ width }) => width}px;
+`;
+
+export default function CartodiagramPlugin(props: CartodiagramPluginProps) {
+ const { height, width } = props;
+ const theme = useTheme();
+
+ const rootElem = createRef();
+
+ const [mapId] = useState(
+ `cartodiagram-plugin-${Math.floor(Math.random() * 1000000)}`,
+ );
+ const [olMap] = useState(new OlMap({}));
+
+ return (
+
+
+
+ );
+}
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/components/ChartLayer.tsx b/superset-frontend/plugins/plugin-chart-cartodiagram/src/components/ChartLayer.tsx
new file mode 100644
index 000000000..8800f3da3
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/components/ChartLayer.tsx
@@ -0,0 +1,282 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import Layer from 'ol/layer/Layer';
+import { FrameState } from 'ol/Map';
+import { apply as applyTransform } from 'ol/transform';
+import ReactDOM from 'react-dom';
+import { SupersetTheme } from '@superset-ui/core';
+import { ChartConfig, ChartLayerOptions, ChartSizeValues } from '../types';
+import { createChartComponent } from '../util/chartUtil';
+import { getProjectedCoordinateFromPointGeoJson } from '../util/geometryUtil';
+
+import Loader from '../images/loading.gif';
+
+/**
+ * Custom OpenLayers layer that displays charts on given locations.
+ */
+export class ChartLayer extends Layer {
+ charts: any[] = [];
+
+ chartConfigs: ChartConfig = {
+ type: 'FeatureCollection',
+ features: [],
+ };
+
+ chartSizeValues: ChartSizeValues = {};
+
+ chartVizType: string;
+
+ div: HTMLDivElement;
+
+ loadingMask: HTMLDivElement;
+
+ chartBackgroundCssColor = '';
+
+ chartBackgroundBorderRadius = 0;
+
+ theme: SupersetTheme;
+
+ /**
+ * Create a ChartLayer.
+ *
+ * @param {ChartLayerOptions} options The options to create a ChartLayer
+ * @param {ChartHtmlElement[]} options.charts An array with the chart objects containing the HTML element and the coordinate
+ * @param {ChartConfig} options.chartConfigs The chart configuration for the charts
+ * @param {ChartSizeValues} options.chartSizeValues The values for the chart sizes
+ * @param {String} options.chartVizType The viztype of the charts
+ * @param {String} options.chartBackgroundCssColor The color of the additionally added chart background
+ * @param {Number} options.chartBackgroundBorderRadius The border radius in percent of the additionally added chart background
+ * @param {Function} options.onMouseOver The handler function to execute when the mouse entering a HTML element
+ * @param {Function} options.onMouseOut The handler function to execute when the mouse leaves a HTML element
+ * @param {SupersetTheme} options.theme The superset theme
+ */
+ constructor(options: ChartLayerOptions) {
+ super(options);
+
+ this.chartVizType = options.chartVizType;
+
+ if (options.chartConfigs) {
+ this.chartConfigs = options.chartConfigs;
+ }
+
+ if (options.chartSizeValues) {
+ this.chartSizeValues = options.chartSizeValues;
+ }
+
+ if (options.chartBackgroundCssColor) {
+ this.chartBackgroundCssColor = options.chartBackgroundCssColor;
+ }
+
+ if (options.chartBackgroundBorderRadius) {
+ this.chartBackgroundBorderRadius = options.chartBackgroundBorderRadius;
+ }
+
+ if (options.theme) {
+ this.theme = options.theme;
+ }
+
+ const spinner = document.createElement('img');
+ spinner.src = Loader;
+ spinner.style.position = 'relative';
+ spinner.style.width = '50px';
+ spinner.style.top = '50%';
+ spinner.style.left = '50%';
+ spinner.style.transform = 'translate(-50%, -50%)';
+
+ this.loadingMask = document.createElement('div');
+ this.loadingMask.style.position = 'relative';
+ this.loadingMask.style.height = '100%';
+ this.loadingMask.appendChild(spinner);
+
+ this.div = document.createElement('div');
+
+ // TODO: consider creating an OpenLayers event
+ if (options.onMouseOver) {
+ this.div.onmouseover = options.onMouseOver;
+ }
+
+ // TODO: consider creating an OpenLayers event
+ if (options.onMouseOut) {
+ this.div.onmouseout = options.onMouseOut;
+ }
+ }
+
+ setChartConfig(chartConfigs: ChartConfig, silent = false) {
+ this.chartConfigs = chartConfigs;
+ if (!silent) {
+ this.changed();
+ }
+ }
+
+ setChartVizType(chartVizType: string, silent = false) {
+ this.chartVizType = chartVizType;
+ if (!silent) {
+ this.changed();
+ }
+ }
+
+ setChartSizeValues(chartSizeValues: ChartSizeValues, silent = false) {
+ this.chartSizeValues = chartSizeValues;
+ if (!silent) {
+ this.changed();
+ }
+ }
+
+ setChartBackgroundCssColor(chartBackgroundCssColor: string, silent = false) {
+ this.chartBackgroundCssColor = chartBackgroundCssColor;
+ if (!silent) {
+ this.changed();
+ }
+ }
+
+ setChartBackgroundBorderRadius(
+ chartBackgroundBorderRadius: number,
+ silent = false,
+ ) {
+ this.chartBackgroundBorderRadius = chartBackgroundBorderRadius;
+ if (!silent) {
+ this.changed();
+ }
+ }
+
+ /**
+ * Unmount and remove all created chart elements from the DOM.
+ */
+ removeAllChartElements() {
+ this.charts.forEach(chart => {
+ ReactDOM.unmountComponentAtNode(chart.htmlElement);
+ chart.htmlElement.remove();
+ });
+ this.charts = [];
+ }
+
+ createCharts(zoom: number) {
+ const charts = this.chartConfigs.features.map(feature => {
+ const container = document.createElement('div');
+
+ let chartWidth = 0;
+ let chartHeight = 0;
+ if (this.chartSizeValues[zoom]) {
+ chartWidth = this.chartSizeValues[zoom].width;
+ chartHeight = this.chartSizeValues[zoom].height;
+ }
+
+ const chartComponent = createChartComponent(
+ this.chartVizType,
+ feature,
+ chartWidth,
+ chartHeight,
+ this.theme,
+ );
+ ReactDOM.render(chartComponent, container);
+
+ return {
+ htmlElement: container,
+ coordinate: getProjectedCoordinateFromPointGeoJson(feature.geometry),
+ width: chartWidth,
+ height: chartHeight,
+ feature,
+ };
+ });
+
+ this.charts = charts;
+ }
+
+ updateCharts(zoom: number) {
+ const charts = this.charts.map(chart => {
+ let chartWidth = 0;
+ let chartHeight = 0;
+ if (this.chartSizeValues[zoom]) {
+ chartWidth = this.chartSizeValues[zoom].width;
+ chartHeight = this.chartSizeValues[zoom].height;
+ }
+
+ // only rerender chart if size changes
+ if (chartWidth === chart.width && chartHeight === chart.height) {
+ return chart;
+ }
+
+ const chartComponent = createChartComponent(
+ this.chartVizType,
+ chart.feature,
+ chartWidth,
+ chartHeight,
+ this.theme,
+ );
+ ReactDOM.render(chartComponent, chart.htmlElement);
+
+ return {
+ ...chart,
+ width: chartWidth,
+ height: chartHeight,
+ };
+ });
+
+ this.charts = charts;
+ }
+
+ render(frameState: FrameState | null) {
+ if (!frameState) {
+ return this.div;
+ }
+
+ const { viewState } = frameState;
+ const currentZoom = Math.round(viewState.zoom);
+
+ // nextResolution is only defined while an animation
+ // is in action. For this time we show a loading mask
+ // to keep the amount of chart rerenderings as low as possible.
+ if (viewState.nextResolution) {
+ return this.loadingMask;
+ }
+
+ if (this.charts.length === 0) {
+ this.createCharts(currentZoom);
+ } else {
+ this.updateCharts(currentZoom);
+ }
+
+ this.charts.forEach(chartObject => {
+ const { htmlElement, coordinate, width, height } = chartObject;
+
+ // clone, because applyTransform modifies in place
+ const coordCopy = [...coordinate];
+
+ const [x, y] = applyTransform(
+ frameState.coordinateToPixelTransform,
+ coordCopy,
+ );
+
+ // left and top are corrected to place the center of the chart to its location
+ htmlElement.style.left = `${x - width / 2}px`;
+ htmlElement.style.top = `${y - height / 2}px`;
+ htmlElement.style.position = 'absolute';
+ htmlElement.style['background-color' as any] =
+ this.chartBackgroundCssColor;
+ htmlElement.style['border-radius' as any] =
+ `${this.chartBackgroundBorderRadius}%`;
+ });
+
+ // TODO should we always replace the html elements or is there a better way?
+ const htmlElements = this.charts.map(c => c.htmlElement);
+ this.div.replaceChildren(...htmlElements);
+
+ return this.div;
+ }
+}
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/components/ChartWrapper.tsx b/superset-frontend/plugins/plugin-chart-cartodiagram/src/components/ChartWrapper.tsx
new file mode 100644
index 000000000..ed441a718
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/components/ChartWrapper.tsx
@@ -0,0 +1,53 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { getChartComponentRegistry, ThemeProvider } from '@superset-ui/core';
+import { FC, useEffect, useState } from 'react';
+import { ChartWrapperProps } from '../types';
+
+export const ChartWrapper: FC = ({
+ vizType,
+ theme,
+ height,
+ width,
+ chartConfig,
+}) => {
+ const [Chart, setChart] = useState();
+
+ const getChartFromRegistry = async (vizType: string) => {
+ const registry = getChartComponentRegistry();
+ const c = await registry.getAsPromise(vizType);
+ setChart(() => c);
+ };
+
+ useEffect(() => {
+ getChartFromRegistry(vizType);
+ }, [vizType]);
+
+ return (
+
+ {Chart === undefined ? (
+ <>>
+ ) : (
+
+ )}
+
+ );
+};
+
+export default ChartWrapper;
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/components/OlChartMap.tsx b/superset-frontend/plugins/plugin-chart-cartodiagram/src/components/OlChartMap.tsx
new file mode 100644
index 000000000..4982c5b95
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/components/OlChartMap.tsx
@@ -0,0 +1,409 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { useEffect, useState } from 'react';
+
+import Point from 'ol/geom/Point';
+import { View } from 'ol';
+import BaseEvent from 'ol/events/Event';
+import { unByKey } from 'ol/Observable';
+import { toLonLat } from 'ol/proj';
+import { debounce } from 'lodash';
+import { fitMapToCharts } from '../util/mapUtil';
+import { ChartLayer } from './ChartLayer';
+import { createLayer } from '../util/layerUtil';
+import {
+ ChartConfig,
+ LayerConf,
+ MapViewConfigs,
+ OlChartMapProps,
+} from '../types';
+import { isChartConfigEqual } from '../util/chartUtil';
+
+/** The name to reference the chart layer */
+const CHART_LAYER_NAME = 'openlayers-chart-layer';
+
+export const OlChartMap = (props: OlChartMapProps) => {
+ const {
+ height,
+ width,
+ mapId,
+ olMap,
+ chartConfigs,
+ chartSize,
+ chartVizType,
+ layerConfigs,
+ mapView,
+ chartBackgroundColor,
+ chartBackgroundBorderRadius,
+ setControlValue,
+ theme,
+ } = props;
+
+ const [currentChartConfigs, setCurrentChartConfigs] =
+ useState(chartConfigs);
+ const [currentMapView, setCurrentMapView] = useState(mapView);
+
+ /**
+ * Add map to correct DOM element.
+ */
+ useEffect(() => {
+ olMap.setTarget(mapId);
+ }, [olMap, mapId]);
+
+ /**
+ * Update map size if size of parent container changes.
+ */
+ useEffect(() => {
+ olMap.updateSize();
+ }, [olMap, width, height]);
+
+ /**
+ * The prop chartConfigs will always be created on the fly,
+ * therefore the shallow comparison of the effect hooks will
+ * always trigger. In this hook, we make a 'deep comparison'
+ * between the incoming prop and the state. Only if the objects
+ * differ will we set the state to the new object. All other
+ * effect hooks that depend on chartConfigs should now depend
+ * on currentChartConfigs instead.
+ */
+ useEffect(() => {
+ setCurrentChartConfigs(oldCurrentChartConfigs => {
+ if (isChartConfigEqual(chartConfigs, oldCurrentChartConfigs)) {
+ return oldCurrentChartConfigs;
+ }
+ return chartConfigs;
+ });
+ }, [chartConfigs]);
+
+ /**
+ * The prop mapView will always be created on the fly,
+ * therefore the shallow comparison of the effect hooks will
+ * always trigger. In this hook, we compare only those props
+ * that might be changed from outside of the component, i.e the
+ * fixed properties and the mode. Only if these values differ will
+ * we set the state to the new object. All other effect hooks that
+ * depend on mapView should now depend on currentMapView instead.
+ */
+ useEffect(() => {
+ setCurrentMapView(oldCurrentMapView => {
+ const sameFixedZoom = oldCurrentMapView.fixedZoom === mapView.fixedZoom;
+ const sameFixedLon =
+ oldCurrentMapView.fixedLongitude === mapView.fixedLongitude;
+ const sameFixedLat =
+ oldCurrentMapView.fixedLatitude === mapView.fixedLatitude;
+ const sameMode = oldCurrentMapView.mode === mapView.mode;
+ if (sameFixedZoom && sameFixedLon && sameFixedLat && sameMode) {
+ return oldCurrentMapView;
+ }
+ return mapView;
+ });
+ }, [mapView]);
+
+ /**
+ * Set initial map extent.
+ */
+ useEffect(() => {
+ const view = olMap.getView();
+ const { mode, fixedLatitude, fixedLongitude, fixedZoom } = mapView;
+
+ switch (mode) {
+ case 'CUSTOM': {
+ const fixedCenter = new Point([fixedLongitude, fixedLatitude]);
+ fixedCenter.transform('EPSG:4326', 'EPSG:3857'); // in-place
+
+ view.setZoom(fixedZoom);
+ view.setCenter(fixedCenter.getCoordinates());
+ break;
+ }
+ default: {
+ fitMapToCharts(olMap, chartConfigs);
+
+ const zoom = view.getZoom();
+ const centerCoord = view.getCenter();
+ if (!centerCoord) return;
+
+ const centerPoint = new Point(centerCoord);
+ centerPoint.transform('EPSG:3857', 'EPSG:4326'); // in-place
+
+ const [longitude, latitude] = centerPoint.getCoordinates();
+
+ setControlValue('map_view', {
+ ...mapView,
+ zoom,
+ longitude,
+ latitude,
+ fixedLatitude: latitude,
+ fixedLongitude: longitude,
+ fixedZoom: zoom,
+ });
+
+ break;
+ }
+ }
+ }, []);
+
+ /**
+ * Update non-chart layers
+ */
+ useEffect(() => {
+ // clear existing layers
+ // We first filter the layers we want to remove,
+ // because removing items from an array during a loop can be erroneous.
+ const layersToRemove = olMap
+ .getLayers()
+ .getArray()
+ .filter(layer => !(layer instanceof ChartLayer));
+
+ layersToRemove.forEach(layer => {
+ olMap.removeLayer(layer);
+ });
+
+ const addLayers = async (configs: LayerConf[]) => {
+ // Loop through layer configs, create layers and add them to map.
+ // The first layer in the list will be the upmost layer on the map.
+ // With insertAt(0) we ensure that the chart layer will always
+ // stay on top, though.
+ const createdLayersPromises = configs.map(createLayer);
+ const createdLayers = await Promise.allSettled(createdLayersPromises);
+ createdLayers.forEach((createdLayer, idx) => {
+ if (createdLayer.status === 'fulfilled' && createdLayer.value) {
+ olMap.getLayers().insertAt(0, createdLayer.value);
+ } else {
+ console.warn(`Layer could not be created: ${configs[idx]}`);
+ }
+ });
+ };
+
+ addLayers(layerConfigs);
+ }, [olMap, layerConfigs]);
+
+ /**
+ * Create listener on map movement
+ */
+ useEffect(() => {
+ const { fixedLatitude, fixedLongitude, fixedZoom } = currentMapView;
+
+ const view = olMap.getView();
+
+ const onViewChange = (event: BaseEvent) => {
+ const targetView: View = event.target as unknown as View;
+
+ const center = targetView.getCenter();
+ const zoom = targetView.getZoom();
+ if (!center) {
+ return;
+ }
+ const [longitude, latitude] = toLonLat(center);
+
+ setControlValue('map_view', {
+ ...currentMapView,
+ zoom,
+ longitude,
+ latitude,
+ fixedLatitude,
+ fixedLongitude,
+ fixedZoom,
+ });
+ };
+
+ // TODO: maybe replace with debounce from lodash
+ // timeout=100ms seems to work well, 1000ms has other side-effects
+ function debounce(func: Function, timeout = 100) {
+ let timer: number;
+ return function (this: any, ...args: any) {
+ clearTimeout(timer);
+ timer = window.setTimeout(() => func.apply(this, args), timeout);
+ };
+ }
+
+ const debouncedOnViewChange = debounce((event: BaseEvent) => {
+ onViewChange(event);
+ });
+
+ const listenerKey = view.on('change', debouncedOnViewChange);
+
+ // this is executed before the next render,
+ // here we cleanup the listener
+ return () => {
+ unByKey(listenerKey);
+ };
+ }, [olMap, setControlValue, currentMapView, currentChartConfigs]);
+
+ useEffect(() => {
+ if (currentMapView.mode === 'FIT_DATA') {
+ const layers = olMap.getLayers();
+ const chartLayer = layers
+ .getArray()
+ .find(layer => layer instanceof ChartLayer) as ChartLayer;
+
+ if (!chartLayer) {
+ return;
+ }
+ const extent = chartLayer.getExtent();
+ if (!extent) {
+ return;
+ }
+ const view = olMap.getView();
+ view.fit(extent, {
+ size: [250, 250],
+ });
+ }
+ }, [olMap, currentMapView.mode]);
+
+ /**
+ * Send updated zoom to chart config control.
+ */
+ useEffect(() => {
+ const view = olMap.getView();
+
+ const onViewChange = (event: BaseEvent) => {
+ const targetView: View = event.target as unknown as View;
+
+ // ensure only zoom has changed
+ const zoom = targetView.getZoom();
+
+ // needed for TypeScript
+ if (!zoom) return;
+
+ // round zoom to full integer
+ const previousZoom = Math.round(chartSize.configs.zoom);
+ const newZoom = Math.round(zoom);
+
+ // if zoom has not changed, we return and do not update the controls
+ if (previousZoom === newZoom) return;
+
+ const updatedChartSizeConf = {
+ ...chartSize,
+ configs: {
+ ...chartSize.configs,
+ zoom: newZoom,
+ },
+ };
+
+ setControlValue('chart_size', updatedChartSizeConf);
+ };
+
+ const debouncedOnZoomChange = debounce((event: BaseEvent) => {
+ onViewChange(event);
+ }, 100);
+
+ const listenerKey = view.on('change:resolution', debouncedOnZoomChange);
+
+ // This is executed before the next render,
+ // here we cleanup our listener.
+ return () => {
+ unByKey(listenerKey);
+ };
+ }, [olMap, setControlValue, chartSize]);
+
+ /**
+ * Handle changes that trigger changes of charts. Also instantiate
+ * the chart layer, if it does not exist yet.
+ */
+ useEffect(() => {
+ const layers = olMap.getLayers();
+ const chartLayer = layers
+ .getArray()
+ .find(layer => layer instanceof ChartLayer) as ChartLayer;
+
+ const { r, g, b, a } = chartBackgroundColor;
+ const cssColor = `rgba(${r}, ${g}, ${b}, ${a})`;
+
+ if (!chartLayer) {
+ layers.forEach(layer => {
+ if (!(layer instanceof ChartLayer)) {
+ return;
+ }
+ // remove all chart elements from dom.
+ layer.removeAllChartElements();
+ // delete previous chart layers
+ olMap.removeLayer(layer);
+ });
+
+ // prevent map interactions when mouse is over chart element
+ // inspired by https://gis.stackexchange.com/questions/303331
+ const deactivateInteractions = () => {
+ olMap.getInteractions().forEach(interaction => {
+ interaction.setActive(false);
+ });
+ };
+
+ const activateInteractions = () => {
+ olMap.getInteractions().forEach(interaction => {
+ interaction.setActive(true);
+ });
+ };
+
+ const newChartLayer = new ChartLayer({
+ name: CHART_LAYER_NAME,
+ chartConfigs: currentChartConfigs,
+ chartVizType,
+ chartSizeValues: chartSize.values,
+ chartBackgroundCssColor: cssColor,
+ chartBackgroundBorderRadius,
+ onMouseOver: deactivateInteractions,
+ onMouseOut: activateInteractions,
+ theme,
+ });
+
+ olMap.addLayer(newChartLayer);
+ } else {
+ let recreateCharts = false;
+ if (chartVizType !== chartLayer.chartVizType) {
+ chartLayer.setChartVizType(chartVizType, true);
+ recreateCharts = true;
+ }
+ if (!isChartConfigEqual(currentChartConfigs, chartLayer.chartConfigs)) {
+ chartLayer.setChartConfig(currentChartConfigs, true);
+ recreateCharts = true;
+ }
+ // Only the last setter triggers rerendering of charts
+ chartLayer.setChartBackgroundBorderRadius(
+ chartBackgroundBorderRadius,
+ true,
+ );
+ chartLayer.setChartBackgroundCssColor(cssColor, true);
+ chartLayer.setChartSizeValues(chartSize.values, true);
+ if (recreateCharts) {
+ chartLayer.removeAllChartElements();
+ }
+ chartLayer.changed();
+ }
+ }, [
+ olMap,
+ theme,
+ currentChartConfigs,
+ chartVizType,
+ chartSize.values,
+ chartBackgroundColor,
+ chartBackgroundBorderRadius,
+ ]);
+
+ return (
+
+ );
+};
+
+export default OlChartMap;
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/images/example1.png b/superset-frontend/plugins/plugin-chart-cartodiagram/src/images/example1.png
new file mode 100644
index 000000000..6fe034477
Binary files /dev/null and b/superset-frontend/plugins/plugin-chart-cartodiagram/src/images/example1.png differ
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/images/example2.png b/superset-frontend/plugins/plugin-chart-cartodiagram/src/images/example2.png
new file mode 100644
index 000000000..7d42dc459
Binary files /dev/null and b/superset-frontend/plugins/plugin-chart-cartodiagram/src/images/example2.png differ
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/images/loading.gif b/superset-frontend/plugins/plugin-chart-cartodiagram/src/images/loading.gif
new file mode 100644
index 000000000..d82fc5d92
Binary files /dev/null and b/superset-frontend/plugins/plugin-chart-cartodiagram/src/images/loading.gif differ
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/images/thumbnail.png b/superset-frontend/plugins/plugin-chart-cartodiagram/src/images/thumbnail.png
new file mode 100644
index 000000000..bfd953933
Binary files /dev/null and b/superset-frontend/plugins/plugin-chart-cartodiagram/src/images/thumbnail.png differ
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/index.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/src/index.ts
new file mode 100644
index 000000000..ca175475a
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/index.ts
@@ -0,0 +1,20 @@
+/**
+ * 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.
+ */
+// eslint-disable-next-line import/prefer-default-export
+export { default as CartodiagramPlugin } from './plugin';
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/plugin/buildQuery.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/src/plugin/buildQuery.ts
new file mode 100644
index 000000000..87f1d1fd8
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/plugin/buildQuery.ts
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { QueryFormData, getChartBuildQueryRegistry } from '@superset-ui/core';
+
+export default function buildQuery(formData: QueryFormData) {
+ const {
+ selected_chart: selectedChartString,
+ geom_column: geometryColumn,
+ extra_form_data: extraFormData,
+ } = formData;
+ const selectedChart = JSON.parse(selectedChartString);
+ const vizType = selectedChart.viz_type;
+ const chartFormData = JSON.parse(selectedChart.params);
+ // Pass extra_form_data to chartFormData so that
+ // dashboard filters will also be applied to the charts
+ // on the map.
+ chartFormData.extra_form_data = {
+ ...chartFormData.extra_form_data,
+ ...extraFormData,
+ };
+
+ // adapt groupby property to ensure geometry column always exists
+ // and is always at first position
+ let { groupby } = chartFormData;
+ if (!groupby) {
+ groupby = [];
+ }
+ // add geometry column at the first place
+ groupby?.unshift(geometryColumn);
+ chartFormData.groupby = groupby;
+
+ // TODO: find way to import correct type "InclusiveLoaderResult"
+ const buildQueryRegistry = getChartBuildQueryRegistry();
+ const chartQueryBuilder = buildQueryRegistry.get(vizType) as any;
+
+ const chartQuery = chartQueryBuilder(chartFormData);
+ return chartQuery;
+}
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/plugin/controlPanel.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/src/plugin/controlPanel.ts
new file mode 100644
index 000000000..163d9defd
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/plugin/controlPanel.ts
@@ -0,0 +1,193 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { t, validateNonEmpty } from '@superset-ui/core';
+import { ControlPanelConfig } from '@superset-ui/chart-controls';
+import { selectedChartMutator } from '../util/controlPanelUtil';
+
+import { MAX_ZOOM_LEVEL, MIN_ZOOM_LEVEL } from '../util/zoomUtil';
+
+const config: ControlPanelConfig = {
+ controlPanelSections: [
+ {
+ label: t('Configuration'),
+ expanded: true,
+ controlSetRows: [
+ [
+ {
+ name: 'selected_chart',
+ config: {
+ type: 'SelectAsyncControl',
+ mutator: selectedChartMutator,
+ multi: false,
+ label: t('Chart'),
+ validators: [validateNonEmpty],
+ description: t('Choose a chart for displaying on the map'),
+ placeholder: t('Select chart'),
+ onAsyncErrorMessage: t('Error while fetching charts'),
+ mapStateToProps: state => {
+ if (state?.datasource?.id) {
+ const datasourceId = state.datasource.id;
+ const query = {
+ columns: ['id', 'slice_name', 'params', 'viz_type'],
+ filters: [
+ {
+ col: 'datasource_id',
+ opr: 'eq',
+ value: datasourceId,
+ },
+ ],
+ page: 0,
+ // TODO check why we only retrieve 100 items, even though there are more
+ page_size: 999,
+ };
+
+ const dataEndpoint = `/api/v1/chart/?q=${JSON.stringify(
+ query,
+ )}`;
+
+ return { dataEndpoint };
+ }
+ // could not extract datasource from map
+ return {};
+ },
+ },
+ },
+ ],
+ [
+ {
+ name: 'geom_column',
+ config: {
+ type: 'SelectControl',
+ label: t('Geometry Column'),
+ renderTrigger: false,
+ description: t('The name of the geometry column'),
+ mapStateToProps: state => ({
+ choices: state.datasource?.columns.map(c => [
+ c.column_name,
+ c.column_name,
+ ]),
+ }),
+ validators: [validateNonEmpty],
+ },
+ },
+ ],
+ ],
+ },
+ {
+ label: t('Map Options'),
+ expanded: true,
+ controlSetRows: [
+ [
+ {
+ name: 'map_view',
+ config: {
+ type: 'MapViewControl',
+ renderTrigger: true,
+ description: t(
+ 'The extent of the map on application start. FIT DATA automatically sets the extent so that all data points are included in the viewport. CUSTOM allows users to define the extent manually.',
+ ),
+ label: t('Extent'),
+ dontRefreshOnChange: true,
+ default: {
+ mode: 'FIT_DATA',
+ },
+ },
+ },
+ ],
+ [
+ {
+ // name is referenced in 'index.ts' for setting default value
+ name: 'layer_configs',
+ config: {
+ type: 'LayerConfigsControl',
+ renderTrigger: true,
+ label: t('Layers'),
+ default: [],
+ description: t('The configuration for the map layers'),
+ },
+ },
+ ],
+ ],
+ },
+ {
+ label: t('Chart Options'),
+ expanded: true,
+ controlSetRows: [
+ [
+ {
+ name: 'chart_background_color',
+ config: {
+ label: t('Background Color'),
+ description: t('The background color of the charts.'),
+ type: 'ColorPickerControl',
+ default: { r: 255, g: 255, b: 255, a: 0.2 },
+ renderTrigger: true,
+ },
+ },
+ ],
+ [
+ {
+ name: 'chart_background_border_radius',
+ config: {
+ label: t('Corner Radius'),
+ description: t('The corner radius of the chart background'),
+ type: 'SliderControl',
+ default: 10,
+ min: 0,
+ step: 1,
+ max: 100,
+ renderTrigger: true,
+ },
+ },
+ ],
+ [
+ {
+ name: 'chart_size',
+ config: {
+ type: 'ZoomConfigControl',
+ // set this to true, if we are able to render it fast
+ renderTrigger: true,
+ default: {
+ type: 'FIXED',
+ configs: {
+ zoom: 6,
+ width: 100,
+ height: 100,
+ slope: 30,
+ exponent: 2,
+ },
+ // create an object with keys MIN_ZOOM_LEVEL - MAX_ZOOM_LEVEL
+ // that all contain the same initial value
+ values: {
+ ...Array.from(
+ { length: MAX_ZOOM_LEVEL - MIN_ZOOM_LEVEL + 1 },
+ () => ({ width: 100, height: 100 }),
+ ),
+ },
+ },
+ label: t('Chart size'),
+ description: t('Configure the chart size for each zoom level'),
+ },
+ },
+ ],
+ ],
+ },
+ ],
+};
+export default config;
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/plugin/index.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/src/plugin/index.ts
new file mode 100644
index 000000000..f26361d68
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/plugin/index.ts
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { t, ChartMetadata, ChartPlugin } from '@superset-ui/core';
+import buildQuery from './buildQuery';
+import controlPanel from './controlPanel';
+import transformProps from './transformProps';
+import thumbnail from '../images/thumbnail.png';
+import example1 from '../images/example1.png';
+import example2 from '../images/example2.png';
+import { CartodiagramPluginConstructorOpts } from '../types';
+import { getLayerConfig } from '../util/controlPanelUtil';
+
+export default class CartodiagramPlugin extends ChartPlugin {
+ constructor(opts: CartodiagramPluginConstructorOpts) {
+ const metadata = new ChartMetadata({
+ description:
+ 'Display charts on a map. For using this plugin, users first have to create any other chart that can then be placed on the map.',
+ name: t('Cartodiagram'),
+ thumbnail,
+ tags: [t('Geo'), t('2D'), t('Spatial'), t('Experimental')],
+ category: t('Map'),
+ exampleGallery: [
+ { url: example1, caption: t('Pie charts on a map') },
+ { url: example2, caption: t('Line charts on a map') },
+ ],
+ });
+
+ if (opts.defaultLayers) {
+ const layerConfig = getLayerConfig(controlPanel);
+
+ // set defaults for layer config if found
+ if (layerConfig) {
+ layerConfig.config.default = opts.defaultLayers;
+ } else {
+ // eslint-disable-next-line no-console
+ console.warn(
+ 'Cannot set defaultLayers. layerConfig not found in control panel. Please check if the path to layerConfig should be adjusted.',
+ );
+ }
+ }
+
+ super({
+ buildQuery,
+ controlPanel,
+ loadChart: () => import('../CartodiagramPlugin'),
+ metadata,
+ transformProps,
+ });
+ }
+}
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/plugin/transformProps.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/src/plugin/transformProps.ts
new file mode 100644
index 000000000..c868591ea
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/plugin/transformProps.ts
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { ChartProps, getChartTransformPropsRegistry } from '@superset-ui/core';
+import {
+ getChartConfigs,
+ parseSelectedChart,
+} from '../util/transformPropsUtil';
+
+export default function transformProps(chartProps: ChartProps) {
+ const { width, height, formData, hooks, theme } = chartProps;
+ const {
+ geomColumn,
+ selectedChart: selectedChartString,
+ chartSize,
+ layerConfigs,
+ mapView,
+ chartBackgroundColor,
+ chartBackgroundBorderRadius,
+ } = formData;
+ const { setControlValue = () => {} } = hooks;
+ const selectedChart = parseSelectedChart(selectedChartString);
+ const transformPropsRegistry = getChartTransformPropsRegistry();
+ const chartTransformer = transformPropsRegistry.get(selectedChart.viz_type);
+
+ const chartConfigs = getChartConfigs(
+ selectedChart,
+ geomColumn,
+ chartProps,
+ chartTransformer,
+ );
+
+ return {
+ width,
+ height,
+ geomColumn,
+ selectedChart,
+ chartConfigs,
+ chartVizType: selectedChart.viz_type,
+ chartSize,
+ layerConfigs,
+ mapView,
+ chartBackgroundColor,
+ chartBackgroundBorderRadius,
+ setControlValue,
+ theme,
+ };
+}
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/typeguards.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/src/typeguards.ts
new file mode 100644
index 000000000..a65e0f124
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/typeguards.ts
@@ -0,0 +1,31 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { LayerConf, WfsLayerConf, WmsLayerConf, XyzLayerConf } from './types';
+
+export const isWmsLayerConf = (
+ layerConf: LayerConf,
+): layerConf is WmsLayerConf => layerConf.type === 'WMS';
+
+export const isWfsLayerConf = (
+ layerConf: LayerConf,
+): layerConf is WfsLayerConf => layerConf.type === 'WFS';
+
+export const isXyzLayerConf = (
+ layerConf: LayerConf,
+): layerConf is XyzLayerConf => layerConf.type === 'XYZ';
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/types.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/src/types.ts
new file mode 100644
index 000000000..a875103d9
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/types.ts
@@ -0,0 +1,210 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import {
+ DataRecord,
+ SupersetTheme,
+ TimeseriesDataRecord,
+} from '@superset-ui/core';
+import { RenderFunction } from 'ol/layer/Layer';
+import { Extent } from 'ol/extent';
+import Source from 'ol/source/Source';
+import { Coordinate } from 'ol/coordinate';
+import { Map } from 'ol';
+import { Feature, FeatureCollection, Point } from 'geojson';
+import { Style } from 'geostyler-style';
+
+export interface CartodiagramPluginStylesProps {
+ height: number;
+ width: number;
+ theme: SupersetTheme;
+}
+
+// TODO find a way to reference props from other charts
+export type ChartConfigProperties = any;
+
+export type ChartConfigFeature = Feature;
+export type ChartConfig = FeatureCollection<
+ ChartConfigFeature['geometry'],
+ ChartConfigFeature['properties']
+>;
+
+interface CartodiagramPluginCustomizeProps {
+ geomColumn: string;
+ selectedChart: string;
+ chartConfigs: ChartConfig;
+ chartSize: ZoomConfigs;
+ chartVizType: string;
+ layerConfigs: LayerConf[];
+ mapView: MapViewConfigs;
+ chartBackgroundColor: {
+ r: number;
+ g: number;
+ b: number;
+ a: number;
+ };
+ chartBackgroundBorderRadius: number;
+ setControlValue: Function;
+}
+
+export type CartodiagramPluginProps = CartodiagramPluginStylesProps &
+ CartodiagramPluginCustomizeProps & {
+ data: TimeseriesDataRecord[];
+ };
+
+export interface OlChartMapProps extends CartodiagramPluginProps {
+ mapId: string;
+ olMap: Map;
+}
+
+export interface BaseLayerConf {
+ title: string;
+ url: string;
+ type: string;
+ attribution?: string;
+}
+
+export interface WfsLayerConf extends BaseLayerConf {
+ type: 'WFS';
+ typeName: string;
+ version: string;
+ maxFeatures?: number;
+ style?: Style;
+}
+
+export interface XyzLayerConf extends BaseLayerConf {
+ type: 'XYZ';
+}
+
+export interface WmsLayerConf extends BaseLayerConf {
+ type: 'WMS';
+ version: string;
+ layersParam: string;
+}
+
+export type LayerConf = WmsLayerConf | WfsLayerConf | XyzLayerConf;
+
+export type EventHandlers = Record;
+
+export type SelectedChartConfig = {
+ viz_type: string;
+ params: {
+ [key: string]: any;
+ };
+};
+
+export type LocationConfigMapping = {
+ [key: string]: DataRecord[];
+};
+
+export type MapViewConfigs = {
+ mode: 'FIT_DATA' | 'CUSTOM';
+ zoom: number;
+ latitude: number;
+ longitude: number;
+ fixedZoom: number;
+ fixedLatitude: number;
+ fixedLongitude: number;
+};
+
+export type ZoomConfigs = ZoomConfigsFixed | ZoomConfigsLinear | ZoomConfigsExp;
+
+export type ChartSizeValues = {
+ [index: number]: { width: number; height: number };
+};
+
+export interface ZoomConfigsBase {
+ type: string;
+ configs: {
+ zoom: number;
+ width: number;
+ height: number;
+ slope?: number;
+ exponent?: number;
+ };
+ values: ChartSizeValues;
+}
+
+export interface ZoomConfigsFixed extends ZoomConfigsBase {
+ type: 'FIXED';
+}
+
+export interface ZoomConfigsLinear extends ZoomConfigsBase {
+ type: 'LINEAR';
+ configs: {
+ zoom: number;
+ width: number;
+ height: number;
+ slope: number;
+ exponent?: number;
+ };
+}
+
+export interface ZoomConfigsExp extends ZoomConfigsBase {
+ type: 'EXP';
+ configs: {
+ zoom: number;
+ width: number;
+ height: number;
+ slope?: number;
+ exponent: number;
+ };
+}
+
+export type ChartHtmlElement = {
+ htmlElement: HTMLDivElement;
+ coordinate: Coordinate;
+ width: number;
+ height: number;
+};
+
+export type ChartLayerOptions = {
+ chartSizeValues?: ChartSizeValues;
+ chartConfigs?: ChartConfig;
+ chartVizType: string;
+ onMouseOver?: (this: GlobalEventHandlers, ev: MouseEvent) => any | undefined;
+ onMouseOut?: (this: GlobalEventHandlers, ev: MouseEvent) => any | undefined;
+ [key: string]: any; // allow custom types like 'name'
+ // these properties are copied from OpenLayers
+ // TODO: consider extending the OpenLayers options type
+ className?: string | undefined;
+ opacity?: number | undefined;
+ visible?: boolean | undefined;
+ extent?: Extent | undefined;
+ zIndex?: number | undefined;
+ minResolution?: number | undefined;
+ maxResolution?: number | undefined;
+ minZoom?: number | undefined;
+ maxZoom?: number | undefined;
+ source?: Source | undefined;
+ map?: Map | null | undefined;
+ render?: RenderFunction | undefined;
+ properties?: { [x: string]: any } | undefined;
+};
+
+export type CartodiagramPluginConstructorOpts = {
+ defaultLayers?: LayerConf[];
+};
+
+export type ChartWrapperProps = {
+ vizType: string;
+ theme: SupersetTheme;
+ width: number;
+ height: number;
+ chartConfig: ChartConfigFeature;
+};
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/chartUtil.tsx b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/chartUtil.tsx
new file mode 100644
index 000000000..e0b4932f3
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/chartUtil.tsx
@@ -0,0 +1,86 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { SupersetTheme } from '@superset-ui/core';
+import { ChartConfig, ChartConfigFeature } from '../types';
+import ChartWrapper from '../components/ChartWrapper';
+
+/**
+ * Create a chart component for a location.
+ *
+ * @param chartVizType The superset visualization type
+ * @param chartConfigs The chart configurations
+ * @param chartWidth The chart width
+ * @param chartHeight The chart height
+ * @param chartTheme The chart theme
+ * @returns The chart as React component
+ */
+export const createChartComponent = (
+ chartVizType: string,
+ chartConfig: ChartConfigFeature,
+ chartWidth: number,
+ chartHeight: number,
+ chartTheme: SupersetTheme,
+) => (
+
+);
+
+/**
+ * Simplifies a chart configuration by removing
+ * non-serializable properties.
+ *
+ * @param config The chart configuration to simplify.
+ * @returns The simplified chart configuration.
+ */
+export const simplifyConfig = (config: ChartConfig) => {
+ const simplifiedConfig: ChartConfig = {
+ type: config.type,
+ features: config.features.map(f => ({
+ type: f.type,
+ geometry: f.geometry,
+ properties: Object.keys(f.properties)
+ .filter(k => k !== 'refs')
+ .reduce((prev, cur) => ({ ...prev, [cur]: f.properties[cur] }), {}),
+ })),
+ };
+ return simplifiedConfig;
+};
+
+/**
+ * Check if two chart configurations are equal (deep equality).
+ *
+ * @param configA The first chart config for comparison.
+ * @param configB The second chart config for comparison.
+ * @returns True, if configurations are equal. False otherwise.
+ */
+export const isChartConfigEqual = (
+ configA: ChartConfig,
+ configB: ChartConfig,
+) => {
+ const simplifiedConfigA = simplifyConfig(configA);
+ const simplifiedConfigB = simplifyConfig(configB);
+ return (
+ JSON.stringify(simplifiedConfigA) === JSON.stringify(simplifiedConfigB)
+ );
+};
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/controlPanelUtil.tsx b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/controlPanelUtil.tsx
new file mode 100644
index 000000000..96aaf7ef3
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/controlPanelUtil.tsx
@@ -0,0 +1,128 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { t } from '@superset-ui/core';
+import { SelectValue } from 'antd/lib/select';
+import { ControlPanelConfig } from '@superset-ui/chart-controls';
+
+/**
+ * Get the layer configuration object from the control panel.
+ *
+ * @param controlPanel The control panel
+ * @returns The layer configuration object or undefined if not found
+ */
+export const getLayerConfig = (controlPanel: ControlPanelConfig) => {
+ let layerConfig: any;
+ controlPanel.controlPanelSections.forEach(section => {
+ if (!section) {
+ return;
+ }
+ const { controlSetRows } = section;
+ controlSetRows.forEach((row: any[]) => {
+ const configObject = row[0] as any;
+ if (configObject && configObject.name === 'layer_configs') {
+ layerConfig = configObject;
+ }
+ });
+ });
+
+ return layerConfig;
+};
+
+/**
+ * Mutates response of chart request into select options.
+ *
+ * If a currently selected value is not included in the response,
+ * it will be added explicitly, in order to prevent antd from creating
+ * a non-user-friendly select option.
+ *
+ * @param response Response json from resolved http request.
+ * @param value The currently selected value of the select input.
+ * @returns The list of options for the select input.
+ */
+export const selectedChartMutator = (
+ response: Record,
+ value: SelectValue | undefined,
+) => {
+ if (!response?.result) {
+ if (value && typeof value === 'string') {
+ return [
+ {
+ label: JSON.parse(value).slice_name,
+ value,
+ },
+ ];
+ }
+ return [];
+ }
+
+ const data: any[] = [];
+ if (value && typeof value === 'string') {
+ const parsedValue = JSON.parse(value);
+ let itemFound = false;
+ response.result.forEach((config: any) => {
+ const configString = JSON.stringify(config);
+ const sameId = config.id === parsedValue.id;
+ const isUpdated = configString !== value;
+ const label = config.slice_name;
+
+ if (sameId) {
+ itemFound = true;
+ }
+ if (!sameId || !isUpdated) {
+ data.push({
+ value: configString,
+ label,
+ });
+ } else {
+ data.push({
+ value: configString,
+ label: (
+
+ ({t('updated')})
+ {label}
+
+ ),
+ });
+ data.push({
+ value,
+ label,
+ });
+ }
+ });
+
+ if (!itemFound) {
+ data.push({
+ value,
+ label: parsedValue.slice_name,
+ });
+ }
+ } else {
+ response.result.forEach((config: any) => {
+ const configString = JSON.stringify(config);
+ const label = config.slice_name;
+
+ data.push({
+ value: configString,
+ label,
+ });
+ });
+ }
+
+ return data;
+};
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/geometryUtil.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/geometryUtil.ts
new file mode 100644
index 000000000..fee050694
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/geometryUtil.ts
@@ -0,0 +1,60 @@
+/**
+ * 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.
+ */
+
+/**
+ * Util for geometry related operations.
+ */
+
+import GeoJSON from 'ol/format/GeoJSON';
+import Feature from 'ol/Feature';
+import { Point as OlPoint } from 'ol/geom';
+import VectorSource from 'ol/source/Vector';
+import { Point as GeoJsonPoint } from 'geojson';
+
+/**
+ * Extracts the coordinate from a Point GeoJSON in the current map projection.
+ *
+ * @param geoJsonPoint The GeoJSON string for the point
+ *
+ * @returns The coordinate
+ */
+export const getProjectedCoordinateFromPointGeoJson = (
+ geoJsonPoint: GeoJsonPoint,
+) => {
+ const geom: OlPoint = new GeoJSON().readGeometry(geoJsonPoint, {
+ // TODO: adapt to map projection
+ featureProjection: 'EPSG:3857',
+ }) as OlPoint;
+ return geom.getCoordinates();
+};
+
+/**
+ * Computes the extent for an array of features.
+ *
+ * @param features An Array of OpenLayers features
+ * @returns The OpenLayers extent or undefined
+ */
+export const getExtentFromFeatures = (features: Feature[]) => {
+ if (features.length === 0) {
+ return undefined;
+ }
+ const source = new VectorSource();
+ source.addFeatures(features);
+ return source.getExtent();
+};
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/layerUtil.tsx b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/layerUtil.tsx
new file mode 100644
index 000000000..65e608bd7
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/layerUtil.tsx
@@ -0,0 +1,160 @@
+/**
+ * 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.
+ */
+
+/**
+ * Util for layer related operations.
+ */
+
+import OlParser from 'geostyler-openlayers-parser';
+import TileLayer from 'ol/layer/Tile';
+import TileWMS from 'ol/source/TileWMS';
+import { bbox as bboxStrategy } from 'ol/loadingstrategy';
+import VectorLayer from 'ol/layer/Vector';
+import VectorSource from 'ol/source/Vector';
+import XyzSource from 'ol/source/XYZ';
+import GeoJSON from 'ol/format/GeoJSON';
+import { WmsLayerConf, WfsLayerConf, LayerConf, XyzLayerConf } from '../types';
+import { isWfsLayerConf, isWmsLayerConf, isXyzLayerConf } from '../typeguards';
+import { isVersionBelow } from './serviceUtil';
+
+/**
+ * Create a WMS layer.
+ *
+ * @param wmsLayerConf The layer configuration
+ *
+ * @returns The created WMS layer
+ */
+export const createWmsLayer = (wmsLayerConf: WmsLayerConf) => {
+ const { url, layersParam, version, attribution } = wmsLayerConf;
+ return new TileLayer({
+ source: new TileWMS({
+ url,
+ params: {
+ LAYERS: layersParam,
+ VERSION: version,
+ },
+ attributions: attribution,
+ }),
+ });
+};
+
+/**
+ * Create a XYZ layer.
+ *
+ * @param xyzLayerConf The layer configuration
+ *
+ * @returns The created XYZ layer
+ */
+export const createXyzLayer = (xyzLayerConf: XyzLayerConf) => {
+ const { url, attribution } = xyzLayerConf;
+ return new TileLayer({
+ source: new XyzSource({
+ url,
+ attributions: attribution,
+ }),
+ });
+};
+
+/**
+ * Create a WFS layer.
+ *
+ * @param wfsLayerConf The layer configuration
+ *
+ * @returns The created WFS layer
+ */
+export const createWfsLayer = async (wfsLayerConf: WfsLayerConf) => {
+ const {
+ url,
+ typeName,
+ maxFeatures,
+ version = '1.1.0',
+ style,
+ attribution,
+ } = wfsLayerConf;
+
+ const wfsSource = new VectorSource({
+ format: new GeoJSON(),
+ attributions: attribution,
+ url: extent => {
+ const requestUrl = new URL(url);
+ const params = requestUrl.searchParams;
+ params.append('service', 'wfs');
+ params.append('request', 'GetFeature');
+ params.append('outputFormat', 'application/json');
+ // TODO: make CRS configurable or take it from Ol Map
+ params.append('srsName', 'EPSG:3857');
+ params.append('version', version);
+
+ let typeNameQuery = 'typeNames';
+ if (isVersionBelow(version, '2.0.0', 'WFS')) {
+ typeNameQuery = 'typeName';
+ }
+ params.append(typeNameQuery, typeName);
+
+ params.append('bbox', extent.join(','));
+ if (maxFeatures) {
+ let maxFeaturesQuery = 'count';
+ if (isVersionBelow(version, '2.0.0', 'WFS')) {
+ maxFeaturesQuery = 'maxFeatures';
+ }
+ params.append(maxFeaturesQuery, maxFeatures.toString());
+ }
+
+ return requestUrl.toString();
+ },
+ strategy: bboxStrategy,
+ });
+
+ let writeStyleResult;
+ if (style) {
+ const olParser = new OlParser();
+ writeStyleResult = await olParser.writeStyle(style);
+ if (writeStyleResult.errors) {
+ console.warn('Could not create ol-style', writeStyleResult.errors);
+ return undefined;
+ }
+ }
+
+ return new VectorLayer({
+ source: wfsSource,
+ // @ts-ignore
+ style: writeStyleResult?.output,
+ });
+};
+
+/**
+ * Create a layer instance with the provided configuration.
+ *
+ * @param layerConf The layer configuration
+ *
+ * @returns The created layer
+ */
+export const createLayer = async (layerConf: LayerConf) => {
+ let layer;
+ if (isWmsLayerConf(layerConf)) {
+ layer = createWmsLayer(layerConf);
+ } else if (isWfsLayerConf(layerConf)) {
+ layer = await createWfsLayer(layerConf);
+ } else if (isXyzLayerConf(layerConf)) {
+ layer = createXyzLayer(layerConf);
+ } else {
+ console.warn('Provided layerconfig is not recognized');
+ }
+ return layer;
+};
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/mapUtil.tsx b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/mapUtil.tsx
new file mode 100644
index 000000000..56af025f7
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/mapUtil.tsx
@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Util for map related operations.
+ */
+import { Map } from 'ol';
+import GeoJSON from 'ol/format/GeoJSON';
+import { ChartConfig } from '../types';
+import { getExtentFromFeatures } from './geometryUtil';
+
+// default map extent of world if no features are found
+// TODO: move to generic config file or plugin configuration
+// TODO: adapt to CRS other than Web Mercator
+const defaultExtent = [-16000000, -7279000, 20500000, 11000000];
+
+/**
+ * Fits map to the spatial extent of provided charts.
+ *
+ * @param olMap The OpenLayers map
+ * @param chartConfigs The chart configuration
+ */
+export const fitMapToCharts = (olMap: Map, chartConfigs: ChartConfig) => {
+ const view = olMap.getView();
+ const features = new GeoJSON().readFeatures(chartConfigs, {
+ // TODO: adapt to map projection
+ featureProjection: 'EPSG:3857',
+ });
+
+ const extent = getExtentFromFeatures(features) || defaultExtent;
+
+ view.fit(extent, {
+ // tested for a desktop size monitor
+ size: [250, 250],
+ });
+};
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/serviceUtil.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/serviceUtil.ts
new file mode 100644
index 000000000..b4d79485d
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/serviceUtil.ts
@@ -0,0 +1,59 @@
+/**
+ * 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.
+ */
+
+/**
+ * Get the available versions of WFS and WMS.
+ *
+ * @returns the versions
+ */
+export const getServiceVersions = () => ({
+ WMS: ['1.3.0', '1.1.1'],
+ WFS: ['2.0.2', '2.0.0', '1.1.0'],
+});
+
+/**
+ * Checks if a given version is below the comparer version.
+ *
+ * @param version The version to check.
+ * @param below The version to compare to.
+ * @param serviceType The service type.
+ * @returns True, if the version is below comparer version. False, otherwise.
+ */
+export const isVersionBelow = (
+ version: string,
+ below: string,
+ serviceType: 'WFS' | 'WMS',
+) => {
+ const versions = getServiceVersions()[serviceType];
+ // versions is ordered from newest to oldest, so we invert the order
+ // to improve the readability of this function.
+ versions.reverse();
+ const versionIdx = versions.indexOf(version);
+ if (versionIdx === -1) {
+ // TODO: consider throwing an error instead
+ return false;
+ }
+ const belowIdx = versions.indexOf(below);
+ if (belowIdx === -1) {
+ // TODO: consider throwing an error instead
+ return false;
+ }
+
+ return versionIdx < belowIdx;
+};
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/transformPropsUtil.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/transformPropsUtil.ts
new file mode 100644
index 000000000..fb4160057
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/transformPropsUtil.ts
@@ -0,0 +1,340 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import {
+ ChartProps,
+ convertKeysToCamelCase,
+ DataRecord,
+} from '@superset-ui/core';
+import { isObject } from 'lodash';
+import {
+ LocationConfigMapping,
+ SelectedChartConfig,
+ ChartConfig,
+ ChartConfigFeature,
+} from '../types';
+
+const COLUMN_SEPARATOR = ', ';
+
+/**
+ * Get the indices of columns where the title is a geojson.
+ *
+ * @param columns List of column names.
+ * @returns List of indices containing geojsonColumns.
+ */
+export const getGeojsonColumns = (columns: string[]) =>
+ columns.reduce((prev, current, idx) => {
+ let parsedColName;
+ try {
+ parsedColName = JSON.parse(current);
+ } catch {
+ parsedColName = undefined;
+ }
+ if (!parsedColName || !isObject(parsedColName)) {
+ return [...prev];
+ }
+ if (!('type' in parsedColName) || !('coordinates' in parsedColName)) {
+ return [...prev];
+ }
+ return [...prev, idx];
+ }, []);
+
+/**
+ * Create a column name ignoring provided indices.
+ *
+ * @param columns List of column names.
+ * @param ignoreIdx List of indices to ignore.
+ * @returns Column name.
+ */
+export const createColumnName = (columns: string[], ignoreIdx: number[]) =>
+ columns.filter((l, idx) => !ignoreIdx.includes(idx)).join(COLUMN_SEPARATOR);
+
+/**
+ * Group data by location for data providing a generic
+ * x-axis.
+ *
+ * @param data The data to group.
+ * @param params The data params.
+ * @returns Data grouped by location.
+ */
+export const groupByLocationGenericX = (
+ data: DataRecord[],
+ params: SelectedChartConfig['params'],
+ queryData: any,
+) => {
+ const locations: LocationConfigMapping = {};
+ if (!data) {
+ return locations;
+ }
+ data.forEach(d => {
+ Object.keys(d)
+ .filter(k => k !== params.x_axis)
+ .forEach(k => {
+ const labelMap: string[] = queryData.label_map?.[k];
+
+ if (!labelMap) {
+ console.log(
+ 'Cannot extract location from queryData. label_map not defined',
+ );
+ return;
+ }
+
+ const geojsonCols = getGeojsonColumns(labelMap);
+
+ if (geojsonCols.length > 1) {
+ // TODO what should we do, if there is more than one geom column?
+ console.log(
+ 'More than one geometry column detected. Using first found.',
+ );
+ }
+ const location = labelMap[geojsonCols[0]];
+ const filter = geojsonCols.length ? [geojsonCols[0]] : [];
+ const leftOverKey = createColumnName(labelMap, filter);
+
+ if (!Object.keys(locations).includes(location)) {
+ locations[location] = [];
+ }
+
+ let dataAtX = locations[location].find(
+ i => i[params.x_axis] === d[params.x_axis],
+ );
+
+ if (!dataAtX) {
+ dataAtX = {
+ // add the x_axis value explicitly, since we
+ // filtered it out for the rest of the computation.
+ [params.x_axis]: d[params.x_axis],
+ };
+ locations[location].push(dataAtX);
+ }
+ dataAtX[leftOverKey] = d[k];
+ });
+ });
+
+ return locations;
+};
+
+/**
+ * Group data by location.
+ *
+ * @param data The incoming dataset
+ * @param geomColumn The name of the geometry column
+ * @returns The grouped data
+ */
+export const groupByLocation = (data: DataRecord[], geomColumn: string) => {
+ const locations: LocationConfigMapping = {};
+
+ data.forEach(d => {
+ const loc = d[geomColumn] as string;
+ if (!loc) {
+ return;
+ }
+
+ if (!Object.keys(locations).includes(loc)) {
+ locations[loc] = [];
+ }
+
+ const newData = {
+ ...d,
+ };
+ delete newData[geomColumn];
+
+ locations[loc].push(newData);
+ });
+
+ return locations;
+};
+
+/**
+ * Strips the geom from colnames and coltypes.
+ *
+ * @param queryData The querydata.
+ * @param geomColumn Name of the geom column.
+ * @returns colnames and coltypes without the geom.
+ */
+export const stripGeomFromColnamesAndTypes = (
+ queryData: any,
+ geomColumn: string,
+) => {
+ const newColnames: string[] = [];
+ const newColtypes: number[] = [];
+ queryData.colnames?.forEach((colname: string, idx: number) => {
+ if (colname === geomColumn) {
+ return;
+ }
+
+ const parts = colname.split(COLUMN_SEPARATOR);
+ const geojsonColumns = getGeojsonColumns(parts);
+ const filter = geojsonColumns.length ? [geojsonColumns[0]] : [];
+
+ const newColname = createColumnName(parts, filter);
+ if (newColnames.includes(newColname)) {
+ return;
+ }
+ newColnames.push(newColname);
+ newColtypes.push(queryData.coltypes[idx]);
+ });
+
+ return {
+ colnames: newColnames,
+ coltypes: newColtypes,
+ };
+};
+
+/**
+ * Strips the geom from labelMap.
+ *
+ * @param queryData The querydata.
+ * @param geomColumn Name of the geom column.
+ * @returns labelMap without the geom column.
+ */
+export const stripGeomColumnFromLabelMap = (
+ labelMap: { [key: string]: string[] },
+ geomColumn: string,
+) => {
+ const newLabelMap: Record = {};
+ Object.entries(labelMap).forEach(([key, value]) => {
+ if (key === geomColumn) {
+ return;
+ }
+ const geojsonCols = getGeojsonColumns(value);
+ const filter = geojsonCols.length ? [geojsonCols[0]] : [];
+ const columnName = createColumnName(value, filter);
+ const restItems = value.filter((v, idx) => !geojsonCols.includes(idx));
+ newLabelMap[columnName] = restItems;
+ });
+ return newLabelMap;
+};
+
+/**
+ * Strip occurrences of the geom column from the query data.
+ *
+ * @param queryDataClone The query data
+ * @param geomColumn The name of the geom column
+ * @returns query data without geom column.
+ */
+export const stripGeomColumnFromQueryData = (
+ queryData: any,
+ geomColumn: string,
+) => {
+ const queryDataClone = {
+ ...structuredClone(queryData),
+ ...stripGeomFromColnamesAndTypes(queryData, geomColumn),
+ };
+ if (queryDataClone.label_map) {
+ queryDataClone.label_map = stripGeomColumnFromLabelMap(
+ queryData.label_map,
+ geomColumn,
+ );
+ }
+ return queryDataClone;
+};
+
+/**
+ * Create the chart configurations depending on the referenced Superset chart.
+ *
+ * @param selectedChart The configuration of the referenced Superset chart
+ * @param geomColumn The name of the geometry column
+ * @param chartProps The properties provided within this OL plugin
+ * @param chartTransformer The transformer function
+ * @returns The chart configurations
+ */
+export const getChartConfigs = (
+ selectedChart: SelectedChartConfig,
+ geomColumn: string,
+ chartProps: ChartProps,
+ chartTransformer: any,
+) => {
+ const chartFormDataSnake = selectedChart.params;
+ const chartFormData = convertKeysToCamelCase(chartFormDataSnake);
+
+ const baseConfig = {
+ ...chartProps,
+ // We overwrite width and height, which are not needed
+ // here, but leads to unnecessary updating of the UI.
+ width: null,
+ height: null,
+ formData: chartFormData,
+ rawFormData: chartFormDataSnake,
+ datasource: {},
+ };
+
+ const { queriesData } = chartProps;
+ const [queryData] = queriesData;
+
+ const data = queryData.data as DataRecord[];
+ let dataByLocation: LocationConfigMapping;
+
+ const chartConfigs: ChartConfig = {
+ type: 'FeatureCollection',
+ features: [],
+ };
+
+ if (!data) {
+ return chartConfigs;
+ }
+
+ if ('x_axis' in selectedChart.params) {
+ dataByLocation = groupByLocationGenericX(
+ data,
+ selectedChart.params,
+ queryData,
+ );
+ } else {
+ dataByLocation = groupByLocation(data, geomColumn);
+ }
+
+ const strippedQueryData = stripGeomColumnFromQueryData(queryData, geomColumn);
+
+ Object.keys(dataByLocation).forEach(location => {
+ const config = {
+ ...baseConfig,
+ queriesData: [
+ {
+ ...strippedQueryData,
+ data: dataByLocation[location],
+ },
+ ],
+ };
+ const transformedProps = chartTransformer(config);
+
+ const feature: ChartConfigFeature = {
+ type: 'Feature',
+ geometry: JSON.parse(location),
+ properties: {
+ ...transformedProps,
+ },
+ };
+
+ chartConfigs.features.push(feature);
+ });
+ return chartConfigs;
+};
+
+/**
+ * Return the same chart configuration with parsed values for of the stringified "params" object.
+ *
+ * @param selectedChart Incoming chart configuration
+ * @returns Chart configuration with parsed values for "params"
+ */
+export const parseSelectedChart = (selectedChart: string) => {
+ const selectedChartParsed = JSON.parse(selectedChart);
+ selectedChartParsed.params = JSON.parse(selectedChartParsed.params);
+ return selectedChartParsed;
+};
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Pie/data.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/zoomUtil.ts
similarity index 84%
rename from superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Pie/data.ts
rename to superset-frontend/plugins/plugin-chart-cartodiagram/src/util/zoomUtil.ts
index 6db3c5f69..c21fda764 100644
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/Pie/data.ts
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/src/util/zoomUtil.ts
@@ -1,4 +1,4 @@
-/*
+/**
* 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
@@ -17,14 +17,5 @@
* under the License.
*/
-/* eslint-disable sort-keys, no-magic-numbers */
-export default [
- {
- x: 'boy',
- y: 48133355,
- },
- {
- x: 'girl',
- y: 32546308,
- },
-];
+export const MAX_ZOOM_LEVEL = 28;
+export const MIN_ZOOM_LEVEL = 0;
diff --git a/superset-frontend/plugins/legacy-plugin-chart-sankey-loop/src/index.js b/superset-frontend/plugins/plugin-chart-cartodiagram/test/components/chartLayer.test.ts
similarity index 51%
rename from superset-frontend/plugins/legacy-plugin-chart-sankey-loop/src/index.js
rename to superset-frontend/plugins/plugin-chart-cartodiagram/test/components/chartLayer.test.ts
index 38922d5a7..050af2803 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-sankey-loop/src/index.js
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/test/components/chartLayer.test.ts
@@ -16,26 +16,33 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { t, ChartMetadata, ChartPlugin } from '@superset-ui/core';
-import transformProps from './transformProps';
-import thumbnail from './images/thumbnail.png';
-import controlPanel from './controlPanel';
-const metadata = new ChartMetadata({
- credits: ['https://github.com/ricklupton/d3-sankey-diagram'],
- description: '',
- name: t('Sankey Diagram with Loops'),
- thumbnail,
- useLegacyApi: true,
+import { ChartLayer } from '../../src/components/ChartLayer';
+import { ChartLayerOptions } from '../../src/types';
+
+describe('ChartLayer', () => {
+ it('creates div and loading mask', () => {
+ const options: ChartLayerOptions = {
+ chartVizType: 'pie',
+ };
+ const chartLayer = new ChartLayer(options);
+
+ expect(chartLayer.loadingMask).toBeDefined();
+ expect(chartLayer.div).toBeDefined();
+ });
+
+ it('can remove chart elements', () => {
+ const options: ChartLayerOptions = {
+ chartVizType: 'pie',
+ };
+ const chartLayer = new ChartLayer(options);
+ chartLayer.charts = [
+ {
+ htmlElement: document.createElement('div'),
+ },
+ ];
+
+ chartLayer.removeAllChartElements();
+ expect(chartLayer.charts).toEqual([]);
+ });
});
-
-export default class SankeyChartPlugin extends ChartPlugin {
- constructor() {
- super({
- loadChart: () => import('./ReactSankeyLoop'),
- metadata,
- transformProps,
- controlPanel,
- });
- }
-}
diff --git a/superset-frontend/plugins/legacy-preset-chart-nvd3/src/BoxPlot/index.js b/superset-frontend/plugins/plugin-chart-cartodiagram/test/index.test.ts
similarity index 61%
rename from superset-frontend/plugins/legacy-preset-chart-nvd3/src/BoxPlot/index.js
rename to superset-frontend/plugins/plugin-chart-cartodiagram/test/index.test.ts
index 1f5a5e99d..a43ce12ca 100644
--- a/superset-frontend/plugins/legacy-preset-chart-nvd3/src/BoxPlot/index.js
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/test/index.test.ts
@@ -16,24 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { t, ChartMetadata, ChartPlugin } from '@superset-ui/core';
-import transformProps from '../transformProps';
-import thumbnail from './images/thumbnail.png';
+import { CartodiagramPlugin } from '../src';
-const metadata = new ChartMetadata({
- credits: ['http://nvd3.org'],
- description: '',
- name: t('Box Plot'),
- thumbnail,
- useLegacyApi: true,
+/**
+ * The example tests in this file act as a starting point, and
+ * we encourage you to build more. These tests check that the
+ * plugin loads properly, and focus on `transformProps`
+ * to ake sure that data, controls, and props are all
+ * treated correctly (e.g. formData from plugin controls
+ * properly transform the data and/or any resulting props).
+ */
+describe('CartodiagramPlugin', () => {
+ it('exists', () => {
+ expect(CartodiagramPlugin).toBeDefined();
+ });
});
-
-export default class BoxPlotChartPlugin extends ChartPlugin {
- constructor() {
- super({
- loadChart: () => import('../ReactNVD3'),
- metadata,
- transformProps,
- });
- }
-}
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/test/plugin/buildQuery.test.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/test/plugin/buildQuery.test.ts
new file mode 100644
index 000000000..7b0da000e
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/test/plugin/buildQuery.test.ts
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { getChartBuildQueryRegistry } from '@superset-ui/core';
+import buildQuery from '../../src/plugin/buildQuery';
+
+describe('CartodiagramPlugin buildQuery', () => {
+ const selectedChartParams = {
+ extra_form_data: {},
+ groupby: [],
+ };
+
+ const selectedChart = {
+ viz_type: 'pie',
+ params: JSON.stringify(selectedChartParams),
+ };
+
+ const formData = {
+ datasource: '5__table',
+ granularity_sqla: 'ds',
+ series: 'foo',
+ viz_type: 'my_chart',
+ selected_chart: JSON.stringify(selectedChart),
+ geom_column: 'geom',
+ };
+
+ let chartQueryBuilderMock: jest.MockedFunction;
+ beforeEach(() => {
+ chartQueryBuilderMock = jest.fn();
+
+ const registry = getChartBuildQueryRegistry();
+ registry.registerValue('pie', chartQueryBuilderMock);
+ });
+
+ afterEach(() => {
+ // remove registered buildQuery
+ const registry = getChartBuildQueryRegistry();
+ registry.clear();
+ });
+
+ it('should call the buildQuery function of the referenced chart', () => {
+ buildQuery(formData);
+ expect(chartQueryBuilderMock.mock.calls).toHaveLength(1);
+ });
+
+ it('should build groupby with geom in form data', () => {
+ const expectedParams = { ...selectedChartParams, groupby: ['geom'] };
+
+ buildQuery(formData);
+ expect(chartQueryBuilderMock.mock.calls[0][0]).toEqual(expectedParams);
+ });
+});
diff --git a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/DistBar/NVD3DistBar.stories.tsx b/superset-frontend/plugins/plugin-chart-cartodiagram/test/plugin/index.test.ts
similarity index 71%
rename from superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/DistBar/NVD3DistBar.stories.tsx
rename to superset-frontend/plugins/plugin-chart-cartodiagram/test/plugin/index.test.ts
index 5b9ef5012..04563b081 100644
--- a/superset-frontend/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-nvd3/DistBar/NVD3DistBar.stories.tsx
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/test/plugin/index.test.ts
@@ -1,4 +1,4 @@
-/*
+/**
* 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
@@ -17,13 +17,10 @@
* under the License.
*/
-import { DistBarChartPlugin } from '@superset-ui/legacy-preset-chart-nvd3';
+import CartodiagramPlugin from '../../src/CartodiagramPlugin';
-new DistBarChartPlugin().configure({ key: 'dist-bar' }).register();
-
-export default {
- title: 'Legacy Chart Plugins/legacy-preset-chart-nvd3/DistBar',
-};
-
-export { basic } from './stories/basic';
-export { manyBars } from './stories/manyBars';
+describe('CartodiagramPlugin', () => {
+ it('exists', () => {
+ expect(CartodiagramPlugin).toBeDefined();
+ });
+});
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/test/plugin/transformProps.test.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/test/plugin/transformProps.test.ts
new file mode 100644
index 000000000..98cfc4977
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/test/plugin/transformProps.test.ts
@@ -0,0 +1,150 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import {
+ ChartProps,
+ getChartTransformPropsRegistry,
+ supersetTheme,
+} from '@superset-ui/core';
+import { LayerConf, MapViewConfigs, ZoomConfigs } from '../../src/types';
+import transformProps from '../../src/plugin/transformProps';
+import {
+ groupedTimeseriesChartData,
+ groupedTimeseriesLabelMap,
+} from '../testData';
+
+describe('CartodiagramPlugin transformProps', () => {
+ const chartSize: ZoomConfigs = {
+ type: 'FIXED',
+ configs: {
+ height: 10,
+ width: 10,
+ zoom: 1,
+ },
+ values: {
+ 1: {
+ height: 10,
+ width: 10,
+ },
+ },
+ };
+ const layerConfigs: LayerConf[] = [
+ {
+ type: 'XYZ',
+ title: 'foo',
+ url: 'example.com',
+ },
+ ];
+ const mapView: MapViewConfigs = {
+ mode: 'FIT_DATA',
+ zoom: 1,
+ latitude: 0,
+ longitude: 0,
+ fixedZoom: 1,
+ fixedLatitude: 0,
+ fixedLongitude: 0,
+ };
+
+ // only minimal subset of actual params
+ const selectedChartParams = {
+ groupby: ['bar'],
+ x_axis: 'mydate',
+ };
+
+ const selectedChart = {
+ id: 1,
+ viz_type: 'pie',
+ slice_name: 'foo',
+ params: JSON.stringify(selectedChartParams),
+ };
+
+ const formData = {
+ viz_type: 'cartodiagram',
+ geomColumn: 'geom',
+ selectedChart: JSON.stringify(selectedChart),
+ chartSize,
+ layerConfigs,
+ mapView,
+ chartBackgroundColor: '#000000',
+ chartBackgroundBorderRadius: 5,
+ };
+
+ const chartProps = new ChartProps({
+ formData,
+ width: 800,
+ height: 600,
+ queriesData: [
+ {
+ data: groupedTimeseriesChartData,
+ label_map: groupedTimeseriesLabelMap,
+ },
+ ],
+ theme: supersetTheme,
+ });
+
+ let chartTransformPropsPieMock: jest.MockedFunction;
+ let chartTransformPropsTimeseriesMock: jest.MockedFunction;
+ beforeEach(() => {
+ chartTransformPropsPieMock = jest.fn();
+ chartTransformPropsTimeseriesMock = jest.fn();
+ const registry = getChartTransformPropsRegistry();
+ registry.registerValue('pie', chartTransformPropsPieMock);
+ registry.registerValue(
+ 'echarts_timeseries',
+ chartTransformPropsTimeseriesMock,
+ );
+ });
+
+ afterEach(() => {
+ // remove registered transformProps
+ const registry = getChartTransformPropsRegistry();
+ registry.clear();
+ });
+
+ it('should call the transform props function of the referenced chart', () => {
+ transformProps(chartProps);
+ expect(chartTransformPropsPieMock).toHaveBeenCalled();
+ expect(chartTransformPropsTimeseriesMock).not.toHaveBeenCalled();
+ });
+
+ it('should transform chart props for viz', () => {
+ const transformedProps = transformProps(chartProps);
+ expect(transformedProps).toEqual(
+ expect.objectContaining({
+ width: chartProps.width,
+ height: chartProps.height,
+ geomColumn: formData.geomColumn,
+ selectedChart: expect.objectContaining({
+ viz_type: selectedChart.viz_type,
+ params: selectedChartParams,
+ }),
+ // The actual test for the created chartConfigs
+ // will be done in transformPropsUtil.test.ts
+ chartConfigs: expect.objectContaining({
+ type: 'FeatureCollection',
+ }),
+ chartVizType: selectedChart.viz_type,
+ chartSize,
+ layerConfigs,
+ mapView,
+ chartBackgroundColor: formData.chartBackgroundColor,
+ chartBackgroundBorderRadius: formData.chartBackgroundBorderRadius,
+ }),
+ );
+ });
+});
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/test/testData.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/test/testData.ts
new file mode 100644
index 000000000..5b5a3a0e7
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/test/testData.ts
@@ -0,0 +1,113 @@
+/**
+ * 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.
+ */
+
+const coord1 = '[1,2]';
+const coord2 = '[3,4]';
+export const geom1 = `{"type":"Point","coordinates":${coord1}}`;
+export const geom2 = `{"type":"Point","coordinates":${coord2}}`;
+
+export const nonTimeSeriesChartData: any = [
+ {
+ geom: geom1,
+ my_value: 'apple',
+ my_count: 347,
+ },
+ {
+ geom: geom1,
+ my_value: 'apple',
+ my_count: 360,
+ },
+ {
+ geom: geom1,
+ my_value: 'lemon',
+ my_count: 335,
+ },
+ {
+ geom: geom1,
+ my_value: 'lemon',
+ my_count: 333,
+ },
+ {
+ geom: geom1,
+ my_value: 'lemon',
+ my_count: 353,
+ },
+ {
+ geom: geom1,
+ my_value: 'lemon',
+ my_count: 359,
+ },
+ {
+ geom: geom2,
+ my_value: 'lemon',
+ my_count: 347,
+ },
+ {
+ geom: geom2,
+ my_value: 'apple',
+ my_count: 335,
+ },
+ {
+ geom: geom2,
+ my_value: 'apple',
+ my_count: 356,
+ },
+ {
+ geom: geom2,
+ my_value: 'banana',
+ my_count: 218,
+ },
+];
+
+export const timeseriesChartData = [
+ {
+ [geom1]: 347,
+ [geom2]: 360,
+ mydate: 1564275000000,
+ },
+ {
+ [geom1]: 353,
+ [geom2]: 328,
+ mydate: 1564272000000,
+ },
+];
+
+export const groupedTimeseriesChartData = [
+ {
+ [`${geom1}, apple`]: 347,
+ [`${geom2}, apple`]: 360,
+ [`${geom1}, lemon`]: 352,
+ [`${geom2}, lemon`]: 364,
+ mydate: 1564275000000,
+ },
+ {
+ [`${geom1}, apple`]: 353,
+ [`${geom2}, apple`]: 328,
+ [`${geom1}, lemon`]: 346,
+ [`${geom2}, lemon`]: 333,
+ mydate: 1564272000000,
+ },
+];
+
+export const groupedTimeseriesLabelMap = {
+ [`${geom1}, apple`]: [geom1, 'apple'],
+ [`${geom2}, apple`]: [geom2, 'apple'],
+ [`${geom1}, lemon`]: [geom1, 'lemon'],
+ [`${geom2}, lemon`]: [geom2, 'lemon'],
+};
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/test/tsconfig.json b/superset-frontend/plugins/plugin-chart-cartodiagram/test/tsconfig.json
new file mode 100644
index 000000000..07351e503
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/test/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "composite": false,
+ "emitDeclarationOnly": false,
+ "noEmit": true,
+ "rootDir": "."
+ },
+ "extends": "../../../tsconfig.json",
+ "include": [
+ "**/*",
+ "../types/**/*",
+ "../../../types/**/*"
+ ],
+ "references": [
+ {
+ "path": "../../../packages/superset-ui-chart-controls"
+ },
+ {
+ "path": "../../../packages/superset-ui-core"
+ },
+ ]
+}
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/chartUtil.test.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/chartUtil.test.ts
new file mode 100644
index 000000000..891ac9541
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/chartUtil.test.ts
@@ -0,0 +1,77 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { ChartConfig } from '../../src/types';
+import { isChartConfigEqual, simplifyConfig } from '../../src/util/chartUtil';
+
+describe('chartUtil', () => {
+ const configA: ChartConfig = {
+ type: 'FeatureCollection',
+ features: [
+ {
+ type: 'Feature',
+ geometry: {
+ type: 'Point',
+ coordinates: [],
+ },
+ properties: {
+ refs: 'foo',
+ },
+ },
+ ],
+ };
+
+ const configB: ChartConfig = {
+ type: 'FeatureCollection',
+ features: [
+ {
+ type: 'Feature',
+ geometry: {
+ type: 'Point',
+ coordinates: [],
+ },
+ properties: {
+ refs: 'foo',
+ foo: 'bar',
+ },
+ },
+ ],
+ };
+
+ describe('simplifyConfig', () => {
+ it('removes the refs property from a feature', () => {
+ const simplifiedConfig = simplifyConfig(configA);
+ const propKeys = Object.keys(simplifiedConfig.features[0].properties);
+
+ expect(propKeys).toHaveLength(0);
+ });
+ });
+
+ describe('isChartConfigEqual', () => {
+ it('returns true, if configurations are equal', () => {
+ const isEqual = isChartConfigEqual(configA, structuredClone(configA));
+ expect(isEqual).toBe(true);
+ });
+
+ it('returns false if configurations are not equal', () => {
+ const isEqual = isChartConfigEqual(configA, configB);
+ expect(isEqual).toBe(false);
+ });
+ });
+});
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/controlPanelUtil.test.tsx b/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/controlPanelUtil.test.tsx
new file mode 100644
index 000000000..88e1e3b9e
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/controlPanelUtil.test.tsx
@@ -0,0 +1,212 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import {
+ ControlPanelConfig,
+ CustomControlItem,
+} from '@superset-ui/chart-controls';
+import {
+ getLayerConfig,
+ selectedChartMutator,
+} from '../../src/util/controlPanelUtil';
+
+describe('controlPanelUtil', () => {
+ describe('getLayerConfig', () => {
+ it('returns the correct layer config', () => {
+ const layerConfigs: CustomControlItem = {
+ name: 'layer_configs',
+ config: {
+ type: 'dummy',
+ renderTrigger: true,
+ label: 'Layers',
+ default: [
+ {
+ type: 'XYZ',
+ url: 'http://example.com/',
+ title: 'dummy title',
+ attribution: 'dummy attribution',
+ },
+ ],
+ description: 'The configuration for the map layers',
+ },
+ };
+ const controlPanel: ControlPanelConfig = {
+ controlPanelSections: [
+ {
+ label: 'Configuration',
+ expanded: true,
+ controlSetRows: [],
+ },
+ {
+ label: 'Map Options',
+ expanded: true,
+ controlSetRows: [
+ [
+ {
+ name: 'map_view',
+ config: {
+ type: 'dummy',
+ },
+ },
+ ],
+ [layerConfigs],
+ ],
+ },
+ {
+ label: 'Chart Options',
+ expanded: true,
+ controlSetRows: [],
+ },
+ ],
+ };
+ const extractedLayerConfigs = getLayerConfig(controlPanel);
+
+ expect(extractedLayerConfigs).toEqual(layerConfigs);
+ });
+ });
+
+ describe('selectedChartMutator', () => {
+ it('returns empty array for empty inputs', () => {
+ const response = {};
+ const value = undefined;
+ const result = selectedChartMutator(response, value);
+ expect(result).toEqual([]);
+ });
+
+ it('returns parsed value if response is empty', () => {
+ const response = {};
+
+ const sliceName = 'foobar';
+ const value = JSON.stringify({
+ id: 278,
+ params: '',
+ slice_name: sliceName,
+ viz_type: 'pie',
+ });
+
+ const result = selectedChartMutator(response, value);
+
+ expect(result[0].label).toEqual(sliceName);
+ });
+
+ it('returns response options if no value is chosen', () => {
+ const sliceName1 = 'foo';
+ const sliceName2 = 'bar';
+ const response = {
+ result: [
+ {
+ id: 1,
+ params: '{}',
+ slice_name: sliceName1,
+ viz_type: 'viz1',
+ },
+ {
+ id: 2,
+ params: '{}',
+ slice_name: sliceName2,
+ viz_type: 'viz2',
+ },
+ ],
+ };
+ const value = undefined;
+
+ const result = selectedChartMutator(response, value);
+ expect(result[0].label).toEqual(sliceName1);
+ expect(result[1].label).toEqual(sliceName2);
+ });
+
+ it('returns correct result if id of chosen config does not exist in response', () => {
+ const response = {
+ result: [
+ {
+ id: 1,
+ params: '{}',
+ slice_name: 'foo',
+ viz_type: 'viz1',
+ },
+ {
+ id: 2,
+ params: '{}',
+ slice_name: 'bar',
+ viz_type: 'viz2',
+ },
+ ],
+ };
+
+ const value = JSON.stringify({
+ id: 3,
+ params: '{}',
+ slice_name: 'my-slice',
+ viz_type: 'pie',
+ });
+
+ const result = selectedChartMutator(response, value);
+
+ // collect all ids in a set to prevent double entries
+ const ids = new Set();
+ result.forEach((item: any) => {
+ const config = JSON.parse(item.value);
+ const { id } = config;
+ ids.add(id);
+ });
+
+ const threeDifferentIds = ids.size === 3;
+
+ expect(threeDifferentIds).toEqual(true);
+ });
+
+ it('returns correct result if id of chosen config already exists', () => {
+ const response = {
+ result: [
+ {
+ id: 1,
+ params: '{}',
+ slice_name: 'foo',
+ viz_type: 'viz1',
+ },
+ {
+ id: 2,
+ params: '{}',
+ slice_name: 'bar',
+ viz_type: 'viz2',
+ },
+ ],
+ };
+
+ const value = JSON.stringify({
+ id: 1,
+ params: '{}',
+ slice_name: 'my-slice',
+ viz_type: 'pie',
+ });
+
+ const result = selectedChartMutator(response, value);
+
+ const itemsIdWithId1 = result.filter((item: any) => {
+ const config = JSON.parse(item.value);
+ const { id } = config;
+ return id === 1;
+ });
+ expect(itemsIdWithId1.length).toEqual(2);
+
+ const labelsEqual = itemsIdWithId1[0].label === itemsIdWithId1[1].label;
+ expect(labelsEqual).toEqual(false);
+ });
+ });
+});
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/geometryUtil.test.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/geometryUtil.test.ts
new file mode 100644
index 000000000..4f070f4b7
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/geometryUtil.test.ts
@@ -0,0 +1,102 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import GeoJSON from 'ol/format/GeoJSON';
+import { Point } from 'geojson';
+import {
+ getExtentFromFeatures,
+ getProjectedCoordinateFromPointGeoJson,
+} from '../../src/util/geometryUtil';
+import { ChartConfig } from '../../src/types';
+
+describe('geometryUtil', () => {
+ describe('getProjectedCoordinateFromPointGeoJson', () => {
+ it('returns a plausible result', () => {
+ const pointGeoJson: Point = {
+ type: 'Point',
+ coordinates: [6.6555, 49.74283],
+ };
+ const result = getProjectedCoordinateFromPointGeoJson(pointGeoJson);
+
+ expect(result.length).toEqual(2);
+
+ const valuesAreNumbers =
+ !Number.isNaN(result[0]) && !Number.isNaN(result[1]);
+ expect(valuesAreNumbers).toEqual(true);
+ });
+ });
+
+ describe('getExtentFromFeatures', () => {
+ it('computes correct extent with valid input', () => {
+ const expectedExtent = [1, 2, 3, 4];
+
+ const chartConfig: ChartConfig = {
+ type: 'FeatureCollection',
+ features: [
+ {
+ type: 'Feature',
+ geometry: {
+ type: 'Point',
+ coordinates: [expectedExtent[0], expectedExtent[1]],
+ },
+ properties: {
+ setDataMask: '',
+ labelMap: '',
+ labelMapB: '',
+ groupby: '',
+ selectedValues: '',
+ formData: '',
+ groupbyB: '',
+ seriesBreakdown: '',
+ legendData: '',
+ echartOptions: '',
+ },
+ },
+ {
+ type: 'Feature',
+ geometry: {
+ type: 'Point',
+ coordinates: [expectedExtent[2], expectedExtent[3]],
+ },
+ properties: {
+ setDataMask: '',
+ labelMap: '',
+ labelMapB: '',
+ groupby: '',
+ selectedValues: '',
+ formData: '',
+ groupbyB: '',
+ seriesBreakdown: '',
+ legendData: '',
+ echartOptions: '',
+ },
+ },
+ ],
+ };
+
+ const features = new GeoJSON().readFeatures(chartConfig);
+ const extent = getExtentFromFeatures(features);
+ expect(extent).toEqual(expectedExtent);
+ });
+
+ it('returns undefined on invalid input', () => {
+ const emptyExtent = getExtentFromFeatures([]);
+ expect(emptyExtent).toBeUndefined();
+ });
+ });
+});
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/layerUtil.test.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/layerUtil.test.ts
new file mode 100644
index 000000000..d2912105e
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/layerUtil.test.ts
@@ -0,0 +1,96 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { WfsLayerConf } from '../../src/types';
+import {
+ createLayer,
+ createWfsLayer,
+ createWmsLayer,
+ createXyzLayer,
+} from '../../src/util/layerUtil';
+
+describe('layerUtil', () => {
+ describe('createWmsLayer', () => {
+ it('exists', () => {
+ // function is trivial
+ expect(createWmsLayer).toBeDefined();
+ });
+ });
+
+ describe('createWfsLayer', () => {
+ it('properly applies style', async () => {
+ const colorToExpect = '#123456';
+
+ const wfsLayerConf: WfsLayerConf = {
+ title: 'osm:osm-fuel',
+ url: 'https://ows-demo.terrestris.de/geoserver/osm/wfs',
+ type: 'WFS',
+ version: '2.0.2',
+ typeName: 'osm:osm-fuel',
+ style: {
+ name: 'Default Style',
+ rules: [
+ {
+ name: 'Default Rule',
+ symbolizers: [
+ {
+ kind: 'Line',
+ color: '#000000',
+ width: 2,
+ },
+ {
+ kind: 'Mark',
+ wellKnownName: 'circle',
+ color: colorToExpect,
+ },
+ {
+ kind: 'Fill',
+ color: '#000000',
+ },
+ ],
+ },
+ ],
+ },
+ };
+
+ const wfsLayer = await createWfsLayer(wfsLayerConf);
+
+ const style = wfsLayer!.getStyle();
+ // @ts-ignore
+ expect(style!.length).toEqual(3);
+
+ // @ts-ignore upgrade `ol` package for better type of StyleLike type.
+ const colorAtLayer = style![1].getImage().getFill().getColor();
+ expect(colorToExpect).toEqual(colorAtLayer);
+ });
+ });
+
+ describe('createXyzLayer', () => {
+ it('exists', () => {
+ // function is trivial
+ expect(createXyzLayer).toBeDefined();
+ });
+ });
+
+ describe('createLayer', () => {
+ it('exists', () => {
+ expect(createLayer).toBeDefined();
+ });
+ });
+});
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/mapUtil.test.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/mapUtil.test.ts
new file mode 100644
index 000000000..0447b03af
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/mapUtil.test.ts
@@ -0,0 +1,116 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import Map from 'ol/Map.js';
+import OSM from 'ol/source/OSM.js';
+import TileLayer from 'ol/layer/Tile.js';
+import View from 'ol/View.js';
+import { ChartConfig } from '../../src/types';
+import { fitMapToCharts } from '../../src/util/mapUtil';
+
+describe('mapUtil', () => {
+ describe('fitMapToCharts', () => {
+ it('changes the center of the map', () => {
+ const chartConfig: ChartConfig = {
+ type: 'FeatureCollection',
+ features: [
+ {
+ type: 'Feature',
+ geometry: {
+ type: 'Point',
+ coordinates: [8.793, 53.04117],
+ },
+ properties: {
+ setDataMask: '',
+ labelMap: '',
+ labelMapB: '',
+ groupby: '',
+ selectedValues: '',
+ formData: '',
+ groupbyB: '',
+ seriesBreakdown: '',
+ legendData: '',
+ echartOptions: '',
+ },
+ },
+ {
+ type: 'Feature',
+ geometry: {
+ type: 'Point',
+ coordinates: [10.61833, 51.8],
+ },
+ properties: {
+ setDataMask: '',
+ labelMap: '',
+ labelMapB: '',
+ groupby: '',
+ selectedValues: '',
+ formData: '',
+ groupbyB: '',
+ seriesBreakdown: '',
+ legendData: '',
+ echartOptions: '',
+ },
+ },
+ {
+ type: 'Feature',
+ geometry: {
+ type: 'Point',
+ coordinates: [6.86883, 50.35667],
+ },
+ properties: {
+ setDataMask: '',
+ labelMap: '',
+ labelMapB: '',
+ groupby: '',
+ selectedValues: '',
+ formData: '',
+ groupbyB: '',
+ seriesBreakdown: '',
+ legendData: '',
+ echartOptions: '',
+ },
+ },
+ ],
+ };
+
+ const initialCenter = [0, 0];
+
+ const olMap = new Map({
+ layers: [
+ new TileLayer({
+ source: new OSM(),
+ }),
+ ],
+ target: 'map',
+ view: new View({
+ center: initialCenter,
+ zoom: 2,
+ }),
+ });
+
+ // should set center
+ fitMapToCharts(olMap, chartConfig);
+
+ const updatedCenter = olMap.getView().getCenter();
+
+ expect(initialCenter).not.toEqual(updatedCenter);
+ });
+ });
+});
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/serviceUtil.test.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/serviceUtil.test.ts
new file mode 100644
index 000000000..0728839b9
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/serviceUtil.test.ts
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { isVersionBelow } from '../../src/util/serviceUtil';
+
+describe('serviceUtil', () => {
+ describe('isVersionBelow', () => {
+ describe('WMS', () => {
+ it('recognizes the higher version', () => {
+ const result = isVersionBelow('1.3.0', '1.1.0', 'WMS');
+ expect(result).toEqual(false);
+ });
+ it('recognizes the lower version', () => {
+ const result = isVersionBelow('1.1.1', '1.3.0', 'WMS');
+ expect(result).toEqual(true);
+ });
+ });
+
+ describe('WFS', () => {
+ it('recognizes the higher version', () => {
+ const result = isVersionBelow('2.0.2', '1.1.0', 'WFS');
+ expect(result).toEqual(false);
+ });
+ it('recognizes the lower version', () => {
+ const result = isVersionBelow('1.1.0', '2.0.2', 'WFS');
+ expect(result).toEqual(true);
+ });
+ });
+ });
+});
diff --git a/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/transformPropsUtil.test.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/transformPropsUtil.test.ts
new file mode 100644
index 000000000..6190990e0
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/test/util/transformPropsUtil.test.ts
@@ -0,0 +1,249 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import {
+ groupByLocation,
+ getChartConfigs,
+ parseSelectedChart,
+ getGeojsonColumns,
+ createColumnName,
+ groupByLocationGenericX,
+ stripGeomFromColnamesAndTypes,
+ stripGeomColumnFromLabelMap,
+} from '../../src/util/transformPropsUtil';
+import {
+ nonTimeSeriesChartData,
+ groupedTimeseriesChartData,
+ geom1,
+ geom2,
+ groupedTimeseriesLabelMap,
+} from '../testData';
+
+describe('transformPropsUtil', () => {
+ const groupedTimeseriesParams = {
+ x_axis: 'mydate',
+ };
+
+ const groupedTimeseriesQueryData = {
+ label_map: groupedTimeseriesLabelMap,
+ };
+
+ describe('getGeojsonColumns', () => {
+ it('gets the GeoJSON columns', () => {
+ const columns = ['foo', 'bar', geom1];
+ const result = getGeojsonColumns(columns);
+ expect(result).toHaveLength(1);
+ expect(result[0]).toEqual(2);
+ });
+
+ it('gets multiple GeoJSON columns', () => {
+ const columns = ['foo', geom2, 'bar', geom1];
+ const result = getGeojsonColumns(columns);
+ expect(result).toHaveLength(2);
+ expect(result[0]).toEqual(1);
+ expect(result[1]).toEqual(3);
+ });
+
+ it('returns empty array when no GeoJSON is included', () => {
+ const columns = ['foo', 'bar'];
+ const result = getGeojsonColumns(columns);
+ expect(result).toHaveLength(0);
+ });
+ });
+
+ describe('createColumnName', () => {
+ it('creates a columns name', () => {
+ const columns = ['foo', 'bar'];
+ const result = createColumnName(columns, []);
+ expect(result).toEqual('foo, bar');
+ });
+
+ it('ignores items provided by ignoreIdx', () => {
+ const columns = ['foo', 'bar', 'baz'];
+ const ignoreIdx = [1];
+ const result = createColumnName(columns, ignoreIdx);
+ expect(result).toEqual('foo, baz');
+ });
+ });
+
+ describe('groupByLocationGenericX', () => {
+ it('groups in the correct count of geometries', () => {
+ const result = groupByLocationGenericX(
+ groupedTimeseriesChartData,
+ groupedTimeseriesParams,
+ groupedTimeseriesQueryData,
+ );
+ const countOfGeometries = Object.keys(result).length;
+ expect(countOfGeometries).toEqual(2);
+ });
+
+ it('groups items by same geometry', () => {
+ const result = groupByLocationGenericX(
+ groupedTimeseriesChartData,
+ groupedTimeseriesParams,
+ groupedTimeseriesQueryData,
+ );
+ const allGeom1 = result[geom1].length === 2;
+ const allGeom2 = result[geom2].length === 2;
+ expect(allGeom1 && allGeom2).toBe(true);
+ });
+ });
+
+ describe('groupByLocation', () => {
+ it('groups in the correct count of geometries', () => {
+ const geometryColumn = 'geom';
+ const result = groupByLocation(nonTimeSeriesChartData, geometryColumn);
+ const countOfGeometries = Object.keys(result).length;
+ expect(countOfGeometries).toEqual(2);
+ });
+
+ it('groups items by same geometry', () => {
+ const geometryColumn = 'geom';
+ const result = groupByLocation(nonTimeSeriesChartData, geometryColumn);
+ const allGeom1 = result[geom1].length === 6;
+ const allGeom2 = result[geom2].length === 4;
+ expect(allGeom1 && allGeom2).toBe(true);
+ });
+ });
+
+ describe('stripGeomFromColnamesAndTypes', () => {
+ it('strips the geom from colnames with geom column', () => {
+ const queryData = {
+ colnames: ['foo', 'geom'],
+ coltypes: [0, 0],
+ };
+ const result = stripGeomFromColnamesAndTypes(queryData, 'geom');
+ expect(result).toEqual({
+ colnames: ['foo'],
+ coltypes: [0],
+ });
+ });
+
+ it('strips the geom from colnames with grouped columns', () => {
+ const queryData = {
+ colnames: ['foo', `bar, ${geom1}`],
+ coltypes: [0, 0],
+ };
+ const result = stripGeomFromColnamesAndTypes(queryData, 'geom');
+ expect(result).toEqual({
+ colnames: ['foo', 'bar'],
+ coltypes: [0, 0],
+ });
+ });
+
+ it('strips the geom from colnames with grouped columns without geom', () => {
+ const queryData = {
+ colnames: ['foo', `bar, baz`],
+ coltypes: [0, 0],
+ };
+ const result = stripGeomFromColnamesAndTypes(queryData, 'geom');
+ expect(result).toEqual({
+ colnames: ['foo', 'bar, baz'],
+ coltypes: [0, 0],
+ });
+ });
+ });
+
+ describe('stripGeomColumnFromLabelMap', () => {
+ it('strips the geom column from label_map', () => {
+ const labelMap = {
+ [`apple, ${geom1}`]: ['apple', geom1],
+ [`${geom2}, lemon`]: [geom2, 'lemon'],
+ geom: ['geom'],
+ };
+ const result = stripGeomColumnFromLabelMap(labelMap, 'geom');
+ expect(result).toEqual({
+ apple: ['apple'],
+ lemon: ['lemon'],
+ });
+ });
+ });
+
+ describe('getChartConfigs', () => {
+ let chartTransformer: jest.MockedFunction;
+ const geomColumn = 'geom';
+ const pieChartConfig = {
+ params: {},
+ viz_type: 'pie',
+ };
+ const chartProps: any = {
+ queriesData: [
+ {
+ data: nonTimeSeriesChartData,
+ },
+ ],
+ };
+ beforeEach(() => {
+ chartTransformer = jest.fn();
+ });
+
+ it('calls the transformProps function for every location', () => {
+ getChartConfigs(pieChartConfig, geomColumn, chartProps, chartTransformer);
+
+ expect(chartTransformer).toHaveBeenCalledTimes(2);
+ });
+ it('returns a geojson', () => {
+ const result = getChartConfigs(
+ pieChartConfig,
+ geomColumn,
+ chartProps,
+ chartTransformer,
+ );
+
+ expect(result).toEqual(
+ expect.objectContaining({
+ type: 'FeatureCollection',
+ features: expect.arrayContaining([
+ expect.objectContaining({
+ type: 'Feature',
+ }),
+ ]),
+ }),
+ );
+ });
+ it('returns a feature for each location', () => {
+ const result = getChartConfigs(
+ pieChartConfig,
+ geomColumn,
+ chartProps,
+ chartTransformer,
+ );
+ expect(result.features).toHaveLength(2);
+ expect(result.features[0].geometry).toEqual(JSON.parse(geom1));
+ expect(result.features[1].geometry).toEqual(JSON.parse(geom2));
+ });
+ });
+
+ describe('parseSelectedChart', () => {
+ it('parses the inline stringified JSON', () => {
+ const selectedChartObject = {
+ id: 278,
+ params:
+ '{"adhoc_filters":[],"applied_time_extras":{},"datasource":"24__table","viz_type":"pie","time_range":"No filter","groupby":["nuclide"],"metric":{"expressionType":"SIMPLE","column":{"advanced_data_type":null,"certification_details":null,"certified_by":null,"column_name":"nuclide","description":null,"expression":null,"filterable":true,"groupby":true,"id":772,"is_certified":false,"is_dttm":false,"python_date_format":null,"type":"TEXT","type_generic":1,"verbose_name":null,"warning_markdown":null},"aggregate":"COUNT","sqlExpression":null,"isNew":false,"datasourceWarning":false,"hasCustomLabel":false,"label":"COUNT(nuclide)","optionName":"metric_k6d9mt9zujc_7v9szd1i0pl"},"dashboards":[]}',
+ slice_name: 'pie',
+ viz_type: 'pie',
+ };
+
+ const selectedChartString = JSON.stringify(selectedChartObject);
+ const result = parseSelectedChart(selectedChartString);
+ const expectedParams = JSON.parse(selectedChartObject.params);
+
+ expect(result.params).toEqual(expectedParams);
+ });
+ });
+});
diff --git a/superset-frontend/plugins/legacy-plugin-chart-event-flow/tsconfig.json b/superset-frontend/plugins/plugin-chart-cartodiagram/tsconfig.json
similarity index 98%
rename from superset-frontend/plugins/legacy-plugin-chart-event-flow/tsconfig.json
rename to superset-frontend/plugins/plugin-chart-cartodiagram/tsconfig.json
index b6bfaa2d9..019b367ef 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-event-flow/tsconfig.json
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/tsconfig.json
@@ -20,6 +20,6 @@
},
{
"path": "../../packages/superset-ui-core"
- }
+ },
]
}
diff --git a/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/types/external.d.ts b/superset-frontend/plugins/plugin-chart-cartodiagram/types/external.d.ts
similarity index 84%
rename from superset-frontend/plugins/legacy-plugin-chart-event-flow/src/types/external.d.ts
rename to superset-frontend/plugins/plugin-chart-cartodiagram/types/external.d.ts
index a9b451b31..4bb0ad129 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-event-flow/src/types/external.d.ts
+++ b/superset-frontend/plugins/plugin-chart-cartodiagram/types/external.d.ts
@@ -17,6 +17,12 @@
* under the License.
*/
-declare module '*.png';
-declare module '*.jpg';
-declare module '@data-ui/event-flow';
+declare module '*.png' {
+ const value: any;
+ export default value;
+}
+
+declare module '*.gif' {
+ const value: any;
+ export default value;
+}
diff --git a/superset-frontend/plugins/plugin-chart-echarts/package.json b/superset-frontend/plugins/plugin-chart-echarts/package.json
index e67df3297..f84ecd0ed 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/package.json
+++ b/superset-frontend/plugins/plugin-chart-echarts/package.json
@@ -25,15 +25,15 @@
],
"dependencies": {
"d3-array": "^1.2.0",
- "echarts": "^5.4.1",
"lodash": "^4.17.21",
"dayjs": "^1.11.13"
},
"peerDependencies": {
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
+ "echarts": "*",
"memoize-one": "*",
- "react": "^16.13.1"
+ "react": "^17.0.2"
},
"publishConfig": {
"access": "public"
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/transformProps.ts
index 9ba045802..b434fbbc5 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/transformProps.ts
@@ -165,7 +165,8 @@ export default function transformProps(chartProps: ChartProps) {
percentDifferenceNum = (bigNumber - prevNumber) / Math.abs(prevNumber);
}
- const compType = compTitles[formData.timeComparison];
+ const compType =
+ compTitles[formData.timeComparison as keyof typeof compTitles];
bigNumber = numberFormatter(bigNumber);
prevNumber = numberFormatter(prevNumber);
valueDifference = numberFormatter(valueDifference);
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/utils.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/utils.ts
index a12f0c975..4fb45ab88 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/utils.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberPeriodOverPeriod/utils.ts
@@ -35,7 +35,7 @@ const getFontSizeMapping = (
proportionValues: number[],
actualSizes: number[],
) =>
- proportionValues.reduce((acc, value, index) => {
+ proportionValues.reduce>((acc, value, index) => {
acc[value] = actualSizes[index] ?? actualSizes[actualSizes.length - 1];
return acc;
}, {});
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.ts
index 31758164e..b466ae04f 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/controlPanel.ts
@@ -112,12 +112,15 @@ export default {
Array.isArray(colnames) && Array.isArray(coltypes)
? colnames
.filter(
- (colname: string, index: number) =>
+ (_: string, index: number) =>
coltypes[index] === GenericDataType.Numeric,
)
- .map(colname => ({
+ .map((colname: string | number) => ({
value: colname,
- label: verboseMap[colname] ?? colname,
+ label:
+ (Array.isArray(verboseMap)
+ ? verboseMap[colname as number]
+ : verboseMap[colname as string]) ?? colname,
}))
: [];
return {
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/transformProps.ts
index f1a62ab7d..1888383a5 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/transformProps.ts
@@ -38,18 +38,37 @@ import { getPadding } from '../Timeseries/transformers';
import { convertInteger } from '../utils/convertInteger';
import { NULL_STRING } from '../constants';
+const isIterable = (obj: any): obj is Iterable =>
+ obj != null && typeof obj[Symbol.iterator] === 'function';
+
function normalizeSymbolSize(
nodes: ScatterSeriesOption[],
maxBubbleValue: number,
) {
- const [bubbleMinValue, bubbleMaxValue] = extent(nodes, x => x.data?.[0]?.[2]);
- const nodeSpread = bubbleMaxValue - bubbleMinValue;
- nodes.forEach(node => {
- // eslint-disable-next-line no-param-reassign
- node.symbolSize =
- (((node.data?.[0]?.[2] - bubbleMinValue) / nodeSpread) *
- (maxBubbleValue * 2) || 0) + MINIMUM_BUBBLE_SIZE;
- });
+ const [bubbleMinValue, bubbleMaxValue] = extent(
+ nodes,
+ x => {
+ const tmpValue = x.data?.[0];
+ const result = isIterable(tmpValue) ? tmpValue[2] : null;
+ if (typeof result === 'number') {
+ return result;
+ }
+ return null;
+ },
+ );
+ if (bubbleMinValue !== undefined && bubbleMaxValue !== undefined) {
+ const nodeSpread = bubbleMaxValue - bubbleMinValue;
+ nodes.forEach(node => {
+ const tmpValue = node.data?.[0];
+ const calculated = isIterable(tmpValue) ? tmpValue[2] : null;
+ if (typeof calculated === 'number') {
+ // eslint-disable-next-line no-param-reassign
+ node.symbolSize =
+ (((calculated - bubbleMinValue) / nodeSpread) *
+ (maxBubbleValue * 2) || 0) + MINIMUM_BUBBLE_SIZE;
+ }
+ });
+ }
}
export function formatTooltip(
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/buildQuery.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/buildQuery.ts
index 2d1ee869e..858a8ddb3 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/buildQuery.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/buildQuery.ts
@@ -18,6 +18,7 @@
*/
import {
QueryFormColumn,
+ QueryFormData,
QueryFormOrderBy,
buildQueryContext,
ensureIsArray,
@@ -26,9 +27,8 @@ import {
getXAxisColumn,
} from '@superset-ui/core';
import { rankOperator } from '@superset-ui/chart-controls';
-import { HeatmapFormData } from './types';
-export default function buildQuery(formData: HeatmapFormData) {
+export default function buildQuery(formData: QueryFormData) {
const { groupby, normalize_across, sort_x_axis, sort_y_axis, x_axis } =
formData;
const metric = getMetricLabel(formData.metric);
@@ -36,16 +36,19 @@ export default function buildQuery(formData: HeatmapFormData) {
...ensureIsArray(getXAxisColumn(formData)),
...ensureIsArray(groupby),
];
- const orderby: QueryFormOrderBy[] = [
- [
+ const orderby: QueryFormOrderBy[] = [];
+ if (sort_x_axis) {
+ orderby.push([
sort_x_axis.includes('value') ? metric : columns[0],
sort_x_axis.includes('asc'),
- ],
- [
+ ]);
+ }
+ if (sort_y_axis) {
+ orderby.push([
sort_y_axis.includes('value') ? metric : columns[1],
sort_y_axis.includes('asc'),
- ],
- ];
+ ]);
+ }
const group_by =
normalize_across === 'x'
? getColumnLabel(x_axis)
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/controlPanel.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/controlPanel.tsx
index 16b825e84..bc949acf9 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/controlPanel.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/controlPanel.tsx
@@ -50,8 +50,7 @@ const config: ControlPanelConfig = {
label: t('Sort X Axis'),
choices: sortAxisChoices,
renderTrigger: false,
- clearable: false,
- default: 'alpha_asc',
+ clearable: true,
},
},
],
@@ -63,8 +62,7 @@ const config: ControlPanelConfig = {
label: t('Sort Y Axis'),
choices: sortAxisChoices,
renderTrigger: false,
- clearable: false,
- default: 'alpha_asc',
+ clearable: true,
},
},
],
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/transformProps.ts
index d0b0b1dd7..5a3cd7587 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/transformProps.ts
@@ -156,8 +156,10 @@ export default function transformProps(
),
label: {
show: showValues,
- formatter: (params: CallbackDataParams) =>
- valueFormatter(params.value?.[2]),
+ formatter: (params: CallbackDataParams) => {
+ const paramsValue = params.value as (string | number)[];
+ return valueFormatter(paramsValue?.[2] as number | null | undefined);
+ },
},
},
];
@@ -178,9 +180,10 @@ export default function transformProps(
yAxisLabel,
metricLabel,
);
- const x = params.value?.[0];
- const y = params.value?.[1];
- const value = params.value?.[2];
+ const paramsValue = params.value as (string | number)[];
+ const x = paramsValue?.[0];
+ const y = paramsValue?.[1];
+ const value = paramsValue?.[2] as number | null | undefined;
const formattedX = xAxisFormatter(x);
const formattedY = yAxisFormatter(y);
const formattedValue = valueFormatter(value);
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/types.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/types.ts
index 8ec984703..11b1685e4 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/types.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Heatmap/types.ts
@@ -36,8 +36,8 @@ export interface HeatmapFormData extends QueryFormData {
showLegend?: boolean;
showPercentage?: boolean;
showValues?: boolean;
- sortXAxis: string;
- sortYAxis: string;
+ sortXAxis?: string;
+ sortYAxis?: string;
timeFormat?: string;
xAxis: QueryFormColumn;
xscaleInterval: number;
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 d4d19f9c2..7526b820d 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
@@ -78,6 +78,7 @@ import {
extractForecastValuesFromTooltipParams,
formatForecastTooltipSeries,
rebaseForecastDatum,
+ reorderForecastSeries,
} from '../utils/forecast';
import { convertInteger } from '../utils/convertInteger';
import { defaultGrid, defaultYAxis } from '../defaults';
@@ -517,7 +518,9 @@ export default function transformProps(
minorTick: { show: minorTicks },
minInterval:
xAxisType === AxisType.Time && timeGrainSqla
- ? TIMEGRAIN_TO_TIMESTAMP[timeGrainSqla]
+ ? TIMEGRAIN_TO_TIMESTAMP[
+ timeGrainSqla as keyof typeof TIMEGRAIN_TO_TIMESTAMP
+ ]
: 0,
...getMinAndMaxFromBounds(
xAxisType,
@@ -661,7 +664,7 @@ export default function transformProps(
.map(entry => entry.name || '')
.concat(extractAnnotationLabels(annotationLayers, annotationData)),
},
- series: dedupSeries(series),
+ series: dedupSeries(reorderForecastSeries(series) as SeriesOption[]),
toolbox: {
show: zoomable,
top: TIMESERIES_CONSTANTS.toolboxTop,
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 5eb0bdd0a..0fb392a12 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
@@ -45,7 +45,6 @@ import {
extractExtraMetrics,
getOriginalSeries,
isDerivedSeries,
- getTimeOffset,
} from '@superset-ui/chart-controls';
import type { EChartsCoreOption } from 'echarts/core';
import type { LineStyleOption } from 'echarts/types/src/util/types';
@@ -81,6 +80,7 @@ import {
extractForecastValuesFromTooltipParams,
formatForecastTooltipSeries,
rebaseForecastDatum,
+ reorderForecastSeries,
} from '../utils/forecast';
import { convertInteger } from '../utils/convertInteger';
import { defaultGrid, defaultYAxis } from '../defaults';
@@ -281,21 +281,15 @@ export default function transformProps(
const array = ensureIsArray(chartProps.rawFormData?.time_compare);
const inverted = invert(verboseMap);
- const offsetLineWidths: { [key: string]: number } = {};
+ let patternIncrement = 0;
rawSeries.forEach(entry => {
const derivedSeries = isDerivedSeries(entry, chartProps.rawFormData);
const lineStyle: LineStyleOption = {};
if (derivedSeries) {
- const offset = getTimeOffset(
- entry,
- ensureIsArray(chartProps.rawFormData?.time_compare),
- )!;
- if (!offsetLineWidths[offset]) {
- offsetLineWidths[offset] = Object.keys(offsetLineWidths).length + 1;
- }
- lineStyle.type = 'dashed';
- lineStyle.width = offsetLineWidths[offset];
+ patternIncrement += 1;
+ // use a combination of dash and dot for the line style
+ lineStyle.type = [(patternIncrement % 5) + 1, (patternIncrement % 3) + 1];
lineStyle.opacity = OpacityEnum.DerivedSeries;
}
@@ -628,10 +622,11 @@ export default function transformProps(
theme,
zoomable,
legendState,
+ padding,
),
data: legendData as string[],
},
- series: dedupSeries(series),
+ series: dedupSeries(reorderForecastSeries(series) as SeriesOption[]),
toolbox: {
show: zoomable,
top: TIMESERIES_CONSTANTS.toolboxTop,
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformers.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformers.ts
index 30d2509e4..cadf64748 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformers.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformers.ts
@@ -315,15 +315,7 @@ export function transformSeries(
opacity: opacity * areaOpacity,
}
: undefined,
- emphasis: {
- // bold on hover as required since 5.3.0 to retain backwards feature parity:
- // https://apache.github.io/echarts-handbook/en/basics/release-note/5-3-0/#removing-the-default-bolding-emphasis-effect-in-the-line-chart
- // TODO: should consider only adding emphasis to currently hovered series
- lineStyle: {
- width: 'bolder',
- },
- ...emphasis,
- },
+ emphasis,
showSymbol,
symbolSize: markerSize,
label: {
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx
index f55d1fb7a..db7daa02b 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/controls.tsx
@@ -306,7 +306,7 @@ export const truncateXAxis: ControlSetItem = {
default: DEFAULT_FORM_DATA.truncateXAxis,
renderTrigger: true,
description: t(
- 'Truncate X Axis. Can be overridden by specifying a min or max bound. Only applicable for numercal X axis.',
+ 'Truncate X Axis. Can be overridden by specifying a min or max bound. Only applicable for numerical X axis.',
),
},
};
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/utils/forecast.ts b/superset-frontend/plugins/plugin-chart-echarts/src/utils/forecast.ts
index c7244baf4..8364f4ed2 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/forecast.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/forecast.ts
@@ -16,9 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { isNumber } from 'lodash';
import { DataRecord, DTTM_ALIAS, ValueFormatter } from '@superset-ui/core';
-import type { OptionName } from 'echarts/types/src/util/types';
+import type { OptionName, SeriesOption } from 'echarts/types/src/util/types';
import type { TooltipMarker } from 'echarts/types/src/util/format';
import {
ForecastSeriesContext,
@@ -64,7 +63,7 @@ export const extractForecastValuesFromTooltipParams = (
const { marker, seriesId, value } = param;
const context = extractForecastSeriesContext(seriesId);
const numericValue = isHorizontal ? value[0] : value[1];
- if (isNumber(numericValue)) {
+ if (typeof numericValue === 'number') {
if (!(context.name in values))
values[context.name] = {
marker: marker || '',
@@ -97,7 +96,7 @@ export const formatForecastTooltipSeries = ({
formatter: ValueFormatter;
}): string[] => {
const name = `${marker}${sanitizeHtml(seriesName)}`;
- let value = isNumber(observation) ? formatter(observation) : '';
+ let value = typeof observation === 'number' ? formatter(observation) : '';
if (forecastTrend || forecastLower || forecastUpper) {
// forecast values take the form of "20, y = 30 (10, 40)"
// where the first part is the observation, the second part is the forecast trend
@@ -150,3 +149,34 @@ export function rebaseForecastDatum(
return newRow;
});
}
+
+// For Confidence Bands, forecast series on mixed charts require the series sent in the following sortOrder:
+export function reorderForecastSeries(row: SeriesOption[]): SeriesOption[] {
+ const sortOrder = {
+ [ForecastSeriesEnum.ForecastLower]: 1,
+ [ForecastSeriesEnum.ForecastUpper]: 2,
+ [ForecastSeriesEnum.ForecastTrend]: 3,
+ [ForecastSeriesEnum.Observation]: 4,
+ };
+
+ // Check if any item needs reordering
+ if (
+ !row.some(
+ item =>
+ item.id &&
+ sortOrder.hasOwnProperty(extractForecastSeriesContext(item.id).type),
+ )
+ ) {
+ return row;
+ }
+
+ return row.sort((a, b) => {
+ const aOrder =
+ sortOrder[extractForecastSeriesContext(a.id ?? '').type] ??
+ Number.MAX_SAFE_INTEGER;
+ const bOrder =
+ sortOrder[extractForecastSeriesContext(b.id ?? '').type] ??
+ Number.MAX_SAFE_INTEGER;
+ return aOrder - bOrder;
+ });
+}
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/utils/formDataSuffix.ts b/superset-frontend/plugins/plugin-chart-echarts/src/utils/formDataSuffix.ts
index c256e6f87..4fb9a1430 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/formDataSuffix.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/formDataSuffix.ts
@@ -29,7 +29,7 @@ export const retainFormDataSuffix = (
* > removeFormDataSuffix(fd, '_b')
* { metrics: ['zee'], limit: 100, ... }
* */
- const newFormData = {};
+ const newFormData: Record = {};
Object.entries(formData)
.sort(([a], [b]) => {
@@ -63,7 +63,7 @@ export const removeFormDataSuffix = (
* > removeUnusedFormData(fd, '_b')
* { metrics: ['foo', 'bar'], limit: 100, ... }
* */
- const newFormData = {};
+ const newFormData: Record = {};
Object.entries(formData).forEach(([key, value]) => {
if (!key.endsWith(controlSuffix)) {
newFormData[key] = value;
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts b/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
index 0aa0ae988..bbf222a2a 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
@@ -33,7 +33,7 @@ import {
TimeFormatter,
ValueFormatter,
} from '@superset-ui/core';
-import { SortSeriesType } from '@superset-ui/chart-controls';
+import { SortSeriesType, LegendPaddingType } from '@superset-ui/chart-controls';
import { format } from 'echarts/core';
import type { LegendComponentOption } from 'echarts/components';
import type { SeriesOption } from 'echarts';
@@ -425,6 +425,7 @@ export function getLegendProps(
theme: SupersetTheme,
zoomable = false,
legendState?: LegendState,
+ padding?: LegendPaddingType,
): LegendComponentOption | LegendComponentOption[] {
const legend: LegendComponentOption | LegendComponentOption[] = {
orient: [LegendOrientation.Top, LegendOrientation.Bottom].includes(
@@ -443,13 +444,30 @@ export function getLegendProps(
borderColor: theme.colors.grayscale.base,
},
};
+ const MIN_LEGEND_WIDTH = 0;
+ const MARGIN_GUTTER = 45;
+ const getLegendWidth = (paddingWidth: number) =>
+ Math.max(paddingWidth - MARGIN_GUTTER, MIN_LEGEND_WIDTH);
+
switch (orientation) {
case LegendOrientation.Left:
legend.left = 0;
+ if (padding?.left) {
+ legend.textStyle = {
+ overflow: 'truncate',
+ width: getLegendWidth(padding.left),
+ };
+ }
break;
case LegendOrientation.Right:
legend.right = 0;
legend.top = zoomable ? TIMESERIES_CONSTANTS.legendRightTopOffset : 0;
+ if (padding?.right) {
+ legend.textStyle = {
+ overflow: 'truncate',
+ width: getLegendWidth(padding.right),
+ };
+ }
break;
case LegendOrientation.Bottom:
legend.bottom = 0;
@@ -467,7 +485,7 @@ export function getChartPadding(
show: boolean,
orientation: LegendOrientation,
margin?: string | number | null,
- padding?: { top?: number; bottom?: number; left?: number; right?: number },
+ padding?: LegendPaddingType,
isHorizontal?: boolean,
): {
bottom: number;
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/utils/treeBuilder.ts b/superset-frontend/plugins/plugin-chart-echarts/src/utils/treeBuilder.ts
index cda78da93..919d6e6db 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/treeBuilder.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/treeBuilder.ts
@@ -17,7 +17,7 @@
* under the License.
*/
import { DataRecord, DataRecordValue } from '@superset-ui/core';
-import { groupBy as _groupBy, isNumber, transform } from 'lodash';
+import { groupBy as _groupBy, transform } from 'lodash';
export type TreeNode = {
name: DataRecordValue;
@@ -28,7 +28,7 @@ export type TreeNode = {
};
function getMetricValue(datum: DataRecord, metric: string) {
- return isNumber(datum[metric]) ? (datum[metric] as number) : 0;
+ return typeof datum[metric] === 'number' ? (datum[metric] as number) : 0;
}
export function treeBuilder(
diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/BigNumber/transformProps.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/BigNumber/transformProps.test.ts
index 8c9ee5621..8b0bf3552 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/test/BigNumber/transformProps.test.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/test/BigNumber/transformProps.test.ts
@@ -173,7 +173,7 @@ describe('BigNumberWithTrendline', () => {
label: 'value',
metric_name: 'value',
d3format: '.2f',
- currency: `{symbol: 'USD', symbolPosition: 'prefix' }`,
+ currency: { symbol: 'USD', symbolPosition: 'prefix' },
},
],
},
diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts
index bbb6271cc..bc2aa2bd5 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts
@@ -469,7 +469,7 @@ describe('Does transformProps transform series correctly', () => {
(totals, currentStack) => {
const total = Object.keys(currentStack).reduce((stackSum, key) => {
if (key === '__timestamp') return stackSum;
- return stackSum + currentStack[key];
+ return stackSum + currentStack[key as keyof typeof currentStack];
}, 0);
totals.push(total);
return totals;
diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/utils/forecast.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/utils/forecast.test.ts
index 1d35a2b11..e737cdada 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/test/utils/forecast.test.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/test/utils/forecast.test.ts
@@ -17,11 +17,13 @@
* under the License.
*/
import { getNumberFormatter, NumberFormats } from '@superset-ui/core';
+import { SeriesOption } from 'echarts';
import {
extractForecastSeriesContext,
extractForecastValuesFromTooltipParams,
formatForecastTooltipSeries,
rebaseForecastDatum,
+ reorderForecastSeries,
} from '../../src/utils/forecast';
import { ForecastSeriesEnum } from '../../src/types';
@@ -46,6 +48,47 @@ describe('extractForecastSeriesContext', () => {
});
});
+describe('reorderForecastSeries', () => {
+ it('should reorder the forecast series and preserve values', () => {
+ const input: SeriesOption[] = [
+ { id: `series${ForecastSeriesEnum.Observation}`, data: [10, 20, 30] },
+ { id: `series${ForecastSeriesEnum.ForecastTrend}`, data: [15, 25, 35] },
+ { id: `series${ForecastSeriesEnum.ForecastLower}`, data: [5, 15, 25] },
+ { id: `series${ForecastSeriesEnum.ForecastUpper}`, data: [25, 35, 45] },
+ ];
+ const expectedOutput: SeriesOption[] = [
+ { id: `series${ForecastSeriesEnum.ForecastLower}`, data: [5, 15, 25] },
+ { id: `series${ForecastSeriesEnum.ForecastUpper}`, data: [25, 35, 45] },
+ { id: `series${ForecastSeriesEnum.ForecastTrend}`, data: [15, 25, 35] },
+ { id: `series${ForecastSeriesEnum.Observation}`, data: [10, 20, 30] },
+ ];
+ expect(reorderForecastSeries(input)).toEqual(expectedOutput);
+ });
+
+ it('should handle an empty array', () => {
+ expect(reorderForecastSeries([])).toEqual([]);
+ });
+
+ it('should not reorder if no relevant series are present', () => {
+ const input: SeriesOption[] = [{ id: 'some-other-series' }];
+ expect(reorderForecastSeries(input)).toEqual(input);
+ });
+
+ it('should handle undefined ids', () => {
+ const input: SeriesOption[] = [
+ { id: `series${ForecastSeriesEnum.ForecastLower}` },
+ { id: undefined },
+ { id: `series${ForecastSeriesEnum.ForecastTrend}` },
+ ];
+ const expectedOutput: SeriesOption[] = [
+ { id: `series${ForecastSeriesEnum.ForecastLower}` },
+ { id: `series${ForecastSeriesEnum.ForecastTrend}` },
+ { id: undefined },
+ ];
+ expect(reorderForecastSeries(input)).toEqual(expectedOutput);
+ });
+});
+
describe('rebaseForecastDatum', () => {
it('should subtract lower confidence level from upper value', () => {
expect(
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/README.md b/superset-frontend/plugins/plugin-chart-handlebars/README.md
index d0c7bdc52..1d9b2bd91 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/README.md
+++ b/superset-frontend/plugins/plugin-chart-handlebars/README.md
@@ -73,3 +73,26 @@ more details.
└── types
└── external.d.ts
```
+
+### Available Handlebars Helpers in Superset
+
+Below, you will find a list of all currently registered helpers in the Handlebars plugin for Superset. These helpers are registered and managed in the file [`HandlebarsViewer.tsx`](./path/to/HandlebarsViewer.tsx).
+
+#### List of Registered Helpers:
+
+1. **`dateFormat`**: Formats a date using a specified format.
+
+ - **Usage**: `{{dateFormat my_date format="MMMM YYYY"}}`
+ - **Default format**: `YYYY-MM-DD`.
+
+2. **`stringify`**: Converts an object into a JSON string or returns a string representation of non-object values.
+
+ - **Usage**: `{{stringify myObj}}`.
+
+3. **`formatNumber`**: Formats a number using locale-specific formatting.
+
+ - **Usage**: `{{formatNumber number locale="en-US"}}`.
+ - **Default locale**: `en-US`.
+
+4. **`parseJson`**: Parses a JSON string into a JavaScript object.
+ - **Usage**: `{{parseJson jsonString}}`.
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/package.json b/superset-frontend/plugins/plugin-chart-handlebars/package.json
index 9df2df8fa..9ff9ef71c 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/package.json
+++ b/superset-frontend/plugins/plugin-chart-handlebars/package.json
@@ -37,9 +37,9 @@
"ace-builds": "^1.4.14",
"lodash": "^4.17.11",
"dayjs": "^1.11.13",
- "react": "^16.13.1",
+ "react": "^17.0.2",
"react-ace": "^10.1.0",
- "react-dom": "^16.13.1"
+ "react-dom": "^17.0.2"
},
"devDependencies": {
"@types/jest": "^29.5.14",
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx
index 883040743..8e1a1aab9 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/components/Handlebars/HandlebarsViewer.tsx
@@ -99,5 +99,18 @@ Handlebars.registerHelper(
},
);
+// usage: {{parseJson jsonString}}
+Handlebars.registerHelper('parseJson', (jsonString: string) => {
+ try {
+ return JSON.parse(jsonString);
+ } catch (error) {
+ if (error instanceof Error) {
+ error.message = `Invalid JSON string: ${error.message}`;
+ throw error;
+ }
+ throw new Error(`Invalid JSON string: ${String(error)}`);
+ }
+});
+
Helpers.registerHelpers(Handlebars);
HandlebarsGroupBy.register(Handlebars);
diff --git a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx
index 71b5b9b06..c43d95487 100644
--- a/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx
+++ b/superset-frontend/plugins/plugin-chart-handlebars/src/plugin/controls/handlebarTemplate.tsx
@@ -20,8 +20,9 @@ import {
ControlSetItem,
CustomControlConfig,
sharedControls,
+ InfoTooltipWithTrigger,
} from '@superset-ui/chart-controls';
-import { t, validateNonEmpty } from '@superset-ui/core';
+import { t, validateNonEmpty, useTheme, SafeMarkdown } from '@superset-ui/core';
import { CodeEditor } from '../../components/CodeEditor/CodeEditor';
import { ControlHeader } from '../../components/ControlHeader/controlHeader';
import { debounceFunc } from '../../consts';
@@ -33,13 +34,48 @@ interface HandlebarsCustomControlProps {
const HandlebarsTemplateControl = (
props: CustomControlConfig,
) => {
+ const theme = useTheme();
+
const val = String(
props?.value ? props?.value : props?.default ? props?.default : '',
);
+ const helperDescriptionsHeader = t(
+ 'Available Handlebars Helpers in Superset:',
+ );
+
+ const helperDescriptions = [
+ { key: 'dateFormat', descKey: 'Formats a date using a specified format.' },
+ { key: 'stringify', descKey: 'Converts an object to a JSON string.' },
+ {
+ key: 'formatNumber',
+ descKey: 'Formats a number using locale-specific formatting.',
+ },
+ {
+ key: 'parseJson',
+ descKey: 'Parses a JSON string into a JavaScript object.',
+ },
+ ];
+
+ const helpersTooltipContent = `
+${helperDescriptionsHeader}
+
+${helperDescriptions
+ .map(({ key, descKey }) => `- **${key}**: ${t(descKey)}`)
+ .join('\n')}
+`;
+
return (