Skip to content

Commit 78ccb5e

Browse files
committed
Apply editor form validation
1 parent 0b9ddc0 commit 78ccb5e

11 files changed

Lines changed: 96 additions & 17 deletions

File tree

src/legacy/ui/public/agg_types/agg_config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ export class AggConfig {
125125
public enabled: boolean;
126126
public params: any;
127127
public parent?: AggConfigs;
128+
public brandNew?: boolean;
128129

129130
private __schema: Schema;
130131
private __type: AggType;

src/legacy/ui/public/vis/editors/default/components/agg.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export interface DefaultEditorAggProps extends DefaultEditorAggCommonProps {
4141
isDraggable: boolean;
4242
isLastBucket: boolean;
4343
isRemovable: boolean;
44+
setValidity: (isValid: boolean) => void;
4445
}
4546

4647
function DefaultEditorAgg({

src/legacy/ui/public/vis/editors/default/components/agg_common_props.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,4 @@ export interface DefaultEditorAggCommonProps {
4444
onToggleEnableAgg: (aggId: AggId, isEnable: boolean) => void;
4545
removeAgg: (aggId: AggId) => void;
4646
setTouched: (isTouched: boolean) => void;
47-
setValidity: (isValid: boolean) => void;
4847
}

src/legacy/ui/public/vis/editors/default/components/agg_group.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export interface DefaultEditorAggGroupProps extends DefaultEditorAggCommonProps
4848
schemas: Schema[];
4949
addSchema: AddSchema;
5050
reorderAggs: ReorderAggs;
51+
setValidity(modelName: string, value: boolean): void;
5152
}
5253

5354
function DefaultEditorAggGroup({
@@ -119,7 +120,7 @@ function DefaultEditorAggGroup({
119120
}, [formIsTouched]);
120121

121122
useEffect(() => {
122-
setValidity(isGroupValid);
123+
setValidity(`aggGroup__${groupName}`, isGroupValid);
123124
}, [isGroupValid]);
124125

125126
const onDragEnd: DragDropContextProps['onDragEnd'] = ({ source, destination }) => {

src/legacy/ui/public/vis/editors/default/components/bottom_bar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { EuiBottomBar, EuiFlexGroup, EuiFlexItem, EuiButton, EuiButtonEmpty } fr
2222
import { FormattedMessage } from '@kbn/i18n/react';
2323
import { i18n } from '@kbn/i18n';
2424
import { Vis } from 'ui/vis';
25-
import { discardChanges, EditorAction } from '../state/actions';
25+
import { discardChanges, EditorAction } from '../state';
2626

2727
interface DefaultEditorBottomBarProps {
2828
applyChanges(): void;

src/legacy/ui/public/vis/editors/default/components/sidebar/data_tab.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,24 @@ import {
3535
setAggParamValue,
3636
changeAggType,
3737
toggleEnabledAgg,
38-
} from '../../state/actions';
38+
} from '../../state';
3939
import { ISchemas } from '../../schemas';
4040
import { AddSchema, ReorderAggs, DefaultEditorAggCommonProps } from '../agg_common_props';
4141

4242
export interface DefaultEditorDataTabProps {
4343
dispatch: React.Dispatch<EditorAction>;
44+
formIsTouched: boolean;
4445
metricAggs: AggConfig[];
4546
schemas: ISchemas;
4647
state: VisState;
4748
setTouched(isTouched: boolean): void;
48-
setValidity(isValid: boolean): void;
49+
setValidity(modelName: string, value: boolean): void;
4950
setStateValue: DefaultEditorAggCommonProps['setStateParamValue'];
5051
}
5152

5253
function DefaultEditorDataTab({
5354
dispatch,
55+
formIsTouched,
5456
metricAggs,
5557
schemas,
5658
state,
@@ -96,6 +98,7 @@ function DefaultEditorDataTab({
9698

9799
const commonProps = {
98100
addSchema,
101+
formIsTouched,
99102
lastParentPipelineAggTitle,
100103
metricAggs,
101104
state,
@@ -113,7 +116,6 @@ function DefaultEditorDataTab({
113116
<>
114117
<DefaultEditorAggGroup
115118
data-test-subj="metricsAggGroup"
116-
formIsTouched={false}
117119
groupName={AggGroupNames.Metrics}
118120
schemas={schemas.metrics}
119121
{...commonProps}
@@ -123,7 +125,6 @@ function DefaultEditorDataTab({
123125

124126
<DefaultEditorAggGroup
125127
data-test-subj="bucketsAggGroup"
126-
formIsTouched={false}
127128
groupName={AggGroupNames.Buckets}
128129
schemas={schemas.buckets}
129130
{...commonProps}

src/legacy/ui/public/vis/editors/default/components/sidebar/sidebar.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,29 @@ import { keyCodes } from '@elastic/eui';
2525
import { Vis, VisState } from 'ui/vis';
2626
import { PersistedState } from 'ui/persisted_state';
2727
import { DefaultEditorNavBar, OptionTab } from './navbar';
28-
import { setStateParamValue, EditorAction } from '../../state/actions';
28+
import { setStateParamValue, EditorAction, SetValidity, SetTouched } from '../../state';
2929
import { AggGroupNames } from '../../agg_groups';
3030
import { DefaultEditorAggCommonProps } from '../agg_common_props';
3131

3232
interface DefaultEditorSideBarProps {
33-
dispatch: React.Dispatch<EditorAction>;
3433
applyChanges(): void;
34+
dispatch: React.Dispatch<EditorAction>;
35+
formIsTouched: boolean;
3536
optionTabs: OptionTab[];
37+
setTouched: SetTouched;
38+
setValidity: SetValidity;
3639
state: VisState;
3740
uiState: PersistedState;
3841
vis: Vis;
3942
}
4043

4144
function DefaultEditorSideBar({
42-
dispatch,
4345
applyChanges,
46+
dispatch,
47+
formIsTouched,
4448
optionTabs,
49+
setTouched,
50+
setValidity,
4551
state,
4652
uiState,
4753
vis,
@@ -57,8 +63,9 @@ function DefaultEditorSideBar({
5763
responseAggs,
5864
]);
5965

60-
const setValidity = () => {};
61-
const setTouched = () => {};
66+
const setStateValidity = useCallback((value: boolean) => {
67+
setValidity('visOptions', value);
68+
}, []);
6269

6370
const setStateValue: DefaultEditorAggCommonProps['setStateParamValue'] = useCallback(
6471
(paramName, value) => {
@@ -85,6 +92,7 @@ function DefaultEditorSideBar({
8592

8693
const dataTabProps = {
8794
dispatch,
95+
formIsTouched,
8896
metricAggs,
8997
state,
9098
schemas: vis.type.schemas,
@@ -100,7 +108,7 @@ function DefaultEditorSideBar({
100108
vis,
101109
uiState,
102110
setValue: setStateValue,
103-
setValidity,
111+
setValidity: setStateValidity,
104112
setTouched,
105113
};
106114

src/legacy/ui/public/vis/editors/default/default_editor.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { EditorRenderProps } from 'src/legacy/core_plugins/kibana/public/visuali
2525

2626
import { DefaultEditorSideBar } from './components/sidebar';
2727
import { DefaultEditorBottomBar } from './components/bottom_bar';
28-
import { useEditorReducer, useEditorContext } from './state';
28+
import { useEditorReducer, useEditorContext, useEditorFormState } from './state';
2929
import { DefaultEditorControllerState } from './default_editor_controller';
3030

3131
const sidebarClassName = 'visEditor__collapsibleSidebar';
@@ -44,6 +44,7 @@ function DefaultEditor({
4444
const { vis } = savedObj;
4545
const { isDirty, setDirty } = useEditorContext();
4646
const [state, dispatch] = useEditorReducer(vis);
47+
const { formState, setTouched, setValidity } = useEditorFormState();
4748

4849
useEffect(() => {
4950
async function visualize() {
@@ -85,6 +86,7 @@ function DefaultEditor({
8586
isDirty: false,
8687
});
8788
setDirty(false);
89+
setTouched(true);
8890
}, [vis, state]);
8991

9092
return (
@@ -110,11 +112,14 @@ function DefaultEditor({
110112
ref={sidebarRef}
111113
>
112114
<DefaultEditorSideBar
115+
applyChanges={applyChanges}
113116
dispatch={dispatch}
117+
formIsTouched={formState.touched}
114118
optionTabs={optionTabs}
115-
applyChanges={applyChanges}
116-
vis={vis}
119+
setTouched={setTouched}
120+
setValidity={setValidity}
117121
state={state}
122+
vis={vis}
118123
uiState={uiState}
119124
/>
120125
</div>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import { useState, useCallback } from 'react';
21+
22+
export type SetValidity = (modelName: string, value: boolean) => void;
23+
export type SetTouched = (value: boolean) => void;
24+
25+
function useEditorFormState() {
26+
const [formState, setFormState] = useState({
27+
validity: {},
28+
touched: false,
29+
});
30+
31+
const setValidity: SetValidity = useCallback((modelName, value) => {
32+
setFormState(model => ({
33+
...model,
34+
validity: {
35+
...model.validity,
36+
[modelName]: value,
37+
},
38+
}));
39+
}, []);
40+
41+
const setTouched = useCallback(
42+
(touched: boolean) =>
43+
setFormState(model => ({
44+
...model,
45+
touched,
46+
})),
47+
[]
48+
);
49+
50+
return {
51+
formState,
52+
setValidity,
53+
setTouched,
54+
};
55+
}
56+
57+
export { useEditorFormState };

src/legacy/ui/public/vis/editors/default/state/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import { EditorStateActionTypes } from './constants';
2424
import { EditorAction } from './actions';
2525

2626
export * from './editor_state_context';
27+
export * from './editor_form_state';
28+
export * from './actions';
2729

2830
export function useEditorReducer(vis: Vis): [VisState, React.Dispatch<EditorAction>] {
2931
const [state, dispatch] = useReducer(editorStateReducer, vis, initEditorState);

0 commit comments

Comments
 (0)