mirror of
https://github.com/apache/druid.git
synced 2025-02-20 00:47:40 +00:00
Web console: fix lookup edit dialog, allow column renaming (#10406)
* column rename * update licenses file * remove empty file * update license file * move comment
This commit is contained in:
parent
ae247b6e63
commit
6c5c86d800
@ -4721,7 +4721,7 @@ license_category: binary
|
|||||||
module: web-console
|
module: web-console
|
||||||
license_name: Apache License version 2.0
|
license_name: Apache License version 2.0
|
||||||
copyright: Imply Data
|
copyright: Imply Data
|
||||||
version: 0.9.11
|
version: 0.9.15
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
6
web-console/package-lock.json
generated
6
web-console/package-lock.json
generated
@ -4243,9 +4243,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"druid-query-toolkit": {
|
"druid-query-toolkit": {
|
||||||
"version": "0.9.11",
|
"version": "0.9.15",
|
||||||
"resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.9.11.tgz",
|
"resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.9.15.tgz",
|
||||||
"integrity": "sha512-pg0Ux/y0IM2TxYEfY2cK361w+c5Efw40KVrkIK8s8uVDYF3BLVN+XWQO/ykKB73hOUHLq1ctLOxRUyKphnbyvQ==",
|
"integrity": "sha512-HiJVqa6X6z/LeEU3GVxbkaP/X8JCn/9n8txoG1tSgk6edc1BZXj7F7hZpaNlAThVcZcFOYeE1gFOHzMMjK4U0A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tslib": "^1.10.0"
|
"tslib": "^1.10.0"
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
"d3-axis": "^1.0.12",
|
"d3-axis": "^1.0.12",
|
||||||
"d3-scale": "^3.2.0",
|
"d3-scale": "^3.2.0",
|
||||||
"d3-selection": "^1.4.0",
|
"d3-selection": "^1.4.0",
|
||||||
"druid-query-toolkit": "^0.9.11",
|
"druid-query-toolkit": "^0.9.15",
|
||||||
"file-saver": "^2.0.2",
|
"file-saver": "^2.0.2",
|
||||||
"has-own-prop": "^2.0.0",
|
"has-own-prop": "^2.0.0",
|
||||||
"hjson": "^3.2.1",
|
"hjson": "^3.2.1",
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { isDisabled, LookupEditDialog } from './lookup-edit-dialog';
|
import { isLookupSubmitDisabled, LookupEditDialog } from './lookup-edit-dialog';
|
||||||
|
|
||||||
describe('lookup edit dialog', () => {
|
describe('lookup edit dialog', () => {
|
||||||
it('matches snapshot', () => {
|
it('matches snapshot', () => {
|
||||||
@ -43,44 +43,46 @@ describe('lookup edit dialog', () => {
|
|||||||
|
|
||||||
describe('Type Map Should be disabled', () => {
|
describe('Type Map Should be disabled', () => {
|
||||||
it('Missing LookupName', () => {
|
it('Missing LookupName', () => {
|
||||||
expect(isDisabled(undefined, 'v1', '__default', { type: '' })).toBe(true);
|
expect(isLookupSubmitDisabled(undefined, 'v1', '__default', { type: '' })).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Empty version', () => {
|
it('Empty version', () => {
|
||||||
expect(isDisabled('lookup', '', '__default', { type: '' })).toBe(true);
|
expect(isLookupSubmitDisabled('lookup', '', '__default', { type: '' })).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Missing version', () => {
|
it('Missing version', () => {
|
||||||
expect(isDisabled('lookup', undefined, '__default', { type: '' })).toBe(true);
|
expect(isLookupSubmitDisabled('lookup', undefined, '__default', { type: '' })).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Empty tier', () => {
|
it('Empty tier', () => {
|
||||||
expect(isDisabled('lookup', 'v1', '', { type: '' })).toBe(true);
|
expect(isLookupSubmitDisabled('lookup', 'v1', '', { type: '' })).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Missing tier', () => {
|
it('Missing tier', () => {
|
||||||
expect(isDisabled('lookup', 'v1', undefined, { type: '' })).toBe(true);
|
expect(isLookupSubmitDisabled('lookup', 'v1', undefined, { type: '' })).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Missing spec', () => {
|
it('Missing spec', () => {
|
||||||
expect(isDisabled('lookup', 'v1', '__default', {})).toBe(true);
|
expect(isLookupSubmitDisabled('lookup', 'v1', '__default', {})).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Type undefined', () => {
|
it('Type undefined', () => {
|
||||||
expect(isDisabled('lookup', 'v1', '__default', { type: undefined })).toBe(true);
|
expect(isLookupSubmitDisabled('lookup', 'v1', '__default', { type: undefined })).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Lookup of type map with no map', () => {
|
it('Lookup of type map with no map', () => {
|
||||||
expect(isDisabled('lookup', 'v1', '__default', { type: 'map' })).toBe(true);
|
expect(isLookupSubmitDisabled('lookup', 'v1', '__default', { type: 'map' })).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Lookup of type cachedNamespace with no extractionNamespace', () => {
|
it('Lookup of type cachedNamespace with no extractionNamespace', () => {
|
||||||
expect(isDisabled('lookup', 'v1', '__default', { type: 'cachedNamespace' })).toBe(true);
|
expect(isLookupSubmitDisabled('lookup', 'v1', '__default', { type: 'cachedNamespace' })).toBe(
|
||||||
|
true,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Lookup of type cachedNamespace with extractionNamespace type uri, format csv, no namespaceParseSpec', () => {
|
it('Lookup of type cachedNamespace with extractionNamespace type uri, format csv, no namespaceParseSpec', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'uri',
|
type: 'uri',
|
||||||
@ -94,7 +96,7 @@ describe('Type Map Should be disabled', () => {
|
|||||||
|
|
||||||
it('Lookup of type cachedNamespace with extractionNamespace type uri, format csv, no columns and skipHeaderRows', () => {
|
it('Lookup of type cachedNamespace with extractionNamespace type uri, format csv, no columns and skipHeaderRows', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'uri',
|
type: 'uri',
|
||||||
@ -111,7 +113,7 @@ describe('Type Map Should be disabled', () => {
|
|||||||
|
|
||||||
it('Lookup of type cachedNamespace with extractionNamespace type uri, format tsv, no columns', () => {
|
it('Lookup of type cachedNamespace with extractionNamespace type uri, format tsv, no columns', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'uri',
|
type: 'uri',
|
||||||
@ -129,7 +131,7 @@ describe('Type Map Should be disabled', () => {
|
|||||||
|
|
||||||
it('Lookup of type cachedNamespace with extractionNamespace type customJson, format tsv, no keyFieldName', () => {
|
it('Lookup of type cachedNamespace with extractionNamespace type customJson, format tsv, no keyFieldName', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'uri',
|
type: 'uri',
|
||||||
@ -147,7 +149,7 @@ describe('Type Map Should be disabled', () => {
|
|||||||
|
|
||||||
it('Lookup of type cachedNamespace with extractionNamespace type customJson, format customJson, no valueFieldName', () => {
|
it('Lookup of type cachedNamespace with extractionNamespace type customJson, format customJson, no valueFieldName', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'uri',
|
type: 'uri',
|
||||||
@ -166,13 +168,15 @@ describe('Type Map Should be disabled', () => {
|
|||||||
|
|
||||||
describe('Type cachedNamespace should be disabled', () => {
|
describe('Type cachedNamespace should be disabled', () => {
|
||||||
it('No extractionNamespace', () => {
|
it('No extractionNamespace', () => {
|
||||||
expect(isDisabled('lookup', 'v1', '__default', { type: 'cachedNamespace' })).toBe(true);
|
expect(isLookupSubmitDisabled('lookup', 'v1', '__default', { type: 'cachedNamespace' })).toBe(
|
||||||
|
true,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('ExtractionNamespace type URI', () => {
|
describe('ExtractionNamespace type URI', () => {
|
||||||
it('Format csv, no namespaceParseSpec', () => {
|
it('Format csv, no namespaceParseSpec', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'uri',
|
type: 'uri',
|
||||||
@ -186,7 +190,7 @@ describe('Type cachedNamespace should be disabled', () => {
|
|||||||
|
|
||||||
it('Format csv, no columns and skipHeaderRows', () => {
|
it('Format csv, no columns and skipHeaderRows', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'uri',
|
type: 'uri',
|
||||||
@ -203,7 +207,7 @@ describe('Type cachedNamespace should be disabled', () => {
|
|||||||
|
|
||||||
it('Format tsv, no columns', () => {
|
it('Format tsv, no columns', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'uri',
|
type: 'uri',
|
||||||
@ -221,7 +225,7 @@ describe('Type cachedNamespace should be disabled', () => {
|
|||||||
|
|
||||||
it('Format tsv, no keyFieldName', () => {
|
it('Format tsv, no keyFieldName', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'uri',
|
type: 'uri',
|
||||||
@ -239,7 +243,7 @@ describe('Type cachedNamespace should be disabled', () => {
|
|||||||
|
|
||||||
it('Format customJson, no valueFieldName', () => {
|
it('Format customJson, no valueFieldName', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'uri',
|
type: 'uri',
|
||||||
@ -259,7 +263,7 @@ describe('Type cachedNamespace should be disabled', () => {
|
|||||||
describe('ExtractionNamespace type JDBC', () => {
|
describe('ExtractionNamespace type JDBC', () => {
|
||||||
it('No namespace', () => {
|
it('No namespace', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'jdbc',
|
type: 'jdbc',
|
||||||
@ -282,7 +286,7 @@ describe('Type cachedNamespace should be disabled', () => {
|
|||||||
|
|
||||||
it('No connectorConfig', () => {
|
it('No connectorConfig', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'jdbc',
|
type: 'jdbc',
|
||||||
@ -300,7 +304,7 @@ describe('Type cachedNamespace should be disabled', () => {
|
|||||||
|
|
||||||
it('No table', () => {
|
it('No table', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'jdbc',
|
type: 'jdbc',
|
||||||
@ -323,7 +327,7 @@ describe('Type cachedNamespace should be disabled', () => {
|
|||||||
|
|
||||||
it('No keyColumn', () => {
|
it('No keyColumn', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'jdbc',
|
type: 'jdbc',
|
||||||
@ -346,7 +350,7 @@ describe('Type cachedNamespace should be disabled', () => {
|
|||||||
|
|
||||||
it('No keyColumn', () => {
|
it('No keyColumn', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'jdbc',
|
type: 'jdbc',
|
||||||
@ -371,7 +375,9 @@ describe('Type cachedNamespace should be disabled', () => {
|
|||||||
|
|
||||||
describe('Type Map Should be enabled', () => {
|
describe('Type Map Should be enabled', () => {
|
||||||
it('Has type and has Map', () => {
|
it('Has type and has Map', () => {
|
||||||
expect(isDisabled('lookup', 'v1', '__default', { type: 'map', map: { a: 'b' } })).toBe(false);
|
expect(
|
||||||
|
isLookupSubmitDisabled('lookup', 'v1', '__default', { type: 'map', map: { a: 'b' } }),
|
||||||
|
).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -379,7 +385,7 @@ describe('Type cachedNamespace Should be enabled', () => {
|
|||||||
describe('ExtractionNamespace type URI', () => {
|
describe('ExtractionNamespace type URI', () => {
|
||||||
it('Format csv with columns', () => {
|
it('Format csv with columns', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'uri',
|
type: 'uri',
|
||||||
@ -396,7 +402,7 @@ describe('Type cachedNamespace Should be enabled', () => {
|
|||||||
|
|
||||||
it('Format csv with skipHeaderRows', () => {
|
it('Format csv with skipHeaderRows', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'uri',
|
type: 'uri',
|
||||||
@ -413,7 +419,7 @@ describe('Type cachedNamespace Should be enabled', () => {
|
|||||||
|
|
||||||
it('Format tsv, only columns', () => {
|
it('Format tsv, only columns', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'uri',
|
type: 'uri',
|
||||||
@ -430,7 +436,7 @@ describe('Type cachedNamespace Should be enabled', () => {
|
|||||||
|
|
||||||
it('Format tsv, keyFieldName and valueFieldName', () => {
|
it('Format tsv, keyFieldName and valueFieldName', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'uri',
|
type: 'uri',
|
||||||
@ -450,7 +456,7 @@ describe('Type cachedNamespace Should be enabled', () => {
|
|||||||
describe('ExtractionNamespace type JDBC', () => {
|
describe('ExtractionNamespace type JDBC', () => {
|
||||||
it('No namespace', () => {
|
it('No namespace', () => {
|
||||||
expect(
|
expect(
|
||||||
isDisabled('lookup', 'v1', '__default', {
|
isLookupSubmitDisabled('lookup', 'v1', '__default', {
|
||||||
type: 'cachedNamespace',
|
type: 'cachedNamespace',
|
||||||
extractionNamespace: {
|
extractionNamespace: {
|
||||||
type: 'jdbc',
|
type: 'jdbc',
|
||||||
|
@ -76,7 +76,7 @@ export interface LookupSpec {
|
|||||||
export interface LookupEditDialogProps {
|
export interface LookupEditDialogProps {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onSubmit: (updateLookupVersion: boolean) => void;
|
onSubmit: (updateLookupVersion: boolean) => void;
|
||||||
onChange: (field: string, value: string | LookupSpec) => void;
|
onChange: (field: 'name' | 'tier' | 'version' | 'spec', value: string | LookupSpec) => void;
|
||||||
lookupName: string;
|
lookupName: string;
|
||||||
lookupTier: string;
|
lookupTier: string;
|
||||||
lookupVersion: string;
|
lookupVersion: string;
|
||||||
@ -85,11 +85,11 @@ export interface LookupEditDialogProps {
|
|||||||
allLookupTiers: string[];
|
allLookupTiers: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isDisabled(
|
export function isLookupSubmitDisabled(
|
||||||
lookupName?: string,
|
lookupName: string | undefined,
|
||||||
lookupVersion?: string,
|
lookupVersion: string | undefined,
|
||||||
lookupTier?: string,
|
lookupTier: string | undefined,
|
||||||
lookupSpec?: LookupSpec,
|
lookupSpec: LookupSpec | undefined,
|
||||||
) {
|
) {
|
||||||
let disableSubmit =
|
let disableSubmit =
|
||||||
!lookupName ||
|
!lookupName ||
|
||||||
@ -141,6 +141,405 @@ export function isDisabled(
|
|||||||
}
|
}
|
||||||
return disableSubmit;
|
return disableSubmit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LOOKUP_FIELDS: Field<LookupSpec>[] = [
|
||||||
|
{
|
||||||
|
name: 'type',
|
||||||
|
type: 'string',
|
||||||
|
suggestions: ['map', 'cachedNamespace'],
|
||||||
|
adjustment: (model: LookupSpec) => {
|
||||||
|
if (model.type === 'map' && model.extractionNamespace && model.extractionNamespace.type) {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
model.extractionNamespace = { type: 'uri', namespaceParseSpec: { format: 'csv' } };
|
||||||
|
return model;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'map',
|
||||||
|
type: 'json',
|
||||||
|
defined: (model: LookupSpec) => {
|
||||||
|
return model.type === 'map';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.type',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Globally cached lookup type',
|
||||||
|
placeholder: 'uri',
|
||||||
|
suggestions: ['uri', 'jdbc'],
|
||||||
|
defined: (model: LookupSpec) => model.type === 'cachedNamespace',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.uriPrefix',
|
||||||
|
type: 'string',
|
||||||
|
label: 'URI prefix',
|
||||||
|
info:
|
||||||
|
'A URI which specifies a directory (or other searchable resource) in which to search for files',
|
||||||
|
placeholder: 's3://bucket/some/key/prefix/',
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'uri',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.fileRegex',
|
||||||
|
type: 'string',
|
||||||
|
label: 'File regex',
|
||||||
|
placeholder: '(optional)',
|
||||||
|
info:
|
||||||
|
'Optional regex for matching the file name under uriPrefix. Only used if uriPrefix is used',
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'uri',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.namespaceParseSpec.format',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Format',
|
||||||
|
defaultValue: 'csv',
|
||||||
|
suggestions: ['csv', 'tsv', 'customJson', 'simpleJson'],
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
Boolean(
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'uri',
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.namespaceParseSpec.columns',
|
||||||
|
type: 'string-array',
|
||||||
|
label: 'Columns',
|
||||||
|
placeholder: `["key", "value"]`,
|
||||||
|
info: 'The list of columns in the csv file',
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
Boolean(
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'uri' &&
|
||||||
|
model.extractionNamespace.namespaceParseSpec &&
|
||||||
|
(model.extractionNamespace.namespaceParseSpec.format === 'csv' ||
|
||||||
|
model.extractionNamespace.namespaceParseSpec.format === 'tsv'),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.namespaceParseSpec.keyColumn',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Key column',
|
||||||
|
placeholder: 'Key',
|
||||||
|
info: 'The name of the column containing the key',
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
Boolean(
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'uri' &&
|
||||||
|
model.extractionNamespace.namespaceParseSpec &&
|
||||||
|
(model.extractionNamespace.namespaceParseSpec.format === 'csv' ||
|
||||||
|
model.extractionNamespace.namespaceParseSpec.format === 'tsv'),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.namespaceParseSpec.valueColumn',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Value column',
|
||||||
|
placeholder: 'Value',
|
||||||
|
info: 'The name of the column containing the value',
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
Boolean(
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'uri' &&
|
||||||
|
model.extractionNamespace.namespaceParseSpec &&
|
||||||
|
(model.extractionNamespace.namespaceParseSpec.format === 'csv' ||
|
||||||
|
model.extractionNamespace.namespaceParseSpec.format === 'tsv'),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.namespaceParseSpec.hasHeaderRow',
|
||||||
|
type: 'boolean',
|
||||||
|
label: 'Has header row',
|
||||||
|
defaultValue: false,
|
||||||
|
info: `A flag to indicate that column information can be extracted from the input files' header row`,
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
Boolean(
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'uri' &&
|
||||||
|
model.extractionNamespace.namespaceParseSpec &&
|
||||||
|
(model.extractionNamespace.namespaceParseSpec.format === 'csv' ||
|
||||||
|
model.extractionNamespace.namespaceParseSpec.format === 'tsv'),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.namespaceParseSpec.skipHeaderRows',
|
||||||
|
type: 'number',
|
||||||
|
label: 'Skip header rows',
|
||||||
|
placeholder: '(optional)',
|
||||||
|
info: `Number of header rows to be skipped. The default number of header rows to be skipped is 0.`,
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
Boolean(
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'uri' &&
|
||||||
|
model.extractionNamespace.namespaceParseSpec &&
|
||||||
|
(model.extractionNamespace.namespaceParseSpec.format === 'csv' ||
|
||||||
|
model.extractionNamespace.namespaceParseSpec.format === 'tsv'),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.namespaceParseSpec.delimiter',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Delimiter',
|
||||||
|
placeholder: `(optional)`,
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
Boolean(
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'uri' &&
|
||||||
|
model.extractionNamespace.namespaceParseSpec &&
|
||||||
|
model.extractionNamespace.namespaceParseSpec.format === 'tsv',
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.namespaceParseSpec.listDelimiter',
|
||||||
|
type: 'string',
|
||||||
|
label: 'List delimiter',
|
||||||
|
placeholder: `(optional)`,
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
Boolean(
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'uri' &&
|
||||||
|
model.extractionNamespace.namespaceParseSpec &&
|
||||||
|
model.extractionNamespace.namespaceParseSpec.format === 'tsv',
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.namespaceParseSpec.keyFieldName',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Key field name',
|
||||||
|
placeholder: `key`,
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
Boolean(
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'uri' &&
|
||||||
|
model.extractionNamespace.namespaceParseSpec &&
|
||||||
|
model.extractionNamespace.namespaceParseSpec.format === 'customJson',
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.namespaceParseSpec.valueFieldName',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Value field name',
|
||||||
|
placeholder: `value`,
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
Boolean(
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'uri' &&
|
||||||
|
model.extractionNamespace.namespaceParseSpec &&
|
||||||
|
model.extractionNamespace.namespaceParseSpec.format === 'customJson',
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.namespace',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Namespace',
|
||||||
|
placeholder: 'some_lookup',
|
||||||
|
info: (
|
||||||
|
<>
|
||||||
|
<p>The namespace value in the SQL query:</p>
|
||||||
|
<p>
|
||||||
|
SELECT keyColumn, valueColumn, tsColumn? FROM <strong>namespace</strong>.table WHERE
|
||||||
|
filter
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'jdbc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.connectorConfig.createTables',
|
||||||
|
type: 'boolean',
|
||||||
|
label: 'CreateTables',
|
||||||
|
info: 'Defines the connectURI value on the The connector config to used',
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'jdbc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.connectorConfig.connectURI',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Connect URI',
|
||||||
|
info: 'Defines the connectURI value on the The connector config to used',
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'jdbc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.connectorConfig.user',
|
||||||
|
type: 'string',
|
||||||
|
label: 'User',
|
||||||
|
info: 'Defines the user to be used by the connector config',
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'jdbc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.connectorConfig.password',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Password',
|
||||||
|
info: 'Defines the password to be used by the connector config',
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'jdbc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.table',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Table',
|
||||||
|
placeholder: 'some_lookup_table',
|
||||||
|
info: (
|
||||||
|
<>
|
||||||
|
<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>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'jdbc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.keyColumn',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Key column',
|
||||||
|
placeholder: 'my_key_value',
|
||||||
|
info: (
|
||||||
|
<>
|
||||||
|
<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>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'jdbc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.valueColumn',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Value column',
|
||||||
|
placeholder: 'my_column_value',
|
||||||
|
info: (
|
||||||
|
<>
|
||||||
|
<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>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'jdbc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.filter',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Filter',
|
||||||
|
placeholder: '(optional)',
|
||||||
|
info: (
|
||||||
|
<>
|
||||||
|
<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>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'jdbc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.tsColumn',
|
||||||
|
type: 'string',
|
||||||
|
label: 'TsColumn',
|
||||||
|
placeholder: '(optional)',
|
||||||
|
info: (
|
||||||
|
<>
|
||||||
|
<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>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'jdbc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'extractionNamespace.pollPeriod',
|
||||||
|
type: 'string',
|
||||||
|
label: 'Poll period',
|
||||||
|
placeholder: '(optional)',
|
||||||
|
info: `Period between polling for updates`,
|
||||||
|
defined: (model: LookupSpec) =>
|
||||||
|
model.type === 'cachedNamespace' &&
|
||||||
|
!!model.extractionNamespace &&
|
||||||
|
model.extractionNamespace.type === 'uri',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'firstCacheTimeout',
|
||||||
|
type: 'number',
|
||||||
|
label: 'First cache timeout',
|
||||||
|
placeholder: '(optional)',
|
||||||
|
info: `How long to wait (in ms) for the first run of the cache to populate. 0 indicates to not wait`,
|
||||||
|
defined: (model: LookupSpec) => model.type === 'cachedNamespace',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'injective',
|
||||||
|
type: 'boolean',
|
||||||
|
defaultValue: false,
|
||||||
|
info: `If the underlying map is injective (keys and values are unique) then optimizations can occur internally by setting this to true`,
|
||||||
|
defined: (model: LookupSpec) => model.type === 'cachedNamespace',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export const LookupEditDialog = React.memo(function LookupEditDialog(props: LookupEditDialogProps) {
|
export const LookupEditDialog = React.memo(function LookupEditDialog(props: LookupEditDialogProps) {
|
||||||
const {
|
const {
|
||||||
onClose,
|
onClose,
|
||||||
@ -159,7 +558,7 @@ export const LookupEditDialog = React.memo(function LookupEditDialog(props: Look
|
|||||||
function addISOVersion() {
|
function addISOVersion() {
|
||||||
const currentDate = new Date();
|
const currentDate = new Date();
|
||||||
const ISOString = currentDate.toISOString();
|
const ISOString = currentDate.toISOString();
|
||||||
onChange('lookupEditVersion', ISOString);
|
onChange('version', ISOString);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderTierInput() {
|
function renderTierInput() {
|
||||||
@ -170,7 +569,7 @@ export const LookupEditDialog = React.memo(function LookupEditDialog(props: Look
|
|||||||
value={lookupTier}
|
value={lookupTier}
|
||||||
onChange={(e: any) => {
|
onChange={(e: any) => {
|
||||||
updateVersionOnSubmit = false;
|
updateVersionOnSubmit = false;
|
||||||
onChange('lookupEditTier', e.target.value);
|
onChange('tier', e.target.value);
|
||||||
}}
|
}}
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
@ -182,7 +581,7 @@ export const LookupEditDialog = React.memo(function LookupEditDialog(props: Look
|
|||||||
<HTMLSelect
|
<HTMLSelect
|
||||||
disabled={isEdit}
|
disabled={isEdit}
|
||||||
value={lookupTier}
|
value={lookupTier}
|
||||||
onChange={(e: any) => onChange('lookupEditTier', e.target.value)}
|
onChange={(e: any) => onChange('tier', e.target.value)}
|
||||||
>
|
>
|
||||||
{allLookupTiers.map(tier => (
|
{allLookupTiers.map(tier => (
|
||||||
<option key={tier} value={tier}>
|
<option key={tier} value={tier}>
|
||||||
@ -195,384 +594,6 @@ export const LookupEditDialog = React.memo(function LookupEditDialog(props: Look
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fields = [
|
|
||||||
{
|
|
||||||
name: 'type',
|
|
||||||
type: 'string',
|
|
||||||
suggestions: ['map', 'cachedNamespace'],
|
|
||||||
adjustment: (model: LookupSpec) => {
|
|
||||||
if (model.type === 'map' && model.extractionNamespace && model.extractionNamespace.type) {
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
model.extractionNamespace = { type: 'uri', namespaceParseSpec: { format: 'csv' } };
|
|
||||||
return model;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'map',
|
|
||||||
type: 'json',
|
|
||||||
defined: (model: LookupSpec) => {
|
|
||||||
return model.type === 'map';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.type',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Globally cached lookup type',
|
|
||||||
placeholder: 'uri',
|
|
||||||
suggestions: ['uri', 'jdbc'],
|
|
||||||
defined: (model: LookupSpec) => model.type === 'cachedNamespace',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.uriPrefix',
|
|
||||||
type: 'string',
|
|
||||||
label: 'URI prefix',
|
|
||||||
info:
|
|
||||||
'A URI which specifies a directory (or other searchable resource) in which to search for files',
|
|
||||||
placeholder: 's3://bucket/some/key/prefix/',
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'uri',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.fileRegex',
|
|
||||||
type: 'string',
|
|
||||||
label: 'File regex',
|
|
||||||
placeholder: '(optional)',
|
|
||||||
info:
|
|
||||||
'Optional regex for matching the file name under uriPrefix. Only used if uriPrefix is used',
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'uri',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.namespaceParseSpec.format',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Format',
|
|
||||||
defaultValue: 'csv',
|
|
||||||
suggestions: ['csv', 'tsv', 'customJson', 'simpleJson'],
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'uri',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.namespaceParseSpec.columns',
|
|
||||||
type: 'string-array',
|
|
||||||
label: 'Columns',
|
|
||||||
placeholder: `["key", "value"]`,
|
|
||||||
info: 'The list of columns in the csv file',
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'uri' &&
|
|
||||||
model.extractionNamespace.namespaceParseSpec &&
|
|
||||||
(model.extractionNamespace.namespaceParseSpec.format === 'csv' ||
|
|
||||||
model.extractionNamespace.namespaceParseSpec.format === 'tsv'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.namespaceParseSpec.keyColumn',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Key column',
|
|
||||||
placeholder: 'Key',
|
|
||||||
info: 'The name of the column containing the key',
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'uri' &&
|
|
||||||
model.extractionNamespace.namespaceParseSpec &&
|
|
||||||
(model.extractionNamespace.namespaceParseSpec.format === 'csv' ||
|
|
||||||
model.extractionNamespace.namespaceParseSpec.format === 'tsv'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.namespaceParseSpec.valueColumn',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Value column',
|
|
||||||
placeholder: 'Value',
|
|
||||||
info: 'The name of the column containing the value',
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'uri' &&
|
|
||||||
model.extractionNamespace.namespaceParseSpec &&
|
|
||||||
(model.extractionNamespace.namespaceParseSpec.format === 'csv' ||
|
|
||||||
model.extractionNamespace.namespaceParseSpec.format === 'tsv'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.namespaceParseSpec.hasHeaderRow',
|
|
||||||
type: 'boolean',
|
|
||||||
label: 'Has header row',
|
|
||||||
defaultValue: false,
|
|
||||||
info: `A flag to indicate that column information can be extracted from the input files' header row`,
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'uri' &&
|
|
||||||
model.extractionNamespace.namespaceParseSpec &&
|
|
||||||
(model.extractionNamespace.namespaceParseSpec.format === 'csv' ||
|
|
||||||
model.extractionNamespace.namespaceParseSpec.format === 'tsv'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.namespaceParseSpec.skipHeaderRows',
|
|
||||||
type: 'number',
|
|
||||||
label: 'Skip header rows',
|
|
||||||
placeholder: '(optional)',
|
|
||||||
info: `Number of header rows to be skipped. The default number of header rows to be skipped is 0.`,
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'uri' &&
|
|
||||||
model.extractionNamespace.namespaceParseSpec &&
|
|
||||||
(model.extractionNamespace.namespaceParseSpec.format === 'csv' ||
|
|
||||||
model.extractionNamespace.namespaceParseSpec.format === 'tsv'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.namespaceParseSpec.delimiter',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Delimiter',
|
|
||||||
placeholder: `(optional)`,
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'uri' &&
|
|
||||||
model.extractionNamespace.namespaceParseSpec &&
|
|
||||||
model.extractionNamespace.namespaceParseSpec.format === 'tsv',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.namespaceParseSpec.listDelimiter',
|
|
||||||
type: 'string',
|
|
||||||
label: 'List delimiter',
|
|
||||||
placeholder: `(optional)`,
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'uri' &&
|
|
||||||
model.extractionNamespace.namespaceParseSpec &&
|
|
||||||
model.extractionNamespace.namespaceParseSpec.format === 'tsv',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.namespaceParseSpec.keyFieldName',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Key field name',
|
|
||||||
placeholder: `key`,
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'uri' &&
|
|
||||||
model.extractionNamespace.namespaceParseSpec &&
|
|
||||||
model.extractionNamespace.namespaceParseSpec.format === 'customJson',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.namespaceParseSpec.valueFieldName',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Value field name',
|
|
||||||
placeholder: `value`,
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'uri' &&
|
|
||||||
model.extractionNamespace.namespaceParseSpec &&
|
|
||||||
model.extractionNamespace.namespaceParseSpec.format === 'customJson',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.namespace',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Namespace',
|
|
||||||
placeholder: 'some_lookup',
|
|
||||||
info: (
|
|
||||||
<>
|
|
||||||
<p>The namespace value in the SQL query:</p>
|
|
||||||
<p>
|
|
||||||
SELECT keyColumn, valueColumn, tsColumn? FROM <strong>namespace</strong>.table WHERE
|
|
||||||
filter
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'jdbc',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.connectorConfig.createTables',
|
|
||||||
type: 'boolean',
|
|
||||||
label: 'CreateTables',
|
|
||||||
info: 'Defines the connectURI value on the The connector config to used',
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'jdbc',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.connectorConfig.connectURI',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Connect URI',
|
|
||||||
info: 'Defines the connectURI value on the The connector config to used',
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'jdbc',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.connectorConfig.user',
|
|
||||||
type: 'string',
|
|
||||||
label: 'User',
|
|
||||||
info: 'Defines the user to be used by the connector config',
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'jdbc',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.connectorConfig.password',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Password',
|
|
||||||
info: 'Defines the password to be used by the connector config',
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'jdbc',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.table',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Table',
|
|
||||||
placeholder: 'some_lookup_table',
|
|
||||||
info: (
|
|
||||||
<>
|
|
||||||
<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>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'jdbc',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.keyColumn',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Key column',
|
|
||||||
placeholder: 'my_key_value',
|
|
||||||
info: (
|
|
||||||
<>
|
|
||||||
<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>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'jdbc',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.valueColumn',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Value column',
|
|
||||||
placeholder: 'my_column_value',
|
|
||||||
info: (
|
|
||||||
<>
|
|
||||||
<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>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'jdbc',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.filter',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Filter',
|
|
||||||
placeholder: '(optional)',
|
|
||||||
info: (
|
|
||||||
<>
|
|
||||||
<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>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'jdbc',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.tsColumn',
|
|
||||||
type: 'string',
|
|
||||||
label: 'TsColumn',
|
|
||||||
placeholder: '(optional)',
|
|
||||||
info: (
|
|
||||||
<>
|
|
||||||
<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>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'jdbc',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extractionNamespace.pollPeriod',
|
|
||||||
type: 'string',
|
|
||||||
label: 'Poll period',
|
|
||||||
placeholder: '(optional)',
|
|
||||||
info: `Period between polling for updates`,
|
|
||||||
defined: (model: LookupSpec) =>
|
|
||||||
model.type === 'cachedNamespace' &&
|
|
||||||
!!model.extractionNamespace &&
|
|
||||||
model.extractionNamespace.type === 'uri',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'firstCacheTimeout',
|
|
||||||
type: 'number',
|
|
||||||
label: 'First cache timeout',
|
|
||||||
placeholder: '(optional)',
|
|
||||||
info: `How long to wait (in ms) for the first run of the cache to populate. 0 indicates to not wait`,
|
|
||||||
defined: (model: LookupSpec) => model.type === 'cachedNamespace',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'injective',
|
|
||||||
type: 'boolean',
|
|
||||||
defaultValue: false,
|
|
||||||
info: `If the underlying map is injective (keys and values are unique) then optimizations can occur internally by setting this to true`,
|
|
||||||
defined: (model: LookupSpec) => model.type === 'cachedNamespace',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
className="lookup-edit-dialog"
|
className="lookup-edit-dialog"
|
||||||
@ -583,7 +604,7 @@ export const LookupEditDialog = React.memo(function LookupEditDialog(props: Look
|
|||||||
<FormGroup className="lookup-label" label="Name">
|
<FormGroup className="lookup-label" label="Name">
|
||||||
<InputGroup
|
<InputGroup
|
||||||
value={lookupName}
|
value={lookupName}
|
||||||
onChange={(e: any) => onChange('lookupEditName', e.target.value)}
|
onChange={(e: any) => onChange('name', e.target.value)}
|
||||||
disabled={isEdit}
|
disabled={isEdit}
|
||||||
placeholder="Enter the lookup name"
|
placeholder="Enter the lookup name"
|
||||||
/>
|
/>
|
||||||
@ -592,7 +613,7 @@ export const LookupEditDialog = React.memo(function LookupEditDialog(props: Look
|
|||||||
<FormGroup className="lookup-label" label="Version">
|
<FormGroup className="lookup-label" label="Version">
|
||||||
<InputGroup
|
<InputGroup
|
||||||
value={lookupVersion}
|
value={lookupVersion}
|
||||||
onChange={(e: any) => onChange('lookupEditVersion', e.target.value)}
|
onChange={(e: any) => onChange('version', e.target.value)}
|
||||||
placeholder="Enter the lookup version"
|
placeholder="Enter the lookup version"
|
||||||
rightElement={
|
rightElement={
|
||||||
<Button minimal text="Use ISO as version" onClick={() => addISOVersion()} />
|
<Button minimal text="Use ISO as version" onClick={() => addISOVersion()} />
|
||||||
@ -600,10 +621,10 @@ export const LookupEditDialog = React.memo(function LookupEditDialog(props: Look
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<AutoForm
|
<AutoForm
|
||||||
fields={fields as Field<LookupSpec>[]}
|
fields={LOOKUP_FIELDS}
|
||||||
model={lookupSpec}
|
model={lookupSpec}
|
||||||
onChange={m => {
|
onChange={m => {
|
||||||
onChange('lookupEditSpec', m);
|
onChange('spec', m);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className={Classes.DIALOG_FOOTER}>
|
<div className={Classes.DIALOG_FOOTER}>
|
||||||
@ -615,7 +636,7 @@ export const LookupEditDialog = React.memo(function LookupEditDialog(props: Look
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
onSubmit(updateVersionOnSubmit && isEdit);
|
onSubmit(updateVersionOnSubmit && isEdit);
|
||||||
}}
|
}}
|
||||||
disabled={isDisabled(lookupName, lookupVersion, lookupTier, lookupSpec)}
|
disabled={isLookupSubmitDisabled(lookupName, lookupVersion, lookupTier, lookupSpec)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,9 +16,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This is set to the latest available version and should be updated to the next version before release
|
|
||||||
import hasOwnProp from 'has-own-prop';
|
import hasOwnProp from 'has-own-prop';
|
||||||
|
|
||||||
|
// This is set to the latest available version and should be updated to the next version before release
|
||||||
const DRUID_DOCS_VERSION = '0.19.0';
|
const DRUID_DOCS_VERSION = '0.19.0';
|
||||||
|
|
||||||
function fillVersion(str: string): string {
|
function fillVersion(str: string): string {
|
||||||
|
@ -185,10 +185,10 @@ export class LookupsView extends React.PureComponent<LookupsViewProps, LookupsVi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleChangeLookup = (field: string, value: string | LookupSpec) => {
|
private handleChangeLookup = (field: keyof LookupEditInfo, value: string | LookupSpec) => {
|
||||||
this.setState({
|
this.setState(state => ({
|
||||||
[field]: value,
|
lookupEdit: Object.assign({}, state.lookupEdit, { [field]: value }),
|
||||||
} as any);
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
private async submitLookupEdit(updatelookupEditVersion: boolean) {
|
private async submitLookupEdit(updatelookupEditVersion: boolean) {
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`ColumnRenameInput matches snapshot 1`] = `
|
||||||
|
<Blueprint3.InputGroup
|
||||||
|
autoFocus={true}
|
||||||
|
className="column-rename-input"
|
||||||
|
onBlur={[Function]}
|
||||||
|
onChange={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
small={true}
|
||||||
|
value="hello"
|
||||||
|
/>
|
||||||
|
`;
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { ColumnRenameInput } from './column-rename-input';
|
||||||
|
|
||||||
|
describe('ColumnRenameInput', () => {
|
||||||
|
it('matches snapshot', () => {
|
||||||
|
const columnRenameInput = shallow(<ColumnRenameInput initialName="hello" onDone={() => {}} />);
|
||||||
|
|
||||||
|
expect(columnRenameInput).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { InputGroup } from '@blueprintjs/core';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
export interface ColumnRenameInputProps {
|
||||||
|
initialName: string;
|
||||||
|
onDone: (newName?: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ColumnRenameInput = React.memo(function ColumnRenameInput(
|
||||||
|
props: ColumnRenameInputProps,
|
||||||
|
) {
|
||||||
|
const { initialName, onDone } = props;
|
||||||
|
const [newName, setNewName] = useState<string>(initialName);
|
||||||
|
|
||||||
|
function maybeDone() {
|
||||||
|
if (newName && newName !== initialName) {
|
||||||
|
onDone(newName);
|
||||||
|
} else {
|
||||||
|
onDone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InputGroup
|
||||||
|
className="column-rename-input"
|
||||||
|
value={newName}
|
||||||
|
onChange={(e: any) => setNewName(e.target.value)}
|
||||||
|
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
switch (e.keyCode) {
|
||||||
|
case 13: // Enter
|
||||||
|
maybeDone();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 27: // Esc
|
||||||
|
onDone();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onBlur={maybeDone}
|
||||||
|
small
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
@ -24,35 +24,46 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
font-feature-settings: tnum;
|
font-feature-settings: tnum;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
|
|
||||||
|
.rt-thead {
|
||||||
|
.rt-th {
|
||||||
|
&.aggregate-header {
|
||||||
|
background: rgb(75, 122, 148);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.renaming {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.asc {
|
||||||
|
box-shadow: inset 0 3px 0 0 rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
box-shadow: inset 0 -3px 0 0 rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bp3-icon {
|
||||||
|
margin-left: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-td {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.clickable-cell {
|
.clickable-cell {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bp3-popover-target {
|
.bp3-popover-target {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.aggregate-column {
|
.aggregate-column {
|
||||||
background-color: rgba(98, 205, 255, 0.1);
|
background-color: rgba(98, 205, 255, 0.1);
|
||||||
}
|
}
|
||||||
.rt-th {
|
|
||||||
&.aggregate-header {
|
|
||||||
background: rgb(75, 122, 148);
|
|
||||||
}
|
|
||||||
|
|
||||||
.asc {
|
|
||||||
box-shadow: inset 0 3px 0 0 rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.desc {
|
|
||||||
box-shadow: inset 0 -3px 0 0 rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bp3-icon {
|
|
||||||
margin-left: 3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.rt-td {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,8 @@ import { ShowValueDialog } from '../../../dialogs/show-value-dialog/show-value-d
|
|||||||
import { copyAndAlert, prettyPrintSql } from '../../../utils';
|
import { copyAndAlert, prettyPrintSql } from '../../../utils';
|
||||||
import { BasicAction, basicActionsToMenu } from '../../../utils/basic-action';
|
import { BasicAction, basicActionsToMenu } from '../../../utils/basic-action';
|
||||||
|
|
||||||
|
import { ColumnRenameInput } from './column-rename-input/column-rename-input';
|
||||||
|
|
||||||
import './query-output.scss';
|
import './query-output.scss';
|
||||||
|
|
||||||
function isComparable(x: unknown): boolean {
|
function isComparable(x: unknown): boolean {
|
||||||
@ -59,9 +61,10 @@ export interface QueryOutputProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputProps) {
|
export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputProps) {
|
||||||
const { queryResult } = props;
|
const { queryResult, onQueryChange, runeMode } = props;
|
||||||
const parsedQuery = queryResult ? queryResult.sqlQuery : undefined;
|
const parsedQuery = queryResult ? queryResult.sqlQuery : undefined;
|
||||||
const [showValue, setShowValue] = useState();
|
const [showValue, setShowValue] = useState<string>();
|
||||||
|
const [renamingColumn, setRenamingColumn] = useState<number>(-1);
|
||||||
|
|
||||||
function hasFilterOnHeader(header: string, headerIndex: number): boolean {
|
function hasFilterOnHeader(header: string, headerIndex: number): boolean {
|
||||||
if (!parsedQuery || !parsedQuery.isRealOutputColumnAtSelectIndex(headerIndex)) return false;
|
if (!parsedQuery || !parsedQuery.isRealOutputColumnAtSelectIndex(headerIndex)) return false;
|
||||||
@ -73,7 +76,6 @@ export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputPro
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getHeaderMenu(header: string, headerIndex: number) {
|
function getHeaderMenu(header: string, headerIndex: number) {
|
||||||
const { onQueryChange, runeMode } = props;
|
|
||||||
const ref = SqlRef.column(header);
|
const ref = SqlRef.column(header);
|
||||||
const prettyRef = prettyPrintSql(ref);
|
const prettyRef = prettyPrintSql(ref);
|
||||||
|
|
||||||
@ -145,6 +147,16 @@ export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputPro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!parsedQuery.hasStarInSelect()) {
|
||||||
|
basicActions.push({
|
||||||
|
icon: IconNames.EDIT,
|
||||||
|
title: `Rename column`,
|
||||||
|
onAction: () => {
|
||||||
|
setRenamingColumn(headerIndex);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
basicActions.push({
|
basicActions.push({
|
||||||
icon: IconNames.CROSS,
|
icon: IconNames.CROSS,
|
||||||
title: `Remove column`,
|
title: `Remove column`,
|
||||||
@ -291,7 +303,7 @@ export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputPro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getHeaderClassName(header: string) {
|
function getHeaderClassName(header: string, i: number) {
|
||||||
if (!parsedQuery) return;
|
if (!parsedQuery) return;
|
||||||
|
|
||||||
const className = [];
|
const className = [];
|
||||||
@ -304,9 +316,31 @@ export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputPro
|
|||||||
className.push('aggregate-header');
|
className.push('aggregate-header');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i === renamingColumn) {
|
||||||
|
className.push('renaming');
|
||||||
|
}
|
||||||
|
|
||||||
return className.join(' ');
|
return className.join(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renameColumnTo(renameTo: string | undefined) {
|
||||||
|
setRenamingColumn(-1);
|
||||||
|
if (renameTo && parsedQuery) {
|
||||||
|
if (parsedQuery.hasStarInSelect()) return;
|
||||||
|
const selectExpression = parsedQuery.selectExpressions.get(renamingColumn);
|
||||||
|
if (!selectExpression) return;
|
||||||
|
onQueryChange(
|
||||||
|
parsedQuery.changeSelectExpressions(
|
||||||
|
parsedQuery.selectExpressions.change(
|
||||||
|
renamingColumn,
|
||||||
|
selectExpression.changeAliasName(renameTo),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="query-output">
|
<div className="query-output">
|
||||||
<ReactTable
|
<ReactTable
|
||||||
@ -316,17 +350,22 @@ export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputPro
|
|||||||
columns={(queryResult ? queryResult.header : []).map((column, i) => {
|
columns={(queryResult ? queryResult.header : []).map((column, i) => {
|
||||||
const h = column.name;
|
const h = column.name;
|
||||||
return {
|
return {
|
||||||
Header: () => {
|
Header:
|
||||||
return (
|
i === renamingColumn && parsedQuery
|
||||||
<Popover className={'clickable-cell'} content={getHeaderMenu(h, i)}>
|
? () => <ColumnRenameInput initialName={h} onDone={renameColumnTo} />
|
||||||
<div>
|
: () => {
|
||||||
{h}
|
return (
|
||||||
{hasFilterOnHeader(h, i) && <Icon icon={IconNames.FILTER} iconSize={14} />}
|
<Popover className={'clickable-cell'} content={getHeaderMenu(h, i)}>
|
||||||
</div>
|
<div>
|
||||||
</Popover>
|
{h}
|
||||||
);
|
{hasFilterOnHeader(h, i) && (
|
||||||
},
|
<Icon icon={IconNames.FILTER} iconSize={14} />
|
||||||
headerClassName: getHeaderClassName(h),
|
)}
|
||||||
|
</div>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
headerClassName: getHeaderClassName(h, i),
|
||||||
accessor: String(i),
|
accessor: String(i),
|
||||||
Cell: row => {
|
Cell: row => {
|
||||||
const value = row.value;
|
const value = row.value;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user