Skip to content

Commit

Permalink
Tooltips support
Browse files Browse the repository at this point in the history
  • Loading branch information
zBritva committed Dec 9, 2023
1 parent e54b6d0 commit 275c51c
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 14 deletions.
37 changes: 32 additions & 5 deletions charticulator-visual/capabilities.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
"displayNameKey": "Charticulator_Links",
"name": "links",
"kind": "GroupingOrMeasure"
},
{
"displayName": "Tooltips",
"displayNameKey": "Charticulator_Tooltips",
"name": "powerBITooltips",
"kind": "GroupingOrMeasure"
}
],
"privileges": [
Expand Down Expand Up @@ -171,15 +177,36 @@
"categorical": {
"categories": {
"select": [
{ "bind": { "to": "primarykey" } },
{ "bind": { "to": "links" } }
{
"bind": {
"to": "primarykey"
}
},
{
"bind": {
"to": "links"
}
},
{
"bind": {
"to": "powerBITooltips"
}
}
],
"dataReductionAlgorithm": { "top": { "count": 30000 } }
},
"values": {
"select": [
{ "bind": { "to": "primarykey" } },
{ "bind": { "to": "links" } }
{
"bind": {
"to": "primarykey"
}
},
{
"bind": {
"to": "links"
}
}
]
}
}
Expand All @@ -196,7 +223,7 @@
"canvas": true,
"default": true
},
"roles": ["data"],
"roles": ["tooltips"],
"supportEnhancedTooltips": true
}
}
42 changes: 39 additions & 3 deletions charticulator-visual/src/utils/dataParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Dataset } from "charticulator/src/container";

//2014-12-31T20:00:00.000Z
const timeFormat = '%Y-%m-%dT%H:%M:%S.000Z'
export const tooltipsTablename = "powerBITooltips"

