Skip to content

Commit

Permalink
Add Error handling on duplicate dashboard names (#441)
Browse files Browse the repository at this point in the history
* Add check for existing panel name

Signed-off-by: Rupal Mahajan <maharup@amazon.com>

* Nit

Signed-off-by: Rupal Mahajan <maharup@amazon.com>

* Remove double await

Signed-off-by: Rupal Mahajan <maharup@amazon.com>

* Add rename name check test

Signed-off-by: Rupal Mahajan <maharup@amazon.com>

* Remove test

Signed-off-by: Rupal Mahajan <maharup@amazon.com>

* Add unique id to sample panel name

Signed-off-by: Rupal Mahajan <maharup@amazon.com>

---------

Signed-off-by: Rupal Mahajan <maharup@amazon.com>
  • Loading branch information
rupal-bq authored May 4, 2023
1 parent 7a9f740 commit 58be126
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 12 deletions.
13 changes: 10 additions & 3 deletions public/components/custom_panels/custom_panel_table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { DeleteModal } from '../common/helpers/delete_modal';
import {
createPanel,
deletePanels,
doesNameExist,
fetchPanels,
isUuid,
newPanelTemplate,
Expand Down Expand Up @@ -120,7 +121,9 @@ export const CustomPanelTable = ({
};

const onCreate = async (newCustomPanelName: string) => {
if (!isNameValid(newCustomPanelName)) {
if (await doesNameExist(newCustomPanelName)) {
setToast(`Observability Dashboard with name "${newCustomPanelName}" already exists`, 'danger');
} else if (!isNameValid(newCustomPanelName)) {
setToast('Invalid Dashboard name', 'danger');
} else {
const newPanel = newPanelTemplate(newCustomPanelName);
Expand All @@ -130,7 +133,9 @@ export const CustomPanelTable = ({
};

const onRename = async (newCustomPanelName: string) => {
if (!isNameValid(newCustomPanelName)) {
if (await doesNameExist(newCustomPanelName)) {
setToast(`Observability Dashboard with name "${newCustomPanelName}" already exists`, 'danger');
} else if (!isNameValid(newCustomPanelName)) {
setToast('Invalid Dashboard name', 'danger');
} else {
dispatch(renameCustomPanel(newCustomPanelName, selectedCustomPanels[0].id));
Expand All @@ -139,7 +144,9 @@ export const CustomPanelTable = ({
};

const onClone = async (newName: string) => {
if (!isNameValid(newName)) {
if (await doesNameExist(newName)) {
setToast(`Observability Dashboard with name "${newName}" already exists`, 'danger');
} else if (!isNameValid(newName)) {
setToast('Invalid Operational Panel name', 'danger');
} else {
let sourcePanel = selectedCustomPanels[0];
Expand Down
5 changes: 4 additions & 1 deletion public/components/custom_panels/custom_panel_view_so.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import { VisaulizationFlyoutSO } from './panel_modules/visualization_flyout/visu
import {
clonePanel,
deletePanels,
doesNameExist,
fetchPanel,
renameCustomPanel,
selectPanel,
Expand Down Expand Up @@ -208,7 +209,9 @@ export const CustomPanelViewSO = (props: CustomPanelViewProps) => {
};

const onRename = async (newCustomPanelName: string) => {
if (!isNameValid(newCustomPanelName)) {
if (await doesNameExist(newCustomPanelName)) {
setToast(`Observability Dashboard with name "${newCustomPanelName}" already exists`, 'danger');
} else if (!isNameValid(newCustomPanelName)) {
setToast('Invalid Dashboard name', 'danger');
} else {
dispatch(renameCustomPanel(newCustomPanelName, panel.id));
Expand Down
20 changes: 12 additions & 8 deletions public/components/custom_panels/redux/panel_slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
addVisualizationPanel,
} from '../helpers/add_visualization_helper';
import { useToast } from '../../../../public/components/common/toast';
import { htmlIdGenerator } from '@elastic/eui';

interface InitialState {
id: string;
Expand Down Expand Up @@ -84,7 +85,7 @@ const normalizedPanel = (panel: CustomPanelType): CustomPanelType => ({

export const selectPanelList = (rootState): CustomPanelType[] => rootState.customPanel.panelList;

const {setToast} = useToast();
const { setToast } = useToast();

/*
** ASYNC DISPATCH FUNCTIONS
Expand Down Expand Up @@ -128,7 +129,7 @@ export const fetchPanel = (id) => async (dispatch, getState) => {
dispatch(setPanel(panel));
};

export const fetchVisualization = () => (dispatch, getState) => {};
export const fetchVisualization = () => (dispatch, getState) => { };

const updateLegacyPanel = (panel: CustomPanelType) =>
coreRefs.http!.post(`${CUSTOM_PANELS_API_PREFIX}/panels/update`, {
Expand All @@ -141,6 +142,10 @@ export const uuidRx = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a

export const isUuid = (id) => !!id.match(uuidRx);

export const doesNameExist = async (newCustomPanelName: string) => {
const panels = await fetchCustomPanels();
return (panels.some(({ title }: {title: string}) => title === newCustomPanelName));
}
export const updatePanel = (panel: CustomPanelType, successMsg: string, failureMsg: string) => async (dispatch, getState) => {
try {
if (isUuid(panel.id)) await updateSavedObjectPanel(panel);
Expand All @@ -151,7 +156,7 @@ export const updatePanel = (panel: CustomPanelType, successMsg: string, failureM
dispatch(setPanel(panel));
const panelList = getState().customPanel.panelList.map((p) => (p.id === panel.id ? panel : p));
dispatch(setPanelList(panelList));
} catch (e) {
} catch (e) {
if (failureMsg) {
setToast(failureMsg, 'danger')
}
Expand Down Expand Up @@ -193,7 +198,7 @@ export const replaceVizInPanel = (oldPanel, oldVizId, vizId, newVisualizationTit
const visualizationsWithNewPanel = addVisualizationPanel(vizId, oldVizId, allVisualizations);

const updatedPanel = { ...panel, visualizations: visualizationsWithNewPanel };

dispatch(updatePanel(updatedPanel, `Visualization ${newVisualizationTitle} successfully added!`, `Error in adding ${newVisualizationTitle} visualization to the panel`));
};

Expand All @@ -211,9 +216,8 @@ const deleteLegacyPanels = (customPanelIdList: string[]) => {
};

export const deletePanels = (panelsToDelete: CustomPanelType[]) => async (dispatch, getState) => {
const toastMessage = `Observability Dashboard${
panelsToDelete.length > 1 ? 's' : ' ' + panelsToDelete[0].title
} successfully deleted!`;
const toastMessage = `Observability Dashboard${panelsToDelete.length > 1 ? 's' : ' ' + panelsToDelete[0].title
} successfully deleted!`;
try {
const ids = panelsToDelete.map((p) => p.id);
await Promise.all([deleteLegacyPanels(ids), deletePanelSO(ids)]);
Expand Down Expand Up @@ -254,7 +258,7 @@ export const createPanelSample = (vizIds) => async (dispatch, getState) => {
...createDemoPanel(vizIds),
dateCreated: new Date().getTime(),
dateModified: new Date().getTime(),
title: samplePanelName,
title: htmlIdGenerator(samplePanelName)(),
};
const newSOPanel = await savedObjectPanelsClient.create(samplePanel);
const newPanel = savedObjectToCustomPanel(newSOPanel);
Expand Down

0 comments on commit 58be126

Please sign in to comment.