diff --git a/src/client/map/MapSet/MapTooltip/getMapTooltip.ts b/src/client/map/MapSet/MapTooltip/getMapTooltip.ts index eed2ecc..916971d 100644 --- a/src/client/map/MapSet/MapTooltip/getMapTooltip.ts +++ b/src/client/map/MapSet/MapTooltip/getMapTooltip.ts @@ -10,6 +10,8 @@ import './getMapTooltip.css'; * - Uses layer configuration to determine tooltip attributes and formatting. * - Tooltip can be customized via geojsonOptions in datasource configuration with tooltipSettings: * - attributes: array of attribute definitions (key, label, unit, decimalPlaces). + * - labelTemplate: optional template applied to all labels (supports [key] substitution). + * - excludeKeys: optional array of attribute keys to exclude from the tooltip. * - nativeStyles: custom CSS styles for tooltip container. * - nativeClassName: additional CSS class names for tooltip container. * - title: optional tooltip title. @@ -57,7 +59,10 @@ export const getMapTooltip = ({ // Use configured attributes if available if (tooltipSettings?.attributes && Array.isArray(tooltipSettings.attributes)) { - tooltipProperties = getTooltipAttributes(tooltipSettings.attributes, featureProperties); + tooltipProperties = getTooltipAttributes(tooltipSettings.attributes, featureProperties, { + labelTemplate: tooltipSettings?.labelTemplate, + excludeKeys: tooltipSettings?.excludeKeys, + }); } // If no valid tooltip properties, do not show tooltip if (!tooltipProperties || tooltipProperties.length === 0) { @@ -72,16 +77,8 @@ export const getMapTooltip = ({ .map(({ key, label, value, unit }) => { const valueStr = value == null ? '' : String(value); - // Replace all [key] patterns in the label with the corresponding featureProperties value - let displayLabel = label; - if (typeof label === 'string') { - displayLabel = label.replace(/\[([^\]]+)\]/g, (_, k) => - featureProperties[k] != null ? featureProperties[k] : `[${k}]` - ); - } - return `
- ${displayLabel + (valueStr ? ':' : '')} + ${label + (valueStr ? ':' : '')} ${valueStr}${unit ? ` ${unit}` : ''} diff --git a/src/client/map/MapSet/handleMapHover.ts b/src/client/map/MapSet/handleMapHover.ts index ab59ec8..059b85f 100644 --- a/src/client/map/MapSet/handleMapHover.ts +++ b/src/client/map/MapSet/handleMapHover.ts @@ -35,7 +35,7 @@ interface HandleMapHoverParams { * Handles hover events on the map and sets tooltip if enabled. * * - Shows tooltip with feature properties if enabled in layer configuration. - * - Tooltip attributes and formatting are defined in geojsonOptions.tooltipSettings. + * - Tooltip attributes and formatting are defined in geojsonOptions.tooltipSettings (attributes, labelTemplate, excludeKeys). * - If no attributes are defined, uses 'value' property if present. * - Tooltip is hidden if not enabled or no valid properties found. * - Also updates layer hover state for cursor feedback. @@ -63,7 +63,7 @@ export function handleMapHover({ ? mapLayers.find((layer: RenderingLayer) => layer.key === layerId) : undefined; - const featureProperties = event.object?.properties; + const featureProperties = event.object?.properties || {}; const config = parseDatasourceConfiguration(mapLayer?.datasource?.configuration); @@ -89,7 +89,10 @@ export function handleMapHover({ * Otherwise, tooltip will not be shown. */ if (tooltipSettings?.attributes && Array.isArray(tooltipSettings.attributes)) { - tooltipProperties = getTooltipAttributes(tooltipSettings.attributes, featureProperties); + tooltipProperties = getTooltipAttributes(tooltipSettings.attributes, featureProperties, { + labelTemplate: tooltipSettings?.labelTemplate, + excludeKeys: tooltipSettings?.excludeKeys, + }); } /** diff --git a/src/client/story/utils/getTooltipAttributes.ts b/src/client/story/utils/getTooltipAttributes.ts index a5cde4c..4a66557 100644 --- a/src/client/story/utils/getTooltipAttributes.ts +++ b/src/client/story/utils/getTooltipAttributes.ts @@ -14,28 +14,54 @@ export interface TooltipAttribute { decimalPlaces?: number; } +/** + * Optional tooltip processing settings. + * @property {string} [labelTemplate] - Template applied to all labels (supports [key] substitution). + * @property {string[]} [excludeKeys] - Attribute keys to exclude from tooltip output. + */ +export interface TooltipAttributeOptions { + labelTemplate?: string; + excludeKeys?: string[]; +} + /** * Maps feature properties to tooltip attributes based on settings. * Rounds numbers if decimalPlaces is specified. + * Supports label substitution for [key] placeholders. * * @param {TooltipAttribute[]} attributes - Array of attribute settings. * @param {Record} featureProperties - Properties of the hovered feature. + * @param {TooltipAttributeOptions} [options] - Optional label/exclusion settings. * @returns {TooltipAttribute[]} Array of tooltip attributes to display. */ export function getTooltipAttributes( attributes: TooltipAttribute[], - featureProperties: Record + featureProperties: Record, + options?: TooltipAttributeOptions ): TooltipAttribute[] { + const properties = featureProperties ?? {}; + const excludeKeys = new Set(options?.excludeKeys ?? []); + const labelTemplate = options?.labelTemplate; + return attributes + .filter((attribute) => !excludeKeys.has(attribute.key)) .map((attribute: TooltipAttribute) => { - let value = featureProperties[attribute.key]; + let value = properties[attribute.key]; // Round value if decimalPlaces is specified and value is a number if (typeof value === 'number' && typeof attribute.decimalPlaces === 'number') { value = Number(value.toFixed(attribute.decimalPlaces)); } + + let label = labelTemplate ?? attribute.label ?? ''; + if (typeof label === 'string') { + label = label.replace(/\[([^\]]+)\]/g, (_, key) => + properties[key] != null ? String(properties[key]) : `[${key}]` + ); + } + return { key: attribute.key, - label: attribute.label ?? '', + label, value, unit: attribute.unit ?? '', };