export function mapColumnType(pbiType: ValueTypeDescriptor): Dataset.DataType {
if (pbiType.bool) {
Expand Down Expand Up @@ -79,6 +80,14 @@ export function convertData(
type: Dataset.TableType.Main
}

const tooltipsTable: Dataset.Table = {
displayName: "Tooltips",
name: tooltipsTablename,
columns: [],
rows: [],
type: Dataset.TableType.Main
}

const mainTableSelectionIds = new Map<number, ISelectionId>();

const linksTable: Dataset.Table = {
Expand All @@ -89,13 +98,14 @@ export function convertData(
type: Dataset.TableType.Links
}


if (categories?.length || values?.length) {
const allColumns = [...(categories ?? []), ...(values ?? [])];
allColumns.forEach(category => {
const source = category.source;
const displayName = source.displayName;

if (source.roles['primarykey']) {
if (source.roles['primarykey'] && !mainTable.columns.find(c => c.displayName === displayName)) {
mainTable.columns.push({
displayName,
name: displayName,
Expand All @@ -106,7 +116,18 @@ export function convertData(
});
}

if (source.roles['links']) {
if (source.roles['powerBITooltips'] && !tooltipsTable.columns.find(c => c.displayName === displayName)) {
tooltipsTable.columns.push({
displayName,
name: displayName,
type: mapColumnType(source.type),
metadata: {
kind: mapColumnKind(source.type),
}
});
}

if (source.roles['links'] && !linksTable.columns.find(c => c.displayName === displayName)) {
linksTable.columns.push({
displayName,
name: displayName,
Expand All @@ -132,6 +153,20 @@ export function convertData(
return row;
});

tooltipsTable.rows = allColumns[0].values.map<Dataset.Row>((_cat, index) => {
const row: Dataset.Row = {
_id: `${index}`
}

tooltipsTable.columns.forEach(column => {
const categoryColumn = allColumns.find(category => category.source.displayName === column.displayName);

row[column.displayName] = categoryColumn.values[index] as any;
})

return row;
});

const uniqueIndex = new Set();
mainTable.rows = [];
allColumns[0].values.forEach((_cat, index) => {
Expand Down Expand Up @@ -177,7 +212,8 @@ export function convertData(
name: "main",
tables: [
mainTable,
linksTable
linksTable,
tooltipsTable
].filter(table => table.columns.length)
},
mainTableSelectionIds
Expand Down
54 changes: 52 additions & 2 deletions charticulator-visual/src/views/Application.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';

import powerbi from "powerbi-visuals-api";
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import VisualTooltipDataItem = powerbi.extensibility.VisualTooltipDataItem;

import { Editor } from './Editor';
import { Mapping, UnmappedColumnName } from './Mapping';
Expand All @@ -21,6 +21,7 @@ import { importTempalte } from '../utils/importTemplate';
import { FluentProvider, Label, Tooltip, makeStyles, shorthands, teamsLightTheme } from "@fluentui/react-components";

import switchVisual from "./../../assets/label_tip.png"
import { tooltipsTablename } from '../utils/dataParser';

const useStyles = makeStyles({
tooltipWidthClass: {
Expand Down Expand Up @@ -139,7 +140,54 @@ export const Application: React.FC = () => {
modifiers.event.preventDefault();
}
return true;
}, [dataView, selections, selectionManager]);
}, [dataset, selections, selectionManager]);

const onMouseEnter = React.useCallback((table: string, rowIndices?: number[], modifiers?: IModifiers) => {
host.tooltipService.hide({
immediately: true,
isTouchEvent: false
});
if (!rowIndices) {
return;
}

const identities = rowIndices
.map(index => selections.get(index))
.filter(s => s)

const tooltipsTable = dataset.tables.find(t => t.name === tooltipsTablename);

if (!tooltipsTable) {
return;
}

const dataRows = rowIndices
.map(index => tooltipsTable.rows[index])
.filter(s => s)

const dataItems = dataRows.flatMap(row => {
return tooltipsTable.columns.map(column => {
return {
displayName: column.displayName,
value : `${row[column.displayName]}`
}
})
})

host.tooltipService.show({
coordinates: [modifiers.clientX, modifiers.clientY],
dataItems,
identities,
isTouchEvent: false
})
}, [dataset]);

const onMouseLeave = React.useCallback((table: string, rowIndices: number[], modifiers?: IModifiers) => {
host.tooltipService.hide({
immediately: true,
isTouchEvent: false
});
}, [dataset]);

const onBackgroundContextMenu = React.useCallback((e: React.MouseEvent) => {
onContextMenu(null, [], {
Expand Down Expand Up @@ -270,6 +318,8 @@ export const Application: React.FC = () => {
dataset={dataset}
onSelect={onSelect}
onContextMenu={onContextMenu}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
localization={localizaiton}
utcTimeZone={settings.localization.utcTimeZone}
/>
Expand Down
11 changes: 8 additions & 3 deletions charticulator-visual/src/views/ChartViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ export interface ViewerProps {
localization?: LocalizationConfig,
utcTimeZone: boolean,
onSelect?: (table: string, rowIndices: number[], modifiers?: IModifiers) => Promise<boolean>;
onContextMenu?: (table: string, rowIndices: number[], modifiers: IModifiers) => void;
onContextMenu?: (table: string, rowIndices: number[], modifiers?: IModifiers) => void;
onMouseEnter?: (table: string, rowIndices: number[], modifiers?: IModifiers) => void;
onMouseLeave?: (table: string, rowIndices: number[], modifiers?: IModifiers) => void;
}


export const ChartViewer: React.FC<ViewerProps> = ({
width,
height,
Expand All @@ -33,7 +34,9 @@ export const ChartViewer: React.FC<ViewerProps> = ({
localization,
utcTimeZone,
onSelect,
onContextMenu
onContextMenu,
onMouseEnter,
onMouseLeave
}) => {
// console.log('ChartViewer');

Expand All @@ -55,6 +58,8 @@ export const ChartViewer: React.FC<ViewerProps> = ({
});
});
container.addContextMenuListener(onContextMenu);
container.addMouseEnterListener(onMouseEnter);
container.addMouseLeaveListener(onMouseLeave);

return container.reactMount(width, height);
}

0 comments on commit 275c51c

Please sign in to comment.