/* * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ import { EuiButton, EuiButtonIcon, EuiCodeBlock, EuiContextMenuItem, EuiContextMenuPanel, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiLoadingChart, EuiModal, EuiModalBody, EuiModalFooter, EuiModalHeader, EuiModalHeaderTitle, EuiPanel, EuiPopover, EuiSpacer, EuiText, EuiToolTip, } from '@elastic/eui'; import React, { useEffect, useMemo, useState } from 'react'; import _ from 'lodash'; import { CoreStart } from '../../../../../../../src/core/public'; import PPLService from '../../../../services/requests/ppl'; import { displayVisualization, renderCatalogVisualization, renderSavedVisualization, } from '../../helpers/utils'; import './visualization_container.scss'; import { VizContainerError } from '../../../../../common/types/custom_panels'; /* * Visualization container - This module is a placeholder to add visualizations in react-grid-layout * * Props taken in as params are: * editMode: boolean to check if the panel is in edit mode * visualizationId: unique visualization id * visualizationTitle: visualization name * query: ppl query to load the visualization * pplService: ppl requestor service * type: type of visualization [bar, horizontal_bar, line] * fromTime: start time in date filter * toTime: end time in date filter * onRefresh: boolean value to trigger refresh of visualizations * cloneVisualization: function to clone a visualization in panel * pplFilterValue: string with panel PPL filter value * showFlyout: function to show the flyout * removeVisualization: function to remove all the visualizations * catalogVisualization: boolean pointing if the container is used for catalog metrics * spanParam: Override the span(timestamp, 1h) in visualization to span(timestamp, spanParam) */ interface Props { http: CoreStart['http']; editMode: boolean; visualizationId: string; savedVisualizationId: string; pplService: PPLService; fromTime: string; toTime: string; onRefresh: boolean; pplFilterValue: string; usedInNotebooks?: boolean; onEditClick: (savedVisualizationId: string) => any; cloneVisualization?: (visualzationTitle: string, savedVisualizationId: string) => void; showFlyout?: (isReplacement?: boolean | undefined, replaceVizId?: string | undefined) => void; removeVisualization?: (visualizationId: string) => void; catalogVisualization?: boolean; spanParam?: string; } export const VisualizationContainer = ({ http, editMode, visualizationId, savedVisualizationId, pplService, fromTime, toTime, onRefresh, pplFilterValue, usedInNotebooks, onEditClick, cloneVisualization, showFlyout, removeVisualization, catalogVisualization, spanParam, }: Props) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); const [visualizationTitle, setVisualizationTitle] = useState(''); const [visualizationType, setVisualizationType] = useState(''); const [visualizationMetaData, setVisualizationMetaData] = useState(); const [visualizationData, setVisualizationData] = useState([]); const [isLoading, setIsLoading] = useState(true); const [isError, setIsError] = useState({} as VizContainerError); const onActionsMenuClick = () => setIsPopoverOpen((currPopoverOpen) => !currPopoverOpen); const closeActionsMenu = () => setIsPopoverOpen(false); const [isModalVisible, setIsModalVisible] = useState(false); const [modalContent, setModalContent] = useState(<>); const closeModal = () => setIsModalVisible(false); const showModal = (modalType: string) => { if (modalType === 'catalogModal') setModalContent(

{visualizationMetaData.name}

This PPL Query is generated in runtime from selected data source {visualizationMetaData.query} Close
); else setModalContent(

{isError.errorMessage}

Error Details {isError.errorDetails} Close
); setIsModalVisible(true); }; let popoverPanel = [ { closeActionsMenu(); onEditClick(savedVisualizationId); }} > Edit , { closeActionsMenu(); showFlyout(true, visualizationId); }} > Replace , { closeActionsMenu(); cloneVisualization(visualizationTitle, savedVisualizationId); }} > Duplicate , ]; const showModelPanel = [ { closeActionsMenu(); showModal('catalogModal'); }} > View query , ]; if (usedInNotebooks) { popoverPanel = catalogVisualization ? [showModelPanel] : [popoverPanel[0]]; } const loadVisaulization = async () => { if (catalogVisualization) await renderCatalogVisualization( http, pplService, savedVisualizationId, fromTime, toTime, pplFilterValue, spanParam, setVisualizationTitle, setVisualizationType, setVisualizationData, setVisualizationMetaData, setIsLoading, setIsError ); else await renderSavedVisualization( http, pplService, savedVisualizationId, fromTime, toTime, pplFilterValue, spanParam, setVisualizationTitle, setVisualizationType, setVisualizationData, setVisualizationMetaData, setIsLoading, setIsError ); }; const memoisedVisualizationBox = useMemo( () => (
{isLoading ? ( ) : !_.isEmpty(isError) ? (

{isError.errorMessage}

{isError.hasOwnProperty('errorDetails') && isError.errorDetails !== '' ? ( showModal('errorModal')} size="s" > See error details ) : ( <> )}
) : ( displayVisualization(visualizationMetaData, visualizationData, visualizationType) )}
), [onRefresh, isLoading, isError, visualizationData, visualizationType, visualizationMetaData] ); useEffect(() => { loadVisaulization(); }, [onRefresh]); return ( <>
{visualizationTitle}
{editMode ? ( { removeVisualization(visualizationId); }} /> ) : ( } isOpen={isPopoverOpen} closePopover={closeActionsMenu} anchorPosition="downLeft" > )}
{memoisedVisualizationBox}
{isModalVisible && modalContent} ); };