From 47f26c765bcc492ab8f9bf61cdfb61c6aab70258 Mon Sep 17 00:00:00 2001 From: Monish Nandakumaran Date: Wed, 20 Nov 2024 09:10:03 +0530 Subject: [PATCH 1/4] checkbox with multiple condition --- src/card/settings/CardSettingsFooter.tsx | 1 + src/chart/table/TableActionsHelper.ts | 8 + src/chart/table/TableChart.tsx | 22 ++- .../actions/ActionsRuleCreationModal.tsx | 148 +++++++++++++++++- 4 files changed, 174 insertions(+), 5 deletions(-) diff --git a/src/card/settings/CardSettingsFooter.tsx b/src/card/settings/CardSettingsFooter.tsx index e70da3d2f..649b1f740 100644 --- a/src/card/settings/CardSettingsFooter.tsx +++ b/src/card/settings/CardSettingsFooter.tsx @@ -148,6 +148,7 @@ const NeoCardSettingsFooter = ({ settingValue={reportSettings[actionsToCustomize]} type={type} fields={fields} + _preConditions={reportSettings?.preConditions} customReportActionsModalOpen={customReportActionsModalOpen} setCustomReportActionsModalOpen={setCustomReportActionsModalOpen} onReportSettingUpdate={onReportSettingUpdate} diff --git a/src/chart/table/TableActionsHelper.ts b/src/chart/table/TableActionsHelper.ts index 7b946df2e..580a59f0d 100644 --- a/src/chart/table/TableActionsHelper.ts +++ b/src/chart/table/TableActionsHelper.ts @@ -3,6 +3,14 @@ export const hasCheckboxes = (actionsRules) => { return rules.length > 0; }; +export const hasPreCondition = (preConditions) => { + return preConditions.length > 0; +}; + +export const convertConditionsToExpression = (conditions, row) => { + return !conditions.every((condition) => row[condition.field] === condition.value); +}; + export const getCheckboxes = (actionsRules, rows, getGlobalParameter) => { let rules = actionsRules.filter((rule) => rule.condition && rule.condition == 'rowCheck'); const params = rules.map((rule) => `neodash_${rule.customizationValue}`); diff --git a/src/chart/table/TableChart.tsx b/src/chart/table/TableChart.tsx index 28ae25f45..cebae41fd 100644 --- a/src/chart/table/TableChart.tsx +++ b/src/chart/table/TableChart.tsx @@ -1,5 +1,5 @@ import React, { useEffect } from 'react'; -import { DataGrid, GridColumnVisibilityModel } from '@mui/x-data-grid'; +import { DataGrid, GridColumnVisibilityModel, GridRowId } from '@mui/x-data-grid'; import { ChartProps } from '../Chart'; import { evaluateRulesOnDict, @@ -22,7 +22,13 @@ import { ThemeProvider, createTheme } from '@mui/material/styles'; import Button from '@mui/material/Button'; import { extensionEnabled } from '../../utils/ReportUtils'; import { renderCellExpand } from '../../component/misc/DataGridExpandRenderer'; -import { getCheckboxes, hasCheckboxes, updateCheckBoxes } from './TableActionsHelper'; +import { + convertConditionsToExpression, + getCheckboxes, + hasCheckboxes, + hasPreCondition, + updateCheckBoxes, +} from './TableActionsHelper'; import ApiService from '../../utils/apiService'; import { AxiosResponse } from 'axios'; @@ -96,6 +102,10 @@ export const NeoTableChart = (props: ChartProps) => { extensionEnabled(props.extensions, 'actions') && props.settings && props.settings.actionsRules ? props.settings.actionsRules : []; + const preConditions = + extensionEnabled(props.extensions, 'actions') && props.settings && props.settings.preConditions + ? props.settings.preConditions + : []; const compact = props.settings && props.settings.compact !== undefined ? props.settings.compact : false; const styleRules = useStyleRules( extensionEnabled(props.extensions, 'styling'), @@ -385,6 +395,13 @@ export const NeoTableChart = (props: ChartProps) => { ? { marginTop: 10, height: '90%', width: '100%', position: 'relative' } : { height: '100%', width: '100%', position: 'relative' }; + const isRowSelectable = (params: { id: GridRowId; row: any }) => { + if (hasPreCondition(preConditions)) { + return convertConditionsToExpression(preConditions, params.row); + } + return false; + }; + return ( {isApiSpecEnabled ? apiCallButton() : <>} @@ -455,6 +472,7 @@ export const NeoTableChart = (props: ChartProps) => { onSelectionModelChange={(selection) => updateCheckBoxes(actionsRules, rows, selection, props.setGlobalParameter) } + isRowSelectable={isRowSelectable} autoPageSize pagination disableSelectionOnClick diff --git a/src/extensions/actions/ActionsRuleCreationModal.tsx b/src/extensions/actions/ActionsRuleCreationModal.tsx index 48d6486ad..9d7e3c408 100644 --- a/src/extensions/actions/ActionsRuleCreationModal.tsx +++ b/src/extensions/actions/ActionsRuleCreationModal.tsx @@ -8,7 +8,26 @@ import { } from '@neo4j-ndl/react/icons'; import { getPageNumbersAndNamesList } from '../advancedcharts/Utils'; import { IconButton, Button, Dialog, Dropdown, TextInput } from '@neo4j-ndl/react'; -import { Autocomplete, TextField } from '@mui/material'; +import { Autocomplete, TextField, Typography } from '@mui/material'; + +// Pre conditions + +const PRE_CONDITIONS_RULES = [ + { + value: '===', + label: '=', + }, + { + value: '!==', + label: '!=', + }, +]; + +const defaultPreCondition = { + condition: '=', + field: '', + value: '', +}; // The set of conditional checks that are included in the rule specification. const RULE_CONDITIONS = { @@ -166,12 +185,17 @@ export const NeoCustomReportActionsModal = ({ fields, setCustomReportActionsModalOpen, onReportSettingUpdate, + _preConditions, }) => { // The rule set defined in this modal is updated whenever the setting value is externally changed. const [rules, setRules] = React.useState([]); + const [preConditions, setPreConditions] = React.useState([defaultPreCondition]); useEffect(() => { if (settingValue) { setRules(settingValue); + if (_preConditions) { + setPreConditions(_preConditions); + } } }, [settingValue]); @@ -183,6 +207,12 @@ export const NeoCustomReportActionsModal = ({ } else { onReportSettingUpdate(settingName, rules); } + + if (preConditions.length === 0) { + onReportSettingUpdate('preConditions', undefined); + } else { + onReportSettingUpdate('preConditions', preConditions); + } setCustomReportActionsModalOpen(false); }; @@ -193,6 +223,10 @@ export const NeoCustomReportActionsModal = ({ setRules(newRules); }; + const updatePreConditionFieldById = (j, field, value) => { + setPreConditions((prevItems) => prevItems.map((item, i) => (i === j ? { ...item, [field]: value } : item))); + }; + /** * Create the list of suggestions used in the autocomplete box of the rule specification window. * This will be dynamic based on the type of report we are customizing. @@ -333,7 +367,7 @@ export const NeoCustomReportActionsModal = ({ const td2Styling = (type) => ({ width: type === 'bar' ? '15%' : '30%' }); const td2DropdownClassname = (type) => `n-align-middle n-pr-1 ${type === 'bar' ? 'n-w-full' : 'n-w-2/5'}`; const td2Autocomplete = (type, index, rule) => - (type !== 'bar' && rule.condition !== 'rowCheck' ? ( + type !== 'bar' && rule.condition !== 'rowCheck' ? ( ) : ( <> - )); + ); const td4Styling = (type) => ({ width: type === 'bar' ? '45%' : '40%' }); const td4DropdownClassname = 'n-align-middle, n-w-1/3'; const td6Styling = (type) => ({ width: type === 'bar' ? '30%' : '20%' }); @@ -535,6 +569,114 @@ export const NeoCustomReportActionsModal = ({ + + + + + + + + + {preConditions.map((con, i) => { + return ( + + + + + + + ); + })} + + + + +
+
+ Report Pre Conditions +
+ {i + 1}. + IF + +
+ + e.toLowerCase().includes(con.field.toLowerCase()) + )} + value={con.field ? con.field : ''} + inputValue={con.field ? con.field : ''} + popupIcon={<>} + style={{ minWidth: 125 }} + onInputChange={(event, value) => { + updatePreConditionFieldById(i, 'field', value); + }} + onChange={(event, newValue) => { + updatePreConditionFieldById(i, 'field', newValue); + }} + renderInput={(params) => ( + + )} + /> + updatePreConditionFieldById(i, 'condition', newValue?.value), + options: PRE_CONDITIONS_RULES.map((option) => ({ + label: option.label, + value: option.value, + })), + value: { label: con.condition, value: con.condition }, + }} + style={{ minWidth: 70, display: 'inline-block' }} + fluid + /> + updatePreConditionFieldById(i, 'value', e.target.value)} + fluid + > +
+
+ { + setPreConditions((prevItems) => prevItems.filter((_, j) => j !== i)); + }} + > + + +
+
+ { + setPreConditions([...preConditions, defaultPreCondition]); + }} + > + + +
+
From a1989f7b5bc3186bd3ba158afb6b469621f064f8 Mon Sep 17 00:00:00 2001 From: Monish Nandakumaran Date: Wed, 20 Nov 2024 09:23:46 +0530 Subject: [PATCH 2/4] multiple condition checkbox disable --- src/chart/table/TableActionsHelper.ts | 13 ++++++++++++- src/extensions/actions/ActionsRuleCreationModal.tsx | 4 ++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/chart/table/TableActionsHelper.ts b/src/chart/table/TableActionsHelper.ts index 580a59f0d..970e6eef2 100644 --- a/src/chart/table/TableActionsHelper.ts +++ b/src/chart/table/TableActionsHelper.ts @@ -8,7 +8,18 @@ export const hasPreCondition = (preConditions) => { }; export const convertConditionsToExpression = (conditions, row) => { - return !conditions.every((condition) => row[condition.field] === condition.value); + return !conditions.every((condition) => evaluateCondition(condition, row)); +}; + +const evaluateCondition = (condition, row) => { + switch (condition.condition) { + case '=': + return row[condition.field] === condition.value; + case '!=': + return row[condition.field] !== condition.value; + default: + return false; + } }; export const getCheckboxes = (actionsRules, rows, getGlobalParameter) => { diff --git a/src/extensions/actions/ActionsRuleCreationModal.tsx b/src/extensions/actions/ActionsRuleCreationModal.tsx index 9d7e3c408..6393c2f40 100644 --- a/src/extensions/actions/ActionsRuleCreationModal.tsx +++ b/src/extensions/actions/ActionsRuleCreationModal.tsx @@ -14,11 +14,11 @@ import { Autocomplete, TextField, Typography } from '@mui/material'; const PRE_CONDITIONS_RULES = [ { - value: '===', + value: '=', label: '=', }, { - value: '!==', + value: '!=', label: '!=', }, ]; From 752f2440f6f107fe2bb28c1a0a091d4a898ab508 Mon Sep 17 00:00:00 2001 From: Monish Nandakumaran Date: Wed, 20 Nov 2024 11:37:13 +0530 Subject: [PATCH 3/4] checkbox disabled feature --- src/chart/table/TableActionsHelper.ts | 29 +++++++++++++++++-- src/chart/table/TableChart.tsx | 2 +- .../actions/ActionsRuleCreationModal.tsx | 8 +++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/chart/table/TableActionsHelper.ts b/src/chart/table/TableActionsHelper.ts index 970e6eef2..65a968eda 100644 --- a/src/chart/table/TableActionsHelper.ts +++ b/src/chart/table/TableActionsHelper.ts @@ -7,16 +7,39 @@ export const hasPreCondition = (preConditions) => { return preConditions.length > 0; }; +const groupConditionsByField = (conditions) => { + return conditions.reduce((acc, condition) => { + if (!acc[condition.field]) { + acc[condition.field] = []; + } + acc[condition.field].push(condition); + return acc; + }, {}); +}; + +const evaluateGroupedConditions = (groupedConditions, row) => { + return Object.keys(groupedConditions).every((field) => { + // Logical OR between conditions for the same field + return groupedConditions[field].some((condition) => evaluateCondition(condition, row)); + }); +}; + export const convertConditionsToExpression = (conditions, row) => { - return !conditions.every((condition) => evaluateCondition(condition, row)); + const groupedConditions = groupConditionsByField(conditions); + return !evaluateGroupedConditions(groupedConditions, row); }; const evaluateCondition = (condition, row) => { + const fieldValue = row[condition.field]; switch (condition.condition) { case '=': - return row[condition.field] === condition.value; + return fieldValue === condition.value; case '!=': - return row[condition.field] !== condition.value; + return fieldValue !== condition.value; + case 'contains': + return typeof fieldValue === 'string' && fieldValue.includes(condition.value); + case 'not_contains': + return typeof fieldValue === 'string' && !fieldValue.includes(condition.value); default: return false; } diff --git a/src/chart/table/TableChart.tsx b/src/chart/table/TableChart.tsx index cebae41fd..2db1b3df2 100644 --- a/src/chart/table/TableChart.tsx +++ b/src/chart/table/TableChart.tsx @@ -399,7 +399,7 @@ export const NeoTableChart = (props: ChartProps) => { if (hasPreCondition(preConditions)) { return convertConditionsToExpression(preConditions, params.row); } - return false; + return true; }; return ( diff --git a/src/extensions/actions/ActionsRuleCreationModal.tsx b/src/extensions/actions/ActionsRuleCreationModal.tsx index 6393c2f40..1826fb433 100644 --- a/src/extensions/actions/ActionsRuleCreationModal.tsx +++ b/src/extensions/actions/ActionsRuleCreationModal.tsx @@ -21,6 +21,14 @@ const PRE_CONDITIONS_RULES = [ value: '!=', label: '!=', }, + { + value: 'contains', + label: 'contains', + }, + { + value: 'not_contains', + label: 'not_contains', + }, ]; const defaultPreCondition = { From e45c07d758f6c68bf4cc1b3d81d5db1f22de58ff Mon Sep 17 00:00:00 2001 From: Monish Nandakumaran Date: Wed, 20 Nov 2024 18:52:22 +0530 Subject: [PATCH 4/4] updated code --- src/card/settings/CardSettingsFooter.tsx | 2 +- src/extensions/actions/ActionsRuleCreationModal.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/card/settings/CardSettingsFooter.tsx b/src/card/settings/CardSettingsFooter.tsx index 649b1f740..8f16c2688 100644 --- a/src/card/settings/CardSettingsFooter.tsx +++ b/src/card/settings/CardSettingsFooter.tsx @@ -148,7 +148,7 @@ const NeoCardSettingsFooter = ({ settingValue={reportSettings[actionsToCustomize]} type={type} fields={fields} - _preConditions={reportSettings?.preConditions} + preConditionsSetting={reportSettings?.preConditions} customReportActionsModalOpen={customReportActionsModalOpen} setCustomReportActionsModalOpen={setCustomReportActionsModalOpen} onReportSettingUpdate={onReportSettingUpdate} diff --git a/src/extensions/actions/ActionsRuleCreationModal.tsx b/src/extensions/actions/ActionsRuleCreationModal.tsx index 1826fb433..737d2eea2 100644 --- a/src/extensions/actions/ActionsRuleCreationModal.tsx +++ b/src/extensions/actions/ActionsRuleCreationModal.tsx @@ -193,7 +193,7 @@ export const NeoCustomReportActionsModal = ({ fields, setCustomReportActionsModalOpen, onReportSettingUpdate, - _preConditions, + preConditionsSetting, }) => { // The rule set defined in this modal is updated whenever the setting value is externally changed. const [rules, setRules] = React.useState([]); @@ -201,8 +201,8 @@ export const NeoCustomReportActionsModal = ({ useEffect(() => { if (settingValue) { setRules(settingValue); - if (_preConditions) { - setPreConditions(_preConditions); + if (preConditionsSetting) { + setPreConditions(preConditionsSetting); } } }, [settingValue]);