You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by fj...@apache.org on 2019/06/09 17:44:23 UTC
[incubator-druid] branch master updated: Web console: make the data
loader more responsive when sampling data with many columns (#7856)
This is an automated email from the ASF dual-hosted git repository.
fjy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-druid.git
The following commit(s) were added to refs/heads/master by this push:
new c3d230b Web console: make the data loader more responsive when sampling data with many columns (#7856)
c3d230b is described below
commit c3d230b35475fdfcdc7ed74f17dc02b46f13142b
Author: Vadim Ogievetsky <va...@gmail.com>
AuthorDate: Sun Jun 9 10:44:13 2019 -0700
Web console: make the data loader more responsive when sampling data with many columns (#7856)
* Don't rerender data loader tables
* removed unused imports
* removed extra console.log
* fix typo
---
web-console/script/mkcomp | 27 +-
web-console/src/bootstrap/react-table-defaults.tsx | 2 +-
.../src/components/action-cell/action-cell.tsx | 2 +-
.../src/components/action-icon/action-icon.tsx | 2 +-
.../src/components/array-input/array-input.tsx | 2 +-
.../components/center-message/center-message.tsx | 2 +-
.../components/clearable-input/clearable-input.tsx | 2 +-
.../src/components/external-link/external-link.tsx | 2 +-
web-console/src/components/index.ts | 1 -
.../src/components/menu-checkbox/menu-checkbox.tsx | 2 +-
.../src/components/table-cell/table-cell.tsx | 2 +-
.../view-control-bar/view-control-bar.tsx | 2 +-
.../__snapshots__/compaction-dialog.spec.tsx.snap | 4 +-
.../table-action-dialog/table-action-dialog.tsx | 2 +-
web-console/src/entry.ts | 5 +
web-console/src/utils/general.tsx | 18 +
web-console/src/utils/ingestion-spec.tsx | 16 +-
web-console/src/utils/sampler.ts | 2 +-
.../__snapshots__/filter-table.spec.tsx.snap | 1014 ++++++++++++++
.../load-data-view/filter-table/filter-table.scss} | 20 +-
.../filter-table/filter-table.spec.tsx} | 28 +-
.../load-data-view/filter-table/filter-table.tsx | 88 ++
.../src/views/load-data-view/load-data-view.scss | 41 -
.../src/views/load-data-view/load-data-view.tsx | 486 ++-----
.../__snapshots__/parse-data-table.spec.tsx.snap | 1476 ++++++++++++++++++++
.../parse-data-table/parse-data-table.scss} | 25 +-
.../parse-data-table/parse-data-table.spec.tsx} | 28 +-
.../parse-data-table/parse-data-table.tsx | 99 ++
.../__snapshots__/parse-time-table.spec.tsx.snap | 1014 ++++++++++++++
.../parse-time-table/parse-time-table.scss} | 12 +-
.../parse-time-table/parse-time-table.spec.tsx} | 31 +-
.../parse-time-table/parse-time-table.tsx | 105 ++
.../__snapshots__/schema-table.spec.tsx.snap | 1014 ++++++++++++++
.../load-data-view/schema-table/schema-table.scss} | 35 +-
.../schema-table/schema-table.spec.tsx} | 31 +-
.../load-data-view/schema-table/schema-table.tsx | 135 ++
.../__snapshots__/transform-table.spec.tsx.snap | 1014 ++++++++++++++
.../transform-table/transform-table.scss} | 20 +-
.../transform-table/transform-table.spec.tsx} | 28 +-
.../transform-table/transform-table.tsx | 92 ++
.../__snapshots__/sql-control.spec.tsx.snap | 2 +-
.../sql-view}/sql-control/sql-control.scss | 2 +-
.../sql-view}/sql-control/sql-control.spec.tsx | 0
.../sql-view}/sql-control/sql-control.tsx | 13 +-
web-console/src/views/sql-view/sql-view.tsx | 4 +-
45 files changed, 6420 insertions(+), 532 deletions(-)
diff --git a/web-console/script/mkcomp b/web-console/script/mkcomp
index a2b9bb5..5c60a80 100755
--- a/web-console/script/mkcomp
+++ b/web-console/script/mkcomp
@@ -17,24 +17,20 @@
* limitations under the License.
*/
-let fs = require('fs-extra');
+const fs = require('fs-extra');
if (!(process.argv.length === 3 || process.argv.length === 4)) {
- console.log('Usage: mkcomp <what?> <component-name>');
+ console.log('Usage: mkcomp <where?> <component-name>');
process.exit();
}
let name;
-let what;
+let where;
if (process.argv.length === 4) {
- what = process.argv[2];
+ where = process.argv[2];
name = process.argv[3];
- if (!(what === 'component' || what === 'dialog' || what === 'singleton')) {
- console.log(`Bad what, should be on of: component, dialog, singleton`);
- process.exit();
- }
} else {
- what = 'component';
+ where = 'components';
name = process.argv[2];
}
@@ -43,7 +39,7 @@ if (!/^([a-z-])+$/.test(name)) {
process.exit();
}
-let path = `./src/${what}s/${name}/`;
+const path = `./src/${where}/${name}/`;
fs.ensureDirSync(path);
console.log('Making path:', path);
@@ -85,7 +81,7 @@ writeFile(path + name + '.tsx',
import { Button, InputGroup } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import classNames from 'classnames';
-import * as React from 'react';
+import React from 'react';
import './${name}.scss';
@@ -95,7 +91,7 @@ export interface ${camelName}Props extends React.Props<any> {
export interface ${camelName}State {
}
-export class ${camelName} extends React.Component<${camelName}Props, ${camelName}State> {
+export class ${camelName} extends React.PureComponent<${camelName}Props, ${camelName}State> {
constructor(props: ${camelName}Props, context: any) {
super(props, context);
// this.state = {};
@@ -155,16 +151,17 @@ writeFile(path + name + '.spec.tsx',
* limitations under the License.
*/
-import * as React from 'react';
+import React from 'react';
import { render } from 'react-testing-library';
import { ${camelName} } from './${name}';
describe('${spaceName}', () => {
- it('action cell snapshot', () => {
+ it('matches snapshot', () => {
const ${snakeName} = <${camelName}
/>;
- const { container, getByText } = render(${snakeName});
+
+ const { container } = render(${snakeName});
expect(container.firstChild).toMatchSnapshot();
});
});
diff --git a/web-console/src/bootstrap/react-table-defaults.tsx b/web-console/src/bootstrap/react-table-defaults.tsx
index 5fb69e2..b39d6ec 100644
--- a/web-console/src/bootstrap/react-table-defaults.tsx
+++ b/web-console/src/bootstrap/react-table-defaults.tsx
@@ -19,7 +19,7 @@
import React from 'react';
import { Filter, ReactTableDefaults } from 'react-table';
-import { Loader } from '../components/loader/loader';
+import { Loader } from '../components';
import { booleanCustomTableFilter, countBy, makeTextFilter } from '../utils';
import { ReactTableCustomPagination } from './react-table-custom-pagination';
diff --git a/web-console/src/components/action-cell/action-cell.tsx b/web-console/src/components/action-cell/action-cell.tsx
index dbf4952..1daa5df 100644
--- a/web-console/src/components/action-cell/action-cell.tsx
+++ b/web-console/src/components/action-cell/action-cell.tsx
@@ -30,7 +30,7 @@ export interface ActionCellProps extends React.Props<any> {
actions?: BasicAction[];
}
-export class ActionCell extends React.PureComponent<ActionCellProps, {}> {
+export class ActionCell extends React.PureComponent<ActionCellProps> {
static COLUMN_ID = 'actions';
static COLUMN_LABEL = 'Actions';
static COLUMN_WIDTH = 70;
diff --git a/web-console/src/components/action-icon/action-icon.tsx b/web-console/src/components/action-icon/action-icon.tsx
index 669e285..eb67bfa 100644
--- a/web-console/src/components/action-icon/action-icon.tsx
+++ b/web-console/src/components/action-icon/action-icon.tsx
@@ -28,7 +28,7 @@ export interface ActionIconProps extends React.Props<any> {
onClick?: () => void;
}
-export class ActionIcon extends React.PureComponent<ActionIconProps, {}> {
+export class ActionIcon extends React.PureComponent<ActionIconProps> {
render() {
const { className, icon, onClick } = this.props;
diff --git a/web-console/src/components/array-input/array-input.tsx b/web-console/src/components/array-input/array-input.tsx
index 7a2d5d6..6e9f776 100644
--- a/web-console/src/components/array-input/array-input.tsx
+++ b/web-console/src/components/array-input/array-input.tsx
@@ -16,7 +16,7 @@
* limitations under the License.
*/
-import { ITagInputProps, TextArea } from '@blueprintjs/core';
+import { TextArea } from '@blueprintjs/core';
import React from 'react';
export interface ArrayInputProps {
diff --git a/web-console/src/components/center-message/center-message.tsx b/web-console/src/components/center-message/center-message.tsx
index dc9515b..bae0d89 100644
--- a/web-console/src/components/center-message/center-message.tsx
+++ b/web-console/src/components/center-message/center-message.tsx
@@ -23,7 +23,7 @@ import './center-message.scss';
export interface CenterMessageProps extends React.Props<any> {
}
-export class CenterMessage extends React.PureComponent<CenterMessageProps, {}> {
+export class CenterMessage extends React.PureComponent<CenterMessageProps> {
render() {
return <div className="center-message bp3-input">
<div className="center-message-inner">
diff --git a/web-console/src/components/clearable-input/clearable-input.tsx b/web-console/src/components/clearable-input/clearable-input.tsx
index 8682a5f..b695bbb 100644
--- a/web-console/src/components/clearable-input/clearable-input.tsx
+++ b/web-console/src/components/clearable-input/clearable-input.tsx
@@ -28,7 +28,7 @@ export interface ClearableInputProps extends React.Props<any> {
placeholder: string;
}
-export class ClearableInput extends React.PureComponent<ClearableInputProps, {}> {
+export class ClearableInput extends React.PureComponent<ClearableInputProps> {
render() {
const { className, value, onChange, placeholder } = this.props;
diff --git a/web-console/src/components/external-link/external-link.tsx b/web-console/src/components/external-link/external-link.tsx
index 229d3f7..9dc0562 100644
--- a/web-console/src/components/external-link/external-link.tsx
+++ b/web-console/src/components/external-link/external-link.tsx
@@ -22,7 +22,7 @@ export interface ExternalLinkProps extends React.Props<any> {
href: string;
}
-export class ExternalLink extends React.PureComponent<ExternalLinkProps, {}> {
+export class ExternalLink extends React.PureComponent<ExternalLinkProps> {
render() {
const { href, children } = this.props;
diff --git a/web-console/src/components/index.ts b/web-console/src/components/index.ts
index 6a706a7..063875a 100644
--- a/web-console/src/components/index.ts
+++ b/web-console/src/components/index.ts
@@ -30,7 +30,6 @@ export * from './table-cell/table-cell';
export * from './rule-editor/rule-editor';
export * from './show-json/show-json';
export * from './show-log/show-log';
-export * from './sql-control/sql-control';
export * from './table-column-selector/table-column-selector';
export * from './view-control-bar/view-control-bar';
export * from './clearable-input/clearable-input';
diff --git a/web-console/src/components/menu-checkbox/menu-checkbox.tsx b/web-console/src/components/menu-checkbox/menu-checkbox.tsx
index 659a78c..f5ea252 100644
--- a/web-console/src/components/menu-checkbox/menu-checkbox.tsx
+++ b/web-console/src/components/menu-checkbox/menu-checkbox.tsx
@@ -21,7 +21,7 @@ import React from 'react';
import './menu-checkbox.scss';
-export class MenuCheckbox extends React.PureComponent<ICheckboxProps, {}> {
+export class MenuCheckbox extends React.PureComponent<ICheckboxProps> {
render() {
return <li className="menu-checkbox">
diff --git a/web-console/src/components/table-cell/table-cell.tsx b/web-console/src/components/table-cell/table-cell.tsx
index 036a4da..767bb1a 100644
--- a/web-console/src/components/table-cell/table-cell.tsx
+++ b/web-console/src/components/table-cell/table-cell.tsx
@@ -39,7 +39,7 @@ interface ShortParts {
suffix: string;
}
-export class TableCell extends React.PureComponent<NullTableCellProps, {}> {
+export class TableCell extends React.PureComponent<NullTableCellProps> {
static MAX_CHARS_TO_SHOW = 50;
static possiblyTruncate(str: string): React.ReactNode {
diff --git a/web-console/src/components/view-control-bar/view-control-bar.tsx b/web-console/src/components/view-control-bar/view-control-bar.tsx
index bcd3e23..247004c 100644
--- a/web-console/src/components/view-control-bar/view-control-bar.tsx
+++ b/web-console/src/components/view-control-bar/view-control-bar.tsx
@@ -24,7 +24,7 @@ export interface ViewControlBarProps {
label: string;
}
-export class ViewControlBar extends React.PureComponent<ViewControlBarProps, {}> {
+export class ViewControlBar extends React.PureComponent<ViewControlBarProps> {
constructor(props: ViewControlBarProps) {
super(props);
}
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 1383230..5e8951c 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
@@ -352,7 +352,7 @@ exports[`compaction dialog matches snapshot 1`] = `
class="bp3-form-content"
>
<div
- class=" ace_editor ace-solarized-dark ace_dark"
+ class=" ace_editor ace-tm"
id="ace-editor"
style="width: 100%; height: 8vh;"
>
@@ -543,7 +543,7 @@ exports[`compaction dialog matches snapshot 1`] = `
class="bp3-form-content"
>
<div
- class=" ace_editor ace-solarized-dark ace_dark"
+ class=" ace_editor ace-tm"
id="ace-editor"
style="width: 100%; height: 8vh;"
>
diff --git a/web-console/src/dialogs/table-action-dialog/table-action-dialog.tsx b/web-console/src/dialogs/table-action-dialog/table-action-dialog.tsx
index 3719a07..11eab92 100644
--- a/web-console/src/dialogs/table-action-dialog/table-action-dialog.tsx
+++ b/web-console/src/dialogs/table-action-dialog/table-action-dialog.tsx
@@ -34,7 +34,7 @@ interface TableActionDialogProps extends IDialogProps {
bottomButtons?: React.ReactNode;
}
-export class TableActionDialog extends React.PureComponent<TableActionDialogProps, {}> {
+export class TableActionDialog extends React.PureComponent<TableActionDialogProps> {
constructor(props: TableActionDialogProps) {
super(props);
this.state = {};
diff --git a/web-console/src/entry.ts b/web-console/src/entry.ts
index b18a145..cd35da7 100644
--- a/web-console/src/entry.ts
+++ b/web-console/src/entry.ts
@@ -16,6 +16,11 @@
* limitations under the License.
*/
+import 'brace'; // Import Ace editor and all the sub components used in the app
+import 'brace/ext/language_tools';
+import 'brace/mode/hjson';
+import 'brace/mode/sql';
+import 'brace/theme/solarized_dark';
import 'es6-shim/es6-shim';
import 'es7-shim'; // Webpack with automatically pick browser.js which does the shim()
import React from 'react';
diff --git a/web-console/src/utils/general.tsx b/web-console/src/utils/general.tsx
index 0d2dc39..438fc9d 100644
--- a/web-console/src/utils/general.tsx
+++ b/web-console/src/utils/general.tsx
@@ -113,6 +113,13 @@ export function sqlQueryCustomTableFilter(filter: Filter): string {
// ----------------------------
+export function caseInsensitiveContains(testString: string, searchString: string): boolean {
+ if (!searchString) return true;
+ return testString.toLowerCase().includes(searchString.toLowerCase());
+}
+
+// ----------------------------
+
export function countBy<T>(array: T[], fn: (x: T, index: number) => string = String): Record<string, number> {
const counts: Record<string, number> = {};
for (let i = 0; i < array.length; i++) {
@@ -177,6 +184,17 @@ export function getHeadProp(results: Record<string, any>[], prop: string): any {
// ----------------------------
+export function memoize<T, U>(fn: (x: T) => U): (x: T) => U {
+ let lastInput: T;
+ let lastOutput: U;
+ return (x: T) => {
+ if (x === lastInput) return lastOutput;
+ lastInput = x;
+ lastOutput = fn(lastInput);
+ return lastOutput;
+ };
+}
+
export function parseJson(json: string): any {
try {
return JSON.parse(json);
diff --git a/web-console/src/utils/ingestion-spec.tsx b/web-console/src/utils/ingestion-spec.tsx
index c7fc446..e9d92b5 100644
--- a/web-console/src/utils/ingestion-spec.tsx
+++ b/web-console/src/utils/ingestion-spec.tsx
@@ -26,6 +26,10 @@ import { ExternalLink } from '../components/external-link/external-link';
import { TIMESTAMP_FORMAT_VALUES } from './druid-time';
import { deepGet, deepSet } from './object-change';
+// These constants are used to make sure that they are not constantly recreated thrashing the pure components
+export const EMPTY_OBJECT: any = {};
+export const EMPTY_ARRAY: any[] = [];
+
export interface IngestionSpec {
type?: IngestionType;
dataSchema: DataSchema;
@@ -61,7 +65,7 @@ function ingestionTypeToIoAndTuningConfigType(ingestionType: IngestionType): str
}
export function getIngestionComboType(spec: IngestionSpec): IngestionComboType | null {
- const ioConfig = deepGet(spec, 'ioConfig') || {};
+ const ioConfig = deepGet(spec, 'ioConfig') || EMPTY_OBJECT;
switch (ioConfig.type) {
case 'kafka':
@@ -70,7 +74,7 @@ export function getIngestionComboType(spec: IngestionSpec): IngestionComboType |
case 'index':
case 'index_parallel':
- const firehose = deepGet(spec, 'ioConfig.firehose') || {};
+ const firehose = deepGet(spec, 'ioConfig.firehose') || EMPTY_OBJECT;
switch (firehose.type) {
case 'local':
case 'http':
@@ -124,7 +128,7 @@ export function isParallel(spec: IngestionSpec): boolean {
export type DimensionMode = 'specific' | 'auto-detect';
export function getDimensionMode(spec: IngestionSpec): DimensionMode {
- const dimensions = deepGet(spec, 'dataSchema.parser.parseSpec.dimensionsSpec.dimensions') || [];
+ const dimensions = deepGet(spec, 'dataSchema.parser.parseSpec.dimensionsSpec.dimensions') || EMPTY_ARRAY;
return Array.isArray(dimensions) && dimensions.length === 0 ? 'auto-detect' : 'specific';
}
@@ -1104,7 +1108,7 @@ export function guessDataSourceName(ioConfig: IoConfig): string | null {
return filenameFromPath(firehose.baseDir);
case 'static-s3':
- return filenameFromPath((firehose.uris || [])[0] || (firehose.prefixes || [])[0]);
+ return filenameFromPath((firehose.uris || EMPTY_ARRAY)[0] || (firehose.prefixes || EMPTY_ARRAY)[0]);
case 'http':
return filenameFromPath(firehose.uris ? firehose.uris[0] : undefined);
@@ -1587,7 +1591,7 @@ export interface DimensionFiltersWithRest {
}
export function splitFilter(filter: DruidFilter | null): DimensionFiltersWithRest {
- const inputAndFilters: DruidFilter[] = filter ? ((filter.type === 'and' && Array.isArray(filter.fields)) ? filter.fields : [filter]) : [];
+ const inputAndFilters: DruidFilter[] = filter ? ((filter.type === 'and' && Array.isArray(filter.fields)) ? filter.fields : [filter]) : EMPTY_ARRAY;
const dimensionFilters: DruidFilter[] = inputAndFilters.filter(f => typeof f.dimension === 'string');
const restFilters: DruidFilter[] = inputAndFilters.filter(f => typeof f.dimension !== 'string');
@@ -1599,7 +1603,7 @@ export function splitFilter(filter: DruidFilter | null): DimensionFiltersWithRes
export function joinFilter(dimensionFiltersWithRest: DimensionFiltersWithRest): DruidFilter | null {
const { dimensionFilters, restFilter } = dimensionFiltersWithRest;
- let newFields = dimensionFilters || [];
+ let newFields = dimensionFilters || EMPTY_ARRAY;
if (restFilter && restFilter.type) newFields = newFields.concat([restFilter]);
if (!newFields.length) return null;
diff --git a/web-console/src/utils/sampler.ts b/web-console/src/utils/sampler.ts
index c20109a..1996bf3 100644
--- a/web-console/src/utils/sampler.ts
+++ b/web-console/src/utils/sampler.ts
@@ -260,7 +260,7 @@ export async function sampleForTimestamp(spec: IngestionSpec, sampleStrategy: Sa
}
},
samplerConfig: Object.assign({}, BASE_SAMPLER_CONFIG, {
- cacheKey
+ cacheKey: sampleColumns.cacheKey || cacheKey
})
};
diff --git a/web-console/src/views/load-data-view/filter-table/__snapshots__/filter-table.spec.tsx.snap b/web-console/src/views/load-data-view/filter-table/__snapshots__/filter-table.spec.tsx.snap
new file mode 100644
index 0000000..3d9f5c8
--- /dev/null
+++ b/web-console/src/views/load-data-view/filter-table/__snapshots__/filter-table.spec.tsx.snap
@@ -0,0 +1,1014 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`filter table matches snapshot 1`] = `
+<div
+ class="ReactTable filter-table -striped -highlight"
+>
+ <div
+ class="rt-table"
+ role="grid"
+ >
+ <div
+ class="rt-thead -header"
+ style="min-width: 100px;"
+ >
+ <div
+ class="rt-tr"
+ role="row"
+ >
+ <div
+ class="rt-th rt-resizable-header"
+ role="columnheader"
+ style="flex: 100 0 auto; width: 100px;"
+ tabindex="-1"
+ >
+ <div
+ class="rt-resizable-header-content"
+ >
+ <div
+ class="clickable"
+ >
+ <div
+ class="column-name"
+ >
+ c1
+ </div>
+ <div
+ class="column-detail"
+ >
+
+
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-resizer"
+ />
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tbody"
+ style="min-width: 100px;"
+ >
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ hello
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div
+ class="-loading"
+ >
+ <div
+ class="-loading-inner"
+ >
+ Loading...
+ </div>
+ </div>
+</div>
+`;
diff --git a/web-console/src/components/menu-checkbox/menu-checkbox.tsx b/web-console/src/views/load-data-view/filter-table/filter-table.scss
similarity index 73%
copy from web-console/src/components/menu-checkbox/menu-checkbox.tsx
copy to web-console/src/views/load-data-view/filter-table/filter-table.scss
index 659a78c..d57d317 100644
--- a/web-console/src/components/menu-checkbox/menu-checkbox.tsx
+++ b/web-console/src/views/load-data-view/filter-table/filter-table.scss
@@ -16,16 +16,16 @@
* limitations under the License.
*/
-import { Checkbox, ICheckboxProps } from '@blueprintjs/core';
-import React from 'react';
-
-import './menu-checkbox.scss';
-
-export class MenuCheckbox extends React.PureComponent<ICheckboxProps, {}> {
+.filter-table {
+ .rt-th {
+ &.filtered {
+ background: rgba(201, 128, 22, 0.2);
+ }
+ }
- render() {
- return <li className="menu-checkbox">
- <Checkbox {...this.props}/>
- </li>;
+ .rt-td {
+ &.filtered {
+ background: rgba(201, 128, 22, 0.05);
+ }
}
}
diff --git a/web-console/src/components/sql-control/sql-control.spec.tsx b/web-console/src/views/load-data-view/filter-table/filter-table.spec.tsx
similarity index 65%
copy from web-console/src/components/sql-control/sql-control.spec.tsx
copy to web-console/src/views/load-data-view/filter-table/filter-table.spec.tsx
index 1ac07be..c959db4 100644
--- a/web-console/src/components/sql-control/sql-control.spec.tsx
+++ b/web-console/src/views/load-data-view/filter-table/filter-table.spec.tsx
@@ -19,18 +19,30 @@
import React from 'react';
import { render } from 'react-testing-library';
-import { SqlControl } from './sql-control';
+import { FilterTable } from './filter-table';
-describe('sql control', () => {
+describe('filter table', () => {
it('matches snapshot', () => {
- const sqlControl = <SqlControl
- initSql={'test'}
- onRun={(query, context, wrapQuery) => {}}
- onExplain={(sqlQuery, context) => {}}
- queryElapsed={2}
+ const sampleData = {
+ header: ['c1'],
+ rows: [
+ {
+ raw: `{"c1":"hello"}`,
+ parsed: { c1: 'hello' }
+ }
+ ]
+ };
+
+ const filterTable = <FilterTable
+ sampleData={sampleData}
+ columnFilter=""
+ dimensionFilters={[]}
+ selectedFilterIndex={-1}
+ onShowGlobalFilter={() => null}
+ onFilterSelect={() => null}
/>;
- const { container } = render(sqlControl);
+ const { container } = render(filterTable);
expect(container.firstChild).toMatchSnapshot();
});
});
diff --git a/web-console/src/views/load-data-view/filter-table/filter-table.tsx b/web-console/src/views/load-data-view/filter-table/filter-table.tsx
new file mode 100644
index 0000000..5e49d4a
--- /dev/null
+++ b/web-console/src/views/load-data-view/filter-table/filter-table.tsx
@@ -0,0 +1,88 @@
+/*
+ * 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 classNames from 'classnames';
+import React from 'react';
+import ReactTable from 'react-table';
+
+import { TableCell } from '../../../components';
+import { caseInsensitiveContains, filterMap } from '../../../utils';
+import { DruidFilter, Transform } from '../../../utils/ingestion-spec';
+import { HeaderAndRows } from '../../../utils/sampler';
+
+import './filter-table.scss';
+
+export interface FilterTableProps extends React.Props<any> {
+ sampleData: HeaderAndRows;
+ columnFilter: string;
+ dimensionFilters: DruidFilter[];
+ selectedFilterIndex: number;
+ onShowGlobalFilter: () => void;
+ onFilterSelect: (filter: DruidFilter, index: number) => void;
+}
+
+export class FilterTable extends React.PureComponent<FilterTableProps> {
+ render() {
+ const { sampleData, columnFilter, dimensionFilters, selectedFilterIndex, onShowGlobalFilter, onFilterSelect } = this.props;
+
+ return <ReactTable
+ className="filter-table -striped -highlight"
+ data={sampleData.rows}
+ columns={filterMap(sampleData.header, (columnName, i) => {
+ if (!caseInsensitiveContains(columnName, columnFilter)) return null;
+ const timestamp = columnName === '__time';
+ const filterIndex = dimensionFilters.findIndex(f => f.dimension === columnName);
+ const filter = dimensionFilters[filterIndex];
+
+ const columnClassName = classNames({
+ filtered: filter,
+ selected: filter && filterIndex === selectedFilterIndex
+ });
+ return {
+ Header: (
+ <div
+ className={classNames('clickable')}
+ onClick={() => {
+ if (timestamp) {
+ onShowGlobalFilter();
+ } else if (filter) {
+ onFilterSelect(filter, filterIndex);
+ } else {
+ onFilterSelect({ type: 'selector', dimension: columnName, value: '' }, -1);
+ }
+ }}
+ >
+ <div className="column-name">{columnName}</div>
+ <div className="column-detail">
+ {filter ? `(filtered)` : ''}
+ </div>
+ </div>
+ ),
+ headerClassName: columnClassName,
+ className: columnClassName,
+ id: String(i),
+ accessor: row => row.parsed ? row.parsed[columnName] : null,
+ Cell: row => <TableCell value={row.value} timestamp={timestamp}/>
+ };
+ })}
+ defaultPageSize={50}
+ showPagination={false}
+ sortable={false}
+ />;
+ }
+}
diff --git a/web-console/src/views/load-data-view/load-data-view.scss b/web-console/src/views/load-data-view/load-data-view.scss
index 64ac83e..0e5a1b1 100644
--- a/web-console/src/views/load-data-view/load-data-view.scss
+++ b/web-console/src/views/load-data-view/load-data-view.scss
@@ -151,11 +151,6 @@
border-radius: 2px;
}
- &.flattened,
- &.transformed {
- background: rgba(201, 128, 22, 0.2);
- }
-
.clickable {
cursor: pointer;
}
@@ -163,48 +158,12 @@
&.timestamp {
background: rgba(19, 129, 201, 0.5);
}
-
- &.dimension {
- background: rgba(38, 170, 201, 0.5);
-
- &.long { background: rgba(19, 129, 201, 0.5); }
- &.float { background: rgba(25, 145, 201, 0.5); }
- }
-
- &.metric {
- background: rgba(201, 191, 55, 0.5);
- }
}
.rt-td {
- &.flattened,
- &.transformed {
- background: rgba(201, 128, 22, 0.05);
- }
-
&.timestamp {
background: rgba(19, 129, 201, 0.15);
}
-
- &.dimension {
- background: rgba(38, 170, 201, 0.1);
-
- &.long { background: rgba(19, 129, 201, 0.1); }
- &.float { background: rgba(25, 145, 201, 0.1); }
- }
-
- &.metric {
- background: rgba(201, 191, 55, 0.1);
- }
- }
-
- .parse-detail {
- padding: 10px;
-
- .parse-error {
- color: #9E2B0E;
- margin-bottom: 12px;
- }
}
}
}
diff --git a/web-console/src/views/load-data-view/load-data-view.tsx b/web-console/src/views/load-data-view/load-data-view.tsx
index 12ae636..b9aee95 100644
--- a/web-console/src/views/load-data-view/load-data-view.tsx
+++ b/web-console/src/views/load-data-view/load-data-view.tsx
@@ -29,7 +29,6 @@ import { IconNames } from '@blueprintjs/icons';
import axios from 'axios';
import classNames from 'classnames';
import React from 'react';
-import ReactTable from 'react-table';
import { AutoForm, CenterMessage, ClearableInput, ExternalLink, JSONInput, Loader, TableCell } from '../../components';
import { AsyncActionDialog } from '../../dialogs';
@@ -39,10 +38,9 @@ import {
getDruidErrorMessage,
localStorageGet,
LocalStorageKeys,
- localStorageSet, parseJson,
- QueryState, sortWithPrefixSuffix
+ localStorageSet, memoize, parseJson,
+ QueryState
} from '../../utils';
-import { escapeColumnName } from '../../utils/druid-expression';
import { possibleDruidFormatForValues } from '../../utils/druid-time';
import { updateSchemaWithSample } from '../../utils/druid-type';
import {
@@ -50,15 +48,13 @@ import {
DimensionMode,
DimensionSpec,
DimensionsSpec,
- DruidFilter,
+ DruidFilter, EMPTY_ARRAY, EMPTY_OBJECT,
fillDataSourceName,
fillParser,
FlattenField,
getBlankSpec,
getDimensionMode,
getDimensionSpecFormFields,
- getDimensionSpecName,
- getDimensionSpecType,
getEmptyTimestampSpec,
getFilterFormFields,
getFlattenFieldFormFields,
@@ -66,20 +62,17 @@ import {
getIoConfigFormFields,
getIoConfigTuningFormFields,
getMetricSpecFormFields,
- getMetricSpecName,
getParseSpecFormFields,
getPartitionRelatedTuningSpecFormFields,
getRollup,
getSpecType,
- getTimestampSpecColumn,
getTimestampSpecFormFields,
getTransformFormFields,
getTuningSpecFormFields,
GranularitySpec,
hasParallelAbility,
- inflateDimensionSpec, IngestionComboType,
+ IngestionComboType,
IngestionSpec,
- IngestionType,
IoConfig,
isColumnTimestampSpec,
isParallel,
@@ -100,7 +93,6 @@ import {
getOverlordModules,
HeaderAndRows,
headerAndRowsFromSampleResponse,
- SampleEntry,
sampleForConnect,
sampleForFilter,
sampleForParser, sampleForSchema,
@@ -111,6 +103,12 @@ import {
} from '../../utils/sampler';
import { computeFlattenPathsForData } from '../../utils/spec-utils';
+import { FilterTable } from './filter-table/filter-table';
+import { ParseDataTable } from './parse-data-table/parse-data-table';
+import { ParseTimeTable } from './parse-time-table/parse-time-table';
+import { SchemaTable } from './schema-table/schema-table';
+import { TransformTable } from './transform-table/transform-table';
+
import './load-data-view.scss';
function showRawLine(line: string): string {
@@ -123,11 +121,6 @@ function showRawLine(line: string): string {
return line;
}
-function filterMatch(testString: string, searchString: string): boolean {
- if (!searchString) return true;
- return testString.toLowerCase().includes(searchString.toLowerCase());
-}
-
function getTimestampSpec(headerAndRows: HeaderAndRows | null): TimestampSpec {
if (!headerAndRows) return getEmptyTimestampSpec();
@@ -201,7 +194,10 @@ export interface LoadDataViewState {
selectedFlattenField: FlattenField | null;
// for timestamp
- timestampQueryState: QueryState<HeaderAndRows>;
+ timestampQueryState: QueryState<{
+ headerAndRows: HeaderAndRows;
+ timestampSpec: TimestampSpec;
+ }>;
// for transform
transformQueryState: QueryState<HeaderAndRows>;
@@ -215,7 +211,11 @@ export interface LoadDataViewState {
showGlobalFilter: boolean;
// for schema
- schemaQueryState: QueryState<HeaderAndRows>;
+ schemaQueryState: QueryState<{
+ headerAndRows: HeaderAndRows;
+ dimensionsSpec: DimensionsSpec;
+ metricsSpec: MetricSpec[];
+ }>;
selectedDimensionSpecIndex: number;
selectedDimensionSpec: DimensionSpec | null;
selectedMetricSpecIndex: number;
@@ -517,7 +517,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
async queryForConnect(initRun = false) {
const { spec, sampleStrategy } = this.state;
- const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || {};
+ const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || EMPTY_OBJECT;
let issue: string | undefined;
if (issueWithIoConfig(ioConfig)) {
@@ -554,7 +554,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
renderConnectStage() {
const { spec, inputQueryState, sampleStrategy } = this.state;
const specType = getSpecType(spec);
- const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || {};
+ const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || EMPTY_OBJECT;
const isBlank = !ioConfig.type;
let mainFill: JSX.Element | string = '';
@@ -653,8 +653,8 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
async queryForParser(initRun = false) {
const { spec, sampleStrategy, cacheKey } = this.state;
- const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || {};
- const parser: Parser = deepGet(spec, 'dataSchema.parser') || {};
+ const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || EMPTY_OBJECT;
+ const parser: Parser = deepGet(spec, 'dataSchema.parser') || EMPTY_OBJECT;
let issue: string | null = null;
if (issueWithIoConfig(ioConfig)) {
@@ -694,8 +694,8 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
renderParserStage() {
const { spec, columnFilter, specialColumnsOnly, parserQueryState, selectedFlattenField } = this.state;
- const parseSpec: ParseSpec = deepGet(spec, 'dataSchema.parser.parseSpec') || {};
- const flattenFields: FlattenField[] = deepGet(spec, 'dataSchema.parser.parseSpec.flattenSpec.fields') || [];
+ const parseSpec: ParseSpec = deepGet(spec, 'dataSchema.parser.parseSpec') || EMPTY_OBJECT;
+ const flattenFields: FlattenField[] = deepGet(spec, 'dataSchema.parser.parseSpec.flattenSpec.fields') || EMPTY_ARRAY;
const isBlank = !parseSpec.format;
const canFlatten = parseSpec.format === 'json';
@@ -732,61 +732,13 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
/>
}
</div>
- <ReactTable
- data={parserQueryState.data.rows}
- columns={filterMap(parserQueryState.data.header, (columnName, i) => {
- if (!filterMatch(columnName, columnFilter)) return null;
- const flattenFieldIndex = flattenFields.findIndex(f => f.name === columnName);
- if (flattenFieldIndex === -1 && specialColumnsOnly) return null;
- const flattenField = flattenFields[flattenFieldIndex];
- return {
- Header: (
- <div
- className={classNames({ clickable: flattenField })}
- onClick={() => {
- this.setState({
- selectedFlattenFieldIndex: flattenFieldIndex,
- selectedFlattenField: flattenField
- });
- }}
- >
- <div className="column-name">{columnName}</div>
- <div className="column-detail">
- {flattenField ? `${flattenField.type}: ${flattenField.expr}` : ''}
- </div>
- </div>
- ),
- id: String(i),
- accessor: (row: SampleEntry) => row.parsed ? row.parsed[columnName] : null,
- Cell: row => {
- if (row.original.unparseable) {
- return <TableCell unparseable/>;
- }
- return <TableCell value={row.value}/>;
- },
- headerClassName: classNames({
- flattened: flattenField
- })
- };
- })}
- SubComponent={rowInfo => {
- const { raw, error } = rowInfo.original;
- const parsedJson: any = parseJson(raw);
-
- if (!error && parsedJson && canFlatten) {
- return <pre className="parse-detail">
- {'Original row: ' + JSON.stringify(parsedJson, null, 2)}
- </pre>;
- } else {
- return <div className="parse-detail">
- {error && <div className="parse-error">{error}</div>}
- <div>{'Original row: ' + rowInfo.original.raw}</div>
- </div>;
- }
- }}
- defaultPageSize={50}
- showPagination={false}
- sortable={false}
+ <ParseDataTable
+ sampleData={parserQueryState.data}
+ columnFilter={columnFilter}
+ canFlatten={canFlatten}
+ flattenedColumnsOnly={specialColumnsOnly}
+ flattenFields={flattenFields}
+ onFlattenFieldSelect={this.onFlattenFieldSelect}
/>
</div>;
}
@@ -859,9 +811,16 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
</>;
}
+ private onFlattenFieldSelect = (field: FlattenField, index: number) => {
+ this.setState({
+ selectedFlattenFieldIndex: index,
+ selectedFlattenField: field
+ });
+ }
+
renderFlattenControls() {
const { spec, selectedFlattenField, selectedFlattenFieldIndex } = this.state;
- const parseSpec: ParseSpec = deepGet(spec, 'dataSchema.parser.parseSpec') || {};
+ const parseSpec: ParseSpec = deepGet(spec, 'dataSchema.parser.parseSpec') || EMPTY_OBJECT;
if (!parseSpecHasFlatten(parseSpec)) return null;
const close = () => {
@@ -934,8 +893,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
async queryForTimestamp(initRun = false) {
const { spec, sampleStrategy, cacheKey } = this.state;
- const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || {};
- const parser: Parser = deepGet(spec, 'dataSchema.parser') || {};
+ const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || EMPTY_OBJECT;
+ const parser: Parser = deepGet(spec, 'dataSchema.parser') || EMPTY_OBJECT;
+ const timestampSpec = deepGet(spec, 'dataSchema.parser.parseSpec.timestampSpec') || EMPTY_OBJECT;
let issue: string | null = null;
if (issueWithIoConfig(ioConfig)) {
@@ -968,16 +928,18 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
this.setState({
cacheKey: sampleResponse.cacheKey,
timestampQueryState: new QueryState({
- data: headerAndRowsFromSampleResponse(sampleResponse)
+ data: {
+ headerAndRows: headerAndRowsFromSampleResponse(sampleResponse),
+ timestampSpec
+ }
})
});
}
renderTimestampStage() {
const { spec, columnFilter, specialColumnsOnly, timestampQueryState } = this.state;
- const parseSpec: ParseSpec = deepGet(spec, 'dataSchema.parser.parseSpec') || {};
- const timestampSpec: TimestampSpec = deepGet(spec, 'dataSchema.parser.parseSpec.timestampSpec') || {};
- const timestampSpecColumn = getTimestampSpecColumn(timestampSpec);
+ const parseSpec: ParseSpec = deepGet(spec, 'dataSchema.parser.parseSpec') || EMPTY_OBJECT;
+ const timestampSpec: TimestampSpec = deepGet(spec, 'dataSchema.parser.parseSpec.timestampSpec') || EMPTY_OBJECT;
const timestampSpecFromColumn = isColumnTimestampSpec(timestampSpec);
const isBlank = !parseSpec.format;
@@ -997,7 +959,6 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
</CenterMessage>;
} else if (timestampQueryState.data) {
- const timestampData = timestampQueryState.data;
mainFill = <div className="table-with-control">
<div className="table-control">
<ClearableInput
@@ -1011,61 +972,11 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
onChange={() => this.setState({ specialColumnsOnly: !specialColumnsOnly })}
/>
</div>
- <ReactTable
- data={timestampData.rows}
- columns={filterMap(timestampData.header.length ? timestampData.header : ['__error__'], (columnName, i) => {
- const timestamp = columnName === '__time';
- if (!timestamp && !filterMatch(columnName, columnFilter)) return null;
- const selected = timestampSpec.column === columnName;
- const possibleFormat = timestamp ? null : possibleDruidFormatForValues(filterMap(timestampData.rows, d => d.parsed ? d.parsed[columnName] : null));
- if (specialColumnsOnly && !timestamp && !possibleFormat) return null;
-
- const columnClassName = classNames({
- timestamp,
- selected
- });
- return {
- Header: (
- <div
- className={classNames({ clickable: !timestamp })}
- onClick={timestamp ? undefined : () => {
- const newTimestampSpec = {
- column: columnName,
- format: possibleFormat || '!!! Could not auto detect a format !!!'
- };
- this.updateSpec(deepSet(spec, 'dataSchema.parser.parseSpec.timestampSpec', newTimestampSpec));
- }}
- >
- <div className="column-name">{columnName}</div>
- <div className="column-detail">
- {
- timestamp ?
- (timestampSpecFromColumn ? `from: '${timestampSpecColumn}'` : `mv: ${timestampSpec.missingValue}`) :
- (possibleFormat || '')
- }
- </div>
- </div>
- ),
- headerClassName: columnClassName,
- className: columnClassName,
- id: String(i),
- accessor: (row: SampleEntry) => row.parsed ? row.parsed[columnName] : null,
- Cell: row => {
- if (columnName === '__error__') {
- return <TableCell value={row.original.error}/>;
- }
- if (row.original.unparseable) {
- return <TableCell unparseable/>;
- }
- return <TableCell value={row.value} timestamp={timestamp}/>;
- },
- minWidth: timestamp ? 200 : 100,
- resizable: !timestamp
- };
- })}
- defaultPageSize={50}
- showPagination={false}
- sortable={false}
+ <ParseTimeTable
+ sampleBundle={timestampQueryState.data}
+ columnFilter={columnFilter}
+ possibleTimestampColumnsOnly={specialColumnsOnly}
+ onTimestampColumnSelect={this.onTimestampColumnSelect}
/>
</div>;
}
@@ -1131,12 +1042,17 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
</>;
}
+ private onTimestampColumnSelect = (newTimestampSpec: TimestampSpec) => {
+ const { spec } = this.state;
+ this.updateSpec(deepSet(spec, 'dataSchema.parser.parseSpec.timestampSpec', newTimestampSpec));
+ }
+
// ==================================================================
async queryForTransform(initRun = false) {
const { spec, sampleStrategy, cacheKey } = this.state;
- const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || {};
- const parser: Parser = deepGet(spec, 'dataSchema.parser') || {};
+ const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || EMPTY_OBJECT;
+ const parser: Parser = deepGet(spec, 'dataSchema.parser') || EMPTY_OBJECT;
let issue: string | null = null;
if (issueWithIoConfig(ioConfig)) {
@@ -1176,7 +1092,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
renderTransformStage() {
const { spec, columnFilter, specialColumnsOnly, transformQueryState, selectedTransformIndex } = this.state;
- const transforms: Transform[] = deepGet(spec, 'dataSchema.transformSpec.transforms') || [];
+ const transforms: Transform[] = deepGet(spec, 'dataSchema.transformSpec.transforms') || EMPTY_ARRAY;
let mainFill: JSX.Element | string = '';
if (transformQueryState.isInit()) {
@@ -1207,57 +1123,13 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
disabled={!transforms.length}
/>
</div>
- <ReactTable
- data={transformQueryState.data.rows}
- columns={filterMap(transformQueryState.data.header, (columnName, i) => {
- if (!filterMatch(columnName, columnFilter)) return null;
- const timestamp = columnName === '__time';
- const transformIndex = transforms.findIndex(f => f.name === columnName);
- if (transformIndex === -1 && specialColumnsOnly) return null;
- const transform = transforms[transformIndex];
-
- const columnClassName = classNames({
- transformed: transform,
- selected: transform && transformIndex === selectedTransformIndex
- });
- return {
- Header: (
- <div
- className={classNames('clickable')}
- onClick={() => {
- if (transform) {
- this.setState({
- selectedTransformIndex: transformIndex,
- selectedTransform: transform
- });
- } else {
- this.setState({
- selectedTransformIndex: -1,
- selectedTransform: {
- type: 'expression',
- name: columnName,
- expression: escapeColumnName(columnName)
- }
- });
- }
- }}
- >
- <div className="column-name">{columnName}</div>
- <div className="column-detail">
- {transform ? `= ${transform.expression}` : ''}
- </div>
- </div>
- ),
- headerClassName: columnClassName,
- className: columnClassName,
- id: String(i),
- accessor: row => row.parsed ? row.parsed[columnName] : null,
- Cell: row => <TableCell value={row.value} timestamp={timestamp}/>
- };
- })}
- defaultPageSize={50}
- showPagination={false}
- sortable={false}
+ <TransformTable
+ sampleData={transformQueryState.data}
+ columnFilter={columnFilter}
+ transformedColumnsOnly={specialColumnsOnly}
+ transforms={transforms}
+ selectedTransformIndex={selectedTransformIndex}
+ onTransformSelect={this.onTransformSelect}
/>
</div>;
}
@@ -1308,6 +1180,13 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
</>;
}
+ private onTransformSelect = (transform: Transform, index: number) => {
+ this.setState({
+ selectedTransformIndex: index,
+ selectedTransform: transform
+ });
+ }
+
renderTransformControls() {
const { spec, selectedTransform, selectedTransformIndex } = this.state;
@@ -1376,8 +1255,8 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
async queryForFilter(initRun = false) {
const { spec, sampleStrategy, cacheKey } = this.state;
- const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || {};
- const parser: Parser = deepGet(spec, 'dataSchema.parser') || {};
+ const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || EMPTY_OBJECT;
+ const parser: Parser = deepGet(spec, 'dataSchema.parser') || EMPTY_OBJECT;
let issue: string | null = null;
if (issueWithIoConfig(ioConfig)) {
@@ -1415,10 +1294,15 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
});
}
+ private getMemoizedDimensionFiltersFromSpec = memoize<IngestionSpec, DruidFilter[]>((spec) => {
+ const { dimensionFilters } = splitFilter(deepGet(spec, 'dataSchema.transformSpec.filter'));
+ return dimensionFilters;
+ });
+
renderFilterStage() {
const { spec, columnFilter, filterQueryState, selectedFilter, selectedFilterIndex, showGlobalFilter } = this.state;
- const parseSpec: ParseSpec = deepGet(spec, 'dataSchema.parser.parseSpec') || {};
- const { dimensionFilters } = splitFilter(deepGet(spec, 'dataSchema.transformSpec.filter'));
+ const parseSpec: ParseSpec = deepGet(spec, 'dataSchema.parser.parseSpec') || EMPTY_OBJECT;
+ const dimensionFilters = this.getMemoizedDimensionFiltersFromSpec(spec);
const isBlank = !parseSpec.format;
@@ -1445,56 +1329,13 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
placeholder="Search columns"
/>
</div>
- <ReactTable
- data={filterQueryState.data.rows}
- columns={filterMap(filterQueryState.data.header, (columnName, i) => {
- if (!filterMatch(columnName, columnFilter)) return null;
- const timestamp = columnName === '__time';
- const filterIndex = dimensionFilters.findIndex(f => f.dimension === columnName);
- const filter = dimensionFilters[filterIndex];
-
- const columnClassName = classNames({
- filtered: filter,
- selected: filter && filterIndex === selectedFilterIndex
- });
- return {
- Header: (
- <div
- className={classNames('clickable')}
- onClick={() => {
- if (timestamp) {
- this.setState({
- showGlobalFilter: true
- });
- } else if (filter) {
- this.setState({
- selectedFilterIndex: filterIndex,
- selectedFilter: filter
- });
- } else {
- this.setState({
- selectedFilterIndex: -1,
- selectedFilter: { type: 'selector', dimension: columnName, value: '' }
- });
- }
- }}
- >
- <div className="column-name">{columnName}</div>
- <div className="column-detail">
- {filter ? `(filtered)` : ''}
- </div>
- </div>
- ),
- headerClassName: columnClassName,
- className: columnClassName,
- id: String(i),
- accessor: row => row.parsed ? row.parsed[columnName] : null,
- Cell: row => <TableCell value={row.value} timestamp={timestamp}/>
- };
- })}
- defaultPageSize={50}
- showPagination={false}
- sortable={false}
+ <FilterTable
+ sampleData={filterQueryState.data}
+ columnFilter={columnFilter}
+ dimensionFilters={dimensionFilters}
+ selectedFilterIndex={selectedFilterIndex}
+ onShowGlobalFilter={this.onShowGlobalFilter}
+ onFilterSelect={this.onFilterSelect}
/>
</div>;
}
@@ -1528,6 +1369,17 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
</>;
}
+ private onShowGlobalFilter = () => {
+ this.setState({ showGlobalFilter: true });
+ }
+
+ private onFilterSelect = (filter: DruidFilter, index: number) => {
+ this.setState({
+ selectedFilterIndex: index,
+ selectedFilter: filter
+ });
+ }
+
renderColumnFilterControls() {
const { spec, selectedFilter, selectedFilterIndex } = this.state;
@@ -1658,8 +1510,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
async queryForSchema(initRun = false) {
const { spec, sampleStrategy, cacheKey } = this.state;
- const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || {};
- const parser: Parser = deepGet(spec, 'dataSchema.parser') || {};
+ const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || EMPTY_OBJECT;
+ const parser: Parser = deepGet(spec, 'dataSchema.parser') || EMPTY_OBJECT;
+ const metricsSpec: MetricSpec[] = deepGet(spec, 'dataSchema.metricsSpec') || EMPTY_ARRAY;
+ const dimensionsSpec: DimensionsSpec = deepGet(spec, 'dataSchema.parser.parseSpec.dimensionsSpec') || EMPTY_OBJECT;
let issue: string | null = null;
if (issueWithIoConfig(ioConfig)) {
@@ -1692,15 +1546,17 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
this.setState({
cacheKey: sampleResponse.cacheKey,
schemaQueryState: new QueryState({
- data: headerAndRowsFromSampleResponse(sampleResponse)
+ data: {
+ headerAndRows: headerAndRowsFromSampleResponse(sampleResponse),
+ dimensionsSpec,
+ metricsSpec
+ }
})
});
}
renderSchemaStage() {
const { spec, columnFilter, schemaQueryState, selectedDimensionSpec, selectedDimensionSpecIndex, selectedMetricSpec, selectedMetricSpecIndex } = this.state;
- const metricsSpec: MetricSpec[] = deepGet(spec, 'dataSchema.metricsSpec') || [];
- const dimensionsSpec: DimensionsSpec = deepGet(spec, 'dataSchema.parser.parseSpec.dimensionsSpec') || {};
const rollup: boolean = Boolean(deepGet(spec, 'dataSchema.granularitySpec.rollup'));
const somethingSelected = Boolean(selectedDimensionSpec || selectedMetricSpec);
const dimensionMode = getDimensionMode(spec);
@@ -1720,7 +1576,6 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
</CenterMessage>;
} else if (schemaQueryState.data) {
- const dimensionMetricSortedHeader = sortWithPrefixSuffix(schemaQueryState.data.header, ['__time'], metricsSpec.map(getMetricSpecName));
mainFill = <div className="table-with-control">
<div className="table-control">
<ClearableInput
@@ -1729,93 +1584,12 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
placeholder="Search columns"
/>
</div>
- <ReactTable
- data={schemaQueryState.data.rows}
- columns={filterMap(dimensionMetricSortedHeader, (columnName, i) => {
- if (!filterMatch(columnName, columnFilter)) return null;
-
- const metricSpecIndex = metricsSpec.findIndex(m => getMetricSpecName(m) === columnName);
- const metricSpec = metricsSpec[metricSpecIndex];
-
- if (metricSpec) {
- const columnClassName = classNames('metric', {
- selected: metricSpec && metricSpecIndex === selectedMetricSpecIndex
- });
- return {
- Header: (
- <div
- className="clickable"
- onClick={() => {
- this.setState({
- selectedMetricSpecIndex: metricSpecIndex,
- selectedMetricSpec: metricSpec,
- selectedDimensionSpecIndex: -1,
- selectedDimensionSpec: null
- });
- }}
- >
- <div className="column-name">{columnName}</div>
- <div className="column-detail">
- {metricSpec.type}
- </div>
- </div>
- ),
- headerClassName: columnClassName,
- className: columnClassName,
- id: String(i),
- accessor: row => row.parsed ? row.parsed[columnName] : null,
- Cell: row => <TableCell value={row.value}/>
- };
- } else {
- const timestamp = columnName === '__time';
- const dimensionSpecIndex = dimensionsSpec.dimensions ? dimensionsSpec.dimensions.findIndex(d => getDimensionSpecName(d) === columnName) : -1;
- const dimensionSpec = dimensionsSpec.dimensions ? dimensionsSpec.dimensions[dimensionSpecIndex] : null;
- const dimensionSpecType = dimensionSpec ? getDimensionSpecType(dimensionSpec) : null;
-
- const columnClassName = classNames(timestamp ? 'timestamp' : 'dimension', dimensionSpecType || 'string', {
- selected: dimensionSpec && dimensionSpecIndex === selectedDimensionSpecIndex
- });
- return {
- Header: (
- <div
- className="clickable"
- onClick={() => {
- if (timestamp) {
- this.setState({
- selectedDimensionSpecIndex: -1,
- selectedDimensionSpec: null,
- selectedMetricSpecIndex: -1,
- selectedMetricSpec: null
- });
- return;
- }
-
- if (!dimensionSpec) return;
- this.setState({
- selectedDimensionSpecIndex: dimensionSpecIndex,
- selectedDimensionSpec: inflateDimensionSpec(dimensionSpec),
- selectedMetricSpecIndex: -1,
- selectedMetricSpec: null
- });
- }}
- >
- <div className="column-name">{columnName}</div>
- <div className="column-detail">
- {timestamp ? 'long (time column)' : (dimensionSpecType || 'string (auto)')}
- </div>
- </div>
- ),
- headerClassName: columnClassName,
- className: columnClassName,
- id: String(i),
- accessor: (row: SampleEntry) => row.parsed ? row.parsed[columnName] : null,
- Cell: row => <TableCell value={row.value} timestamp={timestamp}/>
- };
- }
- })}
- defaultPageSize={50}
- showPagination={false}
- sortable={false}
+ <SchemaTable
+ sampleBundle={schemaQueryState.data}
+ columnFilter={columnFilter}
+ selectedDimensionSpecIndex={selectedDimensionSpecIndex}
+ selectedMetricSpecIndex={selectedMetricSpecIndex}
+ onDimensionOrMetricSelect={this.onDimensionOrMetricSelect}
/>
</div>;
}
@@ -1926,6 +1700,20 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
</>;
}
+ private onDimensionOrMetricSelect = (
+ selectedDimensionSpec: DimensionSpec | null,
+ selectedDimensionSpecIndex: number,
+ selectedMetricSpec: MetricSpec | null,
+ selectedMetricSpecIndex: number
+ ) => {
+ this.setState({
+ selectedDimensionSpec,
+ selectedDimensionSpecIndex,
+ selectedMetricSpec,
+ selectedMetricSpecIndex
+ });
+ }
+
renderChangeRollupAction() {
const { newRollup, spec, sampleStrategy, cacheKey } = this.state;
if (newRollup === null) return;
@@ -2025,7 +1813,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
icon={IconNames.TRASH}
intent={Intent.DANGER}
onClick={() => {
- const curDimensions = deepGet(spec, `dataSchema.parser.parseSpec.dimensionsSpec.dimensions`) || [];
+ const curDimensions = deepGet(spec, `dataSchema.parser.parseSpec.dimensionsSpec.dimensions`) || EMPTY_ARRAY;
if (curDimensions.length <= 1) return; // Guard against removing the last dimension, ToDo: some better feedback here would be good
this.updateSpec(deepDelete(spec, `dataSchema.parser.parseSpec.dimensionsSpec.dimensions.${selectedDimensionSpecIndex}`));
@@ -2128,8 +1916,8 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
renderPartitionStage() {
const { spec } = this.state;
- const tuningConfig: TuningConfig = deepGet(spec, 'tuningConfig') || {};
- const granularitySpec: GranularitySpec = deepGet(spec, 'dataSchema.granularitySpec') || {};
+ const tuningConfig: TuningConfig = deepGet(spec, 'tuningConfig') || EMPTY_OBJECT;
+ const granularitySpec: GranularitySpec = deepGet(spec, 'dataSchema.granularitySpec') || EMPTY_OBJECT;
return <>
<div className="main">
@@ -2187,8 +1975,8 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
renderTuningStage() {
const { spec } = this.state;
- const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || {};
- const tuningConfig: TuningConfig = deepGet(spec, 'tuningConfig') || {};
+ const ioConfig: IoConfig = deepGet(spec, 'ioConfig') || EMPTY_OBJECT;
+ const tuningConfig: TuningConfig = deepGet(spec, 'tuningConfig') || EMPTY_OBJECT;
const ingestionComboType = getIngestionComboType(spec);
const inputTuningFields = ingestionComboType ? getIoConfigTuningFormFields(ingestionComboType) : null;
diff --git a/web-console/src/views/load-data-view/parse-data-table/__snapshots__/parse-data-table.spec.tsx.snap b/web-console/src/views/load-data-view/parse-data-table/__snapshots__/parse-data-table.spec.tsx.snap
new file mode 100644
index 0000000..8a047e5
--- /dev/null
+++ b/web-console/src/views/load-data-view/parse-data-table/__snapshots__/parse-data-table.spec.tsx.snap
@@ -0,0 +1,1476 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`parse data table matches snapshot 1`] = `
+<div
+ class="ReactTable parse-data-table -striped -highlight"
+>
+ <div
+ class="rt-table"
+ role="grid"
+ >
+ <div
+ class="rt-thead -header"
+ style="min-width: 135px;"
+ >
+ <div
+ class="rt-tr"
+ role="row"
+ >
+ <div
+ class="rt-th"
+ role="columnheader"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ tabindex="-1"
+ >
+ <div
+ class=""
+ />
+ </div>
+ <div
+ class="rt-th rt-resizable-header"
+ role="columnheader"
+ style="flex: 100 0 auto; width: 100px;"
+ tabindex="-1"
+ >
+ <div
+ class="rt-resizable-header-content"
+ >
+ <div
+ class=""
+ >
+ <div
+ class="column-name"
+ >
+ c1
+ </div>
+ <div
+ class="column-detail"
+ >
+
+
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-resizer"
+ />
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tbody"
+ style="min-width: 135px;"
+ >
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -odd"
+ role="row"
+ >
+ <div
+ class="rt-td rt-expandable"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <div
+ class="rt-expander"
+ >
+ •
+ </div>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ hello
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 35 0 auto; width: 35px; max-width: 35px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div
+ class="-loading"
+ >
+ <div
+ class="-loading-inner"
+ >
+ Loading...
+ </div>
+ </div>
+</div>
+`;
diff --git a/web-console/src/components/menu-checkbox/menu-checkbox.tsx b/web-console/src/views/load-data-view/parse-data-table/parse-data-table.scss
similarity index 73%
copy from web-console/src/components/menu-checkbox/menu-checkbox.tsx
copy to web-console/src/views/load-data-view/parse-data-table/parse-data-table.scss
index 659a78c..306b3d3 100644
--- a/web-console/src/components/menu-checkbox/menu-checkbox.tsx
+++ b/web-console/src/views/load-data-view/parse-data-table/parse-data-table.scss
@@ -16,16 +16,25 @@
* limitations under the License.
*/
-import { Checkbox, ICheckboxProps } from '@blueprintjs/core';
-import React from 'react';
+.parse-data-table {
+ .rt-th {
+ &.flattened {
+ background: rgba(201, 128, 22, 0.2);
+ }
+ }
-import './menu-checkbox.scss';
+ .rt-td {
+ &.flattened {
+ background: rgba(201, 128, 22, 0.05);
+ }
+ }
-export class MenuCheckbox extends React.PureComponent<ICheckboxProps, {}> {
+ .parse-detail {
+ padding: 10px;
- render() {
- return <li className="menu-checkbox">
- <Checkbox {...this.props}/>
- </li>;
+ .parse-error {
+ color: #9E2B0E;
+ margin-bottom: 12px;
+ }
}
}
diff --git a/web-console/src/components/sql-control/sql-control.spec.tsx b/web-console/src/views/load-data-view/parse-data-table/parse-data-table.spec.tsx
similarity index 65%
copy from web-console/src/components/sql-control/sql-control.spec.tsx
copy to web-console/src/views/load-data-view/parse-data-table/parse-data-table.spec.tsx
index 1ac07be..6a83e73 100644
--- a/web-console/src/components/sql-control/sql-control.spec.tsx
+++ b/web-console/src/views/load-data-view/parse-data-table/parse-data-table.spec.tsx
@@ -19,18 +19,30 @@
import React from 'react';
import { render } from 'react-testing-library';
-import { SqlControl } from './sql-control';
+import { ParseDataTable } from './parse-data-table';
-describe('sql control', () => {
+describe('parse data table', () => {
it('matches snapshot', () => {
- const sqlControl = <SqlControl
- initSql={'test'}
- onRun={(query, context, wrapQuery) => {}}
- onExplain={(sqlQuery, context) => {}}
- queryElapsed={2}
+ const sampleData = {
+ header: ['c1'],
+ rows: [
+ {
+ raw: `{"c1":"hello"}`,
+ parsed: { c1: 'hello' }
+ }
+ ]
+ };
+
+ const parseDataTable = <ParseDataTable
+ sampleData={sampleData}
+ columnFilter=""
+ canFlatten={false}
+ flattenedColumnsOnly={false}
+ flattenFields={[]}
+ onFlattenFieldSelect={() => null}
/>;
- const { container } = render(sqlControl);
+ const { container } = render(parseDataTable);
expect(container.firstChild).toMatchSnapshot();
});
});
diff --git a/web-console/src/views/load-data-view/parse-data-table/parse-data-table.tsx b/web-console/src/views/load-data-view/parse-data-table/parse-data-table.tsx
new file mode 100644
index 0000000..c58f607
--- /dev/null
+++ b/web-console/src/views/load-data-view/parse-data-table/parse-data-table.tsx
@@ -0,0 +1,99 @@
+/*
+ * 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 classNames from 'classnames';
+import React from 'react';
+import ReactTable from 'react-table';
+
+import { TableCell } from '../../../components';
+import { caseInsensitiveContains, filterMap, parseJson } from '../../../utils';
+import { FlattenField } from '../../../utils/ingestion-spec';
+import { HeaderAndRows, SampleEntry } from '../../../utils/sampler';
+
+import './parse-data-table.scss';
+
+export interface ParseDataTableProps extends React.Props<any> {
+ sampleData: HeaderAndRows;
+ columnFilter: string;
+ canFlatten: boolean;
+ flattenedColumnsOnly: boolean;
+ flattenFields: FlattenField[];
+ onFlattenFieldSelect: (field: FlattenField, index: number) => void;
+}
+
+export class ParseDataTable extends React.PureComponent<ParseDataTableProps> {
+ render() {
+ const { sampleData, columnFilter, canFlatten, flattenedColumnsOnly, flattenFields, onFlattenFieldSelect } = this.props;
+
+ return <ReactTable
+ className="parse-data-table -striped -highlight"
+ data={sampleData.rows}
+ columns={filterMap(sampleData.header, (columnName, i) => {
+ if (!caseInsensitiveContains(columnName, columnFilter)) return null;
+ const flattenFieldIndex = flattenFields.findIndex(f => f.name === columnName);
+ if (flattenFieldIndex === -1 && flattenedColumnsOnly) return null;
+ const flattenField = flattenFields[flattenFieldIndex];
+ return {
+ Header: (
+ <div
+ className={classNames({ clickable: flattenField })}
+ onClick={() => {
+ if (!flattenField) return;
+ onFlattenFieldSelect(flattenField, flattenFieldIndex);
+ }}
+ >
+ <div className="column-name">{columnName}</div>
+ <div className="column-detail">
+ {flattenField ? `${flattenField.type}: ${flattenField.expr}` : ''}
+ </div>
+ </div>
+ ),
+ id: String(i),
+ accessor: (row: SampleEntry) => row.parsed ? row.parsed[columnName] : null,
+ Cell: row => {
+ if (row.original.unparseable) {
+ return <TableCell unparseable/>;
+ }
+ return <TableCell value={row.value}/>;
+ },
+ headerClassName: classNames({
+ flattened: flattenField
+ })
+ };
+ })}
+ SubComponent={rowInfo => {
+ const { raw, error } = rowInfo.original;
+ const parsedJson: any = parseJson(raw);
+
+ if (!error && parsedJson && canFlatten) {
+ return <pre className="parse-detail">
+ {'Original row: ' + JSON.stringify(parsedJson, null, 2)}
+ </pre>;
+ } else {
+ return <div className="parse-detail">
+ {error && <div className="parse-error">{error}</div>}
+ <div>{'Original row: ' + rowInfo.original.raw}</div>
+ </div>;
+ }
+ }}
+ defaultPageSize={50}
+ showPagination={false}
+ sortable={false}
+ />;
+ }
+}
diff --git a/web-console/src/views/load-data-view/parse-time-table/__snapshots__/parse-time-table.spec.tsx.snap b/web-console/src/views/load-data-view/parse-time-table/__snapshots__/parse-time-table.spec.tsx.snap
new file mode 100644
index 0000000..8809a06
--- /dev/null
+++ b/web-console/src/views/load-data-view/parse-time-table/__snapshots__/parse-time-table.spec.tsx.snap
@@ -0,0 +1,1014 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`parse time table matches snapshot 1`] = `
+<div
+ class="ReactTable parse-time-table -striped -highlight"
+>
+ <div
+ class="rt-table"
+ role="grid"
+ >
+ <div
+ class="rt-thead -header"
+ style="min-width: 100px;"
+ >
+ <div
+ class="rt-tr"
+ role="row"
+ >
+ <div
+ class="rt-th rt-resizable-header"
+ role="columnheader"
+ style="flex: 100 0 auto; width: 100px;"
+ tabindex="-1"
+ >
+ <div
+ class="rt-resizable-header-content"
+ >
+ <div
+ class="clickable"
+ >
+ <div
+ class="column-name"
+ >
+ c1
+ </div>
+ <div
+ class="column-detail"
+ >
+
+
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-resizer"
+ />
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tbody"
+ style="min-width: 100px;"
+ >
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ hello
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div
+ class="-loading"
+ >
+ <div
+ class="-loading-inner"
+ >
+ Loading...
+ </div>
+ </div>
+</div>
+`;
diff --git a/web-console/src/components/menu-checkbox/menu-checkbox.tsx b/web-console/src/views/load-data-view/parse-time-table/parse-time-table.scss
similarity index 72%
copy from web-console/src/components/menu-checkbox/menu-checkbox.tsx
copy to web-console/src/views/load-data-view/parse-time-table/parse-time-table.scss
index 659a78c..a107a17 100644
--- a/web-console/src/components/menu-checkbox/menu-checkbox.tsx
+++ b/web-console/src/views/load-data-view/parse-time-table/parse-time-table.scss
@@ -16,16 +16,6 @@
* limitations under the License.
*/
-import { Checkbox, ICheckboxProps } from '@blueprintjs/core';
-import React from 'react';
+.parse-time-table {
-import './menu-checkbox.scss';
-
-export class MenuCheckbox extends React.PureComponent<ICheckboxProps, {}> {
-
- render() {
- return <li className="menu-checkbox">
- <Checkbox {...this.props}/>
- </li>;
- }
}
diff --git a/web-console/src/components/sql-control/sql-control.spec.tsx b/web-console/src/views/load-data-view/parse-time-table/parse-time-table.spec.tsx
similarity index 60%
copy from web-console/src/components/sql-control/sql-control.spec.tsx
copy to web-console/src/views/load-data-view/parse-time-table/parse-time-table.spec.tsx
index 1ac07be..ce0be3d 100644
--- a/web-console/src/components/sql-control/sql-control.spec.tsx
+++ b/web-console/src/views/load-data-view/parse-time-table/parse-time-table.spec.tsx
@@ -19,18 +19,33 @@
import React from 'react';
import { render } from 'react-testing-library';
-import { SqlControl } from './sql-control';
+import { getEmptyTimestampSpec } from '../../../utils/ingestion-spec';
-describe('sql control', () => {
+import { ParseTimeTable } from './parse-time-table';
+
+describe('parse time table', () => {
it('matches snapshot', () => {
- const sqlControl = <SqlControl
- initSql={'test'}
- onRun={(query, context, wrapQuery) => {}}
- onExplain={(sqlQuery, context) => {}}
- queryElapsed={2}
+ const sampleData = {
+ header: ['c1'],
+ rows: [
+ {
+ raw: `{"c1":"hello"}`,
+ parsed: { c1: 'hello' }
+ }
+ ]
+ };
+
+ const parseTimeTable = <ParseTimeTable
+ sampleBundle={{
+ headerAndRows: sampleData,
+ timestampSpec: getEmptyTimestampSpec()
+ }}
+ columnFilter=""
+ possibleTimestampColumnsOnly={false}
+ onTimestampColumnSelect={() => null}
/>;
- const { container } = render(sqlControl);
+ const { container } = render(parseTimeTable);
expect(container.firstChild).toMatchSnapshot();
});
});
diff --git a/web-console/src/views/load-data-view/parse-time-table/parse-time-table.tsx b/web-console/src/views/load-data-view/parse-time-table/parse-time-table.tsx
new file mode 100644
index 0000000..b6f1a15
--- /dev/null
+++ b/web-console/src/views/load-data-view/parse-time-table/parse-time-table.tsx
@@ -0,0 +1,105 @@
+/*
+ * 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 classNames from 'classnames';
+import React from 'react';
+import ReactTable from 'react-table';
+
+import { TableCell } from '../../../components';
+import { caseInsensitiveContains, filterMap } from '../../../utils';
+import { possibleDruidFormatForValues } from '../../../utils/druid-time';
+import { getTimestampSpecColumn, isColumnTimestampSpec, TimestampSpec } from '../../../utils/ingestion-spec';
+import { HeaderAndRows, SampleEntry } from '../../../utils/sampler';
+
+import './parse-time-table.scss';
+
+export interface ParseTimeTableProps extends React.Props<any> {
+ sampleBundle: {
+ headerAndRows: HeaderAndRows;
+ timestampSpec: TimestampSpec;
+ };
+ columnFilter: string;
+ possibleTimestampColumnsOnly: boolean;
+ onTimestampColumnSelect: (newTimestampSpec: TimestampSpec) => void;
+}
+
+export class ParseTimeTable extends React.PureComponent<ParseTimeTableProps> {
+ render() {
+ const { sampleBundle, columnFilter, possibleTimestampColumnsOnly, onTimestampColumnSelect } = this.props;
+ const { headerAndRows, timestampSpec } = sampleBundle;
+ const timestampSpecColumn = getTimestampSpecColumn(timestampSpec);
+ const timestampSpecFromColumn = isColumnTimestampSpec(timestampSpec);
+
+ return <ReactTable
+ className="parse-time-table -striped -highlight"
+ data={headerAndRows.rows}
+ columns={filterMap(headerAndRows.header.length ? headerAndRows.header : ['__error__'], (columnName, i) => {
+ const timestamp = columnName === '__time';
+ if (!timestamp && !caseInsensitiveContains(columnName, columnFilter)) return null;
+ const selected = timestampSpec.column === columnName;
+ const possibleFormat = timestamp ? null : possibleDruidFormatForValues(filterMap(headerAndRows.rows, d => d.parsed ? d.parsed[columnName] : null));
+ if (possibleTimestampColumnsOnly && !timestamp && !possibleFormat) return null;
+
+ const columnClassName = classNames({
+ timestamp,
+ selected
+ });
+ return {
+ Header: (
+ <div
+ className={classNames({ clickable: !timestamp })}
+ onClick={timestamp ? undefined : () => {
+ onTimestampColumnSelect({
+ column: columnName,
+ format: possibleFormat || '!!! Could not auto detect a format !!!'
+ });
+ }}
+ >
+ <div className="column-name">{columnName}</div>
+ <div className="column-detail">
+ {
+ timestamp ?
+ (timestampSpecFromColumn ? `from: '${timestampSpecColumn}'` : `mv: ${timestampSpec.missingValue}`) :
+ (possibleFormat || '')
+ }
+ </div>
+ </div>
+ ),
+ headerClassName: columnClassName,
+ className: columnClassName,
+ id: String(i),
+ accessor: (row: SampleEntry) => row.parsed ? row.parsed[columnName] : null,
+ Cell: row => {
+ if (columnName === '__error__') {
+ return <TableCell value={row.original.error}/>;
+ }
+ if (row.original.unparseable) {
+ return <TableCell unparseable/>;
+ }
+ return <TableCell value={row.value} timestamp={timestamp}/>;
+ },
+ minWidth: timestamp ? 200 : 100,
+ resizable: !timestamp
+ };
+ })}
+ defaultPageSize={50}
+ showPagination={false}
+ sortable={false}
+ />;
+ }
+}
diff --git a/web-console/src/views/load-data-view/schema-table/__snapshots__/schema-table.spec.tsx.snap b/web-console/src/views/load-data-view/schema-table/__snapshots__/schema-table.spec.tsx.snap
new file mode 100644
index 0000000..f5f1e2e
--- /dev/null
+++ b/web-console/src/views/load-data-view/schema-table/__snapshots__/schema-table.spec.tsx.snap
@@ -0,0 +1,1014 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`schema table matches snapshot 1`] = `
+<div
+ class="ReactTable schema-table -striped -highlight"
+>
+ <div
+ class="rt-table"
+ role="grid"
+ >
+ <div
+ class="rt-thead -header"
+ style="min-width: 100px;"
+ >
+ <div
+ class="rt-tr"
+ role="row"
+ >
+ <div
+ class="rt-th dimension string rt-resizable-header"
+ role="columnheader"
+ style="flex: 100 0 auto; width: 100px;"
+ tabindex="-1"
+ >
+ <div
+ class="rt-resizable-header-content"
+ >
+ <div
+ class="clickable"
+ >
+ <div
+ class="column-name"
+ >
+ c1
+ </div>
+ <div
+ class="column-detail"
+ >
+ string (auto)
+
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-resizer"
+ />
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tbody"
+ style="min-width: 100px;"
+ >
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ hello
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td dimension string"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div
+ class="-loading"
+ >
+ <div
+ class="-loading-inner"
+ >
+ Loading...
+ </div>
+ </div>
+</div>
+`;
diff --git a/web-console/src/components/view-control-bar/view-control-bar.tsx b/web-console/src/views/load-data-view/schema-table/schema-table.scss
similarity index 61%
copy from web-console/src/components/view-control-bar/view-control-bar.tsx
copy to web-console/src/views/load-data-view/schema-table/schema-table.scss
index bcd3e23..d8e6b37 100644
--- a/web-console/src/components/view-control-bar/view-control-bar.tsx
+++ b/web-console/src/views/load-data-view/schema-table/schema-table.scss
@@ -16,25 +16,30 @@
* limitations under the License.
*/
-import React from 'react';
+.schema-table {
+ .rt-th {
+ &.dimension {
+ background: rgba(38, 170, 201, 0.5);
-import './view-control-bar.scss';
+ &.long { background: rgba(19, 129, 201, 0.5); }
+ &.float { background: rgba(25, 145, 201, 0.5); }
+ }
-export interface ViewControlBarProps {
- label: string;
-}
-
-export class ViewControlBar extends React.PureComponent<ViewControlBarProps, {}> {
- constructor(props: ViewControlBarProps) {
- super(props);
+ &.metric {
+ background: rgba(201, 191, 55, 0.5);
+ }
}
- render() {
- const { label, children } = this.props;
+ .rt-td {
+ &.dimension {
+ background: rgba(38, 170, 201, 0.1);
+
+ &.long { background: rgba(19, 129, 201, 0.1); }
+ &.float { background: rgba(25, 145, 201, 0.1); }
+ }
- return <div className="view-control-bar">
- <div className="control-label">{label}</div>
- {children}
- </div>;
+ &.metric {
+ background: rgba(201, 191, 55, 0.1);
+ }
}
}
diff --git a/web-console/src/components/sql-control/sql-control.spec.tsx b/web-console/src/views/load-data-view/schema-table/schema-table.spec.tsx
similarity index 62%
copy from web-console/src/components/sql-control/sql-control.spec.tsx
copy to web-console/src/views/load-data-view/schema-table/schema-table.spec.tsx
index 1ac07be..e7c2047 100644
--- a/web-console/src/components/sql-control/sql-control.spec.tsx
+++ b/web-console/src/views/load-data-view/schema-table/schema-table.spec.tsx
@@ -19,18 +19,33 @@
import React from 'react';
import { render } from 'react-testing-library';
-import { SqlControl } from './sql-control';
+import { SchemaTable } from './schema-table';
-describe('sql control', () => {
+describe('schema table', () => {
it('matches snapshot', () => {
- const sqlControl = <SqlControl
- initSql={'test'}
- onRun={(query, context, wrapQuery) => {}}
- onExplain={(sqlQuery, context) => {}}
- queryElapsed={2}
+ const sampleData = {
+ header: ['c1'],
+ rows: [
+ {
+ raw: `{"c1":"hello"}`,
+ parsed: { c1: 'hello' }
+ }
+ ]
+ };
+
+ const schemaTable = <SchemaTable
+ sampleBundle={{
+ headerAndRows: sampleData,
+ dimensionsSpec: {},
+ metricsSpec: []
+ }}
+ columnFilter=""
+ selectedDimensionSpecIndex={-1}
+ selectedMetricSpecIndex={-1}
+ onDimensionOrMetricSelect={() => null}
/>;
- const { container } = render(sqlControl);
+ const { container } = render(schemaTable);
expect(container.firstChild).toMatchSnapshot();
});
});
diff --git a/web-console/src/views/load-data-view/schema-table/schema-table.tsx b/web-console/src/views/load-data-view/schema-table/schema-table.tsx
new file mode 100644
index 0000000..1b6f96f
--- /dev/null
+++ b/web-console/src/views/load-data-view/schema-table/schema-table.tsx
@@ -0,0 +1,135 @@
+/*
+ * 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 classNames from 'classnames';
+import React from 'react';
+import ReactTable from 'react-table';
+
+import { TableCell } from '../../../components';
+import { caseInsensitiveContains, filterMap, sortWithPrefixSuffix } from '../../../utils';
+import {
+ DimensionSpec,
+ DimensionsSpec,
+ getDimensionSpecName,
+ getDimensionSpecType,
+ getMetricSpecName,
+ inflateDimensionSpec,
+ MetricSpec, TimestampSpec
+} from '../../../utils/ingestion-spec';
+import { HeaderAndRows, SampleEntry } from '../../../utils/sampler';
+
+import './schema-table.scss';
+
+export interface SchemaTableProps extends React.Props<any> {
+ sampleBundle: {
+ headerAndRows: HeaderAndRows;
+ dimensionsSpec: DimensionsSpec;
+ metricsSpec: MetricSpec[];
+ };
+ columnFilter: string;
+ selectedDimensionSpecIndex: number;
+ selectedMetricSpecIndex: number;
+ onDimensionOrMetricSelect: (
+ selectedDimensionSpec: DimensionSpec | null,
+ selectedDimensionSpecIndex: number,
+ selectedMetricSpec: MetricSpec | null,
+ selectedMetricSpecIndex: number
+ ) => void;
+}
+
+export class SchemaTable extends React.PureComponent<SchemaTableProps> {
+ render() {
+ const { sampleBundle, columnFilter, selectedDimensionSpecIndex, selectedMetricSpecIndex, onDimensionOrMetricSelect } = this.props;
+ const { headerAndRows, dimensionsSpec, metricsSpec } = sampleBundle;
+
+ const dimensionMetricSortedHeader = sortWithPrefixSuffix(headerAndRows.header, ['__time'], metricsSpec.map(getMetricSpecName));
+
+ return <ReactTable
+ className="schema-table -striped -highlight"
+ data={headerAndRows.rows}
+ columns={filterMap(dimensionMetricSortedHeader, (columnName, i) => {
+ if (!caseInsensitiveContains(columnName, columnFilter)) return null;
+
+ const metricSpecIndex = metricsSpec.findIndex(m => getMetricSpecName(m) === columnName);
+ const metricSpec = metricsSpec[metricSpecIndex];
+
+ if (metricSpec) {
+ const columnClassName = classNames('metric', {
+ selected: metricSpec && metricSpecIndex === selectedMetricSpecIndex
+ });
+ return {
+ Header: (
+ <div
+ className="clickable"
+ onClick={() => onDimensionOrMetricSelect(null, -1, metricSpec, metricSpecIndex)}
+ >
+ <div className="column-name">{columnName}</div>
+ <div className="column-detail">
+ {metricSpec.type}
+ </div>
+ </div>
+ ),
+ headerClassName: columnClassName,
+ className: columnClassName,
+ id: String(i),
+ accessor: row => row.parsed ? row.parsed[columnName] : null,
+ Cell: row => <TableCell value={row.value}/>
+ };
+ } else {
+ const timestamp = columnName === '__time';
+ const dimensionSpecIndex = dimensionsSpec.dimensions ? dimensionsSpec.dimensions.findIndex(d => getDimensionSpecName(d) === columnName) : -1;
+ const dimensionSpec = dimensionsSpec.dimensions ? dimensionsSpec.dimensions[dimensionSpecIndex] : null;
+ const dimensionSpecType = dimensionSpec ? getDimensionSpecType(dimensionSpec) : null;
+
+ const columnClassName = classNames(timestamp ? 'timestamp' : 'dimension', dimensionSpecType || 'string', {
+ selected: dimensionSpec && dimensionSpecIndex === selectedDimensionSpecIndex
+ });
+ return {
+ Header: (
+ <div
+ className="clickable"
+ onClick={() => {
+ if (timestamp) {
+ onDimensionOrMetricSelect(null, -1, null, -1);
+ return;
+ }
+
+ if (!dimensionSpec) return;
+ onDimensionOrMetricSelect(inflateDimensionSpec(dimensionSpec), dimensionSpecIndex, null, -1);
+ }}
+ >
+ <div className="column-name">{columnName}</div>
+ <div className="column-detail">
+ {timestamp ? 'long (time column)' : (dimensionSpecType || 'string (auto)')}
+ </div>
+ </div>
+ ),
+ headerClassName: columnClassName,
+ className: columnClassName,
+ id: String(i),
+ accessor: (row: SampleEntry) => row.parsed ? row.parsed[columnName] : null,
+ Cell: row => <TableCell value={row.value} timestamp={timestamp}/>
+ };
+ }
+ })}
+ defaultPageSize={50}
+ showPagination={false}
+ sortable={false}
+ />;
+ }
+}
diff --git a/web-console/src/views/load-data-view/transform-table/__snapshots__/transform-table.spec.tsx.snap b/web-console/src/views/load-data-view/transform-table/__snapshots__/transform-table.spec.tsx.snap
new file mode 100644
index 0000000..2febec3
--- /dev/null
+++ b/web-console/src/views/load-data-view/transform-table/__snapshots__/transform-table.spec.tsx.snap
@@ -0,0 +1,1014 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`transform table matches snapshot 1`] = `
+<div
+ class="ReactTable transform-table -striped -highlight"
+>
+ <div
+ class="rt-table"
+ role="grid"
+ >
+ <div
+ class="rt-thead -header"
+ style="min-width: 100px;"
+ >
+ <div
+ class="rt-tr"
+ role="row"
+ >
+ <div
+ class="rt-th rt-resizable-header"
+ role="columnheader"
+ style="flex: 100 0 auto; width: 100px;"
+ tabindex="-1"
+ >
+ <div
+ class="rt-resizable-header-content"
+ >
+ <div
+ class="clickable"
+ >
+ <div
+ class="column-name"
+ >
+ c1
+ </div>
+ <div
+ class="column-detail"
+ >
+
+
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-resizer"
+ />
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tbody"
+ style="min-width: 100px;"
+ >
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ hello
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -odd"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ <div
+ class="rt-tr-group"
+ role="rowgroup"
+ >
+ <div
+ class="rt-tr -padRow -even"
+ role="row"
+ >
+ <div
+ class="rt-td"
+ role="gridcell"
+ style="flex: 100 0 auto; width: 100px;"
+ >
+ <span>
+
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div
+ class="-loading"
+ >
+ <div
+ class="-loading-inner"
+ >
+ Loading...
+ </div>
+ </div>
+</div>
+`;
diff --git a/web-console/src/components/menu-checkbox/menu-checkbox.tsx b/web-console/src/views/load-data-view/transform-table/transform-table.scss
similarity index 73%
copy from web-console/src/components/menu-checkbox/menu-checkbox.tsx
copy to web-console/src/views/load-data-view/transform-table/transform-table.scss
index 659a78c..0b85f72 100644
--- a/web-console/src/components/menu-checkbox/menu-checkbox.tsx
+++ b/web-console/src/views/load-data-view/transform-table/transform-table.scss
@@ -16,16 +16,16 @@
* limitations under the License.
*/
-import { Checkbox, ICheckboxProps } from '@blueprintjs/core';
-import React from 'react';
-
-import './menu-checkbox.scss';
-
-export class MenuCheckbox extends React.PureComponent<ICheckboxProps, {}> {
+.transform-table {
+ .rt-th {
+ &.transformed {
+ background: rgba(201, 128, 22, 0.2);
+ }
+ }
- render() {
- return <li className="menu-checkbox">
- <Checkbox {...this.props}/>
- </li>;
+ .rt-td {
+ &.transformed {
+ background: rgba(201, 128, 22, 0.05);
+ }
}
}
diff --git a/web-console/src/components/sql-control/sql-control.spec.tsx b/web-console/src/views/load-data-view/transform-table/transform-table.spec.tsx
similarity index 65%
copy from web-console/src/components/sql-control/sql-control.spec.tsx
copy to web-console/src/views/load-data-view/transform-table/transform-table.spec.tsx
index 1ac07be..b750f20 100644
--- a/web-console/src/components/sql-control/sql-control.spec.tsx
+++ b/web-console/src/views/load-data-view/transform-table/transform-table.spec.tsx
@@ -19,18 +19,30 @@
import React from 'react';
import { render } from 'react-testing-library';
-import { SqlControl } from './sql-control';
+import { TransformTable } from './transform-table';
-describe('sql control', () => {
+describe('transform table', () => {
it('matches snapshot', () => {
- const sqlControl = <SqlControl
- initSql={'test'}
- onRun={(query, context, wrapQuery) => {}}
- onExplain={(sqlQuery, context) => {}}
- queryElapsed={2}
+ const sampleData = {
+ header: ['c1'],
+ rows: [
+ {
+ raw: `{"c1":"hello"}`,
+ parsed: { c1: 'hello' }
+ }
+ ]
+ };
+
+ const transformTable = <TransformTable
+ sampleData={sampleData}
+ columnFilter=""
+ transformedColumnsOnly={false}
+ transforms={[]}
+ selectedTransformIndex={-1}
+ onTransformSelect={() => null}
/>;
- const { container } = render(sqlControl);
+ const { container } = render(transformTable);
expect(container.firstChild).toMatchSnapshot();
});
});
diff --git a/web-console/src/views/load-data-view/transform-table/transform-table.tsx b/web-console/src/views/load-data-view/transform-table/transform-table.tsx
new file mode 100644
index 0000000..5a38923
--- /dev/null
+++ b/web-console/src/views/load-data-view/transform-table/transform-table.tsx
@@ -0,0 +1,92 @@
+/*
+ * 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 classNames from 'classnames';
+import React from 'react';
+import ReactTable from 'react-table';
+
+import { TableCell } from '../../../components';
+import { caseInsensitiveContains, filterMap } from '../../../utils';
+import { escapeColumnName } from '../../../utils/druid-expression';
+import { Transform } from '../../../utils/ingestion-spec';
+import { HeaderAndRows } from '../../../utils/sampler';
+
+import './transform-table.scss';
+
+export interface TransformTableProps extends React.Props<any> {
+ sampleData: HeaderAndRows;
+ columnFilter: string;
+ transformedColumnsOnly: boolean;
+ transforms: Transform[];
+ selectedTransformIndex: number;
+ onTransformSelect: (transform: Transform, index: number) => void;
+}
+
+export class TransformTable extends React.PureComponent<TransformTableProps> {
+ render() {
+ const { sampleData, columnFilter, transformedColumnsOnly, transforms, selectedTransformIndex, onTransformSelect } = this.props;
+
+ return <ReactTable
+ className="transform-table -striped -highlight"
+ data={sampleData.rows}
+ columns={filterMap(sampleData.header, (columnName, i) => {
+ if (!caseInsensitiveContains(columnName, columnFilter)) return null;
+ const timestamp = columnName === '__time';
+ const transformIndex = transforms.findIndex(f => f.name === columnName);
+ if (transformIndex === -1 && transformedColumnsOnly) return null;
+ const transform = transforms[transformIndex];
+
+ const columnClassName = classNames({
+ transformed: transform,
+ selected: transform && transformIndex === selectedTransformIndex
+ });
+ return {
+ Header: (
+ <div
+ className={classNames('clickable')}
+ onClick={() => {
+ if (transform) {
+ onTransformSelect(transform, transformIndex);
+ } else {
+ onTransformSelect({
+ type: 'expression',
+ name: columnName,
+ expression: escapeColumnName(columnName)
+ }, transformIndex);
+ }
+ }}
+ >
+ <div className="column-name">{columnName}</div>
+ <div className="column-detail">
+ {transform ? `= ${transform.expression}` : ''}
+ </div>
+ </div>
+ ),
+ headerClassName: columnClassName,
+ className: columnClassName,
+ id: String(i),
+ accessor: row => row.parsed ? row.parsed[columnName] : null,
+ Cell: row => <TableCell value={row.value} timestamp={timestamp}/>
+ };
+ })}
+ defaultPageSize={50}
+ showPagination={false}
+ sortable={false}
+ />;
+ }
+}
diff --git a/web-console/src/components/sql-control/__snapshots__/sql-control.spec.tsx.snap b/web-console/src/views/sql-view/sql-control/__snapshots__/sql-control.spec.tsx.snap
similarity index 98%
rename from web-console/src/components/sql-control/__snapshots__/sql-control.spec.tsx.snap
rename to web-console/src/views/sql-view/sql-control/__snapshots__/sql-control.spec.tsx.snap
index fcb5b8f..80ab5c4 100644
--- a/web-console/src/components/sql-control/__snapshots__/sql-control.spec.tsx.snap
+++ b/web-console/src/views/sql-view/sql-control/__snapshots__/sql-control.spec.tsx.snap
@@ -8,7 +8,7 @@ exports[`sql control matches snapshot 1`] = `
class="ace-container"
>
<div
- class=" ace_editor ace-solarized-dark ace_dark ace_focus"
+ class=" ace_editor ace-tm ace_focus"
id="ace-editor"
style="width: 100%; height: 200px; font-size: 14px;"
>
diff --git a/web-console/src/components/sql-control/sql-control.scss b/web-console/src/views/sql-view/sql-control/sql-control.scss
similarity index 98%
rename from web-console/src/components/sql-control/sql-control.scss
rename to web-console/src/views/sql-view/sql-control/sql-control.scss
index 694de36..95c798b 100644
--- a/web-console/src/components/sql-control/sql-control.scss
+++ b/web-console/src/views/sql-view/sql-control/sql-control.scss
@@ -16,7 +16,7 @@
* limitations under the License.
*/
-@import "../../variables";
+@import "../../../variables";
.sql-control {
.ace-container {
diff --git a/web-console/src/components/sql-control/sql-control.spec.tsx b/web-console/src/views/sql-view/sql-control/sql-control.spec.tsx
similarity index 100%
rename from web-console/src/components/sql-control/sql-control.spec.tsx
rename to web-console/src/views/sql-view/sql-control/sql-control.spec.tsx
diff --git a/web-console/src/components/sql-control/sql-control.tsx b/web-console/src/views/sql-view/sql-control/sql-control.tsx
similarity index 96%
rename from web-console/src/components/sql-control/sql-control.tsx
rename to web-console/src/views/sql-view/sql-control/sql-control.tsx
index 4006105..44730b9 100644
--- a/web-console/src/components/sql-control/sql-control.tsx
+++ b/web-console/src/views/sql-view/sql-control/sql-control.tsx
@@ -29,20 +29,15 @@ import { Hotkey, Hotkeys, HotkeysTarget } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import axios from 'axios';
import ace from 'brace';
-import 'brace/ext/language_tools';
-import 'brace/mode/hjson';
-import 'brace/mode/sql';
-import 'brace/theme/solarized_dark';
import Hjson from 'hjson';
import React from 'react';
import AceEditor from 'react-ace';
import ReactDOMServer from 'react-dom/server';
-import { SQLFunctionDoc } from '../../../lib/sql-function-doc';
-import { AppToaster } from '../../singletons/toaster';
-import { DRUID_DOCS_RUNE, DRUID_DOCS_SQL } from '../../variables';
-
-import { MenuCheckbox } from './../menu-checkbox/menu-checkbox';
+import { SQLFunctionDoc } from '../../../../lib/sql-function-doc';
+import { MenuCheckbox } from '../../../components';
+import { AppToaster } from '../../../singletons/toaster';
+import { DRUID_DOCS_RUNE, DRUID_DOCS_SQL } from '../../../variables';
import './sql-control.scss';
diff --git a/web-console/src/views/sql-view/sql-view.tsx b/web-console/src/views/sql-view/sql-view.tsx
index 178b980..fedd243 100644
--- a/web-console/src/views/sql-view/sql-view.tsx
+++ b/web-console/src/views/sql-view/sql-view.tsx
@@ -21,7 +21,7 @@ import React from 'react';
import SplitterLayout from 'react-splitter-layout';
import ReactTable from 'react-table';
-import { SqlControl, TableCell } from '../../components';
+import { TableCell } from '../../components';
import { QueryPlanDialog } from '../../dialogs';
import {
BasicQueryExplanation,
@@ -34,6 +34,8 @@ import {
SemiJoinQueryExplanation
} from '../../utils';
+import { SqlControl } from './sql-control/sql-control';
+
import './sql-view.scss';
interface QueryWithContext {
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org