2021-04-03 11:14:15 +00:00
|
|
|
import React from 'react';
|
2021-04-30 08:10:57 +00:00
|
|
|
import { dataqueryService } from '@/_services';
|
2021-12-30 11:57:02 +00:00
|
|
|
import { toast } from 'react-hot-toast';
|
2021-04-26 07:13:20 +00:00
|
|
|
import ReactTooltip from 'react-tooltip';
|
2021-04-30 16:15:42 +00:00
|
|
|
import { allSources } from './QueryEditors';
|
|
|
|
|
import { Transformation } from './Transformation';
|
2021-06-17 05:56:53 +00:00
|
|
|
import { previewQuery } from '@/_helpers/appUtils';
|
2021-09-06 14:40:51 +00:00
|
|
|
import { EventManager } from '../Inspector/EventManager';
|
2021-11-15 06:18:09 +00:00
|
|
|
import { CodeHinter } from '../CodeBuilder/CodeHinter';
|
2021-12-08 08:25:22 +00:00
|
|
|
import { DataSourceTypes } from '../DataSourceManager/SourceComponents';
|
2022-03-31 10:30:09 +00:00
|
|
|
import RunjsIcon from '../Icons/runjs.svg';
|
|
|
|
|
import Preview from './Preview';
|
2022-03-18 04:57:35 +00:00
|
|
|
import DataSourceLister from './DataSourceLister';
|
|
|
|
|
import { allSvgs } from '@tooljet/plugins/client';
|
2022-02-02 16:59:57 +00:00
|
|
|
|
2021-04-30 06:31:32 +00:00
|
|
|
const queryNameRegex = new RegExp('^[A-Za-z0-9_-]*$');
|
2021-04-29 16:39:09 +00:00
|
|
|
|
2021-12-08 07:33:08 +00:00
|
|
|
const staticDataSources = [
|
|
|
|
|
{ kind: 'restapi', id: 'null', name: 'REST API' },
|
2021-12-08 08:25:22 +00:00
|
|
|
{ kind: 'runjs', id: 'runjs', name: 'Run JavaScript code' },
|
2021-12-08 07:33:08 +00:00
|
|
|
];
|
2021-04-04 17:07:03 +00:00
|
|
|
|
2021-09-29 09:30:27 +00:00
|
|
|
let QueryManager = class QueryManager extends React.Component {
|
2021-04-30 06:31:32 +00:00
|
|
|
constructor(props) {
|
|
|
|
|
super(props);
|
|
|
|
|
|
2021-12-02 08:47:48 +00:00
|
|
|
this.state = {
|
|
|
|
|
options: {},
|
|
|
|
|
selectedQuery: null,
|
|
|
|
|
selectedDataSource: null,
|
2021-12-08 08:25:22 +00:00
|
|
|
dataSourceMeta: {},
|
2022-02-02 16:59:57 +00:00
|
|
|
dataQueries: [],
|
2022-03-08 09:27:28 +00:00
|
|
|
theme: {},
|
2022-03-18 04:57:35 +00:00
|
|
|
isSourceSelected: false,
|
2021-12-02 08:47:48 +00:00
|
|
|
};
|
2021-05-22 12:57:36 +00:00
|
|
|
|
|
|
|
|
this.previewPanelRef = React.createRef();
|
2021-04-30 06:31:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setStateFromProps = (props) => {
|
|
|
|
|
const selectedQuery = props.selectedQuery;
|
2021-06-17 05:56:53 +00:00
|
|
|
const dataSourceId = selectedQuery?.data_source_id;
|
|
|
|
|
const source = props.dataSources.find((datasource) => datasource.id === dataSourceId);
|
2021-12-08 07:33:08 +00:00
|
|
|
let dataSourceMeta = DataSourceTypes.find((source) => source.kind === selectedQuery?.kind);
|
2021-12-09 03:43:32 +00:00
|
|
|
const paneHeightChanged = this.state.queryPaneHeight !== props.queryPaneHeight;
|
2022-02-02 16:59:57 +00:00
|
|
|
const dataQueries = props.dataQueries?.length ? props.dataQueries : this.state.dataQueries;
|
2021-04-30 06:31:32 +00:00
|
|
|
this.setState(
|
|
|
|
|
{
|
|
|
|
|
appId: props.appId,
|
|
|
|
|
dataSources: props.dataSources,
|
2022-02-02 16:59:57 +00:00
|
|
|
dataQueries: dataQueries,
|
2021-04-30 06:31:32 +00:00
|
|
|
mode: props.mode,
|
|
|
|
|
currentTab: 1,
|
|
|
|
|
addingQuery: props.addingQuery,
|
|
|
|
|
editingQuery: props.editingQuery,
|
|
|
|
|
queryPaneHeight: props.queryPaneHeight,
|
2021-05-22 11:29:27 +00:00
|
|
|
currentState: props.currentState,
|
2021-06-17 05:56:53 +00:00
|
|
|
selectedSource: source,
|
2021-12-08 08:25:22 +00:00
|
|
|
dataSourceMeta,
|
2022-03-31 10:35:12 +00:00
|
|
|
isSourceSelected: paneHeightChanged ? this.state.isSourceSelected : props.isSourceSelected,
|
2021-12-09 03:43:32 +00:00
|
|
|
selectedDataSource: paneHeightChanged ? this.state.selectedDataSource : props.selectedDataSource,
|
2022-03-08 09:27:28 +00:00
|
|
|
theme: {
|
|
|
|
|
scheme: 'bright',
|
|
|
|
|
author: 'chris kempson (http://chriskempson.com)',
|
|
|
|
|
base00: props.darkMode ? '#272822' : '#000000',
|
|
|
|
|
base01: '#303030',
|
|
|
|
|
base02: '#505050',
|
|
|
|
|
base03: '#b0b0b0',
|
|
|
|
|
base04: '#d0d0d0',
|
|
|
|
|
base05: '#e0e0e0',
|
|
|
|
|
base06: '#f5f5f5',
|
|
|
|
|
base07: '#ffffff',
|
|
|
|
|
base08: '#fb0120',
|
|
|
|
|
base09: '#fc6d24',
|
|
|
|
|
base0A: '#fda331',
|
|
|
|
|
base0B: '#a1c659',
|
|
|
|
|
base0C: '#76c7b7',
|
|
|
|
|
base0D: '#6fb3d2',
|
|
|
|
|
base0E: '#d381c3',
|
|
|
|
|
base0F: '#be643c',
|
|
|
|
|
},
|
2021-04-30 06:31:32 +00:00
|
|
|
},
|
|
|
|
|
() => {
|
|
|
|
|
if (this.props.mode === 'edit') {
|
2021-05-02 09:27:26 +00:00
|
|
|
let source = props.dataSources.find((datasource) => datasource.id === selectedQuery.data_source_id);
|
2021-09-06 14:40:51 +00:00
|
|
|
if (selectedQuery.kind === 'restapi') {
|
|
|
|
|
if (!selectedQuery.data_source_id) {
|
2022-02-02 16:59:57 +00:00
|
|
|
source = { kind: 'restapi', id: 'null', name: 'REST API' };
|
2021-07-25 17:20:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
2021-12-08 07:33:08 +00:00
|
|
|
if (selectedQuery.kind === 'runjs') {
|
|
|
|
|
if (!selectedQuery.data_source_id) {
|
2022-02-02 16:59:57 +00:00
|
|
|
source = { kind: 'runjs', id: 'runjs', name: 'Run JavaScript code' };
|
2021-12-08 07:33:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-30 06:31:32 +00:00
|
|
|
this.setState({
|
2022-02-12 16:00:10 +00:00
|
|
|
options:
|
|
|
|
|
paneHeightChanged || this.state.selectedQuery?.id === selectedQuery?.id
|
|
|
|
|
? this.state.options
|
|
|
|
|
: selectedQuery.options,
|
2021-04-30 06:31:32 +00:00
|
|
|
selectedDataSource: source,
|
|
|
|
|
selectedQuery,
|
2021-06-17 05:56:53 +00:00
|
|
|
queryName: selectedQuery.name,
|
2021-04-30 06:31:32 +00:00
|
|
|
});
|
2021-04-29 16:39:09 +00:00
|
|
|
}
|
2021-04-30 06:31:32 +00:00
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
componentWillReceiveProps(nextProps) {
|
|
|
|
|
this.setStateFromProps(nextProps);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
|
this.setStateFromProps(this.props);
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-18 04:57:35 +00:00
|
|
|
handleBackButton = () => {
|
|
|
|
|
this.setState({
|
|
|
|
|
isSourceSelected: true,
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2021-04-30 06:31:32 +00:00
|
|
|
changeDataSource = (sourceId) => {
|
2021-04-30 08:10:57 +00:00
|
|
|
const source = [...this.state.dataSources, ...staticDataSources].find((datasource) => datasource.id === sourceId);
|
2021-06-17 05:56:53 +00:00
|
|
|
|
2021-12-08 07:33:08 +00:00
|
|
|
const isSchemaUnavailable = ['restapi', 'stripe', 'runjs'].includes(source.kind);
|
2021-11-22 08:22:32 +00:00
|
|
|
const schemaUnavailableOptions = {
|
|
|
|
|
restapi: {
|
|
|
|
|
method: 'get',
|
|
|
|
|
url: null,
|
|
|
|
|
url_params: [],
|
|
|
|
|
headers: [],
|
|
|
|
|
body: [],
|
|
|
|
|
},
|
|
|
|
|
stripe: {},
|
2021-12-08 07:33:08 +00:00
|
|
|
runjs: {},
|
2021-11-22 08:22:32 +00:00
|
|
|
};
|
|
|
|
|
|
2021-04-30 06:31:32 +00:00
|
|
|
this.setState({
|
|
|
|
|
selectedDataSource: source,
|
2021-06-17 05:56:53 +00:00
|
|
|
selectedSource: source,
|
|
|
|
|
queryName: this.computeQueryName(source.kind),
|
2022-01-27 10:31:39 +00:00
|
|
|
...(isSchemaUnavailable && {
|
|
|
|
|
options: schemaUnavailableOptions[source.kind],
|
|
|
|
|
}),
|
2021-04-30 06:31:32 +00:00
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
switchCurrentTab = (tab) => {
|
|
|
|
|
this.setState({
|
2021-06-17 05:56:53 +00:00
|
|
|
currentTab: tab,
|
2021-04-30 06:31:32 +00:00
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
validateQueryName = () => {
|
2021-06-17 05:56:53 +00:00
|
|
|
const { queryName, dataQueries, mode, selectedQuery } = this.state;
|
2021-04-30 06:31:32 +00:00
|
|
|
|
|
|
|
|
if (mode === 'create') {
|
|
|
|
|
return dataQueries.find((query) => query.name === queryName) === undefined && queryNameRegex.test(queryName);
|
2021-04-29 16:39:09 +00:00
|
|
|
}
|
2021-04-30 08:10:57 +00:00
|
|
|
const existingQuery = dataQueries.find((query) => query.name === queryName);
|
|
|
|
|
if (existingQuery) {
|
|
|
|
|
return existingQuery.id === selectedQuery.id && queryNameRegex.test(queryName);
|
|
|
|
|
}
|
|
|
|
|
return queryNameRegex.test(queryName);
|
2021-04-30 06:31:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
computeQueryName = (kind) => {
|
|
|
|
|
const { dataQueries } = this.state;
|
|
|
|
|
const currentQueriesForKind = dataQueries.filter((query) => query.kind === kind);
|
|
|
|
|
let found = false;
|
2021-04-30 12:43:29 +00:00
|
|
|
let newName = '';
|
2021-04-30 06:31:32 +00:00
|
|
|
let currentNumber = currentQueriesForKind.length + 1;
|
|
|
|
|
|
|
|
|
|
while (!found) {
|
2021-04-30 12:43:29 +00:00
|
|
|
newName = `${kind}${currentNumber}`;
|
|
|
|
|
if (dataQueries.find((query) => query.name === newName) === undefined) {
|
2021-04-30 06:31:32 +00:00
|
|
|
found = true;
|
|
|
|
|
}
|
2021-04-30 08:10:57 +00:00
|
|
|
currentNumber += 1;
|
2021-04-04 06:26:23 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-30 12:43:29 +00:00
|
|
|
return newName;
|
2021-04-30 06:31:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
createOrUpdateDataQuery = () => {
|
2021-06-17 05:56:53 +00:00
|
|
|
const { appId, options, selectedDataSource, mode, queryName } = this.state;
|
2022-01-04 08:04:12 +00:00
|
|
|
const appVersionId = this.props.editingVersionId;
|
2021-04-30 06:31:32 +00:00
|
|
|
const kind = selectedDataSource.kind;
|
2021-07-24 06:13:21 +00:00
|
|
|
const dataSourceId = selectedDataSource.id === 'null' ? null : selectedDataSource.id;
|
2021-04-30 06:31:32 +00:00
|
|
|
|
|
|
|
|
const isQueryNameValid = this.validateQueryName();
|
|
|
|
|
if (!isQueryNameValid) {
|
2021-12-10 23:11:24 +00:00
|
|
|
toast.error('Invalid query name. Should be unique and only include letters, numbers and underscore.');
|
2021-04-30 06:31:32 +00:00
|
|
|
return;
|
2021-04-03 11:14:15 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-30 06:31:32 +00:00
|
|
|
if (mode === 'edit') {
|
|
|
|
|
this.setState({ isUpdating: true });
|
2021-06-17 05:56:53 +00:00
|
|
|
dataqueryService
|
|
|
|
|
.update(this.state.selectedQuery.id, queryName, options)
|
|
|
|
|
.then(() => {
|
2021-12-10 23:11:24 +00:00
|
|
|
toast.success('Query Updated');
|
2021-06-17 05:56:53 +00:00
|
|
|
this.setState({ isUpdating: false });
|
|
|
|
|
this.props.dataQueriesChanged();
|
|
|
|
|
})
|
|
|
|
|
.catch(({ error }) => {
|
|
|
|
|
this.setState({ isUpdating: false });
|
2021-12-10 23:11:24 +00:00
|
|
|
toast.error(error);
|
2021-06-17 05:56:53 +00:00
|
|
|
});
|
2021-04-30 06:31:32 +00:00
|
|
|
} else {
|
|
|
|
|
this.setState({ isCreating: true });
|
2021-06-17 05:56:53 +00:00
|
|
|
dataqueryService
|
2022-01-04 08:04:12 +00:00
|
|
|
.create(appId, appVersionId, queryName, kind, options, dataSourceId)
|
2021-06-17 05:56:53 +00:00
|
|
|
.then(() => {
|
2021-12-10 23:11:24 +00:00
|
|
|
toast.success('Query Added');
|
2021-06-17 05:56:53 +00:00
|
|
|
this.setState({ isCreating: false });
|
|
|
|
|
this.props.dataQueriesChanged();
|
|
|
|
|
})
|
|
|
|
|
.catch(({ error }) => {
|
|
|
|
|
this.setState({ isCreating: false });
|
2021-12-10 23:11:24 +00:00
|
|
|
toast.error(error);
|
2021-06-17 05:56:53 +00:00
|
|
|
});
|
2021-04-03 11:14:15 +00:00
|
|
|
}
|
2021-04-30 06:31:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
optionchanged = (option, value) => {
|
|
|
|
|
this.setState({ options: { ...this.state.options, [option]: value } });
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
optionsChanged = (newOptions) => {
|
|
|
|
|
this.setState({ options: newOptions });
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
toggleOption = (option) => {
|
|
|
|
|
const currentValue = this.state.options[option] ? this.state.options[option] : false;
|
|
|
|
|
this.optionchanged(option, !currentValue);
|
|
|
|
|
};
|
|
|
|
|
|
2021-09-06 14:40:51 +00:00
|
|
|
// Here we have mocked data query in format of a component to be usable by event manager
|
|
|
|
|
// TODO: Refactor EventManager to be generic
|
|
|
|
|
mockDataQueryAsComponent = () => {
|
|
|
|
|
const dataQueryEvents = this.state.options?.events || [];
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
component: { component: { definition: { events: dataQueryEvents } } },
|
|
|
|
|
componentMeta: {
|
|
|
|
|
events: {
|
|
|
|
|
onDataQuerySuccess: { displayName: 'Query Success' },
|
|
|
|
|
onDataQueryFailure: { displayName: 'Query Failure' },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
eventsChanged = (events) => {
|
|
|
|
|
this.optionchanged('events', events);
|
|
|
|
|
};
|
|
|
|
|
|
2021-04-30 06:31:32 +00:00
|
|
|
render() {
|
|
|
|
|
const {
|
|
|
|
|
dataSources,
|
|
|
|
|
selectedDataSource,
|
|
|
|
|
mode,
|
2021-05-22 11:50:55 +00:00
|
|
|
options,
|
2021-04-30 06:31:32 +00:00
|
|
|
currentTab,
|
|
|
|
|
isUpdating,
|
|
|
|
|
isCreating,
|
|
|
|
|
addingQuery,
|
|
|
|
|
editingQuery,
|
|
|
|
|
selectedQuery,
|
|
|
|
|
currentState,
|
2021-05-22 11:29:27 +00:00
|
|
|
queryName,
|
|
|
|
|
previewLoading,
|
2021-06-17 05:56:53 +00:00
|
|
|
queryPreviewData,
|
2021-12-08 08:25:22 +00:00
|
|
|
dataSourceMeta,
|
2021-04-30 06:31:32 +00:00
|
|
|
} = this.state;
|
|
|
|
|
|
|
|
|
|
let ElementToRender = '';
|
|
|
|
|
|
|
|
|
|
if (selectedDataSource) {
|
|
|
|
|
const sourcecomponentName = selectedDataSource.kind.charAt(0).toUpperCase() + selectedDataSource.kind.slice(1);
|
|
|
|
|
ElementToRender = allSources[sourcecomponentName];
|
2021-04-04 17:07:03 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-30 06:31:32 +00:00
|
|
|
let buttonText = mode === 'edit' ? 'Save' : 'Create';
|
|
|
|
|
const buttonDisabled = isUpdating || isCreating;
|
2021-09-06 14:40:51 +00:00
|
|
|
const mockDataQueryComponent = this.mockDataQueryAsComponent();
|
2022-03-18 04:57:35 +00:00
|
|
|
const Icon = allSvgs[this?.state?.selectedDataSource?.kind];
|
2022-02-01 03:12:57 +00:00
|
|
|
|
2021-04-30 06:31:32 +00:00
|
|
|
return (
|
|
|
|
|
<div className="query-manager" key={selectedQuery ? selectedQuery.id : ''}>
|
|
|
|
|
<ReactTooltip type="dark" effect="solid" delayShow={250} />
|
|
|
|
|
<div className="row header">
|
|
|
|
|
<div className="col">
|
2022-03-15 03:04:32 +00:00
|
|
|
{(addingQuery || editingQuery) && selectedDataSource && (
|
2021-04-30 06:31:32 +00:00
|
|
|
<div className="nav-header">
|
2021-05-22 07:29:44 +00:00
|
|
|
<ul className="nav nav-tabs query-manager-header" data-bs-toggle="tabs">
|
2021-04-30 06:31:32 +00:00
|
|
|
<li className="nav-item">
|
|
|
|
|
<a
|
|
|
|
|
onClick={() => this.switchCurrentTab(1)}
|
|
|
|
|
className={currentTab === 1 ? 'nav-link active' : 'nav-link'}
|
|
|
|
|
>
|
|
|
|
|
General
|
|
|
|
|
</a>
|
|
|
|
|
</li>
|
|
|
|
|
<li className="nav-item">
|
|
|
|
|
<a
|
|
|
|
|
onClick={() => this.switchCurrentTab(2)}
|
|
|
|
|
className={currentTab === 2 ? 'nav-link active' : 'nav-link'}
|
|
|
|
|
>
|
|
|
|
|
Advanced
|
|
|
|
|
</a>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
2021-06-17 05:56:53 +00:00
|
|
|
{(addingQuery || editingQuery) && selectedDataSource && (
|
2022-02-02 16:59:57 +00:00
|
|
|
<div className="col-2 query-name-field">
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
onChange={(e) => this.setState({ queryName: e.target.value })}
|
|
|
|
|
className="form-control-plaintext form-control-plaintext-sm mt-1"
|
|
|
|
|
value={queryName}
|
|
|
|
|
autoFocus={false}
|
|
|
|
|
/>
|
2021-04-30 06:31:32 +00:00
|
|
|
</div>
|
|
|
|
|
)}
|
2021-12-09 03:43:32 +00:00
|
|
|
<div className="col-auto px-1 m-auto">
|
2022-03-18 04:57:35 +00:00
|
|
|
{selectedDataSource && (addingQuery || editingQuery) && (
|
2022-02-02 16:59:57 +00:00
|
|
|
<button
|
2021-06-17 05:56:53 +00:00
|
|
|
onClick={() => {
|
2021-09-06 14:40:51 +00:00
|
|
|
const _options = { ...options };
|
|
|
|
|
|
2021-06-17 05:56:53 +00:00
|
|
|
const query = {
|
2021-09-06 14:40:51 +00:00
|
|
|
data_source_id: selectedDataSource.id === 'null' ? null : selectedDataSource.id,
|
2021-08-30 11:25:27 +00:00
|
|
|
options: _options,
|
2021-06-17 05:56:53 +00:00
|
|
|
kind: selectedDataSource.kind,
|
|
|
|
|
};
|
|
|
|
|
previewQuery(this, query)
|
|
|
|
|
.then(() => {
|
|
|
|
|
this.previewPanelRef.current.scrollIntoView();
|
|
|
|
|
})
|
|
|
|
|
.catch(({ error, data }) => {
|
2021-09-21 13:48:28 +00:00
|
|
|
console.log(error, data);
|
2021-05-22 12:57:36 +00:00
|
|
|
});
|
|
|
|
|
}}
|
2022-02-02 16:59:57 +00:00
|
|
|
className={`btn button-family-secondary m-1 float-right1 ${previewLoading ? 'button-loading' : ''} ${
|
|
|
|
|
this.props.darkMode ? 'dark' : ''
|
2022-02-22 04:54:03 +00:00
|
|
|
} ${this.state.selectedDataSource ? '' : 'disabled'}`}
|
2022-02-02 16:59:57 +00:00
|
|
|
style={{ width: '72px', height: '28px' }}
|
2021-05-22 11:29:27 +00:00
|
|
|
>
|
|
|
|
|
Preview
|
2022-02-02 16:59:57 +00:00
|
|
|
</button>
|
2021-05-22 11:29:27 +00:00
|
|
|
)}
|
2022-03-18 04:57:35 +00:00
|
|
|
{selectedDataSource && (addingQuery || editingQuery) && (
|
2021-04-30 06:31:32 +00:00
|
|
|
<button
|
|
|
|
|
onClick={this.createOrUpdateDataQuery}
|
|
|
|
|
disabled={buttonDisabled}
|
2022-02-22 04:54:03 +00:00
|
|
|
className={`btn btn-primary m-1 float-right ${isUpdating || isCreating ? 'btn-loading' : ''} ${
|
|
|
|
|
this.state.selectedDataSource ? '' : 'disabled'
|
|
|
|
|
}`}
|
2022-02-02 16:59:57 +00:00
|
|
|
style={{ width: '72px', height: '28px' }}
|
2021-04-30 06:31:32 +00:00
|
|
|
>
|
|
|
|
|
{buttonText}
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
2021-12-20 03:54:11 +00:00
|
|
|
<span onClick={this.props.toggleQueryEditor} className="cursor-pointer m-3" data-tip="Hide query editor">
|
|
|
|
|
<svg width="18" height="10" viewBox="0 0 18 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
|
|
|
<path d="M1 1L9 9L17 1" stroke="#61656F" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
|
|
|
|
</svg>
|
|
|
|
|
</span>
|
2021-04-30 06:31:32 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{(addingQuery || editingQuery) && (
|
2021-05-13 16:38:13 +00:00
|
|
|
<div className="py-2">
|
2021-04-30 06:31:32 +00:00
|
|
|
{currentTab === 1 && (
|
2022-02-02 16:59:57 +00:00
|
|
|
<div className="row row-deck px-2 mt-0 query-details">
|
2021-04-30 06:31:32 +00:00
|
|
|
{dataSources && mode === 'create' && (
|
2022-02-02 16:59:57 +00:00
|
|
|
<div className="datasource-picker mt-1 mb-2">
|
2022-03-18 04:57:35 +00:00
|
|
|
<div className="datasource-heading ">
|
|
|
|
|
{this.state.selectedDataSource !== null && (
|
|
|
|
|
<p
|
|
|
|
|
onClick={() => {
|
|
|
|
|
this.setState({
|
|
|
|
|
isSourceSelected: false,
|
|
|
|
|
selectedDataSource: null,
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
style={{ marginTop: '-7px' }}
|
|
|
|
|
>
|
|
|
|
|
<svg
|
|
|
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
|
|
|
className="icon icon-tabler icon-tabler-arrow-left"
|
|
|
|
|
width="44"
|
|
|
|
|
height="44"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
strokeWidth="1.5"
|
|
|
|
|
stroke="#9e9e9e"
|
|
|
|
|
fill="none"
|
|
|
|
|
strokeLinecap="round"
|
|
|
|
|
strokeLinejoin="round"
|
|
|
|
|
>
|
|
|
|
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
|
|
|
<line x1="5" y1="12" x2="19" y2="12" />
|
|
|
|
|
<line x1="5" y1="12" x2="11" y2="18" />
|
|
|
|
|
<line x1="5" y1="12" x2="11" y2="6" />
|
|
|
|
|
</svg>
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
2022-03-19 02:01:50 +00:00
|
|
|
{!this.state.isSourceSelected && <label className="form-label col-md-3">Select Datasource</label>}{' '}
|
2022-03-18 04:57:35 +00:00
|
|
|
{this?.state?.selectedDataSource?.kind && (
|
|
|
|
|
<div className="header-query-datasource-card-container">
|
|
|
|
|
<div
|
|
|
|
|
className="header-query-datasource-card badge "
|
|
|
|
|
style={{
|
|
|
|
|
background: this.props.darkMode ? '#2f3c4c' : 'white',
|
|
|
|
|
color: this.props.darkMode ? 'white' : '#3e525b',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{this.state?.selectedDataSource?.kind === 'runjs' ? (
|
|
|
|
|
<RunjsIcon style={{ height: 18, width: 18, marginTop: '-3px' }} />
|
|
|
|
|
) : (
|
|
|
|
|
Icon && <Icon style={{ height: 18, width: 18, marginLeft: 7 }} />
|
|
|
|
|
)}
|
|
|
|
|
<p className="header-query-datasource-name">
|
|
|
|
|
{' '}
|
|
|
|
|
{this.state?.selectedDataSource?.kind && this.state.selectedDataSource.kind}
|
|
|
|
|
</p>
|
|
|
|
|
</div>{' '}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
{!this.state.isSourceSelected && (
|
|
|
|
|
<DataSourceLister
|
|
|
|
|
dataSources={dataSources}
|
|
|
|
|
staticDataSources={staticDataSources}
|
|
|
|
|
changeDataSource={this.changeDataSource}
|
|
|
|
|
handleBackButton={this.handleBackButton}
|
|
|
|
|
darkMode={this.props.darkMode}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2021-04-30 06:31:32 +00:00
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{selectedDataSource && (
|
|
|
|
|
<div>
|
2021-06-17 05:56:53 +00:00
|
|
|
<ElementToRender
|
|
|
|
|
selectedDataSource={this.state.selectedSource}
|
|
|
|
|
options={this.state.options}
|
|
|
|
|
optionsChanged={this.optionsChanged}
|
2021-11-17 17:59:00 +00:00
|
|
|
optionchanged={this.optionchanged}
|
2021-06-17 05:56:53 +00:00
|
|
|
currentState={currentState}
|
2021-07-03 14:17:47 +00:00
|
|
|
darkMode={this.props.darkMode}
|
2021-08-30 11:25:27 +00:00
|
|
|
isEditMode={this.props.mode === 'edit'}
|
2021-12-10 03:09:23 +00:00
|
|
|
queryName={this.state.queryName}
|
2021-06-17 05:56:53 +00:00
|
|
|
/>
|
2021-12-08 08:25:22 +00:00
|
|
|
{!dataSourceMeta?.disableTransformations && (
|
2021-12-08 07:33:08 +00:00
|
|
|
<div>
|
2022-02-02 16:59:57 +00:00
|
|
|
<div className="mb-3 mt-4">
|
2021-12-08 07:33:08 +00:00
|
|
|
<Transformation
|
|
|
|
|
changeOption={this.optionchanged}
|
2022-01-04 04:21:59 +00:00
|
|
|
options={this.props.selectedQuery.options ?? {}}
|
2021-12-08 07:33:08 +00:00
|
|
|
currentState={currentState}
|
|
|
|
|
darkMode={this.props.darkMode}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2021-12-08 08:25:22 +00:00
|
|
|
)}
|
2022-03-31 10:30:09 +00:00
|
|
|
<Preview
|
|
|
|
|
previewPanelRef={this.previewPanelRef}
|
|
|
|
|
previewLoading={previewLoading}
|
|
|
|
|
queryPreviewData={queryPreviewData}
|
|
|
|
|
theme={this.state.theme}
|
|
|
|
|
darkMode={this.props.darkMode}
|
|
|
|
|
/>
|
2021-04-30 06:31:32 +00:00
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{currentTab === 2 && (
|
2021-05-13 16:38:13 +00:00
|
|
|
<div className="advanced-options-container m-2">
|
2022-01-12 08:26:48 +00:00
|
|
|
<div className="form-check form-switch">
|
2021-04-30 06:31:32 +00:00
|
|
|
<input
|
|
|
|
|
className="form-check-input"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
onClick={() => this.toggleOption('runOnPageLoad')}
|
|
|
|
|
checked={this.state.options.runOnPageLoad}
|
|
|
|
|
/>
|
|
|
|
|
<span className="form-check-label">Run this query on page load?</span>
|
2022-01-12 08:26:48 +00:00
|
|
|
</div>
|
|
|
|
|
<div className="form-check form-switch">
|
2021-04-30 06:31:32 +00:00
|
|
|
<input
|
|
|
|
|
className="form-check-input"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
onClick={() => this.toggleOption('requestConfirmation')}
|
|
|
|
|
checked={this.state.options.requestConfirmation}
|
|
|
|
|
/>
|
|
|
|
|
<span className="form-check-label">Request confirmation before running query?</span>
|
2022-01-12 08:26:48 +00:00
|
|
|
</div>
|
2021-04-30 06:31:32 +00:00
|
|
|
|
2022-01-12 08:26:48 +00:00
|
|
|
<div className="form-check form-switch">
|
2021-04-30 06:31:32 +00:00
|
|
|
<input
|
|
|
|
|
className="form-check-input"
|
|
|
|
|
type="checkbox"
|
|
|
|
|
onClick={() => this.toggleOption('showSuccessNotification')}
|
|
|
|
|
checked={this.state.options.showSuccessNotification}
|
|
|
|
|
/>
|
|
|
|
|
<span className="form-check-label">Show notification on success?</span>
|
2022-01-12 08:26:48 +00:00
|
|
|
</div>
|
2021-09-15 15:40:59 +00:00
|
|
|
{this.state.options.showSuccessNotification && (
|
2021-09-06 14:40:51 +00:00
|
|
|
<div>
|
|
|
|
|
<div className="row mt-3">
|
|
|
|
|
<div className="col-auto">
|
|
|
|
|
<label className="form-label p-2">Success Message</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="col">
|
2021-11-15 06:18:09 +00:00
|
|
|
<CodeHinter
|
|
|
|
|
currentState={this.props.currentState}
|
|
|
|
|
initialValue={this.state.options.successMessage}
|
|
|
|
|
height="36px"
|
2021-09-06 14:40:51 +00:00
|
|
|
className="form-control"
|
2021-11-15 06:18:09 +00:00
|
|
|
theme={'default'}
|
|
|
|
|
onChange={(value) => this.optionchanged('successMessage', value)}
|
|
|
|
|
placeholder="Query ran successfully"
|
2021-09-06 14:40:51 +00:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2021-04-30 06:31:32 +00:00
|
|
|
|
2021-09-06 14:40:51 +00:00
|
|
|
<div className="row mt-3">
|
|
|
|
|
<div className="col-auto">
|
|
|
|
|
<label className="form-label p-2">Notification duration (s)</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="col">
|
|
|
|
|
<input
|
|
|
|
|
type="number"
|
|
|
|
|
disabled={!this.state.options.showSuccessNotification}
|
|
|
|
|
onChange={(e) => this.optionchanged('notificationDuration', e.target.value)}
|
|
|
|
|
placeholder={5}
|
|
|
|
|
className="form-control"
|
|
|
|
|
value={this.state.options.notificationDuration}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2021-04-30 06:31:32 +00:00
|
|
|
</div>
|
2021-09-15 15:40:59 +00:00
|
|
|
)}
|
2021-09-06 14:40:51 +00:00
|
|
|
|
|
|
|
|
<div className="hr-text hr-text-left">Events</div>
|
|
|
|
|
|
|
|
|
|
<div className="query-manager-events">
|
|
|
|
|
<EventManager
|
|
|
|
|
eventsChanged={this.eventsChanged}
|
|
|
|
|
component={mockDataQueryComponent.component}
|
|
|
|
|
componentMeta={mockDataQueryComponent.componentMeta}
|
|
|
|
|
currentState={this.props.currentState}
|
|
|
|
|
dataQueries={this.props.dataQueries}
|
|
|
|
|
components={this.props.allComponents}
|
|
|
|
|
apps={this.props.apps}
|
|
|
|
|
popoverPlacement="top"
|
|
|
|
|
/>
|
2021-04-26 07:13:20 +00:00
|
|
|
</div>
|
2021-04-30 06:31:32 +00:00
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-09-29 09:30:27 +00:00
|
|
|
};
|
2021-04-03 11:14:15 +00:00
|
|
|
|
2021-09-28 17:03:40 +00:00
|
|
|
QueryManager = React.memo(QueryManager);
|
2021-04-04 06:46:53 +00:00
|
|
|
export { QueryManager };
|