mirror of
https://github.com/getredash/redash.git
synced 2026-05-09 03:03:08 -04:00
* Name help text for date range only * Autofocus on name input * Form acts on enter key * Fixed range check * Fixed startsWith
219 lines
6.7 KiB
JavaScript
219 lines
6.7 KiB
JavaScript
|
|
import { includes, startsWith, words, capitalize, clone, isNull } from 'lodash';
|
|
import React, { useState, useEffect } from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import Modal from 'antd/lib/modal';
|
|
import Form from 'antd/lib/form';
|
|
import Checkbox from 'antd/lib/checkbox';
|
|
import Button from 'antd/lib/button';
|
|
import Select from 'antd/lib/select';
|
|
import Input from 'antd/lib/input';
|
|
import Divider from 'antd/lib/divider';
|
|
import { wrap as wrapDialog, DialogPropType } from '@/components/DialogWrapper';
|
|
import { QuerySelector } from '@/components/QuerySelector';
|
|
import { Query } from '@/services/query';
|
|
|
|
const { Option } = Select;
|
|
const formItemProps = { labelCol: { span: 6 }, wrapperCol: { span: 16 } };
|
|
|
|
function getDefaultTitle(text) {
|
|
return capitalize(words(text).join(' ')); // humanize
|
|
}
|
|
|
|
function isTypeDate(type) {
|
|
return startsWith(type, 'date') && !isTypeDateRange(type);
|
|
}
|
|
|
|
function isTypeDateRange(type) {
|
|
return /-range/.test(type);
|
|
}
|
|
|
|
function NameInput({ name, type, onChange, existingNames, setValidation }) {
|
|
let helpText = '';
|
|
let validateStatus = '';
|
|
|
|
if (!name) {
|
|
helpText = 'Choose a keyword for this parameter';
|
|
setValidation(false);
|
|
} else if (includes(existingNames, name)) {
|
|
helpText = 'Parameter with this name already exists';
|
|
setValidation(false);
|
|
validateStatus = 'error';
|
|
} else {
|
|
if (isTypeDateRange(type)) {
|
|
helpText = (
|
|
<React.Fragment>
|
|
Appears in query as {' '}
|
|
<code style={{ display: 'inline-block', color: 'inherit' }}>
|
|
{`{{${name}.start}} {{${name}.end}}`}
|
|
</code>
|
|
</React.Fragment>
|
|
);
|
|
}
|
|
setValidation(true);
|
|
}
|
|
|
|
return (
|
|
<Form.Item
|
|
required
|
|
label="Keyword"
|
|
help={helpText}
|
|
validateStatus={validateStatus}
|
|
{...formItemProps}
|
|
>
|
|
<Input onChange={e => onChange(e.target.value)} autoFocus />
|
|
</Form.Item>
|
|
);
|
|
}
|
|
|
|
NameInput.propTypes = {
|
|
name: PropTypes.string.isRequired,
|
|
onChange: PropTypes.func.isRequired,
|
|
existingNames: PropTypes.arrayOf(PropTypes.string).isRequired,
|
|
setValidation: PropTypes.func.isRequired,
|
|
type: PropTypes.string.isRequired,
|
|
};
|
|
|
|
function EditParameterSettingsDialog(props) {
|
|
const [param, setParam] = useState(clone(props.parameter));
|
|
const [isNameValid, setIsNameValid] = useState(true);
|
|
const [initialQuery, setInitialQuery] = useState();
|
|
|
|
const isNew = !props.parameter.name;
|
|
|
|
// fetch query by id
|
|
useEffect(() => {
|
|
const { queryId } = props.parameter;
|
|
if (queryId) {
|
|
Query.get({ id: queryId }, (query) => {
|
|
setInitialQuery(query);
|
|
});
|
|
}
|
|
}, []);
|
|
|
|
function isFulfilled() {
|
|
// name
|
|
if (!isNameValid) {
|
|
return false;
|
|
}
|
|
|
|
// title
|
|
if (param.title === '') {
|
|
return false;
|
|
}
|
|
|
|
// query
|
|
if (param.type === 'query' && !param.queryId) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function onConfirm(e) {
|
|
// update title to default
|
|
if (!param.title) {
|
|
// forced to do this cause param won't update in time for save
|
|
param.title = getDefaultTitle(param.name);
|
|
setParam(param);
|
|
}
|
|
|
|
props.dialog.close(param);
|
|
|
|
e.preventDefault(); // stops form redirect
|
|
}
|
|
|
|
return (
|
|
<Modal
|
|
{...props.dialog.props}
|
|
title={isNew ? 'Add Parameter' : param.name}
|
|
width={600}
|
|
footer={[(
|
|
<Button key="cancel" onClick={props.dialog.dismiss}>Cancel</Button>
|
|
), (
|
|
<Button key="submit" htmlType="submit" disabled={!isFulfilled()} type="primary" form="paramForm">
|
|
{isNew ? 'Add Parameter' : 'OK'}
|
|
</Button>
|
|
)]}
|
|
>
|
|
<Form layout="horizontal" onSubmit={onConfirm} id="paramForm">
|
|
{isNew && (
|
|
<NameInput
|
|
name={param.name}
|
|
onChange={name => setParam({ ...param, name })}
|
|
setValidation={setIsNameValid}
|
|
existingNames={props.existingParams}
|
|
type={param.type}
|
|
/>
|
|
)}
|
|
<Form.Item label="Title" {...formItemProps}>
|
|
<Input
|
|
value={isNull(param.title) ? getDefaultTitle(param.name) : param.title}
|
|
onChange={e => setParam({ ...param, title: e.target.value })}
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item label="Type" {...formItemProps}>
|
|
<Select value={param.type} onChange={type => setParam({ ...param, type })}>
|
|
<Option value="text">Text</Option>
|
|
<Option value="number">Number</Option>
|
|
<Option value="enum">Dropdown List</Option>
|
|
<Option value="query">Query Based Dropdown List</Option>
|
|
<Option disabled key="dv1">
|
|
<Divider className="select-option-divider" />
|
|
</Option>
|
|
<Option value="date">Date</Option>
|
|
<Option value="datetime-local">Date and Time</Option>
|
|
<Option value="datetime-with-seconds">Date and Time (with seconds)</Option>
|
|
<Option disabled key="dv2">
|
|
<Divider className="select-option-divider" />
|
|
</Option>
|
|
<Option value="date-range">Date Range</Option>
|
|
<Option value="datetime-range">Date and Time Range</Option>
|
|
<Option value="datetime-range-with-seconds">Date and Time Range (with seconds)</Option>
|
|
</Select>
|
|
</Form.Item>
|
|
{isTypeDate(param.type) && (
|
|
<Form.Item label=" " colon={false} {...formItemProps}>
|
|
<Checkbox
|
|
defaultChecked={param.useCurrentDateTime}
|
|
onChange={e => setParam({ ...param, useCurrentDateTime: e.target.checked })}
|
|
>
|
|
Default to Today/Now if no other value is set
|
|
</Checkbox>
|
|
</Form.Item>
|
|
)}
|
|
{param.type === 'enum' && (
|
|
<Form.Item label="Values" help="Dropdown list values (newline delimeted)" {...formItemProps}>
|
|
<Input.TextArea
|
|
rows={3}
|
|
value={param.enumOptions}
|
|
onChange={e => setParam({ ...param, enumOptions: e.target.value })}
|
|
/>
|
|
</Form.Item>
|
|
)}
|
|
{param.type === 'query' && (
|
|
<Form.Item label="Query" help="Select query to load dropdown values from" {...formItemProps}>
|
|
<QuerySelector
|
|
selectedQuery={initialQuery}
|
|
onChange={q => setParam({ ...param, queryId: q && q.id })}
|
|
type="select"
|
|
/>
|
|
</Form.Item>
|
|
)}
|
|
</Form>
|
|
</Modal>
|
|
);
|
|
}
|
|
|
|
EditParameterSettingsDialog.propTypes = {
|
|
parameter: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
|
|
dialog: DialogPropType.isRequired,
|
|
existingParams: PropTypes.arrayOf(PropTypes.string),
|
|
};
|
|
|
|
EditParameterSettingsDialog.defaultProps = {
|
|
existingParams: [],
|
|
};
|
|
|
|
export default wrapDialog(EditParameterSettingsDialog);
|