Skip to content

Commit c1ea932

Browse files
Feature/rule based styling table colouring (#944)
* rule based styling cell colouring feature * changing cell text/background colour now plays nicely * TODO note about row/cell rule mix and match behaviour
1 parent 8d4e72c commit c1ea932

File tree

3 files changed

+60
-11
lines changed

3 files changed

+60
-11
lines changed

src/chart/table/TableChart.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { DataGrid, GridColumnVisibilityModel } from '@mui/x-data-grid';
33
import { ChartProps } from '../Chart';
44
import {
55
evaluateRulesOnDict,
6+
evaluateSingleRuleOnDict,
67
generateClassDefinitionsBasedOnRules,
78
useStyleRules,
89
} from '../../extensions/styling/StyleRuleEvaluator';
@@ -243,6 +244,7 @@ export const NeoTableChart = (props: ChartProps) => {
243244
ColumnSortedDescendingIcon: () => <></>,
244245
ColumnSortedAscendingIcon: () => <></>,
245246
},
247+
// TODO: if mixing and matching row and cell styling, row rules MUST be set first or will not populate correctly
246248
getRowClassName: (params) => {
247249
return ['row color', 'row text color']
248250
.map((e) => {
@@ -253,7 +255,19 @@ export const NeoTableChart = (props: ChartProps) => {
253255
getCellClassName: (params) => {
254256
return ['cell color', 'cell text color']
255257
.map((e) => {
256-
return `rule${evaluateRulesOnDict({ [params.field]: params.value }, styleRules, [e])}`;
258+
let trueRulesList = [''];
259+
let trueRule;
260+
for (const [index, rule] of styleRules.entries()) {
261+
if (rule.targetField) {
262+
if (rule.targetField === params.field) {
263+
trueRule = `rule${evaluateSingleRuleOnDict({ [rule.field]: params.row[rule.field] }, rule, index, [e])}`;
264+
}
265+
} else {
266+
trueRule = `rule${evaluateSingleRuleOnDict({ [params.field]: params.value }, rule, index, [e])}`;
267+
}
268+
trueRulesList.push(trueRule);
269+
}
270+
return trueRulesList.join(' ');
257271
})
258272
.join(' ');
259273
},

src/extensions/styling/StyleRuleCreationModal.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,35 @@ export const NeoCustomReportStyleModal = ({
338338
}}
339339
fluid
340340
/>
341+
<Autocomplete
342+
className='n-align-middle n-inline-block n-w-5/12 n-pr-1'
343+
disableClearable={true}
344+
id={`autocomplete-label-type${index}`}
345+
size='small'
346+
noOptionsText='*Specify an exact field name'
347+
options={createFieldVariableSuggestions().filter((e) =>
348+
e.toLowerCase().includes(rule.targetField)
349+
)}
350+
value={rule.targetField ? rule.targetField : (rule.field ? rule.field : '')}
351+
inputValue={rule.targetField ? rule.targetField : (rule.field ? rule.field : '')}
352+
popupIcon={<></>}
353+
style={{ minWidth: 125, visibility: rule.customization.includes("cell") ? 'visible' : 'hidden', display: rule.customization.includes("cell") ? '' : 'none' }}
354+
onInputChange={(event, value) => {
355+
updateRuleField(index, 'targetField', value);
356+
}}
357+
onChange={(event, newValue) => {
358+
updateRuleField(index, 'targetField', newValue);
359+
}}
360+
renderInput={(params) => (
361+
<TextField
362+
{...params}
363+
placeholder='Target field name...'
364+
InputLabelProps={{ shrink: true }}
365+
style={{ padding: '6px 0 7px' }}
366+
size={'small'}
367+
/>
368+
)}
369+
/>
341370
<TextInput
342371
className='n-align-middle n-inline-block n-w-1/12 n-pr-1'
343372
style={{ minWidth: 30 }}

src/extensions/styling/StyleRuleEvaluator.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,21 +63,27 @@ export const evaluateRulesOnDict = (dict, rules, customizations) => {
6363
}
6464
for (const [index, rule] of rules.entries()) {
6565
// Only check customizations that are specified
66-
if (customizations.includes(rule.customization)) {
67-
// if the row contains the specified field...
68-
if (dict[rule.field] !== undefined && dict[rule.field] !== null) {
69-
const realValue = dict[rule.field].low ? dict[rule.field].low : dict[rule.field];
70-
const ruleValue = rule.value;
71-
if (evaluateCondition(realValue, rule.condition, ruleValue)) {
72-
return index;
73-
}
74-
}
75-
}
66+
return evaluateSingleRuleOnDict (dict, rule, index, customizations)
7667
}
7768
// If no rules are met, return not found (index=-1)
7869
return -1;
7970
};
8071

72+
export const evaluateSingleRuleOnDict = (dict, rule, ruleIndex, customizations) => {
73+
if (customizations.includes(rule.customization)) {
74+
// if the row contains the specified field...
75+
if (dict[rule.field] !== undefined && dict[rule.field] !== null) {
76+
const realValue = dict[rule.field].low ? dict[rule.field].low : dict[rule.field];
77+
const ruleValue = rule.value;
78+
if (evaluateCondition(realValue, rule.condition, ruleValue)) {
79+
return ruleIndex;
80+
}
81+
}
82+
}
83+
return -1;
84+
}
85+
86+
8187
/**
8288
* Evaluates the specified rule set on a node object returned by the Neo4j driver.
8389
* @param node - the node representation returned by the Neo4j driver.

0 commit comments

Comments
 (0)