mirror of https://github.com/apache/superset.git
refactor(standardized form data): refine interface and improve code smells (#20518)
This commit is contained in:
parent
23e62d3782
commit
c348a095b9
|
@ -344,30 +344,36 @@ export interface ControlPanelSectionConfig {
|
|||
controlSetRows: ControlSetRow[];
|
||||
}
|
||||
|
||||
export interface StandardizedState {
|
||||
export interface StandardizedControls {
|
||||
metrics: QueryFormMetric[];
|
||||
columns: QueryFormColumn[];
|
||||
}
|
||||
|
||||
export interface StandardizedFormDataInterface {
|
||||
standardizedState: StandardizedState;
|
||||
// Controls not used in the current viz
|
||||
controls: StandardizedControls;
|
||||
// Transformation history
|
||||
memorizedFormData: Map<string, QueryFormData>;
|
||||
}
|
||||
|
||||
export type QueryStandardizedFormData = QueryFormData & {
|
||||
standardizedFormData: StandardizedFormDataInterface;
|
||||
};
|
||||
|
||||
export const isStandardizedFormData = (
|
||||
formData: QueryFormData,
|
||||
): formData is QueryStandardizedFormData =>
|
||||
formData?.standardizedFormData?.controls &&
|
||||
formData?.standardizedFormData?.memorizedFormData &&
|
||||
Array.isArray(formData.standardizedFormData.controls.metrics) &&
|
||||
Array.isArray(formData.standardizedFormData.controls.columns);
|
||||
|
||||
export interface ControlPanelConfig {
|
||||
controlPanelSections: (ControlPanelSectionConfig | null)[];
|
||||
controlOverrides?: ControlOverrides;
|
||||
sectionOverrides?: SectionOverrides;
|
||||
onInit?: (state: ControlStateMapping) => void;
|
||||
denormalizeFormData?: (
|
||||
formData: QueryFormData & {
|
||||
standardizedFormData: StandardizedFormDataInterface;
|
||||
},
|
||||
) => QueryFormData;
|
||||
updateStandardizedState?: (
|
||||
prevState: StandardizedState,
|
||||
currState: StandardizedState,
|
||||
) => StandardizedState;
|
||||
formDataOverrides?: (formData: QueryFormData) => QueryFormData;
|
||||
}
|
||||
|
||||
export type ControlOverrides = {
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* 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 { makeSingleton, QueryFormData } from '@superset-ui/core';
|
||||
import { isStandardizedFormData, StandardizedControls } from '../types';
|
||||
|
||||
class StandardizedControlsManager {
|
||||
controls: StandardizedControls;
|
||||
|
||||
constructor() {
|
||||
this.controls = {
|
||||
metrics: [],
|
||||
columns: [],
|
||||
};
|
||||
}
|
||||
|
||||
setStandardizedControls(formData: QueryFormData) {
|
||||
if (isStandardizedFormData(formData)) {
|
||||
const { controls } = formData.standardizedFormData;
|
||||
this.controls = {
|
||||
metrics: controls.metrics,
|
||||
columns: controls.columns,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
shiftMetric() {
|
||||
return this.controls.metrics.shift();
|
||||
}
|
||||
|
||||
popAllMetrics() {
|
||||
return this.controls.metrics.splice(0, this.controls.metrics.length);
|
||||
}
|
||||
|
||||
popAllColumns() {
|
||||
return this.controls.columns.splice(0, this.controls.columns.length);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.controls = {
|
||||
metrics: [],
|
||||
columns: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const getStandardizedControls = makeSingleton(
|
||||
StandardizedControlsManager,
|
||||
);
|
|
@ -23,3 +23,4 @@ export * from './getColorFormatters';
|
|||
export { default as mainMetric } from './mainMetric';
|
||||
export { default as columnChoices } from './columnChoices';
|
||||
export * from './defineSavedMetrics';
|
||||
export * from './getStandardizedControls';
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* 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 } from '@superset-ui/core';
|
||||
import { getStandardizedControls } from '../../src';
|
||||
|
||||
const formData: QueryFormData = {
|
||||
datasource: '30__table',
|
||||
viz_type: 'table',
|
||||
standardizedFormData: {
|
||||
controls: {
|
||||
metrics: ['count(*)', 'sum(sales)'],
|
||||
columns: ['gender', 'gender'],
|
||||
},
|
||||
memorizedFormData: [],
|
||||
},
|
||||
};
|
||||
|
||||
test('without standardizedFormData', () => {
|
||||
getStandardizedControls().setStandardizedControls({
|
||||
datasource: '30__table',
|
||||
viz_type: 'table',
|
||||
});
|
||||
expect(getStandardizedControls().controls).toEqual({
|
||||
metrics: [],
|
||||
columns: [],
|
||||
});
|
||||
});
|
||||
|
||||
test('getStandardizedControls', () => {
|
||||
expect(getStandardizedControls().controls).toEqual({
|
||||
metrics: [],
|
||||
columns: [],
|
||||
});
|
||||
getStandardizedControls().setStandardizedControls(formData);
|
||||
expect(getStandardizedControls().controls).toEqual({
|
||||
metrics: ['count(*)', 'sum(sales)'],
|
||||
columns: ['gender', 'gender'],
|
||||
});
|
||||
expect(getStandardizedControls().shiftMetric()).toEqual('count(*)');
|
||||
expect(getStandardizedControls().controls).toEqual({
|
||||
metrics: ['sum(sales)'],
|
||||
columns: ['gender', 'gender'],
|
||||
});
|
||||
expect(getStandardizedControls().popAllMetrics()).toEqual(['sum(sales)']);
|
||||
expect(getStandardizedControls().controls).toEqual({
|
||||
metrics: [],
|
||||
columns: ['gender', 'gender'],
|
||||
});
|
||||
expect(getStandardizedControls().popAllColumns()).toEqual([
|
||||
'gender',
|
||||
'gender',
|
||||
]);
|
||||
expect(getStandardizedControls().controls).toEqual({
|
||||
metrics: [],
|
||||
columns: [],
|
||||
});
|
||||
|
||||
getStandardizedControls().setStandardizedControls(formData);
|
||||
getStandardizedControls().clear();
|
||||
expect(getStandardizedControls().controls).toEqual({
|
||||
metrics: [],
|
||||
columns: [],
|
||||
});
|
||||
});
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
import { GenericDataType } from './QueryResponse';
|
||||
import { QueryFormColumn } from './QueryFormData';
|
||||
|
||||
export interface AdhocColumn {
|
||||
hasCustomLabel?: boolean;
|
||||
|
@ -53,12 +54,18 @@ export interface Column {
|
|||
|
||||
export default {};
|
||||
|
||||
export function isPhysicalColumn(
|
||||
column?: AdhocColumn | PhysicalColumn,
|
||||
): column is PhysicalColumn {
|
||||
export function isPhysicalColumn(column?: any): column is PhysicalColumn {
|
||||
return typeof column === 'string';
|
||||
}
|
||||
|
||||
export function isAdhocColumn(column?: AdhocColumn | PhysicalColumn) {
|
||||
return (column as AdhocColumn)?.sqlExpression !== undefined;
|
||||
export function isAdhocColumn(column?: any): column is AdhocColumn {
|
||||
return (
|
||||
typeof column !== 'string' &&
|
||||
column?.sqlExpression !== undefined &&
|
||||
column?.expressionType === 'SQL'
|
||||
);
|
||||
}
|
||||
|
||||
export function isQueryFormColumn(column: any): column is QueryFormColumn {
|
||||
return isPhysicalColumn(column) || isAdhocColumn(column);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { Maybe } from '../../types';
|
||||
import { Maybe, QueryFormMetric } from '../../types';
|
||||
import { Column } from './Column';
|
||||
|
||||
export type Aggregate =
|
||||
|
@ -74,8 +74,22 @@ export interface Metric {
|
|||
|
||||
export default {};
|
||||
|
||||
export function isAdhocMetricSimple(
|
||||
metric: AdhocMetric,
|
||||
): metric is AdhocMetricSimple {
|
||||
return metric.expressionType === 'SIMPLE';
|
||||
export function isSavedMetric(metric: any): metric is SavedMetric {
|
||||
return typeof metric === 'string';
|
||||
}
|
||||
|
||||
export function isAdhocMetricSimple(metric: any): metric is AdhocMetricSimple {
|
||||
return typeof metric !== 'string' && metric?.expressionType === 'SIMPLE';
|
||||
}
|
||||
|
||||
export function isAdhocMetricSQL(metric: any): metric is AdhocMetricSQL {
|
||||
return typeof metric !== 'string' && metric?.expressionType === 'SQL';
|
||||
}
|
||||
|
||||
export function isQueryFormMetric(metric: any): metric is QueryFormMetric {
|
||||
return (
|
||||
isSavedMetric(metric) ||
|
||||
isAdhocMetricSimple(metric) ||
|
||||
isAdhocMetricSQL(metric)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -220,8 +220,4 @@ export function isDruidFormData(
|
|||
return 'granularity' in formData;
|
||||
}
|
||||
|
||||
export function isSavedMetric(metric: QueryFormMetric): metric is SavedMetric {
|
||||
return typeof metric === 'string';
|
||||
}
|
||||
|
||||
export default {};
|
||||
|
|
|
@ -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 {
|
||||
isAdhocColumn,
|
||||
isPhysicalColumn,
|
||||
isQueryFormColumn,
|
||||
} from '@superset-ui/core';
|
||||
|
||||
const adhocColumn = {
|
||||
expressionType: 'SQL',
|
||||
label: 'country',
|
||||
optionName: 'country',
|
||||
sqlExpression: 'country',
|
||||
};
|
||||
|
||||
test('isPhysicalColumn returns true', () => {
|
||||
expect(isPhysicalColumn('gender')).toEqual(true);
|
||||
});
|
||||
|
||||
test('isPhysicalColumn returns false', () => {
|
||||
expect(isPhysicalColumn(adhocColumn)).toEqual(false);
|
||||
});
|
||||
|
||||
test('isAdhocColumn returns true', () => {
|
||||
expect(isAdhocColumn(adhocColumn)).toEqual(true);
|
||||
});
|
||||
|
||||
test('isAdhocColumn returns false', () => {
|
||||
expect(isAdhocColumn('hello')).toEqual(false);
|
||||
expect(isAdhocColumn({})).toEqual(false);
|
||||
expect(
|
||||
isAdhocColumn({
|
||||
expressionType: 'SQL',
|
||||
label: 'country',
|
||||
optionName: 'country',
|
||||
}),
|
||||
).toEqual(false);
|
||||
});
|
||||
|
||||
test('isQueryFormColumn returns true', () => {
|
||||
expect(isQueryFormColumn('gender')).toEqual(true);
|
||||
expect(isQueryFormColumn(adhocColumn)).toEqual(true);
|
||||
});
|
||||
|
||||
test('isQueryFormColumn returns false', () => {
|
||||
expect(isQueryFormColumn({})).toEqual(false);
|
||||
});
|
|
@ -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 {
|
||||
isSavedMetric,
|
||||
isAdhocMetricSimple,
|
||||
isAdhocMetricSQL,
|
||||
isQueryFormMetric,
|
||||
} from '@superset-ui/core';
|
||||
|
||||
const adhocMetricSimple = {
|
||||
expressionType: 'SIMPLE',
|
||||
column: {
|
||||
id: 1,
|
||||
column_name: 'sales',
|
||||
columnName: 'sales',
|
||||
verbose_name: 'sales',
|
||||
},
|
||||
aggregate: 'SUM',
|
||||
label: 'count',
|
||||
optionName: 'count',
|
||||
};
|
||||
|
||||
const adhocMetricSQL = {
|
||||
expressionType: 'SQL',
|
||||
label: 'count',
|
||||
optionName: 'count',
|
||||
sqlExpression: 'count(*)',
|
||||
};
|
||||
|
||||
test('isSavedMetric returns true', () => {
|
||||
expect(isSavedMetric('count(*)')).toEqual(true);
|
||||
});
|
||||
|
||||
test('isSavedMetric returns false', () => {
|
||||
expect(isSavedMetric(adhocMetricSQL)).toEqual(false);
|
||||
expect(isSavedMetric(null)).toEqual(false);
|
||||
expect(isSavedMetric(undefined)).toEqual(false);
|
||||
});
|
||||
|
||||
test('isAdhocMetricSimple returns true', () => {
|
||||
expect(isAdhocMetricSimple(adhocMetricSimple)).toEqual(true);
|
||||
});
|
||||
|
||||
test('isAdhocMetricSimple returns false', () => {
|
||||
expect(isAdhocMetricSimple('hello')).toEqual(false);
|
||||
expect(isAdhocMetricSimple({})).toEqual(false);
|
||||
expect(isAdhocMetricSimple(adhocMetricSQL)).toEqual(false);
|
||||
});
|
||||
|
||||
test('isAdhocMetricSQL returns true', () => {
|
||||
expect(isAdhocMetricSQL(adhocMetricSQL)).toEqual(true);
|
||||
});
|
||||
|
||||
test('isAdhocMetricSQL returns false', () => {
|
||||
expect(isAdhocMetricSQL('hello')).toEqual(false);
|
||||
expect(isAdhocMetricSQL({})).toEqual(false);
|
||||
expect(isAdhocMetricSQL(adhocMetricSimple)).toEqual(false);
|
||||
});
|
||||
|
||||
test('isQueryFormMetric returns true', () => {
|
||||
expect(isQueryFormMetric(adhocMetricSQL)).toEqual(true);
|
||||
expect(isQueryFormMetric(adhocMetricSimple)).toEqual(true);
|
||||
expect(isQueryFormMetric('count(*)')).toEqual(true);
|
||||
});
|
||||
|
||||
test('isQueryFormMetric returns false', () => {
|
||||
expect(isQueryFormMetric({})).toEqual(false);
|
||||
expect(isQueryFormMetric(undefined)).toEqual(false);
|
||||
expect(isQueryFormMetric(null)).toEqual(false);
|
||||
});
|
|
@ -20,6 +20,7 @@ import { t } from '@superset-ui/core';
|
|||
import {
|
||||
ControlPanelConfig,
|
||||
formatSelectOptions,
|
||||
getStandardizedControls,
|
||||
sections,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import { ColorBy } from './utils';
|
||||
|
@ -152,9 +153,9 @@ const config: ControlPanelConfig = {
|
|||
Boolean(controls?.color_by.value === ColorBy.country),
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
metrics: getStandardizedControls().popAllMetrics(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
import { t } from '@superset-ui/core';
|
||||
import {
|
||||
ControlPanelConfig,
|
||||
getStandardizedControls,
|
||||
sections,
|
||||
sharedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
|
@ -122,10 +123,10 @@ const config: ControlPanelConfig = {
|
|||
timeSeriesSection[1],
|
||||
sections.annotations,
|
||||
],
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
metrics: getStandardizedControls().popAllMetrics(),
|
||||
groupby: getStandardizedControls().popAllColumns(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
ControlPanelConfig,
|
||||
sections,
|
||||
sharedControls,
|
||||
getStandardizedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import {
|
||||
showLegend,
|
||||
|
@ -133,14 +134,18 @@ const config: ControlPanelConfig = {
|
|||
rerender: ['groupby'],
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => {
|
||||
const columns =
|
||||
formData.standardizedFormData.standardizedState.columns.filter(
|
||||
col => !ensureIsArray(formData.groupby).includes(col),
|
||||
formDataOverrides: formData => {
|
||||
const columns = getStandardizedControls().controls.columns.filter(
|
||||
col => !ensureIsArray(formData.groupby).includes(col),
|
||||
);
|
||||
getStandardizedControls().controls.columns =
|
||||
getStandardizedControls().controls.columns.filter(
|
||||
col => !columns.includes(col),
|
||||
);
|
||||
|
||||
return {
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
metrics: getStandardizedControls().popAllMetrics(),
|
||||
columns,
|
||||
};
|
||||
},
|
||||
|
|
|
@ -17,7 +17,11 @@
|
|||
* under the License.
|
||||
*/
|
||||
import { t } from '@superset-ui/core';
|
||||
import { ControlPanelConfig, sections } from '@superset-ui/chart-controls';
|
||||
import {
|
||||
ControlPanelConfig,
|
||||
sections,
|
||||
getStandardizedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import {
|
||||
lineInterpolation,
|
||||
showBrush,
|
||||
|
@ -96,10 +100,10 @@ const config: ControlPanelConfig = {
|
|||
default: 50000,
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
metrics: getStandardizedControls().popAllMetrics(),
|
||||
groupby: getStandardizedControls().popAllColumns(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import {
|
|||
ControlPanelConfig,
|
||||
D3_FORMAT_DOCS,
|
||||
D3_TIME_FORMAT_OPTIONS,
|
||||
getStandardizedControls,
|
||||
sections,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import { headerFontSize, subheaderFontSize } from '../sharedControls';
|
||||
|
@ -96,12 +97,8 @@ export default {
|
|||
label: t('Number format'),
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metric: formData.standardizedFormData.standardizedState.metrics[0],
|
||||
}),
|
||||
updateStandardizedState: (prevState, currState) => ({
|
||||
...currState,
|
||||
metrics: [currState.metrics[0], ...prevState.metrics.slice(1)],
|
||||
metric: getStandardizedControls().shiftMetric(),
|
||||
}),
|
||||
} as ControlPanelConfig;
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
D3_FORMAT_DOCS,
|
||||
D3_TIME_FORMAT_OPTIONS,
|
||||
formatSelectOptions,
|
||||
getStandardizedControls,
|
||||
sections,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import React from 'react';
|
||||
|
@ -270,13 +271,9 @@ const config: ControlPanelConfig = {
|
|||
label: t('Number format'),
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metric: formData.standardizedFormData.standardizedState.metrics[0],
|
||||
}),
|
||||
updateStandardizedState: (prevState, currState) => ({
|
||||
...currState,
|
||||
metrics: [currState.metrics[0], ...prevState.metrics.slice(1)],
|
||||
metric: getStandardizedControls().shiftMetric(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import {
|
|||
sections,
|
||||
emitFilterControl,
|
||||
ControlPanelConfig,
|
||||
getStandardizedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
|
||||
const config: ControlPanelConfig = {
|
||||
|
@ -136,14 +137,18 @@ const config: ControlPanelConfig = {
|
|||
),
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => {
|
||||
const groupby =
|
||||
formData.standardizedFormData.standardizedState.columns.filter(
|
||||
col => !ensureIsArray(formData.columns).includes(col),
|
||||
formDataOverrides: formData => {
|
||||
const groupby = getStandardizedControls().controls.columns.filter(
|
||||
col => !ensureIsArray(formData.columns).includes(col),
|
||||
);
|
||||
getStandardizedControls().controls.columns =
|
||||
getStandardizedControls().controls.columns.filter(
|
||||
col => !groupby.includes(col),
|
||||
);
|
||||
|
||||
return {
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
metrics: getStandardizedControls().popAllMetrics(),
|
||||
groupby,
|
||||
};
|
||||
},
|
||||
|
|
|
@ -25,6 +25,7 @@ import {
|
|||
sharedControls,
|
||||
ControlStateMapping,
|
||||
emitFilterControl,
|
||||
getStandardizedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import { DEFAULT_FORM_DATA, EchartsFunnelLabelTypeType } from './types';
|
||||
import { legendSection } from '../controls';
|
||||
|
@ -143,14 +144,10 @@ const config: ControlPanelConfig = {
|
|||
},
|
||||
};
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metric: formData.standardizedFormData.standardizedState.metrics[0],
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
}),
|
||||
updateStandardizedState: (prevState, currState) => ({
|
||||
...currState,
|
||||
metrics: [currState.metrics[0], ...prevState.metrics.slice(1)],
|
||||
metric: getStandardizedControls().shiftMetric(),
|
||||
groupby: getStandardizedControls().popAllColumns(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import {
|
|||
D3_FORMAT_OPTIONS,
|
||||
sections,
|
||||
emitFilterControl,
|
||||
getStandardizedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import { DEFAULT_FORM_DATA } from './types';
|
||||
|
||||
|
@ -308,14 +309,10 @@ const config: ControlPanelConfig = {
|
|||
],
|
||||
},
|
||||
],
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metric: formData.standardizedFormData.standardizedState.metrics[0],
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
}),
|
||||
updateStandardizedState: (prevState, currState) => ({
|
||||
...currState,
|
||||
metrics: [currState.metrics[0], ...prevState.metrics.slice(1)],
|
||||
metric: getStandardizedControls().shiftMetric(),
|
||||
groupby: getStandardizedControls().popAllColumns(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import React from 'react';
|
|||
import { t } from '@superset-ui/core';
|
||||
import {
|
||||
ControlPanelConfig,
|
||||
getStandardizedControls,
|
||||
sections,
|
||||
sharedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
|
@ -320,13 +321,9 @@ const controlPanel: ControlPanelConfig = {
|
|||
],
|
||||
},
|
||||
],
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metric: formData.standardizedFormData.standardizedState.metrics[0],
|
||||
}),
|
||||
updateStandardizedState: (prevState, currState) => ({
|
||||
...currState,
|
||||
metrics: [currState.metrics[0], ...prevState.metrics.slice(1)],
|
||||
metric: getStandardizedControls().popAllMetrics(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ import {
|
|||
ControlSetRow,
|
||||
CustomControlItem,
|
||||
emitFilterControl,
|
||||
getStandardizedControls,
|
||||
sections,
|
||||
sharedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
|
@ -449,15 +450,23 @@ const config: ControlPanelConfig = {
|
|||
],
|
||||
},
|
||||
],
|
||||
denormalizeFormData: formData => {
|
||||
const groupby =
|
||||
formData.standardizedFormData.standardizedState.columns.filter(
|
||||
col => !ensureIsArray(formData.groupby_b).includes(col),
|
||||
formDataOverrides: formData => {
|
||||
const groupby = getStandardizedControls().controls.columns.filter(
|
||||
col => !ensureIsArray(formData.groupby_b).includes(col),
|
||||
);
|
||||
getStandardizedControls().controls.columns =
|
||||
getStandardizedControls().controls.columns.filter(
|
||||
col => !groupby.includes(col),
|
||||
);
|
||||
const metrics =
|
||||
formData.standardizedFormData.standardizedState.metrics.filter(
|
||||
metric => !ensureIsArray(formData.metrics_b).includes(metric),
|
||||
|
||||
const metrics = getStandardizedControls().controls.metrics.filter(
|
||||
metric => !ensureIsArray(formData.metrics_b).includes(metric),
|
||||
);
|
||||
getStandardizedControls().controls.metrics =
|
||||
getStandardizedControls().controls.metrics.filter(
|
||||
col => !metrics.includes(col),
|
||||
);
|
||||
|
||||
return {
|
||||
...formData,
|
||||
metrics,
|
||||
|
|
|
@ -26,6 +26,7 @@ import {
|
|||
D3_TIME_FORMAT_OPTIONS,
|
||||
sections,
|
||||
emitFilterControl,
|
||||
getStandardizedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import { DEFAULT_FORM_DATA } from './types';
|
||||
import { legendSection } from '../controls';
|
||||
|
@ -253,17 +254,13 @@ const config: ControlPanelConfig = {
|
|||
default: 100,
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metric: formData.standardizedFormData.standardizedState.metrics[0],
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
metric: getStandardizedControls().shiftMetric(),
|
||||
groupby: getStandardizedControls().popAllColumns(),
|
||||
row_limit:
|
||||
ensureIsInt(formData.row_limit, 100) >= 100 ? 100 : formData.row_limit,
|
||||
}),
|
||||
updateStandardizedState: (prevState, currState) => ({
|
||||
...currState,
|
||||
metrics: [currState.metrics[0], ...prevState.metrics.slice(1)],
|
||||
}),
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
|
@ -33,6 +33,7 @@ import {
|
|||
sharedControls,
|
||||
emitFilterControl,
|
||||
ControlFormItemSpec,
|
||||
getStandardizedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import { DEFAULT_FORM_DATA } from './types';
|
||||
import { LABEL_POSITION } from '../constants';
|
||||
|
@ -210,10 +211,10 @@ const config: ControlPanelConfig = {
|
|||
],
|
||||
},
|
||||
],
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
metrics: getStandardizedControls().popAllMetrics(),
|
||||
groupby: getStandardizedControls().popAllColumns(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
ControlPanelConfig,
|
||||
ControlPanelsContainerProps,
|
||||
D3_TIME_FORMAT_DOCS,
|
||||
getStandardizedControls,
|
||||
sections,
|
||||
sharedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
|
@ -276,10 +277,10 @@ const config: ControlPanelConfig = {
|
|||
default: rowLimit,
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
metrics: getStandardizedControls().popAllMetrics(),
|
||||
groupby: getStandardizedControls().popAllColumns(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import {
|
|||
ControlStateMapping,
|
||||
D3_TIME_FORMAT_DOCS,
|
||||
formatSelectOptions,
|
||||
getStandardizedControls,
|
||||
sections,
|
||||
sharedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
|
@ -328,10 +329,10 @@ const config: ControlPanelConfig = {
|
|||
default: rowLimit,
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
metrics: getStandardizedControls().popAllMetrics(),
|
||||
groupby: getStandardizedControls().popAllColumns(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
ControlPanelConfig,
|
||||
ControlPanelsContainerProps,
|
||||
D3_TIME_FORMAT_DOCS,
|
||||
getStandardizedControls,
|
||||
sections,
|
||||
sharedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
|
@ -263,10 +264,10 @@ const config: ControlPanelConfig = {
|
|||
default: rowLimit,
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
metrics: getStandardizedControls().popAllMetrics(),
|
||||
groupby: getStandardizedControls().popAllColumns(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
ControlPanelConfig,
|
||||
ControlPanelsContainerProps,
|
||||
D3_TIME_FORMAT_DOCS,
|
||||
getStandardizedControls,
|
||||
sections,
|
||||
sharedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
|
@ -207,10 +208,10 @@ const config: ControlPanelConfig = {
|
|||
default: rowLimit,
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
metrics: getStandardizedControls().popAllMetrics(),
|
||||
groupby: getStandardizedControls().popAllColumns(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
ControlPanelConfig,
|
||||
ControlPanelsContainerProps,
|
||||
D3_TIME_FORMAT_DOCS,
|
||||
getStandardizedControls,
|
||||
sections,
|
||||
sharedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
|
@ -207,10 +208,10 @@ const config: ControlPanelConfig = {
|
|||
default: rowLimit,
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
metrics: getStandardizedControls().popAllMetrics(),
|
||||
groupby: getStandardizedControls().popAllColumns(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
ControlPanelConfig,
|
||||
ControlPanelsContainerProps,
|
||||
D3_TIME_FORMAT_DOCS,
|
||||
getStandardizedControls,
|
||||
sections,
|
||||
sharedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
|
@ -260,10 +261,10 @@ const config: ControlPanelConfig = {
|
|||
default: rowLimit,
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
metrics: getStandardizedControls().popAllMetrics(),
|
||||
groupby: getStandardizedControls().popAllColumns(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import React from 'react';
|
|||
import { FeatureFlag, isFeatureEnabled, t } from '@superset-ui/core';
|
||||
import {
|
||||
ControlPanelConfig,
|
||||
getStandardizedControls,
|
||||
sections,
|
||||
sharedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
|
@ -285,13 +286,9 @@ const controlPanel: ControlPanelConfig = {
|
|||
],
|
||||
},
|
||||
],
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metric: formData.standardizedFormData.standardizedState.metrics[0],
|
||||
}),
|
||||
updateStandardizedState: (prevState, currState) => ({
|
||||
...currState,
|
||||
metrics: [currState.metrics[0], ...prevState.metrics.slice(1)],
|
||||
metric: getStandardizedControls().shiftMetric(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import {
|
|||
D3_TIME_FORMAT_OPTIONS,
|
||||
sections,
|
||||
emitFilterControl,
|
||||
getStandardizedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import { DEFAULT_FORM_DATA } from './types';
|
||||
|
||||
|
@ -137,14 +138,10 @@ const config: ControlPanelConfig = {
|
|||
],
|
||||
},
|
||||
],
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metric: formData.standardizedFormData.standardizedState.metrics[0],
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
}),
|
||||
updateStandardizedState: (prevState, currState) => ({
|
||||
...currState,
|
||||
metrics: [currState.metrics[0], ...prevState.metrics.slice(1)],
|
||||
metric: getStandardizedControls().shiftMetric(),
|
||||
groupby: getStandardizedControls().popAllColumns(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ import {
|
|||
sharedControls,
|
||||
emitFilterControl,
|
||||
Dataset,
|
||||
getStandardizedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import { MetricsLayoutEnum } from '../types';
|
||||
|
||||
|
@ -373,14 +374,17 @@ const config: ControlPanelConfig = {
|
|||
],
|
||||
},
|
||||
],
|
||||
denormalizeFormData: formData => {
|
||||
const groupbyColumns =
|
||||
formData.standardizedFormData.standardizedState.columns.filter(
|
||||
col => !ensureIsArray(formData.groupbyRows).includes(col),
|
||||
formDataOverrides: formData => {
|
||||
const groupbyColumns = getStandardizedControls().controls.columns.filter(
|
||||
col => !ensureIsArray(formData.groupbyRows).includes(col),
|
||||
);
|
||||
getStandardizedControls().controls.columns =
|
||||
getStandardizedControls().controls.columns.filter(
|
||||
col => !groupbyColumns.includes(col),
|
||||
);
|
||||
return {
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
metrics: getStandardizedControls().popAllMetrics(),
|
||||
groupbyColumns,
|
||||
};
|
||||
},
|
||||
|
|
|
@ -47,6 +47,7 @@ import {
|
|||
Dataset,
|
||||
ColumnMeta,
|
||||
defineSavedMetrics,
|
||||
getStandardizedControls,
|
||||
} from '@superset-ui/chart-controls';
|
||||
|
||||
import i18n from './i18n';
|
||||
|
@ -544,10 +545,10 @@ const config: ControlPanelConfig = {
|
|||
],
|
||||
},
|
||||
],
|
||||
denormalizeFormData: formData => ({
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
metrics: getStandardizedControls().popAllMetrics(),
|
||||
groupby: getStandardizedControls().popAllColumns(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -16,27 +16,65 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { getChartControlPanelRegistry, QueryFormData } from '@superset-ui/core';
|
||||
import {
|
||||
AdhocColumn,
|
||||
AdhocMetricSimple,
|
||||
AdhocMetricSQL,
|
||||
getChartControlPanelRegistry,
|
||||
QueryFormData,
|
||||
} from '@superset-ui/core';
|
||||
import TableChartPlugin from '@superset-ui/plugin-chart-table';
|
||||
import { BigNumberTotalChartPlugin } from '@superset-ui/plugin-chart-echarts';
|
||||
import { sections } from '@superset-ui/chart-controls';
|
||||
import {
|
||||
StandardizedFormData,
|
||||
sharedControls,
|
||||
sharedMetricsKey,
|
||||
sharedColumnsKey,
|
||||
publicControls,
|
||||
} from './standardizedFormData';
|
||||
|
||||
const adhocColumn: AdhocColumn = {
|
||||
expressionType: 'SQL',
|
||||
label: 'country',
|
||||
optionName: 'country',
|
||||
sqlExpression: 'country',
|
||||
};
|
||||
|
||||
const adhocMetricSQL: AdhocMetricSQL = {
|
||||
expressionType: 'SQL',
|
||||
label: 'count',
|
||||
optionName: 'count',
|
||||
sqlExpression: 'count(*)',
|
||||
};
|
||||
|
||||
const adhocMetricSimple: AdhocMetricSimple = {
|
||||
expressionType: 'SIMPLE',
|
||||
column: {
|
||||
id: 1,
|
||||
column_name: 'sales',
|
||||
columnName: 'sales',
|
||||
verbose_name: 'sales',
|
||||
},
|
||||
aggregate: 'SUM',
|
||||
label: 'count',
|
||||
optionName: 'count',
|
||||
};
|
||||
|
||||
describe('should collect control values and create SFD', () => {
|
||||
const sharedKey = [...sharedMetricsKey, ...sharedColumnsKey];
|
||||
const sharedControlsFormData = {
|
||||
// metrics
|
||||
metric: 'm1',
|
||||
metrics: ['m2'],
|
||||
metric_2: 'm3',
|
||||
size: 'm4',
|
||||
// columns
|
||||
groupby: ['c1'],
|
||||
columns: ['c2'],
|
||||
groupbyColumns: ['c3'],
|
||||
groupbyRows: ['c4'],
|
||||
series: 'c5',
|
||||
entity: 'c6',
|
||||
};
|
||||
const publicControlsFormData = {
|
||||
// time section
|
||||
|
@ -112,16 +150,16 @@ describe('should collect control values and create SFD', () => {
|
|||
controlSetRows: [['x_axis']],
|
||||
},
|
||||
],
|
||||
denormalizeFormData: (formData: QueryFormData) => ({
|
||||
formDataOverrides: (formData: QueryFormData) => ({
|
||||
...formData,
|
||||
columns: formData.standardizedFormData.standardizedState.columns,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
columns: formData.standardizedFormData.controls.columns,
|
||||
metrics: formData.standardizedFormData.controls.metrics,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
test('should avoid to overlap', () => {
|
||||
const sharedControlsSet = new Set(Object.keys(sharedControls));
|
||||
const sharedControlsSet = new Set(Object.keys(sharedKey));
|
||||
const publicControlsSet = new Set(publicControls);
|
||||
expect(
|
||||
[...sharedControlsSet].filter((x: string) => publicControlsSet.has(x)),
|
||||
|
@ -130,19 +168,17 @@ describe('should collect control values and create SFD', () => {
|
|||
|
||||
test('should collect all sharedControls', () => {
|
||||
expect(Object.entries(sharedControlsFormData).length).toBe(
|
||||
Object.entries(sharedControls).length,
|
||||
Object.entries(sharedKey).length,
|
||||
);
|
||||
const sfd = new StandardizedFormData(sourceMockFormData);
|
||||
expect(sfd.serialize().standardizedState.metrics).toEqual([
|
||||
'm1',
|
||||
'm2',
|
||||
'm3',
|
||||
]);
|
||||
expect(sfd.serialize().standardizedState.columns).toEqual([
|
||||
expect(sfd.serialize().controls.metrics).toEqual(['m1', 'm2', 'm3', 'm4']);
|
||||
expect(sfd.serialize().controls.columns).toEqual([
|
||||
'c1',
|
||||
'c2',
|
||||
'c3',
|
||||
'c4',
|
||||
'c5',
|
||||
'c6',
|
||||
]);
|
||||
});
|
||||
|
||||
|
@ -157,8 +193,8 @@ describe('should collect control values and create SFD', () => {
|
|||
expect(formData).toHaveProperty(key);
|
||||
expect(value).toEqual(publicControlsFormData[key]);
|
||||
});
|
||||
expect(formData.columns).toEqual(['c1', 'c2', 'c3', 'c4']);
|
||||
expect(formData.metrics).toEqual(['m1', 'm2', 'm3']);
|
||||
expect(formData.columns).toEqual(['c1', 'c2', 'c3', 'c4', 'c5', 'c6']);
|
||||
expect(formData.metrics).toEqual(['m1', 'm2', 'm3', 'm4']);
|
||||
});
|
||||
|
||||
test('should inherit standardizedFormData and memorizedFormData is LIFO', () => {
|
||||
|
@ -210,8 +246,8 @@ describe('should transform form_data between table and bigNumberTotal', () => {
|
|||
time_grain_sqla: 'P1D',
|
||||
time_range: 'No filter',
|
||||
query_mode: 'aggregate',
|
||||
groupby: ['name'],
|
||||
metrics: ['count'],
|
||||
groupby: ['name', 'gender', adhocColumn],
|
||||
metrics: ['count', 'avg(sales)', adhocMetricSimple, adhocMetricSQL],
|
||||
all_columns: [],
|
||||
percent_metrics: [],
|
||||
adhoc_filters: [],
|
||||
|
@ -259,10 +295,10 @@ describe('should transform form_data between table and bigNumberTotal', () => {
|
|||
value: 'aggregate',
|
||||
},
|
||||
groupby: {
|
||||
value: ['name'],
|
||||
value: ['name', 'gender', adhocColumn],
|
||||
},
|
||||
metrics: {
|
||||
value: ['count'],
|
||||
value: ['count', 'avg(sales)', adhocMetricSimple, adhocMetricSQL],
|
||||
},
|
||||
all_columns: {
|
||||
value: [],
|
||||
|
@ -349,7 +385,7 @@ describe('should transform form_data between table and bigNumberTotal', () => {
|
|||
expect(bntFormData.viz_type).toBe('big_number_total');
|
||||
expect(bntFormData.metric).toBe('count');
|
||||
|
||||
// change control values
|
||||
// change control values on bigNumber
|
||||
bntFormData.metric = 'sum(sales)';
|
||||
bntFormData.time_range = '2021 : 2022';
|
||||
bntControlsState.metric.value = 'sum(sales)';
|
||||
|
@ -367,8 +403,13 @@ describe('should transform form_data between table and bigNumberTotal', () => {
|
|||
[...Object.keys(tblControlsState), 'standardizedFormData'].sort(),
|
||||
);
|
||||
expect(tblFormData.viz_type).toBe('table');
|
||||
expect(tblFormData.metrics).toEqual(['sum(sales)']);
|
||||
expect(tblFormData.groupby).toEqual(['name']);
|
||||
expect(tblFormData.metrics).toEqual([
|
||||
'sum(sales)',
|
||||
'avg(sales)',
|
||||
adhocMetricSimple,
|
||||
adhocMetricSQL,
|
||||
]);
|
||||
expect(tblFormData.groupby).toEqual(['name', 'gender', adhocColumn]);
|
||||
expect(tblFormData.time_range).toBe('2021 : 2022');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -16,38 +16,38 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { isEmpty, intersection } from 'lodash';
|
||||
import {
|
||||
ensureIsArray,
|
||||
getChartControlPanelRegistry,
|
||||
QueryFormColumn,
|
||||
QueryFormData,
|
||||
QueryFormMetric,
|
||||
} from '@superset-ui/core';
|
||||
import {
|
||||
ControlStateMapping,
|
||||
StandardizedState,
|
||||
getStandardizedControls,
|
||||
isStandardizedFormData,
|
||||
StandardizedControls,
|
||||
StandardizedFormDataInterface,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import { getControlsState } from 'src/explore/store';
|
||||
import { getFormDataFromControls } from './getFormDataFromControls';
|
||||
|
||||
export const sharedControls: Record<string, keyof StandardizedState> = {
|
||||
// metrics
|
||||
metric: 'metrics', // via sharedControls, scalar
|
||||
metrics: 'metrics', // via sharedControls, array
|
||||
metric_2: 'metrics', // via sharedControls, scalar
|
||||
// columns
|
||||
groupby: 'columns', // via sharedControls, array
|
||||
columns: 'columns', // via sharedControls, array
|
||||
groupbyColumns: 'columns', // via pivot table v2, array
|
||||
groupbyRows: 'columns', // via pivot table v2, array
|
||||
};
|
||||
const sharedControlsMap: Record<keyof StandardizedState, string[]> = {
|
||||
metrics: [],
|
||||
columns: [],
|
||||
};
|
||||
Object.entries(sharedControls).forEach(([key, value]) =>
|
||||
sharedControlsMap[value].push(key),
|
||||
);
|
||||
export const sharedMetricsKey = [
|
||||
'metric', // via sharedControls, scalar
|
||||
'metrics', // via sharedControls, array
|
||||
'metric_2', // via sharedControls, scalar
|
||||
'size', // via sharedControls, scalar
|
||||
];
|
||||
export const sharedColumnsKey = [
|
||||
'groupby', // via sharedControls, array
|
||||
'columns', // via sharedControls, array
|
||||
'groupbyColumns', // via pivot table v2, array
|
||||
'groupbyRows', // via pivot table v2, array
|
||||
'entity', // via sharedControls, scalar
|
||||
'series', // via sharedControls, scalar
|
||||
];
|
||||
|
||||
export const publicControls = [
|
||||
// time section
|
||||
'granularity_sqla', // via sharedControls
|
||||
|
@ -100,65 +100,41 @@ export class StandardizedFormData {
|
|||
memorizedFormData.set(vizType, formData);
|
||||
|
||||
// calculate sharedControls
|
||||
const standardizedState =
|
||||
StandardizedFormData.getStandardizedState(formData);
|
||||
const controls = StandardizedFormData.getStandardizedControls(formData);
|
||||
|
||||
this.sfd = {
|
||||
standardizedState,
|
||||
controls,
|
||||
memorizedFormData,
|
||||
};
|
||||
}
|
||||
|
||||
static getStandardizedState(formData: QueryFormData): StandardizedState {
|
||||
// 1. collect current sharedControls
|
||||
let currState: StandardizedState = {
|
||||
static getStandardizedControls(
|
||||
formData: QueryFormData,
|
||||
): StandardizedControls {
|
||||
// 1. initial StandardizedControls
|
||||
const controls: StandardizedControls = {
|
||||
metrics: [],
|
||||
columns: [],
|
||||
};
|
||||
|
||||
// 2. collect current sharedControls
|
||||
Object.entries(formData).forEach(([key, value]) => {
|
||||
if (key in sharedControls) {
|
||||
currState[sharedControls[key]].push(...ensureIsArray(value));
|
||||
if (sharedMetricsKey.includes(key)) {
|
||||
controls.metrics.push(...ensureIsArray<QueryFormMetric>(value));
|
||||
}
|
||||
if (sharedColumnsKey.includes(key)) {
|
||||
controls.columns.push(...ensureIsArray<QueryFormColumn>(value));
|
||||
}
|
||||
});
|
||||
|
||||
// 2. get previous StandardizedState
|
||||
let prevState: StandardizedState = {
|
||||
metrics: [],
|
||||
columns: [],
|
||||
};
|
||||
if (
|
||||
formData?.standardizedFormData?.standardizedState &&
|
||||
Array.isArray(formData.standardizedFormData.standardizedState.metrics) &&
|
||||
Array.isArray(formData.standardizedFormData.standardizedState.columns)
|
||||
) {
|
||||
prevState = formData.standardizedFormData.standardizedState;
|
||||
}
|
||||
// the initial prevState should equal to currentState
|
||||
if (isEmpty(prevState.metrics) && isEmpty(prevState.columns)) {
|
||||
prevState = currState;
|
||||
// 3. append inherit sharedControls
|
||||
if (isStandardizedFormData(formData)) {
|
||||
const { metrics, columns } = formData.standardizedFormData.controls;
|
||||
controls.metrics.push(...metrics);
|
||||
controls.columns.push(...columns);
|
||||
}
|
||||
|
||||
// 3. inherit SS from previous state if current viz hasn't columns-like controls or metrics-like controls
|
||||
Object.keys(sharedControlsMap).forEach(key => {
|
||||
if (
|
||||
isEmpty(intersection(Object.keys(formData), sharedControlsMap[key]))
|
||||
) {
|
||||
currState[key] = prevState[key];
|
||||
}
|
||||
});
|
||||
|
||||
// 4. update hook
|
||||
const controlPanel = getChartControlPanelRegistry().get(formData.viz_type);
|
||||
if (controlPanel?.updateStandardizedState) {
|
||||
currState = controlPanel.updateStandardizedState(prevState, currState);
|
||||
}
|
||||
|
||||
// 5. clear up
|
||||
Object.entries(currState).forEach(([key, value]) => {
|
||||
currState[key] = value.filter(Boolean);
|
||||
});
|
||||
|
||||
return currState;
|
||||
return controls;
|
||||
}
|
||||
|
||||
private getLatestFormData(vizType: string): QueryFormData {
|
||||
|
@ -169,8 +145,8 @@ export class StandardizedFormData {
|
|||
return this.memorizedFormData.slice(-1)[0][1];
|
||||
}
|
||||
|
||||
private get standardizedState() {
|
||||
return this.sfd.standardizedState;
|
||||
private get standardizedControls() {
|
||||
return this.sfd.controls;
|
||||
}
|
||||
|
||||
private get memorizedFormData() {
|
||||
|
@ -179,7 +155,7 @@ export class StandardizedFormData {
|
|||
|
||||
serialize() {
|
||||
return {
|
||||
standardizedState: this.standardizedState,
|
||||
controls: this.standardizedControls,
|
||||
memorizedFormData: this.memorizedFormData,
|
||||
};
|
||||
}
|
||||
|
@ -205,7 +181,7 @@ export class StandardizedFormData {
|
|||
* 2. collect public control values
|
||||
* 3. generate initial targetControlsState
|
||||
* 4. attach `standardizedFormData` to the initial form_data
|
||||
* 5. call denormalizeFormData to transform initial form_data if the plugin was defined
|
||||
* 5. call formDataOverrides to transform initial form_data if the plugin was defined
|
||||
* 6. use final form_data to generate controlsState
|
||||
* */
|
||||
const latestFormData = this.getLatestFormData(targetVizType);
|
||||
|
@ -226,8 +202,17 @@ export class StandardizedFormData {
|
|||
};
|
||||
|
||||
const controlPanel = getChartControlPanelRegistry().get(targetVizType);
|
||||
if (controlPanel?.denormalizeFormData) {
|
||||
const transformed = controlPanel.denormalizeFormData(targetFormData);
|
||||
if (controlPanel?.formDataOverrides) {
|
||||
getStandardizedControls().setStandardizedControls(targetFormData);
|
||||
const transformed = {
|
||||
...controlPanel.formDataOverrides(targetFormData),
|
||||
standardizedFormData: {
|
||||
controls: { ...getStandardizedControls().controls },
|
||||
memorizedFormData: this.memorizedFormData,
|
||||
},
|
||||
};
|
||||
getStandardizedControls().clear();
|
||||
|
||||
return {
|
||||
formData: transformed,
|
||||
controlsState: getControlsState(exploreState, transformed),
|
||||
|
|
Loading…
Reference in New Issue