diff --git a/src/plugins/wizard/public/application/app.scss b/src/plugins/wizard/public/application/app.scss index 5748cc4464cd..f38959445100 100644 --- a/src/plugins/wizard/public/application/app.scss +++ b/src/plugins/wizard/public/application/app.scss @@ -7,10 +7,9 @@ .wizLayout { padding: 0; display: grid; - grid-template: min-content 1fr / #{$wizSideNavWidth} 1fr; - grid-template-areas: - "topNav topNav" - "sideNav workspace"; + grid-template: + "topNav topNav topNav" min-content + "leftNav workspace rightNav" 1fr / #{$wizSideNavWidth} 1fr #{$wizSideNavWidth}; height: calc(100vh - #{$osdHeaderOffset}); } diff --git a/src/plugins/wizard/public/application/app.tsx b/src/plugins/wizard/public/application/app.tsx index 7c83e152418a..9c93dcb1b552 100644 --- a/src/plugins/wizard/public/application/app.tsx +++ b/src/plugins/wizard/public/application/app.tsx @@ -7,10 +7,11 @@ import React from 'react'; import { I18nProvider } from '@osd/i18n/react'; import { EuiPage } from '@elastic/eui'; import { DragDropProvider } from './utils/drag_drop/drag_drop_context'; -import { SideNav } from './components/side_nav'; +import { LeftNav } from './components/left_nav'; import { TopNav } from './components/top_nav'; import { Workspace } from './components/workspace'; import './app.scss'; +import { RightNav } from './components/right_nav'; export const WizardApp = () => { // Render the application DOM. @@ -19,10 +20,13 @@ export const WizardApp = () => { - + + ); }; + +export { Option } from './components/option'; diff --git a/src/plugins/wizard/public/application/components/data_source_select.tsx b/src/plugins/wizard/public/application/components/data_source_select.tsx index 08c4f86008bf..c51aa40a08e2 100644 --- a/src/plugins/wizard/public/application/components/data_source_select.tsx +++ b/src/plugins/wizard/public/application/components/data_source_select.tsx @@ -29,6 +29,7 @@ export const DataSourceSelect = () => { const { indexPatterns, loading, error, selected } = useIndexPatterns(); const dispatch = useTypedDispatch(); + // TODO: Should be a standard EUI component return ( { + return ( +
+
+ +
+ +
+ ); +}; diff --git a/src/plugins/wizard/public/application/components/option.scss b/src/plugins/wizard/public/application/components/option.scss new file mode 100644 index 000000000000..8bb394c260e8 --- /dev/null +++ b/src/plugins/wizard/public/application/components/option.scss @@ -0,0 +1,8 @@ +.wizOption { + background-color: $euiColorEmptyShade; + padding: $euiSizeM; + + & &__panel { + background-color: $euiColorLightestShade; + } +} diff --git a/src/plugins/wizard/public/application/components/option.tsx b/src/plugins/wizard/public/application/components/option.tsx new file mode 100644 index 000000000000..7440bb0825c0 --- /dev/null +++ b/src/plugins/wizard/public/application/components/option.tsx @@ -0,0 +1,32 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { EuiAccordion, EuiHorizontalRule, EuiPanel, EuiSpacer } from '@elastic/eui'; +import React, { FC } from 'react'; +import './option.scss'; + +interface Props { + title: string; + initialIsOpen?: boolean; +} + +export const Option: FC = ({ title, children, initialIsOpen = false }) => { + return ( + <> + + + + {children} + + + + + ); +}; diff --git a/src/plugins/wizard/public/application/components/right_nav.tsx b/src/plugins/wizard/public/application/components/right_nav.tsx new file mode 100644 index 000000000000..bbd1ce844c2c --- /dev/null +++ b/src/plugins/wizard/public/application/components/right_nav.tsx @@ -0,0 +1,57 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { EuiSuperSelect, EuiSuperSelectOption, EuiIcon, IconType } from '@elastic/eui'; +import { useVisualizationType } from '../utils/use'; +import './side_nav.scss'; +import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public'; +import { WizardServices } from '../../types'; +import { setActiveVisualization, useTypedDispatch } from '../utils/state_management'; + +export const RightNav = () => { + const { + services: { types }, + } = useOpenSearchDashboards(); + const { ui, name: activeVisName } = useVisualizationType(); + const dispatch = useTypedDispatch(); + const StyleSection = ui.containerConfig.style.render; + + const options: Array> = types.all().map(({ name, icon, title }) => ({ + value: name, + inputDisplay: , + dropdownDisplay: , + })); + + return ( +
+
+ { + dispatch( + setActiveVisualization({ + name, + style: types.get(name)?.ui.containerConfig.style.defaults, + }) + ); + }} + fullWidth + /> +
+
+ +
+
+ ); +}; + +const OptionItem = ({ icon, title }: { icon: IconType; title: string }) => ( + <> + + {title} + +); diff --git a/src/plugins/wizard/public/application/components/side_nav.scss b/src/plugins/wizard/public/application/components/side_nav.scss index 021cd34ce190..5fade4b11b4d 100644 --- a/src/plugins/wizard/public/application/components/side_nav.scss +++ b/src/plugins/wizard/public/application/components/side_nav.scss @@ -8,8 +8,29 @@ .wizSidenav { @include scrollNavParent(auto 1fr); - grid-area: sideNav; - border-right: $euiBorderThin; + &.left { + border-right: $euiBorderThin; + grid-area: leftNav; + } + + &.right { + border-left: $euiBorderThin; + grid-area: rightNav; + } + + &__header { + padding: $euiSizeS; + border-bottom: $euiBorderThin; + background-color: $euiColorEmptyShade; + } + + &__style { + @include euiYScrollWithShadows; + } +} + +.wizTypeSelector__icon { + margin-right: $euiSizeS; } .wizSidenavTabs { @@ -25,6 +46,5 @@ } .wizDatasourceSelect { - max-width: $wizSideNavWidth; - padding: $euiSize $euiSize 0 $euiSize; + max-width: calc(#{$wizSideNavWidth} - 1px); } diff --git a/src/plugins/wizard/public/application/components/side_nav.tsx b/src/plugins/wizard/public/application/components/side_nav.tsx deleted file mode 100644 index 4e4291f1c447..000000000000 --- a/src/plugins/wizard/public/application/components/side_nav.tsx +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { ReactElement } from 'react'; -import { EuiTabbedContent, EuiTabbedContentTab } from '@elastic/eui'; -import './side_nav.scss'; -import { useVisualizationType } from '../utils/use'; -import { DataSourceSelect } from './data_source_select'; -import { DataTab } from './data_tab'; -import { StyleTabConfig } from '../../services/type_service'; - -export const SideNav = () => { - const { - ui: { containerConfig }, - } = useVisualizationType(); - - const tabs: EuiTabbedContentTab[] = Object.entries(containerConfig).map( - ([containerName, config]) => { - let content: null | ReactElement = null; - switch (containerName) { - case 'data': - content = ; - break; - - case 'style': - content = (config as StyleTabConfig).render(); - break; - } - - return { - id: containerName, - name: containerName, - content, - }; - } - ); - - return ( -
-
- -
- -
- ); -}; diff --git a/src/plugins/wizard/public/application/components/workspace.tsx b/src/plugins/wizard/public/application/components/workspace.tsx index 087cb656c622..7e51a29be1a6 100644 --- a/src/plugins/wizard/public/application/components/workspace.tsx +++ b/src/plugins/wizard/public/application/components/workspace.tsx @@ -3,24 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { - EuiButton, - EuiContextMenu, - EuiContextMenuPanelItemDescriptor, - EuiEmptyPrompt, - EuiFlexGroup, - EuiFlexItem, - EuiIcon, - EuiPanel, - EuiPopover, -} from '@elastic/eui'; +import { EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiPanel } from '@elastic/eui'; import React, { FC, useState, useMemo, useEffect, useLayoutEffect } from 'react'; import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public'; import { IExpressionLoaderParams } from '../../../../expressions/public'; import { WizardServices } from '../../types'; import { validateSchemaState } from '../utils/validate_schema_state'; -import { useTypedDispatch, useTypedSelector } from '../utils/state_management'; -import { setActiveVisualization } from '../utils/state_management/visualization_slice'; +import { useTypedSelector } from '../utils/state_management'; import { useVisualizationType } from '../utils/use'; import hand_field from '../../assets/hand_field.svg'; @@ -82,9 +71,6 @@ export const Workspace: FC = ({ children }) => { return (
- - - @@ -116,64 +102,3 @@ export const Workspace: FC = ({ children }) => {
); }; - -const TypeSelectorPopover = () => { - const [isPopoverOpen, setPopover] = useState(false); - const { - services: { types }, - } = useOpenSearchDashboards(); - const dispatch = useTypedDispatch(); - const visualizationTypes = types.all(); - const activeVisualization = useVisualizationType(); - - const onButtonClick = () => { - setPopover(!isPopoverOpen); - }; - - const closePopover = () => { - setPopover(false); - }; - - const panels = useMemo( - () => [ - { - id: 0, - title: 'Chart types', - items: visualizationTypes.map( - ({ name, title, icon, description }): EuiContextMenuPanelItemDescriptor => ({ - name: title, - icon: , - onClick: () => { - closePopover(); - // TODO: Fix changing viz type - // dispatch(setActiveVisualization(name)); - }, - toolTipContent: description, - toolTipPosition: 'right', - }) - ), - }, - ], - [visualizationTypes] - ); - - const button = ( - - {activeVisualization?.title} - - ); - - return ( - - - - ); -}; diff --git a/src/plugins/wizard/public/application/utils/state_management/index.ts b/src/plugins/wizard/public/application/utils/state_management/index.ts index edb5c2a17184..5a3e34c8da69 100644 --- a/src/plugins/wizard/public/application/utils/state_management/index.ts +++ b/src/plugins/wizard/public/application/utils/state_management/index.ts @@ -5,3 +5,4 @@ export * from './store'; export * from './hooks'; +export * from './shared_actions'; diff --git a/src/plugins/wizard/public/application/utils/state_management/shared_actions.ts b/src/plugins/wizard/public/application/utils/state_management/shared_actions.ts new file mode 100644 index 000000000000..f1dc6ee027b8 --- /dev/null +++ b/src/plugins/wizard/public/application/utils/state_management/shared_actions.ts @@ -0,0 +1,14 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { createAction } from '@reduxjs/toolkit'; +import { VisualizationType } from '../../../services/type_service/visualization_type'; + +interface ActiveVisPayload { + name: VisualizationType['name']; + style: VisualizationType['ui']['containerConfig']['style']['defaults']; +} + +export const setActiveVisualization = createAction('setActiveVisualzation'); diff --git a/src/plugins/wizard/public/application/utils/state_management/style_slice.ts b/src/plugins/wizard/public/application/utils/state_management/style_slice.ts index 55579c759ccf..9fb0cdedb763 100644 --- a/src/plugins/wizard/public/application/utils/state_management/style_slice.ts +++ b/src/plugins/wizard/public/application/utils/state_management/style_slice.ts @@ -5,6 +5,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { WizardServices } from '../../../types'; +import { setActiveVisualization } from './shared_actions'; export type StyleState = T; @@ -36,6 +37,11 @@ export const styleSlice = createSlice({ }; }, }, + extraReducers(builder) { + builder.addCase(setActiveVisualization, (state, action) => { + return action.payload.style; + }); + }, }); // Exposing the state functions as generics 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 fe1277f33432..cbb6c76a0758 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 @@ -6,6 +6,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { CreateAggConfigParams } from '../../../../../data/common'; import { WizardServices } from '../../../types'; +import { setActiveVisualization } from './shared_actions'; export interface VisualizationState { indexPattern?: string; @@ -46,12 +47,6 @@ export const slice = createSlice({ name: 'visualization', initialState, reducers: { - setActiveVisualization: ( - state, - action: PayloadAction - ) => { - state.activeVisualization = action.payload; - }, setIndexPattern: (state, action: PayloadAction) => { state.indexPattern = action.payload; state.activeVisualization!.aggConfigParams = []; @@ -106,11 +101,18 @@ export const slice = createSlice({ return action.payload; }, }, + extraReducers(builder) { + builder.addCase(setActiveVisualization, (state, action) => { + state.activeVisualization = { + name: action.payload.name, + aggConfigParams: [], + }; + }); + }, }); export const { reducer } = slice; export const { - setActiveVisualization, setIndexPattern, setSearchField, editDraftAgg, 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 b5ef3bdb75cb..4a626cb01179 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,8 +5,7 @@ import React, { useCallback } from 'react'; import { i18n } from '@osd/i18n'; -import { EuiButtonGroup, EuiFormRow, EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; -import { FormattedMessage } from 'react-intl'; +import { EuiButtonGroup, EuiFormRow } from '@elastic/eui'; import produce from 'immer'; import { Draft } from 'immer'; import { @@ -17,10 +16,14 @@ import { RangeOption, SwitchOption, } from '../../../../../charts/public'; -import { useTypedDispatch, useTypedSelector } from '../../../application/utils/state_management'; +import { + useTypedDispatch, + useTypedSelector, + setStyleState, +} 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'; +import { Option } from '../../../application/app'; const METRIC_COLOR_MODES = [ { @@ -51,7 +54,7 @@ function MetricVizOptions() { const setOption = useCallback( (callback: (draft: Draft) => void) => { const newState = produce(styleState, callback); - dispatch(setState(newState)); + dispatch(setStyleState(newState)); }, [dispatch, styleState] ); @@ -61,15 +64,11 @@ function MetricVizOptions() { }); return ( - - - -

- -

-
- - + <> +
- - - - - -

- -

-
- - + +
- - - - - -

- -

-
- - + +
-
+ + ); }