You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by vo...@apache.org on 2020/10/03 15:35:35 UTC
[druid] branch master updated: Web console: fix lookup edit dialog
version setting (#10461)
This is an automated email from the ASF dual-hosted git repository.
vogievetsky pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new f77c16b Web console: fix lookup edit dialog version setting (#10461)
f77c16b is described below
commit f77c16bc6c6fa1a56f678cb311944460810251b3
Author: Vadim Ogievetsky <va...@ogievetsky.com>
AuthorDate: Sat Oct 3 08:35:20 2020 -0700
Web console: fix lookup edit dialog version setting (#10461)
* fix lookup edit dialog
* update snapshots
* clean up test
---
web-console/src/components/auto-form/auto-form.tsx | 2 +
.../__snapshots__/form-json-selector.spec.tsx.snap | 43 ++
.../form-json-selector.spec.tsx} | 33 +-
.../form-json-selector/form-json-selector.tsx} | 39 +-
.../__snapshots__/compaction-dialog.spec.tsx.snap | 88 +--
.../compaction-dialog/compaction-dialog.scss | 2 +-
.../compaction-dialog/compaction-dialog.tsx | 25 +-
.../__snapshots__/lookup-edit-dialog.spec.tsx.snap | 745 ++++++++++-----------
.../lookup-edit-dialog/lookup-edit-dialog.scss | 16 +-
.../lookup-edit-dialog/lookup-edit-dialog.spec.tsx | 6 +-
.../lookup-edit-dialog/lookup-edit-dialog.tsx | 144 ++--
.../src/views/datasource-view/datasource-view.tsx | 5 +-
.../src/views/lookups-view/lookups-view.tsx | 4 +-
13 files changed, 538 insertions(+), 614 deletions(-)
diff --git a/web-console/src/components/auto-form/auto-form.tsx b/web-console/src/components/auto-form/auto-form.tsx
index 59561ac..ce26cad 100644
--- a/web-console/src/components/auto-form/auto-form.tsx
+++ b/web-console/src/components/auto-form/auto-form.tsx
@@ -50,6 +50,7 @@ export interface Field<M> {
placeholder?: Functor<M, string>;
min?: number;
zeroMeansUndefined?: boolean;
+ height?: string;
disabled?: Functor<M, boolean>;
defined?: Functor<M, boolean>;
required?: Functor<M, boolean>;
@@ -272,6 +273,7 @@ export class AutoForm<T extends Record<string, any>> extends React.PureComponent
value={deepGet(model as any, field.name)}
onChange={(v: any) => this.fieldChange(field, v)}
placeholder={AutoForm.evaluateFunctor(field.placeholder, model, '')}
+ height={field.height}
/>
);
}
diff --git a/web-console/src/components/form-json-selector/__snapshots__/form-json-selector.spec.tsx.snap b/web-console/src/components/form-json-selector/__snapshots__/form-json-selector.spec.tsx.snap
new file mode 100644
index 0000000..d2ec216
--- /dev/null
+++ b/web-console/src/components/form-json-selector/__snapshots__/form-json-selector.spec.tsx.snap
@@ -0,0 +1,43 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`FormJsonSelector matches snapshot form json 1`] = `
+<Blueprint3.FormGroup
+ className="form-json-selector"
+>
+ <Blueprint3.ButtonGroup
+ fill={true}
+ >
+ <Blueprint3.Button
+ active={false}
+ onClick={[Function]}
+ text="Form"
+ />
+ <Blueprint3.Button
+ active={true}
+ onClick={[Function]}
+ text="JSON"
+ />
+ </Blueprint3.ButtonGroup>
+</Blueprint3.FormGroup>
+`;
+
+exports[`FormJsonSelector matches snapshot form tab 1`] = `
+<Blueprint3.FormGroup
+ className="form-json-selector"
+>
+ <Blueprint3.ButtonGroup
+ fill={true}
+ >
+ <Blueprint3.Button
+ active={true}
+ onClick={[Function]}
+ text="Form"
+ />
+ <Blueprint3.Button
+ active={false}
+ onClick={[Function]}
+ text="JSON"
+ />
+ </Blueprint3.ButtonGroup>
+</Blueprint3.FormGroup>
+`;
diff --git a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.scss b/web-console/src/components/form-json-selector/form-json-selector.spec.tsx
similarity index 60%
copy from web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.scss
copy to web-console/src/components/form-json-selector/form-json-selector.spec.tsx
index 7ee469b..ae7c3a9 100644
--- a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.scss
+++ b/web-console/src/components/form-json-selector/form-json-selector.spec.tsx
@@ -16,28 +16,21 @@
* limitations under the License.
*/
-.lookup-edit-dialog {
- &.bp3-dialog {
- top: 10vh;
+import { shallow } from 'enzyme';
+import React from 'react';
- width: 600px;
- }
+import { FormJsonSelector } from './form-json-selector';
- .auto-form {
- margin: 5px 20px 10px;
- }
+describe('FormJsonSelector', () => {
+ it('matches snapshot form tab', () => {
+ const formJsonSelector = shallow(<FormJsonSelector tab="form" onChange={() => {}} />);
- .lookup-label {
- padding: 0 20px;
- margin-top: 5px;
- margin-bottom: 5px;
- }
+ expect(formJsonSelector).toMatchSnapshot();
+ });
- .ace-solarized-dark {
- background-color: #232c35;
- }
+ it('matches snapshot form json', () => {
+ const formJsonSelector = shallow(<FormJsonSelector tab="json" onChange={() => {}} />);
- .ace_gutter-layer {
- background-color: #27313c;
- }
-}
+ expect(formJsonSelector).toMatchSnapshot();
+ });
+});
diff --git a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.scss b/web-console/src/components/form-json-selector/form-json-selector.tsx
similarity index 54%
copy from web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.scss
copy to web-console/src/components/form-json-selector/form-json-selector.tsx
index 7ee469b..4999826 100644
--- a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.scss
+++ b/web-console/src/components/form-json-selector/form-json-selector.tsx
@@ -16,28 +16,25 @@
* limitations under the License.
*/
-.lookup-edit-dialog {
- &.bp3-dialog {
- top: 10vh;
+import { Button, ButtonGroup, FormGroup } from '@blueprintjs/core';
+import React from 'react';
- width: 600px;
- }
+export type FormJsonTabs = 'form' | 'json';
- .auto-form {
- margin: 5px 20px 10px;
- }
-
- .lookup-label {
- padding: 0 20px;
- margin-top: 5px;
- margin-bottom: 5px;
- }
+export interface FormJsonSelectorProps {
+ tab: FormJsonTabs;
+ onChange: (tab: FormJsonTabs) => void;
+}
- .ace-solarized-dark {
- background-color: #232c35;
- }
+export const FormJsonSelector = React.memo(function FormJsonSelector(props: FormJsonSelectorProps) {
+ const { tab, onChange } = props;
- .ace_gutter-layer {
- background-color: #27313c;
- }
-}
+ return (
+ <FormGroup className="form-json-selector">
+ <ButtonGroup fill>
+ <Button text="Form" active={tab === 'form'} onClick={() => onChange('form')} />
+ <Button text="JSON" active={tab === 'json'} onClick={() => onChange('json')} />
+ </ButtonGroup>
+ </FormGroup>
+ );
+});
diff --git a/web-console/src/dialogs/compaction-dialog/__snapshots__/compaction-dialog.spec.tsx.snap b/web-console/src/dialogs/compaction-dialog/__snapshots__/compaction-dialog.spec.tsx.snap
index 2b1635e..57ead47 100644
--- a/web-console/src/dialogs/compaction-dialog/__snapshots__/compaction-dialog.spec.tsx.snap
+++ b/web-console/src/dialogs/compaction-dialog/__snapshots__/compaction-dialog.spec.tsx.snap
@@ -8,24 +8,10 @@ exports[`CompactionDialog matches snapshot with compactionConfig (dynamic partit
onClose={[Function]}
title="Compaction config: test1"
>
- <Blueprint3.FormGroup
- className="tabs"
- >
- <Blueprint3.ButtonGroup
- fill={true}
- >
- <Blueprint3.Button
- active={true}
- onClick={[Function]}
- text="Form"
- />
- <Blueprint3.Button
- active={false}
- onClick={[Function]}
- text="JSON"
- />
- </Blueprint3.ButtonGroup>
- </Blueprint3.FormGroup>
+ <Memo(FormJsonSelector)
+ onChange={[Function]}
+ tab="form"
+ />
<div
className="content"
>
@@ -240,24 +226,10 @@ exports[`CompactionDialog matches snapshot with compactionConfig (hashed partiti
onClose={[Function]}
title="Compaction config: test1"
>
- <Blueprint3.FormGroup
- className="tabs"
- >
- <Blueprint3.ButtonGroup
- fill={true}
- >
- <Blueprint3.Button
- active={true}
- onClick={[Function]}
- text="Form"
- />
- <Blueprint3.Button
- active={false}
- onClick={[Function]}
- text="JSON"
- />
- </Blueprint3.ButtonGroup>
- </Blueprint3.FormGroup>
+ <Memo(FormJsonSelector)
+ onChange={[Function]}
+ tab="form"
+ />
<div
className="content"
>
@@ -472,24 +444,10 @@ exports[`CompactionDialog matches snapshot with compactionConfig (single_dim par
onClose={[Function]}
title="Compaction config: test1"
>
- <Blueprint3.FormGroup
- className="tabs"
- >
- <Blueprint3.ButtonGroup
- fill={true}
- >
- <Blueprint3.Button
- active={true}
- onClick={[Function]}
- text="Form"
- />
- <Blueprint3.Button
- active={false}
- onClick={[Function]}
- text="JSON"
- />
- </Blueprint3.ButtonGroup>
- </Blueprint3.FormGroup>
+ <Memo(FormJsonSelector)
+ onChange={[Function]}
+ tab="form"
+ />
<div
className="content"
>
@@ -704,24 +662,10 @@ exports[`CompactionDialog matches snapshot without compactionConfig 1`] = `
onClose={[Function]}
title="Compaction config: test1"
>
- <Blueprint3.FormGroup
- className="tabs"
- >
- <Blueprint3.ButtonGroup
- fill={true}
- >
- <Blueprint3.Button
- active={true}
- onClick={[Function]}
- text="Form"
- />
- <Blueprint3.Button
- active={false}
- onClick={[Function]}
- text="JSON"
- />
- </Blueprint3.ButtonGroup>
- </Blueprint3.FormGroup>
+ <Memo(FormJsonSelector)
+ onChange={[Function]}
+ tab="form"
+ />
<div
className="content"
>
diff --git a/web-console/src/dialogs/compaction-dialog/compaction-dialog.scss b/web-console/src/dialogs/compaction-dialog/compaction-dialog.scss
index 65606ba..f5cd57f 100644
--- a/web-console/src/dialogs/compaction-dialog/compaction-dialog.scss
+++ b/web-console/src/dialogs/compaction-dialog/compaction-dialog.scss
@@ -21,7 +21,7 @@
height: 80vh;
}
- .tabs {
+ .form-json-selector {
margin: 15px;
}
diff --git a/web-console/src/dialogs/compaction-dialog/compaction-dialog.tsx b/web-console/src/dialogs/compaction-dialog/compaction-dialog.tsx
index 4a2611b..44bee9a 100644
--- a/web-console/src/dialogs/compaction-dialog/compaction-dialog.tsx
+++ b/web-console/src/dialogs/compaction-dialog/compaction-dialog.tsx
@@ -16,16 +16,18 @@
* limitations under the License.
*/
-import { Button, ButtonGroup, Classes, Code, Dialog, FormGroup, Intent } from '@blueprintjs/core';
+import { Button, Classes, Code, Dialog, Intent } from '@blueprintjs/core';
import React, { useState } from 'react';
import { AutoForm, Field, JsonInput } from '../../components';
+import {
+ FormJsonSelector,
+ FormJsonTabs,
+} from '../../components/form-json-selector/form-json-selector';
import { deepGet, deepSet } from '../../utils/object-change';
import './compaction-dialog.scss';
-type Tabs = 'form' | 'json';
-
type CompactionConfig = Record<string, any>;
const COMPACTION_CONFIG_FIELDS: Field<CompactionConfig>[] = [
@@ -240,7 +242,7 @@ export interface CompactionDialogProps {
export const CompactionDialog = React.memo(function CompactionDialog(props: CompactionDialogProps) {
const { datasource, compactionConfig, onSave, onClose, onDelete } = props;
- const [currentTab, setCurrentTab] = useState<Tabs>('form');
+ const [currentTab, setCurrentTab] = useState<FormJsonTabs>('form');
const [currentConfig, setCurrentConfig] = useState<CompactionConfig>(
compactionConfig || {
dataSource: datasource,
@@ -261,20 +263,7 @@ export const CompactionDialog = React.memo(function CompactionDialog(props: Comp
canOutsideClickClose={false}
title={`Compaction config: ${datasource}`}
>
- <FormGroup className="tabs">
- <ButtonGroup fill>
- <Button
- text="Form"
- active={currentTab === 'form'}
- onClick={() => setCurrentTab('form')}
- />
- <Button
- text="JSON"
- active={currentTab === 'json'}
- onClick={() => setCurrentTab('json')}
- />
- </ButtonGroup>
- </FormGroup>
+ <FormJsonSelector tab={currentTab} onChange={setCurrentTab} />
<div className="content">
{currentTab === 'form' ? (
<AutoForm
diff --git a/web-console/src/dialogs/lookup-edit-dialog/__snapshots__/lookup-edit-dialog.spec.tsx.snap b/web-console/src/dialogs/lookup-edit-dialog/__snapshots__/lookup-edit-dialog.spec.tsx.snap
index 1fe5202..5349950 100644
--- a/web-console/src/dialogs/lookup-edit-dialog/__snapshots__/lookup-edit-dialog.spec.tsx.snap
+++ b/web-console/src/dialogs/lookup-edit-dialog/__snapshots__/lookup-edit-dialog.spec.tsx.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`lookup edit dialog matches snapshot 1`] = `
+exports[`LookupEditDialog matches snapshot 1`] = `
<Blueprint3.Dialog
canOutsideClickClose={true}
className="lookup-edit-dialog"
@@ -8,405 +8,364 @@ exports[`lookup edit dialog matches snapshot 1`] = `
onClose={[Function]}
title="Add lookup"
>
- <Blueprint3.FormGroup
- className="lookup-label"
- label="Name"
- >
- <Blueprint3.InputGroup
- disabled={false}
- onChange={[Function]}
- placeholder="Enter the lookup name"
- value="test"
- />
- </Blueprint3.FormGroup>
- <Blueprint3.FormGroup
- className="lookup-label"
- label="Tier"
+ <div
+ className="content"
>
- <HTMLSelect
- disabled={false}
- onChange={[Function]}
- value="test"
+ <Blueprint3.FormGroup
+ label="Name"
>
- <option
- key="a"
- value="a"
- >
- a
- </option>
- <option
- key="b"
- value="b"
- >
- b
- </option>
- <option
- key="c"
- value="c"
- >
- c
- </option>
- <option
- key="d"
- value="d"
- >
- d
- </option>
- <option
- key="e"
- value="e"
- >
- e
- </option>
- <option
- key="f"
- value="f"
- >
- f
- </option>
- <option
- key="g"
- value="g"
- >
- g
- </option>
- <option
- key="h"
- value="h"
- >
- h
- </option>
- <option
- key="i"
- value="i"
- >
- i
- </option>
- <option
- key="j"
- value="j"
+ <Blueprint3.InputGroup
+ disabled={false}
+ onChange={[Function]}
+ placeholder="Enter the lookup name"
+ value="test"
+ />
+ </Blueprint3.FormGroup>
+ <Blueprint3.FormGroup
+ label="Tier"
+ >
+ <HTMLSelect
+ onChange={[Function]}
+ value="test"
>
- j
- </option>
- </HTMLSelect>
- </Blueprint3.FormGroup>
- <Blueprint3.FormGroup
- className="lookup-label"
- label="Version"
- >
- <Blueprint3.InputGroup
+ <option
+ key="__default"
+ value="__default"
+ >
+ __default
+ </option>
+ <option
+ key="alt-tier"
+ value="alt-tier"
+ >
+ alt-tier
+ </option>
+ </HTMLSelect>
+ </Blueprint3.FormGroup>
+ <Blueprint3.FormGroup
+ label="Version"
+ >
+ <Blueprint3.InputGroup
+ onChange={[Function]}
+ placeholder="Enter the lookup version"
+ rightElement={
+ <Blueprint3.Button
+ minimal={true}
+ onClick={[Function]}
+ text="Use ISO as version"
+ />
+ }
+ value="test"
+ />
+ </Blueprint3.FormGroup>
+ <Memo(FormJsonSelector)
onChange={[Function]}
- placeholder="Enter the lookup version"
- rightElement={
- <Blueprint3.Button
- minimal={true}
- onClick={[Function]}
- text="Use ISO as version"
- />
- }
- value="test"
+ tab="form"
/>
- </Blueprint3.FormGroup>
- <AutoForm
- fields={
- Array [
- Object {
- "adjustment": [Function],
- "name": "type",
- "suggestions": Array [
- "map",
- "cachedNamespace",
- ],
- "type": "string",
- },
- Object {
- "defined": [Function],
- "name": "map",
- "type": "json",
- },
- Object {
- "defined": [Function],
- "label": "Globally cached lookup type",
- "name": "extractionNamespace.type",
- "placeholder": "uri",
- "suggestions": Array [
- "uri",
- "jdbc",
- ],
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": "A URI which specifies a directory (or other searchable resource) in which to search for files",
- "label": "URI prefix",
- "name": "extractionNamespace.uriPrefix",
- "placeholder": "s3://bucket/some/key/prefix/",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": "Optional regex for matching the file name under uriPrefix. Only used if uriPrefix is used",
- "label": "File regex",
- "name": "extractionNamespace.fileRegex",
- "placeholder": "(optional)",
- "type": "string",
- },
- Object {
- "defaultValue": "csv",
- "defined": [Function],
- "label": "Format",
- "name": "extractionNamespace.namespaceParseSpec.format",
- "suggestions": Array [
- "csv",
- "tsv",
- "customJson",
- "simpleJson",
- ],
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": "The list of columns in the csv file",
- "label": "Columns",
- "name": "extractionNamespace.namespaceParseSpec.columns",
- "placeholder": "[\\"key\\", \\"value\\"]",
- "type": "string-array",
- },
- Object {
- "defined": [Function],
- "info": "The name of the column containing the key",
- "label": "Key column",
- "name": "extractionNamespace.namespaceParseSpec.keyColumn",
- "placeholder": "Key",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": "The name of the column containing the value",
- "label": "Value column",
- "name": "extractionNamespace.namespaceParseSpec.valueColumn",
- "placeholder": "Value",
- "type": "string",
- },
- Object {
- "defaultValue": false,
- "defined": [Function],
- "info": "A flag to indicate that column information can be extracted from the input files' header row",
- "label": "Has header row",
- "name": "extractionNamespace.namespaceParseSpec.hasHeaderRow",
- "type": "boolean",
- },
- Object {
- "defined": [Function],
- "info": "Number of header rows to be skipped. The default number of header rows to be skipped is 0.",
- "label": "Skip header rows",
- "name": "extractionNamespace.namespaceParseSpec.skipHeaderRows",
- "placeholder": "(optional)",
- "type": "number",
- },
- Object {
- "defined": [Function],
- "label": "Delimiter",
- "name": "extractionNamespace.namespaceParseSpec.delimiter",
- "placeholder": "(optional)",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "label": "List delimiter",
- "name": "extractionNamespace.namespaceParseSpec.listDelimiter",
- "placeholder": "(optional)",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "label": "Key field name",
- "name": "extractionNamespace.namespaceParseSpec.keyFieldName",
- "placeholder": "key",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "label": "Value field name",
- "name": "extractionNamespace.namespaceParseSpec.valueFieldName",
- "placeholder": "value",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": <React.Fragment>
- <p>
- The namespace value in the SQL query:
- </p>
- <p>
- SELECT keyColumn, valueColumn, tsColumn? FROM
- <strong>
- namespace
- </strong>
- .table WHERE filter
- </p>
- </React.Fragment>,
- "label": "Namespace",
- "name": "extractionNamespace.namespace",
- "placeholder": "some_lookup",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": "Defines the connectURI value on the The connector config to used",
- "label": "CreateTables",
- "name": "extractionNamespace.connectorConfig.createTables",
- "type": "boolean",
- },
- Object {
- "defined": [Function],
- "info": "Defines the connectURI value on the The connector config to used",
- "label": "Connect URI",
- "name": "extractionNamespace.connectorConfig.connectURI",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": "Defines the user to be used by the connector config",
- "label": "User",
- "name": "extractionNamespace.connectorConfig.user",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": "Defines the password to be used by the connector config",
- "label": "Password",
- "name": "extractionNamespace.connectorConfig.password",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": <React.Fragment>
- <p>
- The table which contains the key value pairs. This will become the table value in the SQL query:
- </p>
- <p>
- SELECT keyColumn, valueColumn, tsColumn? FROM namespace.
- <strong>
- table
- </strong>
- WHERE filter
- </p>
- </React.Fragment>,
- "label": "Table",
- "name": "extractionNamespace.table",
- "placeholder": "some_lookup_table",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": <React.Fragment>
- <p>
- The column in the table which contains the keys. This will become the keyColumn value in the SQL query:
- </p>
- <p>
- SELECT
- <strong>
- keyColumn
- </strong>
- , valueColumn, tsColumn? FROM namespace.table WHERE filter
- </p>
- </React.Fragment>,
- "label": "Key column",
- "name": "extractionNamespace.keyColumn",
- "placeholder": "my_key_value",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": <React.Fragment>
- <p>
- The column in table which contains the values. This will become the valueColumn value in the SQL query:
- </p>
- <p>
- SELECT keyColumn,
- <strong>
- valueColumn
- </strong>
- , tsColumn? FROM namespace.table WHERE filter
- </p>
- </React.Fragment>,
- "label": "Value column",
- "name": "extractionNamespace.valueColumn",
- "placeholder": "my_column_value",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": <React.Fragment>
- <p>
- The filter to be used when selecting lookups, this is used to create a where clause on lookup population. This will become the expression filter in the SQL query:
- </p>
- <p>
- SELECT keyColumn, valueColumn, tsColumn? FROM namespace.table WHERE
-
- <strong>
- filter
- </strong>
- </p>
- </React.Fragment>,
- "label": "Filter",
- "name": "extractionNamespace.filter",
- "placeholder": "(optional)",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": <React.Fragment>
- <p>
- The column in table which contains when the key was updated. This will become the Value in the SQL query:
- </p>
- <p>
- SELECT keyColumn, valueColumn,
- <strong>
- tsColumn
- </strong>
- ? FROM namespace.table WHERE filter
- </p>
- </React.Fragment>,
- "label": "TsColumn",
- "name": "extractionNamespace.tsColumn",
- "placeholder": "(optional)",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": "Period between polling for updates",
- "label": "Poll period",
- "name": "extractionNamespace.pollPeriod",
- "placeholder": "(optional)",
- "type": "string",
- },
- Object {
- "defined": [Function],
- "info": "How long to wait (in ms) for the first run of the cache to populate. 0 indicates to not wait",
- "label": "First cache timeout",
- "name": "firstCacheTimeout",
- "placeholder": "(optional)",
- "type": "number",
- },
+ <AutoForm
+ fields={
+ Array [
+ Object {
+ "adjustment": [Function],
+ "name": "type",
+ "suggestions": Array [
+ "map",
+ "cachedNamespace",
+ ],
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "height": "60vh",
+ "name": "map",
+ "type": "json",
+ },
+ Object {
+ "defined": [Function],
+ "label": "Globally cached lookup type",
+ "name": "extractionNamespace.type",
+ "placeholder": "uri",
+ "suggestions": Array [
+ "uri",
+ "jdbc",
+ ],
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": "A URI which specifies a directory (or other searchable resource) in which to search for files",
+ "label": "URI prefix",
+ "name": "extractionNamespace.uriPrefix",
+ "placeholder": "s3://bucket/some/key/prefix/",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": "Optional regex for matching the file name under uriPrefix. Only used if uriPrefix is used",
+ "label": "File regex",
+ "name": "extractionNamespace.fileRegex",
+ "placeholder": "(optional)",
+ "type": "string",
+ },
+ Object {
+ "defaultValue": "csv",
+ "defined": [Function],
+ "label": "Format",
+ "name": "extractionNamespace.namespaceParseSpec.format",
+ "suggestions": Array [
+ "csv",
+ "tsv",
+ "customJson",
+ "simpleJson",
+ ],
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": "The list of columns in the csv file",
+ "label": "Columns",
+ "name": "extractionNamespace.namespaceParseSpec.columns",
+ "placeholder": "[\\"key\\", \\"value\\"]",
+ "type": "string-array",
+ },
+ Object {
+ "defined": [Function],
+ "info": "The name of the column containing the key",
+ "label": "Key column",
+ "name": "extractionNamespace.namespaceParseSpec.keyColumn",
+ "placeholder": "Key",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": "The name of the column containing the value",
+ "label": "Value column",
+ "name": "extractionNamespace.namespaceParseSpec.valueColumn",
+ "placeholder": "Value",
+ "type": "string",
+ },
+ Object {
+ "defaultValue": false,
+ "defined": [Function],
+ "info": "A flag to indicate that column information can be extracted from the input files' header row",
+ "label": "Has header row",
+ "name": "extractionNamespace.namespaceParseSpec.hasHeaderRow",
+ "type": "boolean",
+ },
+ Object {
+ "defined": [Function],
+ "info": "Number of header rows to be skipped. The default number of header rows to be skipped is 0.",
+ "label": "Skip header rows",
+ "name": "extractionNamespace.namespaceParseSpec.skipHeaderRows",
+ "placeholder": "(optional)",
+ "type": "number",
+ },
+ Object {
+ "defined": [Function],
+ "label": "Delimiter",
+ "name": "extractionNamespace.namespaceParseSpec.delimiter",
+ "placeholder": "(optional)",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "label": "List delimiter",
+ "name": "extractionNamespace.namespaceParseSpec.listDelimiter",
+ "placeholder": "(optional)",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "label": "Key field name",
+ "name": "extractionNamespace.namespaceParseSpec.keyFieldName",
+ "placeholder": "key",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "label": "Value field name",
+ "name": "extractionNamespace.namespaceParseSpec.valueFieldName",
+ "placeholder": "value",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": <React.Fragment>
+ <p>
+ The namespace value in the SQL query:
+ </p>
+ <p>
+ SELECT keyColumn, valueColumn, tsColumn? FROM
+ <strong>
+ namespace
+ </strong>
+ .table WHERE filter
+ </p>
+ </React.Fragment>,
+ "label": "Namespace",
+ "name": "extractionNamespace.namespace",
+ "placeholder": "some_lookup",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": "Defines the connectURI value on the The connector config to used",
+ "label": "CreateTables",
+ "name": "extractionNamespace.connectorConfig.createTables",
+ "type": "boolean",
+ },
+ Object {
+ "defined": [Function],
+ "info": "Defines the connectURI value on the The connector config to used",
+ "label": "Connect URI",
+ "name": "extractionNamespace.connectorConfig.connectURI",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": "Defines the user to be used by the connector config",
+ "label": "User",
+ "name": "extractionNamespace.connectorConfig.user",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": "Defines the password to be used by the connector config",
+ "label": "Password",
+ "name": "extractionNamespace.connectorConfig.password",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": <React.Fragment>
+ <p>
+ The table which contains the key value pairs. This will become the table value in the SQL query:
+ </p>
+ <p>
+ SELECT keyColumn, valueColumn, tsColumn? FROM namespace.
+ <strong>
+ table
+ </strong>
+ WHERE filter
+ </p>
+ </React.Fragment>,
+ "label": "Table",
+ "name": "extractionNamespace.table",
+ "placeholder": "some_lookup_table",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": <React.Fragment>
+ <p>
+ The column in the table which contains the keys. This will become the keyColumn value in the SQL query:
+ </p>
+ <p>
+ SELECT
+ <strong>
+ keyColumn
+ </strong>
+ , valueColumn, tsColumn? FROM namespace.table WHERE filter
+ </p>
+ </React.Fragment>,
+ "label": "Key column",
+ "name": "extractionNamespace.keyColumn",
+ "placeholder": "my_key_value",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": <React.Fragment>
+ <p>
+ The column in table which contains the values. This will become the valueColumn value in the SQL query:
+ </p>
+ <p>
+ SELECT keyColumn,
+ <strong>
+ valueColumn
+ </strong>
+ , tsColumn? FROM namespace.table WHERE filter
+ </p>
+ </React.Fragment>,
+ "label": "Value column",
+ "name": "extractionNamespace.valueColumn",
+ "placeholder": "my_column_value",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": <React.Fragment>
+ <p>
+ The filter to be used when selecting lookups, this is used to create a where clause on lookup population. This will become the expression filter in the SQL query:
+ </p>
+ <p>
+ SELECT keyColumn, valueColumn, tsColumn? FROM namespace.table WHERE
+
+ <strong>
+ filter
+ </strong>
+ </p>
+ </React.Fragment>,
+ "label": "Filter",
+ "name": "extractionNamespace.filter",
+ "placeholder": "(optional)",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": <React.Fragment>
+ <p>
+ The column in table which contains when the key was updated. This will become the Value in the SQL query:
+ </p>
+ <p>
+ SELECT keyColumn, valueColumn,
+ <strong>
+ tsColumn
+ </strong>
+ ? FROM namespace.table WHERE filter
+ </p>
+ </React.Fragment>,
+ "label": "TsColumn",
+ "name": "extractionNamespace.tsColumn",
+ "placeholder": "(optional)",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": "Period between polling for updates",
+ "label": "Poll period",
+ "name": "extractionNamespace.pollPeriod",
+ "placeholder": "(optional)",
+ "type": "string",
+ },
+ Object {
+ "defined": [Function],
+ "info": "How long to wait (in ms) for the first run of the cache to populate. 0 indicates to not wait",
+ "label": "First cache timeout",
+ "name": "firstCacheTimeout",
+ "placeholder": "(optional)",
+ "type": "number",
+ },
+ Object {
+ "defaultValue": false,
+ "defined": [Function],
+ "info": "If the underlying map is injective (keys and values are unique) then optimizations can occur internally by setting this to true",
+ "name": "injective",
+ "type": "boolean",
+ },
+ ]
+ }
+ model={
Object {
- "defaultValue": false,
- "defined": [Function],
- "info": "If the underlying map is injective (keys and values are unique) then optimizations can occur internally by setting this to true",
- "name": "injective",
- "type": "boolean",
- },
- ]
- }
- model={
- Object {
- "map": Object {},
- "type": "map",
+ "map": Object {
+ "a": 1,
+ },
+ "type": "map",
+ }
}
- }
- onChange={[Function]}
- />
+ onChange={[Function]}
+ />
+ </div>
<div
className="bp3-dialog-footer"
>
diff --git a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.scss b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.scss
index 7ee469b..e42914f 100644
--- a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.scss
+++ b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.scss
@@ -18,19 +18,15 @@
.lookup-edit-dialog {
&.bp3-dialog {
- top: 10vh;
-
+ height: 80vh;
width: 600px;
}
- .auto-form {
- margin: 5px 20px 10px;
- }
-
- .lookup-label {
- padding: 0 20px;
- margin-top: 5px;
- margin-bottom: 5px;
+ .content {
+ margin: 0 15px 10px 0;
+ padding: 15px 5px 5px 15px;
+ flex: 1;
+ overflow: auto;
}
.ace-solarized-dark {
diff --git a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx
index a314302..f9eebd8 100644
--- a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx
+++ b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.spec.tsx
@@ -21,7 +21,7 @@ import React from 'react';
import { isLookupSubmitDisabled, LookupEditDialog } from './lookup-edit-dialog';
-describe('lookup edit dialog', () => {
+describe('LookupEditDialog', () => {
it('matches snapshot', () => {
const lookupEditDialog = shallow(
<LookupEditDialog
@@ -31,9 +31,9 @@ describe('lookup edit dialog', () => {
lookupName={'test'}
lookupTier={'test'}
lookupVersion={'test'}
- lookupSpec={{ type: 'map', map: {} }}
+ lookupSpec={{ type: 'map', map: { a: 1 } }}
isEdit={false}
- allLookupTiers={['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']}
+ allLookupTiers={['__default', 'alt-tier']}
/>,
);
diff --git a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx
index fe203fd..24eb832 100644
--- a/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx
+++ b/web-console/src/dialogs/lookup-edit-dialog/lookup-edit-dialog.tsx
@@ -25,9 +25,13 @@ import {
InputGroup,
Intent,
} from '@blueprintjs/core';
-import React from 'react';
+import React, { useState } from 'react';
-import { AutoForm, Field } from '../../components';
+import { AutoForm, Field, JsonInput } from '../../components';
+import {
+ FormJsonSelector,
+ FormJsonTabs,
+} from '../../components/form-json-selector/form-json-selector';
import './lookup-edit-dialog.scss';
@@ -158,9 +162,8 @@ const LOOKUP_FIELDS: Field<LookupSpec>[] = [
{
name: 'map',
type: 'json',
- defined: (model: LookupSpec) => {
- return model.type === 'map';
- },
+ height: '60vh',
+ defined: (model: LookupSpec) => model.type === 'map',
},
{
name: 'extractionNamespace.type',
@@ -552,47 +555,8 @@ export const LookupEditDialog = React.memo(function LookupEditDialog(props: Look
isEdit,
allLookupTiers,
} = props;
-
- let updateVersionOnSubmit = true;
-
- function addISOVersion() {
- const currentDate = new Date();
- const ISOString = currentDate.toISOString();
- onChange('version', ISOString);
- }
-
- function renderTierInput() {
- if (isEdit) {
- return (
- <FormGroup className="lookup-label" label="Tier">
- <InputGroup
- value={lookupTier}
- onChange={(e: any) => {
- updateVersionOnSubmit = false;
- onChange('tier', e.target.value);
- }}
- disabled
- />
- </FormGroup>
- );
- } else {
- return (
- <FormGroup className="lookup-label" label="Tier">
- <HTMLSelect
- disabled={isEdit}
- value={lookupTier}
- onChange={(e: any) => onChange('tier', e.target.value)}
- >
- {allLookupTiers.map(tier => (
- <option key={tier} value={tier}>
- {tier}
- </option>
- ))}
- </HTMLSelect>
- </FormGroup>
- );
- }
- }
+ const [currentTab, setCurrentTab] = useState<FormJsonTabs>('form');
+ const [updateVersionOnSubmit, setUpdateVersionOnSubmit] = useState(true);
return (
<Dialog
@@ -601,32 +565,68 @@ export const LookupEditDialog = React.memo(function LookupEditDialog(props: Look
onClose={onClose}
title={isEdit ? 'Edit lookup' : 'Add lookup'}
>
- <FormGroup className="lookup-label" label="Name">
- <InputGroup
- value={lookupName}
- onChange={(e: any) => onChange('name', e.target.value)}
- disabled={isEdit}
- placeholder="Enter the lookup name"
- />
- </FormGroup>
- {renderTierInput()}
- <FormGroup className="lookup-label" label="Version">
- <InputGroup
- value={lookupVersion}
- onChange={(e: any) => onChange('version', e.target.value)}
- placeholder="Enter the lookup version"
- rightElement={
- <Button minimal text="Use ISO as version" onClick={() => addISOVersion()} />
- }
- />
- </FormGroup>
- <AutoForm
- fields={LOOKUP_FIELDS}
- model={lookupSpec}
- onChange={m => {
- onChange('spec', m);
- }}
- />
+ <div className="content">
+ <FormGroup label="Name">
+ <InputGroup
+ value={lookupName}
+ onChange={(e: any) => onChange('name', e.target.value)}
+ disabled={isEdit}
+ placeholder="Enter the lookup name"
+ />
+ </FormGroup>
+ <FormGroup label="Tier">
+ {isEdit ? (
+ <InputGroup
+ value={lookupTier}
+ onChange={(e: any) => onChange('tier', e.target.value)}
+ disabled
+ />
+ ) : (
+ <HTMLSelect value={lookupTier} onChange={(e: any) => onChange('tier', e.target.value)}>
+ {allLookupTiers.map(tier => (
+ <option key={tier} value={tier}>
+ {tier}
+ </option>
+ ))}
+ </HTMLSelect>
+ )}
+ </FormGroup>
+ <FormGroup label="Version">
+ <InputGroup
+ value={lookupVersion}
+ onChange={(e: any) => {
+ setUpdateVersionOnSubmit(false);
+ onChange('version', e.target.value);
+ }}
+ placeholder="Enter the lookup version"
+ rightElement={
+ <Button
+ minimal
+ text="Use ISO as version"
+ onClick={() => onChange('version', new Date().toISOString())}
+ />
+ }
+ />
+ </FormGroup>
+ <FormJsonSelector tab={currentTab} onChange={setCurrentTab} />
+ {currentTab === 'form' ? (
+ <AutoForm
+ fields={LOOKUP_FIELDS}
+ model={lookupSpec}
+ onChange={m => {
+ onChange('spec', m);
+ }}
+ />
+ ) : (
+ <JsonInput
+ value={lookupSpec}
+ onChange={m => {
+ onChange('spec', m);
+ }}
+ height="80vh"
+ />
+ )}
+ </div>
<div className={Classes.DIALOG_FOOTER}>
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
<Button text="Close" onClick={onClose} />
diff --git a/web-console/src/views/datasource-view/datasource-view.tsx b/web-console/src/views/datasource-view/datasource-view.tsx
index 9f81a03..02397c6 100644
--- a/web-console/src/views/datasource-view/datasource-view.tsx
+++ b/web-console/src/views/datasource-view/datasource-view.tsx
@@ -893,9 +893,10 @@ GROUP BY 1`;
data={datasources}
loading={datasourcesAndDefaultRulesState.loading}
noDataText={
- !datasourcesAndDefaultRulesState.loading && datasources && !datasources.length
+ datasourcesAndDefaultRulesState.getErrorMessage() ||
+ (!datasourcesAndDefaultRulesState.loading && datasources && !datasources.length
? 'No datasources'
- : datasourcesAndDefaultRulesState.getErrorMessage() || ''
+ : '')
}
filterable
filtered={datasourceFilter}
diff --git a/web-console/src/views/lookups-view/lookups-view.tsx b/web-console/src/views/lookups-view/lookups-view.tsx
index 46eb421..3666263 100644
--- a/web-console/src/views/lookups-view/lookups-view.tsx
+++ b/web-console/src/views/lookups-view/lookups-view.tsx
@@ -203,11 +203,11 @@ export class LookupsView extends React.PureComponent<LookupsViewProps, LookupsVi
}));
};
- private async submitLookupEdit(updatelookupEditVersion: boolean) {
+ private async submitLookupEdit(updateLookupVersion: boolean) {
const { lookupEdit, isEdit } = this.state;
if (!lookupEdit) return;
- const version = updatelookupEditVersion ? new Date().toISOString() : lookupEdit.version;
+ const version = updateLookupVersion ? new Date().toISOString() : lookupEdit.version;
let endpoint = '/druid/coordinator/v1/lookups/config';
const specJson: any = lookupEdit.spec;
let dataJson: any;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org