diff --git a/src/card/Card.tsx b/src/card/Card.tsx
index 2a7753c6e..ef10d4782 100644
--- a/src/card/Card.tsx
+++ b/src/card/Card.tsx
@@ -39,6 +39,7 @@ const NeoCard = ({
extensions, // A set of enabled extensions.
globalParameters, // Query parameters that are globally set for the entire dashboard.
dashboardSettings, // Dictionary of settings for the entire dashboard.
+ enableExecuteButtonForIds, // Reports will have save buttons to execute cypher queries
onRemovePressed, // action to take when the card is removed. (passed from parent)
onClonePressed, // action to take when user presses the clone button
onReportHelpButtonPressed, // action to take when someone clicks the 'help' button in the report settings.
@@ -131,6 +132,7 @@ const NeoCard = ({
settingsOpen={settingsOpen}
editable={editable}
dashboardSettings={dashboardSettings}
+ enableExecuteButtonForIds={enableExecuteButtonForIds}
extensions={extensions}
settings={report.settings ? report.settings : {}}
updateReportSetting={(name, value) => onReportSettingUpdate(id, name, value)}
diff --git a/src/card/view/CardView.tsx b/src/card/view/CardView.tsx
index 452a24aae..cca5b626a 100644
--- a/src/card/view/CardView.tsx
+++ b/src/card/view/CardView.tsx
@@ -2,16 +2,18 @@ import React, { useEffect, useState } from 'react';
import { ReportItemContainer } from '../CardStyle';
import NeoCardViewHeader from './CardViewHeader';
import NeoCardViewFooter from './CardViewFooter';
-import { CardContent } from '@mui/material';
+import { CardContent, Fab, Stack } from '@mui/material';
import NeoCodeEditorComponent from '../../component/editor/CodeEditorComponent';
import { CARD_FOOTER_HEIGHT, CARD_HEADER_HEIGHT } from '../../config/CardConfig';
import { getReportTypes } from '../../extensions/ExtensionUtils';
import NeoCodeViewerComponent from '../../component/editor/CodeViewerComponent';
import { NeoReportWrapper } from '../../report/ReportWrapper';
import { identifyStyleRuleParameters } from '../../extensions/styling/StyleRuleEvaluator';
-import { IconButton } from '@neo4j-ndl/react';
-import { PlayCircleIconSolid } from '@neo4j-ndl/react/icons';
+import { IconButton, Typography } from '@neo4j-ndl/react';
+import { PlayCircleIconSolid, PlayIconOutline } from '@neo4j-ndl/react/icons';
import { extensionEnabled } from '../../utils/ReportUtils';
+import { PlayArrowOutlined } from '@mui/icons-material';
+import { checkParametersNameInGlobalParameter, extractAllParameterNames } from '../../utils/parameterUtils';
import { objMerge } from '../../utils/ObjectManipulation';
import { REPORT_TYPES } from '../../config/ReportConfig';
@@ -31,6 +33,7 @@ const NeoCardView = ({
type,
selection,
dashboardSettings,
+ enableExecuteButtonForIds,
settings,
updateReportSetting,
createNotification,
@@ -150,6 +153,11 @@ const NeoCardView = ({
if (!settingsOpen) {
setLastRunTimestamp(Date.now());
}
+
+ // Resets the report with save button
+ if (enableExecuteButtonForIds.map((report) => report.id).includes(id)) {
+ setActive(false);
+ }
}, [JSON.stringify(localParameters)]);
useEffect(() => {
@@ -180,6 +188,68 @@ const NeoCardView = ({
: `${reportHeight}px`,
overflow: 'auto',
};
+
+ const isParametersDefined = (cypherQuery: string) => {
+ const parameterNames = extractAllParameterNames(cypherQuery);
+ if (globalParameters) {
+ return checkParametersNameInGlobalParameter(parameterNames, globalParameters);
+ }
+ return false;
+ };
+
+ const executeButton = (
+
+
+ {
+ setActive(true);
+ }}
+ size='large'
+ style={{
+ color: '#ffffff',
+ backgroundColor: 'green',
+ }}
+ >
+
+
+
+ {settings.executeButtonName ?? 'Execute'}
+
+
+
+ );
+
+ const cypherQueryEditor = (
+ <>
+ {
+ setActive(true);
+ }}
+ clean
+ size='small'
+ >
+
+
+ {}}
+ placeholder={'No query specified...'}
+ />
+ >
+ );
+
const reportContent = (
{active ? (
@@ -206,33 +276,10 @@ const NeoCardView = ({
queryTimeLimit={dashboardSettings.queryTimeLimit ? dashboardSettings.queryTimeLimit : 20}
setFields={onFieldsUpdate}
/>
+ ) : settings.hideQueryEditorInAutoRunOnMode ? (
+ executeButton
) : (
- <>
- {
- setActive(true);
- }}
- clean
- >
-
-
- {}}
- placeholder={'No query specified...'}
- />
- >
+ cypherQueryEditor
)}
);
diff --git a/src/config/ReportConfig.tsx b/src/config/ReportConfig.tsx
index 97b6bc913..a9e5ba524 100644
--- a/src/config/ReportConfig.tsx
+++ b/src/config/ReportConfig.tsx
@@ -25,6 +25,23 @@ export const RUN_QUERY_DELAY_MS = 300;
// The default number of rows to process in a visualization.
export const DEFAULT_ROW_LIMIT = 100;
+const hideQueryEditorInAutoRunOnMode = {
+ hideQueryEditorInAutoRunOnMode: {
+ label: 'Hide query editor on auto run on mode',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+};
+
+const executeButtonName = {
+ executeButtonName: {
+ label: 'Execute Button Name',
+ type: SELECTION_TYPES.TEXT,
+ default: 'Execute',
+ },
+};
+
// A dictionary of available reports (visualizations).
const _REPORT_TYPES = {
table: {
@@ -69,6 +86,36 @@ const _REPORT_TYPES = {
values: [true, false],
default: false,
},
+ refreshButtonEnabled: {
+ label: 'Refreshable',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ fullscreenEnabled: {
+ label: 'Fullscreen enabled',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ downloadImageEnabled: {
+ label: 'Download Image enabled',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ autorun: {
+ label: 'Auto-run query',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: true,
+ },
+ ...hideQueryEditorInAutoRunOnMode,
+ refreshRate: {
+ label: 'Refresh rate (seconds)',
+ type: SELECTION_TYPES.NUMBER,
+ default: '0 (No refresh)',
+ },
},
},
graph: {
@@ -242,6 +289,13 @@ const _REPORT_TYPES = {
values: [true, false],
default: true,
},
+ autorun: {
+ label: 'Auto-run query',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: true,
+ },
+ ...hideQueryEditorInAutoRunOnMode,
iconStyle: {
label: 'Node Label images',
type: SELECTION_TYPES.TEXT,
@@ -254,6 +308,26 @@ const _REPORT_TYPES = {
values: [true, false],
default: false,
},
+ description: {
+ label: 'Report Description',
+ type: SELECTION_TYPES.MULTILINE_TEXT,
+ default: 'Enter markdown here...',
+ },
+ customTablePropertiesOfModal: {
+ label: 'Customized Ordering and Hide Features Of Attributes In Detailed Modal',
+ type: SELECTION_TYPES.DICTIONARY,
+ },
+ minimizable: {
+ label: 'Minimize Button',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ pageIdAndParameterName: {
+ label: '::',
+ type: SELECTION_TYPES.TEXT,
+ },
+ ...executeButtonName,
},
},
bar: {
@@ -438,11 +512,24 @@ const _REPORT_TYPES = {
values: ['Horizontal', 'Vertical'],
default: 'Vertical',
},
- padding: {
- label: 'Padding',
+ ...hideQueryEditorInAutoRunOnMode,
+ refreshRate: {
+ label: 'Refresh rate (seconds)',
type: SELECTION_TYPES.NUMBER,
- default: 0.25,
+ default: '0 (No refresh)',
+ },
+ description: {
+ label: 'Report Description',
+ type: SELECTION_TYPES.MULTILINE_TEXT,
+ default: 'Enter markdown here...',
},
+ minimizable: {
+ label: 'Minimize Button',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ ...executeButtonName,
},
},
pie: {
@@ -573,6 +660,48 @@ const _REPORT_TYPES = {
type: SELECTION_TYPES.NUMBER,
default: 50,
},
+ refreshButtonEnabled: {
+ label: 'Refreshable',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ fullscreenEnabled: {
+ label: 'Fullscreen enabled',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ downloadImageEnabled: {
+ label: 'Download Image enabled',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ autorun: {
+ label: 'Auto-run query',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: true,
+ },
+ ...hideQueryEditorInAutoRunOnMode,
+ refreshRate: {
+ label: 'Refresh rate (seconds)',
+ type: SELECTION_TYPES.NUMBER,
+ default: '0 (No refresh)',
+ },
+ description: {
+ label: 'Report Description',
+ type: SELECTION_TYPES.MULTILINE_TEXT,
+ default: 'Enter markdown here...',
+ },
+ minimizable: {
+ label: 'Minimize Button',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ ...executeButtonName,
},
},
line: {
@@ -721,6 +850,48 @@ const _REPORT_TYPES = {
values: [true, false],
default: false,
},
+ refreshButtonEnabled: {
+ label: 'Refreshable',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ fullscreenEnabled: {
+ label: 'Fullscreen enabled',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ downloadImageEnabled: {
+ label: 'Download Image enabled',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ autorun: {
+ label: 'Auto-run query',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: true,
+ },
+ ...hideQueryEditorInAutoRunOnMode,
+ refreshRate: {
+ label: 'Refresh rate (seconds)',
+ type: SELECTION_TYPES.NUMBER,
+ default: '0 (No refresh)',
+ },
+ description: {
+ label: 'Report Description',
+ type: SELECTION_TYPES.MULTILINE_TEXT,
+ default: 'Enter markdown here...',
+ },
+ minimizable: {
+ label: 'Minimize Button',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ ...executeButtonName,
},
},
// TODO - move to advanced visualization.
@@ -867,6 +1038,46 @@ const _REPORT_TYPES = {
// values: [true, false],
// default: false,
// },
+ // refreshButtonEnabled: {
+ // label: 'Refreshable',
+ // type: SELECTION_TYPES.LIST,
+ // values: [true, false],
+ // default: false,
+ // },
+ // fullscreenEnabled: {
+ // label: 'Fullscreen enabled',
+ // type: SELECTION_TYPES.LIST,
+ // values: [true, false],
+ // default: false,
+ // },
+ // downloadImageEnabled: {
+ // label: 'Download Image enabled',
+ // type: SELECTION_TYPES.LIST,
+ // values: [true, false],
+ // default: false,
+ // },
+ // autorun: {
+ // label: 'Auto-run query',
+ // type: SELECTION_TYPES.LIST,
+ // values: [true, false],
+ // default: true,
+ // },
+ // ...hideQueryEditorInAutoRunOnMode,
+ // refreshRate: {
+ // label: 'Refresh rate (seconds)',
+ // type: SELECTION_TYPES.NUMBER,
+ // default: '0 (No refresh)',
+ // },
+ // description: {
+ // label: 'Report Description',
+ // type: SELECTION_TYPES.MULTILINE_TEXT,
+ // default: 'Enter markdown here...',
+ // },
+ // executeButtonName: {
+ // label: 'Execute Button Name',
+ // type: SELECTION_TYPES.TEXT,
+ // default: 'Execute',
+ // },
// },
// },
map: {
@@ -965,6 +1176,30 @@ const _REPORT_TYPES = {
values: [true, false],
default: false,
},
+ autorun: {
+ label: 'Auto-run query',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: true,
+ },
+ hideQueryEditorInAutoRunOnMode: {
+ label: 'Hide query editor on auto run on mode',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ description: {
+ label: 'Report Description',
+ type: SELECTION_TYPES.MULTILINE_TEXT,
+ default: 'Enter markdown here...',
+ },
+ minimizable: {
+ label: 'Minimize Button',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ ...executeButtonName,
},
},
value: {
@@ -1007,6 +1242,48 @@ const _REPORT_TYPES = {
values: ['bottom', 'middle', 'top'],
default: 'top',
},
+ refreshButtonEnabled: {
+ label: 'Refreshable',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ fullscreenEnabled: {
+ label: 'Fullscreen enabled',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ downloadImageEnabled: {
+ label: 'Download Image enabled',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ autorun: {
+ label: 'Auto-run query',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: true,
+ },
+ ...hideQueryEditorInAutoRunOnMode,
+ refreshRate: {
+ label: 'Refresh rate (seconds)',
+ type: SELECTION_TYPES.NUMBER,
+ default: '0 (No refresh)',
+ },
+ description: {
+ label: 'Report Description',
+ type: SELECTION_TYPES.MULTILINE_TEXT,
+ default: 'Enter markdown here...',
+ },
+ minimizable: {
+ label: 'Minimize Button',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ ...executeButtonName,
},
},
json: {
@@ -1022,6 +1299,48 @@ const _REPORT_TYPES = {
values: ['json', 'yml'],
default: 'json',
},
+ refreshButtonEnabled: {
+ label: 'Refreshable',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ fullscreenEnabled: {
+ label: 'Fullscreen enabled',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ downloadImageEnabled: {
+ label: 'Download Image enabled',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ autorun: {
+ label: 'Auto-run query',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: true,
+ },
+ ...hideQueryEditorInAutoRunOnMode,
+ refreshRate: {
+ label: 'Refresh rate (seconds)',
+ type: SELECTION_TYPES.NUMBER,
+ default: '0 (No refresh)',
+ },
+ description: {
+ label: 'Report Description',
+ type: SELECTION_TYPES.MULTILINE_TEXT,
+ default: 'Enter markdown here...',
+ },
+ minimizable: {
+ label: 'Minimize Button',
+ type: SELECTION_TYPES.LIST,
+ values: [true, false],
+ default: false,
+ },
+ ...executeButtonName,
},
},
select: {
diff --git a/src/page/Page.tsx b/src/page/Page.tsx
index ec487fe48..471376c6e 100644
--- a/src/page/Page.tsx
+++ b/src/page/Page.tsx
@@ -47,6 +47,9 @@ export const NeoPage = ({
const [lastElement, setLastElement] = React.useState();
const [animated, setAnimated] = React.useState(false); // To turn off animations when cards are dragged around.
+ // If hideQueryEditorInAutoRunOnMode is true and autorun option is false
+ const enableExecuteButtonForIds = reports.filter((report: any) => report.settings?.hideQueryEditorInAutoRunOnMode);
+
const availableHandles = () => {
if (dashboardSettings.resizing && dashboardSettings.resizing == 'all') {
return ['s', 'w', 'e', 'sw', 'se'];
@@ -197,6 +200,7 @@ export const NeoPage = ({
id={id}
key={getReportKey(pagenumber, id)}
dashboardSettings={dashboardSettings}
+ enableExecuteButtonForIds={enableExecuteButtonForIds}
onRemovePressed={onRemovePressed}
onClonePressed={(id) => {
const { x, y } = getAddCardButtonPosition();
diff --git a/src/utils/parameterUtils.ts b/src/utils/parameterUtils.ts
new file mode 100644
index 000000000..d2ce7b0a0
--- /dev/null
+++ b/src/utils/parameterUtils.ts
@@ -0,0 +1,22 @@
+export const extractAllParameterNames = (cypherQuery) => {
+ // A regular expression pattern to match parameter names following '$'
+ const pattern = /\$([A-Za-z_]\w*)/g;
+
+ const parameterNames: string[] = [];
+ let match: any;
+
+ while ((match = pattern.exec(cypherQuery)) !== null) {
+ parameterNames.push(match[1]);
+ }
+
+ return parameterNames;
+}
+
+export const checkParametersNameInGlobalParameter = (parameterNames: string[], globalParameterNames: any,) => {
+ for (const key of parameterNames) {
+ if (!globalParameterNames[key] || globalParameterNames[key].trim() === '') {
+ return true;
+ }
+ }
+ return false;
+}
\ No newline at end of file