From d855d044f6715f8f022646fc8a91bb7d3bb0f981 Mon Sep 17 00:00:00 2001 From: Peter Fitzgibbons Date: Wed, 19 Apr 2023 13:36:46 -0700 Subject: [PATCH 1/3] Fixes * Panel View (legacy) - Duplicate - Rename Signed-off-by: Peter Fitzgibbons --- public/components/custom_panels/custom_panel_table.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/components/custom_panels/custom_panel_table.tsx b/public/components/custom_panels/custom_panel_table.tsx index cf4273de65..a6107953b8 100644 --- a/public/components/custom_panels/custom_panel_table.tsx +++ b/public/components/custom_panels/custom_panel_table.tsx @@ -222,7 +222,7 @@ export const CustomPanelTable = ({ 'Duplicate Dashboard', 'Cancel', 'Duplicate', - selectedCustomPanels[0].title + ' (copy)', + selectedCustomPanels[0].title + ' (copy)x', CREATE_PANEL_MESSAGE ) ); From 77820394602c2f7ba967fcb29fd2d50847a41cbb Mon Sep 17 00:00:00 2001 From: Peter Fitzgibbons Date: Thu, 20 Apr 2023 09:54:46 -0700 Subject: [PATCH 2/3] Toasts use hook from useOpenSearchDashboards context provider Signed-off-by: Peter Fitzgibbons --- common/types/shared.ts | 5 ++ public/components/app.tsx | 46 +++++++----- public/components/common/toast/index.tsx | 36 +++++++++ .../custom_panels/custom_panel_table.tsx | 75 +++++++++++-------- .../custom_panels/custom_panel_view.tsx | 10 +-- public/components/custom_panels/home.tsx | 26 ++----- .../custom_panels/redux/panel_slice.ts | 2 - public/components/index.tsx | 3 + .../framework/redux/reducers/toast_slice.ts | 40 ++++++++++ public/plugin.ts | 6 ++ 10 files changed, 166 insertions(+), 83 deletions(-) create mode 100644 common/types/shared.ts create mode 100644 public/components/common/toast/index.tsx create mode 100644 public/framework/redux/reducers/toast_slice.ts diff --git a/common/types/shared.ts b/common/types/shared.ts new file mode 100644 index 0000000000..fd0f0a71e1 --- /dev/null +++ b/common/types/shared.ts @@ -0,0 +1,5 @@ +import { CoreStart, ToastsStart } from '../../../../src/core/public'; + +export interface ObservabilityAppServices extends CoreStart { + toasts: ToastsStart; +} diff --git a/public/components/app.tsx b/public/components/app.tsx index 18066f3281..8ea7e3834b 100644 --- a/public/components/app.tsx +++ b/public/components/app.tsx @@ -18,6 +18,8 @@ import { EventAnalytics } from './event_analytics'; import { Home as MetricsHome } from './metrics/index'; import { Main as NotebooksHome } from './notebooks/components/main'; import { Home as TraceAnalyticsHome } from './trace_analytics/home'; +import { ObservabilityAppServices } from '../../common/types/shared'; +import { OpenSearchDashboardsContextProvider } from '../../../../src/plugins/opensearch_dashboards_react/public'; interface ObservabilityAppDeps { CoreStartProp: CoreStart; @@ -28,6 +30,7 @@ interface ObservabilityAppDeps { timestampUtils: any; queryManager: QueryManager; startPage: string; + services: ObservabilityAppServices; } // for cypress to test redux store @@ -53,6 +56,7 @@ export const App = ({ timestampUtils, queryManager, startPage, + services, }: ObservabilityAppDeps) => { const { chrome, http, notifications, savedObjects: coreSavedObjects } = CoreStartProp; const parentBreadcrumb = { @@ -65,26 +69,28 @@ export const App = ({ return ( - - - + + + + + ); diff --git a/public/components/common/toast/index.tsx b/public/components/common/toast/index.tsx new file mode 100644 index 0000000000..ba3959a515 --- /dev/null +++ b/public/components/common/toast/index.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { useOpenSearchDashboards } from '../../../../../../src/plugins/opensearch_dashboards_react/public'; +import { ToastInputFields } from '../../../../../../src/core/public'; +import { ObservabilityAppServices } from '../../../../common/types/shared'; + +type Color = 'success' | 'primary' | 'warning' | 'danger' | undefined; + +export const useToast = () => { + const { + services: { toasts }, + } = useOpenSearchDashboards(); + + const setToast = (title: string, color: Color = 'success', text?, side?: string) => { + const newToast: ToastInputFields = { + id: new Date().toISOString(), + title, + text, + }; + switch (color) { + case 'danger': { + toasts.addDanger(newToast); + break; + } + case 'warning': { + toasts.addWarning(newToast); + break; + } + default: { + toasts.addSuccess(newToast); + break; + } + } + }; + + return { setToast }; +}; diff --git a/public/components/custom_panels/custom_panel_table.tsx b/public/components/custom_panels/custom_panel_table.tsx index a6107953b8..9c620227f9 100644 --- a/public/components/custom_panels/custom_panel_table.tsx +++ b/public/components/custom_panels/custom_panel_table.tsx @@ -48,7 +48,6 @@ import { getSampleDataModal } from '../common/helpers/add_sample_modal'; import { pageStyles } from '../../../common/constants/shared'; import { DeleteModal } from '../common/helpers/delete_modal'; import { - clonePanel, createPanel, deletePanels, fetchPanels, @@ -57,6 +56,8 @@ import { renameCustomPanel, selectPanelList, } from './redux/panel_slice'; +import { isNameValid } from './helpers/utils'; +import { useToast } from '../common/toast'; /* * "CustomPanelTable" module, used to view all the saved panels @@ -77,8 +78,6 @@ interface Props { loading: boolean; setBreadcrumbs: (newBreadcrumbs: ChromeBreadcrumb[]) => void; parentBreadcrumbs: EuiBreadcrumb[]; - cloneCustomPanel: (newCustomPanelName: string, customPanelId: string) => void; - deleteCustomPanelList: (customPanelIdList: string[], toastMessage: string) => any; addSamplePanels: () => void; } @@ -86,8 +85,6 @@ export const CustomPanelTable = ({ loading, setBreadcrumbs, parentBreadcrumbs, - cloneCustomPanel, - deleteCustomPanelList, addSamplePanels, }: Props) => { const customPanels = useSelector(selectPanelList); @@ -100,16 +97,13 @@ export const CustomPanelTable = ({ const history = useHistory(); const dispatch = useDispatch(); + const { setToast } = useToast(); useEffect(() => { setBreadcrumbs(parentBreadcrumbs); dispatch(fetchPanels()); }, []); - // useEffect(() => - // console.log({ customPanels, selectedCustomPanels }, [customPanels, selectedCustomPanels]) - // ); - useEffect(() => { const url = window.location.hash.split('/'); if (url[url.length - 1] === 'create') { @@ -126,8 +120,12 @@ export const CustomPanelTable = ({ }; const onCreate = async (newCustomPanelName: string) => { - const newPanel = newPanelTemplate(newCustomPanelName); - dispatch(createPanel(newPanel)); + if (!isNameValid(newCustomPanelName)) { + setToast('Invalid Dashboard name', 'danger'); + } else { + const newPanel = newPanelTemplate(newCustomPanelName); + dispatch(createPanel(newPanel)); + } closeModal(); }; @@ -137,25 +135,35 @@ export const CustomPanelTable = ({ }; const onClone = async (newName: string) => { - let sourcePanel = selectedCustomPanels[0]; - try { - if (!isUuid(sourcePanel.id)) { - // Observability Panel API returns partial record, so for duplication - // we will retrieve the entire record and allow new process to continue. - const legacyFetchResult = await coreRefs.http!.get( - `${CUSTOM_PANELS_API_PREFIX}/panels/${sourcePanel.id}` - ); - sourcePanel = legacyFetchResult.operationalPanel; - } + if (!isNameValid(newName)) { + setToast('Invalid Operational Panel name', 'danger'); + } else { + let sourcePanel = selectedCustomPanels[0]; + try { + if (!isUuid(sourcePanel.id)) { + // Observability Panel API returns partial record, so for duplication + // we will retrieve the entire record and allow new process to continue. + const legacyFetchResult = await coreRefs.http!.get( + `${CUSTOM_PANELS_API_PREFIX}/panels/${sourcePanel.id}` + ); + sourcePanel = legacyFetchResult.operationalPanel; + } - const { id, ...newPanel } = { - ...sourcePanel, - title: newName, - }; + const { id, ...newPanel } = { + ...sourcePanel, + title: newName, + }; - dispatch(createPanel(newPanel)); - } catch (err) { - console.log(err); + await dispatch(createPanel(newPanel)); + + setToast(`Observability Dashboard "${newName}" successfully created!`); + } catch (err) { + setToast( + 'Error cloning Operational Panel, please make sure you have the correct permission.', + 'danger' + ); + console.log(err); + } } closeModal(); }; @@ -166,12 +174,13 @@ export const CustomPanelTable = ({ } successfully deleted!`; try { - dispatch(deletePanels(selectedCustomPanels)); + await dispatch(deletePanels(selectedCustomPanels)); + setToast(toastMessage); } catch (err) { - // setToast( - // 'Error deleting Operational Panels, please make sure you have the correct permission.', - // 'danger' - // ); + setToast( + 'Error deleting Operational Panels, please make sure you have the correct permission.', + 'danger' + ); console.error(err.body?.message || err); } diff --git a/public/components/custom_panels/custom_panel_view.tsx b/public/components/custom_panels/custom_panel_view.tsx index 2384d82efc..d45c5214b9 100644 --- a/public/components/custom_panels/custom_panel_view.tsx +++ b/public/components/custom_panels/custom_panel_view.tsx @@ -70,6 +70,7 @@ import { AddVisualizationPopover } from './helpers/add_visualization_popover'; import { DeleteModal } from '../common/helpers/delete_modal'; import { coreRefs } from '../../framework/core_refs'; import { clonePanel } from './redux/panel_slice'; +import { useToast } from '../common/toast'; /* * "CustomPanelsView" module used to render an Observability Dashboard @@ -104,12 +105,6 @@ interface CustomPanelViewProps { chrome: CoreStart['chrome']; parentBreadcrumbs: EuiBreadcrumb[]; cloneCustomPanel: (clonedCustomPanelName: string, clonedCustomPanelId: string) => Promise; - setToast: ( - title: string, - color?: string, - text?: React.ReactChild | undefined, - side?: string | undefined - ) => void; onEditClick: (savedVisualizationId: string) => any; startTime: string; endTime: string; @@ -138,7 +133,6 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { setEndTime, updateAvailabilityVizId, cloneCustomPanel, - setToast, onEditClick, onAddClick, } = props; @@ -169,6 +163,8 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { const dispatch = useDispatch(); + const { setToast } = useToast(); + const closeHelpFlyout = () => { setAddVizDisabled(false); setHelpIsFlyoutVisible(false); diff --git a/public/components/custom_panels/home.tsx b/public/components/custom_panels/home.tsx index c113307e1b..dcde4483f4 100644 --- a/public/components/custom_panels/home.tsx +++ b/public/components/custom_panels/home.tsx @@ -3,9 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { EuiBreadcrumb, EuiGlobalToastList, ShortDate } from '@elastic/eui'; -import { Toast } from '@elastic/eui/src/components/toast/global_toast_list'; -import React, { ReactChild, useState } from 'react'; +import { EuiBreadcrumb, ShortDate } from '@elastic/eui'; +import React, { useState } from 'react'; import { useDispatch } from 'react-redux'; // eslint-disable-next-line @osd/eslint/module_migration import { StaticContext } from 'react-router'; @@ -29,6 +28,7 @@ import { CustomPanelTable } from './custom_panel_table'; import { CustomPanelView } from './custom_panel_view'; import { CustomPanelViewSO } from './custom_panel_view_so'; import { fetchPanels, uuidRx } from './redux/panel_slice'; +import { useToast } from '../common/toast'; // import { ObjectFetcher } from '../common/objectFetcher'; @@ -65,14 +65,14 @@ export const Home = ({ coreSavedObjects, setBreadcrumbs, }: PanelHomeProps) => { - const [toasts, setToasts] = useState([]); const [loading, setLoading] = useState(false); - const [toastRightSide, setToastRightSide] = useState(true); const [start, setStart] = useState(''); const [end, setEnd] = useState(''); const dispatch = useDispatch(); + const { setToast } = useToast(); + const customPanelBreadCrumbs = [ ...parentBreadcrumbs, { @@ -81,12 +81,6 @@ export const Home = ({ }, ]; - const setToast = (title: string, color = 'success', text?: ReactChild, side?: string) => { - if (!text) text = ''; - setToastRightSide(!side ? true : false); - setToasts([...toasts, { id: new Date().toISOString(), title, text, color } as Toast]); - }; - const onEditClick = (savedVisualizationId: string) => { window.location.assign(`${observabilityLogsID}#/explorer/${savedVisualizationId}`); }; @@ -145,14 +139,6 @@ export const Home = ({ return ( - { - setToasts(toasts.filter((toast) => toast.id !== removedToast.id)); - }} - side={toastRightSide ? 'right' : 'left'} - toastLifeTimeMs={6000} - /> async (dispatch, getState) => { const newPanel = savedObjectToCustomPanel(newSOPanel); const panelList = getState().customPanel.panelList; dispatch(setPanelList([...panelList, newPanel])); - - window.location.replace(`#/${newPanel.id}`); }; export const clonePanel = (panel, newPanelName) => async (dispatch, getState) => { diff --git a/public/components/index.tsx b/public/components/index.tsx index 8191752974..440f2518a2 100644 --- a/public/components/index.tsx +++ b/public/components/index.tsx @@ -9,6 +9,7 @@ import { QueryManager } from 'common/query_manager'; import { AppMountParameters, CoreStart } from '../../../../src/core/public'; import { AppPluginStartDependencies } from '../types'; import { App } from './app'; +import { ObservabilityAppServices } from '../../common/types/shared'; export const Observability = ( CoreStartProp: CoreStart, @@ -19,6 +20,7 @@ export const Observability = ( savedObjects: any, timestampUtils: any, queryManager: QueryManager, + services: ObservabilityAppServices, startPage: string ) => { ReactDOM.render( @@ -31,6 +33,7 @@ export const Observability = ( timestampUtils={timestampUtils} queryManager={queryManager} startPage={startPage} + services={services} />, AppMountParametersProp.element ); diff --git a/public/framework/redux/reducers/toast_slice.ts b/public/framework/redux/reducers/toast_slice.ts new file mode 100644 index 0000000000..de856535f7 --- /dev/null +++ b/public/framework/redux/reducers/toast_slice.ts @@ -0,0 +1,40 @@ +import { createSlice } from '@reduxjs/toolkit'; + +const toastSlice = createSlice({ + name: 'toast', + initialState: { toasts: [], toastRightSide: true }, + reducers: { + appendToast: (state, action) => { + state.toasts = [...state.toasts, action.payload]; + }, + + setToastRightSide: (state, action) => (state.toastRightSide = action.payload), + + dismissToast: (state, action) => { + state.toasts = state.toasts.filter((t) => t.id !== action.payload.id); + }, + + resetToasts: (state, action) => { + state.toasts = []; + state.toastRightSide = true; + }, + }, +}); + +export const toastReducer = toastSlice.reducer; + +export const { dismissToast, resetToasts } = toastSlice.actions; +const { appendToast, setToastRightSide } = toastSlice.actions; + +export const selectToasts = (rootState) => rootState.toast.toasts; + +export const selectToastRightSide = (rootState) => rootState.toast.toastRightSide; + +export const addToast = (title, color?, textChild?, side?) => (dispatch, getState) => { + const newToast = { id: new Date().toISOString(), title, textChild, color }; + dispatch(appendToast(newToast)); + + if (side) { + dispatch(setToastRightSide(side === 'left')); + } +}; diff --git a/public/plugin.ts b/public/plugin.ts index 88991af928..a3b20c30ca 100644 --- a/public/plugin.ts +++ b/public/plugin.ts @@ -75,6 +75,7 @@ import { ObservabilityStart, SetupDependencies, } from './types'; +import { ObservabilityAppServices } from '../common/types/shared'; export class ObservabilityPlugin implements @@ -137,6 +138,10 @@ export class ObservabilityPlugin const savedObjects = new SavedObjects(coreStart.http); const timestampUtils = new TimestampUtils(dslService, pplService); + const services: ObservabilityAppServices = { + toasts: coreStart.notifications.toasts, + }; + return Observability( coreStart, depsStart as AppPluginStartDependencies, @@ -146,6 +151,7 @@ export class ObservabilityPlugin savedObjects, timestampUtils, qm, + services, startPage ); }; From caa149973bea9a895cbe44f5bb6e9a1e62db8351 Mon Sep 17 00:00:00 2001 From: Peter Fitzgibbons Date: Fri, 21 Apr 2023 15:51:21 -0700 Subject: [PATCH 3/3] Testing for CustomPanel Toast Signed-off-by: Peter Fitzgibbons --- .cypress/integration/3_panels.spec.ts | 14 +- .../custom_panel_view.test.tsx.snap | 3498 +++++++++-------- .../__tests__/custom_panel_view.test.tsx | 71 +- .../custom_panels/custom_panel_table.tsx | 16 +- public/plugin.ts | 2 +- 5 files changed, 1821 insertions(+), 1780 deletions(-) diff --git a/.cypress/integration/3_panels.spec.ts b/.cypress/integration/3_panels.spec.ts index 4fac68df16..e0eb2c493f 100644 --- a/.cypress/integration/3_panels.spec.ts +++ b/.cypress/integration/3_panels.spec.ts @@ -77,7 +77,7 @@ describe('Creating visualizations', () => { }); }); -describe('Testing panels table', () => { +describe.only('Testing panels table', () => { beforeEach(() => { eraseTestPanels(); moveToPanelHome(); @@ -567,6 +567,7 @@ const eraseLegacyPanels = () => { 'osd-xsrf': true, }, }).then((response) => { + console.log("legacy panels to erase", response.body) response.body.panels.map((panel) => { cy.request({ method: 'DELETE', @@ -596,6 +597,7 @@ const eraseSavedObjectPaenls = () => { }, }) .then((response) => { + console.log("saved objects to erase", response.body) response.body.saved_objects.map((soPanel) => { cy.request({ method: 'DELETE', @@ -605,6 +607,9 @@ const eraseSavedObjectPaenls = () => { 'content-type': 'application/json;charset=UTF-8', 'osd-xsrf': true, }, + }).then((response) => { + const deletedId = response; + console.log('erased SO Panel', response) }); }); }); @@ -681,9 +686,10 @@ const openActionsDropdown = () => { }; const selectThePanel = () => { - cy.get('.euiCheckbox__input[title="Select this row"]').then(() => { - cy.get('.euiCheckbox__input[title="Select this row"]').check({ force: true }); - }); + // cy.get('.euiCheckbox__input[title="Select this row"]').then(() => { + cy.get('.euiCheckbox__input[title="Select this row"]').check({ force: true }); + cy.get('.euiTableRow-isSelected').should('exist') + // }); }; const expectToastWith = (title) => { diff --git a/public/components/custom_panels/__tests__/__snapshots__/custom_panel_view.test.tsx.snap b/public/components/custom_panels/__tests__/__snapshots__/custom_panel_view.test.tsx.snap index 05379e0bcd..226fddb62b 100644 --- a/public/components/custom_panels/__tests__/__snapshots__/custom_panel_view.test.tsx.snap +++ b/public/components/custom_panels/__tests__/__snapshots__/custom_panel_view.test.tsx.snap @@ -2,707 +2,589 @@ exports[`Panels View Component renders panel view container with visualizations 1`] = ` - + -
- -
+
+ - -
- -
- -
- + +
+ +
-

- - -
- + + +
-
- -
- - Created on - Invalid date -
- - -
- +
+ +
+ + Created on + Invalid date +
+
+ +
-
- -
- + +
- - - - -
-
- -
+ + + +
+
+ - - Dashboard Actions -
- } - closePopover={[Function]} - display="inlineBlock" - hasArrow={true} - isOpen={false} - ownFocus={true} - panelPaddingSize="none" - withTitle={true} - > -
-
- - - - - -
-
- -
-
- -
- - Add visualization + Dashboard Actions } closePopover={[Function]} display="inlineBlock" hasArrow={true} - id="addVisualizationContextMenu" isOpen={false} ownFocus={true} panelPaddingSize="none" + withTitle={true} >
-
-
-
-
- -
-
-

