From 3356449d6310d747e9e00a4d71b4cd3fe711caec Mon Sep 17 00:00:00 2001 From: Eugene Lee Date: Thu, 31 Mar 2022 10:33:45 -0700 Subject: [PATCH] Modularize and cleanup panel (#603) Signed-off-by: Eugene Lee --- .../integration/app_analytics.spec.js | 191 ++++++++- .../.cypress/integration/panels.spec.js | 30 +- .../.cypress/utils/app_constants.js | 22 +- .../components/application.tsx | 10 +- .../__tests__/custom_panel_view.test.tsx | 8 + .../custom_panels/custom_panel_view.tsx | 314 +++++--------- .../helpers/add_visualization_popover.tsx | 81 ++++ .../public/components/custom_panels/home.tsx | 9 +- .../__snapshots__/empty_panel.test.tsx.snap | 396 ++++++++---------- .../__tests__/empty_panel.test.tsx | 19 +- .../panel_modules/empty_panel.tsx | 83 +--- .../__snapshots__/panel_grid.test.tsx.snap | 1 + .../panel_grid/__tests__/panel_grid.test.tsx | 4 + .../panel_modules/panel_grid/panel_grid.tsx | 42 +- .../visualization_container.test.tsx | 4 + .../visualization_container.tsx | 12 +- .../visualization_flyout.test.tsx.snap | 26 +- .../__tests__/visualization_flyout.test.tsx | 2 - .../visualization_flyout.tsx | 8 +- .../paragraph_components/para_output.tsx | 4 + 20 files changed, 684 insertions(+), 582 deletions(-) create mode 100644 dashboards-observability/public/components/custom_panels/helpers/add_visualization_popover.tsx diff --git a/dashboards-observability/.cypress/integration/app_analytics.spec.js b/dashboards-observability/.cypress/integration/app_analytics.spec.js index 7d268d08c..0d9aac50d 100644 --- a/dashboards-observability/.cypress/integration/app_analytics.spec.js +++ b/dashboards-observability/.cypress/integration/app_analytics.spec.js @@ -22,10 +22,14 @@ import { trace_one, trace_two, trace_three, - spanQueryPartOne, - spanQueryPartTwo, - spanQueryPartThree, - visName, + spanQueryOnePartOne, + spanQueryOnePartTwo, + spanQueryOnePartThree, + spanQueryTwoPartOne, + spanQueryTwoPartTwo, + spanQueryTwoPartThree, + visOneName, + visTwoName, composition, newName, } from '../utils/app_constants'; @@ -95,10 +99,24 @@ describe('Creating application', () => { cy.get('.euiBadge').contains('2').should('exist'); cy.get('.euiButton').contains('Create').should('not.be.disabled'); cy.get('.euiButton').contains('Create').click(); - cy.wait(delay); + cy.wait(delay*3); cy.get('.euiTitle').contains(nameOne).should('exist'); cy.get('.euiTab').contains('Panel').click(); - cy.get('.euiText').contains('Start by adding metrics').should('exist'); + cy.get('.euiText').contains('Start by adding your first visualization').should('exist'); + }); + + it('Hides application panels in Operational Panels', () => { + cy.visit( + `${Cypress.env('opensearchDashboards')}/app/observability-dashboards#/operational_panels/` + ); + cy.wait(delay*4); + if (cy.get('.euiButton').contains('Create panel').length < 2) { + cy.get('input.euiFieldSearch').type(`${nameOne}'s Panel`); + cy.wait(delay); + cy.get('.euiTableCellContent__text').contains('No items found').should('exist'); + cy.get('.euiFormControlLayoutClearButton').click(); + cy.wait(delay); + } }); it('Redirects to home page on cancel', () => { @@ -276,6 +294,7 @@ describe('Viewing application', () => { it('Opens span detail flyout when Span ID is clicked', () => { cy.get('.euiTab').contains('Traces & Spans').click(); + supressResizeObserverIssue(); cy.wait(delay); cy.get('.euiLink').contains('5ff3516909562c60').click(); cy.get('.euiFlyout').contains('Span detail').should('be.visible'); @@ -296,21 +315,23 @@ describe('Viewing application', () => { cy.get('.euiBadge__text').contains('Base Query').should('exist'); }); - it('Saves visualization to panel', () => { - cy.get('.euiTab').contains('Log Events').click(); + it('Saves visualization #1 to panel', () => { + cy.get('.euiTab').contains('Panel').click(); + cy.get('.euiButton').eq(3).contains('Add').click(); + cy.wait(delay); cy.get('.plot-container').should('exist'); cy.get('[data-test-subj="searchAutocompleteTextArea"]').click(); cy.get('.aa-List').find('.aa-Item').should('have.length', 11); cy.get('[data-test-subj="searchAutocompleteTextArea"]').type('x'); - cy.get('[data-test-subj="searchAutocompleteTextArea"]').clear().wait(delay * 2).type(spanQueryPartOne); - cy.get('[data-test-subj="searchAutocompleteTextArea"]').wait(delay * 2).type(spanQueryPartTwo); - cy.get('[data-test-subj="searchAutocompleteTextArea"]').wait(delay * 2).type(spanQueryPartThree); - changeTimeTo24('hours'); - cy.get('.euiButton').contains('Refresh').click(); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').clear().wait(delay * 2).type(spanQueryOnePartOne); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').wait(delay * 2).type(spanQueryOnePartTwo); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').wait(delay * 2).type(spanQueryOnePartThree); + changeTimeTo24('months'); cy.get('.euiTab').contains('Visualizations').click(); supressResizeObserverIssue(); cy.get('[data-test-subj="eventExplorer__saveManagementPopover"]').click(); - cy.get('[data-test-subj="eventExplorer__querySaveName"]').click().type(visName); + cy.get('[data-test-subj="eventExplorer__querySaveName"]').click().type(visOneName); + cy.wait(delay); cy.get('[data-test-subj="eventExplorer__querySaveConfirm"]').click(); cy.wait(delay); cy.get('.euiTab').contains('Panel').click(); @@ -318,14 +339,14 @@ describe('Viewing application', () => { cy.get('.js-plotly-plot').should('exist'); }); - it('Adds availability level to visualization', () => { + it('Adds availability level to visualization #1', () => { cy.get('.euiTab').contains('Panel').click(); cy.wait(delay); cy.get('[aria-label="actionMenuButton"]').click(); cy.get('.euiContextMenuItem').contains('Edit').click(); supressResizeObserverIssue(); cy.wait(delay); - cy.get('[data-test-subj="superDatePickerShowDatesButton"]').should('contain', 'Last 24 hours'); + cy.get('[data-test-subj="superDatePickerShowDatesButton"]').should('contain', 'Last 24 months'); cy.get('.euiBadge').contains('Bar').click(); cy.focused().type('{downArrow}'); cy.focused().type('{enter}'); @@ -346,14 +367,152 @@ describe('Viewing application', () => { cy.wait(delay); cy.get('.js-plotly-plot').should('exist'); cy.get('.textpoint').contains('Available').should('exist'); + cy.get('.euiBreadcrumb').contains('Application analytics').click(); + cy.wait(delay); + cy.get('.euiBadge').contains('Available').should('exist'); + cy.get('[style="background-color: rgb(84, 179, 153); color: rgb(0, 0, 0);"]').should('exist'); + }); + + it('Saves visualization #2 to panel with availability level', () => { + moveToApplication(nameOne); + changeTimeTo24('months'); + cy.get('.euiTab').contains('Log Events').click(); + cy.wait(delay); + cy.get('.plot-container').should('exist'); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').clear(); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').type('x'); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').clear().wait(delay * 2).type(spanQueryTwoPartOne); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').wait(delay * 2).type(spanQueryTwoPartTwo); + cy.get('[data-test-subj="searchAutocompleteTextArea"]').wait(delay * 2).type(spanQueryTwoPartThree); + cy.get('.euiButton').contains('Refresh').click(); + cy.wait(delay); + cy.get('.euiTab').contains('Visualizations').click(); + supressResizeObserverIssue(); + cy.get('.euiBadge').contains('Bar').click(); + cy.focused().type('{downArrow}'); + cy.focused().type('{enter}'); + cy.wait(delay); + cy.get('.euiButton').contains('+ Add availability level').click(); + cy.get('[data-test-subj="colorPickerAnchor"]').click(); + cy.get('[aria-label="Select #9170B8 as the color"]').click(); + cy.wait(delay); + cy.get('[data-test-subj="nameFieldText"]').click().type('Super'); + cy.get('[data-test-subj="expressionSelect"]').select('<'); + cy.get('[data-test-subj="valueFieldNumber"]').clear().type('5.5'); + cy.get('[data-test-subj="visualizeEditorRenderButton"]').click(); + cy.wait(delay); + cy.get('.euiButton').contains('+ Add availability level').click(); + cy.get('[data-test-subj="colorPickerAnchor"]').first().click(); + cy.get('[aria-label="Select #CA8EAE as the color"]').click(); + cy.wait(delay); + cy.get('[data-test-subj="nameFieldText"]').first().click().type('Cool'); + cy.get('[data-test-subj="expressionSelect"]').first().select('>'); + cy.get('[data-test-subj="valueFieldNumber"]').first().clear().type('0'); + cy.get('[data-test-subj="visualizeEditorRenderButton"]').click(); + cy.wait(delay); + cy.get('[data-test-subj="eventExplorer__saveManagementPopover"]').click(); + cy.get('[data-test-subj="eventExplorer__querySaveName"]').click().type(visTwoName); + cy.wait(delay); + cy.get('[data-test-subj="eventExplorer__querySaveConfirm"]').click(); + cy.wait(delay); + cy.get('.euiTab').contains('Panel').click(); + cy.wait(delay); + cy.get('.js-plotly-plot').should('have.length', 2); + moveToHomePage(); + cy.get('.euiBadge').contains('Super').should('exist'); + cy.get('[style="background-color: rgb(145, 112, 184); color: rgb(0, 0, 0);"]').should('exist'); }); it('Configuration tab shows details', () => { + cy.get('.euiLink').contains(nameOne).click(); + cy.wait(delay); cy.get('.euiTab').contains('Configuration').click(); cy.wait(delay); cy.get('.euiCodeBlock__code').contains(baseQuery).should('exist'); cy.get('[aria-label="List of services and entities"]').find('li').should('have.length', 1); cy.get('[aria-label="List of trace groups"]').find('li').should('have.length', 2); + cy.get('option').should('have.length', 2); + }); + + + it('Changes availability visualization', () => { + cy.get('.euiTab').contains('Configuration').click(); + cy.wait(delay); + cy.get('select').select(visOneName); + cy.wait(delay); + moveToHomePage(); + cy.get('.euiBadge').contains('Available').should('exist'); + cy.get('[style="background-color: rgb(84, 179, 153); color: rgb(0, 0, 0);"]').should('exist'); + moveToApplication(nameOne); + cy.get('.euiTab').contains('Configuration').click(); + cy.wait(delay); + cy.get('select').find('option:selected').should('have.text', visOneName); + }) + + it('Hides application visualizations in Event Analytics', () => { + cy.visit(`${Cypress.env('opensearchDashboards')}/app/observability-dashboards#/event_analytics`); + cy.wait(delay*3); + if (cy.get('.euiFieldSearch').length > 1) { + cy.get('input.euiFieldSearch').type(visOneName); + cy.wait(delay); + cy.get('.euiTableCellContent__text').contains('No items found').should('exist'); + cy.get('input.euiFieldSearch').clear().type(visTwoName); + cy.wait(delay); + cy.get('.euiTableCellContent__text').contains('No items found').should('exist'); + cy.get('.euiFormControlLayoutClearButton').click(); + cy.wait(delay); + cy.get('[data-test-subj="tablePaginationPopoverButton"]').click(); + cy.get('.euiContextMenuItem__text').contains('50 rows').click(); + cy.get('.euiCheckbox__input[data-test-subj="checkboxSelectAll"]').click(); + cy.wait(delay); + cy.get('.euiButton__text').contains('Actions').click(); + cy.wait(delay); + cy.get('.euiContextMenuItem__text').contains('Delete').click(); + cy.wait(delay); + + cy.get('button.euiButton--danger').should('be.disabled'); + + cy.get('input.euiFieldText[placeholder="delete"]').type('delete'); + cy.get('button.euiButton--danger').should('not.be.disabled'); + cy.get('.euiButton__text').contains('Delete').click(); + cy.wait(delay); + } + }); + + it('Hides application visualizations in Operational Panels', () => { + cy.visit( + `${Cypress.env('opensearchDashboards')}/app/observability-dashboards#/operational_panels/` + ); + cy.wait(delay*3); + cy.get('.euiButton__text').contains('Actions').click(); + cy.wait(delay); + cy.get('.euiContextMenuItem__text').contains('Add samples').click(); + cy.wait(delay); + cy.get('.euiButton__text').contains('Yes').click(); + cy.wait(delay*2); + cy.get('.euiLink').contains('[Logs] Web traffic Panel').first().click(); + cy.wait(delay); + cy.get('.euiButton__text').contains('Add visualization').click(); + cy.get('.euiContextMenuItem__text').contains('Select existing visualization').click(); + cy.get('option').contains(visOneName).should('not.exist'); + cy.get('option').contains(visTwoName).should('not.exist'); + cy.visit( + `${Cypress.env('opensearchDashboards')}/app/observability-dashboards#/operational_panels/` + ); + cy.wait(delay*3); + cy.get('input.euiFieldSearch').type('[Logs] Web traffic Panel'); + cy.wait(delay); + cy.get('.euiTableRow').first().within(($row) => { + cy.get('.euiCheckbox').click(); + }); + cy.get('.euiButton__text').contains('Actions').click(); + cy.wait(delay); + cy.get('.euiContextMenuItem__text').contains('Delete').click(); + cy.wait(delay); + cy.get('input.euiFieldText[placeholder="delete"]').type('delete'); + cy.get('button.euiButton--danger').should('not.be.disabled'); + cy.get('.euiButton__text').contains('Delete').click(); + cy.wait(delay); }); }); diff --git a/dashboards-observability/.cypress/integration/panels.spec.js b/dashboards-observability/.cypress/integration/panels.spec.js index 038472413..42a9eb871 100644 --- a/dashboards-observability/.cypress/integration/panels.spec.js +++ b/dashboards-observability/.cypress/integration/panels.spec.js @@ -183,6 +183,24 @@ describe('Testing a panel', () => { moveToTestPanel(); }); + it('Opens visualization flyout from empty panel', () => { + cy.get('.euiButton').eq(4).contains('Add visualization').click(); + cy.wait(delay); + cy.get('.euiContextMenuItem__text').contains('Select existing visualization').click(); + cy.wait(delay); + cy.get('.euiButton').contains('Cancel').click(); + cy.get('.euiButton').eq(2).contains('Add visualization').click(); + cy.wait(delay); + cy.get('.euiContextMenuItem__text').contains('Select existing visualization').click(); + cy.wait(delay); + cy.get('.euiButton').contains('Cancel').click(); + cy.get('.euiButton').contains('Add visualization').first().click(); + cy.get('.euiContextMenuItem__text').contains('Create new visualization').click(); + cy.wait(delay); + cy.get('.euiBreadcrumb').contains('Explorer').should('exist'); + cy.get('.euiCallOut').contains('No results match your search criteria').should('exist'); + }); + it('Redirects to correct page on breadcrumb click', () => { moveToTestPanel(); cy.get('.euiBreadcrumb').contains(TEST_PANEL).click(); @@ -240,9 +258,9 @@ describe('Testing a panel', () => { }); it('Add existing visualization #1', () => { - cy.get('.euiButton__text').contains('Add Visualization').click(); + cy.get('.euiButton__text').contains('Add visualization').click(); cy.wait(delay); - cy.get('.euiContextMenuItem__text').contains('Select Existing Visualization').click(); + cy.get('.euiContextMenuItem__text').contains('Select existing visualization').click(); cy.wait(delay); cy.get('select').select(PPL_VISUALIZATIONS_NAMES[0]); cy.get('button[aria-label="refreshPreview"]').click(); @@ -254,9 +272,9 @@ describe('Testing a panel', () => { }); it('Add existing visualization #2', () => { - cy.get('.euiButton__text').contains('Add Visualization').click(); + cy.get('.euiButton__text').contains('Add visualization').click(); cy.wait(delay); - cy.get('.euiContextMenuItem__text').contains('Select Existing Visualization').click(); + cy.get('.euiContextMenuItem__text').contains('Select existing visualization').click(); cy.wait(delay); cy.get('select').select(PPL_VISUALIZATIONS_NAMES[1]); cy.get('button[aria-label="refreshPreview"]').click(); @@ -367,9 +385,9 @@ describe('Testing a panel', () => { }); it('Create new visualization and add to panel', () => { - cy.get('.euiButton__text').contains('Add Visualization').click(); + cy.get('.euiButton__text').contains('Add visualization').click(); cy.wait(delay); - cy.get('.euiContextMenuItem__text').contains('Create New Visualization').click(); + cy.get('.euiContextMenuItem__text').contains('Create new visualization').click(); cy.wait(delay * 3); cy.url().should('match', new RegExp('(.*)#/event_analytics/explorer')); cy.get('[id^=autocomplete-textarea]').type(PPL_VISUALIZATIONS[2]); diff --git a/dashboards-observability/.cypress/utils/app_constants.js b/dashboards-observability/.cypress/utils/app_constants.js index ae8e86fa6..70a8d220a 100644 --- a/dashboards-observability/.cypress/utils/app_constants.js +++ b/dashboards-observability/.cypress/utils/app_constants.js @@ -5,7 +5,7 @@ import { supressResizeObserverIssue } from './constants'; -export const delay = 700; +export const delay = 1000; export const moveToHomePage = () => { cy.visit(`${Cypress.env('opensearchDashboards')}/app/observability-dashboards#/application_analytics/`); @@ -45,6 +45,7 @@ export const changeTimeTo24 = (timeUnit) => { cy.get('[aria-label="Time unit"]').select(timeUnit); cy.get('.euiButton').contains('Apply').click(); cy.wait(delay); + cy.get('.euiButton').contains('Refresh').click(); }; export const expectMessageOnHover = (message) => { @@ -52,6 +53,13 @@ export const expectMessageOnHover = (message) => { cy.get('.euiToolTipPopover').contains(message).should('exist'); }; +export const moveToPanelHome = () => { + cy.visit( + `${Cypress.env('opensearchDashboards')}/app/observability-dashboards#/operational_panels/` + ); + cy.wait(delay * 3); +}; + export const baseQuery = 'source = opensearch_dashboards_sample_data_flights'; export const nameOne = 'Cypress'; export const nameTwo = 'Pine'; @@ -61,9 +69,13 @@ export const service_two = 'payment'; export const trace_one = 'HTTP POST'; export const trace_two = 'HTTP GET'; export const trace_three = 'client_pay_order'; -export const spanQueryPartOne = 'where DestCityName '; -export const spanQueryPartTwo = '= "Venice" | stats count() by span( timestamp '; -export const spanQueryPartThree = ', 6h )'; -export const visName = 'Flights to Venice'; +export const spanQueryOnePartOne = 'where DestCityName '; +export const spanQueryOnePartTwo = '= "Venice" | stats count() by span( timestamp '; +export const spanQueryOnePartThree = ', 6h )'; +export const spanQueryTwoPartOne = 'where OriginCityName '; +export const spanQueryTwoPartTwo = '= "Seoul" | stats count() by span( timestamp '; +export const spanQueryTwoPartThree = ', 6h )'; +export const visOneName = 'Flights to Venice'; +export const visTwoName = 'Flights from Seoul'; export const composition = 'order, payment, HTTP POST, HTTP GET, client_pay_order' export const newName = 'Monterey Cypress'; \ No newline at end of file diff --git a/dashboards-observability/public/components/application_analytics/components/application.tsx b/dashboards-observability/public/components/application_analytics/components/application.tsx index cf8678ea3..582d181cd 100644 --- a/dashboards-observability/public/components/application_analytics/components/application.tsx +++ b/dashboards-observability/public/components/application_analytics/components/application.tsx @@ -384,6 +384,10 @@ export function Application(props: AppDetailProps) { ); }; + const onEditClick = (savedVisualizationId: string) => { + switchToEditViz(savedVisualizationId); + }; + const getPanel = () => { return ( undefined} cloneCustomPanel={async () => Promise.reject()} deleteCustomPanel={async () => Promise.reject()} setToast={setToasts} page="app" - appName={application.name} appId={appId} startTime={appStartTime} endTime={appEndTime} setStartTime={setStartTimeForApp} setEndTime={setEndTimeForApp} - switchToEvent={switchToEvent} - switchToEditViz={switchToEditViz} + onAddClick={switchToEvent} + onEditClick={onEditClick} /> ); }; diff --git a/dashboards-observability/public/components/custom_panels/__tests__/custom_panel_view.test.tsx b/dashboards-observability/public/components/custom_panels/__tests__/custom_panel_view.test.tsx index c5c3d3df0..3ad38f26d 100644 --- a/dashboards-observability/public/components/custom_panels/__tests__/custom_panel_view.test.tsx +++ b/dashboards-observability/public/components/custom_panels/__tests__/custom_panel_view.test.tsx @@ -42,6 +42,9 @@ describe.skip('Panels View Component', () => { const cloneCustomPanel = jest.fn(); const deleteCustomPanel = jest.fn(); const setToast = jest.fn(); + const onEditClick = (savedVisId: string) => { + window.location.assign(`#/event_analytics/explorer/${savedVisId}`); + }; const wrapper = mount( { cloneCustomPanel={cloneCustomPanel} deleteCustomPanel={deleteCustomPanel} setToast={setToast} + onEditClick={onEditClick} startTime={start} endTime={end} setStartTime={setStart} @@ -97,6 +101,9 @@ describe.skip('Panels View Component', () => { const cloneCustomPanel = jest.fn(); const deleteCustomPanel = jest.fn(); const setToast = jest.fn(); + const onEditClick = (savedVisId: string) => { + window.location.assign(`#/event_analytics/explorer/${savedVisId}`); + }; const wrapper = mount( { cloneCustomPanel={cloneCustomPanel} deleteCustomPanel={deleteCustomPanel} setToast={setToast} + onEditClick={onEditClick} startTime={start} endTime={end} setStartTime={setStart} diff --git a/dashboards-observability/public/components/custom_panels/custom_panel_view.tsx b/dashboards-observability/public/components/custom_panels/custom_panel_view.tsx index 19916104a..ce24791c4 100644 --- a/dashboards-observability/public/components/custom_panels/custom_panel_view.tsx +++ b/dashboards-observability/public/components/custom_panels/custom_panel_view.tsx @@ -58,27 +58,36 @@ import { onItemSelect, parseForIndices, } from '../common/search/autocomplete_logic'; +import { AddVisualizationPopover } from './helpers/add_visualization_popover'; /* * "CustomPanelsView" module used to render an Operational Panel * * Props taken in as params are: * panelId: Name of the panel opened + * page: Page where component is called * http: http core service * pplService: ppl requestor service + * dslService: dsl requestor service * chrome: chrome core service * parentBreadcrumb: parent breadcrumb * renameCustomPanel: Rename function for the panel - * cloneCustomPanel: Clone function for the panel * deleteCustomPanel: Delete function for the panel + * cloneCustomPanel: Clone function for the panel * setToast: create Toast function + * onEditClick: Edit function for visualization + * startTime: Starting time + * endTime: Ending time + * setStartTime: Function to change start time + * setEndTime: Function to change end time + * childBreadcrumbs: Breadcrumbs to extend + * appId: id of application that panel belongs to + * onAddClick: Function for add button instead of add visualization popover */ interface CustomPanelViewProps { panelId: string; page: 'app' | 'operationalPanels'; - appId?: string; - appName?: string; http: CoreStart['http']; pplService: PPLService; dslService: DSLService; @@ -93,35 +102,38 @@ interface CustomPanelViewProps { text?: React.ReactChild | undefined, side?: string | undefined ) => void; + onEditClick: (savedVisualizationId: string) => any; startTime: string; endTime: string; setStartTime: any; setEndTime: any; - switchToEvent?: any; - switchToEditViz?: any; + childBreadcrumbs?: EuiBreadcrumb[]; + appId?: string; + onAddClick?: any; } -export const CustomPanelView = ({ - panelId, - page, - appId, - appName, - http, - pplService, - dslService, - chrome, - parentBreadcrumbs, - startTime, - endTime, - setStartTime, - setEndTime, - renameCustomPanel, - deleteCustomPanel, - cloneCustomPanel, - setToast, - switchToEvent, - switchToEditViz, -}: CustomPanelViewProps) => { +export const CustomPanelView = (props: CustomPanelViewProps) => { + const { + panelId, + page, + appId, + http, + pplService, + dslService, + chrome, + parentBreadcrumbs, + childBreadcrumbs, + startTime, + endTime, + setStartTime, + setEndTime, + renameCustomPanel, + deleteCustomPanel, + cloneCustomPanel, + setToast, + onEditClick, + onAddClick, + } = props; const [openPanelName, setOpenPanelName] = useState(''); const [panelCreatedTime, setPanelCreatedTime] = useState(''); const [pplFilterValue, setPPLFilterValue] = useState(''); @@ -136,7 +148,6 @@ export const CustomPanelView = ({ const [editMode, setEditMode] = useState(false); const [isModalVisible, setIsModalVisible] = useState(false); // Modal Toggle const [modalLayout, setModalLayout] = useState(); // Modal Layout - const [isVizPopoverOpen, setVizPopoverOpen] = useState(false); // Add Visualization Popover const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); // Add Visualization Flyout const [isFlyoutReplacement, setisFlyoutReplacement] = useState(false); const [replaceVisualizationId, setReplaceVisualizationId] = useState(''); @@ -159,37 +170,6 @@ export const CustomPanelView = ({ // DateTimePicker States const [recentlyUsedRanges, setRecentlyUsedRanges] = useState([]); - const getVizContextPanels = (closeVizPopover?: () => void) => { - return [ - { - id: 0, - title: 'Add Visualization', - items: [ - { - name: 'Select Existing Visualization', - onClick: () => { - if (closeVizPopover != null) { - closeVizPopover(); - } - showFlyout(); - }, - }, - { - name: 'Create New Visualization', - onClick: () => { - advancedVisualization(); - }, - }, - ], - }, - ]; - }; - - const advancedVisualization = () => { - closeVizPopover(); - window.location.assign('#/event_analytics/explorer'); - }; - // Fetch Panel by id const fetchCustomPanel = async () => { return http @@ -207,14 +187,6 @@ export const CustomPanelView = ({ }); }; - const onPopoverClick = () => { - setVizPopoverOpen(!isVizPopoverOpen); - }; - - const closeVizPopover = () => { - setVizPopoverOpen(false); - }; - const handleQueryChange = (newQuery: string) => { setPPLFilterValue(newQuery); }; @@ -227,16 +199,16 @@ export const CustomPanelView = ({ setIsModalVisible(true); }; - const onDatePickerChange = (props: OnTimeChangeProps) => { + const onDatePickerChange = (timeProps: OnTimeChangeProps) => { onTimeChange( - props.start, - props.end, + timeProps.start, + timeProps.end, recentlyUsedRanges, setRecentlyUsedRanges, setStartTime, setEndTime ); - onRefreshFilters(props.start, props.end); + onRefreshFilters(timeProps.start, timeProps.end); }; const onDelete = async () => { @@ -422,15 +394,27 @@ export const CustomPanelView = ({ }); }; - // Add Visualization Button - const addVisualizationButton = ( - - Add Visualization + const cancelButton = ( + editPanel('cancel')}> + Cancel + + ); + + const saveButton = ( + editPanel('save')}> + Save + + ); + + const editButton = ( + editPanel('edit')} disabled={editDisabled}> + Edit + + ); + + const addButton = ( + + Add ); @@ -461,7 +445,6 @@ export const CustomPanelView = ({ setPanelVisualizations={setPanelVisualizations} isFlyoutReplacement={isFlyoutReplacement} replaceVisualizationId={replaceVisualizationId} - appPanel={appPanel} appId={appId} /> ); @@ -509,13 +492,6 @@ export const CustomPanelView = ({ }, ]; - // Set saved object id to empty when redirect away from events tab - useEffect(() => { - if (appPanel) { - switchToEditViz(''); - } - }); - // Fetch the custom panel on Initial Mount useEffect(() => { fetchCustomPanel(); @@ -536,28 +512,17 @@ export const CustomPanelView = ({ // Edit the breadcrumb when panel name changes useEffect(() => { let newBreadcrumb; - if (appPanel) { - newBreadcrumb = [ - ...parentBreadcrumbs, - { - text: 'Application analytics', - href: '#/application_analytics', - }, - { - text: appName, - href: `${last(parentBreadcrumbs)!.href}${appId}`, - }, - ]; + if (childBreadcrumbs) { + newBreadcrumb = childBreadcrumbs; } else { newBreadcrumb = [ - ...parentBreadcrumbs, { text: openPanelName, href: `${last(parentBreadcrumbs)!.href}${panelId}`, }, ]; } - chrome.setBreadcrumbs(newBreadcrumb); + chrome.setBreadcrumbs([...parentBreadcrumbs, ...newBreadcrumb]); }, [panelId, openPanelName]); return ( @@ -566,75 +531,46 @@ export const CustomPanelView = ({ {appPanel || ( - - -

{openPanelName}

-
- - - - Created on {moment(panelCreatedTime).format(UI_DATE_FORMAT)} -
- )} - {appPanel || ( - - - {editMode ? ( - <> - - editPanel('cancel')} - > - Cancel - - - - editPanel('save')}> - Save - - - - ) : ( - - editPanel('edit')} - disabled={editDisabled} + <> + + +

{openPanelName}

+
+ + + + Created on {moment(panelCreatedTime).format(UI_DATE_FORMAT)} +
+ + + {editMode ? ( + <> + {cancelButton} + {saveButton} + + ) : ( + {editButton} + )} + + setPanelsMenuPopover(false)} > - Edit -
+ +
- )} - - setPanelsMenuPopover(false)} - > - - - - - - + - - -
-
+ + + + )}
@@ -681,41 +617,13 @@ export const CustomPanelView = ({ <> {editMode ? ( <> - - editPanel('cancel')} - > - Cancel - - - - editPanel('save')}> - Save - - + {cancelButton} + {saveButton} ) : ( - - editPanel('edit')} - disabled={editDisabled} - > - Edit - - + {editButton} )} - - - Add - - + {addButton} )} @@ -723,9 +631,8 @@ export const CustomPanelView = ({ {panelVisualizations.length === 0 && ( )}
diff --git a/dashboards-observability/public/components/custom_panels/helpers/add_visualization_popover.tsx b/dashboards-observability/public/components/custom_panels/helpers/add_visualization_popover.tsx new file mode 100644 index 000000000..7f289c081 --- /dev/null +++ b/dashboards-observability/public/components/custom_panels/helpers/add_visualization_popover.tsx @@ -0,0 +1,81 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { EuiButton, EuiContextMenu, EuiPopover } from '@elastic/eui'; +import React, { useState } from 'react'; + +interface AddVisualizationPopoverProps { + showFlyout: (isReplacement?: boolean, replaceVizId?: string) => void; + addVizDisabled: boolean; +} + +export const AddVisualizationPopover = ({ + addVizDisabled, + showFlyout, +}: AddVisualizationPopoverProps) => { + const [isVizPopoverOpen, setVizPopoverOpen] = useState(false); // Add Visualization Popover + + const onPopoverClick = () => { + setVizPopoverOpen(!isVizPopoverOpen); + }; + + const closeVizPopover = () => { + setVizPopoverOpen(false); + }; + + const advancedVisualization = () => { + closeVizPopover(); + window.location.assign('#/event_analytics/explorer'); + }; + + const getVizContextPanels = () => { + return [ + { + id: 0, + title: 'Add visualization', + items: [ + { + name: 'Select existing visualization', + onClick: () => { + if (closeVizPopover != null) { + closeVizPopover(); + } + showFlyout(); + }, + }, + { + name: 'Create new visualization', + onClick: () => { + advancedVisualization(); + }, + }, + ], + }, + ]; + }; + + const addVisualizationButton = ( + + Add visualization + + ); + return ( + + + + ); +}; diff --git a/dashboards-observability/public/components/custom_panels/home.tsx b/dashboards-observability/public/components/custom_panels/home.tsx index 112015b0b..4a5395fb0 100644 --- a/dashboards-observability/public/components/custom_panels/home.tsx +++ b/dashboards-observability/public/components/custom_panels/home.tsx @@ -40,7 +40,7 @@ import { isNameValid } from './helpers/utils'; * renderProps: Props from router */ -interface Props { +interface PanelHomeProps { http: CoreStart['http']; chrome: CoreStart['chrome']; parentBreadcrumbs: EuiBreadcrumb[]; @@ -56,7 +56,7 @@ export const Home = ({ pplService, dslService, renderProps, -}: Props) => { +}: PanelHomeProps) => { const [customPanelData, setcustomPanelData] = useState([]); const [toasts, setToasts] = useState([]); const [loading, setLoading] = useState(false); @@ -70,6 +70,10 @@ export const Home = ({ setToasts([...toasts, { id: new Date().toISOString(), title, text, color } as Toast]); }; + const onEditClick = (savedVisualizationId: string) => { + window.location.assign(`#/event_analytics/explorer/${savedVisualizationId}`); + }; + // Fetches all saved Custom Panels const fetchCustomPanels = () => { setLoading(true); @@ -330,6 +334,7 @@ export const Home = ({ cloneCustomPanel={cloneCustomPanel} deleteCustomPanel={deleteCustomPanel} setToast={setToast} + onEditClick={onEditClick} startTime={start} endTime={end} setStartTime={setStart} diff --git a/dashboards-observability/public/components/custom_panels/panel_modules/__tests__/__snapshots__/empty_panel.test.tsx.snap b/dashboards-observability/public/components/custom_panels/panel_modules/__tests__/__snapshots__/empty_panel.test.tsx.snap index 8ac886401..8c0fddb67 100644 --- a/dashboards-observability/public/components/custom_panels/panel_modules/__tests__/__snapshots__/empty_panel.test.tsx.snap +++ b/dashboards-observability/public/components/custom_panels/panel_modules/__tests__/__snapshots__/empty_panel.test.tsx.snap @@ -3,22 +3,7 @@ exports[`Empty panel view component renders empty panel view with disabled popover 1`] = `

- 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
@@ -94,115 +77,120 @@ exports[`Empty panel view component renders empty panel view with disabled popov
- - Add Visualization - - } - closePopover={[Function]} - display="inlineBlock" - hasArrow={true} - id="addVisualizationContextMenu" - isOpen={false} - ownFocus={false} - panelPaddingSize="none" + - + Add visualization + + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + id="addVisualizationContextMenu" + isOpen={false} + ownFocus={false} + panelPaddingSize="none" > -
- - - - - + + + + +
-
- - + + + @@ -221,22 +209,7 @@ exports[`Empty panel view component renders empty panel view with disabled popov exports[`Empty panel view component renders empty panel view with enabled popover 1`] = `

- 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
@@ -312,120 +283,125 @@ exports[`Empty panel view component renders empty panel view with enabled popove
- - Add Visualization - - } - closePopover={[Function]} - display="inlineBlock" - hasArrow={true} - id="addVisualizationContextMenu" - isOpen={false} - ownFocus={false} - panelPaddingSize="none" + - + Add visualization + + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + id="addVisualizationContextMenu" + isOpen={false} + ownFocus={false} + panelPaddingSize="none" > -
- - - - - + + + + +
-
- - + + + diff --git a/dashboards-observability/public/components/custom_panels/panel_modules/__tests__/empty_panel.test.tsx b/dashboards-observability/public/components/custom_panels/panel_modules/__tests__/empty_panel.test.tsx index 59da59679..2c3c24dcd 100644 --- a/dashboards-observability/public/components/custom_panels/panel_modules/__tests__/empty_panel.test.tsx +++ b/dashboards-observability/public/components/custom_panels/panel_modules/__tests__/empty_panel.test.tsx @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { EuiButton, EuiContextMenu, EuiPopover } from '@elastic/eui'; import { configure, mount } from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; import React from 'react'; @@ -12,13 +13,10 @@ describe('Empty panel view component', () => { configure({ adapter: new Adapter() }); it('renders empty panel view with disabled popover', () => { - const getVizContextPanels = jest.fn(); + const addVizDisabled = true; + const showFlyout = jest.fn(); const wrapper = mount( - + ); expect(wrapper).toMatchSnapshot(); @@ -26,13 +24,10 @@ describe('Empty panel view component', () => { }); it('renders empty panel view with enabled popover', () => { - const getVizContextPanels = jest.fn(); + const addVizDisabled = false; + const showFlyout = jest.fn(); const wrapper = mount( - + ); expect(wrapper).toMatchSnapshot(); diff --git a/dashboards-observability/public/components/custom_panels/panel_modules/empty_panel.tsx b/dashboards-observability/public/components/custom_panels/panel_modules/empty_panel.tsx index d2c108e9f..5a5a821d3 100644 --- a/dashboards-observability/public/components/custom_panels/panel_modules/empty_panel.tsx +++ b/dashboards-observability/public/components/custom_panels/panel_modules/empty_panel.tsx @@ -3,16 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { - EuiSpacer, - EuiText, - EuiFlexGroup, - EuiFlexItem, - EuiButton, - EuiPopover, - EuiContextMenu, -} from '@elastic/eui'; +import { EuiSpacer, EuiText, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; 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 @@ -22,84 +15,30 @@ import React, { useState } from 'react'; * getVizContextPanels -> Function to populate the add visualization popover */ -interface Props { +interface EmptyPanelViewProps { + addButton?: any; addVizDisabled: boolean; - page: 'app' | 'operationalPanels'; - getVizContextPanels: ( - closeVizPopover?: (() => void) | undefined - ) => Array<{ - id: number; - title: string; - items: Array<{ - name: string; - onClick: () => void; - }>; - }>; - switchToEvent?: any; + showFlyout: (isReplacement?: boolean, replaceVizId?: string) => void; } export const EmptyPanelView = ({ addVizDisabled, - page, - getVizContextPanels, - switchToEvent, -}: Props) => { - const [isVizPopoverOpen, setVizPopoverOpen] = useState(false); - const appMetrics = page === 'app'; - - const onPopoverClick = () => { - setVizPopoverOpen(!isVizPopoverOpen); - }; - - const closeVizPopover = () => { - setVizPopoverOpen(false); - }; - - // Add Visualization Button - const addVisualizationButton = ( - - Add Visualization - - ); - + showFlyout, + addButton = , +}: EmptyPanelViewProps) => { return (
-

Start by adding {appMetrics ? 'metrics' : 'your first visualization'}

+

Start by adding your first visualization

- Use PPL Queries to fetch & filter observability data and create - {appMetrics ? ' metrics' : ' visualizations'} + Use PPL Queries to fetch & filter observability data and create visualizations
- {appMetrics ? ( - - - Add - - - ) : ( - - - - - - )} + {addButton}
diff --git a/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/__tests__/__snapshots__/panel_grid.test.tsx.snap b/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/__tests__/__snapshots__/panel_grid.test.tsx.snap index 2501bc88a..b192dff2d 100644 --- a/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/__tests__/__snapshots__/panel_grid.test.tsx.snap +++ b/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/__tests__/__snapshots__/panel_grid.test.tsx.snap @@ -50,6 +50,7 @@ exports[`Panel Grid Component renders panel grid component with empty visualizat editMode={false} endTime="now" http={[MockFunction]} + onEditClick={[Function]} onRefresh={false} panelId="" panelVisualizations={Array []} diff --git a/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/__tests__/panel_grid.test.tsx b/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/__tests__/panel_grid.test.tsx index a4f548087..1366eb453 100644 --- a/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/__tests__/panel_grid.test.tsx +++ b/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/__tests__/panel_grid.test.tsx @@ -31,6 +31,9 @@ describe('Panel Grid Component', () => { const pplFilterValue = ''; const showFlyout = jest.fn(); const editActionType = ''; + const onEditClick = (savedVisId: string) => { + window.location.assign(`#/event_analytics/explorer/${savedVisId}`); + }; const wrapper = mount( { pplFilterValue={pplFilterValue} showFlyout={showFlyout} editActionType={editActionType} + onEditClick={onEditClick} /> ); wrapper.update(); diff --git a/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/panel_grid.tsx b/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/panel_grid.tsx index 7cbbfd141..78a46179f 100644 --- a/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/panel_grid.tsx +++ b/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/panel_grid.tsx @@ -50,8 +50,7 @@ interface PanelGridProps { pplService: PPLService; startTime: string; endTime: string; - fromApp?: boolean; - switchToEditViz?: any; + onEditClick: (savedVisualizationId: string) => any; onRefresh: boolean; cloneVisualization: (visualzationTitle: string, savedVisualizationId: string) => void; pplFilterValue: string; @@ -60,24 +59,24 @@ interface PanelGridProps { setEditVizId?: any; } -export const PanelGrid = ({ - http, - chrome, - panelId, - panelVisualizations, - setPanelVisualizations, - editMode, - pplService, - startTime, - endTime, - fromApp = false, - switchToEditViz, - onRefresh, - cloneVisualization, - pplFilterValue, - showFlyout, - editActionType, -}: PanelGridProps) => { +export const PanelGrid = (props: PanelGridProps) => { + const { + http, + chrome, + panelId, + panelVisualizations, + setPanelVisualizations, + editMode, + pplService, + startTime, + endTime, + onEditClick, + onRefresh, + cloneVisualization, + pplFilterValue, + showFlyout, + editActionType, + } = props; const [currentLayout, setCurrentLayout] = useState([]); const [postEditLayout, setPostEditLayout] = useState([]); const [gridData, setGridData] = useState(panelVisualizations.map(() => <>)); @@ -102,8 +101,7 @@ export const PanelGrid = ({ fromTime={startTime} toTime={endTime} onRefresh={onRefresh} - fromApp={fromApp} - switchToEditViz={switchToEditViz} + onEditClick={onEditClick} cloneVisualization={cloneVisualization} pplFilterValue={pplFilterValue} showFlyout={showFlyout} diff --git a/dashboards-observability/public/components/custom_panels/panel_modules/visualization_container/__tests__/visualization_container.test.tsx b/dashboards-observability/public/components/custom_panels/panel_modules/visualization_container/__tests__/visualization_container.test.tsx index bf972e5e1..20ab07fa9 100644 --- a/dashboards-observability/public/components/custom_panels/panel_modules/visualization_container/__tests__/visualization_container.test.tsx +++ b/dashboards-observability/public/components/custom_panels/panel_modules/visualization_container/__tests__/visualization_container.test.tsx @@ -39,6 +39,9 @@ describe.skip('Visualization Container Component', () => { const showFlyout = jest.fn(); const removeVisualization = jest.fn(); const pplService = new PPLService(httpClientMock); + const onEditClick = (savedVisId: string) => { + window.location.assign(`#/event_analytics/explorer/${savedVisId}`); + }; const wrapper = mount( { pplFilterValue={pplFilterValue} showFlyout={showFlyout} removeVisualization={removeVisualization} + onEditClick={onEditClick} /> ); wrapper.update(); diff --git a/dashboards-observability/public/components/custom_panels/panel_modules/visualization_container/visualization_container.tsx b/dashboards-observability/public/components/custom_panels/panel_modules/visualization_container/visualization_container.tsx index 483e184e4..7e9931338 100644 --- a/dashboards-observability/public/components/custom_panels/panel_modules/visualization_container/visualization_container.tsx +++ b/dashboards-observability/public/components/custom_panels/panel_modules/visualization_container/visualization_container.tsx @@ -53,8 +53,7 @@ interface Props { onRefresh: boolean; pplFilterValue: string; usedInNotebooks?: boolean; - fromApp?: boolean; - switchToEditViz?: any; + onEditClick: (savedVisualizationId: string) => any; cloneVisualization?: (visualzationTitle: string, savedVisualizationId: string) => void; showFlyout?: (isReplacement?: boolean | undefined, replaceVizId?: string | undefined) => void; removeVisualization?: (visualizationId: string) => void; @@ -71,8 +70,7 @@ export const VisualizationContainer = ({ onRefresh, pplFilterValue, usedInNotebooks, - fromApp, - switchToEditViz, + onEditClick, cloneVisualization, showFlyout, removeVisualization, @@ -94,11 +92,7 @@ export const VisualizationContainer = ({ disabled={disablePopover} onClick={() => { closeActionsMenu(); - if (fromApp) { - switchToEditViz(savedVisualizationId); - } else { - window.location.assign(`#/event_analytics/explorer/${savedVisualizationId}`); - } + onEditClick(savedVisualizationId); }} > Edit diff --git a/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/__tests__/__snapshots__/visualization_flyout.test.tsx.snap b/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/__tests__/__snapshots__/visualization_flyout.test.tsx.snap index 40465e3eb..1d43d5228 100644 --- a/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/__tests__/__snapshots__/visualization_flyout.test.tsx.snap +++ b/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/__tests__/__snapshots__/visualization_flyout.test.tsx.snap @@ -2,7 +2,6 @@ exports[`Visualization Flyout Component renders add visualization Flyout 1`] = ` - Select Existing Visualization + Select existing visualization @@ -240,7 +239,7 @@ exports[`Visualization Flyout Component renders add visualization Flyout 1`] = ` class="euiTitle euiTitle--medium" id="addVisualizationFlyout" > - Select Existing Visualization + Select existing visualization
- Select Existing Visualization + Select existing visualization
- Select Existing Visualization + Select existing visualization
- Select Existing Visualization + Select existing visualization
- Select Existing Visualization + Select existing visualization
@@ -1062,7 +1061,6 @@ exports[`Visualization Flyout Component renders add visualization Flyout 1`] = ` exports[`Visualization Flyout Component renders replace visualization Flyout 1`] = ` - Replace Visualization + Replace visualization @@ -1305,7 +1303,7 @@ exports[`Visualization Flyout Component renders replace visualization Flyout 1`] class="euiTitle euiTitle--medium" id="addVisualizationFlyout" > - Replace Visualization + Replace visualization
- Replace Visualization + Replace visualization
- Replace Visualization + Replace visualization
- Replace Visualization + Replace visualization
- Replace Visualization + Replace visualization
diff --git a/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/__tests__/visualization_flyout.test.tsx b/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/__tests__/visualization_flyout.test.tsx index de3b5cabb..7aebf7b90 100644 --- a/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/__tests__/visualization_flyout.test.tsx +++ b/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/__tests__/visualization_flyout.test.tsx @@ -37,7 +37,6 @@ describe('Visualization Flyout Component', () => { http={httpClientMock} pplService={pplService} isFlyoutReplacement={isFlyoutReplacement} - appPanel={false} /> ); @@ -69,7 +68,6 @@ describe('Visualization Flyout Component', () => { pplService={pplService} isFlyoutReplacement={isFlyoutReplacement} replaceVisualizationId={replaceVisualizationId} - appPanel={false} /> ); diff --git a/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout.tsx b/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout.tsx index 4fbea7141..2c97e7095 100644 --- a/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout.tsx +++ b/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/visualization_flyout.tsx @@ -75,14 +75,12 @@ interface VisualizationFlyoutProps { setPanelVisualizations: React.Dispatch>; isFlyoutReplacement?: boolean | undefined; replaceVisualizationId?: string | undefined; - appPanel: boolean; appId?: string; } export const VisaulizationFlyout = ({ panelId, - appId, - appPanel, + appId = '', pplFilterValue, closeFlyout, start, @@ -215,7 +213,7 @@ export const VisaulizationFlyout = ({

- {isFlyoutReplacement ? 'Replace Visualization' : 'Select Existing Visualization'} + {isFlyoutReplacement ? 'Replace visualization' : 'Select existing visualization'}

@@ -293,7 +291,7 @@ export const VisaulizationFlyout = ({ if (res.visualizations.length > 0) { setSavedVisualizations(res.visualizations); const filterAppVis = res.visualizations.filter((vis: SavedVisualizationType) => { - return appPanel + return appId ? vis.hasOwnProperty('application_id') ? vis.application_id === appId : false diff --git a/dashboards-observability/public/components/notebooks/components/paragraph_components/para_output.tsx b/dashboards-observability/public/components/notebooks/components/paragraph_components/para_output.tsx index 113e4c536..0a3776e9f 100644 --- a/dashboards-observability/public/components/notebooks/components/paragraph_components/para_output.tsx +++ b/dashboards-observability/public/components/notebooks/components/paragraph_components/para_output.tsx @@ -133,6 +133,9 @@ export const ParaOutput = (props: { let toObs = moment(visInput?.timeRange?.to).format(dateFormat); fromObs = fromObs === 'Invalid date' ? visInput.timeRange.from : fromObs; toObs = toObs === 'Invalid date' ? visInput.timeRange.to : toObs; + const onEditClick = (savedVisualizationId: string) => { + window.location.assign(`#/event_analytics/explorer/${savedVisualizationId}`); + }; return ( <> @@ -143,6 +146,7 @@ export const ParaOutput = (props: { http={props.http} editMode={false} visualizationId={''} + onEditClick={onEditClick} savedVisualizationId={para.visSavedObjId} pplService={props.pplService} fromTime={para.visStartTime}