diff --git a/client/app/components/EditParameterSettingsDialog.jsx b/client/app/components/EditParameterSettingsDialog.jsx
index 59673c0ea1..3023a64738 100644
--- a/client/app/components/EditParameterSettingsDialog.jsx
+++ b/client/app/components/EditParameterSettingsDialog.jsx
@@ -1,16 +1,23 @@
-import { includes, words, capitalize, clone, isNull } from "lodash";
-import React, { useState, useEffect } from "react";
+import { includes, words, capitalize, clone, isNull, keys, values } from "lodash";
+import React, { useState, useEffect, useRef } from "react";
import PropTypes from "prop-types";
import Checkbox from "antd/lib/checkbox";
import Modal from "antd/lib/modal";
import Form from "antd/lib/form";
import Button from "antd/lib/button";
import Select from "antd/lib/select";
+import Icon from "antd/lib/icon";
import Input from "antd/lib/input";
+import Table from "antd/lib/table";
import Divider from "antd/lib/divider";
+import Tooltip from "antd/lib/tooltip";
+import Popover from "antd/lib/popover";
+import Radio from "antd/lib/radio";
import { wrap as wrapDialog, DialogPropType } from "@/components/DialogWrapper";
import QuerySelector from "@/components/QuerySelector";
+import ParameterMappingEditor from "@/components//ParameterMappingEditor";
import { Query } from "@/services/query";
+import { QueryBasedParameterMappingType } from "@/services/parameters/QueryBasedDropdownParameter";
const { Option } = Select;
const formItemProps = { labelCol: { span: 6 }, wrapperCol: { span: 16 } };
@@ -66,20 +73,85 @@ NameInput.propTypes = {
type: PropTypes.string.isRequired,
};
+// TODO: put this component in its own file
+function QueryBasedParamMappingEditor({ parameter, mappingType, staticValue, searchAvailable, onChange }) {
+ const [showPopover, setShowPopover] = useState(false);
+
+ let currentState = "Undefined";
+ if (mappingType === QueryBasedParameterMappingType.DROPDOWN_SEARCH) {
+ currentState = "Dropdown Search";
+ } else if (mappingType === QueryBasedParameterMappingType.STATIC) {
+ currentState = `Static value: ${staticValue}`;
+ }
+ return (
+ <>
+ {currentState}
+ setShowPopover(false)}>
+
+
+
+ Dropdown Search{" "}
+ {!searchAvailable && (
+
+
+
+ )}
+
+
+ Static Value
+
+
+
+
+
+ }
+ visible={showPopover}
+ onVisibleChange={setShowPopover}>
+
+
+ >
+ );
+}
+
+QueryBasedParamMappingEditor.propTypes = {
+ parameter: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
+ mappingType: PropTypes.oneOf(values(QueryBasedParameterMappingType)),
+ staticValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ searchAvailable: PropTypes.bool,
+ onChange: PropTypes.func,
+};
+
+QueryBasedParamMappingEditor.defaultProps = {
+ mappingType: QueryBasedParameterMappingType.UNDEFINED,
+ staticValue: undefined,
+ searchAvailable: false,
+ onChance: () => {},
+};
+
function EditParameterSettingsDialog(props) {
const [param, setParam] = useState(clone(props.parameter));
const [isNameValid, setIsNameValid] = useState(true);
- const [initialQuery, setInitialQuery] = useState();
+ const [paramQuery, setParamQuery] = useState();
const isNew = !props.parameter.name;
// fetch query by id
+ const initialQueryId = useRef(props.parameter.queryId);
useEffect(() => {
- const queryId = props.parameter.queryId;
- if (queryId) {
- Query.get({ id: queryId }).then(setInitialQuery);
+ if (initialQueryId.current) {
+ Query.get({ id: initialQueryId.current }).then(setParamQuery);
}
- }, [props.parameter.queryId]);
+ }, []);
function isFulfilled() {
// name
@@ -191,12 +263,55 @@ function EditParameterSettingsDialog(props) {
{param.type === "query" && (
setParam({ ...param, queryId: q && q.id })}
+ selectedQuery={paramQuery}
+ onChange={q => {
+ if (q) {
+ setParamQuery(q);
+ setParam({ ...param, queryId: q.id });
+ }
+ }}
type="select"
/>
)}
+ {param.type === "query" && paramQuery && paramQuery.hasParameters() && (
+
+ `row${idx}`}>
+ mappingParam.getTitle()} />
+ {`{{ ${mappingParam.name} }}`}
}
+ />
+ {
+ const mappingProps = {
+ parameter: mappingParam,
+ mappingType: QueryBasedParameterMappingType.UNDEFINED,
+ searchAvailable: !param.searchColumn,
+ };
+
+ // TODO: Update backend verification accordingly and avoid this
+ if (param.searchColumn === mappingParam.name) {
+ mappingProps.mappingType = QueryBasedParameterMappingType.DROPDOWN_SEARCH;
+ mappingProps.searchAvailable = true;
+ } else if (includes(keys(param.staticValues), mappingParam.name)) {
+ mappingProps.mappingType = QueryBasedParameterMappingType.STATIC;
+ mappingProps.staticValue = param.staticValues[mappingParam.name];
+ }
+ return ;
+ }}
+ />
+
+
+ )}
{(param.type === "enum" || param.type === "query") && (
+ {header && }
+ {children}
+
+
+ );
+}
+
+ParameterMappingEditor.propTypes = {
+ header: PropTypes.node,
+ children: PropTypes.node,
+ saveDisabled: PropTypes.bool,
+ onSave: PropTypes.func,
+ onCancel: PropTypes.func,
+};
+
+ParameterMappingEditor.defaultProps = {
+ header: null,
+ children: null,
+ saveDisabled: false,
+ onSave: () => {},
+ onCancel: () => {},
+};
diff --git a/client/app/components/ParameterMappingEditor.less b/client/app/components/ParameterMappingEditor.less
new file mode 100644
index 0000000000..252018aed3
--- /dev/null
+++ b/client/app/components/ParameterMappingEditor.less
@@ -0,0 +1,37 @@
+@import "~antd/lib/modal/style/index"; // for ant @vars
+
+.parameter-mapping-editor {
+ width: 390px;
+
+ .radio {
+ display: block;
+ height: 30px;
+ line-height: 30px;
+ }
+
+ .form-item {
+ margin-bottom: 10px;
+ }
+
+ header {
+ padding: 0 16px 10px;
+ margin: 0 -16px 20px;
+ border-bottom: @border-width-base @border-style-base @border-color-split;
+ font-size: @font-size-lg;
+ font-weight: 500;
+ color: @heading-color;
+ display: flex;
+ justify-content: space-between;
+ }
+
+ footer {
+ border-top: @border-width-base @border-style-base @border-color-split;
+ padding: 10px 16px 0;
+ margin: 0 -16px;
+ text-align: right;
+
+ button {
+ margin-left: 8px;
+ }
+ }
+}
diff --git a/client/app/components/ParameterMappingInput.jsx b/client/app/components/ParameterMappingInput.jsx
index 1ed41f1b65..dc222a38f7 100644
--- a/client/app/components/ParameterMappingInput.jsx
+++ b/client/app/components/ParameterMappingInput.jsx
@@ -18,6 +18,7 @@ import ParameterValueInput from "@/components/ParameterValueInput";
import { ParameterMappingType } from "@/services/widget";
import { Parameter, cloneParameter } from "@/services/parameters";
import HelpTrigger from "@/components/HelpTrigger";
+import ParameterMappingEditor from "@/components/ParameterMappingEditor";
import "./ParameterMappingInput.less";
@@ -325,23 +326,22 @@ class MappingEditor extends React.Component {
const { mapping, inputError } = this.state;
return (
-
-
- Edit Source and Value
-
+
+ Edit Source and Value
+ >
+ }
+ saveDisabled={!!inputError}
+ onSave={this.save}
+ onCancel={this.hide}>
-
-
+
);
}
diff --git a/client/app/components/ParameterMappingInput.less b/client/app/components/ParameterMappingInput.less
index 4cff86ae21..06bf4ee018 100644
--- a/client/app/components/ParameterMappingInput.less
+++ b/client/app/components/ParameterMappingInput.less
@@ -1,4 +1,4 @@
-@import '~antd/lib/modal/style/index'; // for ant @vars
+@import "~antd/lib/modal/style/index"; // for ant @vars
.parameters-mapping-list {
.keyword {
@@ -22,48 +22,13 @@
}
}
-.parameter-mapping-editor {
- width: 390px;
-
- .radio {
- display: block;
- height: 30px;
- line-height: 30px;
- }
-
- .form-item {
- margin-bottom: 10px;
- }
-
- header {
- padding: 0 16px 10px;
- margin: 0 -16px 20px;
- border-bottom: @border-width-base @border-style-base @border-color-split;
- font-size: @font-size-lg;
- font-weight: 500;
- color: @heading-color;
- display: flex;
- justify-content: space-between;
- }
-
- footer {
- border-top: @border-width-base @border-style-base @border-color-split;
- padding: 10px 16px 0;
- margin: 0 -16px;
- text-align: right;
-
- button {
- margin-left: 8px;
- }
- }
-}
-
.parameter-mapping-title {
.text {
margin-right: 3px;
}
- &.disabled, .fa {
+ &.disabled,
+ .fa {
color: #a4a4a4;
}
diff --git a/client/app/components/Parameters.jsx b/client/app/components/Parameters.jsx
index 075033de25..8ae3fd0c98 100644
--- a/client/app/components/Parameters.jsx
+++ b/client/app/components/Parameters.jsx
@@ -7,7 +7,6 @@ import { Parameter, createParameter } from "@/services/parameters";
import ParameterApplyButton from "@/components/ParameterApplyButton";
import ParameterValueInput from "@/components/ParameterValueInput";
import EditParameterSettingsDialog from "./EditParameterSettingsDialog";
-import { toHuman } from "@/lib/utils";
import "./Parameters.less";
@@ -123,7 +122,7 @@ export default class Parameters extends React.Component {
return (
-
+
{editable && (