Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/style with parameters #330

Merged
merged 4 commits into from
Feb 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/card/view/CardView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import NeoCodeEditorComponent from '../../component/editor/CodeEditorComponent';
import PlayCircleFilledIcon from '@material-ui/icons/PlayCircleFilled';

import { CARD_FOOTER_HEIGHT, CARD_HEADER_HEIGHT } from '../../config/CardConfig';
import { getReportTypes } from '../../extensions/ExtensionUtils';
import { extensionEnabled, getReportTypes } from '../../extensions/ExtensionUtils';
import NeoCodeViewerComponent from '../../component/editor/CodeViewerComponent';
import { NeoReportWrapper } from '../../report/ReportWrapper';
import { identifyStyleRuleParameters } from '../../extensions/styling/StyleRuleEvaluator';

const NeoCardView = ({
title,
Expand Down Expand Up @@ -41,12 +42,18 @@ const NeoCardView = ({
const reportHeight = heightPx - CARD_FOOTER_HEIGHT - CARD_HEADER_HEIGHT + 13;
const cardHeight = heightPx - CARD_FOOTER_HEIGHT;
const ref = React.useRef();

const [lastRunTimestamp, setLastRunTimestamp] = useState(Date.now());

const getLocalParameters = (parse_string): any => {
let re = /(?:^|\W)\$(\w+)(?!\w)/g;
let match;
let localQueryVariables: string[] = [];

// If the report styling extension is enabled, extend the list of local (relevant) parameters with those used by the style rules.
const styleRules = settings.styleRules ? settings.styleRules : [];
const styleParams = extensionEnabled(extensions, 'styling') ? identifyStyleRuleParameters(styleRules) : [];

let localQueryVariables: string[] = [...styleParams];
while ((match = re.exec(parse_string))) {
localQueryVariables.push(match[1]);
}
Expand Down
16 changes: 11 additions & 5 deletions src/chart/bar/BarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import { ResponsiveBar } from '@nivo/bar';
import React, { useEffect } from 'react';
import { NoDrawableDataErrorMessage } from '../../component/editor/CodeViewerComponent';
import { extensionEnabled } from '../../extensions/ExtensionUtils';
import { evaluateRulesOnDict } from '../../extensions/styling/StyleRuleEvaluator';
import {
evaluateRulesOnDict,
styleRulesReplaceParams,
identifyStyleRuleParameters,
useStyleRules,
} from '../../extensions/styling/StyleRuleEvaluator';
import { ChartProps } from '../Chart';
import { convertRecordObjectToString, recordToNative } from '../ChartUtils';

Expand Down Expand Up @@ -94,10 +99,11 @@ const NeoBarChart = (props: ChartProps) => {
const valueScale = settings.valueScale ? settings.valueScale : 'linear';
const minValue = settings.minValue ? settings.minValue : 'auto';
const maxValue = settings.maxValue ? settings.maxValue : 'auto';
const styleRules =
extensionEnabled(props.extensions, 'styling') && props.settings && props.settings.styleRules
? props.settings.styleRules
: [];
const styleRules = useStyleRules(
extensionEnabled(props.extensions, 'styling'),
props.settings.styleRules,
props.getGlobalParameter
);

// Compute bar color based on rules - overrides default color scheme completely.
const getBarColor = (bar) => {
Expand Down
12 changes: 7 additions & 5 deletions src/chart/graph/GraphChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import TableCell from '@material-ui/core/TableCell';
import TableContainer from '@material-ui/core/TableContainer';
import TableRow from '@material-ui/core/TableRow';
import SearchIcon from '@material-ui/icons/Search';
import { evaluateRulesOnNode } from '../../extensions/styling/StyleRuleEvaluator';
import { evaluateRulesOnNode, useStyleRules } from '../../extensions/styling/StyleRuleEvaluator';
import { extensionEnabled } from '../../extensions/ExtensionUtils';

const drawDataURIOnCanvas = (node, strDataURI, canvas, defaultNodeSize) => {
Expand Down Expand Up @@ -80,10 +80,6 @@ const NeoGraphChart = (props: ChartProps) => {
const nodeLabelColor = props.settings && props.settings.nodeLabelColor ? props.settings.nodeLabelColor : 'black';
const nodeLabelFontSize = props.settings && props.settings.nodeLabelFontSize ? props.settings.nodeLabelFontSize : 3.5;
const relLabelFontSize = props.settings && props.settings.relLabelFontSize ? props.settings.relLabelFontSize : 2.75;
const styleRules =
extensionEnabled(props.extensions, 'styling') && props.settings && props.settings.styleRules
? props.settings.styleRules
: [];
const relLabelColor = props.settings && props.settings.relLabelColor ? props.settings.relLabelColor : '#a0a0a0';
const nodeColorScheme = props.settings && props.settings.nodeColorScheme ? props.settings.nodeColorScheme : 'neodash';
const showPropertiesOnHover =
Expand All @@ -103,6 +99,12 @@ const NeoGraphChart = (props: ChartProps) => {
const linkDirectionalParticleSpeed =
props.settings && props.settings.relationshipParticleSpeed ? props.settings.relationshipParticleSpeed : 0.005; // Speed of particles on relationships.
const iconStyle = props.settings && props.settings.iconStyle !== undefined ? props.settings.iconStyle : '';
const styleRules = useStyleRules(
extensionEnabled(props.extensions, 'styling'),
props.settings.styleRules,
props.getGlobalParameter
);

let iconObject = undefined;
try {
iconObject = iconStyle ? JSON.parse(iconStyle) : undefined;
Expand Down
9 changes: 7 additions & 2 deletions src/chart/line/LineChart.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { ResponsiveLine } from '@nivo/line';
import React from 'react';
import { NoDrawableDataErrorMessage } from '../../component/editor/CodeViewerComponent';
import { evaluateRulesOnDict } from '../../extensions/styling/StyleRuleEvaluator';
import { evaluateRulesOnDict, useStyleRules } from '../../extensions/styling/StyleRuleEvaluator';
import { ChartProps } from '../Chart';
import { convertRecordObjectToString, recordToNative } from '../ChartUtils';
import { extensionEnabled } from '../../extensions/ExtensionUtils';

interface LineChartData {
id: string;
Expand Down Expand Up @@ -54,7 +55,11 @@ const NeoLineChart = (props: ChartProps) => {

const xTickRotationAngle = settings.xTickRotationAngle != undefined ? settings.xTickRotationAngle : 0;
const yTickRotationAngle = settings.yTickRotationAngle != undefined ? settings.yTickRotationAngle : 0;
const styleRules = settings && settings.styleRules ? settings.styleRules : [];
const styleRules = useStyleRules(
extensionEnabled(props.extensions, 'styling'),
props.settings.styleRules,
props.getGlobalParameter
);

// Compute line color based on rules - overrides default color scheme completely.
// For line charts, the line color is overridden if at least one value meets the criteria.
Expand Down
12 changes: 7 additions & 5 deletions src/chart/map/MapChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Marker from 'react-leaflet-enhanced-marker';
import MarkerClusterGroup from 'react-leaflet-cluster';
import LocationOnIcon from '@material-ui/icons/LocationOn';
import 'leaflet/dist/leaflet.css';
import { evaluateRulesOnNode } from '../../extensions/styling/StyleRuleEvaluator';
import { evaluateRulesOnNode, useStyleRules } from '../../extensions/styling/StyleRuleEvaluator';
import { extensionEnabled } from '../../extensions/ExtensionUtils';

const update = (state, mutations) => Object.assign({}, state, mutations);
Expand All @@ -26,10 +26,12 @@ const NeoMapChart = (props: ChartProps) => {
const defaultRelWidth = props.settings && props.settings.defaultRelWidth ? props.settings.defaultRelWidth : 3.5;
const defaultRelColor = props.settings && props.settings.defaultRelColor ? props.settings.defaultRelColor : '#666';
const nodeColorScheme = props.settings && props.settings.nodeColorScheme ? props.settings.nodeColorScheme : 'neodash';
const styleRules =
extensionEnabled(props.extensions, 'styling') && props.settings && props.settings.styleRules
? props.settings.styleRules
: [];
const styleRules = useStyleRules(
extensionEnabled(props.extensions, 'styling'),
props.settings.styleRules,
props.getGlobalParameter
);

const clusterMarkers =
props.settings && typeof props.settings.clusterMarkers !== 'undefined' ? props.settings.clusterMarkers : false;
const intensityProp = props.settings && props.settings.intensityProp ? props.settings.intensityProp : '';
Expand Down
9 changes: 7 additions & 2 deletions src/chart/pie/PieChart.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { ResponsivePie } from '@nivo/pie';
import React from 'react';
import { NoDrawableDataErrorMessage } from '../../component/editor/CodeViewerComponent';
import { evaluateRulesOnDict } from '../../extensions/styling/StyleRuleEvaluator';
import { evaluateRulesOnDict, useStyleRules } from '../../extensions/styling/StyleRuleEvaluator';
import { ChartProps } from '../Chart';
import { convertRecordObjectToString, recordToNative } from '../ChartUtils';
import { extensionEnabled } from '../../extensions/ExtensionUtils';

/**
* Embeds a PieChart (from Nivo) into NeoDash.
Expand Down Expand Up @@ -80,7 +81,11 @@ const NeoPieChart = (props: ChartProps) => {

const legend = settings.legend ? settings.legend : false;
const colorScheme = settings.colors ? settings.colors : 'set2';
const styleRules = settings && settings.styleRules ? settings.styleRules : [];
const styleRules = useStyleRules(
extensionEnabled(props.extensions, 'styling'),
props.settings.styleRules,
props.getGlobalParameter
);

// Compute slice color based on rules - overrides default color scheme completely.
const getSliceColor = (slice) => {
Expand Down
16 changes: 11 additions & 5 deletions src/chart/table/TableChart.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import React from 'react';
import { DataGrid } from '@mui/x-data-grid';
import { ChartProps } from '../Chart';
import { evaluateRulesOnDict, generateClassDefinitionsBasedOnRules } from '../../extensions/styling/StyleRuleEvaluator';
import {
evaluateRulesOnDict,
generateClassDefinitionsBasedOnRules,
useStyleRules,
} from '../../extensions/styling/StyleRuleEvaluator';
import { IconButton, Tooltip } from '@material-ui/core';
import { downloadCSV } from '../ChartUtils';
import SaveAltIcon from '@material-ui/icons/SaveAlt';
Expand Down Expand Up @@ -32,10 +36,12 @@ const NeoTableChart = (props: ChartProps) => {
const allowDownload =
props.settings && props.settings.allowDownload !== undefined ? props.settings.allowDownload : false;
const compact = props.settings && props.settings.compact !== undefined ? props.settings.compact : false;
const styleRules =
extensionEnabled(props.extensions, 'styling') && props.settings && props.settings.styleRules
? props.settings.styleRules
: [];
const styleRules = useStyleRules(
extensionEnabled(props.extensions, 'styling'),
props.settings.styleRules,
props.getGlobalParameter
);

const [notificationOpen, setNotificationOpen] = React.useState(false);

const useStyles = generateClassDefinitionsBasedOnRules(styleRules);
Expand Down
10 changes: 8 additions & 2 deletions src/extensions/advancedcharts/chart/radar/RadarChart.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React from 'react';
import { ChartProps } from '../../../../chart/Chart';
import { ResponsiveRadar } from '@nivo/radar';
import { evaluateRulesOnDict } from '../../../styling/StyleRuleEvaluator';
import { evaluateRulesOnDict, useStyleRules } from '../../../styling/StyleRuleEvaluator';
import { NoDrawableDataErrorMessage } from '../../../../component/editor/CodeViewerComponent';
import { extensionEnabled } from '../../../ExtensionUtils';

/**
* Embeds a RadarChart (from Charts) into NeoDash.
Expand Down Expand Up @@ -37,7 +38,12 @@ const NeoRadarChart = (props: ChartProps) => {
const blendMode = settings.blendMode ? settings.blendMode : 'normal';
const motionConfig = settings.motionConfig ? settings.motionConfig : 'gentle';
const curve = settings.curve ? settings.curve : 'linearClosed';
const styleRules = settings && settings.styleRules ? settings.styleRules : [];
const styleRules = useStyleRules(
extensionEnabled(props.extensions, 'styling'),
props.settings.styleRules,
props.getGlobalParameter
);

const keys = selection.values;

// Compute slice color based on rules - overrides default color scheme completely.
Expand Down
9 changes: 7 additions & 2 deletions src/extensions/advancedcharts/chart/sankey/SankeyChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { ResponsiveSankey } from '@nivo/sankey';
import { ChartProps } from '../../../../chart/Chart';
import { valueIsArray, valueIsNode, valueIsPath, valueIsRelationship } from '../../../../chart/ChartUtils';
import { categoricalColorSchemes } from '../../../../config/ColorConfig';
import { evaluateRulesOnDict, evaluateRulesOnNode } from '../../../styling/StyleRuleEvaluator';
import { evaluateRulesOnDict, evaluateRulesOnNode, useStyleRules } from '../../../styling/StyleRuleEvaluator';
import NeoCodeViewerComponent from '../../../../component/editor/CodeViewerComponent';
import { isCyclic } from '../../Utils';
import { extensionEnabled } from '../../../ExtensionUtils';

/**
* Embeds a SankeyChart (from Charts) into NeoDash.
Expand All @@ -31,7 +32,11 @@ const NeoSankeyChart = (props: ChartProps) => {
const nodeThickness = settings.nodeThickness ? settings.nodeThickness : 12;
const nodeSpacing = settings.nodeSpacing ? settings.nodeSpacing : 12;

const styleRules = settings && settings.styleRules ? settings.styleRules : [];
const styleRules = useStyleRules(
extensionEnabled(props.extensions, 'styling'),
props.settings.styleRules,
props.getGlobalParameter
);

// TODO this line is duplicated in a lot of places, should be in an utils file
const update = (state, mutations) => Object.assign({}, state, mutations);
Expand Down
35 changes: 35 additions & 0 deletions src/extensions/styling/StyleRuleEvaluator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { makeStyles } from '@material-ui/styles';
import { extensionEnabled } from '../ExtensionUtils';
import React, { useEffect } from 'react';

/**
* Evaluates the specified rule set on a row returned by the Neo4j driver.
Expand Down Expand Up @@ -179,3 +181,36 @@ export const generateClassDefinitionsBasedOnRules = (rules) => {
root: classes,
});
};

export const identifyStyleRuleParameters = (rules) => {
return rules.reduce((acc, rule) => {
if (rule.value.startsWith('$neodash_')) {
acc.push(rule.value.substring(1).trim());
}
return acc;
}, []);
};

export const styleRulesReplaceParams = (rules, getGlobalParameter) => {
return rules.reduce((acc, rule) => {
let r = Object.assign({}, rule);
if (r.value.startsWith('$neodash_')) {
r.value = getGlobalParameter(r.value.substring(1).trim())
? getGlobalParameter(r.value.substring(1).trim())
: r.value;
}
acc.push(r);
return acc;
}, []);
};

export function useStyleRules(enabled, rules, callback) {
if (!enabled || !rules) {
return [];
}
const styleParamsCalc = identifyStyleRuleParameters(rules);
let styleRules = styleParamsCalc;
styleRules = styleRulesReplaceParams(rules, callback);

return styleRules;
}