import { FC, useState, useEffect } from "react"; import { Box, Button, Grid, Popover, Accordion, AccordionSummary, AccordionDetails, Dialog, Divider, Paper, MenuList, MenuItem, ListItemText, ListItemIcon, TextField, } from "@mui/material"; import { ExpandMore as ExpandMoreIcon, AddCircleOutline as AddCircleOutlineIcon, SavedSearch as SavedSearchIcon, RemoveCircle as RemoveCircleIcon, } from "@mui/icons-material"; import { useTranslate } from "react-polyglot"; import { QueryBuilder } from "components/QueryBuilder"; import { QueryText } from "components/QueryText"; import { LiveDataViewer } from "components/LiveDataViewer"; import { Tooltip } from "components/Tooltip"; import visualizationMap from "config/visualizationMap.json"; import { VisualizationSelectCard } from "./VisualizationSelectCard"; import { MetricSelectCard } from "./MetricSelectCard"; import { useAppContext } from "./AppProvider"; interface VisualizationBuilderProps { templates: any[]; } export const VisualizationBuilder: FC = ({ templates, }) => { const t = useTranslate(); const { typography: { h4 }, colors: { white, leafcutterElectricBlue, cdrLinkOrange }, foundCount, query, replaceQuery, clearQuery, } = useAppContext(); const { visualizations } = visualizationMap; const [selectedVisualizationType, setSelectedVisualizationType] = useState( null as any ); const toggleSelectedVisualizationType = (visualizationType: string) => { if (visualizationType === selectedVisualizationType) { setSelectedVisualizationType(null); } else { setSelectedVisualizationType(visualizationType); } }; const [dialogOpen, setDialogOpen] = useState(false); const [savedSearches, setSavedSearches] = useState([]); const [savedSearchName, setSavedSearchName] = useState(""); const [anchorEl, setAnchorEl] = useState(null); const updateSearches = async () => { const result = await fetch("/api/searches/list"); const existingSearches = await result.json(); setSavedSearches(existingSearches); }; useEffect(() => { updateSearches(); }, [setSavedSearches]); const showSavedSearchPopup = (event: any) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setSavedSearchName(""); setAnchorEl(null); }; const closeDialog = () => { setDialogOpen(false); }; const createSavedSearch = async (name: string, q: any) => { await fetch("/api/searches/create", { method: "POST", body: JSON.stringify({ name, query: q }), }); await updateSearches(); handleClose(); closeDialog(); }; const deleteSavedSearch = async (name: string) => { await fetch("/api/searches/delete", { method: "POST", body: JSON.stringify({ name }), }); await updateSearches(); closeDialog(); }; const updateSearch = (name: string) => { handleClose(); closeDialog(); const found: any = savedSearches.find( (search: any) => search.name === name ); replaceQuery(found?.query); }; const clearSearch = () => clearQuery(); const open = Boolean(anchorEl); const elementID = open ? "simple-popover" : undefined; const [queryExpanded, setQueryExpanded] = useState(true); const [resultsExpanded, setResultsExpanded] = useState(false); const minHeight = "42px"; const maxHeight = "42px"; const summaryStyles = { backgroundColor: leafcutterElectricBlue, height: "14px", minHeight, maxHeight, "&.Mui-expanded": { minHeight, maxHeight, }, }; const buttonStyles = { fontFamily: "Poppins, sans-serif", fontWeight: 700, color: `${white} !important`, borderRadius: 999, backgroundColor: leafcutterElectricBlue, padding: "6px 30px", margin: "20px 0px", whiteSpace: "nowrap", }; return ( setSavedSearchName(e.target.value)} /> Search Criteria { handleClose(); setDialogOpen(true); }} > {t("saveCurrentSearch")} {savedSearches.map((savedSearch: any) => ( updateSearch(savedSearch.name)} > {savedSearch.name} deleteSavedSearch(savedSearch.name)} sx={{ p: 0, m: 0, zIndex: 100 }} > ))} setQueryExpanded(!queryExpanded)} > } sx={summaryStyles} > {t("query")} setResultsExpanded(!resultsExpanded)} > } sx={summaryStyles} > {`${t( "results" )} (${foundCount})`} {t("selectVisualization")}: {Object.keys(visualizations).map((key: string) => ( ))} {t("selectFieldVisualize")}: {templates .filter( (template: any) => template.type === selectedVisualizationType ) .map((template: any) => { const { id, type, title, description } = template; const cleanTitle = title .replace("Templated", "") // @ts-expect-error .replace(visualizations[type].name, ""); const metricType = cleanTitle.replace(/\s/g, "").toLowerCase(); return ( ); })} ); };