diff --git a/src/plugins/vis_default_editor/public/components/agg_common_props.ts b/src/plugins/vis_default_editor/public/components/agg_common_props.ts index 5364be4df6d..0ef9c16f617 100644 --- a/src/plugins/vis_default_editor/public/components/agg_common_props.ts +++ b/src/plugins/vis_default_editor/public/components/agg_common_props.ts @@ -43,7 +43,7 @@ export interface DefaultEditorCommonProps { formIsTouched: boolean; groupName: AggGroupName; metricAggs: IAggConfig[]; - state: EditorVisState; + state: Partial; setAggParamValue: ( aggId: AggId, paramName: T, diff --git a/src/plugins/vis_default_editor/public/index.ts b/src/plugins/vis_default_editor/public/index.ts index af0b54956a9..88769ac71f9 100644 --- a/src/plugins/vis_default_editor/public/index.ts +++ b/src/plugins/vis_default_editor/public/index.ts @@ -31,6 +31,7 @@ export { DefaultEditorController } from './default_editor_controller'; export { useValidation } from './components/controls/utils'; export { RangesParamEditor, RangeValues } from './components/controls/ranges'; +export { DefaultEditorAggParams } from './components/agg_params'; export * from './editor_size'; export * from './vis_options_props'; export * from './utils'; diff --git a/src/plugins/wizard/public/application/contributions/containers/data_tab/config_panel.scss b/src/plugins/wizard/public/application/contributions/containers/data_tab/config_panel.scss index 90dd89f1e3b..b088dca2822 100644 --- a/src/plugins/wizard/public/application/contributions/containers/data_tab/config_panel.scss +++ b/src/plugins/wizard/public/application/contributions/containers/data_tab/config_panel.scss @@ -22,6 +22,10 @@ padding: $euiSizeS; } + &__aggEditor { + padding: 0 $euiSizeM; + } + &--secondary { position: absolute; top: 0; @@ -31,4 +35,4 @@ &.showSecondary > .wizConfig__section { transform: translateX(-100%); } -} \ No newline at end of file +} diff --git a/src/plugins/wizard/public/application/contributions/containers/data_tab/config_panel.tsx b/src/plugins/wizard/public/application/contributions/containers/data_tab/config_panel.tsx index a5fc6a9fef3..07683666eb7 100644 --- a/src/plugins/wizard/public/application/contributions/containers/data_tab/config_panel.tsx +++ b/src/plugins/wizard/public/application/contributions/containers/data_tab/config_panel.tsx @@ -4,101 +4,26 @@ */ import { EuiForm } from '@elastic/eui'; -import React, { useMemo, useState } from 'react'; +import React from 'react'; import { useVisualizationType } from '../../../utils/use'; -import { - DropboxContribution, - MainItemContribution, - SecondaryItemContribution, - TitleItemContribution, - ITEM_TYPES, -} from './items'; import { useTypedSelector } from '../../../utils/state_management'; -import { mapItemToPanelComponents } from './utils/item_to_panel'; -import { ItemTypes } from '../../constants'; -import { SelectContribution } from '../common/items'; -import { INDEX_FIELD_KEY } from './items/use/use_form_field'; -import { DATA_TAB_ID } from '.'; import './config_panel.scss'; import { mapSchemaToAggPanel } from './utils/schema_to_dropbox'; -import { useOpenSearchDashboards } from '../../../../../../opensearch_dashboards_react/public'; -import { WizardServices } from '../../../../types'; import { SecondaryPanel } from './secondary_panel'; -const DEFAULT_ITEMS: MainItemContribution[] = [getTitleContribution()]; - export function ConfigPanel() { const vizType = useVisualizationType(); - const activeAgg = useTypedSelector((state) => state.visualization.activeVisualization?.activeAgg); + const draftAgg = useTypedSelector((state) => state.visualization.activeVisualization?.draftAgg); const schemas = vizType.ui.containerConfig.data.schemas; - // TODO: Will cleanup when add and edit field support is re introduced - // const activeItem = useTypedSelector((state) => state.config.activeItem); - // const configItemState = useTypedSelector((state) => state.config.items[activeItem?.id || '']); - - // const hydratedItems: MainItemContribution[] = useMemo( - // () => [...(items?.[DATA_TAB_ID] ?? []), ...DEFAULT_ITEMS], - // [items] - // ); - - // const mainPanel = useMemo(() => mapItemToPanelComponents(hydratedItems), [hydratedItems]); - // const secondaryPanel = useMemo(() => { - // if (!activeItem || !configItemState || typeof configItemState === 'string') return; - - // // Generate each secondary panel base on active item type - // if (activeItem.type === ITEM_TYPES.DROPBOX) { - // const activeDropboxContribution = hydratedItems.find( - // (item: MainItemContribution) => - // item.type === ITEM_TYPES.DROPBOX && item?.id === activeItem?.id - // ) as DropboxContribution | undefined; - - // if (!activeDropboxContribution) return null; - - // let itemsToRender: SecondaryItemContribution[] = [ - // getTitleContribution(activeDropboxContribution.label), - // getFieldSelectorContribution(), - // ]; - - // const dropboxFieldInstance = configItemState.instances.find( - // ({ id }) => id === activeItem.instanceId - // ); - // if (dropboxFieldInstance && dropboxFieldInstance.properties.fieldName) { - // itemsToRender = [...itemsToRender, ...activeDropboxContribution.items]; - // } - - // return mapItemToPanelComponents(itemsToRender, true); - // } - // }, [activeItem, configItemState, hydratedItems]); - if (!schemas) return null; const mainPanel = mapSchemaToAggPanel(schemas); return ( - +
{mainPanel}
); } - -function getTitleContribution(title?: string): TitleItemContribution { - return { - type: ITEM_TYPES.TITLE, - title: [title, 'Configuration'].join(' '), - }; -} - -// function getFieldSelectorContribution(): SelectContribution { -// return { -// type: ItemTypes.SELECT, -// id: INDEX_FIELD_KEY, -// label: 'Select a Field', -// options: (state) => { -// return state.dataSource.visualizableFields.map((field) => ({ -// value: field.name, -// inputDisplay: field.displayName, -// })); -// }, -// }; -// } diff --git a/src/plugins/wizard/public/application/contributions/containers/data_tab/items/dropbox.tsx b/src/plugins/wizard/public/application/contributions/containers/data_tab/items/dropbox.tsx index 8639340c3a4..29dda2cfd9c 100644 --- a/src/plugins/wizard/public/application/contributions/containers/data_tab/items/dropbox.tsx +++ b/src/plugins/wizard/public/application/contributions/containers/data_tab/items/dropbox.tsx @@ -11,11 +11,9 @@ import { EuiFormRow, EuiPanel, EuiText, - euiDragDropReorder, DropResult, } from '@elastic/eui'; import React, { useCallback } from 'react'; -import { FieldIcon } from '../../../../../../../opensearch_dashboards_react/public'; import { IDropAttributes, IDropState } from '../../../../utils/drag_drop'; import './dropbox.scss'; import { DropboxDisplay } from './types'; @@ -70,11 +68,9 @@ const DropboxComponent = ({
- {fields.map(({ id, label, icon }, index) => ( + {fields.map(({ id, label }, index) => ( - {/* TODO: Verify if field icon makes sense here */} - {/* */} onEditField(id)}> {label} diff --git a/src/plugins/wizard/public/application/contributions/containers/data_tab/items/types.ts b/src/plugins/wizard/public/application/contributions/containers/data_tab/items/types.ts index 3133fd4f39b..5a5c14e4e2d 100644 --- a/src/plugins/wizard/public/application/contributions/containers/data_tab/items/types.ts +++ b/src/plugins/wizard/public/application/contributions/containers/data_tab/items/types.ts @@ -4,7 +4,6 @@ */ import { IndexPatternField } from 'src/plugins/data/common'; -import { FieldIconProps } from '../../../../../../../opensearch_dashboards_react/public'; import { SelectContribution, InputContribution } from '../../common/items'; /** @@ -31,7 +30,6 @@ export interface TitleItemContribution { export interface DropboxDisplay { label: string; - icon: FieldIconProps['type']; id: string; } export interface DropboxFieldProps { @@ -49,7 +47,7 @@ export interface DropboxContribution { display?: ( indexField: IndexPatternField, state: DropboxFieldProps - ) => Pick; + ) => Pick; // Defines how the initial state of a field should be set when a field is dropped onto it onDrop?: (field: IndexPatternField) => DropboxFieldProps; isDroppable?: (field: IndexPatternField) => boolean; diff --git a/src/plugins/wizard/public/application/contributions/containers/data_tab/items/use/use_dropbox.tsx b/src/plugins/wizard/public/application/contributions/containers/data_tab/items/use/use_dropbox.tsx index 4ef732ad84b..c966767b485 100644 --- a/src/plugins/wizard/public/application/contributions/containers/data_tab/items/use/use_dropbox.tsx +++ b/src/plugins/wizard/public/application/contributions/containers/data_tab/items/use/use_dropbox.tsx @@ -5,22 +5,16 @@ import { useCallback, useMemo } from 'react'; import { cloneDeep } from 'lodash'; -import { CreateAggConfigParams, IndexPatternField } from 'src/plugins/data/common'; +import { IndexPatternField } from 'src/plugins/data/common'; import { Schema } from '../../../../../../../../vis_default_editor/public'; import { FieldDragDataType } from '../../../../../utils/drag_drop/types'; import { useTypedDispatch, useTypedSelector } from '../../../../../utils/state_management'; -import { - DropboxContribution, - DropboxState, - ITEM_TYPES, - DropboxDisplay, - DropboxFieldProps, -} from '../types'; +import { DropboxState, DropboxDisplay } from '../types'; import { DropboxProps } from '../dropbox'; import { useDrop } from '../../../../../utils/drag_drop'; import { - createAggConfigParams, - reorderAggConfigParams, + editAgg, + reorderAgg, updateAggConfigParams, } from '../../../../../utils/state_management/visualization_slice'; import { useIndexPattern } from '../../../../../../application/utils/use/use_index_pattern'; @@ -54,7 +48,7 @@ export const useDropbox = (props: UseDropboxProps): DropboxProps => { return indexPattern && aggService.createAggConfigs(indexPattern, cloneDeep(aggConfigParams)); }, [aggConfigParams, aggService, indexPattern]); - const aggs = aggConfigs?.aggs ?? []; + const aggs = useMemo(() => aggConfigs?.aggs ?? [], [aggConfigs?.aggs]); const dropboxAggs = aggs.filter((agg) => agg.schema === schema.name); @@ -63,7 +57,6 @@ export const useDropbox = (props: UseDropboxProps): DropboxProps => { dropboxAggs?.map( (agg): DropboxDisplay => ({ id: agg.id, - icon: 'number', // TODO: Check if we still need an icon here label: agg.makeLabel(), }) ) || [], @@ -72,22 +65,45 @@ export const useDropbox = (props: UseDropboxProps): DropboxProps => { // Event handlers for each dropbox action type const onAddField = useCallback(() => { - const agg = aggConfigs?.createAggConfig( + if (!aggConfigs || !indexPattern) { + throw new Error('Cannot create new field, missing parameters'); + } + + const aggConfig = aggConfigs.createAggConfig( { - type: (schema.defaults as any).aggType, schema: schema.name, - }, + // using any since createAggConfig requires the type property but when an agg is brandNew, this has to be skipped. + // TODO: Update createAggConfig typing to correctly handle missing type field + } as any, { addToAggConfigs: false, } ); - if (agg) { - dispatch(createAggConfigParams(agg.serialize())); + aggConfig.brandNew = true; + const newAggs = [...aggs, aggConfig]; + const newAggConfigs = aggService.createAggConfigs(indexPattern, cloneDeep(newAggs)); + const newAggConfig = newAggConfigs.aggs.find((agg) => agg.brandNew); + + if (!newAggConfig) { + throw new Error('Missing new aggConfig'); } - }, [aggConfigs, dispatch, schema.defaults, schema.name]); - const onEditField = useCallback((instanceId) => {}, []); + dispatch(editAgg(newAggConfig.serialize())); + }, [aggConfigs, aggService, aggs, dispatch, indexPattern, schema.name]); + + const onEditField = useCallback( + (aggId) => { + const aggConfig = aggConfigs?.aggs.find((agg) => agg.id === aggId); + + if (!aggConfig) { + throw new Error('Could not find agg in aggConfigs'); + } + + dispatch(editAgg(aggConfig.serialize())); + }, + [aggConfigs?.aggs, dispatch] + ); const onDeleteField = useCallback( (aggId: string) => { @@ -124,7 +140,7 @@ export const useDropbox = (props: UseDropboxProps): DropboxProps => { const onReorderField = useCallback( ({ sourceAggId, destinationAggId }) => { dispatch( - reorderAggConfigParams({ + reorderAgg({ sourceId: sourceAggId, destinationId: destinationAggId, }) @@ -164,148 +180,6 @@ export const useDropbox = (props: UseDropboxProps): DropboxProps => { isValidDropTarget: isValidDropField, dropProps, }; - - // TODO: Will cleanup once add and edit field support is reintroduced - // const configItemState = items[dropboxId]; - // const dropboxState = - // !configItemState || typeof configItemState === 'string' ? INITIAL_STATE : configItemState; - // const filterPatrialInstances = useCallback( - // ({ properties }: DropboxInstanceState) => !!properties.fieldName, - // [] - // ); - // const mapInstanceToFieldDisplay = useCallback( - // ({ id, properties }: DropboxInstanceState): DropboxDisplay => { - // const indexPatternField = availableFields.find(({ name }) => name === properties.fieldName); - - // if (!indexPatternField) throw new Error('Field to display missing in available fields'); - - // return getDisplayField(id, indexPatternField, properties, display); - // }, - // [availableFields, display] - // ); - - // const displayFields: DropboxDisplay[] = useMemo( - // () => dropboxState.instances.filter(filterPatrialInstances).map(mapInstanceToFieldDisplay), - // [dropboxState.instances, filterPatrialInstances, mapInstanceToFieldDisplay] - // ); - - // Event handlers for each dropbox action type - // const onAddField = useCallback(() => { - // dispatch(addInstance(dropboxId, ITEM_TYPES.DROPBOX)); - // }, [dispatch, dropboxId]); - - // const onEditField = useCallback( - // (instanceId) => { - // dispatch( - // setActiveItem({ - // id: dropboxId, - // type: ITEM_TYPES.DROPBOX, - // instanceId, - // }) - // ); - // }, - // [dispatch, dropboxId] - // ); - - // const onDeleteField = useCallback( - // (instanceId) => { - // dispatch( - // updateInstance({ - // id: dropboxId, - // instanceId, - // instanceState: null, - // }) - // ); - // }, - // [dispatch, dropboxId] - // ); - - // const onDropField = useCallback( - // (data: FieldDragDataType['value']) => { - // if (!data) return; - - // const { name: fieldName } = data; - // const indexField = getIndexPatternField(fieldName, availableFields); - - // if (!indexField) return; - - // if (isDroppable && !isDroppable(indexField)) return; - - // const newState: DropboxFieldProps = { - // ...onDrop?.(indexField), - // fieldName, - // }; - - // dispatch(addInstance(dropboxId, ITEM_TYPES.DROPBOX, false, newState)); - // }, - // [availableFields, isDroppable, onDrop, dispatch, dropboxId] - // ); - - // const onReorderField = useCallback( - // (reorderedInstanceIds: string[]) => { - // dispatch( - // reorderInstances({ - // id: dropboxId, - // reorderedInstanceIds, - // }) - // ); - // }, - // [dispatch, dropboxId] - // ); - - // const [dropProps, { isValidDropTarget, dragData, ...dropState }] = useDrop( - // 'field-data', - // onDropField - // ); - - // const isValidDropField = useMemo(() => { - // if (!dragData) return false; - - // const indexField = getIndexPatternField(dragData.name, availableFields); - - // if (!indexField) return false; - - // return isValidDropTarget && (isDroppable?.(indexField) ?? true); - // }, [availableFields, dragData, isDroppable, isValidDropTarget]); - - // return { - // id: dropboxId, - // label, - // limit, - // fields: displayFields, - // onAddField, - // onEditField, - // onDeleteField, - // onReorderField, - // ...dropState, - // dragData, - // isValidDropTarget: isValidDropField, - // dropProps, - // }; -}; - -const getDisplayField = ( - instanceId: string, - indexField: IndexPatternField, - properties: DropboxFieldProps, - display: DropboxContribution['display'] -): DropboxDisplay => { - let displayField: DropboxDisplay = { - id: instanceId, - icon: indexField.type, - label: indexField.displayName, - }; - if (display) { - const { icon, label } = display(indexField, properties); - - displayField = { - ...displayField, - icon, - label, - }; - } - - return displayField; }; const getIndexPatternField = (indexFieldName: string, availableFields: IndexPatternField[]) => diff --git a/src/plugins/wizard/public/application/contributions/containers/data_tab/secondary_panel.tsx b/src/plugins/wizard/public/application/contributions/containers/data_tab/secondary_panel.tsx index de808c4c5fd..d896116a445 100644 --- a/src/plugins/wizard/public/application/contributions/containers/data_tab/secondary_panel.tsx +++ b/src/plugins/wizard/public/application/contributions/containers/data_tab/secondary_panel.tsx @@ -3,17 +3,86 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React from 'react'; -import { useTypedSelector } from '../../../utils/state_management'; +import React, { useCallback, useMemo, useState } from 'react'; +import { cloneDeep } from 'lodash'; +import { useTypedDispatch, useTypedSelector } from '../../../utils/state_management'; +import { DefaultEditorAggParams } from '../../../../../../vis_default_editor/public'; import { Title } from './items'; +import { useIndexPattern, useVisualizationType } from '../../../utils/use'; +import { useOpenSearchDashboards } from '../../../../../../opensearch_dashboards_react/public'; +import { WizardServices } from '../../../../types'; +import { IAggType } from '../../../../../../data/public'; +import { saveAgg, editAgg } from '../../../utils/state_management/visualization_slice'; export function SecondaryPanel() { - const activeAgg = useTypedSelector((state) => state.visualization.activeVisualization?.activeAgg); + const draftAgg = useTypedSelector((state) => state.visualization.activeVisualization!.draftAgg); + const [valid, setValid] = useState(true); + const [touched, setTouched] = useState(false); + const dispatch = useTypedDispatch(); + const vizType = useVisualizationType(); + const indexPattern = useIndexPattern(); + const { + services: { + data: { + search: { aggs: aggService }, + }, + }, + } = useOpenSearchDashboards(); + const schemas = vizType.ui.containerConfig.data.schemas.all; + + const aggConfigs = useMemo(() => { + return ( + indexPattern && draftAgg && aggService.createAggConfigs(indexPattern, [cloneDeep(draftAgg)]) + ); + }, [draftAgg, aggService, indexPattern]); + + const aggConfig = aggConfigs?.aggs[0]; + + const groupName = useMemo( + () => schemas.find((schema) => schema.name === aggConfig?.schema)?.group, + [aggConfig?.schema, schemas] + ); + + const showAggParamEditor = !!(aggConfig && indexPattern); + + const closeMenu = useCallback(() => { + // Save the agg if valid else discard + dispatch(saveAgg(valid)); + }, [dispatch, valid]); return (
- - <div>{JSON.stringify(activeAgg)}</div> + <Title title="Test" isSecondary closeMenu={closeMenu} /> + {showAggParamEditor && ( + <DefaultEditorAggParams + className="wizConfig__aggEditor" + agg={aggConfig!} + indexPattern={indexPattern!} + setValidity={setValid} + setTouched={setTouched} + schemas={schemas} + formIsTouched={false} + groupName={groupName ?? 'none'} + metricAggs={[]} + state={{ + data: {}, + description: 'Falalala', + title: 'Title for the aggParams', + }} + setAggParamValue={function <T extends string | number | symbol>( + aggId: string, + paramName: T, + value: any + ): void { + aggConfig.params[paramName] = value; + dispatch(editAgg(aggConfig.serialize())); + }} + onAggTypeChange={function (aggId: string, aggType: IAggType): void { + aggConfig.type = aggType; + dispatch(editAgg(aggConfig.serialize())); + }} + /> + )} </div> ); } diff --git a/src/plugins/wizard/public/application/utils/state_management/visualization_slice.ts b/src/plugins/wizard/public/application/utils/state_management/visualization_slice.ts index b5a4b4e9332..d18396197a2 100644 --- a/src/plugins/wizard/public/application/utils/state_management/visualization_slice.ts +++ b/src/plugins/wizard/public/application/utils/state_management/visualization_slice.ts @@ -13,7 +13,7 @@ interface VisualizationState { activeVisualization?: { name: string; aggConfigParams: CreateAggConfigParams[]; - activeAgg?: CreateAggConfigParams; + draftAgg?: CreateAggConfigParams; }; } @@ -59,15 +59,28 @@ export const slice = createSlice({ setSearchField: (state, action: PayloadAction<string>) => { state.searchField = action.payload; }, - createAggConfigParams: (state, action: PayloadAction<CreateAggConfigParams>) => { - state.activeVisualization!.activeAgg = action.payload; + editAgg: (state, action: PayloadAction<CreateAggConfigParams>) => { + state.activeVisualization!.draftAgg = action.payload; }, - saveAggConfigParams: (state, action: PayloadAction<CreateAggConfigParams>) => { - delete state.activeVisualization!.activeAgg; + saveAgg: (state, action: PayloadAction<boolean>) => { + const saveDraft = action.payload; + const draftAgg = state.activeVisualization!.draftAgg; - // TODO: Impliment reducer + // Delete the aggConfigParam if the save is not true + if (saveDraft && draftAgg) { + const aggIndex = state.activeVisualization!.aggConfigParams.findIndex( + (agg) => agg.id === draftAgg.id + ); + + if (aggIndex === -1) { + state.activeVisualization!.aggConfigParams.push(draftAgg); + } else { + state.activeVisualization!.aggConfigParams.splice(aggIndex, 1, draftAgg); + } + } + delete state.activeVisualization!.draftAgg; }, - reorderAggConfigParams: ( + reorderAgg: ( state, action: PayloadAction<{ sourceId: string; @@ -100,7 +113,8 @@ export const { setActiveVisualization, setIndexPattern, setSearchField, - createAggConfigParams, + editAgg, updateAggConfigParams, - reorderAggConfigParams, + saveAgg, + reorderAgg, } = slice.actions; diff --git a/src/plugins/wizard/public/visualizations/metric/components/metric_viz_options.tsx b/src/plugins/wizard/public/visualizations/metric/components/metric_viz_options.tsx index acfaab04580..b5ef3bdb75c 100644 --- a/src/plugins/wizard/public/visualizations/metric/components/metric_viz_options.tsx +++ b/src/plugins/wizard/public/visualizations/metric/components/metric_viz_options.tsx @@ -5,19 +5,43 @@ import React, { useCallback } from 'react'; import { i18n } from '@osd/i18n'; -import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { EuiButtonGroup, EuiFormRow, EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from 'react-intl'; import produce from 'immer'; import { Draft } from 'immer'; import { + ColorModes, ColorRanges, + ColorSchemaOptions, + colorSchemas, RangeOption, - SetColorRangeValue, SwitchOption, } from '../../../../../charts/public'; import { useTypedDispatch, useTypedSelector } from '../../../application/utils/state_management'; import { MetricOptionsDefaults } from '../metric_viz_type'; import { setState } from '../../../application/utils/state_management/style_slice'; +import { PersistedState } from '../../../../../visualizations/public'; + +const METRIC_COLOR_MODES = [ + { + id: ColorModes.NONE, + label: i18n.translate('visTypeMetric.colorModes.noneOptionLabel', { + defaultMessage: 'None', + }), + }, + { + id: ColorModes.LABELS, + label: i18n.translate('visTypeMetric.colorModes.labelsOptionLabel', { + defaultMessage: 'Labels', + }), + }, + { + id: ColorModes.BACKGROUND, + label: i18n.translate('visTypeMetric.colorModes.backgroundOptionLabel', { + defaultMessage: 'Background', + }), + }, +]; function MetricVizOptions() { const styleState = useTypedSelector((state) => state.style) as MetricOptionsDefaults; @@ -32,8 +56,12 @@ function MetricVizOptions() { [dispatch, styleState] ); + const metricColorModeLabel = i18n.translate('visTypeMetric.params.color.useForLabel', { + defaultMessage: 'Use color for', + }); + return ( - <div> + <EuiPanel paddingSize="s" hasShadow={false} hasBorder={false} color="transparent"> <EuiPanel paddingSize="s"> <EuiTitle size="xs"> <h3> @@ -71,8 +99,7 @@ function MetricVizOptions() { <EuiSpacer size="s" /> - {/* TODO: Reintroduce the other style properties */} - {/* <EuiPanel paddingSize="s"> + <EuiPanel paddingSize="s"> <EuiTitle size="xs"> <h3> <FormattedMessage id="visTypeMetric.params.rangesTitle" defaultMessage="Ranges" /> @@ -83,9 +110,13 @@ function MetricVizOptions() { <ColorRanges data-test-subj="metricColorRange" colorsRange={metric.colorsRange} - setValue={setMetric('labels') as SetColorRangeValue} - setTouched={setMetric('touched')} - setValidity={setMetric('validity')} + setValue={(_, value) => + setOption((draft) => { + draft.metric.colorsRange = value; + }) + } + setTouched={() => {}} + setValidity={() => {}} /> <EuiFormRow fullWidth display="rowCompressed" label={metricColorModeLabel}> @@ -95,26 +126,33 @@ function MetricVizOptions() { isDisabled={metric.colorsRange.length === 1} isFullWidth={true} legend={metricColorModeLabel} - options={vis.type.editorConfig.collections.metricColorMode} - onChange={setColorMode} + options={METRIC_COLOR_MODES} + onChange={(value) => + setOption((draft) => { + draft.metric.metricColorMode = value as ColorModes; + }) + } /> </EuiFormRow> <ColorSchemaOptions colorSchema={metric.colorSchema} - colorSchemas={vis.type.editorConfig.collections.colorSchemas} - disabled={ - metric.colorsRange.length === 1 || - metric.metricColorMode === ColorModes.NONE - } + colorSchemas={colorSchemas} + disabled={metric.colorsRange.length === 1 || metric.metricColorMode === ColorModes.NONE} invertColors={metric.invertColors} - setValue={setMetricValue as SetColorSchemaOptionsValue} + setValue={(paramName, value) => + setOption((draft) => { + // The paramName and associated value are expected to pair correctly but will be messy to type correctly + draft.metric[paramName] = value as any; + }) + } showHelpText={false} - uiState={uiState} + // uistate here is used for custom colors which is not currently supported. Update when supported + uiState={new PersistedState({})} /> </EuiPanel> - <EuiSpacer size="s" /> */} + <EuiSpacer size="s" /> <EuiPanel paddingSize="s"> <EuiTitle size="xs"> @@ -142,7 +180,7 @@ function MetricVizOptions() { showValue={false} /> </EuiPanel> - </div> + </EuiPanel> ); } diff --git a/src/plugins/wizard/public/visualizations/metric/metric_viz_type.ts b/src/plugins/wizard/public/visualizations/metric/metric_viz_type.ts index eabd9df1cb2..406984f87ec 100644 --- a/src/plugins/wizard/public/visualizations/metric/metric_viz_type.ts +++ b/src/plugins/wizard/public/visualizations/metric/metric_viz_type.ts @@ -4,7 +4,7 @@ */ import { i18n } from '@osd/i18n'; -import { Schemas } from '../../../../vis_default_editor/public'; +import { RangeValues, Schemas } from '../../../../vis_default_editor/public'; import { AggGroupNames } from '../../../../data/public'; import { ColorModes, ColorSchemas } from '../../../../charts/public'; import { MetricVizOptions } from './components/metric_viz_options'; @@ -20,7 +20,7 @@ export interface MetricOptionsDefaults { useRanges: boolean; colorSchema: ColorSchemas; metricColorMode: ColorModes; - colorsRange: [{ from: number; to: number }]; + colorsRange: RangeValues[]; labels: { show: boolean; };