-
- -
- + + +
+ + + Add visualization + + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + id="addVisualizationContextMenu" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > +
+
+ + + + + +
+
+
+
+
+
+
+ +
+
+
+
+ +
-
- -
- + +
+ + PPL + + } + baseQuery="source = " + dslService={ + DSLService { + "fetch": [Function], + "fetchFields": [Function], + "fetchIndices": [Function], + "http": [MockFunction], } - > - PPL - - } - baseQuery="source = " - dslService={ - DSLService { - "fetch": [Function], - "fetchFields": [Function], - "fetchIndices": [Function], - "http": [MockFunction], } - } - getSuggestions={[Function]} - handleQueryChange={[Function]} - handleQuerySearch={[Function]} - isDisabled={true} - key="autocomplete-search-bar" - onItemSelect={[Function]} - placeholder="Use PPL 'where' clauses to add filters on all visualizations [where Carrier = 'OpenSearch-Air']" - possibleCommands={ - Array [ - Object { - "label": "where", - }, - ] - } - query="" - tabId="panels-filter" - tempQuery="" - > -
- - PPL - - } - aria-autocomplete="both" +
- } + aria-autocomplete="both" + aria-labelledby="autocomplete-4-label" + autoCapitalize="off" + autoComplete="off" + autoCorrect="off" + autoFocus={false} + data-test-subj="searchAutocompleteTextArea" + disabled={true} + enterKeyHint="search" fullWidth={true} - inputId="autocomplete-textarea" + id="autocomplete-textarea" + maxLength={512} + onBlur={[Function]} + onChange={[Function]} + onClick={[Function]} + onFocus={[Function]} + onKeyDown={[Function]} + placeholder="Use PPL 'where' clauses to add filters on all visualizations [where Carrier = 'OpenSearch-Air']" + spellCheck="false" + type="search" + value="" > -
+ PPL + + } + fullWidth={true} + inputId="autocomplete-textarea" >
- - - - -
- -
+ - PPL - - -
- -
-
-
-
-
- -
+ PPL + + +
+ + +
+ +
+ + - - -
- -
- - } +
+ +
-
+ } > - - - - + -
-
+ - - + + + +
-
- - -
- } - iconType={false} - isCustom={true} - startDateControl={
} + + +
-
} + iconType={false} + isCustom={true} + startDateControl={
} > - -
- - -
-
- -
- - -
+ Show dates + + + +
+
+ +
+
+ +
+ + - - - - - - - - - - - -
-
-
-
-
-
- -
- - -
- - -
- -
- - -
+ + + + + + +
+ +
+ + +
+ +
+ + +
+ + +
+ +
+ + - -
-

