Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] Panels/Dashboard Duplicate Action fails when source is saved-object #361

Merged
merged 16 commits into from
Apr 17, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
402 changes: 210 additions & 192 deletions .cypress/integration/3_panels.spec.ts

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions cypress.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"baseUrl": "http://localhost:5602",
"baseUrl": "http://localhost:5601",
"video": true,
"chromeWebSecurity": true,
"fixturesFolder": ".cypress/fixtures",
Expand All @@ -17,7 +17,7 @@
"experimentalNetworkStubbing": true,
"env": {
"opensearch": "localhost:9200",
"opensearchDashboards": "localhost:5602",
"opensearchDashboards": "localhost:5601",
"security_enabled": true
},
"cypress-watch-and-reload": {
Expand Down
9 changes: 3 additions & 6 deletions public/components/custom_panels/custom_panel_table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,9 @@ export const CustomPanelTable = ({

const onClone = async (newName: string) => {
const sourcePanel = selectedCustomPanels[0];
console.log('onClone', { sourcePanel });
if (sourcePanel.savedObject) {
dispatch(createPanel({ ...sourcePanel, name: sourcePanel.name + ' (copy)', id: undefined }));
} else {
cloneCustomPanel(newName, selectedCustomPanels[0].id);
}
const { id, ...newPanel } = { ...sourcePanel, title: sourcePanel.title + ' (copy)' };

dispatch(createPanel(newPanel));
closeModal();
};

Expand Down
22 changes: 8 additions & 14 deletions public/components/custom_panels/custom_panel_view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import React, { useEffect, useState } from 'react';
import { DurationRange } from '@elastic/eui/src/components/date_picker/types';
import moment from 'moment';
import _ from 'lodash';
import { useDispatch, useSelector } from 'react-redux';
import DSLService from '../../services/requests/dsl';
import { CoreStart } from '../../../../../src/core/public';
import { EmptyPanelView } from './panel_modules/empty_panel';
Expand All @@ -49,10 +48,9 @@ import PPLService from '../../services/requests/ppl';
import {
isDateValid,
convertDateTime,
prependRecentlyUsedRange as onTimeChange,
onTimeChange,
isPPLFilterValid,
fetchVisualizationById,
prependRecentlyUsedRange,
} from './helpers/utils';
import { UI_DATE_FORMAT } from '../../../common/constants/shared';
import { VisaulizationFlyout } from './panel_modules/visualization_flyout';
Expand All @@ -66,7 +64,6 @@ import {
} from '../common/search/autocomplete_logic';
import { AddVisualizationPopover } from './helpers/add_visualization_popover';
import { DeleteModal } from '../common/helpers/delete_modal';
import { selectPanel, updatePanel } from './redux/panel_slice';

/*
* "CustomPanelsView" module used to render an Operational Panel
Expand Down Expand Up @@ -145,9 +142,6 @@ export const CustomPanelView = (props: CustomPanelViewProps) => {
onAddClick,
} = props;

const dispatch = useDispatch();
const panel = useSelector(selectPanel);

const [openPanelName, setOpenPanelName] = useState('');
const [panelCreatedTime, setPanelCreatedTime] = useState('');
const [pplFilterValue, setPPLFilterValue] = useState('');
Expand Down Expand Up @@ -214,14 +208,14 @@ export const CustomPanelView = (props: CustomPanelViewProps) => {
};

const onDatePickerChange = (timeProps: OnTimeChangeProps) => {
const updatedRanges = prependRecentlyUsedRange(
onTimeChange(
timeProps.start,
timeProps.end,
recentlyUsedRanges
recentlyUsedRanges,
setRecentlyUsedRanges,
setStartTime,
setEndTime
);
dispatch(updatePanel({ ...panel, timeRange: { from: timeProps.start, to: timeProps.end } }));

setRecentlyUsedRanges(updatedRanges.slice(0, 9));
onRefreshFilters(timeProps.start, timeProps.end);
};

Expand Down Expand Up @@ -643,8 +637,8 @@ export const CustomPanelView = (props: CustomPanelViewProps) => {
<EuiFlexItem grow={false}>
<EuiSuperDatePicker
dateFormat={uiSettingsService.get('dateFormat')}
start={panel.timeRange.from}
end={panel.timeRange.to}
start={startTime}
end={endTime}
onTimeChange={onDatePickerChange}
recentlyUsedRanges={recentlyUsedRanges}
isDisabled={dateDisabled}
Expand Down
51 changes: 0 additions & 51 deletions public/components/custom_panels/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,54 +161,6 @@ export const Home = ({
// });
};

// Clones an existing Custom Panel, return new Custom Panel id
const cloneCustomPanel = async (
clonedCustomPanelName: string,
clonedCustomPanelId: string
): Promise<string> => {
if (!isNameValid(clonedCustomPanelName)) {
setToast('Invalid Operational Panel name', 'danger');
return Promise.reject();
}

const fetchPanelFn = isUuid(clonedCustomPanelId) ? fetchSavedObjectPanel : fetchLegacyPanel;

try {
// const panelToClone = await fetchPanelfn(clonedCustomPanelId)
// const newPanel: PanelType = {
// ...panelToClone,
// title: clonedCustomPanelName,
// dateCreated: new Date().getTime(),
// dateModified: new Date().getTime()
// }
// const clonedPanel: CustomPanelType = await coreRefs.savedObjectsClient!.create(
// CUSTOM_PANELS_SAVED_OBJECT_TYPE, newPanel, { id: panelToClone.id }
// )
// setcustomPanelData((prevCustomPanelData) => {
// const newPanelData = [
// ...prevCustomPanelData,
// {
// id: clonedPanel.id,
// title: clonedCustomPanelName,
// dateCreated: clonedPanel.dateCreated,
// dateModified: clonedPanel.dateModified,
// },
// ];
// console.log("setcustomPanelData", newPanelData)
// return newPanelData
// });
// setToast(`Operational Panel "${clonedCustomPanelName}" successfully created!`);
// return clonedPanel.id;
} catch (err) {
setToast(
'Error cloning Operational Panel, please make sure you have the correct permission.',
'danger'
);
}

console.error(err.body.message);
};

const deletePanelSO = (customPanelIdList: string[]) => {
const soPanelIds = customPanelIdList.filter((id) => id.match(uuidRx));
return Promise.all(
Expand Down Expand Up @@ -340,7 +292,6 @@ export const Home = ({
createCustomPanel={createCustomPanel}
setBreadcrumbs={chrome.setBreadcrumbs}
parentBreadcrumbs={customPanelBreadCrumbs}
cloneCustomPanel={cloneCustomPanel}
deleteCustomPanelList={deleteCustomPanelList}
addSamplePanels={addSamplePanels}
/>
Expand All @@ -357,7 +308,6 @@ export const Home = ({
panelId={props.match.params.id}
chrome={chrome}
parentBreadcrumbs={customPanelBreadCrumbs}
cloneCustomPanel={cloneCustomPanel}
deleteCustomPanel={deleteCustomPanel}
setToast={setToast}
onEditClick={onEditClick}
Expand All @@ -373,7 +323,6 @@ export const Home = ({
chrome={chrome}
parentBreadcrumbs={customPanelBreadCrumbs}
// renameCustomPanel={renameCustomPanel}
cloneCustomPanel={cloneCustomPanel}
deleteCustomPanel={deleteCustomPanel}
setToast={setToast}
onEditClick={onEditClick}
Expand Down
45 changes: 22 additions & 23 deletions public/components/custom_panels/redux/panel_slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,18 @@ const fetchCustomPanels = async () => {
const panels$: Observable<CustomPanelListType> = concat(
fetchSavedObjectPanels$(),
fetchObservabilityPanels$()
).pipe(map((res) => {
console.log("fetchCustomPanels", res);
return res as CustomPanelListType
}));
).pipe(
map((res) => {
console.log('fetchCustomPanels', res);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove debug logs?

return res as CustomPanelListType;
})
);

return panels$.pipe(toArray()).toPromise();
};

export const fetchPanels = () => async (dispatch, getState) => {
const panels = await fetchCustomPanels()
const panels = await fetchCustomPanels();
console.log('fetchPanels', { panels });
dispatch(setPanelList(panels));
};
Expand All @@ -112,31 +114,27 @@ export const fetchPanel = (id) => async (dispatch, getState) => {

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

const updateLegacyPanel = (panel: CustomPanelType) => coreRefs.http!
.post(`${CUSTOM_PANELS_API_PREFIX}/panels/update`, {
const updateLegacyPanel = (panel: CustomPanelType) =>
coreRefs.http!.post(`${CUSTOM_PANELS_API_PREFIX}/panels/update`, {
body: JSON.stringify({ panelId: panel.id, panel: panel as PanelType }),
});

const updateSavedObjectPanel = (panel: CustomPanelType) => savedObjectPanelsClient.update(panel);


const uuidRx = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/;

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


export const updatePanel = (panel: CustomPanelType) => async (dispatch, getState) => {
try {
if (isUuid(panel.id))
await updateSavedObjectPanel(panel)
else
await updateLegacyPanel(panel)
if (isUuid(panel.id)) await updateSavedObjectPanel(panel);
else await updateLegacyPanel(panel);

dispatch(setPanel(panel));
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 panel', { err, panel });
}
};

Expand All @@ -147,12 +145,12 @@ export const deletePanel = (id) => async (dispatch, getState) => {
};

export const createPanel = (panel) => async (dispatch, getState) => {
const newPanel = await savedObjectPanelsClient.create(panel);
const panelList = getState().panelList;
const newSOPanel = await savedObjectPanelsClient.create(panel);
const newPanel = savedObjectToCustomPanel(newSOPanel);
const panelList = getState().customPanel.panelList;
dispatch(setPanelList([...panelList, newPanel]));
};


const saveRenamedPanel = async (id, name) => {
const renamePanelObject = {
panelId: id,
Expand All @@ -174,17 +172,18 @@ const saveRenamedPanelSO = async (id, name) => {
};

// Renames an existing CustomPanel
export const renameCustomPanel = (editedCustomPanelName: string, id: string) => async (dispatch, getState) => {
console.log("renameCustomPanel dispatched", { editedCustomPanelName, id })

export const renameCustomPanel = (editedCustomPanelName: string, id: string) => async (
dispatch,
getState
) => {
if (!isNameValid(editedCustomPanelName)) {
console.log('Invalid Custom Panel name', 'danger');
return Promise.reject();
}

const panel = getState().customPanel.panelList.find(p => p.id === id)
const updatedPanel = { ...panel, title: editedCustomPanelName }
dispatch(updatePanel(updatedPanel))
const panel = getState().customPanel.panelList.find((p) => p.id === id);
const updatedPanel = { ...panel, title: editedCustomPanelName };
dispatch(updatePanel(updatedPanel));

// try {
// // await savePanelFn(editedCustomPanelId, editedCustomPanelName);
Expand Down
2 changes: 1 addition & 1 deletion public/components/event_analytics/home/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ const EventAnalyticsHome = (props: IHomeProps) => {
await dispatchInitialData(newTabId);

// redirect to explorer
history.push('/');
history.push('/explorer');
};

const handleQueryChange = async (query: string) => setSearchQuery(query);
Expand Down
4 changes: 2 additions & 2 deletions public/components/event_analytics/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,14 @@ export const EventAnalytics = ({
<HashRouter>
<Switch>
<Route
path={[`/:id`]}
path={[`/explorer/:id`, '/explorer']}
render={(routerProps) => {
chrome.setBreadcrumbs([
...parentBreadcrumbs,
eventAnalyticsBreadcrumb,
{
text: 'Explorer',
href: `#/event_analytics/explorer`,
href: `#/`,
},
]);
return (
Expand Down