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 b6b1e61 Added tslint to web console (#7280)
b6b1e61 is described below
commit b6b1e6160ca38e3140e151f7bf5133e6809ae1be
Author: Vadim Ogievetsky <[email protected]>
AuthorDate: Sun Mar 17 09:23:17 2019 -0700
Added tslint to web console (#7280)
* added tslint to web console
* added react linting and made rules stricter
* order imports
* update package-lock
---
web-console/package-lock.json | 117 +++++++++++++++++++
web-console/package.json | 3 +
web-console/script/create-sql-function-doc | 41 +++++--
.../a-shim-for-react-props.ts} | 11 +-
.../react-table-defaults.tsx | 4 +-
web-console/src/components/auto-form.tsx | 19 ++--
web-console/src/components/filler.tsx | 25 ++---
web-console/src/components/header-bar.tsx | 52 ++++++---
web-console/src/components/loader.tsx | 31 +++--
web-console/src/components/rule-editor.tsx | 30 ++---
web-console/src/components/sql-control.tsx | 57 +++++-----
web-console/src/console-application.tsx | 82 +++++++++-----
web-console/src/dialogs/about-dialog.tsx | 7 +-
web-console/src/dialogs/async-action-dialog.tsx | 26 ++---
.../src/dialogs/coordinator-dynamic-config.tsx | 19 ++--
web-console/src/dialogs/lookup-edit-dialog.tsx | 48 ++++----
web-console/src/dialogs/retention-dialog.tsx | 12 +-
web-console/src/dialogs/snitch-dialog.tsx | 14 +--
web-console/src/dialogs/spec-dialog.tsx | 19 ++--
web-console/src/entry.ts | 7 +-
web-console/src/singletons/toaster.ts | 2 +-
web-console/src/utils/general.tsx | 14 +--
web-console/src/utils/query-manager.tsx | 6 +-
web-console/src/utils/rune-decoder.tsx | 7 +-
web-console/src/views/datasource-view.tsx | 36 +++---
web-console/src/views/home-view.tsx | 27 ++---
web-console/src/views/lookups-view.tsx | 86 +++++++-------
web-console/src/views/segments-view.tsx | 28 ++---
web-console/src/views/servers-view.tsx | 37 +++---
web-console/src/views/sql-view.tsx | 19 ++--
web-console/src/views/tasks-view.tsx | 43 +++----
web-console/tslint.json | 125 +++++++++++++++++++++
web-console/webpack.config.js | 14 +++
33 files changed, 719 insertions(+), 349 deletions(-)
diff --git a/web-console/package-lock.json b/web-console/package-lock.json
index 8c5035a..5c60be7 100644
--- a/web-console/package-lock.json
+++ b/web-console/package-lock.json
@@ -944,6 +944,65 @@
"is-buffer": "^1.1.5"
}
},
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved":
"https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "dev": true,
+ "requires": {
+ "chalk": "^1.1.3",
+ "esutils": "^2.0.2",
+ "js-tokens": "^3.0.2"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved":
"https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved":
"https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved":
"https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved":
"https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved":
"https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ },
"babel-jest": {
"version": "24.1.0",
"resolved":
"https://registry.npmjs.org/babel-jest/-/babel-jest-24.1.0.tgz",
@@ -1372,6 +1431,12 @@
"integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
"dev": true
},
+ "builtin-modules": {
+ "version": "1.1.1",
+ "resolved":
"https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+ "dev": true
+ },
"builtin-status-codes": {
"version": "3.0.0",
"resolved":
"https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
@@ -9636,6 +9701,58 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
"integrity":
"sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
},
+ "tslint": {
+ "version": "5.14.0",
+ "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.14.0.tgz",
+ "integrity":
"sha512-IUla/ieHVnB8Le7LdQFRGlVJid2T/gaJe5VkjzRVSRR6pA2ODYrnfR1hmxi+5+au9l50jBwpbBL34txgv4NnTQ==",
+ "dev": true,
+ "requires": {
+ "babel-code-frame": "^6.22.0",
+ "builtin-modules": "^1.1.1",
+ "chalk": "^2.3.0",
+ "commander": "^2.12.1",
+ "diff": "^3.2.0",
+ "glob": "^7.1.1",
+ "js-yaml": "^3.7.0",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "resolve": "^1.3.2",
+ "semver": "^5.3.0",
+ "tslib": "^1.8.0",
+ "tsutils": "^2.29.0"
+ }
+ },
+ "tslint-loader": {
+ "version": "3.5.4",
+ "resolved":
"https://registry.npmjs.org/tslint-loader/-/tslint-loader-3.5.4.tgz",
+ "integrity":
"sha512-jBHNNppXut6SgZ7CsTBh+6oMwVum9n8azbmcYSeMlsABhWWoHwjq631vIFXef3VSd75cCdX3rc6kstsB7rSVVw==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "object-assign": "^4.1.1",
+ "rimraf": "^2.4.4",
+ "semver": "^5.3.0"
+ }
+ },
+ "tslint-react": {
+ "version": "3.6.0",
+ "resolved":
"https://registry.npmjs.org/tslint-react/-/tslint-react-3.6.0.tgz",
+ "integrity":
"sha512-AIv1QcsSnj7e9pFir6cJ6vIncTqxfqeFF3Lzh8SuuBljueYzEAtByuB6zMaD27BL0xhMEqsZ9s5eHuCONydjBw==",
+ "dev": true,
+ "requires": {
+ "tsutils": "^2.13.1"
+ }
+ },
+ "tsutils": {
+ "version": "2.29.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
+ "integrity":
"sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
"tty-browserify": {
"version": "0.0.0",
"resolved":
"https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
diff --git a/web-console/package.json b/web-console/package.json
index 201100c..fcde0ad 100644
--- a/web-console/package.json
+++ b/web-console/package.json
@@ -70,6 +70,9 @@
"ts-jest": "^23.10.5",
"ts-loader": "^5.3.3",
"ts-node": "^8.0.2",
+ "tslint": "^5.14.0",
+ "tslint-loader": "^3.5.4",
+ "tslint-react": "^3.6.0",
"typescript": "^3.2.4",
"webpack": "^4.29.0",
"webpack-cli": "^3.2.1",
diff --git a/web-console/script/create-sql-function-doc
b/web-console/script/create-sql-function-doc
index 146a39e..0142178 100755
--- a/web-console/script/create-sql-function-doc
+++ b/web-console/script/create-sql-function-doc
@@ -21,8 +21,35 @@ writefile='lib/sql-function-doc.ts'
> "$writefile"
-echo -e "// This file is auto generated and should not be modified\n" >
"$writefile"
-echo -e 'export const SQLFunctionDoc: any[] = [' >> "$writefile"
+cat > "$writefile" <<- EOM
+/*
+ * 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.
+ */
+
+// This file is auto generated and should not be modified
+
+export interface FunctionDescription {
+ syntax: string;
+ description: string;
+}
+
+/* tslint:disable */
+export const SQLFunctionDoc: FunctionDescription[] = [
+EOM
isFunction=false
@@ -39,12 +66,12 @@ while read -r line; do
description=$(echo $line | grep -o '`|.*.|')
description=${description//\"/\'}
description=${description:2:${#description}-4}
- echo -e " {" >> "$writefile"
- echo -e " syntax: \"$syntax\"," >> "$writefile"
- echo -e " description: \"$description\"" >> "$writefile"
- echo -e " }," >> "$writefile"
+ echo -e " {" >> "$writefile"
+ echo -e " syntax: \"$syntax\"," >> "$writefile"
+ echo -e " description: \"$description\"" >> "$writefile"
+ echo -e " }," >> "$writefile"
fi
fi
done < "$readfile"
-echo -e ']' >> "$writefile"
\ No newline at end of file
+echo -e '];' >> "$writefile"
diff --git a/web-console/src/singletons/toaster.ts
b/web-console/src/bootstrap/a-shim-for-react-props.ts
similarity index 71%
copy from web-console/src/singletons/toaster.ts
copy to web-console/src/bootstrap/a-shim-for-react-props.ts
index 3f4998e..844e0f3 100644
--- a/web-console/src/singletons/toaster.ts
+++ b/web-console/src/bootstrap/a-shim-for-react-props.ts
@@ -16,9 +16,10 @@
* limitations under the License.
*/
-import { Position, Toaster } from "@blueprintjs/core";
+// Trick blueprint 1.0.1 into accepting React 16 as React 15.
+// This is broken into its own file to make linting and import sorting easy
+// This file "a" to make sure it is imported before console-application in
entry.ts
-export const AppToaster = Toaster.create({
- className: "recipe-toaster",
- position: Position.TOP,
-});
+// tslint:disable
+import * as React from 'react';
+(React as any).PropTypes = require('prop-types');
diff --git a/web-console/src/singletons/react-table-defaults.tsx
b/web-console/src/bootstrap/react-table-defaults.tsx
similarity index 100%
rename from web-console/src/singletons/react-table-defaults.tsx
rename to web-console/src/bootstrap/react-table-defaults.tsx
index 86cfd6d..edb776c 100644
--- a/web-console/src/singletons/react-table-defaults.tsx
+++ b/web-console/src/bootstrap/react-table-defaults.tsx
@@ -16,10 +16,10 @@
* limitations under the License.
*/
-
+import { Button } from "@blueprintjs/core";
import * as React from 'react';
import { Filter, ReactTableDefaults } from "react-table";
-import { Button } from "@blueprintjs/core";
+
import { Loader } from '../components/loader';
import { countBy, makeTextFilter } from '../utils';
diff --git a/web-console/src/components/auto-form.tsx
b/web-console/src/components/auto-form.tsx
index 39e8baa..6f86a41 100644
--- a/web-console/src/components/auto-form.tsx
+++ b/web-console/src/components/auto-form.tsx
@@ -16,11 +16,10 @@
* limitations under the License.
*/
-import { resolveSrv } from 'dns';
-import * as React from 'react';
-import axios from 'axios';
import { InputGroup } from "@blueprintjs/core";
-import { HTMLSelect, FormGroup, NumericInput, TagInput } from
"../components/filler";
+import * as React from 'react';
+
+import { FormGroup, HTMLSelect, NumericInput, TagInput } from
"../components/filler";
interface Field {
name: string;
@@ -31,8 +30,8 @@ interface Field {
export interface AutoFormProps<T> extends React.Props<any> {
fields: Field[];
- model: T | null,
- onChange: (newValue: T) => void
+ model: T | null;
+ onChange: (newValue: T) => void;
}
export interface AutoFormState<T> {
@@ -48,7 +47,7 @@ export class AutoForm<T> extends
React.Component<AutoFormProps<T>, AutoFormState
constructor(props: AutoFormProps<T>) {
super(props);
this.state = {
- }
+ };
}
private renderNumberInput(field: Field): JSX.Element {
@@ -97,7 +96,7 @@ export class AutoForm<T> extends
React.Component<AutoFormProps<T>, AutoFormState
>
<option value="True">True</option>
<option value="False">False</option>
- </HTMLSelect>
+ </HTMLSelect>;
}
private renderStringArrayInput(field: Field): JSX.Element {
@@ -127,7 +126,7 @@ export class AutoForm<T> extends
React.Component<AutoFormProps<T>, AutoFormState
const label = field.label || AutoForm.makeLabelName(field.name);
return <FormGroup label={label} key={field.name}>
{this.renderFieldInput(field)}
- </FormGroup>
+ </FormGroup>;
}
render() {
@@ -135,6 +134,6 @@ export class AutoForm<T> extends
React.Component<AutoFormProps<T>, AutoFormState
return <div className="auto-form">
{model && fields.map(field => this.renderField(field))}
- </div>
+ </div>;
}
}
diff --git a/web-console/src/components/filler.tsx
b/web-console/src/components/filler.tsx
index a0685f6..e20cd77 100644
--- a/web-console/src/components/filler.tsx
+++ b/web-console/src/components/filler.tsx
@@ -17,10 +17,10 @@
*/
import { Button } from '@blueprintjs/core';
-import * as React from 'react';
import classNames from 'classnames';
-import './filler.scss';
+import * as React from 'react';
+import './filler.scss';
export const IconNames = {
ERROR: "error" as "error",
@@ -103,16 +103,15 @@ export class FormGroup extends React.Component<{
className?: string, label?: str
render() {
const { className, label, children } = this.props;
return <div className={classNames("form-group", className)}>
- { label ? <Label>{label}</Label> : null }
+ {label ? <Label>{label}</Label> : null}
{children}
</div>;
}
}
-
export const Alignment = {
LEFT: "left" as "left",
- RIGHT: "right" as "right",
+ RIGHT: "right" as "right"
};
export type Alignment = typeof Alignment[keyof typeof Alignment];
@@ -166,7 +165,7 @@ export interface NumericInputProps {
min?: number;
max?: number;
stepSize?: number;
- majorStepSize?: number
+ majorStepSize?: number;
}
export class NumericInput extends React.Component<NumericInputProps, {
stringValue: string }> {
@@ -174,20 +173,20 @@ export class NumericInput extends
React.Component<NumericInputProps, { stringVal
static defaultProps = {
stepSize: 1,
majorStepSize: 10
- }
+ };
constructor(props: NumericInputProps) {
super(props);
this.state = {
stringValue: typeof props.value === 'number' ? String(props.value) : ''
- }
+ };
}
private constrain(n: number): number {
const { min, max } = this.props;
if (typeof min === 'number') n = Math.max(n, min);
if (typeof max === 'number') n = Math.min(n, max);
- return n
+ return n;
}
private handleChange = (e: any) => {
@@ -236,13 +235,13 @@ export class TagInput extends
React.Component<TagInputProps, { stringValue: stri
super(props);
this.state = {
stringValue: Array.isArray(props.values) ? props.values.join(', ') : ''
- }
+ };
}
handleChange = (e: any) => {
- let stringValue = e.target.value;
- let newValues = stringValue.split(',').map((v: string) => v.trim());
- let newValuesFiltered = newValues.filter(Boolean);
+ const stringValue = e.target.value;
+ const newValues = stringValue.split(',').map((v: string) => v.trim());
+ const newValuesFiltered = newValues.filter(Boolean);
this.setState({
stringValue: newValues.length === newValuesFiltered.length ?
newValues.join(', ') : stringValue
});
diff --git a/web-console/src/components/header-bar.tsx
b/web-console/src/components/header-bar.tsx
index b4e4dad..9eea252 100644
--- a/web-console/src/components/header-bar.tsx
+++ b/web-console/src/components/header-bar.tsx
@@ -16,13 +16,13 @@
* limitations under the License.
*/
-import * as React from 'react';
+import { AnchorButton, Button, Classes, Menu, MenuItem, Popover, Position }
from "@blueprintjs/core";
import classNames from 'classnames';
-import { Button, Classes, AnchorButton, Popover, Position, Menu, MenuItem }
from "@blueprintjs/core";
-import { IconNames, NavbarGroup, Alignment, NavbarDivider, Navbar } from
"../components/filler";
+import * as React from 'react';
+
+import { Alignment, IconNames, Navbar, NavbarDivider, NavbarGroup } from
"../components/filler";
import { AboutDialog } from "../dialogs/about-dialog";
import { CoordinatorDynamicConfigDialog } from
'../dialogs/coordinator-dynamic-config';
-import "./header-bar.scss";
import {
DRUID_DOCS,
DRUID_GITHUB,
@@ -31,6 +31,8 @@ import {
LEGACY_OVERLORD_CONSOLE
} from '../variables';
+import "./header-bar.scss";
+
export type HeaderActiveTab = null | 'datasources' | 'segments' | 'tasks' |
'servers' | 'sql' | 'lookups';
export interface HeaderBarProps extends React.Props<any> {
@@ -54,30 +56,48 @@ export class HeaderBar extends
React.Component<HeaderBarProps, HeaderBarState> {
renderLogo() {
return <div className="logo">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 288
134">
- <path fill="#FFFFFF"
d="M136.7,67.5c0.5-6.1,5-10.4,10.6-10.4c3.9,0,6.5,2,7.4,4.3l1.1-12.4c0-0.1,0.3-0.2,0.7-0.2
+ <path
+ fill="#FFFFFF"
+
d="M136.7,67.5c0.5-6.1,5-10.4,10.6-10.4c3.9,0,6.5,2,7.4,4.3l1.1-12.4c0-0.1,0.3-0.2,0.7-0.2
c0.7,0,1.3,0.4,1.2,2l-2.3,25.9c-0.1,0.7-0.5,1-1,1h-0.2c-0.6,0-0.9-0.3-0.8-1l0.3-3.2c-1.7,2.7-4.5,4.5-8.3,4.5
C139.9,77.9,136.2,73.7,136.7,67.5z
M154,68.9l0.4-4.7c-0.9-3.3-3.3-5.4-7.2-5.4c-4.5,0-8.1,3.6-8.5,8.6
- c-0.4,5.1,2.5,8.7,6.9,8.7C150,76.1,153.7,72.9,154,68.9z"/>
- <path fill="#FFFFFF"
d="M161.2,76.6l1.7-19.1c0,0,0.3-0.2,0.7-0.2c0.7,0,1.3,0.4,1.1,2l-0.2,2.5c1.1-3.3,3.3-4.8,6-4.8
+ c-0.4,5.1,2.5,8.7,6.9,8.7C150,76.1,153.7,72.9,154,68.9z"
+ />
+ <path
+ fill="#FFFFFF"
+
d="M161.2,76.6l1.7-19.1c0,0,0.3-0.2,0.7-0.2c0.7,0,1.3,0.4,1.1,2l-0.2,2.5c1.1-3.3,3.3-4.8,6-4.8
c1.6,0,2.7,0.7,2.6,1.7c-0.1,0.8-0.6,1.1-0.7,1.1c-0.5-0.5-1.3-0.8-2.3-0.8c-3.6,0-5.6,3.6-6.1,9l-0.8,8.7c-0.1,0.7-0.5,1-1,1
- h-0.2C161.5,77.6,161.2,77.4,161.2,76.6z"/>
- <path fill="#FFFFFF"
d="M175.6,69l0.9-10.7c0.1-0.8,0.5-1,1-1h0.3c0.5,0,0.9,0.2,0.8,1l-0.9,10.5c-0.4,4.4,1.5,7.2,5.5,7.2
+ h-0.2C161.5,77.6,161.2,77.4,161.2,76.6z"
+ />
+ <path
+ fill="#FFFFFF"
+
d="M175.6,69l0.9-10.7c0.1-0.8,0.5-1,1-1h0.3c0.5,0,0.9,0.2,0.8,1l-0.9,10.5c-0.4,4.4,1.5,7.2,5.5,7.2
c3.3,0,6-1.9,7.5-4.7l1.1-13c0.1-0.8,0.5-1,1-1h0.3c0.5,0,0.9,0.2,0.8,1l-1.7,19.1c0,0-0.4,0.2-0.7,0.2c-0.7,0-1.2-0.4-1.1-2
-
l0.2-1.8c-1.6,2.4-4.2,4.1-7.6,4.1C177.6,77.9,175.2,74.4,175.6,69z"/>
- <path fill="#FFFFFF"
d="M200.1,50.7c0.1-1,0.6-1.4,1.6-1.4c0.9,0,1.4,0.5,1.3,1.4c-0.1,0.9-0.6,1.4-1.6,1.4
+
l0.2-1.8c-1.6,2.4-4.2,4.1-7.6,4.1C177.6,77.9,175.2,74.4,175.6,69z"
+ />
+ <path
+ fill="#FFFFFF"
+
d="M200.1,50.7c0.1-1,0.6-1.4,1.6-1.4c0.9,0,1.4,0.5,1.3,1.4c-0.1,0.9-0.6,1.4-1.6,1.4
C200.5,52.1,200,51.6,200.1,50.7z
M198.2,76.6l1.6-18.3c0.1-0.8,0.5-1,1-1h0.3c0.5,0,0.9,0.2,0.8,1l-1.6,18.3
- c-0.1,0.8-0.5,1-1,1H199C198.5,77.6,198.2,77.4,198.2,76.6z"/>
- <path fill="#FFFFFF"
d="M205.8,67.5c0.5-6.1,5-10.4,10.6-10.4c3.9,0,6.5,2,7.4,4.3l1.1-12.4c0-0.1,0.3-0.2,0.7-0.2
+ c-0.1,0.8-0.5,1-1,1H199C198.5,77.6,198.2,77.4,198.2,76.6z"
+ />
+ <path
+ fill="#FFFFFF"
+
d="M205.8,67.5c0.5-6.1,5-10.4,10.6-10.4c3.9,0,6.5,2,7.4,4.3l1.1-12.4c0-0.1,0.3-0.2,0.7-0.2
c0.7,0,1.3,0.4,1.2,2l-2.3,25.9c-0.1,0.7-0.5,1-1,1h-0.2c-0.5,0-0.9-0.3-0.8-1l0.3-3.2c-1.7,2.7-4.5,4.5-8.3,4.5
C209,77.9,205.2,73.7,205.8,67.5z
M223.1,68.9l0.4-4.7c-0.9-3.3-3.3-5.4-7.2-5.4c-4.5,0-8.1,3.6-8.5,8.6
- c-0.4,5.1,2.5,8.7,6.9,8.7C219,76.1,222.7,72.9,223.1,68.9z"/>
- <path fill="#2CEEFB"
d="M96.2,89.8h-2.7c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h2.7c11.5,0,23.8-7.4,23.8-23.7
+ c-0.4,5.1,2.5,8.7,6.9,8.7C219,76.1,222.7,72.9,223.1,68.9z"
+ />
+ <path
+ fill="#2CEEFB"
+
d="M96.2,89.8h-2.7c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h2.7c11.5,0,23.8-7.4,23.8-23.7
c0-9.1-6.9-15.8-16.4-15.8H80c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h23.6c5.3,0,10.1,1.9,13.6,5.3
c3.5,3.4,5.4,8,5.4,13.1c0,6.6-2.3,13-6.3,17.7C111.5,86.8,104.5,89.8,96.2,89.8z
M87.1,89.8h-5.8c-0.7,0-1.3-0.6-1.3-1.3
c0-0.7,0.6-1.3,1.3-1.3h5.8c0.7,0,1.3,0.6,1.3,1.3C88.4,89.2,87.8,89.8,87.1,89.8z
M97.7,79.5h-26c-0.7,0-1.3-0.6-1.3-1.3
c0-0.7,0.6-1.3,1.3-1.3h26c7.5,0,11.5-5.8,11.5-11.5c0-4.2-3.2-7.3-7.7-7.3h-26c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3
h26c5.9,0,10.3,4.3,10.3,9.9c0,3.7-1.3,7.2-3.7,9.8C105.5,78,101.9,79.5,97.7,79.5z
M69.2,58h-6.3c-0.7,0-1.3-0.6-1.3-1.3
-
c0-0.7,0.6-1.3,1.3-1.3h6.3c0.7,0,1.3,0.6,1.3,1.3C70.5,57.4,69.9,58,69.2,58z"/>
+
c0-0.7,0.6-1.3,1.3-1.3h6.3c0.7,0,1.3,0.6,1.3,1.3C70.5,57.4,69.9,58,69.2,58z"
+ />
</svg>
</div>;
}
diff --git a/web-console/src/components/loader.tsx
b/web-console/src/components/loader.tsx
index cb9ef81..3a122b9 100644
--- a/web-console/src/components/loader.tsx
+++ b/web-console/src/components/loader.tsx
@@ -17,6 +17,7 @@
*/
import * as React from 'react';
+
import './loader.scss';
export interface LoaderProps extends React.Props<any> {
@@ -31,23 +32,35 @@ export class Loader extends React.Component<LoaderProps,
LoaderState> {
render() {
const { loadingText, loading } = this.props;
- if (loading === false) return null;
+ if (!loading) return null;
return <div className="loader">
<div className="loader-logo">
<svg viewBox="0 0 100 100">
- <path className="one"
d="M54.2,69.8h-2.7c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h2.7c11.5,0,23.8-7.4,23.8-23.7
+ <path
+ className="one"
+
d="M54.2,69.8h-2.7c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h2.7c11.5,0,23.8-7.4,23.8-23.7
c0-9.1-6.9-15.8-16.4-15.8H38c-0.7,0-1.3-0.6-1.3-1.3s0.6-1.3,1.3-1.3h23.6c5.3,0,10.1,1.9,13.6,5.3c3.5,3.4,5.4,8,5.4,13.1
- c0,6.6-2.3,13-6.3,17.7C69.5,66.8,62.5,69.8,54.2,69.8z"/>
- <path className="two"
d="M55.7,59.5h-26c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h26c7.5,0,11.5-5.8,11.5-11.5
+ c0,6.6-2.3,13-6.3,17.7C69.5,66.8,62.5,69.8,54.2,69.8z"
+ />
+ <path
+ className="two"
+
d="M55.7,59.5h-26c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h26c7.5,0,11.5-5.8,11.5-11.5
c0-4.2-3.2-7.3-7.7-7.3h-26c-0.7,0-1.3-0.6-1.3-1.3s0.6-1.3,1.3-1.3h26c5.9,0,10.3,4.3,10.3,9.9c0,3.7-1.3,7.2-3.7,9.8
- C63.5,58,59.9,59.5,55.7,59.5z"/>
- <path className="three"
d="M27.2,38h-6.3c-0.7,0-1.3-0.6-1.3-1.3s0.6-1.3,1.3-1.3h6.3c0.7,0,1.3,0.6,1.3,1.3S27.9,38,27.2,38z"/>
- <path className="four"
d="M45.1,69.8h-5.8c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h5.8c0.7,0,1.3,0.6,1.3,1.3
- C46.4,69.2,45.8,69.8,45.1,69.8z"/>
+ C63.5,58,59.9,59.5,55.7,59.5z"
+ />
+ <path
+ className="three"
+
d="M27.2,38h-6.3c-0.7,0-1.3-0.6-1.3-1.3s0.6-1.3,1.3-1.3h6.3c0.7,0,1.3,0.6,1.3,1.3S27.9,38,27.2,38z"
+ />
+ <path
+ className="four"
+
d="M45.1,69.8h-5.8c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h5.8c0.7,0,1.3,0.6,1.3,1.3
+ C46.4,69.2,45.8,69.8,45.1,69.8z"
+ />
</svg>
{loadingText ? <div className="label">{loadingText}</div> : null}
</div>
- </div>
+ </div>;
}
}
diff --git a/web-console/src/components/rule-editor.tsx
b/web-console/src/components/rule-editor.tsx
index a431ce6..f13f046 100644
--- a/web-console/src/components/rule-editor.tsx
+++ b/web-console/src/components/rule-editor.tsx
@@ -16,10 +16,12 @@
* limitations under the License.
*/
-import * as React from 'react';
+import { Button, Collapse, InputGroup } from "@blueprintjs/core";
import axios from 'axios';
-import { Button, InputGroup, Collapse } from "@blueprintjs/core";
-import { IconNames, FormGroup, HTMLSelect, Card, ControlGroup, NumericInput,
TagInput } from "../components/filler";
+import * as React from 'react';
+
+import { Card, ControlGroup, FormGroup, HTMLSelect, IconNames, NumericInput,
TagInput } from "../components/filler";
+
import './rule-editor.scss';
export interface Rule {
@@ -107,7 +109,7 @@ export class RuleEditor extends
React.Component<RuleEditorProps, RuleEditorState
super(props);
this.state = {
isOpen: true
- }
+ };
}
private removeTier = (key: string) => {
@@ -126,9 +128,9 @@ export class RuleEditor extends
React.Component<RuleEditorProps, RuleEditorState
let newTierName = tiers[0];
if (rule.tieredReplicants) {
- for (let i = 0; i < tiers.length; i++) {
- if (rule.tieredReplicants[tiers[i]] === undefined) {
- newTierName = tiers[i];
+ for (const tier of tiers) {
+ if (rule.tieredReplicants[tier] === undefined) {
+ newTierName = tier;
break;
}
}
@@ -160,7 +162,7 @@ export class RuleEditor extends
React.Component<RuleEditorProps, RuleEditorState
/>
<Button className="pt-minimal" style={{pointerEvents:
'none'}}>Tier:</Button>
<HTMLSelect
- fill={true}
+ fill
value={tier}
onChange={(e: any) => onChange(RuleEditor.changeTier(rule, tier,
e.target.value))}
>
@@ -194,7 +196,7 @@ export class RuleEditor extends
React.Component<RuleEditorProps, RuleEditorState
return <FormGroup label="Colocated datasources:">
<TagInput
values={rule.colocatedDataSources || []}
- onChange={(v: any) =>
onChange(RuleEditor.changeColocatedDataSources(rule, v)) }
+ onChange={(v: any) =>
onChange(RuleEditor.changeColocatedDataSources(rule, v))}
fill
/>
</FormGroup>;
@@ -240,21 +242,21 @@ export class RuleEditor extends
React.Component<RuleEditorProps, RuleEditorState
<option value="ByPeriod">by period</option>
<option value="ByInterval">by interval</option>
</HTMLSelect>
- { ruleTimeType === 'ByPeriod' && <InputGroup value={rule.period
|| ''} onChange={(e: any) => onChange(RuleEditor.changePeriod(rule,
e.target.value as any))}/>}
- { ruleTimeType === 'ByInterval' && <InputGroup
value={rule.interval || ''} onChange={(e: any) =>
onChange(RuleEditor.changeInterval(rule, e.target.value as any))}/>}
+ {ruleTimeType === 'ByPeriod' && <InputGroup value={rule.period
|| ''} onChange={(e: any) => onChange(RuleEditor.changePeriod(rule,
e.target.value as any))}/>}
+ {ruleTimeType === 'ByInterval' && <InputGroup
value={rule.interval || ''} onChange={(e: any) =>
onChange(RuleEditor.changeInterval(rule, e.target.value as any))}/>}
</ControlGroup>
</FormGroup>
{
ruleLoadType === 'load' &&
<FormGroup>
- { this.renderTiers() }
- { this.renderTierAdder() }
+ {this.renderTiers()}
+ {this.renderTierAdder()}
</FormGroup>
}
{
ruleLoadType === 'broadcast' &&
<FormGroup>
- { this.renderColocatedDataSources() }
+ {this.renderColocatedDataSources()}
</FormGroup>
}
</Card>
diff --git a/web-console/src/components/sql-control.tsx
b/web-console/src/components/sql-control.tsx
index a2d21b5..c63b880 100644
--- a/web-console/src/components/sql-control.tsx
+++ b/web-console/src/components/sql-control.tsx
@@ -16,21 +16,24 @@
* limitations under the License.
*/
-import * as React from 'react';
-import * as ReactDOMServer from 'react-dom/server';
+import { Button, Checkbox, Classes, Intent, Popover, Position } from
"@blueprintjs/core";
import axios from "axios";
-import * as classNames from 'classnames';
-import * as ace from 'brace'
-import AceEditor from "react-ace";
-import 'brace/mode/sql';
+import * as ace from 'brace';
+import 'brace/ext/language_tools';
import 'brace/mode/hjson';
+import 'brace/mode/sql';
import 'brace/theme/solarized_dark';
-import 'brace/ext/language_tools';
-import {Intent, Button, Popover, Checkbox, Classes, Position} from
"@blueprintjs/core";
+import * as classNames from 'classnames';
+import * as React from 'react';
+import AceEditor from "react-ace";
+import * as ReactDOMServer from 'react-dom/server';
+
import { SQLFunctionDoc } from "../../lib/sql-function-doc";
+import { AppToaster } from "../singletons/toaster";
+
import { IconNames } from './filler';
-import './sql-control.scss'
-import {AppToaster} from "../singletons/toaster";
+
+import './sql-control.scss';
const langTools = ace.acequire('ace/ext/language_tools');
@@ -55,9 +58,8 @@ export class SqlControl extends
React.Component<SqlControlProps, SqlControlState
};
}
-
- private addDatasourceAutoCompleter = async (): Promise<any> =>{
- const datasourceResp = await axios.post("/druid/v2/sql", { query: `SELECT
datasource FROM sys.segments GROUP BY 1`})
+ private addDatasourceAutoCompleter = async (): Promise<any> => {
+ const datasourceResp = await axios.post("/druid/v2/sql", { query: `SELECT
datasource FROM sys.segments GROUP BY 1`});
const datasourceList: any[] = datasourceResp.data.map((d: any) => {
const datasourceName: string = d.datasource;
return {
@@ -68,7 +70,7 @@ export class SqlControl extends
React.Component<SqlControlProps, SqlControlState
});
const completer = {
- getCompletions: (editor:any , session: any, pos: any, prefix: any,
callback: any) => {
+ getCompletions: (editor: any, session: any, pos: any, prefix: any,
callback: any) => {
callback(null, datasourceList);
}
};
@@ -77,7 +79,7 @@ export class SqlControl extends
React.Component<SqlControlProps, SqlControlState
}
private addColumnNameAutoCompleter = async (): Promise<any> => {
- const columnNameResp = await axios.post("/druid/v2/sql", {query: `SELECT
COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'druid'`})
+ const columnNameResp = await axios.post("/druid/v2/sql", {query: `SELECT
COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'druid'`});
const columnNameList: any[] = columnNameResp.data.map((d: any) => {
const columnName: string = d.COLUMN_NAME;
return {
@@ -88,7 +90,7 @@ export class SqlControl extends
React.Component<SqlControlProps, SqlControlState
});
const completer = {
- getCompletions: (editor:any , session: any, pos: any, prefix: any,
callback: any) => {
+ getCompletions: (editor: any, session: any, pos: any, prefix: any,
callback: any) => {
callback(null, columnNameList);
}
};
@@ -97,9 +99,9 @@ export class SqlControl extends
React.Component<SqlControlProps, SqlControlState
}
private addFunctionAutoCompleter = (): void => {
- const functionList: any[]= SQLFunctionDoc.map((entry: any) => {
- let funcName: string = entry.syntax.replace(/\(.*\)/,"()");
- if (!funcName.includes("(")) funcName = funcName.substr(0,10);
+ const functionList: any[] = SQLFunctionDoc.map((entry: any) => {
+ let funcName: string = entry.syntax.replace(/\(.*\)/, "()");
+ if (!funcName.includes("(")) funcName = funcName.substr(0, 10);
return {
value: funcName,
score: 80,
@@ -107,22 +109,22 @@ export class SqlControl extends
React.Component<SqlControlProps, SqlControlState
syntax: entry.syntax,
description: entry.description,
completer: {
- insertMatch: (editor:any, data:any) => {
+ insertMatch: (editor: any, data: any) => {
editor.completer.insertMatch({value: data.caption});
const pos = editor.getCursorPosition();
- editor.gotoLine(pos.row+1, pos.column-1);
+ editor.gotoLine(pos.row + 1, pos.column - 1);
}
}
};
});
const completer = {
- getCompletions: (editor:any , session: any, pos: any, prefix: any,
callback: any) => {
+ getCompletions: (editor: any, session: any, pos: any, prefix: any,
callback: any) => {
callback(null, functionList);
},
getDocTooltip: (item: any) => {
if (item.meta === "function") {
- const functionName = item.caption.slice(0,-2);
+ const functionName = item.caption.slice(0, -2);
item.docHTML = ReactDOMServer.renderToStaticMarkup((
<div className={"function-doc"}>
<div className={"function-doc-name"}><b>{functionName}</b></div>
@@ -133,7 +135,7 @@ export class SqlControl extends
React.Component<SqlControlProps, SqlControlState
<div><b>Description:</b></div>
<div>{item.description}</div>
</div>
- ))
+ ));
}
}
};
@@ -160,7 +162,7 @@ export class SqlControl extends
React.Component<SqlControlProps, SqlControlState
private handleChange = (newValue: string): void => {
this.setState({
query: newValue
- })
+ });
}
render() {
@@ -186,7 +188,7 @@ export class SqlControl extends
React.Component<SqlControlProps, SqlControlState
theme="solarized_dark"
name="ace-editor"
onChange={this.handleChange}
- focus={true}
+ focus
fontSize={14}
width={'100%'}
height={"30vh"}
@@ -199,7 +201,7 @@ export class SqlControl extends
React.Component<SqlControlProps, SqlControlState
enableBasicAutocompletion: isRune ? false : autoCompleteOn,
enableLiveAutocompletion: isRune ? false : autoCompleteOn,
showLineNumbers: true,
- tabSize: 2,
+ tabSize: 2
}}
/>
<div className="buttons">
@@ -213,4 +215,3 @@ export class SqlControl extends
React.Component<SqlControlProps, SqlControlState
</div>;
}
}
-
diff --git a/web-console/src/console-application.tsx
b/web-console/src/console-application.tsx
index 9b61052..332783f 100644
--- a/web-console/src/console-application.tsx
+++ b/web-console/src/console-application.tsx
@@ -16,22 +16,23 @@
* limitations under the License.
*/
+import { Intent } from "@blueprintjs/core";
import axios from 'axios';
-import * as React from 'react';
import * as classNames from 'classnames';
+import * as React from 'react';
import { HashRouter, Route, Switch } from "react-router-dom";
-import { Intent } from "@blueprintjs/core";
+
+import { HeaderActiveTab, HeaderBar } from './components/header-bar';
import { AppToaster } from './singletons/toaster';
-import { HeaderBar, HeaderActiveTab } from './components/header-bar';
-import { localStorageGet, localStorageSet } from './utils';
import { DRUID_DOCS_SQL, LEGACY_COORDINATOR_CONSOLE, LEGACY_OVERLORD_CONSOLE }
from './variables';
-import { HomeView } from './views/home-view';
import { DatasourcesView } from './views/datasource-view';
+import { HomeView } from './views/home-view';
+import { LookupsView } from "./views/lookups-view";
import { SegmentsView } from './views/segments-view';
import { ServersView } from './views/servers-view';
-import { TasksView } from './views/tasks-view';
import { SqlView } from './views/sql-view';
-import { LookupsView } from "./views/lookups-view";
+import { TasksView } from './views/tasks-view';
+
import "./console-application.scss";
export interface ConsoleApplicationProps extends React.Props<any> {
@@ -63,14 +64,16 @@ export class ConsoleApplication extends
React.Component<ConsoleApplicationProps,
iconName: 'error',
intent: Intent.DANGER,
timeout: 120000,
+ /* tslint:disable:jsx-alignment */
message: <>
It appears that the SQL endpoint is disabled. Either <a
href={DRUID_DOCS_SQL}>enable the SQL endpoint</a> or use the old <a
href={LEGACY_COORDINATOR_CONSOLE}>coordinator</a> and <a
href={LEGACY_OVERLORD_CONSOLE}>overlord</a> consoles that do not
rely on the SQL endpoint.
</>
+ /* tslint:enable:jsx-alignment */
});
- return false
+ return false;
}
return true;
}
@@ -142,30 +145,49 @@ export class ConsoleApplication extends
React.Component<ConsoleApplicationProps,
return <HashRouter hashType="noslash">
<div className="console-application">
<Switch>
- <Route path="/datasources" component={() => {
- return wrapInViewContainer('datasources', <DatasourcesView
goToSql={this.goToSql} goToSegments={this.goToSegments}/>);
- }} />
- <Route path="/segments" component={() => {
- return wrapInViewContainer('segments', <SegmentsView
datasource={this.datasource} onlyUnavailable={this.onlyUnavailable}
goToSql={this.goToSql}/>);
- }} />
- <Route path="/tasks" component={() => {
- return wrapInViewContainer('tasks', <TasksView
taskId={this.taskId} goToSql={this.goToSql}
goToMiddleManager={this.goToMiddleManager}/>, true);
- }} />
- <Route path="/servers" component={() => {
- return wrapInViewContainer('servers', <ServersView
middleManager={this.middleManager} goToSql={this.goToSql}
goToTask={this.goToTask}/>, true);
- }} />
- <Route path="/sql" component={() => {
- return wrapInViewContainer('sql', <SqlView
initSql={this.initSql}/>);
- }} />
- <Route path="/lookups" component={() => {
- return wrapInViewContainer('lookups', <LookupsView />);
- }} />
- <Route component={() => {
- return wrapInViewContainer(null, <HomeView/>)
- }} />
+ <Route
+ path="/datasources"
+ component={() => {
+ return wrapInViewContainer('datasources', <DatasourcesView
goToSql={this.goToSql} goToSegments={this.goToSegments}/>);
+ }}
+ />
+ <Route
+ path="/segments"
+ component={() => {
+ return wrapInViewContainer('segments', <SegmentsView
datasource={this.datasource} onlyUnavailable={this.onlyUnavailable}
goToSql={this.goToSql}/>);
+ }}
+ />
+ <Route
+ path="/tasks"
+ component={() => {
+ return wrapInViewContainer('tasks', <TasksView
taskId={this.taskId} goToSql={this.goToSql}
goToMiddleManager={this.goToMiddleManager}/>, true);
+ }}
+ />
+ <Route
+ path="/servers"
+ component={() => {
+ return wrapInViewContainer('servers', <ServersView
middleManager={this.middleManager} goToSql={this.goToSql}
goToTask={this.goToTask}/>, true);
+ }}
+ />
+ <Route
+ path="/sql"
+ component={() => {
+ return wrapInViewContainer('sql', <SqlView
initSql={this.initSql}/>);
+ }}
+ />
+ <Route
+ path="/lookups"
+ component={() => {
+ return wrapInViewContainer('lookups', <LookupsView />);
+ }}
+ />
+ <Route
+ component={() => {
+ return wrapInViewContainer(null, <HomeView/>);
+ }}
+ />
</Switch>
</div>
</HashRouter>;
}
}
-
diff --git a/web-console/src/dialogs/about-dialog.tsx
b/web-console/src/dialogs/about-dialog.tsx
index ee1fe0b..570fc13 100644
--- a/web-console/src/dialogs/about-dialog.tsx
+++ b/web-console/src/dialogs/about-dialog.tsx
@@ -16,13 +16,14 @@
* limitations under the License.
*/
+import { AnchorButton, Button, Classes, Dialog, Intent } from
"@blueprintjs/core";
import * as React from 'react';
-import { Button, Dialog, Classes, AnchorButton, Intent } from
"@blueprintjs/core";
+
import { IconNames } from "../components/filler";
import { DRUID_COMMUNITY, DRUID_DEVELOPER_GROUP, DRUID_USER_GROUP,
DRUID_WEBSITE } from '../variables';
export interface AboutDialogProps extends React.Props<any> {
- onClose: () => void
+ onClose: () => void;
}
export interface AboutDialogState {
@@ -37,6 +38,7 @@ export class AboutDialog extends
React.Component<AboutDialogProps, AboutDialogSt
render() {
const { onClose } = this.props;
+ /* tslint:disable:jsx-alignment */
return <Dialog
iconName={IconNames.GRAPH}
onClose={onClose}
@@ -75,5 +77,6 @@ export class AboutDialog extends
React.Component<AboutDialogProps, AboutDialogSt
</div>
</div>
</Dialog>;
+ /* tslint:enable:jsx-alignment */
}
}
diff --git a/web-console/src/dialogs/async-action-dialog.tsx
b/web-console/src/dialogs/async-action-dialog.tsx
index 0dc5af1..bbab05c 100644
--- a/web-console/src/dialogs/async-action-dialog.tsx
+++ b/web-console/src/dialogs/async-action-dialog.tsx
@@ -16,25 +16,25 @@
* limitations under the License.
*/
-import classNames from 'classnames';
-import * as React from 'react';
import {
Button,
- InputGroup,
- Dialog,
Classes,
+ Dialog,
Intent,
ProgressBar
} from "@blueprintjs/core";
-import { Icon, FormGroup, ButtonGroup, NumericInput, TagInput } from
'../components/filler';
+import classNames from 'classnames';
+import * as React from 'react';
+
+import { ButtonGroup, FormGroup, Icon, NumericInput, TagInput } from
'../components/filler';
import { AppToaster } from '../singletons/toaster';
export interface AsyncAlertDialogProps extends React.Props<any> {
- action: null | (() => Promise<void>),
- onClose: (success: boolean) => void,
+ action: null | (() => Promise<void>);
+ onClose: (success: boolean) => void;
confirmButtonText: string;
cancelButtonText?: string;
- className?: string,
+ className?: string;
icon?: string;
intent?: Intent;
successText: string;
@@ -42,7 +42,7 @@ export interface AsyncAlertDialogProps extends
React.Props<any> {
}
export interface AsyncAlertDialogState {
- working: boolean
+ working: boolean;
}
export class AsyncActionDialog extends React.Component<AsyncAlertDialogProps,
AsyncAlertDialogState> {
@@ -59,7 +59,7 @@ export class AsyncActionDialog extends
React.Component<AsyncAlertDialogProps, As
this.setState({ working: true });
try {
- await action()
+ await action();
} catch (e) {
AppToaster.show({
message: `${failText}: ${e.message}`,
@@ -92,8 +92,8 @@ export class AsyncActionDialog extends
React.Component<AsyncAlertDialogProps, As
onClose={handleClose}
>
<div className={Classes.ALERT_BODY}>
- { icon && <Icon icon={icon} /> }
- { !working && <div className={Classes.ALERT_CONTENTS}>{children}</div>
}
+ {icon && <Icon icon={icon} />}
+ {!working && <div className={Classes.ALERT_CONTENTS}>{children}</div>}
</div>
{
working ?
@@ -103,6 +103,6 @@ export class AsyncActionDialog extends
React.Component<AsyncAlertDialogProps, As
<Button text={cancelButtonText || 'Cancel'} onClick={handleClose}/>
</div>
}
- </Dialog>
+ </Dialog>;
}
}
diff --git a/web-console/src/dialogs/coordinator-dynamic-config.tsx
b/web-console/src/dialogs/coordinator-dynamic-config.tsx
index 474b0e2..59ee165 100644
--- a/web-console/src/dialogs/coordinator-dynamic-config.tsx
+++ b/web-console/src/dialogs/coordinator-dynamic-config.tsx
@@ -17,17 +17,20 @@
*/
import { Intent } from '@blueprintjs/core';
-import * as React from 'react';
import axios from 'axios';
-import { AppToaster } from '../singletons/toaster';
-import { IconNames } from '../components/filler';
+import * as React from 'react';
+
import { AutoForm } from '../components/auto-form';
+import { IconNames } from '../components/filler';
+import { AppToaster } from '../singletons/toaster';
import { getDruidErrorMessage } from '../utils';
+
import { SnitchDialog } from './snitch-dialog';
+
import './coordinator-dynamic-config.scss';
export interface CoordinatorDynamicConfigDialogProps extends React.Props<any> {
- onClose: () => void
+ onClose: () => void;
}
export interface CoordinatorDynamicConfigDialogState {
@@ -39,7 +42,7 @@ export class CoordinatorDynamicConfigDialog extends
React.Component<CoordinatorD
super(props);
this.state = {
dynamicConfig: null
- }
+ };
}
componentDidMount(): void {
@@ -50,7 +53,7 @@ export class CoordinatorDynamicConfigDialog extends
React.Component<CoordinatorD
let config: Record<string, any> | null = null;
try {
const configResp = await axios.get("/druid/coordinator/v1/config");
- config = configResp.data
+ config = configResp.data;
} catch (e) {
AppToaster.show({
iconName: IconNames.ERROR,
@@ -66,7 +69,7 @@ export class CoordinatorDynamicConfigDialog extends
React.Component<CoordinatorD
private saveClusterConfig = async (author: string, comment: string) => {
const { onClose } = this.props;
- let newState: any = this.state.dynamicConfig;
+ const newState: any = this.state.dynamicConfig;
try {
await axios.post("/druid/coordinator/v1/config", newState, {
headers: {
@@ -158,6 +161,6 @@ export class CoordinatorDynamicConfigDialog extends
React.Component<CoordinatorD
model={dynamicConfig}
onChange={m => this.setState({ dynamicConfig: m })}
/>
- </SnitchDialog>
+ </SnitchDialog>;
}
}
diff --git a/web-console/src/dialogs/lookup-edit-dialog.tsx
b/web-console/src/dialogs/lookup-edit-dialog.tsx
index 3375b94..e32ec5a 100644
--- a/web-console/src/dialogs/lookup-edit-dialog.tsx
+++ b/web-console/src/dialogs/lookup-edit-dialog.tsx
@@ -16,24 +16,26 @@
* limitations under the License.
*/
+import { Button, Classes, Dialog, InputGroup, Intent } from
"@blueprintjs/core";
import * as React from "react";
-import {Button, Classes, Dialog, Intent, InputGroup } from "@blueprintjs/core";
-import "./lookup-edit-dialog.scss"
-import {validJson} from "../utils";
import AceEditor from "react-ace";
-import {FormGroup} from "../components/filler";
+
+import { FormGroup } from "../components/filler";
+import { validJson } from "../utils";
+
+import "./lookup-edit-dialog.scss";
export interface LookupEditDialogProps extends React.Props<any> {
- isOpen: boolean,
- onClose: () => void,
- onSubmit: () => void,
- onChange: (field: string, value: string) => void
- lookupName: string,
- lookupTier: string,
- lookupVersion: string,
- lookupSpec: string,
- isEdit: boolean,
- allLookupTiers: string[]
+ isOpen: boolean;
+ onClose: () => void;
+ onSubmit: () => void;
+ onChange: (field: string, value: string) => void;
+ lookupName: string;
+ lookupTier: string;
+ lookupVersion: string;
+ lookupSpec: string;
+ isEdit: boolean;
+ allLookupTiers: string[];
}
export interface LookupEditDialogState {
@@ -45,7 +47,7 @@ export class LookupEditDialog extends
React.Component<LookupEditDialogProps, Loo
super(props);
this.state = {
- }
+ };
}
private addISOVersion = () => {
@@ -62,21 +64,21 @@ export class LookupEditDialog extends
React.Component<LookupEditDialogProps, Loo
<InputGroup
value={lookupTier}
onChange={(e: any) => onChange("lookupEditTier", e.target.value)}
- disabled={true}
+ disabled
/>
- </FormGroup>
+ </FormGroup>;
} else {
return <FormGroup className={"lookup-label"} label={"Tier:"}>
<div className="pt-select">
- <select disabled={isEdit} value={lookupTier} onChange={(e:any) =>
onChange("lookupEditTier", e.target.value)}>
+ <select disabled={isEdit} value={lookupTier} onChange={(e: any) =>
onChange("lookupEditTier", e.target.value)}>
{
allLookupTiers.map(tier => {
- return <option key={tier} value={tier}>{tier}</option>
+ return <option key={tier} value={tier}>{tier}</option>;
})
}
</select>
</div>
- </FormGroup>
+ </FormGroup>;
}
}
@@ -101,7 +103,7 @@ export class LookupEditDialog extends
React.Component<LookupEditDialogProps, Loo
/>
</FormGroup>
- { this.renderTierInput() }
+ {this.renderTierInput()}
<FormGroup className={"lookup-label"} label={"Version:"}>
<InputGroup
@@ -131,7 +133,7 @@ export class LookupEditDialog extends
React.Component<LookupEditDialogProps, Loo
setOptions={{
enableBasicAutocompletion: false,
enableLiveAutocompletion: false,
- tabSize: 2,
+ tabSize: 2
}}
/>
@@ -151,4 +153,4 @@ export class LookupEditDialog extends
React.Component<LookupEditDialogProps, Loo
</div>
</Dialog>;
}
-}
\ No newline at end of file
+}
diff --git a/web-console/src/dialogs/retention-dialog.tsx
b/web-console/src/dialogs/retention-dialog.tsx
index a6e02af..10d85f2 100644
--- a/web-console/src/dialogs/retention-dialog.tsx
+++ b/web-console/src/dialogs/retention-dialog.tsx
@@ -16,17 +16,19 @@
* limitations under the License.
*/
-import * as React from 'react';
-import axios from 'axios';
import { Button } from "@blueprintjs/core";
+import axios from 'axios';
+import * as React from 'react';
+
import { FormGroup, IconNames } from '../components/filler';
-import { RuleEditor, Rule } from '../components/rule-editor';
+import { Rule, RuleEditor } from '../components/rule-editor';
+
import { SnitchDialog } from './snitch-dialog';
import './retention-dialog.scss';
export function reorderArray<T>(items: T[], oldIndex: number, newIndex:
number): T[] {
- let newItems = items.concat();
+ const newItems = items.concat();
if (newIndex > oldIndex) newIndex--;
@@ -111,7 +113,7 @@ export class RetentionDialog extends
React.Component<RetentionDialogProps, Reten
onDelete={() => this.onDeleteRule(index)}
moveUp={index > 0 ? () => this.moveRule(index, -1) : null}
moveDown={index < (currentRules || []).length - 1 ? () =>
this.moveRule(index, 2) : null}
- />
+ />;
}
reset = () => {
diff --git a/web-console/src/dialogs/snitch-dialog.tsx
b/web-console/src/dialogs/snitch-dialog.tsx
index d20971e..c01913e 100644
--- a/web-console/src/dialogs/snitch-dialog.tsx
+++ b/web-console/src/dialogs/snitch-dialog.tsx
@@ -16,17 +16,17 @@
* limitations under the License.
*/
-import * as React from 'react';
import {
Button,
- InputGroup,
+ Classes,
Dialog,
IDialogProps,
- Classes,
- Intent,
+ InputGroup,
+ Intent
} from "@blueprintjs/core";
-import { IconNames, FormGroup } from '../components/filler';
+import * as React from 'react';
+import { FormGroup, IconNames } from '../components/filler';
export interface SnitchDialogProps extends IDialogProps {
onSave: (author: string, comment: string) => void;
@@ -50,7 +50,7 @@ export class SnitchDialog extends
React.Component<SnitchDialogProps, SnitchDialo
comment: "",
author: "",
saveDisabled: true
- }
+ };
}
save = () => {
@@ -136,7 +136,7 @@ export class SnitchDialog extends
React.Component<SnitchDialogProps, SnitchDialo
? <Button disabled={saveDisabled} text="Save" onClick={this.save}
intent={Intent.PRIMARY as any} rightIconName={IconNames.TICK}/>
: <Button disabled={saveDisabled} text="Next"
onClick={this.goToFinalStep} intent={Intent.PRIMARY as any}
rightIconName={IconNames.ARROW_RIGHT}/>
}
- </div>
+ </div>;
}
render() {
diff --git a/web-console/src/dialogs/spec-dialog.tsx
b/web-console/src/dialogs/spec-dialog.tsx
index 8cd8065..9b65901 100644
--- a/web-console/src/dialogs/spec-dialog.tsx
+++ b/web-console/src/dialogs/spec-dialog.tsx
@@ -16,12 +16,13 @@
* limitations under the License.
*/
-import * as React from "react";
import { Button, Classes, Dialog, Intent } from "@blueprintjs/core";
-import "./spec-dialog.scss"
-import AceEditor from "react-ace";
+import "brace/mode/json";
import "brace/theme/solarized_dark";
-import "brace/mode/json"
+import * as React from "react";
+import AceEditor from "react-ace";
+
+import "./spec-dialog.scss";
export interface SpecDialogProps extends React.Props<any> {
onSubmit: (spec: JSON) => void;
@@ -47,7 +48,7 @@ export class SpecDialog extends
React.Component<SpecDialogProps, SpecDialogState
super(props);
this.state = {
spec: ""
- }
+ };
}
private postSpec(): void {
@@ -72,11 +73,11 @@ export class SpecDialog extends
React.Component<SpecDialogProps, SpecDialogState
mode="json"
theme="solarized_dark"
className={"post-spec-dialog-textarea"}
- onChange={ (e) => {this.setState({ spec: e })} }
+ onChange={(e) => { this.setState({ spec: e }); }}
fontSize={12}
showPrintMargin={false}
- showGutter={true}
- highlightActiveLine={true}
+ showGutter
+ highlightActiveLine
value={spec}
width={"100%"}
setOptions={{
@@ -84,7 +85,7 @@ export class SpecDialog extends
React.Component<SpecDialogProps, SpecDialogState
enableLiveAutocompletion: true,
showLineNumbers: true,
enableSnippets: true,
- tabSize: 2,
+ tabSize: 2
}}
/>
<div className={Classes.DIALOG_FOOTER}>
diff --git a/web-console/src/entry.ts b/web-console/src/entry.ts
index ae2892c..9597d70 100644
--- a/web-console/src/entry.ts
+++ b/web-console/src/entry.ts
@@ -19,13 +19,14 @@
import 'es6-shim/es6-shim';
import 'es7-shim'; // Webpack with automatically pick browser.js which does
the shim()
import * as React from 'react';
-(React as any).PropTypes = require('prop-types'); // Trick blueprint 1.0.1
into accepting React 16 as React 15.
import * as ReactDOM from 'react-dom';
-import "./singletons/react-table-defaults";
-import "./entry.scss";
+import "./bootstrap/a-shim-for-react-props";
+import "./bootstrap/react-table-defaults";
import { ConsoleApplication } from './console-application';
+import "./entry.scss";
+
const container = document.getElementsByClassName('app-container')[0];
if (!container) throw new Error('container not found');
diff --git a/web-console/src/singletons/toaster.ts
b/web-console/src/singletons/toaster.ts
index 3f4998e..4fc529c 100644
--- a/web-console/src/singletons/toaster.ts
+++ b/web-console/src/singletons/toaster.ts
@@ -20,5 +20,5 @@ import { Position, Toaster } from "@blueprintjs/core";
export const AppToaster = Toaster.create({
className: "recipe-toaster",
- position: Position.TOP,
+ position: Position.TOP
});
diff --git a/web-console/src/utils/general.tsx
b/web-console/src/utils/general.tsx
index a40ebad..7fce279 100644
--- a/web-console/src/utils/general.tsx
+++ b/web-console/src/utils/general.tsx
@@ -17,14 +17,14 @@
*/
import { Button, InputGroup, Intent } from '@blueprintjs/core';
-import { IconNames, HTMLSelect } from "../components/filler";
import * as numeral from "numeral";
import * as React from 'react';
import { Filter, FilterRender } from 'react-table';
+import { HTMLSelect, IconNames } from "../components/filler";
export function addFilter(filters: Filter[], id: string, value: string):
Filter[] {
- let currentFilter = filters.find(f => f.id === id);
+ const currentFilter = filters.find(f => f.id === id);
if (currentFilter) {
filters = filters.filter(f => f.id !== id);
if (currentFilter.value !== value) {
@@ -36,7 +36,7 @@ export function addFilter(filters: Filter[], id: string,
value: string): Filter[
return filters;
}
-export function makeTextFilter(placeholder: string = ''): FilterRender {
+export function makeTextFilter(placeholder = ''): FilterRender {
return ({ filter, onChange, key }) => {
const filterValue = filter ? filter.value : '';
return <InputGroup
@@ -45,8 +45,8 @@ export function makeTextFilter(placeholder: string = ''):
FilterRender {
value={filterValue}
rightElement={filterValue ? <Button iconName={IconNames.CROSS}
className="pt-minimal" onClick={() => onChange('')} /> : undefined}
placeholder={placeholder}
- />
- }
+ />;
+ };
}
export function makeBooleanFilter(): FilterRender {
@@ -57,13 +57,13 @@ export function makeBooleanFilter(): FilterRender {
style={{ width: '100%' }}
onChange={(event: any) => onChange(event.target.value)}
value={filterValue || "all"}
- fill={true}
+ fill
>
<option value="all">Show all</option>
<option value="true">true</option>
<option value="false">false</option>
</HTMLSelect>;
- }
+ };
}
// ----------------------------
diff --git a/web-console/src/utils/query-manager.tsx
b/web-console/src/utils/query-manager.tsx
index 38ef3ef..22fc3f7 100644
--- a/web-console/src/utils/query-manager.tsx
+++ b/web-console/src/utils/query-manager.tsx
@@ -74,7 +74,7 @@ export class QueryManager<Q, R> {
private run() {
this.lastQuery = this.nextQuery;
this.currentQueryId++;
- let myQueryId = this.currentQueryId;
+ const myQueryId = this.currentQueryId;
this.actuallyLoading = true;
this.processQuery(this.lastQuery)
@@ -95,9 +95,9 @@ export class QueryManager<Q, R> {
result: null,
loading: false,
error: e.message
- })
+ });
}
- )
+ );
}
private trigger() {
diff --git a/web-console/src/utils/rune-decoder.tsx
b/web-console/src/utils/rune-decoder.tsx
index c3fe5a1..3863812 100644
--- a/web-console/src/utils/rune-decoder.tsx
+++ b/web-console/src/utils/rune-decoder.tsx
@@ -16,7 +16,6 @@
* limitations under the License.
*/
-
export interface HeaderRows {
header: string[];
rows: any[][];
@@ -86,7 +85,11 @@ export function decodeRune(runeQuery: any, runeResult:
any[]): HeaderRows {
throw new Error(`Unsupported query type in treatQueryTypeAs:
'${treatQueryTypeAs}'`);
}
} else {
- throw new Error(`Unsupported query type '${queryType}'. Supported query
types are: '${SUPPORTED_QUERY_TYPES.join("', '")}'. If this is a custom query
you can parse the result as a known query type by setting 'treatQueryTypeAs' in
the context to one of the supported types.`);
+ throw new Error([
+ `Unsupported query type '${queryType}'.`,
+ `Supported query types are: '${SUPPORTED_QUERY_TYPES.join("', '")}'.`,
+ `If this is a custom query you can parse the result as a known query
type by setting 'treatQueryTypeAs' in the context to one of the supported
types.`
+ ].join(' '));
}
}
diff --git a/web-console/src/views/datasource-view.tsx
b/web-console/src/views/datasource-view.tsx
index aacaace..1deae85 100644
--- a/web-console/src/views/datasource-view.tsx
+++ b/web-console/src/views/datasource-view.tsx
@@ -16,25 +16,26 @@
* limitations under the License.
*/
+import { Button, Intent, Switch } from "@blueprintjs/core";
import axios from 'axios';
-import * as React from 'react';
import * as classNames from 'classnames';
+import * as React from 'react';
import ReactTable from "react-table";
import { Filter } from "react-table";
-import { Button, Intent, Switch } from "@blueprintjs/core";
+
import { IconNames } from "../components/filler";
-import { AppToaster } from '../singletons/toaster';
import { RuleEditor } from '../components/rule-editor';
import { AsyncActionDialog } from '../dialogs/async-action-dialog';
import { RetentionDialog } from '../dialogs/retention-dialog';
+import { AppToaster } from '../singletons/toaster';
import {
addFilter,
- formatNumber,
- formatBytes,
countBy,
+ formatBytes,
+ formatNumber,
+ getDruidErrorMessage,
lookupBy,
- QueryManager,
- pluralIfNeeded, queryDruidSql, getDruidErrorMessage
+ pluralIfNeeded, queryDruidSql, QueryManager
} from "../utils";
import "./datasource-view.scss";
@@ -54,7 +55,7 @@ export interface DatasourcesViewState {
datasourcesLoading: boolean;
datasources: Datasource[] | null;
tiers: string[];
- defaultRules: any[]
+ defaultRules: any[];
datasourcesError: string | null;
datasourcesFilter: Filter[];
@@ -73,7 +74,7 @@ export class DatasourcesView extends
React.Component<DatasourcesViewProps, Datas
static formatRules(rules: any[]): string {
if (rules.length === 0) {
return 'No rules';
- } if (rules.length <= 2) {
+ } else if (rules.length <= 2) {
return rules.map(RuleEditor.ruleToString).join(', ');
} else {
return `${RuleEditor.ruleToString(rules[0])} +${rules.length - 1} more
rules`;
@@ -161,7 +162,7 @@ GROUP BY 1`);
return <AsyncActionDialog
action={
dropDataDatasource ? async () => {
- const resp = await
axios.delete(`/druid/coordinator/v1/datasources/${dropDataDatasource}`, {})
+ const resp = await
axios.delete(`/druid/coordinator/v1/datasources/${dropDataDatasource}`, {});
return resp.data;
} : null
}
@@ -186,7 +187,7 @@ GROUP BY 1`);
return <AsyncActionDialog
action={
enableDatasource ? async () => {
- const resp = await
axios.post(`/druid/coordinator/v1/datasources/${enableDatasource}`, {})
+ const resp = await
axios.post(`/druid/coordinator/v1/datasources/${enableDatasource}`, {});
return resp.data;
} : null
}
@@ -291,7 +292,7 @@ GROUP BY 1`);
let data = datasources || [];
if (!showDisabled) {
- data = data.filter(d => !d.disabled)
+ data = data.filter(d => !d.disabled);
}
return <>
@@ -299,7 +300,7 @@ GROUP BY 1`);
data={data}
loading={datasourcesLoading}
noDataText={!datasourcesLoading && datasources && !datasources.length
? 'No datasources' : (datasourcesError || '')}
- filterable={true}
+ filterable
filtered={datasourcesFilter}
onFilteredChange={(filtered, column) => {
this.setState({ datasourcesFilter: filtered });
@@ -311,7 +312,7 @@ GROUP BY 1`);
width: 150,
Cell: row => {
const value = row.value;
- return <a onClick={() => { this.setState({ datasourcesFilter:
addFilter(datasourcesFilter, 'datasource', value) }) }}>{value}</a>
+ return <a onClick={() => { this.setState({ datasourcesFilter:
addFilter(datasourcesFilter, 'datasource', value) }); }}>{value}</a>;
}
},
{
@@ -415,11 +416,11 @@ GROUP BY 1`);
return <div>
<a onClick={() => this.setState({ enableDatasource:
datasource })}>Enable</a>
<a onClick={() => this.setState({ killDatasource: datasource
})}>Permanently delete</a>
- </div>
+ </div>;
} else {
return <div>
<a onClick={() => this.setState({ dropDataDatasource:
datasource })}>Drop data</a>
- </div>
+ </div>;
}
}
}
@@ -458,7 +459,6 @@ GROUP BY 1`);
/>
</div>
{this.renderDatasourceTable()}
- </div>
+ </div>;
}
}
-
diff --git a/web-console/src/views/home-view.tsx
b/web-console/src/views/home-view.tsx
index 83df542..b435bba 100644
--- a/web-console/src/views/home-view.tsx
+++ b/web-console/src/views/home-view.tsx
@@ -17,10 +17,12 @@
*/
import axios from 'axios';
-import * as React from 'react';
import * as classNames from 'classnames';
-import { H5, Card, Icon, IconNames } from "../components/filler";
-import { QueryManager, pluralIfNeeded, queryDruidSql, getHeadProp } from
'../utils';
+import * as React from 'react';
+
+import { Card, H5, Icon, IconNames } from "../components/filler";
+import { getHeadProp, pluralIfNeeded, queryDruidSql, QueryManager } from
'../utils';
+
import './home-view.scss';
export interface CardOptions {
@@ -164,14 +166,14 @@ export class HomeView extends
React.Component<HomeViewProps, HomeViewState> {
this.taskQueryManager = new QueryManager({
processQuery: async (query) => {
const taskCountsFromSql = await queryDruidSql({ query });
- let taskCounts = {
+ const taskCounts = {
successTaskCount: 0,
failedTaskCount: 0,
runningTaskCount: 0,
waitingTaskCount: 0,
pendingTaskCount: 0
};
- for (let dataStatus of taskCountsFromSql) {
+ for (const dataStatus of taskCountsFromSql) {
if (dataStatus.status === "SUCCESS") {
taskCounts.successTaskCount = dataStatus.count;
} else if (dataStatus.status === "FAILED") {
@@ -254,7 +256,7 @@ GROUP BY 1`);
renderCard(cardOptions: CardOptions): JSX.Element {
return <a href={cardOptions.href} target={cardOptions.href[0] === '/' ?
'_blank' : undefined}>
- <Card interactive={true}>
+ <Card interactive>
<H5><Icon color="#bfccd5"
icon={cardOptions.icon}/> {cardOptions.title}</H5>
{cardOptions.loading ? <p>Loading...</p> : (cardOptions.error ?
`Error: ${cardOptions.error}` : cardOptions.content)}
</Card>
@@ -298,11 +300,11 @@ GROUP BY 1`);
title: "Tasks",
loading: state.taskCountLoading,
content: <>
- { Boolean(state.runningTaskCount) &&
<p>{pluralIfNeeded(state.runningTaskCount, 'running task')}</p> }
- { Boolean(state.pendingTaskCount) &&
<p>{pluralIfNeeded(state.pendingTaskCount, 'pending task')}</p> }
- { Boolean(state.successTaskCount) &&
<p>{pluralIfNeeded(state.successTaskCount, 'successful task')}</p> }
- { Boolean(state.waitingTaskCount) &&
<p>{pluralIfNeeded(state.waitingTaskCount, 'waiting task')}</p> }
- { Boolean(state.failedTaskCount) &&
<p>{pluralIfNeeded(state.failedTaskCount, 'failed task')}</p> }
+ {Boolean(state.runningTaskCount) &&
<p>{pluralIfNeeded(state.runningTaskCount, 'running task')}</p>}
+ {Boolean(state.pendingTaskCount) &&
<p>{pluralIfNeeded(state.pendingTaskCount, 'pending task')}</p>}
+ {Boolean(state.successTaskCount) &&
<p>{pluralIfNeeded(state.successTaskCount, 'successful task')}</p>}
+ {Boolean(state.waitingTaskCount) &&
<p>{pluralIfNeeded(state.waitingTaskCount, 'waiting task')}</p>}
+ {Boolean(state.failedTaskCount) &&
<p>{pluralIfNeeded(state.failedTaskCount, 'failed task')}</p>}
{ !(state.runningTaskCount + state.pendingTaskCount +
state.successTaskCount + state.waitingTaskCount + state.failedTaskCount) &&
<p>There are no tasks</p>
}
@@ -321,7 +323,6 @@ GROUP BY 1`);
</>,
error: state.dataServerCountError
})}
- </div>
+ </div>;
}
}
-
diff --git a/web-console/src/views/lookups-view.tsx
b/web-console/src/views/lookups-view.tsx
index f7e9fe6..02a6d0e 100644
--- a/web-console/src/views/lookups-view.tsx
+++ b/web-console/src/views/lookups-view.tsx
@@ -16,15 +16,17 @@
* limitations under the License.
*/
+import { Button, Intent } from "@blueprintjs/core";
import axios from 'axios';
-import * as React from 'react';
import * as classNames from 'classnames';
+import * as React from 'react';
import ReactTable from "react-table";
import { Filter } from "react-table";
-import { Button, Intent } from "@blueprintjs/core";
-import {getDruidErrorMessage, QueryManager} from "../utils";
-import {LookupEditDialog} from "../dialogs/lookup-edit-dialog";
+
+import { LookupEditDialog } from "../dialogs/lookup-edit-dialog";
import { AppToaster } from "../singletons/toaster";
+import { getDruidErrorMessage, QueryManager } from "../utils";
+
import "./lookups-view.scss";
export interface LookupsViewProps extends React.Props<any> {
@@ -32,16 +34,16 @@ export interface LookupsViewProps extends React.Props<any> {
}
export interface LookupsViewState {
- lookups: {}[],
- loadingLookups: boolean,
- lookupsError: string | null,
- lookupEditDialogOpen: boolean,
- lookupEditName: string,
- lookupEditTier: string,
- lookupEditVersion: string,
- lookupEditSpec: string,
- isEdit: boolean,
- allLookupTiers: string[]
+ lookups: {}[];
+ loadingLookups: boolean;
+ lookupsError: string | null;
+ lookupEditDialogOpen: boolean;
+ lookupEditName: string;
+ lookupEditTier: string;
+ lookupEditVersion: string;
+ lookupEditSpec: string;
+ isEdit: boolean;
+ allLookupTiers: string[];
}
export class LookupsView extends React.Component<LookupsViewProps,
LookupsViewState> {
@@ -70,15 +72,15 @@ export class LookupsView extends
React.Component<LookupsViewProps, LookupsViewSt
const tiersResp = await axios.get('/druid/coordinator/v1/tiers');
const tiers = tiersResp.data;
- let lookupEntries: {}[] = [];
+ const lookupEntries: {}[] = [];
const lookupResp = await
axios.get("/druid/coordinator/v1/lookups/config/all");
const lookupData = lookupResp.data;
Object.keys(lookupData).map((tier: string) => {
const lookupIds = lookupData[tier];
Object.keys(lookupIds).map((id: string) => {
- lookupEntries.push({tier: tier, id: id,
version:lookupData[tier][id].version, spec:
lookupData[tier][id].lookupExtractorFactory},);
- })
- })
+ lookupEntries.push({tier, id, version:
lookupData[tier][id].version, spec:
lookupData[tier][id].lookupExtractorFactory});
+ });
+ });
return {
lookupEntries,
tiers
@@ -123,11 +125,11 @@ export class LookupsView extends
React.Component<LookupsViewProps, LookupsViewSt
intent: Intent.DANGER,
message: getDruidErrorMessage(e)
}
- )
+ );
}
}
- private async openLookupEditDialog(tier:string, id: string) {
+ private async openLookupEditDialog(tier: string, id: string) {
const { lookups, allLookupTiers } = this.state;
const target: any = lookups.find((lookupEntry: any) => {
return lookupEntry.tier === tier && lookupEntry.id === id;
@@ -156,7 +158,7 @@ export class LookupsView extends
React.Component<LookupsViewProps, LookupsViewSt
private changeLookup(field: string, value: string) {
this.setState({
[field]: value
- } as any)
+ } as any);
}
private async submitLookupEdit() {
@@ -184,20 +186,20 @@ export class LookupsView extends
React.Component<LookupsViewProps, LookupsViewSt
await axios.post(endpoint, dataJSON);
this.setState({
lookupEditDialogOpen: false
- })
+ });
this.lookupsGetQueryManager.rerunLastQuery();
- } catch(e) {
+ } catch (e) {
AppToaster.show(
{
iconName: 'error',
intent: Intent.DANGER,
message: getDruidErrorMessage(e)
}
- )
+ );
}
}
- private deleteLookup(tier:string, name: string): void {
+ private deleteLookup(tier: string, name: string): void {
const url = `/druid/coordinator/v1/lookups/config/${tier}/${name}`;
this.lookupDeleteQueryManager.runQuery(url);
}
@@ -211,52 +213,52 @@ export class LookupsView extends
React.Component<LookupsViewProps, LookupsViewSt
text="Initialize Lookup"
onClick={() => this.initializeLookup()}
/>
- </div>
+ </div>;
}
return <>
<ReactTable
data={lookups}
loading={loadingLookups}
noDataText={!loadingLookups && lookups && !lookups.length ? 'No
lookups' : (lookupsError || '')}
- filterable={true}
+ filterable
columns={[
{
Header: "Lookup Name",
id: "lookup_name",
accessor: (row: any) => row.id,
- filterable: true,
+ filterable: true
},
{
Header: "Tier",
id: "tier",
accessor: (row: any) => row.tier,
- filterable: true,
+ filterable: true
},
{
Header: "Type",
id: "type",
accessor: (row: any) => row.spec.type,
- filterable: true,
+ filterable: true
},
{
Header: "Version",
id: "version",
accessor: (row: any) => row.version,
- filterable: true,
+ filterable: true
},
{
Header: "Config",
id: "config",
- accessor: row => {return {id: row.id, tier: row.tier};},
+ accessor: row => ({id: row.id, tier: row.tier}),
filterable: false,
Cell: (row: any) => {
const lookupId = row.value.id;
const lookupTier = row.value.tier;
return <div>
- <a onClick={() =>
this.openLookupEditDialog(lookupTier,lookupId)}>Edit</a>
+ <a onClick={() => this.openLookupEditDialog(lookupTier,
lookupId)}>Edit</a>
- <a onClick={() =>
this.deleteLookup(lookupTier,lookupId)}>Delete</a>
- </div>
+ <a onClick={() => this.deleteLookup(lookupTier,
lookupId)}>Delete</a>
+ </div>;
}
}
]}
@@ -266,21 +268,21 @@ export class LookupsView extends
React.Component<LookupsViewProps, LookupsViewSt
</>;
}
- renderLookupEditDialog () {
- const { lookupEditDialogOpen, allLookupTiers, lookupEditSpec,
lookupEditTier, lookupEditName, lookupEditVersion, isEdit } = this.state
+ renderLookupEditDialog() {
+ const { lookupEditDialogOpen, allLookupTiers, lookupEditSpec,
lookupEditTier, lookupEditName, lookupEditVersion, isEdit } = this.state;
return <LookupEditDialog
isOpen={lookupEditDialogOpen}
onClose={() => this.setState({ lookupEditDialogOpen: false })}
onSubmit={() => this.submitLookupEdit()}
onChange={(field: string, value: string) => this.changeLookup(field,
value)}
- lookupSpec= {lookupEditSpec}
+ lookupSpec={lookupEditSpec}
lookupName={lookupEditName}
lookupTier={lookupEditTier}
- lookupVersion = {lookupEditVersion}
+ lookupVersion={lookupEditVersion}
isEdit={isEdit}
allLookupTiers={allLookupTiers}
- />
+ />;
}
render() {
@@ -301,6 +303,6 @@ export class LookupsView extends
React.Component<LookupsViewProps, LookupsViewSt
</div>
{this.renderLookupsTable()}
{this.renderLookupEditDialog()}
- </div>
+ </div>;
}
-}
\ No newline at end of file
+}
diff --git a/web-console/src/views/segments-view.tsx
b/web-console/src/views/segments-view.tsx
index 920f61a..8320f05 100644
--- a/web-console/src/views/segments-view.tsx
+++ b/web-console/src/views/segments-view.tsx
@@ -16,22 +16,24 @@
* limitations under the License.
*/
+import { Button } from "@blueprintjs/core";
import axios from 'axios';
-import * as React from 'react';
import * as classNames from 'classnames';
+import * as React from 'react';
import ReactTable from "react-table";
import { Filter } from "react-table";
-import { Button } from "@blueprintjs/core";
+
import { H5, IconNames } from "../components/filler";
import {
addFilter,
- makeBooleanFilter,
- QueryManager,
formatBytes,
formatNumber,
+ makeBooleanFilter,
parseList,
- queryDruidSql
+ queryDruidSql,
+ QueryManager
} from "../utils";
+
import "./segments-view.scss";
export interface SegmentsViewProps extends React.Props<any> {
@@ -88,7 +90,7 @@ export class SegmentsView extends
React.Component<SegmentsViewProps, SegmentsVie
segmentsError: error
});
}
- })
+ });
}
componentWillUnmount(): void {
@@ -99,7 +101,7 @@ export class SegmentsView extends
React.Component<SegmentsViewProps, SegmentsVie
const { page, pageSize, filtered, sorted } = state;
const totalQuerySize = (page + 1) * pageSize;
- let queryParts = [
+ const queryParts = [
`SELECT "segment_id", "datasource", "start", "end", "size", "version",
"partition_num", "num_replicas", "num_rows", "is_published", "is_available",
"is_realtime", "payload"`,
`FROM sys.segments`
];
@@ -114,7 +116,7 @@ export class SegmentsView extends
React.Component<SegmentsViewProps, SegmentsVie
}).filter(Boolean);
if (whereParts.length) {
- queryParts.push('WHERE ' + whereParts.join(' AND '))
+ queryParts.push('WHERE ' + whereParts.join(' AND '));
}
if (sorted.length) {
@@ -160,7 +162,7 @@ export class SegmentsView extends
React.Component<SegmentsViewProps, SegmentsVie
accessor: "datasource",
Cell: row => {
const value = row.value;
- return <a onClick={() => { this.setState({ segmentFilter:
addFilter(segmentFilter, 'datasource', value) }) }}>{value}</a>
+ return <a onClick={() => { this.setState({ segmentFilter:
addFilter(segmentFilter, 'datasource', value) }); }}>{value}</a>;
}
},
{
@@ -170,7 +172,7 @@ export class SegmentsView extends
React.Component<SegmentsViewProps, SegmentsVie
defaultSortDesc: true,
Cell: row => {
const value = row.value;
- return <a onClick={() => { this.setState({ segmentFilter:
addFilter(segmentFilter, 'start', value) }) }}>{value}</a>
+ return <a onClick={() => { this.setState({ segmentFilter:
addFilter(segmentFilter, 'start', value) }); }}>{value}</a>;
}
},
{
@@ -180,14 +182,14 @@ export class SegmentsView extends
React.Component<SegmentsViewProps, SegmentsVie
width: 120,
Cell: row => {
const value = row.value;
- return <a onClick={() => { this.setState({ segmentFilter:
addFilter(segmentFilter, 'end', value) }) }}>{value}</a>
+ return <a onClick={() => { this.setState({ segmentFilter:
addFilter(segmentFilter, 'end', value) }); }}>{value}</a>;
}
},
{
Header: "Version",
accessor: "version",
defaultSortDesc: true,
- width: 120,
+ width: 120
},
{
Header: "Partition",
@@ -272,6 +274,6 @@ export class SegmentsView extends
React.Component<SegmentsViewProps, SegmentsVie
/>
</div>
{this.renderSegmentsTable()}
- </div>
+ </div>;
}
}
diff --git a/web-console/src/views/servers-view.tsx
b/web-console/src/views/servers-view.tsx
index 89ac5c4..e8598be 100644
--- a/web-console/src/views/servers-view.tsx
+++ b/web-console/src/views/servers-view.tsx
@@ -16,19 +16,21 @@
* limitations under the License.
*/
+import { Button, Switch } from "@blueprintjs/core";
import axios from 'axios';
-import * as React from 'react';
import * as classNames from 'classnames';
+import { sum } from "d3-array";
+import * as React from 'react';
import ReactTable from "react-table";
import { Filter } from "react-table";
-import { sum } from "d3-array";
-import { Button, Switch } from "@blueprintjs/core";
+
import { IconNames } from '../components/filler';
-import { addFilter, formatBytes, formatBytesCompact, QueryManager,
queryDruidSql } from "../utils";
+import { addFilter, formatBytes, formatBytesCompact, queryDruidSql,
QueryManager } from "../utils";
+
import "./servers-view.scss";
function formatQueues(segmentsToLoad: number, segmentsToLoadSize: number,
segmentsToDrop: number, segmentsToDropSize: number): string {
- let queueParts: string[] = [];
+ const queueParts: string[] = [];
if (segmentsToLoad) {
queueParts.push(`${segmentsToLoad} segments to load
(${formatBytesCompact(segmentsToLoadSize)})`);
}
@@ -73,7 +75,7 @@ export class ServersView extends
React.Component<ServersViewProps, ServersViewSt
middleManagersLoading: true,
middleManagers: null,
middleManagersError: null,
- middleManagerFilter: props.middleManager ? [{ id: 'host', value:
props.middleManager }] : [],
+ middleManagerFilter: props.middleManager ? [{ id: 'host', value:
props.middleManager }] : []
};
}
@@ -82,7 +84,7 @@ export class ServersView extends
React.Component<ServersViewProps, ServersViewSt
processQuery: async (query: string) => {
const servers = await queryDruidSql({ query });
- let loadQueueResponse = await
axios.get("/druid/coordinator/v1/loadqueue?simple");
+ const loadQueueResponse = await
axios.get("/druid/coordinator/v1/loadqueue?simple");
const loadQueues = loadQueueResponse.data;
return servers.map((s: any) => {
@@ -143,7 +145,7 @@ WHERE "server_type" = 'historical'`);
data={servers || []}
loading={serversLoading}
noDataText={!serversLoading && servers && !servers.length ? 'No
historicals' : (serversError || '')}
- filterable={true}
+ filterable
filtered={serverFilter}
onFilteredChange={(filtered, column) => {
this.setState({ serverFilter: filtered });
@@ -161,7 +163,7 @@ WHERE "server_type" = 'historical'`);
accessor: "tier",
Cell: row => {
const value = row.value;
- return <a onClick={() => { this.setState({ serverFilter:
addFilter(serverFilter, 'tier', value) }) }}>{value}</a>
+ return <a onClick={() => { this.setState({ serverFilter:
addFilter(serverFilter, 'tier', value) }); }}>{value}</a>;
}
},
{
@@ -234,7 +236,7 @@ WHERE "server_type" = 'historical'`);
const segmentsToDrop = sum(originals, s => s.segmentsToDrop);
const segmentsToDropSize = sum(originals, s =>
s.segmentsToDropSize);
return formatQueues(segmentsToLoad, segmentsToLoadSize,
segmentsToDrop, segmentsToDropSize);
- },
+ }
},
{
Header: "Host",
@@ -245,7 +247,7 @@ WHERE "server_type" = 'historical'`);
Header: "Port",
id: 'port',
accessor: (row) => {
- let ports: string[] = [];
+ const ports: string[] = [];
if (row.plaintext_port !== -1) {
ports.push(`${row.plaintext_port} (plain)`);
}
@@ -255,7 +257,7 @@ WHERE "server_type" = 'historical'`);
return ports.join(', ') || 'No port';
},
Aggregated: () => ''
- },
+ }
]}
defaultPageSize={10}
className="-striped -highlight"
@@ -270,7 +272,7 @@ WHERE "server_type" = 'historical'`);
data={middleManagers || []}
loading={middleManagersLoading}
noDataText={!middleManagersLoading && middleManagers &&
!middleManagers.length ? 'No MiddleManagers' : (middleManagersError || '')}
- filterable={true}
+ filterable
filtered={middleManagerFilter}
onFilteredChange={(filtered, column) => {
this.setState({ middleManagerFilter: filtered });
@@ -282,7 +284,7 @@ WHERE "server_type" = 'historical'`);
accessor: (row) => row.worker.host,
Cell: row => {
const value = row.value;
- return <a onClick={() => { this.setState({ middleManagerFilter:
addFilter(middleManagerFilter, 'host', value) }) }}>{value}</a>
+ return <a onClick={() => { this.setState({ middleManagerFilter:
addFilter(middleManagerFilter, 'host', value) }); }}>{value}</a>;
}
},
{
@@ -297,7 +299,7 @@ WHERE "server_type" = 'historical'`);
id: "availabilityGroups",
width: 60,
accessor: (row) => row.availabilityGroups.length,
- filterable: false,
+ filterable: false
},
{
Header: "Last completed task time",
@@ -317,7 +319,7 @@ WHERE "server_type" = 'historical'`);
runningTasks.length ?
<>
<span>Running tasks:</span>
- <ul>{ runningTasks.map((t: string) => <li key={t}>{t} <a
onClick={() => goToTask(t)}>➚</a></li>) }</ul>
+ <ul>{runningTasks.map((t: string) => <li key={t}>{t} <a
onClick={() => goToTask(t)}>➚</a></li>)}</ul>
</> :
<span>No running tasks</span>
}
@@ -362,7 +364,6 @@ WHERE "server_type" = 'historical'`);
/>
</div>
{this.renderMiddleManagerTable()}
- </div>
+ </div>;
}
}
-
diff --git a/web-console/src/views/sql-view.tsx
b/web-console/src/views/sql-view.tsx
index d424316..cde181e 100644
--- a/web-console/src/views/sql-view.tsx
+++ b/web-console/src/views/sql-view.tsx
@@ -17,19 +17,21 @@
*/
import axios from 'axios';
-import * as React from 'react';
import * as classNames from 'classnames';
-import ReactTable from "react-table";
import * as Hjson from "hjson";
+import * as React from 'react';
+import ReactTable from "react-table";
+
import { SqlControl } from '../components/sql-control';
import {
- QueryManager,
- localStorageSet,
- localStorageGet,
decodeRune,
HeaderRows,
- queryDruidRune, queryDruidSql
+ localStorageGet,
+ localStorageSet,
+ queryDruidRune,
+ queryDruidSql, QueryManager
} from '../utils';
+
import "./sql-view.scss";
export interface SqlViewProps extends React.Props<any> {
@@ -84,7 +86,7 @@ export class SqlView extends React.Component<SqlViewProps,
SqlViewState> {
error
});
}
- })
+ });
}
componentWillUnmount(): void {
@@ -117,7 +119,6 @@ export class SqlView extends React.Component<SqlViewProps,
SqlViewState> {
}}
/>
{this.renderResultTable()}
- </div>
+ </div>;
}
}
-
diff --git a/web-console/src/views/tasks-view.tsx
b/web-console/src/views/tasks-view.tsx
index 8219c88..0816c4c 100644
--- a/web-console/src/views/tasks-view.tsx
+++ b/web-console/src/views/tasks-view.tsx
@@ -16,17 +16,19 @@
* limitations under the License.
*/
+import { Alert, Button, Intent } from "@blueprintjs/core";
import axios from 'axios';
-import * as React from 'react';
import * as classNames from 'classnames';
+import * as React from 'react';
import ReactTable from "react-table";
import { Filter } from "react-table";
-import { Button, Intent, Alert } from "@blueprintjs/core";
-import { ButtonGroup, Label, IconNames } from "../components/filler";
-import { addFilter, QueryManager, getDruidErrorMessage, countBy,
formatDuration, queryDruidSql } from "../utils";
+
+import { ButtonGroup, IconNames, Label } from "../components/filler";
import { AsyncActionDialog } from "../dialogs/async-action-dialog";
import { SpecDialog } from "../dialogs/spec-dialog";
import { AppToaster } from '../singletons/toaster';
+import { addFilter, countBy, formatDuration, getDruidErrorMessage,
queryDruidSql, QueryManager } from "../utils";
+
import "./tasks-view.scss";
export interface TasksViewProps extends React.Props<any> {
@@ -102,7 +104,7 @@ export class TasksView extends
React.Component<TasksViewProps, TasksViewState> {
componentDidMount(): void {
this.supervisorQueryManager = new QueryManager({
processQuery: async (query: string) => {
- const resp = await axios.get("/druid/indexer/v1/supervisor?full")
+ const resp = await axios.get("/druid/indexer/v1/supervisor?full");
return resp.data;
},
onStateChange: ({ result, loading, error }) => {
@@ -299,7 +301,7 @@ ORDER BY "rank" DESC, "created_time" DESC`);
data={supervisors || []}
loading={supervisorsLoading}
noDataText={!supervisorsLoading && supervisors && !supervisors.length
? 'No supervisors' : (supervisorsError || '')}
- filterable={true}
+ filterable
columns={[
{
Header: "Datasource",
@@ -338,7 +340,9 @@ ORDER BY "rank" DESC, "created_time" DESC`);
return <span>
<span
style={{ color: value === 'Suspended' ? '#d58512' :
'#2167d5' }}
- >● </span>
+ >
+ ●
+ </span>
{value}
</span>;
}
@@ -363,7 +367,7 @@ ORDER BY "rank" DESC, "created_time" DESC`);
{suspendResume}
<a onClick={() => this.setState({ resetSupervisorId: id
})}>Reset</a>
<a onClick={() => this.setState({ terminateSupervisorId: id
})}>Terminate</a>
- </div>
+ </div>;
}
}
]}
@@ -413,7 +417,7 @@ ORDER BY "rank" DESC, "created_time" DESC`);
data={tasks || []}
loading={tasksLoading}
noDataText={!tasksLoading && tasks && !tasks.length ? 'No tasks' :
(tasksError || '')}
- filterable={true}
+ filterable
filtered={taskFilter}
onFilteredChange={(filtered, column) => {
this.setState({ taskFilter: filtered });
@@ -432,7 +436,7 @@ ORDER BY "rank" DESC, "created_time" DESC`);
accessor: "type",
Cell: row => {
const value = row.value;
- return <a onClick={() => { this.setState({ taskFilter:
addFilter(taskFilter, 'type', value) }) }}>{value}</a>
+ return <a onClick={() => { this.setState({ taskFilter:
addFilter(taskFilter, 'type', value) }); }}>{value}</a>;
}
},
{
@@ -440,7 +444,7 @@ ORDER BY "rank" DESC, "created_time" DESC`);
accessor: "datasource",
Cell: row => {
const value = row.value;
- return <a onClick={() => { this.setState({ taskFilter:
addFilter(taskFilter, 'datasource', value) }) }}>{value}</a>
+ return <a onClick={() => { this.setState({ taskFilter:
addFilter(taskFilter, 'datasource', value) }); }}>{value}</a>;
}
},
{
@@ -462,10 +466,12 @@ ORDER BY "rank" DESC, "created_time" DESC`);
return <span>
<span
style={{ color: statusToColor(status) }}
- >● </span>
- { status }
- { location && <a onClick={() =>
goToMiddleManager(locationHostname)} title={`Go to:
${locationHostname}`}> ➚</a> }
- { errorMsg && <a onClick={() => this.setState({ alertErrorMsg:
errorMsg })} title={errorMsg}> ?</a> }
+ >
+ ●
+ </span>
+ {status}
+ {location && <a onClick={() =>
goToMiddleManager(locationHostname)} title={`Go to:
${locationHostname}`}> ➚</a>}
+ {errorMsg && <a onClick={() => this.setState({ alertErrorMsg:
errorMsg })} title={errorMsg}> ?</a>}
</span>;
},
PivotValue: (opt) => {
@@ -503,8 +509,8 @@ ORDER BY "rank" DESC, "created_time" DESC`);
<a href={`/druid/indexer/v1/task/${id}/reports`}
target="_blank">Reports</a>
<a href={`/druid/indexer/v1/task/${id}/log`}
target="_blank">Log (all)</a>
<a href={`/druid/indexer/v1/task/${id}/log?offset=-8192`}
target="_blank">Log (last 8kb)</a>
- { (status === 'RUNNING' || status === 'WAITING' || status ===
'PENDING') && <a onClick={() => this.setState({ killTaskId: id })}>Kill</a> }
- </div>
+ {(status === 'RUNNING' || status === 'WAITING' || status ===
'PENDING') && <a onClick={() => this.setState({ killTaskId: id })}>Kill</a>}
+ </div>;
},
Aggregated: row => ''
}
@@ -583,7 +589,6 @@ ORDER BY "rank" DESC, "created_time" DESC`);
>
<p>{alertErrorMsg}</p>
</Alert>
- </div>
+ </div>;
}
}
-
diff --git a/web-console/tslint.json b/web-console/tslint.json
new file mode 100644
index 0000000..daed15b
--- /dev/null
+++ b/web-console/tslint.json
@@ -0,0 +1,125 @@
+{
+ "extends": [
+ "tslint:recommended",
+ "tslint-react"
+ ],
+ "rules": {
+ "align": true,
+ "array-type": [true, "array"],
+ "arrow-parens": false,
+ "ban": [false,
+ ["_", "extend"],
+ ["_", "isNull"],
+ ["_", "isDefined"]
+ ],
+ "comment-format": [false,
+ "check-space"
+ ],
+ "curly": [true, "ignore-same-line"],
+ "file-header": [true, "Licensed to the Apache Software Foundation
\\(ASF\\).+"],
+ "forin": false,
+ "indent": [true, "spaces", 2],
+ "interface-name": [true, "never-prefix"],
+ "jsdoc-format": true,
+ "label-position": true,
+ "max-line-length": [true, 200],
+ "max-classes-per-file": false,
+ "member-access": false,
+ "member-ordering": [true,
+ {
+ "order": [
+ "static-field",
+ "static-method",
+ "instance-field",
+ "constructor",
+ "instance-method"
+ ]
+ }
+ ],
+ "no-any": false,
+ "no-arg": true,
+ "no-console": [true,
+ "debug",
+ "info",
+ "time",
+ "timeEnd",
+ "trace"
+ ],
+ "no-empty": [true, "allow-empty-catch"],
+ "no-empty-interface": false,
+ "no-eval": true,
+ "no-inferrable-types": true,
+ "no-null-keyword": false,
+ "no-parameter-properties": true,
+ "no-require-imports": false,
+ "no-shadowed-variable": false,
+ "no-string-literal": false,
+ "no-switch-case-fall-through": false,
+ "no-trailing-whitespace": true,
+ "no-unused-expression": false,
+ "no-use-before-declare": false,
+ "object-literal-sort-keys": false,
+ "one-line": [true,
+ "check-catch",
+ "check-else",
+ "check-finally",
+ "check-open-brace",
+ "check-whitespace"
+ ],
+ "ordered-imports": [
+ true,
+ {
+ "import-sources-order": "case-insensitive",
+ "grouped-imports": true,
+ "groups": [
+ { "name": "parent directories", "match": "^\\.\\.", "order": 20 },
+ { "name": "styles", "match": ".scss$", "order": 40 },
+ { "name": "current directory", "match": "^\\.", "order": 30 },
+ { "name": "libraries", "match": ".*", "order": 10 }
+ ]
+ }
+ ],
+ "prefer-const": [true, {"destructuring": "all"}],
+ "quotemark": [false, "double", "jsx-double", "avoid-escape"],
+ "semicolon": true,
+ "switch-default": false,
+ "trailing-comma": [true, {
+ "singleline": "never",
+ "multiline": "never"
+ }],
+ "triple-equals": [true, "allow-null-check"],
+ "typedef": false,
+ "typedef-whitespace": [true, {
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace"
+ }, {
+ "call-signature": "onespace",
+ "index-signature": "onespace",
+ "parameter": "onespace",
+ "property-declaration": "onespace",
+ "variable-declaration": "onespace"
+ }],
+ "variable-name": false,
+ "whitespace": [true,
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-module",
+ "check-separator",
+ "check-type",
+ "check-type-operator"
+ ],
+ "jsx-alignment": true,
+ "jsx-boolean-value": [true, "never"],
+ "jsx-curly-spacing": [true, "never"],
+ "jsx-no-lambda": false,
+ "jsx-no-multiline-js": false,
+ "jsx-no-string-ref": true,
+ "jsx-self-close": true,
+ "jsx-space-before-trailing-slash": false,
+ "jsx-wrap-multiline": false
+ }
+}
diff --git a/web-console/webpack.config.js b/web-console/webpack.config.js
index d9fad8b..cc248a2 100644
--- a/web-console/webpack.config.js
+++ b/web-console/webpack.config.js
@@ -52,6 +52,20 @@ module.exports = (env) => {
rules: [
{
test: /\.tsx?$/,
+ enforce: 'pre',
+ use: [
+ {
+ loader: 'tslint-loader',
+ options: {
+ configFile: 'tslint.json',
+ emitErrors: true,
+ fix: false // Set this to true to auto fix errors
+ }
+ }
+ ]
+ },
+ {
+ test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
},
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]