From 1180e2cf96ee379d27189e961f5ea7c37f01c99f Mon Sep 17 00:00:00 2001 From: Jovan Cvetkovic Date: Mon, 16 Jan 2023 13:03:49 +0100 Subject: [PATCH] [FEATURE] Upgrade Vega-tooltips plugin version #254 Signed-off-by: Jovan Cvetkovic --- public/app.scss | 70 ++++++++++++++++++++++++++++++++++++++-- public/utils/helpers.tsx | 56 ++++++++++++++++++++++++++++++-- 2 files changed, 122 insertions(+), 4 deletions(-) diff --git a/public/app.scss b/public/app.scss index 9c4535b3b..17459e201 100644 --- a/public/app.scss +++ b/public/app.scss @@ -11,6 +11,9 @@ $euiColorGhost: #FFF !default; $euiColorInk: #000 !default; $euiTextColor: $euiColorDarkestShade !default; +@import "./components/Charts/ChartContainer.scss"; +@import "./pages/Overview/components/Widgets/WidgetContainer.scss"; + .selected-radio-panel { background-color: tintOrShade($euiColorPrimary, 90%, 70%); border-color: $euiColorPrimary; @@ -45,5 +48,68 @@ $euiTextColor: $euiColorDarkestShade !default; text-decoration: none; } -@import "./components/Charts/ChartContainer.scss"; -@import "./pages/Overview/components/Widgets/WidgetContainer.scss"; +.vg-tooltip { + background-color: #404040 !important; + border-radius: 4px !important; + color: #FFFFFF !important; + border: none !important; + padding: 0 !important; + font-family: "Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol" !important; + font-weight: 600 !important; + font-size: 12px !important; + + .vg-tooltip-innerContainer { + .vg-tooltip-header { + border-bottom: 1px solid gray; + table tr:nth-child(odd) { + background-color: #535353 !important; + } + + td:nth-child(1) { + position: relative; + width: 6px; + padding: 0 0 0 2px !important; + + .vg-tooltip-color { + width: 4px; + position: absolute; + top: 2px; + height: calc(100% - 4px); + } + } + td:nth-child(3) { + padding-right: 8px !important; + text-align: right; + } + } + + .vg-tooltip-body { + padding: 4px; + + table tr:nth-child(even) { + background-color: #535353 !important; + } + + td:nth-child(2) { + text-align: right; + } + } + + table { + width: 100%; + + tbody tr { + td { + height: 28px; + padding: 4px !important; + vertical-align: middle !important; + } + + td:nth-child(1) { + padding-right: 10px !important; + font-weight: 400 !important; + } + } + } + } +} diff --git a/public/utils/helpers.tsx b/public/utils/helpers.tsx index b45c94660..5647545f7 100644 --- a/public/utils/helpers.tsx +++ b/public/utils/helpers.tsx @@ -28,6 +28,7 @@ import { RuleInfo } from '../../server/models/interfaces'; import { NotificationsStart } from 'opensearch-dashboards/public'; import { OpenSearchService } from '../services'; import { Handler } from 'vega-tooltip'; +import _ from 'lodash'; export const parseStringsToOptions = (strings: string[]) => { return strings.map((str) => ({ id: str, label: str })); @@ -165,14 +166,65 @@ export function renderVisualization(spec: TopLevelSpec, containerId: string) { } function renderVegaSpec(spec: {}) { - const handler = new Handler(); + let pathGroup: any[] = []; + const handler = new Handler({ + formatTooltip: (value, sanitize) => { + let tooltipData = { ...value }; + let values = Object.entries(tooltipData); + if (!values.length) return ''; + const tooltipItem = pathGroup.filter((groupItem: any) => + _.isEqual(groupItem.tooltip, tooltipData) + ); + const color = tooltipItem.length + ? tooltipItem[0].fill || tooltipItem[0].stroke + : 'transparent'; + + const firstItem = values.pop() || ['', '']; + + let rowData = ''; + values.forEach((item: any) => { + rowData += ` + + ${sanitize(item[0])} + ${sanitize(item[1])} + + `; + }); + let tableData = `${rowData}
`; + + return ` +
+
+ + + + + + +
${sanitize(firstItem[0])}${sanitize(firstItem[1])}
+
+
+ ${tableData} +
+
+ `; + }, + }); view = new View(parse(spec, null, { expr: vegaExpressionInterpreter }), { renderer: 'canvas', // renderer (canvas or svg) container: `#${containerId}`, // parent DOM container hover: true, // enable hover processing }); view.tooltip(handler.call); - return view.runAsync(); + return view.runAsync().then((view: any) => { + const items = view.scenegraph().root.items[0].items || []; + const groups = items.filter( + (item: any) => item.name && item.name.match(/^(layer_).*(_marks)$/) + ); + for (let item of groups) { + pathGroup = pathGroup.concat(item.items); + } + }); } }