import { map, find } from "lodash"; import React, { useState, useMemo, useEffect, useRef } from "react"; import PropTypes from "prop-types"; import getQueryResultData from "@/lib/getQueryResultData"; import { getColumnCleanName } from "@/services/query-result"; import Filters, { FiltersType, filterData } from "@/components/Filters"; import { VisualizationType } from "@/visualizations/prop-types"; import { Renderer } from "@/components/visualizations/visualizationComponents"; function combineFilters(localFilters, globalFilters) { // tiny optimization - to avoid unnecessary updates if (localFilters.length === 0 || globalFilters.length === 0) { return localFilters; } return map(localFilters, localFilter => { const globalFilter = find(globalFilters, f => f.name === localFilter.name); if (globalFilter) { return { ...localFilter, current: globalFilter.current, }; } return localFilter; }); } export default function VisualizationRenderer(props) { const data = useMemo(() => getQueryResultData(props.queryResult), [props.queryResult]); const [filters, setFilters] = useState(data.filters); const filtersRef = useRef(); filtersRef.current = filters; // Reset local filters when query results updated useEffect(() => { setFilters(combineFilters(data.filters, props.filters)); }, [data.filters, props.filters]); // Update local filters when global filters changed. // For correct behavior need to watch only `props.filters` here, // therefore using ref to access current local filters useEffect(() => { setFilters(combineFilters(filtersRef.current, props.filters)); }, [props.filters]); const cleanColumnNames = useMemo( () => map(data.columns, col => ({ ...col, name: getColumnCleanName(col.friendly_name) })), [data.columns] ); const filteredData = useMemo( () => ({ columns: cleanColumnNames, rows: filterData(data.rows, filters), }), [cleanColumnNames, data.rows, filters] ); const { showFilters, visualization } = props; let options = { ...visualization.options }; // define pagination size based on context for Table visualization if (visualization.type === "TABLE") { options.paginationSize = props.context === "widget" ? "small" : "default"; } return ( } /> ); } VisualizationRenderer.propTypes = { visualization: VisualizationType.isRequired, queryResult: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types filters: FiltersType, showFilters: PropTypes.bool, context: PropTypes.oneOf(["query", "widget"]).isRequired, }; VisualizationRenderer.defaultProps = { filters: [], showFilters: true, };