feat: standardized form_data (#20010)
This commit is contained in:
parent
b08e21efd9
commit
dd4b581fb5
|
|
@ -25,6 +25,8 @@ import type {
|
|||
JsonValue,
|
||||
Metric,
|
||||
QueryFormData,
|
||||
QueryFormMetric,
|
||||
QueryFormColumn,
|
||||
} from '@superset-ui/core';
|
||||
import { sharedControls } from './shared-controls';
|
||||
import sharedControlComponents from './shared-controls/components';
|
||||
|
|
@ -340,11 +342,26 @@ export interface ControlPanelSectionConfig {
|
|||
controlSetRows: ControlSetRow[];
|
||||
}
|
||||
|
||||
export interface StandardizedState {
|
||||
metrics: QueryFormMetric[];
|
||||
columns: QueryFormColumn[];
|
||||
}
|
||||
|
||||
export interface StandardizedFormDataInterface {
|
||||
standardizedState: StandardizedState;
|
||||
memorizedFormData: Map<string, QueryFormData>;
|
||||
}
|
||||
|
||||
export interface ControlPanelConfig {
|
||||
controlPanelSections: (ControlPanelSectionConfig | null)[];
|
||||
controlOverrides?: ControlOverrides;
|
||||
sectionOverrides?: SectionOverrides;
|
||||
onInit?: (state: ControlStateMapping) => void;
|
||||
denormalizeFormData?: (
|
||||
formData: QueryFormData & {
|
||||
standardizedFormData: StandardizedFormDataInterface;
|
||||
},
|
||||
) => QueryFormData;
|
||||
}
|
||||
|
||||
export type ControlOverrides = {
|
||||
|
|
|
|||
|
|
@ -96,4 +96,8 @@ export default {
|
|||
label: t('Number format'),
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
...formData,
|
||||
metric: formData.standardizedFormData.standardizedState.metrics[0],
|
||||
}),
|
||||
} as ControlPanelConfig;
|
||||
|
|
|
|||
|
|
@ -270,6 +270,10 @@ const config: ControlPanelConfig = {
|
|||
label: t('Number format'),
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
...formData,
|
||||
metric: formData.standardizedFormData.standardizedState.metrics[0],
|
||||
}),
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
|
|||
|
|
@ -253,6 +253,11 @@ const config: ControlPanelConfig = {
|
|||
default: 100,
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
...formData,
|
||||
metric: formData.standardizedFormData.standardizedState.metrics[0],
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
}),
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
|
|||
|
|
@ -240,6 +240,10 @@ const config: ControlPanelConfig = {
|
|||
default: rowLimit,
|
||||
},
|
||||
},
|
||||
denormalizeFormData: formData => ({
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
}),
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import {
|
||||
ensureIsArray,
|
||||
QueryFormMetric,
|
||||
smartDateFormatter,
|
||||
t,
|
||||
|
|
@ -367,6 +368,17 @@ const config: ControlPanelConfig = {
|
|||
],
|
||||
},
|
||||
],
|
||||
denormalizeFormData: formData => {
|
||||
const groupbyColumns =
|
||||
formData.standardizedFormData.standardizedState.columns.filter(
|
||||
col => !ensureIsArray(formData.groupbyRows).includes(col),
|
||||
);
|
||||
return {
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
groupbyColumns,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
|
|||
|
|
@ -531,6 +531,11 @@ const config: ControlPanelConfig = {
|
|||
],
|
||||
},
|
||||
],
|
||||
denormalizeFormData: formData => ({
|
||||
...formData,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
groupby: formData.standardizedFormData.standardizedState.columns,
|
||||
}),
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
|
|||
|
|
@ -21,3 +21,4 @@ export * from './getControlConfig';
|
|||
export * from './getControlState';
|
||||
export * from './getFormDataFromControls';
|
||||
export * from './getControlValuesCompatibleWithDatasource';
|
||||
export * from './standardizedFormData';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,307 @@
|
|||
/**
|
||||
* 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 { 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,
|
||||
publicControls,
|
||||
} from './standardizedFormData';
|
||||
import { xAxisControl } from '../../../plugins/plugin-chart-echarts/src/controls';
|
||||
|
||||
describe('should collect control values and create SFD', () => {
|
||||
const sharedControlsFormData = {};
|
||||
Object.entries(sharedControls).forEach(([, names]) => {
|
||||
names.forEach(name => {
|
||||
sharedControlsFormData[name] = name;
|
||||
});
|
||||
});
|
||||
const publicControlsFormData = Object.fromEntries(
|
||||
publicControls.map((name, idx) => [[name], idx]),
|
||||
);
|
||||
const sourceMockFormData: QueryFormData = {
|
||||
...sharedControlsFormData,
|
||||
...publicControlsFormData,
|
||||
datasource: '100__table',
|
||||
viz_type: 'source_viz',
|
||||
};
|
||||
const sourceMockStore = {
|
||||
form_data: sourceMockFormData,
|
||||
controls: Object.fromEntries(
|
||||
Object.entries(sourceMockFormData).map(([key, value]) => [
|
||||
key,
|
||||
{ value },
|
||||
]),
|
||||
),
|
||||
datasource: {
|
||||
type: 'table',
|
||||
columns: [],
|
||||
},
|
||||
};
|
||||
beforeAll(() => {
|
||||
getChartControlPanelRegistry().registerValue('source_viz', {
|
||||
controlPanelSections: [
|
||||
sections.advancedAnalyticsControls,
|
||||
{
|
||||
label: 'transform controls',
|
||||
controlSetRows: publicControls.map(control => [control]),
|
||||
},
|
||||
{
|
||||
label: 'axis column',
|
||||
controlSetRows: [[xAxisControl]],
|
||||
},
|
||||
],
|
||||
});
|
||||
getChartControlPanelRegistry().registerValue('target_viz', {
|
||||
controlPanelSections: [
|
||||
sections.advancedAnalyticsControls,
|
||||
{
|
||||
label: 'transform controls',
|
||||
controlSetRows: publicControls.map(control => [control]),
|
||||
},
|
||||
{
|
||||
label: 'axis column',
|
||||
controlSetRows: [[xAxisControl]],
|
||||
},
|
||||
],
|
||||
denormalizeFormData: (formData: QueryFormData) => ({
|
||||
...formData,
|
||||
columns: formData.standardizedFormData.standardizedState.columns,
|
||||
metrics: formData.standardizedFormData.standardizedState.metrics,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
test('collect sharedControls', () => {
|
||||
const sfd = new StandardizedFormData(sourceMockFormData);
|
||||
|
||||
expect(sfd.dumpSFD().standardizedState.metrics).toEqual(
|
||||
sharedControls.metrics.map(controlName => controlName),
|
||||
);
|
||||
expect(sfd.dumpSFD().standardizedState.columns).toEqual(
|
||||
sharedControls.columns.map(controlName => controlName),
|
||||
);
|
||||
});
|
||||
|
||||
test('should transform all publicControls', () => {
|
||||
const sfd = new StandardizedFormData(sourceMockFormData);
|
||||
const { formData } = sfd.transform('target_viz', sourceMockStore);
|
||||
Object.entries(publicControlsFormData).forEach(([key]) => {
|
||||
expect(formData).toHaveProperty(key);
|
||||
});
|
||||
Object.entries(sharedControls).forEach(([key, value]) => {
|
||||
expect(formData[key]).toEqual(value);
|
||||
});
|
||||
});
|
||||
|
||||
test('should inherit standardizedFormData and memorizedFormData is LIFO', () => {
|
||||
// from source_viz to target_viz
|
||||
const sfd = new StandardizedFormData(sourceMockFormData);
|
||||
const { formData, controlsState } = sfd.transform(
|
||||
'target_viz',
|
||||
sourceMockStore,
|
||||
);
|
||||
expect(
|
||||
formData.standardizedFormData.memorizedFormData.map(
|
||||
(fd: [string, QueryFormData]) => fd[0],
|
||||
),
|
||||
).toEqual(['source_viz']);
|
||||
|
||||
// from target_viz to source_viz
|
||||
const sfd2 = new StandardizedFormData(formData);
|
||||
const { formData: fd2, controlsState: cs2 } = sfd2.transform('source_viz', {
|
||||
...sourceMockStore,
|
||||
form_data: formData,
|
||||
controls: controlsState,
|
||||
});
|
||||
expect(
|
||||
fd2.standardizedFormData.memorizedFormData.map(
|
||||
(fd: [string, QueryFormData]) => fd[0],
|
||||
),
|
||||
).toEqual(['source_viz', 'target_viz']);
|
||||
|
||||
// from source_viz to target_viz
|
||||
const sfd3 = new StandardizedFormData(fd2);
|
||||
const { formData: fd3 } = sfd3.transform('target_viz', {
|
||||
...sourceMockStore,
|
||||
form_data: fd2,
|
||||
controls: cs2,
|
||||
});
|
||||
expect(
|
||||
fd3.standardizedFormData.memorizedFormData.map(
|
||||
(fd: [string, QueryFormData]) => fd[0],
|
||||
),
|
||||
).toEqual(['target_viz', 'source_viz']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('should transform form_data between table and bigNumberTotal', () => {
|
||||
const tableVizFormData = {
|
||||
datasource: '30__table',
|
||||
viz_type: 'table',
|
||||
time_grain_sqla: 'P1D',
|
||||
time_range: 'No filter',
|
||||
query_mode: 'aggregate',
|
||||
groupby: ['name'],
|
||||
metrics: ['count'],
|
||||
all_columns: [],
|
||||
percent_metrics: [],
|
||||
adhoc_filters: [],
|
||||
order_by_cols: [],
|
||||
row_limit: 10000,
|
||||
server_page_length: 10,
|
||||
order_desc: true,
|
||||
table_timestamp_format: 'smart_date',
|
||||
show_cell_bars: true,
|
||||
color_pn: true,
|
||||
applied_time_extras: {},
|
||||
url_params: {
|
||||
form_data_key:
|
||||
'p3No_sqDW7k-kMTzlBPAPd9vwp1IXTf6stbyzjlrPPa0ninvdYUUiMC6F1iKit3Y',
|
||||
dataset_id: '30',
|
||||
},
|
||||
};
|
||||
const tableVizStore = {
|
||||
form_data: tableVizFormData,
|
||||
controls: {
|
||||
datasource: {
|
||||
value: '30__table',
|
||||
},
|
||||
viz_type: {
|
||||
value: 'table',
|
||||
},
|
||||
slice_id: {},
|
||||
cache_timeout: {},
|
||||
url_params: {
|
||||
value: {
|
||||
form_data_key:
|
||||
'p3No_sqDW7k-kMTzlBPAPd9vwp1IXTf6stbyzjlrPPa0ninvdYUUiMC6F1iKit3Y',
|
||||
dataset_id: '30',
|
||||
},
|
||||
},
|
||||
granularity_sqla: {},
|
||||
time_grain_sqla: {
|
||||
value: 'P1D',
|
||||
},
|
||||
time_range: {
|
||||
value: 'No filter',
|
||||
},
|
||||
query_mode: {
|
||||
value: 'aggregate',
|
||||
},
|
||||
groupby: {
|
||||
value: ['name'],
|
||||
},
|
||||
metrics: {
|
||||
value: ['count'],
|
||||
},
|
||||
all_columns: {
|
||||
value: [],
|
||||
},
|
||||
percent_metrics: {
|
||||
value: [],
|
||||
},
|
||||
adhoc_filters: {
|
||||
value: [],
|
||||
},
|
||||
timeseries_limit_metric: {},
|
||||
order_by_cols: {
|
||||
value: [],
|
||||
},
|
||||
server_pagination: {},
|
||||
row_limit: {
|
||||
value: 10000,
|
||||
},
|
||||
server_page_length: {
|
||||
value: 10,
|
||||
},
|
||||
include_time: {},
|
||||
order_desc: {
|
||||
value: true,
|
||||
},
|
||||
show_totals: {},
|
||||
emit_filter: {},
|
||||
table_timestamp_format: {
|
||||
value: 'smart_date',
|
||||
},
|
||||
page_length: {},
|
||||
include_search: {},
|
||||
show_cell_bars: {
|
||||
value: true,
|
||||
},
|
||||
align_pn: {},
|
||||
color_pn: {
|
||||
value: true,
|
||||
},
|
||||
column_config: {},
|
||||
conditional_formatting: {},
|
||||
},
|
||||
datasource: {
|
||||
type: 'table',
|
||||
columns: [],
|
||||
},
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
getChartControlPanelRegistry().registerValue(
|
||||
'big_number_total',
|
||||
new BigNumberTotalChartPlugin().controlPanel,
|
||||
);
|
||||
getChartControlPanelRegistry().registerValue(
|
||||
'table',
|
||||
new TableChartPlugin().controlPanel,
|
||||
);
|
||||
});
|
||||
|
||||
test('transform', () => {
|
||||
// table -> bigNumberTotal
|
||||
const sfd = new StandardizedFormData(tableVizFormData);
|
||||
const { formData: bntFormData, controlsState: bntControlsState } =
|
||||
sfd.transform('big_number_total', tableVizStore);
|
||||
expect(Object.keys(bntFormData).sort()).toEqual(
|
||||
[...Object.keys(bntControlsState), 'standardizedFormData'].sort(),
|
||||
);
|
||||
expect(bntFormData.viz_type).toBe('big_number_total');
|
||||
expect(bntFormData.metric).toBe('count');
|
||||
|
||||
// change control values
|
||||
bntFormData.metric = 'sum(sales)';
|
||||
bntFormData.time_range = '2021 : 2022';
|
||||
bntControlsState.metric.value = 'sum(sales)';
|
||||
bntControlsState.time_range.value = '2021 : 2022';
|
||||
|
||||
// bigNumberTotal -> table
|
||||
const sfd2 = new StandardizedFormData(bntFormData);
|
||||
const { formData: tblFormData, controlsState: tblControlsState } =
|
||||
sfd2.transform('table', {
|
||||
...tableVizStore,
|
||||
form_data: bntFormData,
|
||||
controls: bntControlsState,
|
||||
});
|
||||
expect(Object.keys(tblFormData).sort()).toEqual(
|
||||
[...Object.keys(tblControlsState), 'standardizedFormData'].sort(),
|
||||
);
|
||||
expect(tblFormData.viz_type).toBe('table');
|
||||
expect(tblFormData.metrics).toEqual(['sum(sales)']);
|
||||
expect(tblFormData.groupby).toEqual([]);
|
||||
expect(tblFormData.time_range).toBe('2021 : 2022');
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
/**
|
||||
* 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 {
|
||||
ensureIsArray,
|
||||
getChartControlPanelRegistry,
|
||||
QueryFormData,
|
||||
} from '@superset-ui/core';
|
||||
import {
|
||||
ControlStateMapping,
|
||||
StandardizedState,
|
||||
StandardizedFormDataInterface,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import { getControlsState } from 'src/explore/store';
|
||||
import { getFormDataFromControls } from './getFormDataFromControls';
|
||||
|
||||
export const sharedControls: Record<keyof StandardizedState, string[]> = {
|
||||
metrics: ['metric', 'metrics', 'metric_2'],
|
||||
columns: ['groupby', 'columns', 'groupbyColumns', 'groupbyRows'],
|
||||
};
|
||||
export const publicControls = [
|
||||
// time section
|
||||
'granularity_sqla',
|
||||
'time_grain_sqla',
|
||||
'time_range',
|
||||
// filters
|
||||
'adhoc_filters',
|
||||
// subquery limit(series limit)
|
||||
'limit',
|
||||
// order by clause
|
||||
'timeseries_limit_metric',
|
||||
'series_limit_metric',
|
||||
// desc or asc in order by clause
|
||||
'order_desc',
|
||||
// outer query limit
|
||||
'row_limit',
|
||||
// x asxs column
|
||||
'x_axis',
|
||||
// advanced analytics - rolling window
|
||||
'rolling_type',
|
||||
'rolling_periods',
|
||||
'min_periods',
|
||||
// advanced analytics - time comparison
|
||||
'time_compare',
|
||||
'comparison_type',
|
||||
// advanced analytics - resample
|
||||
'resample_rule',
|
||||
'resample_method',
|
||||
];
|
||||
|
||||
export class StandardizedFormData {
|
||||
private sfd: StandardizedFormDataInterface;
|
||||
|
||||
constructor(sourceFormData: QueryFormData) {
|
||||
/*
|
||||
* Support form_data for smooth switching between different viz
|
||||
* */
|
||||
const standardizedState = {
|
||||
metrics: [],
|
||||
columns: [],
|
||||
};
|
||||
const formData = Object.freeze(sourceFormData);
|
||||
const reversedMap = StandardizedFormData.getReversedMap();
|
||||
|
||||
Object.entries(formData).forEach(([key, value]) => {
|
||||
if (reversedMap.has(key)) {
|
||||
standardizedState[reversedMap.get(key)].push(...ensureIsArray(value));
|
||||
}
|
||||
});
|
||||
|
||||
const memorizedFormData = Array.isArray(
|
||||
formData?.standardizedFormData?.memorizedFormData,
|
||||
)
|
||||
? new Map(formData.standardizedFormData.memorizedFormData)
|
||||
: new Map();
|
||||
const vizType = formData.viz_type;
|
||||
if (memorizedFormData.has(vizType)) {
|
||||
memorizedFormData.delete(vizType);
|
||||
}
|
||||
memorizedFormData.set(vizType, formData);
|
||||
this.sfd = {
|
||||
standardizedState,
|
||||
memorizedFormData,
|
||||
};
|
||||
}
|
||||
|
||||
static getReversedMap() {
|
||||
const reversedMap = new Map();
|
||||
Object.entries(sharedControls).forEach(([key, names]) => {
|
||||
names.forEach(name => {
|
||||
reversedMap.set(name, key);
|
||||
});
|
||||
});
|
||||
return reversedMap;
|
||||
}
|
||||
|
||||
private getLatestFormData(vizType: string): QueryFormData {
|
||||
if (this.sfd.memorizedFormData.has(vizType)) {
|
||||
return this.sfd.memorizedFormData.get(vizType) as QueryFormData;
|
||||
}
|
||||
|
||||
return this.memorizedFormData.slice(-1)[0][1];
|
||||
}
|
||||
|
||||
private get standardizedState() {
|
||||
return this.sfd.standardizedState;
|
||||
}
|
||||
|
||||
private get memorizedFormData() {
|
||||
return Array.from(this.sfd.memorizedFormData.entries());
|
||||
}
|
||||
|
||||
dumpSFD() {
|
||||
return {
|
||||
standardizedState: this.standardizedState,
|
||||
memorizedFormData: this.memorizedFormData,
|
||||
};
|
||||
}
|
||||
|
||||
transform(
|
||||
targetVizType: string,
|
||||
exploreState: Record<string, any>,
|
||||
): {
|
||||
formData: QueryFormData;
|
||||
controlsState: ControlStateMapping;
|
||||
} {
|
||||
/*
|
||||
* Transfrom form_data between different viz. Return new form_data and controlsState.
|
||||
* 1. get memorized form_data by viz type or get previous form_data
|
||||
* 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
|
||||
* 6. use final form_data to generate controlsState
|
||||
* */
|
||||
const latestFormData = this.getLatestFormData(targetVizType);
|
||||
const publicFormData = {};
|
||||
publicControls.forEach(key => {
|
||||
if (key in exploreState.form_data) {
|
||||
publicFormData[key] = exploreState.form_data[key];
|
||||
}
|
||||
});
|
||||
const targetControlsState = getControlsState(exploreState, {
|
||||
...latestFormData,
|
||||
...publicFormData,
|
||||
viz_type: targetVizType,
|
||||
});
|
||||
const targetFormData = {
|
||||
...getFormDataFromControls(targetControlsState),
|
||||
standardizedFormData: this.dumpSFD(),
|
||||
};
|
||||
|
||||
const controlPanel = getChartControlPanelRegistry().get(targetVizType);
|
||||
if (controlPanel?.denormalizeFormData) {
|
||||
const transformed = controlPanel.denormalizeFormData(targetFormData);
|
||||
return {
|
||||
formData: transformed,
|
||||
controlsState: getControlsState(exploreState, transformed),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
formData: targetFormData,
|
||||
controlsState: targetControlsState,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -23,9 +23,9 @@ import { DEFAULT_TIME_RANGE } from 'src/explore/constants';
|
|||
import { getControlsState } from 'src/explore/store';
|
||||
import {
|
||||
getControlConfig,
|
||||
getFormDataFromControls,
|
||||
getControlStateFromControlConfig,
|
||||
getControlValuesCompatibleWithDatasource,
|
||||
StandardizedFormData,
|
||||
} from 'src/explore/controlUtils';
|
||||
import * as actions from 'src/explore/actions/exploreActions';
|
||||
|
||||
|
|
@ -129,11 +129,10 @@ export default function exploreReducer(state = {}, action) {
|
|||
};
|
||||
},
|
||||
[actions.SET_FIELD_VALUE]() {
|
||||
const new_form_data = state.form_data;
|
||||
const { controlName, value, validationErrors } = action;
|
||||
let new_form_data = { ...state.form_data, [controlName]: value };
|
||||
const old_metrics_data = state.form_data.metrics;
|
||||
const new_column_config = state.form_data.column_config;
|
||||
const { controlName, value, validationErrors } = action;
|
||||
new_form_data[controlName] = value;
|
||||
|
||||
const vizType = new_form_data.viz_type;
|
||||
|
||||
|
|
@ -204,18 +203,17 @@ export default function exploreReducer(state = {}, action) {
|
|||
});
|
||||
const hasErrors = errors && errors.length > 0;
|
||||
|
||||
const currentControlsState =
|
||||
const isVizSwitch =
|
||||
action.controlName === 'viz_type' &&
|
||||
action.value !== state.controls.viz_type.value
|
||||
? // rebuild the full control state if switching viz type
|
||||
getControlsState(
|
||||
state,
|
||||
getFormDataFromControls({
|
||||
...state.controls,
|
||||
viz_type: control,
|
||||
}),
|
||||
)
|
||||
: state.controls;
|
||||
action.value !== state.controls.viz_type.value;
|
||||
let currentControlsState = state.controls;
|
||||
if (isVizSwitch) {
|
||||
// get StandardizedFormData from source form_data
|
||||
const sfd = new StandardizedFormData(state.form_data);
|
||||
const transformed = sfd.transform(action.value, state);
|
||||
new_form_data = transformed.formData;
|
||||
currentControlsState = transformed.controlsState;
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
|
|
|
|||
Loading…
Reference in New Issue