From 09e0a630f7115acc32e44554f239bd0c80ae0184 Mon Sep 17 00:00:00 2001 From: Peter Fitzgibbons Date: Tue, 18 Apr 2023 10:03:41 -0700 Subject: [PATCH 1/5] Rename Panels => Observability Dashboard Signed-off-by: Peter Fitzgibbons --- .../custom_panels/custom_panel_table.tsx | 28 ++++++++++--------- .../custom_panels/custom_panel_view.tsx | 26 ++++++++--------- .../custom_panels/custom_panel_view_so.tsx | 28 +++++++++---------- .../helpers/modal_containers.tsx | 4 +-- public/components/custom_panels/home.tsx | 14 +++++----- .../panel_modules/empty_panel.tsx | 2 +- .../visualization_flyout.tsx | 2 +- .../visualization_flyout_so.tsx | 5 ++-- .../custom_panels/redux/panel_slice.ts | 6 ++-- public/plugin.ts | 8 ++++-- 10 files changed, 63 insertions(+), 60 deletions(-) diff --git a/public/components/custom_panels/custom_panel_table.tsx b/public/components/custom_panels/custom_panel_table.tsx index 8b2fe9d5be..9ba6c69f8c 100644 --- a/public/components/custom_panels/custom_panel_table.tsx +++ b/public/components/custom_panels/custom_panel_table.tsx @@ -136,7 +136,7 @@ export const CustomPanelTable = ({ }; const onDelete = async () => { - const toastMessage = `Custom Panels ${ + const toastMessage = `Observability Dashboards ${ selectedCustomPanels.length > 1 ? 's' : ' ' + selectedCustomPanels[0].title } successfully deleted!`; const PanelList = selectedCustomPanels.map((panel) => panel.id); @@ -153,7 +153,7 @@ export const CustomPanelTable = ({ history.goBack(); }, 'Name', - 'Create operational panel', + 'Create Observability Dashboard', 'Cancel', 'Create', undefined, @@ -169,7 +169,7 @@ export const CustomPanelTable = ({ onRename, closeModal, 'Name', - 'Rename Panel', + 'Rename Dashboard', 'Cancel', 'Rename', selectedCustomPanels[0].title, @@ -185,7 +185,7 @@ export const CustomPanelTable = ({ onClone, closeModal, 'Name', - 'Duplicate Panel', + 'Duplicate Dashboard', 'Cancel', 'Duplicate', selectedCustomPanels[0].title + ' (copy)', @@ -196,7 +196,9 @@ export const CustomPanelTable = ({ }; const deletePanel = () => { - const customPanelString = `operational panel${selectedCustomPanels.length > 1 ? 's' : ''}`; + const customPanelString = `Observability Dashboard${ + selectedCustomPanels.length > 1 ? 's' : '' + }`; setModalLayout(

- Panels + Dashboard ({customPanels.length})

- Use Operational panels to create and view different visualizations on ingested - observability data, using PPL (Piped Processing Language) queries.{' '} + Use Observability Dashboard to create and view different visualizations on + ingested observability data, using PPL (Piped Processing Language) queries.{' '} Learn more @@ -345,7 +347,7 @@ export const CustomPanelTable = ({ - Create panel + Create Dashboard @@ -357,7 +359,7 @@ export const CustomPanelTable = ({ setSearchQuery(e.target.value)} /> @@ -395,10 +397,10 @@ export const CustomPanelTable = ({ <> -

No Operational Panels

+

No Observability Dashboards

- Use operational panels to dive deeper into observability + Use Observability Dashboards to dive deeper into observability
using PPL queries and insightful visualizations
@@ -411,7 +413,7 @@ export const CustomPanelTable = ({ fullWidth={false} href="#/create" > - Create panel + Create Dashboard diff --git a/public/components/custom_panels/custom_panel_view.tsx b/public/components/custom_panels/custom_panel_view.tsx index 22a0d33d15..882b0fd7a7 100644 --- a/public/components/custom_panels/custom_panel_view.tsx +++ b/public/components/custom_panels/custom_panel_view.tsx @@ -69,7 +69,7 @@ import { DeleteModal } from '../common/helpers/delete_modal'; import { coreRefs } from '../../framework/core_refs'; /* - * "CustomPanelsView" module used to render an Operational Panel + * "CustomPanelsView" module used to render an Observability Dashboard * * Props taken in as params are: * panelId: Name of the panel opened @@ -196,7 +196,7 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { setPanelVisualizations(res.operationalPanel.visualizations); }) .catch((err) => { - console.error('Issue in fetching the operational panels', err); + console.error('Issue in fetching the Observability Dashboards', err); }); }; @@ -244,7 +244,7 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { onConfirm={onDelete} onCancel={closeModal} title={`Delete ${openPanelName}`} - message={`Are you sure you want to delete this Operational Panel?`} + message={`Are you sure you want to delete this Observability Dashboard?`} /> ); showModal(); @@ -263,7 +263,7 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { onRename, closeModal, 'Name', - 'Rename Panel', + 'Rename Dashboard', 'Cancel', 'Rename', openPanelName, @@ -295,7 +295,7 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { onClone, closeModal, 'Name', - 'Duplicate Panel', + 'Duplicate Dashboard', 'Cancel', 'Duplicate', openPanelName + ' (copy)', @@ -401,7 +401,7 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { setOnRefresh(!onRefresh); }) .catch((err) => { - setToast('Error is adding filters to the operational panel', 'danger'); + setToast('Error is adding filters to the Observability Dashboard', 'danger'); console.error(err.body.message); }); }; @@ -419,7 +419,7 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { setToast(`Visualization ${visualzationTitle} successfully added!`, 'success'); }) .catch((err) => { - setToast(`Error in adding ${visualzationTitle} visualization to the panel`, 'danger'); + setToast(`Error in adding ${visualzationTitle} visualization to the Dashboard`, 'danger'); console.error(err); }); }; @@ -472,7 +472,7 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { onClick={() => setPanelsMenuPopover(true)} disabled={addVizDisabled} > - Panel actions + Dashboard Actions ); @@ -507,7 +507,7 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { title: 'Panel actions', items: [ { - name: 'Reload panel', + name: 'Reload Dashboard', 'data-test-subj': 'reloadPanelContextMenuItem', onClick: () => { setPanelsMenuPopover(false); @@ -515,7 +515,7 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { }, }, { - name: 'Rename panel', + name: 'Rename Dashboard', 'data-test-subj': 'renamePanelContextMenuItem', onClick: () => { setPanelsMenuPopover(false); @@ -523,7 +523,7 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { }, }, { - name: 'Duplicate panel', + name: 'Duplicate Dashboard', 'data-test-subj': 'duplicatePanelContextMenuItem', onClick: () => { setPanelsMenuPopover(false); @@ -531,7 +531,7 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { }, }, { - name: 'Delete panel', + name: 'Delete Dashboard', 'data-test-subj': 'deletePanelContextMenuItem', onClick: () => { setPanelsMenuPopover(false); @@ -542,7 +542,7 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { }, ]; - // Fetch the custom panel on Initial Mount + // Fetch the Observability Dashboard on Initial Mount useEffect(() => { fetchCustomPanel(); }, [panelId]); diff --git a/public/components/custom_panels/custom_panel_view_so.tsx b/public/components/custom_panels/custom_panel_view_so.tsx index 3f6c61f302..823be4e969 100644 --- a/public/components/custom_panels/custom_panel_view_so.tsx +++ b/public/components/custom_panels/custom_panel_view_so.tsx @@ -80,7 +80,7 @@ import { import { coreRefs } from '../../framework/core_refs'; /* - * "CustomPanelsView" module used to render an Operational Panel + * "CustomPanelsView" module used to render an Observability Dashboard * * Props taken in as params are: * panelId: Name of the panel opened @@ -220,7 +220,7 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { onConfirm={onDelete} onCancel={closeModal} title={`Delete ${panel?.title}`} - message={`Are you sure you want to delete this Operational Panel?`} + message={`Are you sure you want to delete this Observability Dashboard?`} /> ); showModal(); @@ -228,7 +228,7 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { const renameCustomPanel = (editedCustomPanelName: string) => { if (!isNameValid(editedCustomPanelName)) { - setToast('Invalid Custom Panel name', 'danger'); + setToast('Invalid Observability Dashboard name', 'danger'); return Promise.reject(); } @@ -238,11 +238,11 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { .update(CUSTOM_PANELS_SAVED_OBJECT_TYPE, panel.id, panel) .then((res) => { setOpenPanelName(editedCustomPanelName); - setToast(`Operational Panel successfully renamed into "${editedCustomPanelName}"`); + setToast(`Observability Dashboard successfully renamed into "${editedCustomPanelName}"`); }) .catch((err) => { setToast( - 'Error renaming Operational Panel, please make sure you have the correct permission.', + 'Error renaming Observability Dashboard, please make sure you have the correct permission.', 'danger' ); console.error(err.body.message); @@ -260,7 +260,7 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { onRename, closeModal, 'Name', - 'Rename Panel', + 'Rename Dashboard', 'Cancel', 'Rename', panel.title, @@ -283,7 +283,7 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { onClone, closeModal, 'Name', - 'Duplicate Panel', + 'Duplicate Dashboard', 'Cancel', 'Duplicate', panel.title + ' (copy)', @@ -466,7 +466,7 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { onClick={() => setPanelsMenuPopover(true)} disabled={addVizDisabled} > - Panel actions + Dashboard Actions ); @@ -489,7 +489,7 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { try { dispatch(updatePanel(updatedPanel)); } catch (err) { - setToast('Error adding visualization to this panel', 'danger'); + setToast('Error adding visualization to this Dashboard', 'danger'); console.error(err?.body?.message || err); } }; @@ -531,7 +531,7 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { title: 'Panel actions', items: [ { - name: 'Reload panel', + name: 'Reload Dashboard', 'data-test-subj': 'reloadPanelContextMenuItem', onClick: () => { setPanelsMenuPopover(false); @@ -539,7 +539,7 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { }, }, { - name: 'Rename panel', + name: 'Rename Dashboard', 'data-test-subj': 'renamePanelContextMenuItem', onClick: () => { setPanelsMenuPopover(false); @@ -547,7 +547,7 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { }, }, { - name: 'Duplicate panel', + name: 'Duplicate Dashboard', 'data-test-subj': 'duplicatePanelContextMenuItem', onClick: () => { setPanelsMenuPopover(false); @@ -555,7 +555,7 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { }, }, { - name: 'Delete panel', + name: 'Delete Dashboard', 'data-test-subj': 'deletePanelContextMenuItem', onClick: () => { setPanelsMenuPopover(false); @@ -565,7 +565,7 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { ], }, ]; - // Fetch the custom panel on Initial Mount + // Fetch the Observability Dashboard on Initial Mount useEffect(() => { dispatch(fetchPanel(panelId)); }, []); diff --git a/public/components/custom_panels/helpers/modal_containers.tsx b/public/components/custom_panels/helpers/modal_containers.tsx index 0fb80a5979..cdc93226c9 100644 --- a/public/components/custom_panels/helpers/modal_containers.tsx +++ b/public/components/custom_panels/helpers/modal_containers.tsx @@ -67,14 +67,14 @@ export const getCloneModal = ( return ( -

Do you want to clone this operational panel?

+

Do you want to clone this Observability Dashboard?

); diff --git a/public/components/custom_panels/home.tsx b/public/components/custom_panels/home.tsx index 0714b56303..f5267803c7 100644 --- a/public/components/custom_panels/home.tsx +++ b/public/components/custom_panels/home.tsx @@ -98,7 +98,7 @@ export const Home = ({ // Creates a new CustomPanel const createCustomPanel = async (newCustomPanelName: string) => { if (!isNameValid(newCustomPanelName)) { - setToast('Invalid Operational Panel name', 'danger'); + setToast('Invalid Observability Dashboard name', 'danger'); return; } @@ -122,7 +122,7 @@ export const Home = ({ return coreSavedObjects.client .create('observability-panel', newPanel, {}) .then(async (res) => { - setToast(`Operational Panel "${newCustomPanelName}" successfully created!`); + setToast(`Observability Dashboard "${newCustomPanelName}" successfully created!`); window.location.assign(`${_.last(parentBreadcrumbs)!.href}${res.id}`); }) .catch((err) => { @@ -147,7 +147,7 @@ export const Home = ({ return http.get(`${CUSTOM_PANELS_API_PREFIX}/panels/${id}`); // .then((res) => res.operationalPanel) // .catch((err) => { - // console.error('Issue in fetching the operational panel to duplicate', err); + // console.error('Issue in fetching the Observability Dashboard to duplicate', err); // }); }; @@ -186,25 +186,25 @@ export const Home = ({ }); }; - // Deletes an existing Operational Panel + // Deletes an existing Observability Dashboard const deleteCustomPanel = async (customPanelId: string, customPanelName: string) => { return http .delete(`${CUSTOM_PANELS_API_PREFIX}/panels/` + customPanelId) .then((res) => { dispatch(fetchPanels()); - setToast(`Operational Panel "${customPanelName}" successfully deleted!`); + setToast(`Observability Dashboard "${customPanelName}" successfully deleted!`); return res; }) .catch((err) => { setToast( - 'Error deleting Operational Panel, please make sure you have the correct permission.', + 'Error deleting Observability Dashboard, please make sure you have the correct permission.', 'danger' ); console.error(err.body.message); }); }; - // Deletes an existing SO Operational Panel + // Deletes an existing SO Observability Dashboard const deleteCustomPanelSO = async (customPanelId: string, customPanelName: string) => { dispatch(deletePanel(customPanelId)); // TODO: toast here diff --git a/public/components/custom_panels/panel_modules/empty_panel.tsx b/public/components/custom_panels/panel_modules/empty_panel.tsx index 32a1226b76..dcebe55732 100644 --- a/public/components/custom_panels/panel_modules/empty_panel.tsx +++ b/public/components/custom_panels/panel_modules/empty_panel.tsx @@ -8,7 +8,7 @@ import React, { useState } from 'react'; import { AddVisualizationPopover } from '../helpers/add_visualization_popover'; /* - * EmptyPanelView - This Sub-component is shown to the user when a operational panel is empty + * EmptyPanelView - This Sub-component is shown to the user when a Observability Dashboard is empty * * Props taken in as params are: * addVizDisabled -> Boolean to enable/disable the add visualization button diff --git a/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout.tsx b/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout.tsx index 944db72377..c21cd61272 100644 --- a/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout.tsx +++ b/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout.tsx @@ -61,7 +61,7 @@ import './visualization_flyout.scss'; * VisaulizationFlyout - This module create a flyout to add visualization * * Props taken in as params are: - * panelId: panel Id of current operational panel + * panelId: panel Id of current Observability Dashboard * closeFlyout: function to close the flyout * start: start time in date filter * end: end time in date filter diff --git a/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout_so.tsx b/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout_so.tsx index c2db1d193b..5ffb427592 100644 --- a/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout_so.tsx +++ b/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout_so.tsx @@ -35,6 +35,7 @@ import { import _, { isError } from 'lodash'; import React, { useEffect, useState } from 'react'; import { v4 as uuidv4 } from 'uuid'; +import { useDispatch, useSelector } from 'react-redux'; import { FlyoutContainers } from '../../../common/flyout_containers'; import { displayVisualization, getQueryResponse, isDateValid } from '../../helpers/utils'; import { convertDateTime } from '../../helpers/utils'; @@ -52,13 +53,12 @@ import './visualization_flyout.scss'; import { uiSettingsService } from '../../../../../common/utils'; import { ILegacyScopedClusterClient } from '../../../../../../../src/core/server'; import { replaceVizInPanel, selectPanel } from '../../redux/panel_slice'; -import { useDispatch, useSelector } from 'react-redux'; /* * VisaulizationFlyoutSO - This module create a flyout to add visualization for SavedObjects custom Panels * * Props taken in as params are: - * panelId: panel Id of current operational panel + * panelId: panel Id of current Observability Dashboard * closeFlyout: function to close the flyout * start: start time in date filter * end: end time in date filter @@ -108,7 +108,6 @@ export const VisaulizationFlyoutSO = ({ replaceVisualizationId, addVisualizationPanel, }: VisualizationFlyoutSOProps) => { - const dispatch = useDispatch(); const panel = useSelector(selectPanel); diff --git a/public/components/custom_panels/redux/panel_slice.ts b/public/components/custom_panels/redux/panel_slice.ts index 4fa90f3129..ce99681c58 100644 --- a/public/components/custom_panels/redux/panel_slice.ts +++ b/public/components/custom_panels/redux/panel_slice.ts @@ -212,7 +212,7 @@ export const renameCustomPanel = (editedCustomPanelName: string, id: string) => getState ) => { if (!isNameValid(editedCustomPanelName)) { - console.log('Invalid Custom Panel name', 'danger'); + console.log('Invalid Observability Dashboard name', 'danger'); return Promise.reject(); } @@ -231,10 +231,10 @@ export const renameCustomPanel = (editedCustomPanelName: string, id: string) => // // if (renamedCustomPanel) renamedCustomPanel.name = editedCustomPanelName; // // return newCustomPanelData; // // }); - // // setToast(`Operational Panel successfully renamed into "${editedCustomPanelName}"`); + // // setToast(`Observability Dashboard successfully renamed into "${editedCustomPanelName}"`); // } catch (err) { // console.log( - // 'Error renaming Operational Panel, please make sure you have the correct permission.', + // 'Error renaming Observability Dashboard, please make sure you have the correct permission.', // 'danger' // ); // console.error(err.body.message); diff --git a/public/plugin.ts b/public/plugin.ts index 81b61c6576..7726e80de1 100644 --- a/public/plugin.ts +++ b/public/plugin.ts @@ -111,11 +111,11 @@ export class ObservabilityPlugin setupDeps.dashboard.registerDashboardProvider({ appId: 'observability-panel', savedObjectsType: 'observability-panel', - savedObjectsName: 'Observability Panel', + savedObjectsName: 'Observability', editUrlPathFn: (obj: SavedObject) => `/app/observability-dashboards#/${obj.id}/edit`, viewUrlPathFn: (obj: SavedObject) => `/app/observability-dashboards#/${obj.id}`, - createLinkText: 'Observability Panel', - createSortText: 'Observability Panel', + createLinkText: 'Observability Dashboard', + createSortText: 'Observability Dashboard', createUrl: '/app/observability-dashboards#/create', }); @@ -235,6 +235,7 @@ export class ObservabilityPlugin // Return methods that should be available to other plugins return {}; } + public start(core: CoreStart): ObservabilityStart { const pplService: PPLService = new PPLService(core.http); @@ -244,5 +245,6 @@ export class ObservabilityPlugin return {}; } + public stop() {} } From aab2f83b5b27c193756b82d05f93e7d31c30da81 Mon Sep 17 00:00:00 2001 From: Peter Fitzgibbons Date: Tue, 18 Apr 2023 11:17:37 -0700 Subject: [PATCH 2/5] Further Renames Signed-off-by: Peter Fitzgibbons --- .../visualization_flyout/visualization_flyout.tsx | 5 ++++- public/components/custom_panels/redux/panel_slice.ts | 2 +- public/components/metrics/top_menu/top_menu.tsx | 6 +++--- .../saved_object_savers/ppl/save_as_new_vis.ts | 4 ++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout.tsx b/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout.tsx index c21cd61272..99fb39112f 100644 --- a/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout.tsx +++ b/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout.tsx @@ -187,7 +187,10 @@ export const VisaulizationFlyout = ({ setToast(`Visualization ${newVisualizationTitle} successfully added!`, 'success'); }) .catch((err) => { - setToast(`Error in adding ${newVisualizationTitle} visualization to the panel`, 'danger'); + setToast( + `Error in adding ${newVisualizationTitle} visualization to the Dashboard`, + 'danger' + ); console.error(err); }); } else { diff --git a/public/components/custom_panels/redux/panel_slice.ts b/public/components/custom_panels/redux/panel_slice.ts index ce99681c58..981d5ae077 100644 --- a/public/components/custom_panels/redux/panel_slice.ts +++ b/public/components/custom_panels/redux/panel_slice.ts @@ -137,7 +137,7 @@ export const updatePanel = (panel: CustomPanelType) => async (dispatch, getState const panelList = getState().customPanel.panelList.map((p) => (p.id === panel.id ? panel : p)); dispatch(setPanelList(panelList)); } catch (err) { - console.log('Error updating panel', { err, panel }); + console.log('Error updating Dashboard', { err, panel }); } }; diff --git a/public/components/metrics/top_menu/top_menu.tsx b/public/components/metrics/top_menu/top_menu.tsx index cd3d17e3b3..8ab98fb2e3 100644 --- a/public/components/metrics/top_menu/top_menu.tsx +++ b/public/components/metrics/top_menu/top_menu.tsx @@ -21,8 +21,8 @@ import { } from '@elastic/eui'; import { DurationRange } from '@elastic/eui/src/components/date_picker/types'; import { useDispatch, useSelector } from 'react-redux'; -import { uiSettingsService } from '../../../../common/utils'; import React, { useEffect, useState } from 'react'; +import { uiSettingsService } from '../../../../common/utils'; import { MetricType } from '../../../../common/types/metrics'; import { resolutionOptions } from '../../../../common/constants/metrics'; import './top_menu.scss'; @@ -92,7 +92,7 @@ export const TopMenu = ({ const [originalPanelVisualizations, setOriginalPanelVisualizations] = useState([]); const [isSavePanelOpen, setIsSavePanelOpen] = useState(false); const [selectedPanelOptions, setSelectedPanelOptions] = useState< - EuiComboBoxOptionOption[] | undefined + Array> | undefined >([]); // toggle between panel edit mode @@ -206,7 +206,7 @@ export const TopMenu = ({ console.error(message, e); setToast('Issue in saving metrics', 'danger'); } - setToast('Saved metrics to panels successfully!'); + setToast('Saved metrics to Dashboards successfully!'); } }; diff --git a/public/services/saved_objects/saved_object_savers/ppl/save_as_new_vis.ts b/public/services/saved_objects/saved_object_savers/ppl/save_as_new_vis.ts index 9d3821740d..5ca6bb8c40 100644 --- a/public/services/saved_objects/saved_object_savers/ppl/save_as_new_vis.ts +++ b/public/services/saved_objects/saved_object_savers/ppl/save_as_new_vis.ts @@ -96,13 +96,13 @@ export class SaveAsNewVisualization extends SavedQuerySaver { .then((res: any) => { notifications.toasts.addSuccess({ title: 'Saved successfully.', - text: `Visualization '${saveTitle}' has been successfully saved to operation panels.`, + text: `Visualization '${saveTitle}' has been successfully saved to Observability Dashboards.`, }); }) .catch((error: any) => { notifications.toasts.addError(error, { title: 'Failed to save', - text: `Cannot add Visualization '${saveTitle}' to operation panels`, + text: `Cannot add Visualization '${saveTitle}' to Observability Dashboards`, }); }); } From e059545772745ab65ab934ed5966a3f29ad625f0 Mon Sep 17 00:00:00 2001 From: Peter Fitzgibbons Date: Mon, 17 Apr 2023 16:51:46 -0700 Subject: [PATCH 3/5] Recover Panel View Legacy - Duplicate Action (#376) Panel View SavedObject - Duplicate Action - protect render from invalid record - hide render while loading Signed-off-by: Peter Fitzgibbons Co-authored-by: Peter Fitzgibbons --- .../custom_panels/custom_panel_table.tsx | 13 ++-- .../custom_panels/custom_panel_view.tsx | 13 +--- .../custom_panels/custom_panel_view_so.tsx | 59 +++++++----------- .../custom_panels/helpers/utils.tsx | 13 ++++ public/components/custom_panels/home.tsx | 62 +------------------ .../custom_panels/redux/panel_slice.ts | 57 ++++++++++++----- 6 files changed, 89 insertions(+), 128 deletions(-) diff --git a/public/components/custom_panels/custom_panel_table.tsx b/public/components/custom_panels/custom_panel_table.tsx index 9ba6c69f8c..c0914e0b74 100644 --- a/public/components/custom_panels/custom_panel_table.tsx +++ b/public/components/custom_panels/custom_panel_table.tsx @@ -46,7 +46,13 @@ import { CustomPanelListType } from '../../../common/types/custom_panels'; import { getSampleDataModal } from '../common/helpers/add_sample_modal'; import { pageStyles } from '../../../common/constants/shared'; import { DeleteModal } from '../common/helpers/delete_modal'; -import { createPanel, fetchPanels, renameCustomPanel, selectPanelList } from './redux/panel_slice'; +import { + createPanel, + fetchPanels, + newPanelTemplate, + renameCustomPanel, + selectPanelList, +} from './redux/panel_slice'; /* * "CustomPanelTable" module, used to view all the saved panels @@ -65,7 +71,6 @@ import { createPanel, fetchPanels, renameCustomPanel, selectPanelList } from './ interface Props { loading: boolean; - createCustomPanel: (newCustomPanelName: string) => void; setBreadcrumbs: (newBreadcrumbs: ChromeBreadcrumb[]) => void; parentBreadcrumbs: EuiBreadcrumb[]; cloneCustomPanel: (newCustomPanelName: string, customPanelId: string) => void; @@ -75,7 +80,6 @@ interface Props { export const CustomPanelTable = ({ loading, - createCustomPanel, setBreadcrumbs, parentBreadcrumbs, cloneCustomPanel, @@ -118,7 +122,8 @@ export const CustomPanelTable = ({ }; const onCreate = async (newCustomPanelName: string) => { - createCustomPanel(newCustomPanelName); + const newPanel = newPanelTemplate(newCustomPanelName); + dispatch(createPanel(newPanel)); closeModal(); }; diff --git a/public/components/custom_panels/custom_panel_view.tsx b/public/components/custom_panels/custom_panel_view.tsx index 882b0fd7a7..99075358bf 100644 --- a/public/components/custom_panels/custom_panel_view.tsx +++ b/public/components/custom_panels/custom_panel_view.tsx @@ -213,19 +213,10 @@ export const CustomPanelView = (props: CustomPanelViewProps) => { }; const onDatePickerChange = (timeProps: OnTimeChangeProps) => { - onTimeChange( - timeProps.start, - timeProps.end, - recentlyUsedRanges, - setRecentlyUsedRanges, - setStartTime, - setEndTime - ); + const { updatedRanges } = onTimeChange(timeProps.start, timeProps.end, recentlyUsedRanges); setStartTime(timeProps.start); setEndTime(timeProps.end); - dispatch(updatePanel({ ...panel, timeRange: { from: timeProps.start, to: timeProps.end } })); - - setRecentlyUsedRanges(updatedRanges.slice(0, 9)); + setRecentlyUsedRanges(updatedRanges); onRefreshFilters(timeProps.start, timeProps.end); }; diff --git a/public/components/custom_panels/custom_panel_view_so.tsx b/public/components/custom_panels/custom_panel_view_so.tsx index 823be4e969..19eb6cde4d 100644 --- a/public/components/custom_panels/custom_panel_view_so.tsx +++ b/public/components/custom_panels/custom_panel_view_so.tsx @@ -42,7 +42,7 @@ import { CUSTOM_PANELS_API_PREFIX, CUSTOM_PANELS_SAVED_OBJECT_TYPE, } from '../../../common/constants/custom_panels'; -import { CustomPanelType } from '../../../common/types/custom_panels'; +import { CustomPanelType, PanelType } from '../../../common/types/custom_panels'; import { PanelGridSO } from './panel_modules/panel_grid/panel_grid_so'; import { getCustomModal } from './helpers/modal_containers'; @@ -69,7 +69,10 @@ import { DeleteModal } from '../common/helpers/delete_modal'; import { VisaulizationFlyoutSO } from './panel_modules/visualization_flyout/visualization_flyout_so'; import { addVisualizationPanel } from './helpers/add_visualization_helper'; import { + clonePanel, + createPanel, fetchPanel, + newPanelTemplate, selectPanel, setPanel, setPanelEt, @@ -147,6 +150,7 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { const dispatch = useDispatch(); const panel = useSelector(selectPanel); + const [loading, setLoading] = useState(true); const [pplFilterValue, setPPLFilterValue] = useState(''); const [baseQuery, setBaseQuery] = useState(''); @@ -226,34 +230,6 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { showModal(); }; - const renameCustomPanel = (editedCustomPanelName: string) => { - if (!isNameValid(editedCustomPanelName)) { - setToast('Invalid Observability Dashboard name', 'danger'); - return Promise.reject(); - } - - const updatedPanel = { ...panel, name: editedCustomPanelName }; - - return coreRefs.savedObjectsClient - .update(CUSTOM_PANELS_SAVED_OBJECT_TYPE, panel.id, panel) - .then((res) => { - setOpenPanelName(editedCustomPanelName); - setToast(`Observability Dashboard successfully renamed into "${editedCustomPanelName}"`); - }) - .catch((err) => { - setToast( - 'Error renaming Observability Dashboard, please make sure you have the correct permission.', - 'danger' - ); - console.error(err.body.message); - }); - }; - const onRename = async (newCustomPanelName: string) => { - const newPanel = { ...panel, title: newCustomPanelName }; - dispatch(updatePanel(newPanel)); - closeModal(); - }; - const renamePanel = () => { setModalLayout( getCustomModal( @@ -271,13 +247,11 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { }; const onClone = async (newCustomPanelName: string) => { - cloneCustomPanel(newCustomPanelName, panelId).then((id: string) => { - window.location.assign(`${last(parentBreadcrumbs)!.href}${id}`); - }); + dispatch(clonePanel(panel, newCustomPanelName)); closeModal(); }; - const clonePanel = () => { + const clonePanelModal = () => { setModalLayout( getCustomModal( onClone, @@ -551,7 +525,7 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { 'data-test-subj': 'duplicatePanelContextMenuItem', onClick: () => { setPanelsMenuPopover(false); - clonePanel(); + clonePanelModal(); }, }, { @@ -567,20 +541,27 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { ]; // Fetch the Observability Dashboard on Initial Mount useEffect(() => { + setLoading(true); dispatch(fetchPanel(panelId)); }, []); // Toggle input type (disabled or not disabled) // Disabled when there no visualizations in panels or when the panel is in edit mode useEffect(() => { - checkDisabledInputs(); - }, [isEditing]); + !loading && checkDisabledInputs(); + }, [isEditing, loading]); // Build base query with all of the indices included in the current visualizations useEffect(() => { + if (loading) { + if (panel.id === props.panelId) setLoading(false); + else return; + } + checkDisabledInputs(); buildBaseQuery(); - }, [panel]); + setLoading(false); + }, [panel, loading]); // Edit the breadcrumb when panel name changes useEffect(() => { @@ -600,7 +581,9 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => { chrome.setBreadcrumbs([...parentBreadcrumbs, ...newBreadcrumb]); }, [panelId, panel]); - return ( + return loading ? ( + <> + ) : (
diff --git a/public/components/custom_panels/helpers/utils.tsx b/public/components/custom_panels/helpers/utils.tsx index 16aa3e6bcc..266939d09f 100644 --- a/public/components/custom_panels/helpers/utils.tsx +++ b/public/components/custom_panels/helpers/utils.tsx @@ -515,3 +515,16 @@ export const displayVisualization = (metaData: any, data: any, type: string) => /> ); }; + +export const onTimeChange = ( + start: ShortDate, + end: ShortDate, + recentlyUsedRanges: DurationRange[] +) => { + const updatedRanges = recentlyUsedRanges.filter((recentlyUsedRange) => { + const isDuplicate = recentlyUsedRange.start === start && recentlyUsedRange.end === end; + return !isDuplicate; + }); + updatedRanges.unshift({ start, end }); + return { start, end, updatedRanges }; +}; diff --git a/public/components/custom_panels/home.tsx b/public/components/custom_panels/home.tsx index f5267803c7..8e9de6b1c0 100644 --- a/public/components/custom_panels/home.tsx +++ b/public/components/custom_panels/home.tsx @@ -30,9 +30,10 @@ import DSLService from '../../services/requests/dsl'; import PPLService from '../../services/requests/ppl'; import { CustomPanelTable } from './custom_panel_table'; import { CustomPanelView } from './custom_panel_view'; -import { CustomPanelViewSO } from './custom_panel_view_so'; import { isNameValid } from './helpers/utils'; -import { fetchPanels, uuidRx } from './redux/panel_slice'; +import { CustomPanelViewSO } from './custom_panel_view_so'; +import { coreRefs } from '../../framework/core_refs'; +import { deletePanel, fetchPanels, uuidRx } from './redux/panel_slice'; // import { ObjectFetcher } from '../common/objectFetcher'; @@ -95,62 +96,6 @@ export const Home = ({ window.location.assign(`${observabilityLogsID}#/explorer/${savedVisualizationId}`); }; - // Creates a new CustomPanel - const createCustomPanel = async (newCustomPanelName: string) => { - if (!isNameValid(newCustomPanelName)) { - setToast('Invalid Observability Dashboard name', 'danger'); - return; - } - - const newPanel: ObservabilityPanelAttrs = { - title: newCustomPanelName, - description: '', - dateCreated: new Date().getTime(), - dateModified: new Date().getTime(), - timeRange: { - to: 'now', - from: 'now-1d', - }, - queryFilter: { - query: '', - language: 'ppl', - }, - visualizations: [], - applicationId: '', - }; - - return coreSavedObjects.client - .create('observability-panel', newPanel, {}) - .then(async (res) => { - setToast(`Observability Dashboard "${newCustomPanelName}" successfully created!`); - window.location.assign(`${_.last(parentBreadcrumbs)!.href}${res.id}`); - }) - .catch((err) => { - setToast( - 'Please ask your administrator to enable Operational Panels for you.', - 'danger', - - Documentation - - ); - console.error('create error', err); - }); - }; - - const fetchSavedObjectPanel = async (id: string) => { - const soPanel = await coreRefs.savedObjectsClient?.get(CUSTOM_PANELS_SAVED_OBJECT_TYPE, id); - return savedObjectToCustomPanel(soPanel); - }; - - // Fetch Panel by id - const fetchLegacyPanel = async (id: string) => { - return http.get(`${CUSTOM_PANELS_API_PREFIX}/panels/${id}`); - // .then((res) => res.operationalPanel) - // .catch((err) => { - // console.error('Issue in fetching the Observability Dashboard to duplicate', err); - // }); - }; - const deletePanelSO = (customPanelIdList: string[]) => { const soPanelIds = customPanelIdList.filter((id) => id.match(uuidRx)); return Promise.all( @@ -280,7 +225,6 @@ export const Home = ({ return ( ({ + title: newName, + dateCreated: new Date().getTime(), + dateModified: new Date().getTime(), + visualizations: [], + queryFilter: { language: '', query: '' }, + timeRange: { from: 'now', to: 'now-1d' }, +}); + const initialState: InitialState = { id: '', - panel: { - id: '', - title: '', - visualizations: [], - dateCreated: 0, - dateModified: 0, - queryFilter: { language: '', query: '' }, - timeRange: { from: 'now', to: 'now-1d' }, - }, + panel: newPanelTemplate(''), panelList: [], + loadingFlag: false, }; export const panelSlice = createSlice({ @@ -59,7 +61,15 @@ export const { setPanel, setPanelList } = panelSlice.actions; export const panelReducer = panelSlice.reducer; -export const selectPanel = (rootState): CustomPanelType => rootState.customPanel.panel; +export const selectPanel = createSelector( + (rootState) => rootState.customPanel.panel, + (panel) => normalizedPanel(panel) +); + +const normalizedPanel = (panel): PanelType => ({ + ...newPanelTemplate(''), + ...panel, +}); export const selectPanelList = (rootState): CustomPanelType[] => rootState.customPanel.panelList; @@ -76,7 +86,6 @@ const fetchSavedObjectPanels$ = () => from(savedObjectPanelsClient.find()).pipe( mergeMap((res) => res.savedObjects), map(savedObjectToCustomPanel) - // tap((res) => console.log('panel', res)) ); const fetchObservabilityPanels$ = () => @@ -84,7 +93,6 @@ const fetchObservabilityPanels$ = () => mergeMap((res) => res), mergeMap((res) => res.panels as ObservabilityPanelAttrs[]), map((p: ObservabilityPanelAttrs) => ({ ...p, title: p.name, savedObject: false })) - // tap((res) => console.log('observability panels', res)) ); // Fetches all saved Custom Panels @@ -94,7 +102,6 @@ const fetchCustomPanels = async () => { fetchObservabilityPanels$() ).pipe( map((res) => { - console.log('fetchCustomPanels', res); return res as CustomPanelListType; }) ); @@ -104,14 +111,12 @@ const fetchCustomPanels = async () => { export const fetchPanels = () => async (dispatch, getState) => { const panels = await fetchCustomPanels(); - console.log('fetchPanels', { panels }); dispatch(setPanelList(panels)); }; export const fetchPanel = (id) => async (dispatch, getState) => { const soPanel = await savedObjectPanelsClient.get(id); const panel = savedObjectToCustomPanel(soPanel); - console.log('fetchPanel', panel); dispatch(setPanel(panel)); }; @@ -184,6 +189,26 @@ export const createPanel = (panel) => 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) => { + const { id, ...panelCopy } = { + ...panel, + title: newPanelName, + dateCreated: new Date().getTime(), + dateModified: new Date().getTime(), + } as PanelType; + + const newSOPanel = await savedObjectPanelsClient.create(panelCopy); + + const newPanel = savedObjectToCustomPanel(newSOPanel); + const panelList = getState().customPanel.panelList; + dispatch(setPanelList([...panelList, newPanel])); + dispatch(setPanel(newPanel)); + + window.location.replace(`#/${newPanel.id}`); }; const saveRenamedPanel = async (id, name) => { From bb1d7c4f164dcc84cc446e70239a880f0af08c09 Mon Sep 17 00:00:00 2001 From: Joshua Li Date: Mon, 17 Apr 2023 16:58:36 -0700 Subject: [PATCH 4/5] Organize imports on custom panels home file (#377) Signed-off-by: Joshua Li --- public/components/custom_panels/home.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/public/components/custom_panels/home.tsx b/public/components/custom_panels/home.tsx index 8e9de6b1c0..6c86318e26 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, EuiLink, ShortDate } from '@elastic/eui'; +import { EuiBreadcrumb, EuiGlobalToastList, ShortDate } from '@elastic/eui'; import { Toast } from '@elastic/eui/src/components/toast/global_toast_list'; -import _ from 'lodash'; import React, { ReactChild, useState } from 'react'; import { useDispatch } from 'react-redux'; // eslint-disable-next-line @osd/eslint/module_migration @@ -14,7 +13,6 @@ import { HashRouter, Route, RouteComponentProps, Switch } from 'react-router-dom import { CoreStart, SavedObjectsStart } from '../../../../../src/core/public'; import { CUSTOM_PANELS_API_PREFIX, - CUSTOM_PANELS_DOCUMENTATION_URL, CUSTOM_PANELS_SAVED_OBJECT_TYPE, } from '../../../common/constants/custom_panels'; import { @@ -24,15 +22,12 @@ import { OBSERVABILITY_BASE, SAVED_OBJECTS, } from '../../../common/constants/shared'; -import { ObservabilityPanelAttrs } from '../../../common/types/custom_panels'; import { coreRefs } from '../../framework/core_refs'; import DSLService from '../../services/requests/dsl'; import PPLService from '../../services/requests/ppl'; import { CustomPanelTable } from './custom_panel_table'; import { CustomPanelView } from './custom_panel_view'; -import { isNameValid } from './helpers/utils'; import { CustomPanelViewSO } from './custom_panel_view_so'; -import { coreRefs } from '../../framework/core_refs'; import { deletePanel, fetchPanels, uuidRx } from './redux/panel_slice'; // import { ObjectFetcher } from '../common/objectFetcher'; From 1a3489487bdb794ef4f48e9271534efd8e06b0c2 Mon Sep 17 00:00:00 2001 From: Shenoy Pratik Date: Mon, 17 Apr 2023 21:16:26 -0700 Subject: [PATCH 5/5] fix doc viewer flyout styling in explorer (#378) Signed-off-by: Shenoy Pratik --- .../explorer/events_views/doc_flyout.tsx | 18 ++--- .../events_views/surrounding_flyout.tsx | 68 ++++++++++--------- 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/public/components/event_analytics/explorer/events_views/doc_flyout.tsx b/public/components/event_analytics/explorer/events_views/doc_flyout.tsx index beba69089c..e7183cc4a0 100644 --- a/public/components/event_analytics/explorer/events_views/doc_flyout.tsx +++ b/public/components/event_analytics/explorer/events_views/doc_flyout.tsx @@ -123,14 +123,16 @@ export const DocFlyout = ({ const flyoutBody = ( - {populateDataGrid( - explorerFields, - getHeaders(explorerFields.queriedFields, DEFAULT_COLUMNS.slice(1), true), - {memorizedTds}, - getHeaders(explorerFields.selectedFields, DEFAULT_COLUMNS.slice(1), true), - {memorizedTds} - )} - +
+ {populateDataGrid( + explorerFields, + getHeaders(explorerFields.queriedFields, DEFAULT_COLUMNS.slice(1), true), + {memorizedTds}, + getHeaders(explorerFields.selectedFields, DEFAULT_COLUMNS.slice(1), true), + {memorizedTds} + )} + +
); diff --git a/public/components/event_analytics/explorer/events_views/surrounding_flyout.tsx b/public/components/event_analytics/explorer/events_views/surrounding_flyout.tsx index 4c67c3e199..e7fe8d9899 100644 --- a/public/components/event_analytics/explorer/events_views/surrounding_flyout.tsx +++ b/public/components/event_analytics/explorer/events_views/surrounding_flyout.tsx @@ -124,9 +124,11 @@ export const SurroundingFlyout = ({ }; const loadButton = (typeOfDocs: 'new' | 'old') => { - typeOfDocs === 'new' - ? loadData(typeOfDocs, numNewEvents + 5) - : loadData(typeOfDocs, valueOldEvents + 5); + if (typeOfDocs === 'new') { + loadData(typeOfDocs, numNewEvents + 5); + } else { + loadData(typeOfDocs, valueOldEvents + 5); + } }; const handleKeyDown = ( @@ -139,11 +141,11 @@ export const SurroundingFlyout = ({ }; const onChangeNewEvents = (e: React.ChangeEvent) => { - setNumNewEvents(parseInt(e.target.value)); + setNumNewEvents(parseInt(e.target.value, 10)); }; const onChangeOldEvents = (e: React.ChangeEvent) => { - setNumOldEvents(parseInt(e.target.value)); + setNumOldEvents(parseInt(e.target.value, 10)); }; const flyoutHeader = ( @@ -227,35 +229,37 @@ export const SurroundingFlyout = ({ const flyoutBody = ( - {getInputForm('arrowUp', onChangeNewEvents, numNewEvents, 'new')} - -
- {newEventsError !== '' && ( - - )} -
- {populateDataGrid( - explorerFields, - getHeaders(explorerFields.queriedFields, DEFAULT_COLUMNS.slice(1), true), - <> - {newEventsData} - {memorizedTds} - {oldEventsData} - , - getHeaders(explorerFields.selectedFields, DEFAULT_COLUMNS.slice(1), true), - <> - {newEventsData} - {memorizedTds} - {oldEventsData} - - )} -
- {oldEventsError !== '' && ( - +
+ {getInputForm('arrowUp', onChangeNewEvents, numNewEvents, 'new')} + +
+ {newEventsError !== '' && ( + + )} +
+ {populateDataGrid( + explorerFields, + getHeaders(explorerFields.queriedFields, DEFAULT_COLUMNS.slice(1), true), + <> + {newEventsData} + {memorizedTds} + {oldEventsData} + , + getHeaders(explorerFields.selectedFields, DEFAULT_COLUMNS.slice(1), true), + <> + {newEventsData} + {memorizedTds} + {oldEventsData} + )} +
+ {oldEventsError !== '' && ( + + )} +
+ + {getInputForm('arrowDown', onChangeOldEvents, valueOldEvents, 'old')}
- - {getInputForm('arrowDown', onChangeOldEvents, valueOldEvents, 'old')} );