Skip to content

Commit dbf3ee2

Browse files
Custom Query Parameter Select (#353)
* Version 1 * Fixed label for selector type * Version 1 * Fixed label for selector type * Bugs on db selector * Improving hint text * Removed unused variables * Solving breaks on non valid queries * Solving compatibility mode * Display valid not only lowercase * Bug query lost fix * Fixed styling for custom query parameter select --------- Co-authored-by: Niels de Jong <[email protected]>
1 parent c1f84e7 commit dbf3ee2

File tree

5 files changed

+126
-24
lines changed

5 files changed

+126
-24
lines changed

src/card/settings/custom/CardSettingsContentPropertySelect.tsx

Lines changed: 77 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ import { debounce, MenuItem, TextField } from '@material-ui/core';
88
import { Autocomplete } from '@material-ui/lab';
99
import NeoField from '../../../component/field/Field';
1010
import { getReportTypes } from '../../../extensions/ExtensionUtils';
11+
import NeoCodeEditorComponent from '../../../component/editor/CodeEditorComponent';
1112

1213
const NeoCardSettingsContentPropertySelect = ({
14+
query,
1315
type,
1416
database,
1517
settings,
@@ -24,6 +26,8 @@ const NeoCardSettingsContentPropertySelect = ({
2426
);
2527
}
2628

29+
const [queryText, setQueryText] = React.useState(query);
30+
const debouncedQueryUpdate = useCallback(debounce(onQueryUpdate, 250), []);
2731
const debouncedRunCypherQuery = useCallback(debounce(runCypherQuery, RUN_QUERY_DELAY_MS), []);
2832

2933
const { manualPropertyNameSpecification } = settings;
@@ -45,11 +49,15 @@ const NeoCardSettingsContentPropertySelect = ({
4549
);
4650
}, [settings.suggestionLimit, settings.deduplicateSuggestions, settings.searchType, settings.caseSensitive]);
4751

52+
useEffect(() => {
53+
setLabelRecords([]);
54+
setPropertyRecords([]);
55+
}, [database]);
56+
4857
const cleanParameter = (parameter: string) => parameter.replaceAll(' ', '_').replaceAll('-', '_').toLowerCase();
4958
const formatParameterId = (id: string | undefined | null) => {
5059
const cleanedId = id || '';
51-
const formattedId = cleanedId == '' || cleanedId.startsWith('_') ? cleanedId : `_${cleanedId}`;
52-
return formattedId;
60+
return cleanedId == '' || cleanedId.startsWith('_') ? cleanedId : `_${cleanedId}`;
5361
};
5462

5563
if (settings.type == undefined) {
@@ -64,20 +72,23 @@ const NeoCardSettingsContentPropertySelect = ({
6472
onReportSettingUpdate('parameterName', parameterName);
6573
}
6674
// Define query callback to allow reports to get extra data on interactions.
67-
const queryCallback = useCallback((query, parameters, setRecords) => {
68-
debouncedRunCypherQuery(
69-
driver,
70-
database,
71-
query,
72-
parameters,
73-
10,
74-
(status) => {
75-
status == QueryStatus.NO_DATA ? setRecords([]) : null;
76-
},
77-
(result) => setRecords(result),
78-
() => {}
79-
);
80-
}, []);
75+
const queryCallback = useCallback(
76+
(query, parameters, setRecords) => {
77+
debouncedRunCypherQuery(
78+
driver,
79+
database,
80+
query,
81+
parameters,
82+
10,
83+
(status) => {
84+
status == QueryStatus.NO_DATA ? setRecords([]) : null;
85+
},
86+
(result) => setRecords(result),
87+
() => {}
88+
);
89+
},
90+
[database]
91+
);
8192

8293
function handleParameterTypeUpdate(newValue) {
8394
onReportSettingUpdate('entityType', undefined);
@@ -178,13 +189,13 @@ const NeoCardSettingsContentPropertySelect = ({
178189
`ORDER BY size(toString(value)) ASC LIMIT ${limit}`;
179190
onQueryUpdate(newQuery);
180191
} else {
181-
const newQuery = 'RETURN true';
192+
const newQuery = query;
182193
onQueryUpdate(newQuery);
183194
}
184195
}
185196

186197
// TODO: since this component is only rendered for parameter select, this is technically not needed
187-
const parameterSelectTypes = ['Node Property', 'Relationship Property', 'Free Text', 'Date Picker'];
198+
const parameterSelectTypes = ['Node Property', 'Relationship Property', 'Free Text', 'Custom Query', 'Date Picker'];
188199
const reportTypes = getReportTypes(extensions);
189200
const overridePropertyDisplayName =
190201
settings.overridePropertyDisplayName !== undefined ? settings.overridePropertyDisplayName : false;
@@ -219,7 +230,7 @@ const NeoCardSettingsContentPropertySelect = ({
219230
</MenuItem>
220231
))}
221232
</TextField>
222-
233+
<br />
223234
{settings.type == 'Free Text' || settings.type == 'Date Picker' ? (
224235
<NeoField
225236
label={'Name'}
@@ -234,6 +245,53 @@ const NeoCardSettingsContentPropertySelect = ({
234245
handleFreeTextNameSelectionUpdate(value);
235246
}}
236247
/>
248+
) : settings.type == 'Custom Query' ? (
249+
<>
250+
<div>
251+
<NeoField
252+
label={'Name'}
253+
key={'query'}
254+
value={settings?.entityType || ''}
255+
defaultValue={''}
256+
placeholder={'Enter a parameter name here...'}
257+
style={{ width: 350, marginLeft: '5px', marginTop: '0px' }}
258+
onChange={(value) => {
259+
setLabelInputText(value);
260+
handleNodeLabelSelectionUpdate(value);
261+
handleFreeTextNameSelectionUpdate(value);
262+
}}
263+
/>
264+
<br />
265+
<br />
266+
<div style={{ display: labelInputText ? 'inherit' : 'none' }}>
267+
<NeoCodeEditorComponent
268+
value={queryText}
269+
editable={true}
270+
language={reportTypes[type] && reportTypes[type].inputMode ? reportTypes[type].inputMode : 'cypher'}
271+
onChange={(value) => {
272+
debouncedQueryUpdate(value);
273+
setQueryText(value);
274+
}}
275+
placeholder={'Enter Cypher here...'}
276+
/>
277+
<p
278+
style={{
279+
color: 'grey',
280+
fontSize: 12,
281+
paddingLeft: '5px',
282+
borderBottom: '1px solid lightgrey',
283+
borderLeft: '1px solid lightgrey',
284+
borderRight: '1px solid lightgrey',
285+
marginTop: '0px',
286+
}}
287+
>
288+
{
289+
'Specify a query that takes a parameter $input (the user typed text) and return a number of rows with a field called `value` (the suggestions).'
290+
}
291+
</p>
292+
</div>
293+
</div>
294+
</>
237295
) : (
238296
<>
239297
<Autocomplete

src/chart/parameter/ParameterSelectionChart.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import DatePickerParameterSelectComponent from './component/DateParameterSelect'
44
import NodePropertyParameterSelectComponent from './component/NodePropertyParameterSelect';
55
import RelationshipPropertyParameterSelectComponent from './component/RelationshipPropertyParameterSelect';
66
import FreeTextParameterSelectComponent from './component/FreeTextParameterSelect';
7+
import QueryParameterSelectComponent from './component/QueryParameterSelect';
78

89
/**
910
* A special chart type to define global dashboard parameters that are injected as query parameters into each report.
@@ -28,7 +29,7 @@ export const NeoParameterSelectionChart = (props: ChartProps) => {
2829
const allParameters = props.parameters;
2930

3031
// in NeoDash 2.2.1 or earlier, there was no means to have a different display value in the selector. This condition handles that.
31-
const compatibilityMode = !query == undefined && !query.includes('as display');
32+
const compatibilityMode = !query?.toLowerCase().includes('as display') || false;
3233

3334
if (!query || query.trim().length == 0) {
3435
return <p style={{ margin: '15px' }}>No selection specified.</p>;
@@ -98,6 +99,22 @@ export const NeoParameterSelectionChart = (props: ChartProps) => {
9899
compatibilityMode={compatibilityMode}
99100
/>
100101
);
102+
} else if (type == 'Custom Query') {
103+
return (
104+
<QueryParameterSelectComponent
105+
parameterName={parameterName}
106+
parameterDisplayName={parameterName}
107+
parameterValue={parameterValue}
108+
parameterDisplayValue={parameterDisplayValue}
109+
setParameterValue={setParameterValue}
110+
setParameterDisplayValue={setParameterDisplayValue}
111+
query={query}
112+
queryCallback={queryCallback}
113+
settings={props.settings}
114+
allParameters={allParameters}
115+
compatibilityMode={compatibilityMode}
116+
/>
117+
);
101118
}
102119
return <div>Invalid Parameter Selector Type.</div>;
103120
};

src/chart/parameter/component/NodePropertyParameterSelect.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ const NodePropertyParameterSelectComponent = (props: ParameterSelectProps) => {
2323
props.settings && props.settings.clearParameterOnFieldClear ? props.settings.clearParameterOnFieldClear : false;
2424

2525
// index of the display value in the resulting extra records retrieved by the component when the user types. equals '1' for NeoDash 2.2.2 and later.
26-
const displayValueRowIndex = props.compatibilityMode ? 0 : 1;
26+
const displayValueRowIndex = props.compatibilityMode
27+
? 0
28+
: extraRecords[0]?.keys?.findIndex((e) => e.toLowerCase() == 'display') || 0;
29+
30+
const realValueRowIndex = props.compatibilityMode ? 0 : 1 - displayValueRowIndex;
2731

2832
return (
2933
<Autocomplete
@@ -57,8 +61,8 @@ const NodePropertyParameterSelectComponent = (props: ParameterSelectProps) => {
5761
}
5862

5963
let newValue = extraRecords.filter((r) => r._fields[displayValueRowIndex].toString() == newDisplayValue)[0]
60-
._fields[0];
61-
setInputDisplayText(newDisplayValue !== null ? `${newDisplayValue}` : '');
64+
._fields[realValueRowIndex];
65+
setInputDisplayText(newDisplayValue);
6266
if (newValue && newValue.low) {
6367
newValue = newValue.low;
6468
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from 'react';
2+
import NodePropertyParameterSelectComponent from './NodePropertyParameterSelect';
3+
import { ParameterSelectProps } from './ParameterSelect';
4+
5+
const QueryParameterSelectComponent = (props: ParameterSelectProps) => {
6+
return (
7+
<NodePropertyParameterSelectComponent
8+
parameterName={props.parameterName}
9+
parameterDisplayName={props.parameterDisplayName}
10+
parameterValue={props.parameterValue}
11+
parameterDisplayValue={props.parameterDisplayValue}
12+
setParameterValue={props.setParameterValue}
13+
setParameterDisplayValue={props.setParameterDisplayValue}
14+
query={props.query}
15+
queryCallback={props.queryCallback}
16+
settings={props.settings}
17+
allParameters={props.allParameters}
18+
compatibilityMode={props.compatibilityMode}
19+
/>
20+
);
21+
};
22+
23+
export default QueryParameterSelectComponent;

src/report/Report.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ export const NeoReport = ({
150150
}
151151
}, [lastRunTimestamp]);
152152

153-
// Define query callback to allow reports to get extra data on interactions./
153+
// Define query callback to allow reports to get extra data on interactions.
154154
// Can retrieve a maximum of 1000 rows at a time.
155155
const queryCallback = useCallback(
156156
(query, parameters, setRecords) => {

0 commit comments

Comments
 (0)