From fcd0c4028ae67afa65e6ee358cd52b2c75d41eef Mon Sep 17 00:00:00 2001 From: sulemanof Date: Thu, 31 Oct 2019 17:18:49 +0300 Subject: [PATCH] Create a state reducer and a state context --- .../components/options/metrics_axes/index.tsx | 19 +++- .../public/vis/editors/default/_sidebar.scss | 5 - .../vis/editors/default/components/agg.tsx | 2 + .../default/components/agg_common_props.ts | 1 + .../editors/default/components/agg_group.tsx | 2 + .../editors/default/components/agg_params.tsx | 13 +-- .../editors/default/components/bottom_bar.tsx | 72 ++++++++---- .../editors/default/components/data_tab.tsx | 27 ++--- .../ui/public/vis/editors/default/default.js | 1 - .../vis/editors/default/default_editor.tsx | 87 ++++----------- .../default/default_editor_controller.tsx | 5 +- .../vis/editors/default/state/actions.ts | 59 ++++++++++ .../vis/editors/default/state/constants.ts | 26 +++++ .../default/state/editor_state_context.tsx | 45 ++++++++ .../public/vis/editors/default/state/index.ts | 49 +++++++++ .../vis/editors/default/state/reducers.ts | 104 ++++++++++++++++++ .../vis/editors/default/vis_editor_resizer.js | 64 ----------- .../editors/default/vis_editor_sidebar.tsx | 25 ++--- 18 files changed, 402 insertions(+), 204 deletions(-) create mode 100644 src/legacy/ui/public/vis/editors/default/state/actions.ts create mode 100644 src/legacy/ui/public/vis/editors/default/state/constants.ts create mode 100644 src/legacy/ui/public/vis/editors/default/state/editor_state_context.tsx create mode 100644 src/legacy/ui/public/vis/editors/default/state/index.ts create mode 100644 src/legacy/ui/public/vis/editors/default/state/reducers.ts delete mode 100644 src/legacy/ui/public/vis/editors/default/vis_editor_resizer.js diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.tsx index c7ada18f9e1f25..ede7582a1fb6b1 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.tsx +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/index.tsx @@ -22,6 +22,7 @@ import { cloneDeep, uniq, get } from 'lodash'; import { EuiSpacer } from '@elastic/eui'; import { AggConfig } from 'ui/vis'; +import { useEditorState } from 'ui/vis/editors/default/state'; import { BasicVislibParams, ValueAxis, SeriesParam, Axis } from '../../../types'; import { ValidationVisOptionsProps } from '../../common'; import { SeriesPanel } from './series_panel'; @@ -52,7 +53,7 @@ export type ChangeValueAxis = ( const VALUE_AXIS_PREFIX = 'ValueAxis-'; function MetricsAxisOptions(props: ValidationVisOptionsProps) { - const { stateParams, setValue, aggs, aggsLabels, setVisType, vis } = props; + const { stateParams, setValue, aggs, setVisType, vis } = props; const [isCategoryAxisHorizontal, setIsCategoryAxisHorizontal] = useState(true); @@ -240,11 +241,17 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps) const metrics = useMemo(() => { const schemaName = vis.type.schemas.metrics[0].name; return aggs.bySchemaName(schemaName); - }, [vis.type.schemas.metrics[0].name, aggs, aggsLabels]); + }, [vis.type.schemas.metrics[0].name, aggs]); const firstValueAxesId = stateParams.valueAxes[0].id; + const { isDirty } = useEditorState(); + useEffect(() => { + if (!isDirty) { + return; + } + const updatedSeries = metrics.map(agg => { const params = stateParams.seriesParams.find(param => param.data.id === agg.id); const label = agg.makeLabel(); @@ -270,7 +277,7 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps) }); setValue('seriesParams', updatedSeries); - }, [aggsLabels, metrics, firstValueAxesId]); + }, [isDirty, metrics, firstValueAxesId]); const visType = useMemo(() => { const types = uniq(stateParams.seriesParams.map(({ type }) => type)); @@ -282,8 +289,12 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps) }, [visType]); useEffect(() => { + if (!isDirty) { + return; + } + updateAxisTitle(); - }, [aggsLabels]); + }, [aggs, isDirty]); return ( <> diff --git a/src/legacy/ui/public/vis/editors/default/_sidebar.scss b/src/legacy/ui/public/vis/editors/default/_sidebar.scss index e132dc2e8b4f6f..cf65ea058f8949 100644 --- a/src/legacy/ui/public/vis/editors/default/_sidebar.scss +++ b/src/legacy/ui/public/vis/editors/default/_sidebar.scss @@ -60,11 +60,6 @@ } } -.visEditorSidebar__navButtonLink { - // Make the line-height the same size as the icon for better alignment - line-height: $euiSize; -} - // // SECTIONS // diff --git a/src/legacy/ui/public/vis/editors/default/components/agg.tsx b/src/legacy/ui/public/vis/editors/default/components/agg.tsx index 984c67875589ee..345c9254ff6c15 100644 --- a/src/legacy/ui/public/vis/editors/default/components/agg.tsx +++ b/src/legacy/ui/public/vis/editors/default/components/agg.tsx @@ -58,6 +58,7 @@ function DefaultEditorAgg({ lastParentPipelineAggTitle, state, onAggParamsChange, + onAggTypeChange, onToggleEnableAgg, removeAgg, setTouched, @@ -264,6 +265,7 @@ function DefaultEditorAgg({ metricAggs={metricAggs} state={state} onAggParamsChange={onAggParamsChange} + onAggTypeChange={onAggTypeChange} setTouched={setTouched} setValidity={onSetValidity} /> diff --git a/src/legacy/ui/public/vis/editors/default/components/agg_common_props.ts b/src/legacy/ui/public/vis/editors/default/components/agg_common_props.ts index 7e822bb0a97ccc..6577f9d74f5e1e 100644 --- a/src/legacy/ui/public/vis/editors/default/components/agg_common_props.ts +++ b/src/legacy/ui/public/vis/editors/default/components/agg_common_props.ts @@ -35,6 +35,7 @@ export interface DefaultEditorAggCommonProps { metricAggs: AggConfig[]; state: VisState; onAggParamsChange: OnParamChange; + onAggTypeChange: (aggId: AggConfig['id'], aggType: AggType) => void; onToggleEnableAgg: (agg: AggConfig, isEnable: boolean) => void; removeAgg: (agg: AggConfig) => void; setTouched: (isTouched: boolean) => void; diff --git a/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx b/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx index e8657593172429..6d3b5fc4e63557 100644 --- a/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx +++ b/src/legacy/ui/public/vis/editors/default/components/agg_group.tsx @@ -57,6 +57,7 @@ function DefaultEditorAggGroup({ schemas = [], addSchema, onAggParamsChange, + onAggTypeChange, onToggleEnableAgg, removeAgg, reorderAggs, @@ -168,6 +169,7 @@ function DefaultEditorAggGroup({ metricAggs={metricAggs} state={state} onAggParamsChange={onAggParamsChange} + onAggTypeChange={onAggTypeChange} onToggleEnableAgg={onToggleEnableAgg} removeAgg={removeAgg} setTouched={isTouched => setTouchedHandler(agg.id, isTouched)} diff --git a/src/legacy/ui/public/vis/editors/default/components/agg_params.tsx b/src/legacy/ui/public/vis/editors/default/components/agg_params.tsx index 81b1077df76130..039058998deb31 100644 --- a/src/legacy/ui/public/vis/editors/default/components/agg_params.tsx +++ b/src/legacy/ui/public/vis/editors/default/components/agg_params.tsx @@ -17,7 +17,7 @@ * under the License. */ -import React, { useReducer, useEffect, useMemo, useCallback } from 'react'; +import React, { useReducer, useEffect, useMemo } from 'react'; import { EuiForm, EuiAccordion, EuiSpacer, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -58,7 +58,7 @@ type EditorParamConfigType = EditorParamConfig & { export interface SubAggParamsProp { formIsTouched: boolean; onAggParamsChange: OnParamChange; - onAggTypeChange: (agg: AggConfig, aggType: AggType) => void; + onAggTypeChange: (aggId: AggConfig['id'], aggType: AggType) => void; } export interface DefaultEditorAggParamsProps extends SubAggParamsProp { agg: AggConfig; @@ -88,6 +88,7 @@ function DefaultEditorAggParams({ metricAggs, state = {} as VisState, onAggParamsChange, + onAggTypeChange, setTouched, setValidity, }: DefaultEditorAggParamsProps) { @@ -115,12 +116,6 @@ function DefaultEditorAggParams({ const isAllInvalidParamsTouched = !!errors.length || isInvalidParamsTouched(agg.type, aggType, paramsState); - const onAggTypeChange = useCallback((aggr, value) => { - if (aggr.type !== value) { - aggr.type = value; - } - }, []); - // reset validity before component destroyed useUnmount(() => setValidity(true)); @@ -215,7 +210,7 @@ function DefaultEditorAggParams({ isSubAggregation={aggIndex >= 1 && groupName === AggGroupNames.Buckets} showValidation={formIsTouched || aggType.touched} setValue={value => { - onAggTypeChange(agg, value); + onAggTypeChange(agg.id, value); // reset touched and valid of params onChangeParamsState({ type: AGG_PARAMS_ACTION_KEYS.RESET }); }} diff --git a/src/legacy/ui/public/vis/editors/default/components/bottom_bar.tsx b/src/legacy/ui/public/vis/editors/default/components/bottom_bar.tsx index 742eceafed5ccf..226365a2301d6d 100644 --- a/src/legacy/ui/public/vis/editors/default/components/bottom_bar.tsx +++ b/src/legacy/ui/public/vis/editors/default/components/bottom_bar.tsx @@ -19,17 +19,13 @@ import React, { useCallback } from 'react'; import { EuiBottomBar, EuiFlexGroup, EuiFlexItem, EuiButton, EuiButtonEmpty } from '@elastic/eui'; -import { visDimension } from 'src/legacy/core_plugins/interpreter/public/functions/vis_dimension'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { discardChanges } from '../state'; -function DefaultEditorBottomBar({ dispatch, vis }) { - const discardChanges = useCallback( - () => - dispatch({ - type: 'discardChanges', - payload: vis, - }), - [dispatch, vis] - ); +function DefaultEditorBottomBar({ dispatch, isDirty, vis }) { + const onClickDiscard = useCallback(() => dispatch(discardChanges(vis)), [dispatch, vis]); + const { enableAutoApply } = vis.type.editorConfig; return ( @@ -37,16 +33,52 @@ function DefaultEditorBottomBar({ dispatch, vis }) { - - - Discard changes - - - - - Update chart - - + {!enableAutoApply && ( + <> + + + + + + + + + + + + + )} diff --git a/src/legacy/ui/public/vis/editors/default/components/data_tab.tsx b/src/legacy/ui/public/vis/editors/default/components/data_tab.tsx index 50e2d1564144d9..9026c98451992c 100644 --- a/src/legacy/ui/public/vis/editors/default/components/data_tab.tsx +++ b/src/legacy/ui/public/vis/editors/default/components/data_tab.tsx @@ -21,12 +21,12 @@ import React, { useCallback } from 'react'; import { EuiSpacer } from '@elastic/eui'; import { DefaultEditorAggGroup } from './agg_group'; import { AggGroupNames } from '../agg_groups'; +import { addNewAgg, changeAggType, setAggParamValue } from '../state'; function DefaultEditorDataTab({ metricAggs, state, schemas, - onParamChange, onToggleEnableAgg, removeAgg, reorderAggs, @@ -41,28 +41,16 @@ function DefaultEditorDataTab({ const onAggParamsChange = useCallback( (aggId, paramName, value) => { - dispatch({ - type: 'setAggParamValue', - payload: { - aggId, - paramName, - value, - }, - }); + dispatch(setAggParamValue(aggId, paramName, value)); }, [dispatch] ); - const addSchema = useCallback( - schema => - dispatch({ - type: 'addNewAgg', - payload: { - schema, - }, - }), - [dispatch] - ); + const addSchema = useCallback(schema => dispatch(addNewAgg(schema)), [dispatch]); + + const onAggTypeChange = useCallback((aggId, value) => dispatch(changeAggType(aggId, value)), [ + dispatch, + ]); const commonProps = { addSchema, @@ -70,6 +58,7 @@ function DefaultEditorDataTab({ state, reorderAggs, onAggParamsChange, + onAggTypeChange, onToggleEnableAgg, setValidity, setTouched, diff --git a/src/legacy/ui/public/vis/editors/default/default.js b/src/legacy/ui/public/vis/editors/default/default.js index e31f780c010fd8..8c0c48ba7c6e84 100644 --- a/src/legacy/ui/public/vis/editors/default/default.js +++ b/src/legacy/ui/public/vis/editors/default/default.js @@ -21,7 +21,6 @@ import 'ui/angular-bootstrap'; import './fancy_forms'; import './sidebar'; import { i18n } from '@kbn/i18n'; -import './vis_editor_resizer'; import './vis_type_agg_filter'; import $ from 'jquery'; diff --git a/src/legacy/ui/public/vis/editors/default/default_editor.tsx b/src/legacy/ui/public/vis/editors/default/default_editor.tsx index 0bcd240be49e97..78743d7f64ab2f 100644 --- a/src/legacy/ui/public/vis/editors/default/default_editor.tsx +++ b/src/legacy/ui/public/vis/editors/default/default_editor.tsx @@ -17,62 +17,23 @@ * under the License. */ -import React, { useEffect, useReducer, useRef, useState } from 'react'; +import React, { useEffect, useReducer, useRef, useState, useCallback } from 'react'; import { getVisualizeLoader, EmbeddedVisualizeHandler } from 'ui/visualize'; -import { AggConfigs } from 'ui/agg_types'; import { VisEditorSideBar } from './vis_editor_sidebar'; import { DefaultEditorBottomBar } from './components/bottom_bar'; +import { editorStateReducer, initEditorState, useEditorState, useEditorReducer } from './state'; +// import { Resizer } from './resizer'; +import { EditorStateActionTypes } from './state/constants'; const sidebarClassName = 'visEditor__collapsibleSidebar'; -function initEditorState(vis) { - return vis.copyCurrentState(true); -} - -function editorStateReducer(state, action) { - switch (action.type) { - case 'setAggParamValue': { - const { aggId, paramName, value } = action.payload; - - const newAggs = state.aggs.aggs.map(agg => { - if (agg.id === aggId) { - const parsedAgg = agg.toJSON(); - - return { - ...parsedAgg, - params: { - ...parsedAgg.params, - [paramName]: value, - }, - }; - } - - return agg; - }); - - return { - ...state, - aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), - }; - } - case 'addNewAgg': { - const newAggs = [...state.aggs.aggs, state.aggs.createAggConfig(action.payload)]; - - return { - ...state, - aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), - }; - } - - case 'discardChanges': { - return initEditorState(action.payload); - } - } -} - function DefaultEditor({ el, savedObj, uiState, timeRange, filters, appState, vis, optionTabs }) { const visRef = useRef(null); + const sidebarRef = useRef(null); const [visHandler, setVisHandler] = useState(null); + const [sidebarStyle, setSidebarStyle] = useState({}); + const { isDirty, setDirty } = useEditorState(); + const [state, dispatch] = useEditorReducer(vis); useEffect(() => { async function visualize() { @@ -84,7 +45,6 @@ function DefaultEditor({ el, savedObj, uiState, timeRange, filters, appState, vi const loader = await getVisualizeLoader(); const handler = loader.embedVisualizationWithSavedObject(visRef.current, savedObj, { uiState, - listenOnChange: false, timeRange, filters, appState, @@ -102,53 +62,54 @@ function DefaultEditor({ el, savedObj, uiState, timeRange, filters, appState, vi visualize(); }, [visRef.current, visHandler, uiState, savedObj, timeRange, filters, appState]); - const onParamChange = (params, paramName, value) => { - if (params[paramName] !== value) { - params[paramName] = value; - } - }; - const setVisType = type => { vis.type.type = type; }; - const [state, dispatch] = useReducer(editorStateReducer, vis, initEditorState); + useEffect(() => { + vis.on('dirtyStateChange', ({ isDirty }) => { + setDirty(isDirty); + }); + }, [vis]); + + const onResize = useCallback(width => { + setSidebarStyle(style => ({ ...style, width })); + }, []); return (
- + {/* */}
- +
); } diff --git a/src/legacy/ui/public/vis/editors/default/default_editor_controller.tsx b/src/legacy/ui/public/vis/editors/default/default_editor_controller.tsx index 9cbd586a0da487..69dab169bd62c5 100644 --- a/src/legacy/ui/public/vis/editors/default/default_editor_controller.tsx +++ b/src/legacy/ui/public/vis/editors/default/default_editor_controller.tsx @@ -23,6 +23,7 @@ import { i18n } from '@kbn/i18n'; import { I18nContext } from 'ui/i18n'; import { DefaultEditor } from './default_editor'; import { DefaultEditorDataTab } from './components/data_tab'; +import { EditorStateContextProvider } from './state'; export function createEditorController() { return class { @@ -66,7 +67,9 @@ export function createEditorController() { render(props) { render( - + + + , this.el ); diff --git a/src/legacy/ui/public/vis/editors/default/state/actions.ts b/src/legacy/ui/public/vis/editors/default/state/actions.ts new file mode 100644 index 00000000000000..73ff1ee839df02 --- /dev/null +++ b/src/legacy/ui/public/vis/editors/default/state/actions.ts @@ -0,0 +1,59 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. 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 { EditorStateActionTypes } from './constants'; + +const addNewAgg = schema => ({ + type: EditorStateActionTypes.ADD_NEW_AGG, + payload: { + schema, + }, +}); + +const discardChanges = vis => ({ + type: EditorStateActionTypes.DISCARD_CHANGES, + payload: vis, +}); + +const changeAggType = (aggId, value) => ({ + type: EditorStateActionTypes.CHANGE_AGG_TYPE, + payload: { + aggId, + value, + }, +}); + +const setAggParamValue = (aggId, paramName, value) => ({ + type: EditorStateActionTypes.SET_AGG_PARAM_VALUE, + payload: { + aggId, + paramName, + value, + }, +}); + +const setStateParamValue = (paramName, value) => ({ + type: EditorStateActionTypes.SET_STATE_PARAM_VALUE, + payload: { + paramName, + value, + }, +}); + +export { addNewAgg, discardChanges, changeAggType, setAggParamValue, setStateParamValue }; diff --git a/src/legacy/ui/public/vis/editors/default/state/constants.ts b/src/legacy/ui/public/vis/editors/default/state/constants.ts new file mode 100644 index 00000000000000..42cf520a8b327f --- /dev/null +++ b/src/legacy/ui/public/vis/editors/default/state/constants.ts @@ -0,0 +1,26 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. 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 enum EditorStateActionTypes { + ADD_NEW_AGG = 'ADD_NEW_AGG', + DISCARD_CHANGES = 'DISCARD_CHANGES', + CHANGE_AGG_TYPE = 'CHANGE_AGG_TYPE', + SET_AGG_PARAM_VALUE = 'SET_AGG_PARAM_VALUE', + SET_STATE_PARAM_VALUE = 'SET_STATE_PARAM_VALUE', +} diff --git a/src/legacy/ui/public/vis/editors/default/state/editor_state_context.tsx b/src/legacy/ui/public/vis/editors/default/state/editor_state_context.tsx new file mode 100644 index 00000000000000..13d9b464f9667b --- /dev/null +++ b/src/legacy/ui/public/vis/editors/default/state/editor_state_context.tsx @@ -0,0 +1,45 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. 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 React, { createContext, useContext, useState } from 'react'; + +const EditorStateContext = createContext([{}, () => {}]); + +const EditorStateContextProvider = props => { + const [state, setState] = useState({ isDirty: false }); + + return ( + + {props.children} + + ); +}; + +const useEditorState = () => { + const [editorState, setEditorState] = useContext(EditorStateContext); + + const setDirty = (isDirty: boolean) => setEditorState(state => ({ ...state, isDirty })); + + return { + ...editorState, + setDirty, + }; +}; + +export { useEditorState, EditorStateContextProvider }; diff --git a/src/legacy/ui/public/vis/editors/default/state/index.ts b/src/legacy/ui/public/vis/editors/default/state/index.ts new file mode 100644 index 00000000000000..ce46768add76ff --- /dev/null +++ b/src/legacy/ui/public/vis/editors/default/state/index.ts @@ -0,0 +1,49 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. 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 { useCallback, useEffect, useReducer } from 'react'; +import { editorStateReducer, initEditorState } from './reducers'; +import { EditorStateActionTypes } from './constants'; + +export * from './actions'; +// export * from './reducers'; +export * from './editor_state_context'; + +export function useEditorReducer(vis) { + const [state, dispatch] = useReducer(editorStateReducer, vis, initEditorState); + + const stateDispatch = useCallback( + action => { + vis.emit('dirtyStateChange', { + isDirty: action.type !== EditorStateActionTypes.DISCARD_CHANGES, + }); + + dispatch(action); + }, + [vis] + ); + + // useEffect(() => { + // vis.on('dirtyStateChange', ({ isDirty }) => { + // setDirty(isDirty); + // }); + // }, [vis]); + + return [state, stateDispatch]; +} diff --git a/src/legacy/ui/public/vis/editors/default/state/reducers.ts b/src/legacy/ui/public/vis/editors/default/state/reducers.ts new file mode 100644 index 00000000000000..bd755b3ab50b78 --- /dev/null +++ b/src/legacy/ui/public/vis/editors/default/state/reducers.ts @@ -0,0 +1,104 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. 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 { AggConfigs } from 'ui/agg_types'; +import { Vis } from 'ui/vis'; +import { EditorStateActionTypes } from './constants'; + +function initEditorState(vis: Vis) { + return vis.copyCurrentState(true); +} + +function editorStateReducer(state, action) { + switch (action.type) { + case EditorStateActionTypes.ADD_NEW_AGG: { + const newAggs = [...state.aggs.aggs, state.aggs.createAggConfig(action.payload)]; + + return { + ...state, + aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + }; + } + + case EditorStateActionTypes.DISCARD_CHANGES: { + return initEditorState(action.payload); + } + + case EditorStateActionTypes.CHANGE_AGG_TYPE: { + const { aggId, value } = action.payload; + + const newAggs = state.aggs.aggs.map(agg => { + if (agg.id === aggId) { + const parsedAgg = agg.toJSON(); + + return { + ...parsedAgg, + type: value, + }; + } + + return agg; + }); + + return { + ...state, + aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + }; + } + + case EditorStateActionTypes.SET_AGG_PARAM_VALUE: { + const { aggId, paramName, value } = action.payload; + + const newAggs = state.aggs.aggs.map(agg => { + if (agg.id === aggId) { + const parsedAgg = agg.toJSON(); + + return { + ...parsedAgg, + params: { + ...parsedAgg.params, + [paramName]: value, + }, + }; + } + + return agg; + }); + + return { + ...state, + aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas), + }; + } + + case EditorStateActionTypes.SET_STATE_PARAM_VALUE: { + const { paramName, value } = action.payload; + + return { + ...state, + params: { + ...state.params, + [paramName]: value, + }, + }; + } + } +} + +export { editorStateReducer, initEditorState }; diff --git a/src/legacy/ui/public/vis/editors/default/vis_editor_resizer.js b/src/legacy/ui/public/vis/editors/default/vis_editor_resizer.js deleted file mode 100644 index f2d0d364f6ef78..00000000000000 --- a/src/legacy/ui/public/vis/editors/default/vis_editor_resizer.js +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. 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 $ from 'jquery'; -import { uiModules } from '../../../modules'; -import { keyCodes } from '@elastic/eui'; - -uiModules - .get('kibana') - .directive('visEditorResizer', function () { - return { - restrict: 'E', - link: function ($scope, $el) { - const $left = $el.parent(); - - $el.on('mousedown', function (event) { - $el.addClass('active'); - const startWidth = $left.width(); - const startX = event.pageX; - - function onMove(event) { - const newWidth = startWidth + event.pageX - startX; - $left.width(newWidth); - } - - $(document.body) - .on('mousemove', onMove) - .one('mouseup', () => { - $el.removeClass('active'); - $(document.body).off('mousemove', onMove); - $scope.$broadcast('render'); - }); - }); - - $el.on('keydown', event => { - const { keyCode } = event; - - if (keyCode === keyCodes.LEFT || keyCode === keyCodes.RIGHT) { - event.preventDefault(); - const startWidth = $left.width(); - const newWidth = startWidth + (keyCode === keyCodes.LEFT ? -15 : 15); - $left.width(newWidth); - $scope.$broadcast('render'); - } - }); - } - }; - }); diff --git a/src/legacy/ui/public/vis/editors/default/vis_editor_sidebar.tsx b/src/legacy/ui/public/vis/editors/default/vis_editor_sidebar.tsx index 5f676c16c601b6..db8fd720792259 100644 --- a/src/legacy/ui/public/vis/editors/default/vis_editor_sidebar.tsx +++ b/src/legacy/ui/public/vis/editors/default/vis_editor_sidebar.tsx @@ -24,8 +24,8 @@ import { keyCodes, EuiTabbedContent } from '@elastic/eui'; import { VisEditorNavBar, OptionTab } from './vis_editor_navbar'; import { DefaultEditorDataTab } from './components/data_tab'; -import { safeMakeLabel } from './controls/agg_utils'; import { VisOptionsProps } from './vis_options_props'; +import { setStateParamValue } from './state'; interface VisEditorSideBarProps { hasHistogramAgg?: boolean; @@ -40,7 +40,6 @@ function VisEditorSideBar({ stageEditableVis, state, uiState, - onParamChange, setVisType, removeAgg, reorderAggs, @@ -48,21 +47,12 @@ function VisEditorSideBar({ dispatch, }: VisEditorSideBarProps) { const [selectedTab, setSelectedTab] = useState(optionTabs[0].name); - const [aggsLabels, setAggsLabels] = useState(''); - useEffect(() => { - const labels = state.aggs.aggs - .map(agg => { - return safeMakeLabel(agg); - }) - .join(); - - setAggsLabels(labels); - }); - - const setStateParamValue = useCallback( - (paramName, value) => onParamChange(state.params, paramName, value), - [onParamChange, state.params] + const onStateParamsChange = useCallback( + (paramName, value) => { + dispatch(setStateParamValue(paramName, value)); + }, + [dispatch] ); const setValidity = () => { @@ -82,12 +72,11 @@ function VisEditorSideBar({ const optionTabProps = { aggs: state.aggs, - aggsLabels, hasHistogramAgg, stateParams: state.params, vis, uiState, - setValue: setStateParamValue, + setValue: onStateParamsChange, setValidity, setVisType, setTouched,