UNPKG

@grafana/ui

Version:
240 lines (235 loc) • 9.42 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var jsxRuntime = require('react/jsx-runtime'); var css = require('@emotion/css'); var React = require('react'); var data = require('@grafana/data'); var i18n = require('@grafana/i18n'); var schema = require('@grafana/schema'); var types = require('../PanelChrome/types.cjs'); var ThemeContext = require('../../themes/ThemeContext.cjs'); var Button = require('../Button/Button.cjs'); var IconButton = require('../IconButton/IconButton.cjs'); require('../PanelChrome/index.cjs'); var Toggletip = require('../Toggletip/Toggletip.cjs'); var VizLayout = require('../VizLayout/VizLayout.cjs'); var FacetedLabelsFilter = require('../VizLegend/FacetedLabelsFilter.cjs'); var VizLegend = require('../VizLegend/VizLegend.cjs'); var utils = require('./utils.cjs'); var PanelContext = require('../PanelChrome/PanelContext.cjs'); "use strict"; function hasVisibleLegendSeries(config, data) { return config.getSeries().some((s) => { var _a, _b, _c; const fieldIndex = s.props.dataFrameFieldIndex; if (!fieldIndex) { return false; } const field = (_a = data[fieldIndex.frameIndex]) == null ? void 0 : _a.fields[fieldIndex.fieldIndex]; if (!field || ((_c = (_b = field.config.custom) == null ? void 0 : _b.hideFrom) == null ? void 0 : _c.legend)) { return false; } return true; }); } const PlotLegend = React.memo(function PlotLegend2({ data: data$1, config, placement, calcs, displayMode, limit, enableFacetedFilter = false, facetedFilterPinned = false, onPinnedToSidebarChange, ...vizLayoutLegendProps }) { const theme = ThemeContext.useTheme2(); const styles = ThemeContext.useStyles2(getPlotLegendStyles); const { onToggleSeriesVisibility } = PanelContext.usePanelContext(); const [selectedLabels, setSelectedLabels] = React.useState({}); const facetedLabels = React.useMemo( () => enableFacetedFilter && onToggleSeriesVisibility ? data.extractFacetedLabels(data$1) : {}, [enableFacetedFilter, onToggleSeriesVisibility, data$1] ); const hasFacetedLabels = Object.keys(facetedLabels).length > 0; const hasActiveFilters = Object.values(selectedLabels).some((v) => v.length > 0); const legendItems = config.getSeries().map((s) => { var _a, _b, _c, _d; const seriesConfig = s.props; const fieldIndex = seriesConfig.dataFrameFieldIndex; const axisPlacement = config.getAxisPlacement(s.props.scaleKey); if (!fieldIndex) { return void 0; } const field = (_a = data$1[fieldIndex.frameIndex]) == null ? void 0 : _a.fields[fieldIndex.fieldIndex]; if (!field || ((_c = (_b = field.config.custom) == null ? void 0 : _b.hideFrom) == null ? void 0 : _c.legend)) { return void 0; } const label = data.getFieldDisplayName(field, data$1[fieldIndex.frameIndex], data$1); const scaleColor = data.getFieldSeriesColor(field, theme); const seriesColor = scaleColor.color; return { disabled: !((_d = seriesConfig.show) != null ? _d : true), fieldIndex, color: seriesColor, label, yAxis: axisPlacement === schema.AxisPlacement.Left || axisPlacement === schema.AxisPlacement.Bottom ? 1 : 2, getDisplayValues: () => utils.getDisplayValuesForCalcs(calcs, field, theme), getItemKey: () => `${label}-${fieldIndex.frameIndex}-${fieldIndex.fieldIndex}`, lineStyle: seriesConfig.lineStyle }; }).filter((i) => i !== void 0); const legendHasPrecedence = React.useMemo(() => { if (!hasActiveFilters) { return false; } const expectedVisible = data.resolveFacetedFilterNames(data$1, selectedLabels, data.getFieldDisplayName); if (!expectedVisible) { return false; } const expectedSet = new Set(expectedVisible); const actuallyVisible = new Set(legendItems.filter((item) => !item.disabled).map((item) => item.label)); if (expectedSet.size !== actuallyVisible.size) { return true; } return !Array.from(expectedSet).every((name) => actuallyVisible.has(name)); }, [hasActiveFilters, data$1, selectedLabels, legendItems]); const handleLabelsChange = React.useCallback( (selected) => { setSelectedLabels(selected); const visibleNames = data.resolveFacetedFilterNames(data$1, selected, data.getFieldDisplayName); onToggleSeriesVisibility == null ? void 0 : onToggleSeriesVisibility(visibleNames, types.SeriesVisibilityChangeMode.SetExactly); }, [data$1, onToggleSeriesVisibility] ); const handleClearFilters = React.useCallback(() => { setSelectedLabels({}); onToggleSeriesVisibility == null ? void 0 : onToggleSeriesVisibility(null, types.SeriesVisibilityChangeMode.SetExactly); }, [onToggleSeriesVisibility]); const handleToggleFilterDock = React.useCallback(() => { onPinnedToSidebarChange == null ? void 0 : onPinnedToSidebarChange(!facetedFilterPinned); }, [onPinnedToSidebarChange, facetedFilterPinned]); const facetedFilter = hasFacetedLabels ? /* @__PURE__ */ jsxRuntime.jsx( FacetedLabelsFilter.FacetedLabelsFilter, { labels: facetedLabels, selected: selectedLabels, onChange: handleLabelsChange, dimmed: legendHasPrecedence } ) : null; const filterToggle = facetedFilter ? /* @__PURE__ */ jsxRuntime.jsx( Toggletip.Toggletip, { content: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.filterPopoverContent, children: [ facetedFilter, /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.filterPopoverFooter, children: [ /* @__PURE__ */ jsxRuntime.jsx(Button.Button, { variant: "secondary", size: "sm", icon: "gf-pin", onClick: handleToggleFilterDock, children: i18n.t("grafana-ui.viz-legend.pin-filter", "Pin to sidebar") }), hasActiveFilters && /* @__PURE__ */ jsxRuntime.jsx(Button.Button, { variant: "secondary", size: "sm", icon: "times", onClick: handleClearFilters, children: i18n.t("grafana-ui.viz-legend.clear-filters", "Clear all") }) ] }) ] }), placement: "bottom-start", fitContent: true, dismissOnScroll: true, children: /* @__PURE__ */ jsxRuntime.jsx( IconButton.IconButton, { name: "eye", size: "md", tooltip: i18n.t("grafana-ui.viz-legend.series-visibility", "Series visibility"), variant: hasActiveFilters ? "primary" : void 0, "data-testid": "faceted-labels-filter-toggle" } ) } ) : null; const legend = /* @__PURE__ */ jsxRuntime.jsx( VizLegend.VizLegend, { placement, items: legendItems, displayMode, sortBy: vizLayoutLegendProps.sortBy, sortDesc: vizLayoutLegendProps.sortDesc, isSortable: true, limit, filterAction: !facetedFilterPinned ? filterToggle : void 0, overflow: vizLayoutLegendProps.overflow } ); if (facetedFilterPinned && facetedFilter) { return /* @__PURE__ */ jsxRuntime.jsx(VizLayout.VizLayout.Legend, { placement, ...vizLayoutLegendProps, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.legendWithFilter, children: [ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.filterContent, children: [ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.filterDockedActions, children: [ hasActiveFilters && /* @__PURE__ */ jsxRuntime.jsx( IconButton.IconButton, { name: "filter-minus", size: "sm", tooltip: i18n.t("grafana-ui.viz-legend.clear-filters", "Clear all"), onClick: handleClearFilters } ), /* @__PURE__ */ jsxRuntime.jsx( IconButton.IconButton, { name: "times", size: "sm", tooltip: i18n.t("grafana-ui.viz-legend.unpin-sidebar", "Unpin"), onClick: handleToggleFilterDock } ) ] }), facetedFilter ] }), /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.legendContent, children: legend }) ] }) }); } return /* @__PURE__ */ jsxRuntime.jsx(VizLayout.VizLayout.Legend, { placement, ...vizLayoutLegendProps, children: legend }); }); PlotLegend.displayName = "PlotLegend"; const getPlotLegendStyles = (theme) => ({ legendWithFilter: css.css({ display: "flex", width: "100%", height: "100%", gap: theme.spacing(1), overflow: "hidden" }), legendContent: css.css({ flex: 1, minWidth: 0, overflow: "auto" }), filterContent: css.css({ position: "relative", maxWidth: "50%", overflow: "auto", borderRight: `1px solid ${theme.colors.border.weak}`, paddingRight: theme.spacing(1) }), filterDockedActions: css.css({ position: "absolute", zIndex: 1, right: theme.spacing(0.5), top: theme.spacing(0.5), display: "flex", gap: theme.spacing(0.25), color: theme.colors.text.secondary }), filterPopoverContent: css.css({ margin: theme.spacing(-3, -2), maxHeight: 400, overflow: "auto" }), filterPopoverFooter: css.css({ display: "flex", gap: theme.spacing(1), borderTop: `1px solid ${theme.colors.border.medium}`, padding: theme.spacing(1) }) }); exports.PlotLegend = PlotLegend; exports.hasVisibleLegendSeries = hasVisibleLegendSeries; //# sourceMappingURL=PlotLegend.cjs.map