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 all 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
80 changes: 47 additions & 33 deletions .cypress/integration/3_panels.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,15 @@ describe('Creating visualizations', () => {

describe('Testing panels table', () => {
beforeEach(() => {
moveToPanelHome();
eraseTestPanels();
moveToPanelHome();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do the erase panels before other things.

});

describe('Without Any Panels', () => {
beforeEach(() => {
moveToPanelHome();
});

it('Displays error toast for invalid panel name', () => {
clickCreatePanelButton();
confirmModal();
Expand All @@ -101,18 +105,25 @@ describe('Testing panels table', () => {
});

describe('with a Legacy Panel', () => {
it('Duplicates the legacy panel', () => {
beforeEach(() => {
createLegacyPanel();
moveToPanelHome();
});

it('Duplicates a legacy panel', () => {
cy.get('.euiTableRow').should('have.length', 1);
selectThePanel();
openActionsDropdown();
cy.get('button[data-test-subj="duplicateContextMenuItem"]').click();
cy.get('button[data-test-subj="runModalButton"]').click();
cy.contains(TEST_PANEL + ' (copy)').should('exist');
const duplicate = testPanelTableCell();
cy.get('.euiTableRow').should('have.length', 2);
const duplicateName = TEST_PANEL + ' (copy)';
cy.contains(duplicateName).should('exist');
const duplicate = cy.get('.euiLink').contains(duplicateName);
expectUuid(duplicate);
});

it('Renames the legacy panel', () => {
it('Renames the panel', () => {
createLegacyPanel();
cy.reload();
const cell = cy.get('.euiTableCellContent');
Expand All @@ -126,7 +137,7 @@ describe('Testing panels table', () => {
expectUuid(renamed);
});

it('Deletes the legacy panel', () => {
it('Deletes the panel', () => {
cy.get('input[data-test-subj="checkboxSelectAll"]').click();
openActionsDropdown();
cy.get('button[data-test-subj="deleteContextMenuItem"]').click();
Expand All @@ -142,21 +153,25 @@ describe('Testing panels table', () => {
});

describe('with a SavedObjects Panel', () => {
it.only('Duplicates a saved object panel', () => {
beforeEach(() => {
createSavedObjectPanel();
moveToPanelHome();
cy.get('.euiTableRow').should('have.length', 1);
});

it('Duplicates the panel', () => {
selectThePanel();
openActionsDropdown();
cy.get('button[data-test-subj="duplicateContextMenuItem"]').click();
cy.get('button[data-test-subj="runModalButton"]').click();
cy.contains(TEST_PANEL + ' (copy)').should('exist');
const duplicate = testPanelTableCell();
const duplicateName = TEST_PANEL + ' (copy)';
cy.get('.euiTableRow').should('have.length', 2);
cy.contains(duplicateName).should('exist');
const duplicate = cy.get('.euiLink').contains(duplicateName);
expectUuid(duplicate);
});

it('Renames a saved-objects panel', () => {
createSavedObjectPanel();
cy.reload();

selectThePanel();
openActionsDropdown();
cy.get('button[data-test-subj="renameContextMenuItem"]').click();
Expand All @@ -166,7 +181,7 @@ describe('Testing panels table', () => {
cy.get('button[data-test-subj="runModalButton"]').click();
});

it('Deletes saved object panels', () => {
it('Deletes the panel', () => {
createSavedObjectPanel();
cy.get('input[data-test-subj="checkboxSelectAll"]').click();
openActionsDropdown();
Expand Down Expand Up @@ -205,6 +220,7 @@ describe('Testing panels table', () => {
});

it('Create a panel for testing', () => {
moveToPanelHome();
// keep a panel for testing
clickCreatePanelButton();
cy.get('input.euiFieldText').focus().type(TEST_PANEL, {
Expand Down Expand Up @@ -258,7 +274,7 @@ describe('Testing a panel', () => {

cy.get(`input.euiFieldText[value="${TEST_PANEL} (copy)"]`)
.focus()
.clear({ force: true })
.clear({force: true})
.focus()
.type('Renamed Panel', {
delay: 200,
Expand Down Expand Up @@ -331,9 +347,9 @@ describe('Testing a panel', () => {

cy.get('h5[data-test-subj="visualizationHeader"]')
.contains(PPL_VISUALIZATIONS_NAMES[1])
.trigger('mousedown', { which: 1 })
.trigger('mousemove', { clientX: 1100, clientY: 0 })
.trigger('mouseup', { force: true });
.trigger('mousedown', {which: 1})
.trigger('mousemove', {clientX: 1100, clientY: 0})
.trigger('mouseup', {force: true});

cy.get('button[data-test-subj="savePanelButton"]').click();
cy.wait(delay * 3);
Expand All @@ -348,9 +364,9 @@ describe('Testing a panel', () => {

cy.get('.react-resizable-handle')
.eq(1)
.trigger('mousedown', { which: 1 })
.trigger('mousemove', { clientX: 2000, clientY: 800 })
.trigger('mouseup', { force: true });
.trigger('mousedown', {which: 1})
.trigger('mousemove', {clientX: 2000, clientY: 800})
.trigger('mouseup', {force: true});

cy.get('button[data-test-subj="savePanelButton"]').click();
cy.wait(delay * 3);
Expand Down Expand Up @@ -465,7 +481,7 @@ describe('Testing a panel', () => {
cy.get('[data-test-subj="eventExplorer__saveManagementPopover"]').trigger('mouseover').click();
cy.wait(1000);
cy.get('[data-test-subj="eventExplorer__querySaveName"]')
.clear({ force: true })
.clear({force: true})
.type(NEW_VISUALIZATION_NAME, {
delay: 200,
});
Expand Down Expand Up @@ -520,7 +536,7 @@ describe('Clean up all test data', () => {
});

const moveToEventsHome = () => {
cy.visit(`${Cypress.env('opensearchDashboards')}/app/observability-events#/`);
cy.visit(`${Cypress.env('opensearchDashboards')}/app/observability-logs#/`);
cy.wait(delay * 3);
};

Expand All @@ -531,7 +547,7 @@ const moveToPanelHome = () => {
cy.wait(delay * 3);
};

const testPanelTableCell = () => cy.get('.euiTableCellContent').contains(TEST_PANEL);
const testPanelTableCell = (name = TEST_PANEL) => cy.get('.euiTableCellContent').contains(name);

const moveToTestPanel = () => {
moveToPanelHome();
Expand Down Expand Up @@ -599,7 +615,7 @@ const eraseTestPanels = () => {
eraseLegacyPanels();
eraseSavedObjectPaenls();
};
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 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 clickCreatePanelButton = () =>
cy.get('a[data-test-subj="customPanels__createNewPanels"]').click();
Expand Down Expand Up @@ -649,16 +665,12 @@ const createLegacyPanel = () => {
});
};

const expectUuid = (cell) => {
cell.find('a').its('href').should('match', uuidRx);
// const id = url.split('/').slice(-1)
// expect(id).not.to.match(uuidRx)
const expectUuid = (anchorElem) => {
anchorElem.invoke('attr', 'href').should('match', uuidRx);
};

const expectLegacyId = (cell) => {
cell.find('a').its('href').should('not.match', uuidRx);
// const id = url.split('/').slice(-1)
// expect(id).not.to.match(uuidRx)
const expectLegacyId = (anchorElem) => {
anchorElem.invoke('attr', 'href').should('not.match', uuidRx);
};

const clickDeleteAction = () => {
Expand All @@ -670,7 +682,9 @@ const openActionsDropdown = () => {
};

const selectThePanel = () => {
cy.get('.euiCheckbox__input[title="Select this row"]').eq(0).trigger('mouseover').click();
cy.get('.euiCheckbox__input[title="Select this row"]').then(() => {
cy.get('.euiCheckbox__input[title="Select this row"]').check({ force: true });
});
};

const expectToastWith = (title) => {
Expand Down
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
13 changes: 5 additions & 8 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 Expand Up @@ -175,7 +172,7 @@ export const CustomPanelTable = ({
'Rename Panel',
'Cancel',
'Rename',
selectedCustomPanels[0].name,
selectedCustomPanels[0].title,
CREATE_PANEL_MESSAGE
)
);
Expand All @@ -191,7 +188,7 @@ export const CustomPanelTable = ({
'Duplicate Panel',
'Cancel',
'Duplicate',
selectedCustomPanels[0].name + ' (copy)',
selectedCustomPanels[0].title + ' (copy)',
CREATE_PANEL_MESSAGE
)
);
Expand Down
19 changes: 8 additions & 11 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,10 +208,13 @@ export const CustomPanelView = (props: CustomPanelViewProps) => {
};

const onDatePickerChange = (timeProps: OnTimeChangeProps) => {
const updatedRanges = prependRecentlyUsedRange(
onTimeChange(
timeProps.start,
timeProps.end,
recentlyUsedRanges
recentlyUsedRanges,
setRecentlyUsedRanges,
setStartTime,
setEndTime
);
setStartTime(timeProps.start);
setEndTime(timeProps.end);
Expand Down Expand Up @@ -645,8 +642,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
Loading