- Start by adding your first visualization -

- -
- - -
+ Start by adding your first visualization + + - + + +
-
- Use PPL Queries to fetch & filter observability data and create visualizations -
- -
-
-
- -
- - -
- - -
+ Use PPL Queries to fetch & filter observability data and create visualizations +
+ +
+ +
+
+
+ + - + + +
-
- - - Add visualization - - } - closePopover={[Function]} - display="inlineBlock" - hasArrow={true} - id="addVisualizationContextMenu" - isOpen={false} - ownFocus={true} - panelPaddingSize="none" + -
-
+ - + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + id="addVisualizationContextMenu" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > +
+
+ - - - + + + + +
-
- - -
- -
- - -
- -
- - + +
+ +
+ + +
+ +
+
+ - - - -
- - - - -
- -
-
-
- -
- + maxRows={Infinity} + onDrag={[Function]} + onDragStart={[Function]} + onDragStop={[Function]} + onLayoutChange={[Function]} + onResize={[Function]} + onResizeStart={[Function]} + onResizeStop={[Function]} + preventCollision={false} + rowHeight={150} + style={Object {}} + useCSSTransforms={true} + verticalCompact={true} + width={0} + > +
+ + + + +
+ +
+ + + + +
+
`; diff --git a/public/components/custom_panels/__tests__/custom_panel_view.test.tsx b/public/components/custom_panels/__tests__/custom_panel_view.test.tsx index b37601519f..5a5da64e15 100644 --- a/public/components/custom_panels/__tests__/custom_panel_view.test.tsx +++ b/public/components/custom_panels/__tests__/custom_panel_view.test.tsx @@ -20,13 +20,16 @@ import PPLService from '../../../../public/services/requests/ppl'; import DSLService from '../../../../public/services/requests/dsl'; import { coreStartMock } from '../../../../test/__mocks__/coreMocks'; import { HttpResponse } from '../../../../../../src/core/public'; -import { createStore } from '@reduxjs/toolkit'; +import { applyMiddleware, createStore } from 'redux'; import { rootReducer } from '../../../framework/redux/reducers'; +import thunk from 'redux-thunk'; import { Provider } from 'react-redux'; +import { OpenSearchDashboardsContextProvider } from '../../../../../../src/plugins/opensearch_dashboards_react/public'; describe('Panels View Component', () => { configure({ adapter: new Adapter() }); - const store = createStore(rootReducer); + + const store = createStore(rootReducer, applyMiddleware(thunk)); it('renders panel view container without visualizations', async () => { httpClientMock.get = jest.fn(() => @@ -71,6 +74,26 @@ describe('Panels View Component', () => { page="operationalPanels" /> + + + ); wrapper.update(); @@ -111,27 +134,31 @@ describe('Panels View Component', () => { window.location.assign(`#/event_analytics/explorer/${savedVisId}`); }; + const services = { toasts: { addDanger: (t) => {} } } + const wrapper = mount( - - - + + + + + ); wrapper.update(); diff --git a/public/components/custom_panels/custom_panel_table.tsx b/public/components/custom_panels/custom_panel_table.tsx index 9c620227f9..fb419fa5c6 100644 --- a/public/components/custom_panels/custom_panel_table.tsx +++ b/public/components/custom_panels/custom_panel_table.tsx @@ -91,7 +91,7 @@ export const CustomPanelTable = ({ const [isModalVisible, setIsModalVisible] = useState(false); // Modal Toggle const [modalLayout, setModalLayout] = useState(); // Modal Layout const [isActionsPopoverOpen, setIsActionsPopoverOpen] = useState(false); - const [selectedCustomPanels, setselectedCustomPanels] = useState([]); + const [selectedCustomPanels, setselectedCustomPanels$] = useState([]); const [searchQuery, setSearchQuery] = useState(''); const location = useLocation(); const history = useHistory(); @@ -169,9 +169,8 @@ export const CustomPanelTable = ({ }; const onDelete = async () => { - const toastMessage = `Observability Dashboards ${ - selectedCustomPanels.length > 1 ? 's' : ' ' + selectedCustomPanels[0].title - } successfully deleted!`; + const toastMessage = `Observability Dashboards ${selectedCustomPanels.length > 1 ? 's' : ' ' + selectedCustomPanels[0].title + } successfully deleted!`; try { await dispatch(deletePanels(selectedCustomPanels)); @@ -239,9 +238,8 @@ export const CustomPanelTable = ({ }; const deletePanel = () => { - const customPanelString = `Observability Dashboard${ - selectedCustomPanels.length > 1 ? 's' : '' - }`; + const customPanelString = `Observability Dashboard${selectedCustomPanels.length > 1 ? 's' : '' + }`; setModalLayout( - customPanel.title.toLowerCase().includes(searchQuery.toLowerCase()) - ) + customPanel.title.toLowerCase().includes(searchQuery.toLowerCase()) + ) : customPanels } itemId="id" diff --git a/public/plugin.ts b/public/plugin.ts index a3b20c30ca..940c780348 100644 --- a/public/plugin.ts +++ b/public/plugin.ts @@ -79,7 +79,7 @@ import { ObservabilityAppServices } from '../common/types/shared'; export class ObservabilityPlugin implements - Plugin { + Plugin { public setup( core: CoreSetup, setupDeps: SetupDependencies