Skip to content

Commit

Permalink
feat: remove onClick handler to be more sandboxed
Browse files Browse the repository at this point in the history
  • Loading branch information
BrightGrafana committed Oct 17, 2023
1 parent a9fbd2f commit b5209bb
Show file tree
Hide file tree
Showing 4 changed files with 10 additions and 55 deletions.
4 changes: 2 additions & 2 deletions README.md
@@ -1,6 +1,6 @@
# Interactive Tree Plugin

Welcome to the Interactive Tree Plugin, your solution for creating interactive Tree diagrams in Grafana 9.5+.
Welcome to the Interactive Tree Plugin, your solution for creating interactive Tree diagrams in Grafana 10.0+.

![Plugin Demo](https://equansdatahub.azureedge.net/grafana-tree-panel/tree-usage-demo.gif)

Expand Down Expand Up @@ -29,7 +29,7 @@ When configuring the panel, you have several customization options at your dispo
- **Show item count**: Toggle to display the count of first-level child nodes for nodes with children.
- **Order in each level**: Sort nodes by name in ascending, descending, or custom order.
- **Allow multi select using Ctrl-Click or Shift-Click**: Enable multiple node selection by holding the Ctrl or shift key.
- **Node Click Behavior**: Define the action to perform when clicking on a tree node. Either set a dashboard variable or run a custom JS function
- **Node click dashboard variable**: Define the dashboard variable to set when clicking a node or leaf.

![Plugin Options Demo](https://equansdatahub.azureedge.net/grafana-tree-panel/equans-grafana-tree-plugin-options-demo.gif)

Expand Down
26 changes: 7 additions & 19 deletions src/TreePanel.tsx
@@ -1,15 +1,12 @@
import { PanelData, PanelProps } from '@grafana/data';
import { getTemplateSrv, locationService } from '@grafana/runtime';
import { locationService } from '@grafana/runtime';
import { TreeView, TreeItem } from '@material-ui/lab';
import { ExpandMore, ChevronRight } from '@material-ui/icons';
import React from 'react';
import { Utils, Validator } from './';
import { Node, PanelOptions, TreeLevelOrderMode, TreeClickEventControlMode, RawNode } from './models';
import { Node, PanelOptions, TreeLevelOrderMode, RawNode } from './models';
import './CSS/classes.css';

// TODO: try and moe into the Tree function
let treeDepth: number;

function validateOptionsInput(options: PanelOptions, data: PanelData) {
// Check for required panel options
if (options.displayedTreeDepth === undefined || options.displayedTreeDepth < 0) {
Expand All @@ -29,10 +26,7 @@ function validateOptionsInput(options: PanelOptions, data: PanelData) {
);
}

if (
options.clickMode === TreeClickEventControlMode.Basic &&
(!options.dashboardVariableName || options.dashboardVariableName.trim() === '')
) {
if (!options.dashboardVariableName || options.dashboardVariableName.trim() === '') {
throw new ReferenceError(
"'Dashboard variable name' must be defined in panel options, when using dashboard variable on click mode."
);
Expand All @@ -51,8 +45,7 @@ function validateOptionsInput(options: PanelOptions, data: PanelData) {

export const Tree: React.FC<PanelProps<PanelOptions>> = ({ options, data }) => {
validateOptionsInput(options, data);

const customJsFn = new Function('data', 'locationService', 'getTemplateSrv', options.onClick);
let treeDepth = 0;

// Convert data to a Node array
const queryResult: RawNode[] = React.useMemo(
Expand Down Expand Up @@ -127,14 +120,9 @@ export const Tree: React.FC<PanelProps<PanelOptions>> = ({ options, data }) => {

// Handle node selection
function setSelectedNodeId(event: React.ChangeEvent<any>, nodeIds: any): void {
if (options.clickMode === TreeClickEventControlMode.Basic) {
// SET a dashboard variable.
const nodeId = typeof nodeIds === 'number' ? [nodeIds] : nodeIds;
locationService.partial({ [`var-${options.dashboardVariableName}`]: nodeId }, true);
} else if (options.clickMode === TreeClickEventControlMode.Advanced) {
// use custom onClink handler
customJsFn(Utils.extractSelectedTreeNodes(data, nodeIds, options.idColumn), locationService, getTemplateSrv);
}
// SET a dashboard variable.
const nodeId = typeof nodeIds === 'number' ? [nodeIds] : nodeIds;
locationService.partial({ [`var-${options.dashboardVariableName}`]: nodeId }, true);
}

// Render TreeItem components recursively
Expand Down
4 changes: 1 addition & 3 deletions src/models/panel-options.ts
@@ -1,4 +1,4 @@
import { TreeClickEventControlMode, TreeLevelOrderMode } from "./";
import { TreeLevelOrderMode } from "./";

export interface PanelOptions {
multiSelect: boolean;
Expand All @@ -8,7 +8,5 @@ export interface PanelOptions {
parentIdColumn: string;
displayedTreeDepth: number;
showItemCount: boolean;
clickMode: TreeClickEventControlMode;
dashboardVariableName: string;
onClick: string;
}
31 changes: 0 additions & 31 deletions src/module.ts
@@ -1,10 +1,6 @@
import { PanelPlugin } from '@grafana/data';
import { Tree } from './TreePanel';
import { PanelOptions, TreeLevelOrderMode } from 'models';
import { PanelOptionCode } from 'PanelOptionCode';
import { TreeClickEventControlMode } from 'models/tree-click-event-control-mode';

const isOnClickMode = (mode: PanelOptions['onClick']) => (config: any) => config.clickMode === mode;

export const plugin = new PanelPlugin<PanelOptions>(Tree).setPanelOptions((builder) => {
return builder
Expand Down Expand Up @@ -54,37 +50,10 @@ export const plugin = new PanelPlugin<PanelOptions>(Tree).setPanelOptions((build
name: 'Allow multi select using Ctrl-Click or Shift-Click.',
defaultValue: true,
})
.addRadio({
path: 'clickMode',
name: 'Select type of clicking control',
defaultValue: TreeClickEventControlMode.Basic,
settings: {
options: [
{ value: TreeClickEventControlMode.Basic, label: 'Set dashboard variable' },
{ value: TreeClickEventControlMode.Advanced, label: 'Advanced' },
],
},
})
.addTextInput({
path: 'dashboardVariableName',
name: 'Dashboard variable name',
description: 'Name of the dashboard variable in which the id of the clicked node(s) is/are stored.',
defaultValue: 'Placeholder',
showIf: isOnClickMode(TreeClickEventControlMode.Basic),
})
.addCustomEditor({
id: 'onClick',
path: 'onClick',
name: 'On-click Trigger',
description: `
Script executed when Tree node(s) are clicked.
\`f(data,locationService, getTemplateSrv){...}\``,
editor: PanelOptionCode,
settings: {
language: 'javascript',
},
defaultValue: `// console.log(data, locationService, getTemplateSrv);
// window.updateVariables({query:{'var-project':'test'}, partial: true})`,
showIf: isOnClickMode(TreeClickEventControlMode.Advanced),
});
});

0 comments on commit b5209bb

Please sign in to comment.