2021-09-15 02:50:55 +00:00
|
|
|
import React from 'react';
|
2021-11-17 17:59:00 +00:00
|
|
|
import cx from 'classnames';
|
2021-09-15 02:50:55 +00:00
|
|
|
import Input from '@/_ui/Input';
|
2021-10-25 09:16:46 +00:00
|
|
|
import Textarea from '@/_ui/Textarea';
|
2021-09-15 02:50:55 +00:00
|
|
|
import Select from '@/_ui/Select';
|
|
|
|
|
import Headers from '@/_ui/HttpHeaders';
|
|
|
|
|
import OAuth from '@/_ui/OAuth';
|
|
|
|
|
import Toggle from '@/_ui/Toggle';
|
2021-11-17 17:59:00 +00:00
|
|
|
import { CodeHinter } from '@/Editor/CodeBuilder/CodeHinter';
|
2021-09-15 02:50:55 +00:00
|
|
|
|
2021-09-15 07:40:11 +00:00
|
|
|
import GoogleSheets from '@/_components/Googlesheets';
|
2021-09-15 02:50:55 +00:00
|
|
|
import Slack from '@/_components/Slack';
|
|
|
|
|
|
2021-11-17 17:59:00 +00:00
|
|
|
import { find, isEmpty } from 'lodash';
|
2021-09-15 02:50:55 +00:00
|
|
|
|
2021-11-17 17:59:00 +00:00
|
|
|
const DynamicForm = ({
|
|
|
|
|
schema,
|
|
|
|
|
optionchanged,
|
|
|
|
|
createDataSource,
|
|
|
|
|
options,
|
|
|
|
|
isSaving,
|
|
|
|
|
selectedDataSource,
|
|
|
|
|
currentState,
|
2021-11-22 08:22:32 +00:00
|
|
|
isEditMode,
|
|
|
|
|
optionsChanged,
|
2021-12-10 03:09:23 +00:00
|
|
|
queryName,
|
2021-11-17 17:59:00 +00:00
|
|
|
}) => {
|
2021-09-15 02:50:55 +00:00
|
|
|
// if(schema.properties) todo add empty check
|
2022-01-17 07:08:17 +00:00
|
|
|
React.useLayoutEffect(() => {
|
2021-11-22 08:22:32 +00:00
|
|
|
if (!isEditMode || isEmpty(options)) {
|
|
|
|
|
optionsChanged(schema?.defaults ?? {});
|
|
|
|
|
}
|
2021-12-02 06:55:40 +00:00
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
2021-11-22 08:22:32 +00:00
|
|
|
}, []);
|
|
|
|
|
|
2021-09-15 02:50:55 +00:00
|
|
|
const getElement = (type) => {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case 'password':
|
|
|
|
|
case 'text':
|
|
|
|
|
return Input;
|
2021-10-25 09:16:46 +00:00
|
|
|
case 'textarea':
|
|
|
|
|
return Textarea;
|
2021-09-15 02:50:55 +00:00
|
|
|
case 'dropdown':
|
|
|
|
|
return Select;
|
|
|
|
|
case 'toggle':
|
|
|
|
|
return Toggle;
|
|
|
|
|
case 'react-component-headers':
|
|
|
|
|
return Headers;
|
|
|
|
|
case 'react-component-oauth-authentication':
|
|
|
|
|
return OAuth;
|
|
|
|
|
case 'react-component-google-sheets':
|
|
|
|
|
return GoogleSheets;
|
|
|
|
|
case 'react-component-slack':
|
|
|
|
|
return Slack;
|
2021-11-17 17:59:00 +00:00
|
|
|
case 'codehinter':
|
|
|
|
|
return CodeHinter;
|
2021-09-15 02:50:55 +00:00
|
|
|
default:
|
|
|
|
|
return <div>Type is invalid</div>;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2021-11-17 17:59:00 +00:00
|
|
|
const getElementProps = ({
|
2022-01-17 07:08:17 +00:00
|
|
|
key,
|
|
|
|
|
list,
|
|
|
|
|
rows = 5,
|
2021-11-17 17:59:00 +00:00
|
|
|
helpText,
|
|
|
|
|
description,
|
|
|
|
|
type,
|
|
|
|
|
placeholder = '',
|
|
|
|
|
mode = 'sql',
|
|
|
|
|
lineNumbers = true,
|
|
|
|
|
initialValue,
|
2021-11-21 04:14:26 +00:00
|
|
|
height = 'auto',
|
2022-02-02 16:59:57 +00:00
|
|
|
width,
|
2021-12-02 06:55:40 +00:00
|
|
|
ignoreBraces = false,
|
2022-02-02 16:59:57 +00:00
|
|
|
className,
|
2021-11-17 17:59:00 +00:00
|
|
|
}) => {
|
|
|
|
|
const darkMode = localStorage.getItem('darkMode') === 'true';
|
2021-09-15 02:50:55 +00:00
|
|
|
switch (type) {
|
|
|
|
|
case 'password':
|
|
|
|
|
case 'text':
|
|
|
|
|
case 'textarea':
|
|
|
|
|
return {
|
|
|
|
|
type,
|
|
|
|
|
placeholder: description,
|
|
|
|
|
className: 'form-control',
|
2022-01-17 07:08:17 +00:00
|
|
|
value: options[key]?.value,
|
|
|
|
|
...(type === 'textarea' && { rows: rows }),
|
2021-09-15 02:50:55 +00:00
|
|
|
...(helpText && { helpText }),
|
2022-01-17 07:08:17 +00:00
|
|
|
onChange: (e) => optionchanged(key, e.target.value),
|
2021-09-15 02:50:55 +00:00
|
|
|
};
|
|
|
|
|
case 'toggle':
|
|
|
|
|
return {
|
2022-01-17 07:08:17 +00:00
|
|
|
defaultChecked: options[key],
|
|
|
|
|
checked: options[key]?.value,
|
|
|
|
|
onChange: (e) => optionchanged(key, e.target.checked),
|
2021-09-15 02:50:55 +00:00
|
|
|
};
|
|
|
|
|
case 'dropdown':
|
|
|
|
|
case 'dropdown-component-flip':
|
|
|
|
|
return {
|
2022-01-17 07:08:17 +00:00
|
|
|
options: list,
|
|
|
|
|
value: options[key]?.value || options[key],
|
|
|
|
|
onChange: (value) => optionchanged(key, value),
|
2021-09-15 02:50:55 +00:00
|
|
|
};
|
|
|
|
|
case 'react-component-headers':
|
|
|
|
|
return {
|
2022-01-17 07:08:17 +00:00
|
|
|
getter: key,
|
|
|
|
|
options: options[key]?.value,
|
2021-09-15 02:50:55 +00:00
|
|
|
optionchanged,
|
|
|
|
|
};
|
|
|
|
|
case 'react-component-oauth-authentication':
|
|
|
|
|
return {
|
2021-11-24 10:42:16 +00:00
|
|
|
grant_type: options.grant_type?.value,
|
|
|
|
|
auth_type: options.auth_type?.value,
|
|
|
|
|
add_token_to: options.add_token_to?.value,
|
|
|
|
|
header_prefix: options.header_prefix?.value,
|
|
|
|
|
access_token_url: options.access_token_url?.value,
|
|
|
|
|
client_id: options.client_id?.value,
|
|
|
|
|
client_secret: options.client_secret?.value,
|
|
|
|
|
client_auth: options.client_auth?.value,
|
|
|
|
|
scopes: options.scopes?.value,
|
|
|
|
|
auth_url: options.auth_url?.value,
|
|
|
|
|
custom_auth_params: options.custom_auth_params?.value,
|
2021-09-15 02:50:55 +00:00
|
|
|
optionchanged,
|
|
|
|
|
};
|
|
|
|
|
case 'react-component-google-sheets':
|
|
|
|
|
case 'react-component-slack':
|
|
|
|
|
return { optionchanged, createDataSource, options, isSaving, selectedDataSource };
|
2021-11-17 17:59:00 +00:00
|
|
|
case 'codehinter':
|
|
|
|
|
return {
|
|
|
|
|
currentState,
|
2022-01-17 07:08:17 +00:00
|
|
|
initialValue: options[key]
|
|
|
|
|
? typeof options[key] === 'string'
|
|
|
|
|
? options[key]
|
|
|
|
|
: JSON.stringify(options[key])
|
2021-11-17 17:59:00 +00:00
|
|
|
: initialValue,
|
|
|
|
|
mode,
|
|
|
|
|
lineNumbers,
|
2022-02-02 16:59:57 +00:00
|
|
|
className: className ? className : lineNumbers ? 'query-hinter' : 'codehinter-query-editor-input',
|
2022-01-17 07:08:17 +00:00
|
|
|
onChange: (value) => optionchanged(key, value),
|
2021-11-17 17:59:00 +00:00
|
|
|
theme: darkMode ? 'monokai' : lineNumbers ? 'duotone-light' : 'default',
|
|
|
|
|
placeholder,
|
2021-11-21 04:14:26 +00:00
|
|
|
height,
|
2022-02-02 16:59:57 +00:00
|
|
|
width,
|
2022-01-17 07:08:17 +00:00
|
|
|
componentName: queryName ? `${queryName}::${key ?? ''}` : null,
|
2021-12-02 06:55:40 +00:00
|
|
|
ignoreBraces,
|
2021-11-17 17:59:00 +00:00
|
|
|
};
|
2021-09-15 02:50:55 +00:00
|
|
|
default:
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getLayout = (obj) => {
|
2021-11-17 17:59:00 +00:00
|
|
|
if (isEmpty(obj)) return null;
|
|
|
|
|
const flipComponentDropdown = isFlipComponentDropdown(obj);
|
|
|
|
|
|
|
|
|
|
if (flipComponentDropdown) {
|
|
|
|
|
return flipComponentDropdown;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-15 02:50:55 +00:00
|
|
|
return (
|
|
|
|
|
<div className="row">
|
|
|
|
|
{Object.keys(obj).map((key) => {
|
2022-01-17 07:08:17 +00:00
|
|
|
const { label, type, encrypted, className } = obj[key];
|
2021-09-15 02:50:55 +00:00
|
|
|
|
|
|
|
|
const Element = getElement(type);
|
|
|
|
|
|
|
|
|
|
return (
|
2021-11-17 17:59:00 +00:00
|
|
|
<div className={cx('my-2', { 'col-md-12': !className, [className]: !!className })} key={key}>
|
2022-01-17 07:08:17 +00:00
|
|
|
{label && (
|
2021-09-15 02:50:55 +00:00
|
|
|
<label className="form-label">
|
2022-01-17 07:08:17 +00:00
|
|
|
{label}
|
|
|
|
|
{(type === 'password' || encrypted) && (
|
2021-09-15 02:50:55 +00:00
|
|
|
<small className="text-green mx-2">
|
|
|
|
|
<img
|
|
|
|
|
className="mx-2 encrypted-icon"
|
|
|
|
|
src="/assets/images/icons/padlock.svg"
|
|
|
|
|
width="12"
|
|
|
|
|
height="12"
|
|
|
|
|
/>
|
|
|
|
|
Encrypted
|
|
|
|
|
</small>
|
|
|
|
|
)}
|
|
|
|
|
</label>
|
|
|
|
|
)}
|
|
|
|
|
<Element {...getElementProps(obj[key])} />
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2021-11-17 17:59:00 +00:00
|
|
|
const isFlipComponentDropdown = (obj) => {
|
|
|
|
|
const flipComponentDropdown = find(obj, ['type', 'dropdown-component-flip']);
|
|
|
|
|
if (flipComponentDropdown) {
|
|
|
|
|
// options[key].value for datasource
|
|
|
|
|
// options[key] for dataquery
|
2022-01-17 07:08:17 +00:00
|
|
|
const selector = options[flipComponentDropdown.key]?.value || options[flipComponentDropdown.key];
|
2021-11-17 17:59:00 +00:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<div className="row">
|
|
|
|
|
<div className="col-md-12 my-2">
|
2022-01-17 07:08:17 +00:00
|
|
|
{flipComponentDropdown.label && <label className="form-label">{flipComponentDropdown.label}</label>}
|
2021-11-17 17:59:00 +00:00
|
|
|
<Select {...getElementProps(flipComponentDropdown)} />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
{getLayout(obj[selector])}
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const flipComponentDropdown = isFlipComponentDropdown(schema.properties);
|
2021-09-15 02:50:55 +00:00
|
|
|
|
|
|
|
|
if (flipComponentDropdown) {
|
2021-11-17 17:59:00 +00:00
|
|
|
return flipComponentDropdown;
|
2021-09-15 02:50:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return getLayout(schema.properties);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default DynamicForm;
|