Update console packages and enforce tslint quotes (#7419)

* update packages and enforce tslint quotes

* remove direct dep on tslint-react
This commit is contained in:
Vadim Ogievetsky 2019-04-07 20:19:08 -07:00 committed by Fangjin Yang
parent 799c66d9ac
commit c69c37e99d
39 changed files with 1506 additions and 1306 deletions

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,10 @@
"pretest": "./script/build",
"run": "./script/run",
"test": "jest --silent 2>&1",
"tslint": "./node_modules/.bin/tslint -c tslint.json --project tsconfig.json --formatters-dir ./node_modules/awesome-code-style/formatter 'src/**/*.ts?(x)'",
"tslint-fix": "npm run tslint -- --fix",
"tslint-changed-only": "git diff --diff-filter=ACMR --name-only | grep -E \\.tsx\\?$ | xargs ./node_modules/.bin/tslint -c tslint.json --project tsconfig.json --formatters-dir ./node_modules/awesome-code-style/formatter",
"tslint-fix-changed-only": "npm run tslint-changed-only -- --fix",
"generate-licenses-file": "license-checker --production --json --out licenses.json",
"check-licenses": "license-checker --production --onlyAllow 'Apache-1.1;Apache-2.0;BSD-2-Clause;BSD-3-Clause;MIT;CC0-1.0' --summary",
"start": "webpack-dev-server --hot --open",
@ -26,58 +30,58 @@
"classnames": "^2.2.6",
"d3-array": "^2.0.3",
"druid-console": "^0.0.2",
"es6-shim": "^0.35.4",
"es6-shim": "^0.35.5",
"es7-shim": "^6.0.0",
"hjson": "^3.1.2",
"lodash.debounce": "^4.0.8",
"numeral": "^2.0.6",
"react": "^16.8.3",
"react": "^16.8.6",
"react-ace": "^6.4.0",
"react-dom": "^16.8.3",
"react-router": "^4.3.1",
"react-router-dom": "^4.3.1",
"react-dom": "^16.8.6",
"react-router": "^5.0.0",
"react-router-dom": "^5.0.0",
"react-table": "~6.8.6",
"tslib": "^1.9.3"
},
"devDependencies": {
"@types/classnames": "^2.2.7",
"@types/d3-array": "^1.2.4",
"@types/hjson": "^2.4.0",
"@types/jest": "^23.3.13",
"@types/lodash.debounce": "^4.0.4",
"@types/mocha": "^5.2.5",
"@types/node": "^10.12.18",
"@types/d3-array": "^2.0.0",
"@types/hjson": "^2.4.1",
"@types/jest": "^24.0.11",
"@types/lodash.debounce": "^4.0.6",
"@types/mocha": "^5.2.6",
"@types/node": "^11.13.0",
"@types/numeral": "^0.0.25",
"@types/react-dom": "^16.0.11",
"@types/react-dom": "^16.8.3",
"@types/react-router-dom": "^4.3.1",
"@types/react-table": "^6.7.21",
"autoprefixer": "^9.4.6",
"css-loader": "^2.1.0",
"@types/react-table": "^6.8.0",
"autoprefixer": "^9.5.0",
"awesome-code-style": "^1.1.4",
"css-loader": "^2.1.1",
"identity-obj-proxy": "^3.0.0",
"ignore-styles": "^5.0.1",
"jest": "^24.0.0",
"jest": "^24.7.1",
"license-checker": "^25.0.1",
"mocha": "^5.2.0",
"mocha": "^6.0.2",
"node-sass": "^4.11.0",
"node-sass-chokidar": "^1.3.4",
"postcss-cli": "^6.1.1",
"postcss-cli": "^6.1.2",
"postcss-loader": "^3.0.0",
"postcss-preset-env": "^6.5.0",
"postcss-preset-env": "^6.6.0",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"stylelint": "^9.10.1",
"stylelint-config-recommended-scss": "^3.2.0",
"stylelint-scss": "^3.5.4",
"stylus": "^0.54.5",
"ts-jest": "^23.10.5",
"ts-jest": "^24.0.1",
"ts-loader": "^5.3.3",
"ts-node": "^8.0.2",
"tslint": "^5.14.0",
"ts-node": "^8.0.3",
"tslint": "^5.15.0",
"tslint-loader": "^3.5.4",
"tslint-react": "^3.6.0",
"typescript": "^3.2.4",
"webpack": "^4.29.0",
"webpack-cli": "^3.2.1",
"webpack-dev-server": "^3.1.14"
"typescript": "^3.4.1",
"webpack": "^4.29.6",
"webpack-cli": "^3.3.0",
"webpack-dev-server": "^3.2.1"
}
}

View File

@ -1,25 +0,0 @@
/*
* 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.
*/
// 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
// tslint:disable
import * as React from 'react';
(React as any).PropTypes = require('prop-types');

View File

@ -16,13 +16,15 @@
* limitations under the License.
*/
import { Button } from "@blueprintjs/core";
import { Button } from '@blueprintjs/core';
import * as React from 'react';
import { Filter, ReactTableDefaults } from "react-table";
import { Filter, ReactTableDefaults } from 'react-table';
import { Loader } from '../components/loader';
import { countBy, makeTextFilter } from '../utils';
/* tslint:disable:max-classes-per-file */
class FullButton extends React.Component {
render() {
return <Button fill {...this.props}/>;
@ -37,6 +39,8 @@ class NoData extends React.Component {
}
}
/* tslint:enable:max-classes-per-file */
Object.assign(ReactTableDefaults, {
defaultFilterMethod: (filter: Filter, row: any, column: any) => {
const id = filter.pivotId || filter.id;

View File

@ -16,13 +16,13 @@
* limitations under the License.
*/
import { InputGroup } from "@blueprintjs/core";
import { FormGroup, HTMLSelect, NumericInput, TagInput } from "@blueprintjs/core";
import { InputGroup } from '@blueprintjs/core';
import { FormGroup, HTMLSelect, NumericInput, TagInput } from '@blueprintjs/core';
import * as React from 'react';
import { JSONInput } from './json-input';
import "./auto-form.scss";
import './auto-form.scss';
interface Field {
name: string;
@ -44,7 +44,7 @@ export interface AutoFormState<T> {
export class AutoForm<T> extends React.Component<AutoFormProps<T>, AutoFormState<T>> {
static makeLabelName(label: string): string {
let newLabel = label.split(/(?=[A-Z])/).map(s => s.toLowerCase()).join(" ");
let newLabel = label.split(/(?=[A-Z])/).map(s => s.toLowerCase()).join(' ');
newLabel = newLabel[0].toUpperCase() + newLabel.slice(1);
return newLabel;
}
@ -95,9 +95,9 @@ export class AutoForm<T> extends React.Component<AutoFormProps<T>, AutoFormState
private renderBooleanInput(field: Field): JSX.Element {
const { model, onChange } = this.props;
return <HTMLSelect
value={(model as any)[field.name] === true ? "True" : "False"}
value={(model as any)[field.name] === true ? 'True' : 'False'}
onChange={(e: any) => {
onChange(Object.assign({}, model, { [field.name]: e.currentTarget.value === "True" }));
onChange(Object.assign({}, model, { [field.name]: e.currentTarget.value === 'True' }));
}}
>
<option value="True">True</option>

View File

@ -17,7 +17,7 @@
*/
.header-bar {
z-index: 10;
overflow: hidden;
.logo {
position: relative;

View File

@ -16,14 +16,14 @@
* limitations under the License.
*/
import { Alignment, AnchorButton, Button, Classes, Menu, MenuItem, Navbar, NavbarDivider, NavbarGroup, Popover, Position } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons";
import { Alignment, AnchorButton, Button, Classes, Menu, MenuItem, Navbar, NavbarDivider, NavbarGroup, Popover, Position } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import classNames from 'classnames';
import * as React from 'react';
import { AboutDialog } from "../dialogs/about-dialog";
import { AboutDialog } from '../dialogs/about-dialog';
import { CoordinatorDynamicConfigDialog } from '../dialogs/coordinator-dynamic-config';
import { OverlordDynamicConfigDialog } from "../dialogs/overlord-dynamic-config";
import { OverlordDynamicConfigDialog } from '../dialogs/overlord-dynamic-config';
import {
DRUID_DOCS,
DRUID_GITHUB,
@ -32,7 +32,7 @@ import {
LEGACY_OVERLORD_CONSOLE
} from '../variables';
import "./header-bar.scss";
import './header-bar.scss';
export type HeaderActiveTab = null | 'datasources' | 'segments' | 'tasks' | 'servers' | 'sql' | 'lookups';

View File

@ -41,7 +41,7 @@ export class JSONCollapse extends React.Component<JSONCollapseProps, JSONCollaps
const { stringValue, buttonText} = this.props;
const { isOpen } = this.state;
const prettyValue = JSON.stringify(JSON.parse(stringValue), undefined, 2);
return <div className={"json-collapse"}>
return <div className="json-collapse">
<Button
minimal
active={isOpen}

View File

@ -17,9 +17,9 @@
*/
import * as React from 'react';
import AceEditor from "react-ace";
import AceEditor from 'react-ace';
import { parseStringToJSON, stringifyJSON, validJson } from "../utils";
import { parseStringToJSON, stringifyJSON, validJson } from '../utils';
interface JSONInputProps extends React.Props<any> {
onChange: (newJSONValue: any) => void;
@ -38,7 +38,7 @@ export class JSONInput extends React.Component<JSONInputProps, JSONInputState> {
constructor(props: JSONInputProps) {
super(props);
this.state = {
stringValue: ""
stringValue: ''
};
}
@ -62,19 +62,19 @@ export class JSONInput extends React.Component<JSONInputProps, JSONInputState> {
const { onChange, updateInputValidity, focus, width, height } = this.props;
const { stringValue } = this.state;
return <AceEditor
key={"hjson"}
mode={"hjson"}
key="hjson"
mode="hjson"
theme="solarized_dark"
name="ace-editor"
onChange={(e: string) => {
this.setState({stringValue: e});
if (validJson(e) || e === "") onChange(parseStringToJSON(e));
if (validJson(e) || e === '') onChange(parseStringToJSON(e));
if (updateInputValidity) updateInputValidity(validJson(e) || e === '');
}}
focus={focus}
fontSize={12}
width={width || '100%'}
height={height || "8vh"}
height={height || '8vh'}
showPrintMargin={false}
showGutter={false}
value={stringValue}

View File

@ -16,8 +16,8 @@
* limitations under the License.
*/
import { Button, Card, Collapse, ControlGroup, FormGroup, HTMLSelect, InputGroup, NumericInput, TagInput } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons";
import { Button, Card, Collapse, ControlGroup, FormGroup, HTMLSelect, InputGroup, NumericInput, TagInput } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import axios from 'axios';
import * as React from 'react';

View File

@ -16,9 +16,9 @@
* limitations under the License.
*/
import { Button, Checkbox, Classes, FormGroup, Intent, Menu, Popover, Position } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons";
import axios from "axios";
import { Button, Checkbox, Classes, FormGroup, Intent, Menu, Popover, Position } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import axios from 'axios';
import * as ace from 'brace';
import 'brace/ext/language_tools';
import 'brace/mode/hjson';
@ -26,11 +26,11 @@ import 'brace/mode/sql';
import 'brace/theme/solarized_dark';
import * as classNames from 'classnames';
import * as React from 'react';
import AceEditor from "react-ace";
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 { SQLFunctionDoc } from '../../lib/sql-function-doc';
import { AppToaster } from '../singletons/toaster';
import './sql-control.scss';
@ -59,13 +59,13 @@ 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`});
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 {
value: datasourceName,
score: 50,
meta: "datasource"
meta: 'datasource'
};
});
@ -79,13 +79,13 @@ 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 {
value: columnName,
score: 50,
meta: "column"
meta: 'column'
};
});
@ -100,12 +100,12 @@ 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);
let funcName: string = entry.syntax.replace(/\(.*\)/, '()');
if (!funcName.includes('(')) funcName = funcName.substr(0, 10);
return {
value: funcName,
score: 80,
meta: "function",
meta: 'function',
syntax: entry.syntax,
description: entry.description,
completer: {
@ -123,11 +123,11 @@ export class SqlControl extends React.Component<SqlControlProps, SqlControlState
callback(null, functionList);
},
getDocTooltip: (item: any) => {
if (item.meta === "function") {
if (item.meta === 'function') {
const functionName = item.caption.slice(0, -2);
item.docHTML = ReactDOMServer.renderToStaticMarkup((
<div className={"function-doc"}>
<div className={"function-doc-name"}><b>{functionName}</b></div>
<div className="function-doc">
<div className="function-doc-name"><b>{functionName}</b></div>
<hr/>
<div><b>Syntax:</b></div>
<div>{item.syntax}</div>
@ -149,7 +149,7 @@ export class SqlControl extends React.Component<SqlControlProps, SqlControlState
await this.addColumnNameAutoCompleter();
} catch (e) {
AppToaster.show({
message: "Failed to load SQL auto completer",
message: 'Failed to load SQL auto completer',
intent: Intent.DANGER
});
}
@ -173,16 +173,16 @@ export class SqlControl extends React.Component<SqlControlProps, SqlControlState
const SqlControlPopover = <Popover position={Position.BOTTOM_LEFT}>
<Button minimal icon={IconNames.MORE}/>
<div className={"sql-control-popover"}>
<div className="sql-control-popover">
<Checkbox
checked={isRune ? false : autoCompleteOn}
label={"Auto complete"}
label="Auto complete"
onChange={() => this.setState({autoCompleteOn: !autoCompleteOn})}
/>
<Button
icon={IconNames.CLEAN}
className={Classes.POPOVER_DISMISS}
text={"Explain"}
text="Explain"
onClick={() => onExplain(query)}
minimal
/>
@ -192,15 +192,15 @@ export class SqlControl extends React.Component<SqlControlProps, SqlControlState
// Set the key in the AceEditor to force a rebind and prevent an error that happens otherwise
return <div className="sql-control">
<AceEditor
key={isRune ? "hjson" : "sql"}
mode={isRune ? "hjson" : "sql"}
key={isRune ? 'hjson' : 'sql'}
mode={isRune ? 'hjson' : 'sql'}
theme="solarized_dark"
name="ace-editor"
onChange={this.handleChange}
focus
fontSize={14}
width={'100%'}
height={"30vh"}
width="100%"
height="30vh"
showPrintMargin={false}
value={query}
editorProps={{

View File

@ -16,11 +16,11 @@
* limitations under the License.
*/
import { Button, Checkbox, FormGroup, Menu, Popover, Position } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons";
import { Button, Checkbox, FormGroup, Menu, Popover, Position } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import * as React from 'react';
import "./table-column-selection.scss";
import './table-column-selection.scss';
interface TableColumnSelectionProps extends React.Props<any> {
columns: string[];
@ -61,7 +61,7 @@ export class TableColumnSelection extends React.Component<TableColumnSelectionPr
content={checkboxes}
position={Position.BOTTOM_RIGHT}
>
<Button rightIcon={IconNames.CARET_DOWN} text={"Columns"} />
<Button rightIcon={IconNames.CARET_DOWN} text="Columns" />
</Popover>;
}
}

View File

@ -16,25 +16,25 @@
* limitations under the License.
*/
import { Intent } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons";
import { Intent } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import axios from 'axios';
import * as classNames from 'classnames';
import * as React from 'react';
import { HashRouter, Route, Switch } from "react-router-dom";
import { HashRouter, Route, Switch } from 'react-router-dom';
import { HeaderActiveTab, HeaderBar } from './components/header-bar';
import { AppToaster } from './singletons/toaster';
import { DRUID_DOCS_SQL, LEGACY_COORDINATOR_CONSOLE, LEGACY_OVERLORD_CONSOLE } from './variables';
import { DatasourcesView } from './views/datasource-view';
import { HomeView } from './views/home-view';
import { LookupsView } from "./views/lookups-view";
import { LookupsView } from './views/lookups-view';
import { SegmentsView } from './views/segments-view';
import { ServersView } from './views/servers-view';
import { SqlView } from './views/sql-view';
import { TasksView } from './views/tasks-view';
import "./console-application.scss";
import './console-application.scss';
export interface ConsoleApplicationProps extends React.Props<any> {
hideLegacy: boolean;
@ -51,12 +51,12 @@ export class ConsoleApplication extends React.Component<ConsoleApplicationProps,
static async ensureSql() {
try {
await axios.post("/druid/v2/sql", { query: 'SELECT 1337' });
await axios.post('/druid/v2/sql', { query: 'SELECT 1337' });
} catch (e) {
const { response } = e;
if (response.status !== 405 || response.statusText !== "Method Not Allowed") return true; // other failure
if (response.status !== 405 || response.statusText !== 'Method Not Allowed') return true; // other failure
try {
await axios.get("/status");
await axios.get('/status');
} catch (e) {
return true; // total failure
}

View File

@ -16,8 +16,8 @@
* limitations under the License.
*/
import { AnchorButton, Button, Classes, Dialog, Intent } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons";
import { AnchorButton, Button, Classes, Dialog, Intent } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import * as React from 'react';
import { DRUID_COMMUNITY, DRUID_DEVELOPER_GROUP, DRUID_USER_GROUP, DRUID_WEBSITE } from '../variables';

View File

@ -23,8 +23,8 @@ import {
Dialog,
FormGroup,
Icon, Intent, NumericInput, ProgressBar, TagInput
} from "@blueprintjs/core";
import { IconName } from "@blueprintjs/icons";
} from '@blueprintjs/core';
import { IconName } from '@blueprintjs/icons';
import classNames from 'classnames';
import * as React from 'react';

View File

@ -16,7 +16,7 @@
* limitations under the License.
*/
import { Button, Classes, Dialog, Intent } from "@blueprintjs/core";
import { Button, Classes, Dialog, Intent } from '@blueprintjs/core';
import * as React from 'react';
import { AutoForm } from '../components/auto-form';
@ -52,7 +52,7 @@ export class CompactionDialog extends React.Component<CompactionDialogProps, Com
inputSegmentSizeBytes: 419430400,
keepSegmentGranularity: true,
maxNumSegmentsToCompact: 150,
skipOffsetFromLatest: "P1D",
skipOffsetFromLatest: 'P1D',
targetCompactionSizeBytes: 419430400,
taskContext: null,
taskPriority: 25,
@ -79,36 +79,36 @@ export class CompactionDialog extends React.Component<CompactionDialogProps, Com
<AutoForm
fields={[
{
name: "inputSegmentSizeBytes",
type: "number"
name: 'inputSegmentSizeBytes',
type: 'number'
},
{
name: "keepSegmentGranularity",
type: "boolean"
name: 'keepSegmentGranularity',
type: 'boolean'
},
{
name: "maxNumSegmentsToCompact",
type: "number"
name: 'maxNumSegmentsToCompact',
type: 'number'
},
{
name: "skipOffsetFromLatest",
type: "string"
name: 'skipOffsetFromLatest',
type: 'string'
},
{
name: "targetCompactionSizeBytes",
type: "number"
name: 'targetCompactionSizeBytes',
type: 'number'
},
{
name: "taskContext",
type: "json"
name: 'taskContext',
type: 'json'
},
{
name: "taskPriority",
type: "number"
name: 'taskPriority',
type: 'number'
},
{
name: "tuningConfig",
type: "json"
name: 'tuningConfig',
type: 'json'
}
]}
model={currentConfig}

View File

@ -70,7 +70,7 @@ export class CoordinatorDynamicConfigDialog extends React.Component<CoordinatorD
async getClusterConfig() {
let config: Record<string, any> | null = null;
try {
const configResp = await axios.get("/druid/coordinator/v1/config");
const configResp = await axios.get('/druid/coordinator/v1/config');
config = configResp.data;
} catch (e) {
AppToaster.show({
@ -89,10 +89,10 @@ export class CoordinatorDynamicConfigDialog extends React.Component<CoordinatorD
const { onClose } = this.props;
const newState: any = this.state.dynamicConfig;
try {
await axios.post("/druid/coordinator/v1/config", newState, {
await axios.post('/druid/coordinator/v1/config', newState, {
headers: {
"X-Druid-Author": "console",
"X-Druid-Comment": comment
'X-Druid-Author': 'console',
'X-Druid-Comment': comment
}
});
} catch (e) {
@ -129,52 +129,52 @@ export class CoordinatorDynamicConfigDialog extends React.Component<CoordinatorD
<AutoForm
fields={[
{
name: "balancerComputeThreads",
type: "number"
name: 'balancerComputeThreads',
type: 'number'
},
{
name: "emitBalancingStats",
type: "boolean"
name: 'emitBalancingStats',
type: 'boolean'
},
{
name: "killAllDataSources",
type: "boolean"
name: 'killAllDataSources',
type: 'boolean'
},
{
name: "killDataSourceWhitelist",
type: "string-array"
name: 'killDataSourceWhitelist',
type: 'string-array'
},
{
name: "killPendingSegmentsSkipList",
type: "string-array"
name: 'killPendingSegmentsSkipList',
type: 'string-array'
},
{
name: "maxSegmentsInNodeLoadingQueue",
type: "number"
name: 'maxSegmentsInNodeLoadingQueue',
type: 'number'
},
{
name: "maxSegmentsToMove",
type: "number"
name: 'maxSegmentsToMove',
type: 'number'
},
{
name: "mergeBytesLimit",
type: "size-bytes"
name: 'mergeBytesLimit',
type: 'size-bytes'
},
{
name: "mergeSegmentsLimit",
type: "number"
name: 'mergeSegmentsLimit',
type: 'number'
},
{
name: "millisToWaitBeforeDeleting",
type: "number"
name: 'millisToWaitBeforeDeleting',
type: 'number'
},
{
name: "replicantLifetime",
type: "number"
name: 'replicantLifetime',
type: 'number'
},
{
name: "replicationThrottleLimit",
type: "number"
name: 'replicationThrottleLimit',
type: 'number'
}
]}
model={dynamicConfig}

View File

@ -16,12 +16,12 @@
* limitations under the License.
*/
import { Card, Dialog } from "@blueprintjs/core";
import * as React from "react";
import { Card, Dialog } from '@blueprintjs/core';
import * as React from 'react';
import { JSONCollapse } from '../components/json-collapse';
import "./history-dialog.scss";
import './history-dialog.scss';
interface HistoryDialogProps extends React.Props<any> {
historyRecords: any;
@ -43,28 +43,28 @@ export class HistoryDialog extends React.Component<HistoryDialogProps, HistoryDi
const {children, historyRecords} = this.props;
let content;
if (historyRecords.length === 0) {
content = <div className={"no-record"}>No history records available</div>;
content = <div className="no-record">No history records available</div>;
} else {
content = <>
<h3>History</h3>
<div className={"history-record-entries"}>
<div className="history-record-entries">
{
historyRecords.map((record: any) => {
const auditInfo = record.auditInfo;
const auditTime = record.auditTime;
const formattedTime = auditTime.replace("T", " ").substring(0, auditTime.length - 5);
const formattedTime = auditTime.replace('T', ' ').substring(0, auditTime.length - 5);
return <div key={record.auditTime} className={"history-record-entry"}>
return <div key={record.auditTime} className="history-record-entry">
<Card>
<div className={"history-record-title"}>
<div className="history-record-title">
<h5>Change</h5>
<p>{formattedTime}</p>
</div>
<hr/>
<p>{auditInfo.comment === "" ? "(No comment)" : auditInfo.comment}</p>
<p>{auditInfo.comment === '' ? '(No comment)' : auditInfo.comment}</p>
<JSONCollapse
stringValue={record.payload}
buttonText={"Payload"}
buttonText="Payload"
/>
</Card>
</div>;
@ -73,7 +73,7 @@ export class HistoryDialog extends React.Component<HistoryDialogProps, HistoryDi
</div>
</>;
}
return <div className={"history-record-container"}>
return <div className="history-record-container">
{content}
{children}
</div>;
@ -81,9 +81,9 @@ export class HistoryDialog extends React.Component<HistoryDialogProps, HistoryDi
render(): React.ReactNode {
return <Dialog
className="history-dialog"
isOpen
{...this.props}
className={"history-dialog"}
>
{this.renderRecords()}
</Dialog>;

View File

@ -16,13 +16,13 @@
* limitations under the License.
*/
import { Button, Classes, Dialog, FormGroup, HTMLSelect, InputGroup, Intent } from "@blueprintjs/core";
import * as React from "react";
import AceEditor from "react-ace";
import { Button, Classes, Dialog, FormGroup, HTMLSelect, InputGroup, Intent } from '@blueprintjs/core';
import * as React from 'react';
import AceEditor from 'react-ace';
import { validJson } from "../utils";
import { validJson } from '../utils';
import "./lookup-edit-dialog.scss";
import './lookup-edit-dialog.scss';
export interface LookupEditDialogProps extends React.Props<any> {
isOpen: boolean;
@ -53,22 +53,22 @@ export class LookupEditDialog extends React.Component<LookupEditDialogProps, Loo
const {onChange} = this.props;
const currentDate = new Date();
const ISOString = currentDate.toISOString();
onChange("lookupEditVersion", ISOString);
onChange('lookupEditVersion', ISOString);
}
private renderTierInput() {
const { isEdit, lookupTier, allLookupTiers, onChange } = this.props;
if (isEdit) {
return <FormGroup className={"lookup-label"} label={"Tier: "}>
return <FormGroup className="lookup-label" label="Tier: ">
<InputGroup
value={lookupTier}
onChange={(e: any) => onChange("lookupEditTier", e.target.value)}
onChange={(e: any) => onChange('lookupEditTier', e.target.value)}
disabled
/>
</FormGroup>;
} else {
return <FormGroup className={"lookup-label"} label={"Tier:"}>
<HTMLSelect disabled={isEdit} value={lookupTier} onChange={(e: any) => onChange("lookupEditTier", e.target.value)}>
return <FormGroup className="lookup-label" label="Tier:">
<HTMLSelect disabled={isEdit} value={lookupTier} onChange={(e: any) => onChange('lookupEditTier', e.target.value)}>
{allLookupTiers.map(tier => (
<option key={tier} value={tier}>{tier}</option>
))}
@ -80,47 +80,47 @@ export class LookupEditDialog extends React.Component<LookupEditDialogProps, Loo
render() {
const { isOpen, onClose, onSubmit, lookupSpec, lookupTier, lookupName, lookupVersion, onChange, isEdit, allLookupTiers } = this.props;
const disableSubmit = lookupName === "" || lookupVersion === "" ||
lookupTier === "" || !validJson(lookupSpec);
const disableSubmit = lookupName === '' || lookupVersion === '' ||
lookupTier === '' || !validJson(lookupSpec);
return <Dialog
className={"lookup-edit-dialog"}
className="lookup-edit-dialog"
isOpen={isOpen}
onClose={onClose}
title={isEdit ? "Edit lookup" : "Add lookup"}
title={isEdit ? 'Edit lookup' : 'Add lookup'}
>
<FormGroup className={"lookup-label"} label={"Name: "}>
<FormGroup className="lookup-label" label="Name: ">
<InputGroup
value={lookupName}
onChange={(e: any) => onChange("lookupEditName", e.target.value)}
onChange={(e: any) => onChange('lookupEditName', e.target.value)}
disabled={isEdit}
placeholder={"Enter the lookup name"}
placeholder="Enter the lookup name"
/>
</FormGroup>
{this.renderTierInput()}
<FormGroup className={"lookup-label"} label={"Version:"}>
<FormGroup className="lookup-label" label="Version:">
<InputGroup
value={lookupVersion}
onChange={(e: any) => onChange("lookupEditVersion", e.target.value)}
placeholder={"Enter the lookup version"}
rightElement={<Button minimal text={"Use ISO as version"} onClick={() => this.addISOVersion()} />}
onChange={(e: any) => onChange('lookupEditVersion', e.target.value)}
placeholder="Enter the lookup version"
rightElement={<Button minimal text="Use ISO as version" onClick={() => this.addISOVersion()} />}
/>
</FormGroup>
<FormGroup className={"lookup-label"} label={"Spec:"}/>
<FormGroup className="lookup-label" label="Spec:"/>
<AceEditor
className={"lookup-edit-dialog-textarea"}
className="lookup-edit-dialog-textarea"
mode="sql"
theme="solarized_dark"
onChange={
(e: any) => onChange("lookupEditSpec", e)
(e: any) => onChange('lookupEditSpec', e)
}
fontSize={12}
height={"40vh"}
width={"auto"}
height="40vh"
width="auto"
showPrintMargin={false}
showGutter={false}
value={lookupSpec}

View File

@ -16,18 +16,18 @@
* limitations under the License.
*/
import { Intent } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons";
import axios from "axios";
import * as React from "react";
import { Intent } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import axios from 'axios';
import * as React from 'react';
import { AutoForm } from "../components/auto-form";
import { AppToaster } from "../singletons/toaster";
import { getDruidErrorMessage, QueryManager } from "../utils";
import { AutoForm } from '../components/auto-form';
import { AppToaster } from '../singletons/toaster';
import { getDruidErrorMessage, QueryManager } from '../utils';
import { SnitchDialog } from "./snitch-dialog";
import { SnitchDialog } from './snitch-dialog';
import "./overlord-dynamic-config.scss";
import './overlord-dynamic-config.scss';
export interface OverlordDynamicConfigDialogProps extends React.Props<any> {
onClose: () => void;
@ -72,7 +72,7 @@ export class OverlordDynamicConfigDialog extends React.Component<OverlordDynamic
async getConfig() {
let config: Record<string, any> | null = null;
try {
const configResp = await axios.get("/druid/indexer/v1/worker");
const configResp = await axios.get('/druid/indexer/v1/worker');
config = configResp.data || {};
} catch (e) {
AppToaster.show({
@ -91,10 +91,10 @@ export class OverlordDynamicConfigDialog extends React.Component<OverlordDynamic
const { onClose } = this.props;
const newState: any = this.state.dynamicConfig;
try {
await axios.post("/druid/indexer/v1/worker", newState, {
await axios.post('/druid/indexer/v1/worker', newState, {
headers: {
"X-Druid-Author": "console",
"X-Druid-Comment": comment
'X-Druid-Author': 'console',
'X-Druid-Comment': comment
}
});
} catch (e) {
@ -132,12 +132,12 @@ export class OverlordDynamicConfigDialog extends React.Component<OverlordDynamic
<AutoForm
fields={[
{
name: "selectStrategy",
type: "json"
name: 'selectStrategy',
type: 'json'
},
{
name: "autoScaler",
type: "json"
name: 'autoScaler',
type: 'json'
}
]}
model={dynamicConfig}

View File

@ -16,12 +16,12 @@
* limitations under the License.
*/
import { Button, Classes, Dialog, FormGroup, InputGroup, TextArea } from "@blueprintjs/core";
import * as React from "react";
import { Button, Classes, Dialog, FormGroup, InputGroup, TextArea } from '@blueprintjs/core';
import * as React from 'react';
import { BasicQueryExplanation, SemiJoinQueryExplanation } from "../utils";
import { BasicQueryExplanation, SemiJoinQueryExplanation } from '../utils';
import "./query-plan-dialog.scss";
import './query-plan-dialog.scss';
export interface QueryPlanDialogProps extends React.Props<any> {
explainResult: BasicQueryExplanation | SemiJoinQueryExplanation | string | null;
@ -53,17 +53,17 @@ export class QueryPlanDialog extends React.Component<QueryPlanDialogProps, Query
let signature: JSX.Element | null = null;
if ((explainResult as BasicQueryExplanation).signature) {
const signatureContent = (explainResult as BasicQueryExplanation).signature || "";
const signatureContent = (explainResult as BasicQueryExplanation).signature || '';
signature = <FormGroup
label={"Signature"}
label="Signature"
>
<InputGroup defaultValue={signatureContent} readOnly/>
</FormGroup>;
}
content = <div className={"one-query"}>
content = <div className="one-query">
<FormGroup
label={"Query"}
label="Query"
>
<TextArea
readOnly
@ -77,25 +77,25 @@ export class QueryPlanDialog extends React.Component<QueryPlanDialogProps, Query
let mainSignature: JSX.Element | null = null;
let subSignature: JSX.Element | null = null;
if ((explainResult as SemiJoinQueryExplanation).mainQuery.signature) {
const signatureContent = (explainResult as SemiJoinQueryExplanation).mainQuery.signature || "";
const signatureContent = (explainResult as SemiJoinQueryExplanation).mainQuery.signature || '';
mainSignature = <FormGroup
label={"Signature"}
label="Signature"
>
<InputGroup defaultValue={signatureContent} readOnly/>
</FormGroup>;
}
if ((explainResult as SemiJoinQueryExplanation).subQueryRight.signature) {
const signatureContent = (explainResult as SemiJoinQueryExplanation).subQueryRight.signature || "";
const signatureContent = (explainResult as SemiJoinQueryExplanation).subQueryRight.signature || '';
subSignature = <FormGroup
label={"Signature"}
label="Signature"
>
<InputGroup defaultValue={signatureContent} readOnly/>
</FormGroup>;
}
content = <div className={"two-queries"}>
content = <div className="two-queries">
<FormGroup
label={"Main query"}
label="Main query"
>
<TextArea
readOnly
@ -104,7 +104,7 @@ export class QueryPlanDialog extends React.Component<QueryPlanDialogProps, Query
</FormGroup>
{mainSignature}
<FormGroup
label={"Sub query"}
label="Sub query"
>
<TextArea
readOnly
@ -118,10 +118,10 @@ export class QueryPlanDialog extends React.Component<QueryPlanDialogProps, Query
}
return <Dialog
className={'query-plan-dialog'}
className="query-plan-dialog"
isOpen
onClose={onClose}
title={"Query plan"}
title="Query plan"
>
<div className={Classes.DIALOG_BODY}>
{content}

View File

@ -16,13 +16,13 @@
* limitations under the License.
*/
import { Button, FormGroup } from "@blueprintjs/core";
import { Button, FormGroup } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import axios from 'axios';
import * as React from 'react';
import { Rule, RuleEditor } from '../components/rule-editor';
import { QueryManager } from "../utils";
import { QueryManager } from '../utils';
import { SnitchDialog } from './snitch-dialog';

View File

@ -24,12 +24,12 @@ import {
IDialogProps,
InputGroup,
Intent
} from "@blueprintjs/core";
} from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import classNames = require('classnames');
import * as React from 'react';
import { HistoryDialog } from "./history-dialog";
import { HistoryDialog } from './history-dialog';
import './snitch-dialog.scss';
@ -54,7 +54,7 @@ export class SnitchDialog extends React.Component<SnitchDialogProps, SnitchDialo
super(props);
this.state = {
comment: "",
comment: '',
saveDisabled: true
};
}
@ -107,11 +107,11 @@ export class SnitchDialog extends React.Component<SnitchDialogProps, SnitchDialo
return <Dialog {...this.props}>
<div className={`dialog-body ${Classes.DIALOG_BODY}`}>
<FormGroup label={"Why are you making this change?"} className={"comment"}>
<FormGroup label="Why are you making this change?" className="comment">
<InputGroup
large
value={comment}
placeholder={"Enter description here"}
placeholder="Enter description here"
onChange={(e: any) => this.changeComment(e.target.value)}
/>
</FormGroup>
@ -147,7 +147,7 @@ export class SnitchDialog extends React.Component<SnitchDialogProps, SnitchDialo
{ showFinalStep
? <Button onClick={this.back} icon={IconNames.ARROW_LEFT}>Back</Button>
: onReset ? <Button onClick={this.reset} intent={"none" as any}>Reset</Button> : null
: onReset ? <Button onClick={this.reset} intent={'none' as any}>Reset</Button> : null
}
{ showFinalStep

View File

@ -16,13 +16,13 @@
* limitations under the License.
*/
import { Button, Classes, Dialog, Intent } from "@blueprintjs/core";
import "brace/mode/json";
import "brace/theme/solarized_dark";
import * as React from "react";
import AceEditor from "react-ace";
import { Button, Classes, Dialog, Intent } from '@blueprintjs/core';
import 'brace/mode/json';
import 'brace/theme/solarized_dark';
import * as React from 'react';
import AceEditor from 'react-ace';
import "./spec-dialog.scss";
import './spec-dialog.scss';
export interface SpecDialogProps extends React.Props<any> {
onSubmit: (spec: JSON) => void;
@ -65,7 +65,7 @@ export class SpecDialog extends React.Component<SpecDialogProps, SpecDialogState
const { spec } = this.state;
return <Dialog
className={"spec-dialog"}
className="spec-dialog"
isOpen
onClose={onClose}
title={title}
@ -74,14 +74,14 @@ export class SpecDialog extends React.Component<SpecDialogProps, SpecDialogState
<AceEditor
mode="json"
theme="solarized_dark"
className={"spec-dialog-textarea"}
className="spec-dialog-textarea"
onChange={(e) => { this.setState({ spec: e }); }}
fontSize={12}
showPrintMargin={false}
showGutter
highlightActiveLine
value={spec}
width={"100%"}
width="100%"
setOptions={{
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,

View File

@ -21,11 +21,10 @@ import 'es7-shim'; // Webpack with automatically pick browser.js which does the
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import "./bootstrap/a-shim-for-react-props";
import "./bootstrap/react-table-defaults";
import './bootstrap/react-table-defaults';
import { ConsoleApplication } from './console-application';
import "./entry.scss";
import './entry.scss';
const container = document.getElementsByClassName('app-container')[0];
if (!container) throw new Error('container not found');

View File

@ -16,9 +16,9 @@
* limitations under the License.
*/
import { Position, Toaster } from "@blueprintjs/core";
import { Position, Toaster } from '@blueprintjs/core';
export const AppToaster = Toaster.create({
className: "recipe-toaster",
className: 'recipe-toaster',
position: Position.TOP
});

View File

@ -27,7 +27,7 @@ export function getDruidErrorMessage(e: any) {
export async function queryDruidRune(runeQuery: Record<string, any>): Promise<any> {
let runeResultResp: AxiosResponse<any>;
try {
runeResultResp = await axios.post("/druid/v2", runeQuery);
runeResultResp = await axios.post('/druid/v2', runeQuery);
} catch (e) {
throw new Error(getDruidErrorMessage(e));
}
@ -37,7 +37,7 @@ export async function queryDruidRune(runeQuery: Record<string, any>): Promise<an
export async function queryDruidSql(sqlQuery: Record<string, any>): Promise<any[]> {
let sqlResultResp: AxiosResponse<any>;
try {
sqlResultResp = await axios.post("/druid/v2/sql", sqlQuery);
sqlResultResp = await axios.post('/druid/v2/sql', sqlQuery);
} catch (e) {
throw new Error(getDruidErrorMessage(e));
}

View File

@ -18,7 +18,7 @@
import { Button, HTMLSelect, InputGroup, Intent } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import * as numeral from "numeral";
import * as numeral from 'numeral';
import * as React from 'react';
import { Filter, FilterRender } from 'react-table';
@ -55,7 +55,7 @@ export function makeBooleanFilter(): FilterRender {
key={key}
style={{ width: '100%' }}
onChange={(event: any) => onChange(event.target.value)}
value={filterValue || "all"}
value={filterValue || 'all'}
fill
>
<option value="all">Show all</option>
@ -141,13 +141,13 @@ export function stringifyJSON(item: any): string {
if (item != null) {
return JSON.stringify(item, null, 2);
} else {
return "";
return '';
}
}
// parse string to JSON object; if string is empty, return null
export function parseStringToJSON(s: string): JSON | null {
if (s === "") {
if (s === '') {
return null;
} else {
return JSON.parse(s);

View File

@ -17,13 +17,13 @@
*/
export const LocalStorageKeys = {
DATASOURCE_TABLE_COLUMN_SELECTION: "datasource-table-column-selection" as "datasource-table-column-selection",
SEGMENT_TABLE_COLUMN_SELECTION: "segment-table-column-selection" as "segment-table-column-selection",
SUPERVISOR_TABLE_COLUMN_SELECTION: "supervisor-table-column-selection" as "supervisor-table-column-selection",
TASK_TABLE_COLUMN_SELECTION: "task-table-column-selection" as "task-table-column-selection",
SERVER_TABLE_COLUMN_SELECTION: "historical-table-column-selection" as "historical-table-column-selection",
MIDDLEMANAGER_TABLE_COLUMN_SELECTION: "middleManager-table-column-selection" as "middleManager-table-column-selection",
LOOKUP_TABLE_COLUMN_SELECTION: "lookup-table-column-selection" as "lookup-table-column-selection",
DATASOURCE_TABLE_COLUMN_SELECTION: 'datasource-table-column-selection' as 'datasource-table-column-selection',
SEGMENT_TABLE_COLUMN_SELECTION: 'segment-table-column-selection' as 'segment-table-column-selection',
SUPERVISOR_TABLE_COLUMN_SELECTION: 'supervisor-table-column-selection' as 'supervisor-table-column-selection',
TASK_TABLE_COLUMN_SELECTION: 'task-table-column-selection' as 'task-table-column-selection',
SERVER_TABLE_COLUMN_SELECTION: 'historical-table-column-selection' as 'historical-table-column-selection',
MIDDLEMANAGER_TABLE_COLUMN_SELECTION: 'middleManager-table-column-selection' as 'middleManager-table-column-selection',
LOOKUP_TABLE_COLUMN_SELECTION: 'lookup-table-column-selection' as 'lookup-table-column-selection',
QUERY_KEY: 'druid-console-query' as 'druid-console-query'
};

View File

@ -16,7 +16,7 @@
* limitations under the License.
*/
import { localStorageGet, LocalStorageKeys, localStorageSet } from "../utils";
import { localStorageGet, LocalStorageKeys, localStorageSet } from '../utils';
export class TableColumnSelectionHandler {
tableName: LocalStorageKeys;

View File

@ -16,13 +16,13 @@
* limitations under the License.
*/
export const LEGACY_COORDINATOR_CONSOLE = "/index.html";
export const LEGACY_OVERLORD_CONSOLE = "/console.html";
export const LEGACY_COORDINATOR_CONSOLE = '/index.html';
export const LEGACY_OVERLORD_CONSOLE = '/console.html';
export const DRUID_WEBSITE = "http://druid.io";
export const DRUID_GITHUB = "https://github.com/apache/druid";
export const DRUID_DOCS = "http://druid.io/docs/latest";
export const DRUID_DOCS_SQL = "http://druid.io/docs/latest/querying/sql.html";
export const DRUID_COMMUNITY = "http://druid.io/community/";
export const DRUID_USER_GROUP = "https://groups.google.com/forum/#!forum/druid-user";
export const DRUID_DEVELOPER_GROUP = "https://lists.apache.org/list.html?dev@druid.apache.org";
export const DRUID_WEBSITE = 'http://druid.io';
export const DRUID_GITHUB = 'https://github.com/apache/druid';
export const DRUID_DOCS = 'http://druid.io/docs/latest';
export const DRUID_DOCS_SQL = 'http://druid.io/docs/latest/querying/sql.html';
export const DRUID_COMMUNITY = 'http://druid.io/community/';
export const DRUID_USER_GROUP = 'https://groups.google.com/forum/#!forum/druid-user';
export const DRUID_DEVELOPER_GROUP = 'https://lists.apache.org/list.html?dev@druid.apache.org';

View File

@ -16,16 +16,16 @@
* limitations under the License.
*/
import { Button, Intent, Switch } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons";
import { Button, Intent, Switch } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import axios from 'axios';
import * as React from 'react';
import ReactTable, { Filter } from "react-table";
import ReactTable, { Filter } from 'react-table';
import { RuleEditor } from '../components/rule-editor';
import { TableColumnSelection } from "../components/table-column-selection";
import { TableColumnSelection } from '../components/table-column-selection';
import { AsyncActionDialog } from '../dialogs/async-action-dialog';
import { CompactionDialog } from "../dialogs/compaction-dialog";
import { CompactionDialog } from '../dialogs/compaction-dialog';
import { RetentionDialog } from '../dialogs/retention-dialog';
import { AppToaster } from '../singletons/toaster';
import {
@ -38,11 +38,11 @@ import {
pluralIfNeeded,
queryDruidSql,
QueryManager, TableColumnSelectionHandler
} from "../utils";
} from '../utils';
import "./datasource-view.scss";
import './datasource-view.scss';
const tableColumns: string[] = ["Datasource", "Availability", "Retention", "Compaction", "Size", "Num rows", "Actions"];
const tableColumns: string[] = ['Datasource', 'Availability', 'Retention', 'Compaction', 'Size', 'Num rows', 'Actions'];
export interface DatasourcesViewProps extends React.Props<any> {
goToSql: (initSql: string) => void;
@ -252,8 +252,8 @@ GROUP BY 1`);
try {
await axios.post(`/druid/coordinator/v1/rules/${datasource}`, rules, {
headers: {
"X-Druid-Author": "console",
"X-Druid-Comment": comment
'X-Druid-Author': 'console',
'X-Druid-Comment': comment
}
});
} catch (e) {
@ -308,7 +308,7 @@ GROUP BY 1`);
message: `Are you sure you want to delete ${datasource}'s compaction?`,
intent: Intent.DANGER,
action: {
text: "Confirm",
text: 'Confirm',
onClick: async () => {
try {
await axios.delete(`/druid/coordinator/v1/config/compaction/${datasource}`);
@ -372,18 +372,18 @@ GROUP BY 1`);
}}
columns={[
{
Header: "Datasource",
accessor: "datasource",
Header: 'Datasource',
accessor: 'datasource',
width: 150,
Cell: row => {
const value = row.value;
return <a onClick={() => { this.setState({ datasourcesFilter: addFilter(datasourcesFilter, 'datasource', value) }); }}>{value}</a>;
},
show: tableColumnSelectionHandler.showColumn("Datasource")
show: tableColumnSelectionHandler.showColumn('Datasource')
},
{
Header: "Availability",
id: "availability",
Header: 'Availability',
id: 'availability',
filterable: false,
accessor: (row) => row.num_available_segments / row.num_segments,
Cell: (row) => {
@ -414,7 +414,7 @@ GROUP BY 1`);
}
},
show: tableColumnSelectionHandler.showColumn("Availability")
show: tableColumnSelectionHandler.showColumn('Availability')
},
{
Header: 'Retention',
@ -432,13 +432,13 @@ GROUP BY 1`);
return <span
onClick={() => this.setState({retentionDialogOpenOn: { datasource: row.original.datasource, rules: row.original.rules }})}
className={"clickable-cell"}
className="clickable-cell"
>
{text}&nbsp;
<a>&#x270E;</a>
</span>;
},
show: tableColumnSelectionHandler.showColumn("Retention")
show: tableColumnSelectionHandler.showColumn('Retention')
},
{
Header: 'Compaction',
@ -458,14 +458,14 @@ GROUP BY 1`);
text = 'None';
}
return <span
className={"clickable-cell"}
className="clickable-cell"
onClick={() => this.setState({compactionDialogOpenOn: compactionOpenOn})}
>
{text}&nbsp;
<a>&#x270E;</a>
</span>;
},
show: tableColumnSelectionHandler.showColumn("Compaction")
show: tableColumnSelectionHandler.showColumn('Compaction')
},
{
Header: 'Size',
@ -473,7 +473,7 @@ GROUP BY 1`);
filterable: false,
width: 100,
Cell: (row) => formatBytes(row.value),
show: tableColumnSelectionHandler.showColumn("Size")
show: tableColumnSelectionHandler.showColumn('Size')
},
{
Header: 'Num rows',
@ -481,7 +481,7 @@ GROUP BY 1`);
filterable: false,
width: 100,
Cell: (row) => formatNumber(row.value),
show: tableColumnSelectionHandler.showColumn("Num rows")
show: tableColumnSelectionHandler.showColumn('Num rows')
},
{
Header: 'Actions',
@ -503,7 +503,7 @@ GROUP BY 1`);
</div>;
}
},
show: tableColumnSelectionHandler.showColumn("Actions")
show: tableColumnSelectionHandler.showColumn('Actions')
}
]}
defaultPageSize={50}

View File

@ -16,8 +16,8 @@
* limitations under the License.
*/
import { Card, H5, Icon } from "@blueprintjs/core";
import { IconName, IconNames } from "@blueprintjs/icons";
import { Card, H5, Icon } from '@blueprintjs/core';
import { IconName, IconNames } from '@blueprintjs/icons';
import axios from 'axios';
import * as classNames from 'classnames';
import * as React from 'react';
@ -175,13 +175,13 @@ export class HomeView extends React.Component<HomeViewProps, HomeViewState> {
pendingTaskCount: 0
};
for (const dataStatus of taskCountsFromSql) {
if (dataStatus.status === "SUCCESS") {
if (dataStatus.status === 'SUCCESS') {
taskCounts.successTaskCount = dataStatus.count;
} else if (dataStatus.status === "FAILED") {
} else if (dataStatus.status === 'FAILED') {
taskCounts.failedTaskCount = dataStatus.count;
} else if (dataStatus.status === "RUNNING") {
} else if (dataStatus.status === 'RUNNING') {
taskCounts.runningTaskCount = dataStatus.count;
} else if (dataStatus.status === "WAITING") {
} else if (dataStatus.status === 'WAITING') {
taskCounts.waitingTaskCount = dataStatus.count;
} else {
taskCounts.pendingTaskCount = dataStatus.count;
@ -230,7 +230,7 @@ GROUP BY 1`);
this.middleManagerQueryManager = new QueryManager({
processQuery: async (query) => {
const middleManagerResp = await axios.get("/druid/indexer/v1/workers");
const middleManagerResp = await axios.get('/druid/indexer/v1/workers');
const middleManagerCount: number = middleManagerResp.data.length;
return middleManagerCount;
},
@ -269,36 +269,36 @@ GROUP BY 1`);
return <div className="home-view app-view">
{this.renderCard({
href: "/status",
href: '/status',
icon: IconNames.GRAPH,
title: "Status",
title: 'Status',
loading: state.statusLoading,
content: state.status ? `Apache Druid is running version ${state.status.version}` : '',
error: state.statusError
})}
{this.renderCard({
href: "#datasources",
href: '#datasources',
icon: IconNames.MULTI_SELECT,
title: "Datasources",
title: 'Datasources',
loading: state.datasourceCountLoading,
content: pluralIfNeeded(state.datasourceCount, 'datasource'),
error: state.datasourceCountError
})}
{this.renderCard({
href: "#segments",
href: '#segments',
icon: IconNames.STACKED_CHART,
title: "Segments",
title: 'Segments',
loading: state.segmentCountLoading,
content: pluralIfNeeded(state.segmentCount, 'segment'),
error: state.datasourceCountError
})}
{this.renderCard({
href: "#tasks",
href: '#tasks',
icon: IconNames.GANTT_CHART,
title: "Tasks",
title: 'Tasks',
loading: state.taskCountLoading,
content: <>
{Boolean(state.runningTaskCount) && <p>{pluralIfNeeded(state.runningTaskCount, 'running task')}</p>}
@ -314,9 +314,9 @@ GROUP BY 1`);
})}
{this.renderCard({
href: "#servers",
href: '#servers',
icon: IconNames.DATABASE,
title: "Data servers",
title: 'Data servers',
loading: state.dataServerCountLoading || state.middleManagerCountLoading,
content: <>
<p>{pluralIfNeeded(state.dataServerCount, 'historical')}</p>

View File

@ -16,26 +16,26 @@
* limitations under the License.
*/
import { Button, Intent } from "@blueprintjs/core";
import { Button, Intent } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import axios from 'axios';
import * as classNames from 'classnames';
import * as React from 'react';
import ReactTable from "react-table";
import ReactTable from 'react-table';
import { TableColumnSelection } from "../components/table-column-selection";
import { TableColumnSelection } from '../components/table-column-selection';
import { AsyncActionDialog } from '../dialogs/async-action-dialog';
import { LookupEditDialog } from "../dialogs/lookup-edit-dialog";
import { AppToaster } from "../singletons/toaster";
import { LookupEditDialog } from '../dialogs/lookup-edit-dialog';
import { AppToaster } from '../singletons/toaster';
import {
getDruidErrorMessage, LocalStorageKeys,
QueryManager,
TableColumnSelectionHandler
} from "../utils";
} from '../utils';
import "./lookups-view.scss";
import './lookups-view.scss';
const tableColumns: string[] = ["Lookup name", "Tier", "Type", "Version", "Actions"];
const tableColumns: string[] = ['Lookup name', 'Tier', 'Type', 'Version', 'Actions'];
export interface LookupsViewProps extends React.Props<any> {
@ -70,10 +70,10 @@ export class LookupsView extends React.Component<LookupsViewProps, LookupsViewSt
lookupsError: null,
lookupsUninitialized: false,
lookupEditDialogOpen: false,
lookupEditTier: "",
lookupEditName: "",
lookupEditVersion: "",
lookupEditSpec: "",
lookupEditTier: '',
lookupEditName: '',
lookupEditVersion: '',
lookupEditSpec: '',
isEdit: false,
allLookupTiers: [],
@ -92,7 +92,7 @@ export class LookupsView extends React.Component<LookupsViewProps, LookupsViewSt
const tiers = tiersResp.data;
const lookupEntries: {}[] = [];
const lookupResp = await axios.get("/druid/coordinator/v1/lookups/config/all");
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];
@ -117,7 +117,7 @@ export class LookupsView extends React.Component<LookupsViewProps, LookupsViewSt
}
});
this.lookupsGetQueryManager.runQuery("dummy");
this.lookupsGetQueryManager.runQuery('dummy');
}
componentWillUnmount(): void {
@ -146,12 +146,12 @@ export class LookupsView extends React.Component<LookupsViewProps, LookupsViewSt
const target: any = lookups.find((lookupEntry: any) => {
return lookupEntry.tier === tier && lookupEntry.id === id;
});
if (id === "") {
if (id === '') {
this.setState({
lookupEditName: "",
lookupEditName: '',
lookupEditTier: allLookupTiers[0],
lookupEditDialogOpen: true,
lookupEditSpec: "",
lookupEditSpec: '',
lookupEditVersion: (new Date()).toISOString(),
isEdit: false
});
@ -175,7 +175,7 @@ export class LookupsView extends React.Component<LookupsViewProps, LookupsViewSt
private async submitLookupEdit() {
const { lookupEditTier, lookupEditName, lookupEditSpec, lookupEditVersion, isEdit } = this.state;
let endpoint = "/druid/coordinator/v1/lookups/config";
let endpoint = '/druid/coordinator/v1/lookups/config';
const specJSON: any = JSON.parse(lookupEditSpec);
let dataJSON: any;
if (isEdit) {
@ -240,7 +240,7 @@ export class LookupsView extends React.Component<LookupsViewProps, LookupsViewSt
const { tableColumnSelectionHandler } = this;
if (lookupsUninitialized) {
return <div className={"init-div"}>
return <div className="init-div">
<Button
icon={IconNames.BUILD}
text="Initialize lookup"
@ -257,36 +257,36 @@ export class LookupsView extends React.Component<LookupsViewProps, LookupsViewSt
filterable
columns={[
{
Header: "Lookup name",
id: "lookup_name",
Header: 'Lookup name',
id: 'lookup_name',
accessor: (row: any) => row.id,
filterable: true,
show: tableColumnSelectionHandler.showColumn("Lookup name")
show: tableColumnSelectionHandler.showColumn('Lookup name')
},
{
Header: "Tier",
id: "tier",
Header: 'Tier',
id: 'tier',
accessor: (row: any) => row.tier,
filterable: true,
show: tableColumnSelectionHandler.showColumn("Tier")
show: tableColumnSelectionHandler.showColumn('Tier')
},
{
Header: "Type",
id: "type",
Header: 'Type',
id: 'type',
accessor: (row: any) => row.spec.type,
filterable: true,
show: tableColumnSelectionHandler.showColumn("Type")
show: tableColumnSelectionHandler.showColumn('Type')
},
{
Header: "Version",
id: "version",
Header: 'Version',
id: 'version',
accessor: (row: any) => row.version,
filterable: true,
show: tableColumnSelectionHandler.showColumn("Version")
show: tableColumnSelectionHandler.showColumn('Version')
},
{
Header: "Actions",
id: "actions",
Header: 'Actions',
id: 'actions',
accessor: row => ({id: row.id, tier: row.tier}),
filterable: false,
Cell: (row: any) => {
@ -298,7 +298,7 @@ export class LookupsView extends React.Component<LookupsViewProps, LookupsViewSt
<a onClick={() => this.setState({ deleteLookupTier: lookupTier, deleteLookupName: lookupId })}>Delete</a>
</div>;
},
show: tableColumnSelectionHandler.showColumn("Actions")
show: tableColumnSelectionHandler.showColumn('Actions')
}
]}
defaultPageSize={50}
@ -340,7 +340,7 @@ export class LookupsView extends React.Component<LookupsViewProps, LookupsViewSt
<Button
icon={IconNames.PLUS}
text="Add"
onClick={() => this.openLookupEditDialog("", "")}
onClick={() => this.openLookupEditDialog('', '')}
/>
}
<TableColumnSelection

View File

@ -16,17 +16,17 @@
* limitations under the License.
*/
import { Button, Intent } from "@blueprintjs/core";
import { H5 } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons";
import { Button, Intent } from '@blueprintjs/core';
import { H5 } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import axios from 'axios';
import * as classNames from 'classnames';
import * as React from 'react';
import ReactTable from "react-table";
import { Filter } from "react-table";
import ReactTable from 'react-table';
import { Filter } from 'react-table';
import { TableColumnSelection } from "../components/table-column-selection";
import { AppToaster } from "../singletons/toaster";
import { TableColumnSelection } from '../components/table-column-selection';
import { AppToaster } from '../singletons/toaster';
import {
addFilter,
formatBytes,
@ -35,12 +35,12 @@ import {
parseList,
queryDruidSql,
QueryManager, TableColumnSelectionHandler
} from "../utils";
} from '../utils';
import "./segments-view.scss";
import './segments-view.scss';
const tableColumns: string[] = ["Segment ID", "Datasource", "Start", "End", "Version", "Partition",
"Size", "Num rows", "Replicas", "Is published", "Is realtime", "Is available"];
const tableColumns: string[] = ['Segment ID', 'Datasource', 'Start', 'End', 'Version', 'Partition',
'Size', 'Num rows', 'Replicas', 'Is published', 'Is realtime', 'Is available'];
export interface SegmentsViewProps extends React.Props<any> {
goToSql: (initSql: string) => void;
@ -156,7 +156,7 @@ export class SegmentsView extends React.Component<SegmentsViewProps, SegmentsVie
manual
filterable
filtered={segmentFilter}
defaultSorted={[{id: "start", desc: true}]}
defaultSorted={[{id: 'start', desc: true}]}
onFilteredChange={(filtered, column) => {
this.setState({ segmentFilter: filtered });
}}
@ -165,100 +165,100 @@ export class SegmentsView extends React.Component<SegmentsViewProps, SegmentsVie
ofText=""
columns={[
{
Header: "Segment ID",
accessor: "segment_id",
Header: 'Segment ID',
accessor: 'segment_id',
width: 300,
show: tableColumnSelectionHandler.showColumn("Segment ID")
show: tableColumnSelectionHandler.showColumn('Segment ID')
},
{
Header: "Datasource",
accessor: "datasource",
Header: 'Datasource',
accessor: 'datasource',
Cell: row => {
const value = row.value;
return <a onClick={() => { this.setState({ segmentFilter: addFilter(segmentFilter, 'datasource', value) }); }}>{value}</a>;
},
show: tableColumnSelectionHandler.showColumn("Datasource")
show: tableColumnSelectionHandler.showColumn('Datasource')
},
{
Header: "Start",
accessor: "start",
Header: 'Start',
accessor: 'start',
width: 120,
defaultSortDesc: true,
Cell: row => {
const value = row.value;
return <a onClick={() => { this.setState({ segmentFilter: addFilter(segmentFilter, 'start', value) }); }}>{value}</a>;
},
show: tableColumnSelectionHandler.showColumn("Start")
show: tableColumnSelectionHandler.showColumn('Start')
},
{
Header: "End",
accessor: "end",
Header: 'End',
accessor: 'end',
defaultSortDesc: true,
width: 120,
Cell: row => {
const value = row.value;
return <a onClick={() => { this.setState({ segmentFilter: addFilter(segmentFilter, 'end', value) }); }}>{value}</a>;
},
show: tableColumnSelectionHandler.showColumn("End")
show: tableColumnSelectionHandler.showColumn('End')
},
{
Header: "Version",
accessor: "version",
Header: 'Version',
accessor: 'version',
defaultSortDesc: true,
width: 120,
show: tableColumnSelectionHandler.showColumn("Version")
show: tableColumnSelectionHandler.showColumn('Version')
},
{
Header: "Partition",
accessor: "partition_num",
Header: 'Partition',
accessor: 'partition_num',
width: 60,
filterable: false,
show: tableColumnSelectionHandler.showColumn("Partition")
show: tableColumnSelectionHandler.showColumn('Partition')
},
{
Header: "Size",
accessor: "size",
Header: 'Size',
accessor: 'size',
filterable: false,
defaultSortDesc: true,
Cell: row => formatBytes(row.value),
show: tableColumnSelectionHandler.showColumn("Size")
show: tableColumnSelectionHandler.showColumn('Size')
},
{
Header: "Num rows",
accessor: "num_rows",
Header: 'Num rows',
accessor: 'num_rows',
filterable: false,
defaultSortDesc: true,
Cell: row => formatNumber(row.value),
show: tableColumnSelectionHandler.showColumn("Num rows")
show: tableColumnSelectionHandler.showColumn('Num rows')
},
{
Header: "Replicas",
accessor: "num_replicas",
Header: 'Replicas',
accessor: 'num_replicas',
width: 60,
filterable: false,
defaultSortDesc: true,
show: tableColumnSelectionHandler.showColumn("Replicas")
show: tableColumnSelectionHandler.showColumn('Replicas')
},
{
Header: "Is published",
id: "is_published",
Header: 'Is published',
id: 'is_published',
accessor: (row) => String(Boolean(row.is_published)),
Filter: makeBooleanFilter(),
show: tableColumnSelectionHandler.showColumn("Is published")
show: tableColumnSelectionHandler.showColumn('Is published')
},
{
Header: "Is realtime",
id: "is_realtime",
Header: 'Is realtime',
id: 'is_realtime',
accessor: (row) => String(Boolean(row.is_realtime)),
Filter: makeBooleanFilter(),
show: tableColumnSelectionHandler.showColumn("Is realtime")
show: tableColumnSelectionHandler.showColumn('Is realtime')
},
{
Header: "Is available",
id: "is_available",
Header: 'Is available',
id: 'is_available',
accessor: (row) => String(Boolean(row.is_available)),
Filter: makeBooleanFilter(),
show: tableColumnSelectionHandler.showColumn("Is available")
show: tableColumnSelectionHandler.showColumn('Is available')
}
]}
defaultPageSize={50}

View File

@ -16,28 +16,28 @@
* limitations under the License.
*/
import { Button, Switch } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons";
import { Button, Switch } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import axios from 'axios';
import * as classNames from 'classnames';
import { sum } from "d3-array";
import { sum } from 'd3-array';
import * as React from 'react';
import ReactTable from "react-table";
import { Filter } from "react-table";
import ReactTable from 'react-table';
import { Filter } from 'react-table';
import { TableColumnSelection } from "../components/table-column-selection";
import { TableColumnSelection } from '../components/table-column-selection';
import {
addFilter,
formatBytes,
formatBytesCompact, LocalStorageKeys,
queryDruidSql,
QueryManager, TableColumnSelectionHandler
} from "../utils";
} from '../utils';
import "./servers-view.scss";
import './servers-view.scss';
const serverTableColumns: string[] = ["Server", "Tier", "Curr size", "Max size", "Usage", "Load/drop queues", "Host", "Port"];
const middleManagerTableColumns: string[] = ["Host", "Usage", "Availability groups", "Last completed task time", "Blacklisted until"];
const serverTableColumns: string[] = ['Server', 'Tier', 'Curr size', 'Max size', 'Usage', 'Load/drop queues', 'Host', 'Port'];
const middleManagerTableColumns: string[] = ['Host', 'Usage', 'Availability groups', 'Last completed task time', 'Blacklisted until'];
function formatQueues(segmentsToLoad: number, segmentsToLoadSize: number, segmentsToDrop: number, segmentsToDropSize: number): string {
const queueParts: string[] = [];
@ -104,7 +104,7 @@ export class ServersView extends React.Component<ServersViewProps, ServersViewSt
processQuery: async (query: string) => {
const servers = await queryDruidSql({ query });
const 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) => {
@ -131,7 +131,7 @@ WHERE "server_type" = 'historical'`);
this.middleManagerQueryManager = new QueryManager({
processQuery: async (query: string) => {
const resp = await axios.get("/druid/indexer/v1/workers");
const resp = await axios.get('/druid/indexer/v1/workers');
return resp.data;
},
onStateChange: ({ result, loading, error }) => {
@ -172,26 +172,26 @@ WHERE "server_type" = 'historical'`);
onFilteredChange={(filtered, column) => {
this.setState({ serverFilter: filtered });
}}
pivotBy={groupByTier ? ["tier"] : []}
pivotBy={groupByTier ? ['tier'] : []}
columns={[
{
Header: "Server",
accessor: "server",
Header: 'Server',
accessor: 'server',
width: 300,
Aggregated: row => '',
show: serverTableColumnSelectionHandler.showColumn("Server")
show: serverTableColumnSelectionHandler.showColumn('Server')
},
{
Header: "Tier",
accessor: "tier",
Header: 'Tier',
accessor: 'tier',
Cell: row => {
const value = row.value;
return <a onClick={() => { this.setState({ serverFilter: addFilter(serverFilter, 'tier', value) }); }}>{value}</a>;
},
show: serverTableColumnSelectionHandler.showColumn("Tier")
show: serverTableColumnSelectionHandler.showColumn('Tier')
},
{
Header: "Curr size",
Header: 'Curr size',
id: 'curr_size',
width: 100,
filterable: false,
@ -206,10 +206,10 @@ WHERE "server_type" = 'historical'`);
if (row.value === null) return '';
return formatBytes(row.value);
},
show: serverTableColumnSelectionHandler.showColumn("Curr size")
show: serverTableColumnSelectionHandler.showColumn('Curr size')
},
{
Header: "Max size",
Header: 'Max size',
id: 'max_size',
width: 100,
filterable: false,
@ -224,10 +224,10 @@ WHERE "server_type" = 'historical'`);
if (row.value === null) return '';
return formatBytes(row.value);
},
show: serverTableColumnSelectionHandler.showColumn("Max size")
show: serverTableColumnSelectionHandler.showColumn('Max size')
},
{
Header: "Usage",
Header: 'Usage',
id: 'usage',
width: 100,
filterable: false,
@ -243,10 +243,10 @@ WHERE "server_type" = 'historical'`);
if (row.value === null) return '';
return fillIndicator(row.value);
},
show: serverTableColumnSelectionHandler.showColumn("Usage")
show: serverTableColumnSelectionHandler.showColumn('Usage')
},
{
Header: "Load/drop queues",
Header: 'Load/drop queues',
id: 'queue',
width: 400,
filterable: false,
@ -264,16 +264,16 @@ WHERE "server_type" = 'historical'`);
const segmentsToDropSize = sum(originals, s => s.segmentsToDropSize);
return formatQueues(segmentsToLoad, segmentsToLoadSize, segmentsToDrop, segmentsToDropSize);
},
show: serverTableColumnSelectionHandler.showColumn("Load/drop queues")
show: serverTableColumnSelectionHandler.showColumn('Load/drop queues')
},
{
Header: "Host",
accessor: "host",
Header: 'Host',
accessor: 'host',
Aggregated: () => '',
show: serverTableColumnSelectionHandler.showColumn("Host")
show: serverTableColumnSelectionHandler.showColumn('Host')
},
{
Header: "Port",
Header: 'Port',
id: 'port',
accessor: (row) => {
const ports: string[] = [];
@ -286,7 +286,7 @@ WHERE "server_type" = 'historical'`);
return ports.join(', ') || 'No port';
},
Aggregated: () => '',
show: serverTableColumnSelectionHandler.showColumn("Port")
show: serverTableColumnSelectionHandler.showColumn('Port')
}
]}
defaultPageSize={10}
@ -310,47 +310,47 @@ WHERE "server_type" = 'historical'`);
}}
columns={[
{
Header: "Host",
id: "host",
Header: 'Host',
id: 'host',
accessor: (row) => row.worker.host,
Cell: row => {
const value = row.value;
return <a onClick={() => { this.setState({ middleManagerFilter: addFilter(middleManagerFilter, 'host', value) }); }}>{value}</a>;
},
show: middleManagerTableColumnSelectionHandler.showColumn("Host")
show: middleManagerTableColumnSelectionHandler.showColumn('Host')
},
{
Header: "Usage",
id: "usage",
Header: 'Usage',
id: 'usage',
width: 60,
accessor: (row) => `${row.currCapacityUsed} / ${row.worker.capacity}`,
filterable: false,
show: middleManagerTableColumnSelectionHandler.showColumn("Usage")
show: middleManagerTableColumnSelectionHandler.showColumn('Usage')
},
{
Header: "Availability groups",
id: "availabilityGroups",
Header: 'Availability groups',
id: 'availabilityGroups',
width: 60,
accessor: (row) => row.availabilityGroups.length,
filterable: false,
show: middleManagerTableColumnSelectionHandler.showColumn("Availability groups")
show: middleManagerTableColumnSelectionHandler.showColumn('Availability groups')
},
{
Header: "Last completed task time",
accessor: "lastCompletedTaskTime",
show: middleManagerTableColumnSelectionHandler.showColumn("Last completed task time")
Header: 'Last completed task time',
accessor: 'lastCompletedTaskTime',
show: middleManagerTableColumnSelectionHandler.showColumn('Last completed task time')
},
{
Header: "Blacklisted until",
accessor: "blacklistedUntil",
show: middleManagerTableColumnSelectionHandler.showColumn("Blacklisted until")
Header: 'Blacklisted until',
accessor: 'blacklistedUntil',
show: middleManagerTableColumnSelectionHandler.showColumn('Blacklisted until')
}
]}
defaultPageSize={10}
className="-striped -highlight"
SubComponent={rowInfo => {
const runningTasks = rowInfo.original.runningTasks;
return <div style={{ padding: "20px" }}>
return <div style={{ padding: '20px' }}>
{
runningTasks.length ?
<>

View File

@ -16,12 +16,12 @@
* limitations under the License.
*/
import * as Hjson from "hjson";
import * as Hjson from 'hjson';
import * as React from 'react';
import ReactTable from "react-table";
import ReactTable from 'react-table';
import { SqlControl } from '../components/sql-control';
import { QueryPlanDialog } from "../dialogs/query-plan-dialog";
import { QueryPlanDialog } from '../dialogs/query-plan-dialog';
import {
BasicQueryExplanation,
decodeRune,
@ -32,7 +32,7 @@ import {
queryDruidSql, QueryManager, SemiJoinQueryExplanation
} from '../utils';
import "./sql-view.scss";
import './sql-view.scss';
export interface SqlViewProps extends React.Props<any> {
initSql: string | null;
@ -77,7 +77,7 @@ export class SqlView extends React.Component<SqlViewProps, SqlViewState> {
} else {
const result = await queryDruidSql({
query,
resultFormat: "array",
resultFormat: 'array',
header: true
});
@ -101,9 +101,9 @@ export class SqlView extends React.Component<SqlViewProps, SqlViewState> {
const explainQuery = `explain plan for ${query}`;
const result = await queryDruidSql({
query: explainQuery,
resultFormat: "object"
resultFormat: 'object'
});
const data: BasicQueryExplanation | SemiJoinQueryExplanation | string = parseQueryPlan(result[0]["PLAN"]);
const data: BasicQueryExplanation | SemiJoinQueryExplanation | string = parseQueryPlan(result[0]['PLAN']);
return data;
},
onStateChange: ({ result, loading, error }) => {

View File

@ -16,17 +16,17 @@
* limitations under the License.
*/
import { Alert, Button, ButtonGroup, Intent, Label } from "@blueprintjs/core";
import { IconNames } from "@blueprintjs/icons";
import { Alert, Button, ButtonGroup, Intent, Label } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import axios from 'axios';
import * as classNames from 'classnames';
import * as React from 'react';
import ReactTable from "react-table";
import { Filter } from "react-table";
import ReactTable from 'react-table';
import { Filter } from 'react-table';
import { TableColumnSelection } from "../components/table-column-selection";
import { AsyncActionDialog } from "../dialogs/async-action-dialog";
import { SpecDialog } from "../dialogs/spec-dialog";
import { TableColumnSelection } from '../components/table-column-selection';
import { AsyncActionDialog } from '../dialogs/async-action-dialog';
import { SpecDialog } from '../dialogs/spec-dialog';
import { AppToaster } from '../singletons/toaster';
import {
addFilter,
@ -35,12 +35,12 @@ import {
getDruidErrorMessage, LocalStorageKeys,
queryDruidSql,
QueryManager, TableColumnSelectionHandler
} from "../utils";
} from '../utils';
import "./tasks-view.scss";
import './tasks-view.scss';
const supervisorTableColumns: string[] = ["Datasource", "Type", "Topic/Stream", "Status", "Actions"];
const taskTableColumns: string[] = ["Task ID", "Type", "Datasource", "Created time", "Status", "Duration", "Actions"];
const supervisorTableColumns: string[] = ['Datasource', 'Type', 'Topic/Stream', 'Status', 'Actions'];
const taskTableColumns: string[] = ['Task ID', 'Type', 'Datasource', 'Created time', 'Status', 'Duration', 'Actions'];
export interface TasksViewProps extends React.Props<any> {
taskId: string | null;
@ -126,7 +126,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 }) => {
@ -328,11 +328,11 @@ ORDER BY "rank" DESC, "created_time" DESC`);
filterable
columns={[
{
Header: "Datasource",
Header: 'Datasource',
id: 'datasource',
accessor: "id",
accessor: 'id',
width: 300,
show: supervisorTableColumnSelectionHandler.showColumn("Datasource")
show: supervisorTableColumnSelectionHandler.showColumn('Datasource')
},
{
Header: 'Type',
@ -344,7 +344,7 @@ ORDER BY "rank" DESC, "created_time" DESC`);
if (!tuningConfig) return '';
return tuningConfig.type;
},
show: supervisorTableColumnSelectionHandler.showColumn("Type")
show: supervisorTableColumnSelectionHandler.showColumn('Type')
},
{
Header: 'Topic/Stream',
@ -356,10 +356,10 @@ ORDER BY "rank" DESC, "created_time" DESC`);
if (!ioConfig) return '';
return ioConfig.topic || ioConfig.stream || '';
},
show: supervisorTableColumnSelectionHandler.showColumn("Topic/Stream")
show: supervisorTableColumnSelectionHandler.showColumn('Topic/Stream')
},
{
Header: "Status",
Header: 'Status',
id: 'status',
accessor: (row) => row.spec.suspended ? 'Suspended' : 'Running',
Cell: row => {
@ -373,7 +373,7 @@ ORDER BY "rank" DESC, "created_time" DESC`);
{value}
</span>;
},
show: supervisorTableColumnSelectionHandler.showColumn("Status")
show: supervisorTableColumnSelectionHandler.showColumn('Status')
},
{
Header: 'Actions',
@ -397,7 +397,7 @@ ORDER BY "rank" DESC, "created_time" DESC`);
<a onClick={() => this.setState({ terminateSupervisorId: id })}>Terminate</a>
</div>;
},
show: supervisorTableColumnSelectionHandler.showColumn("Actions")
show: supervisorTableColumnSelectionHandler.showColumn('Actions')
}
]}
defaultPageSize={10}
@ -452,44 +452,44 @@ ORDER BY "rank" DESC, "created_time" DESC`);
onFilteredChange={(filtered, column) => {
this.setState({ taskFilter: filtered });
}}
defaultSorted={[{id: "status", desc: true}]}
defaultSorted={[{id: 'status', desc: true}]}
pivotBy={groupTasksBy ? [groupTasksBy] : []}
columns={[
{
Header: "Task ID",
accessor: "task_id",
Header: 'Task ID',
accessor: 'task_id',
width: 300,
Aggregated: row => '',
show: taskTableColumnSelectionHandler.showColumn("Task ID")
show: taskTableColumnSelectionHandler.showColumn('Task ID')
},
{
Header: "Type",
accessor: "type",
Header: 'Type',
accessor: 'type',
Cell: row => {
const value = row.value;
return <a onClick={() => { this.setState({ taskFilter: addFilter(taskFilter, 'type', value) }); }}>{value}</a>;
},
show: taskTableColumnSelectionHandler.showColumn("Type")
show: taskTableColumnSelectionHandler.showColumn('Type')
},
{
Header: "Datasource",
accessor: "datasource",
Header: 'Datasource',
accessor: 'datasource',
Cell: row => {
const value = row.value;
return <a onClick={() => { this.setState({ taskFilter: addFilter(taskFilter, 'datasource', value) }); }}>{value}</a>;
},
show: taskTableColumnSelectionHandler.showColumn("Datasource")
show: taskTableColumnSelectionHandler.showColumn('Datasource')
},
{
Header: "Created time",
accessor: "created_time",
Header: 'Created time',
accessor: 'created_time',
width: 120,
Aggregated: row => '',
show: taskTableColumnSelectionHandler.showColumn("Created time")
show: taskTableColumnSelectionHandler.showColumn('Created time')
},
{
Header: "Status",
id: "status",
Header: 'Status',
id: 'status',
width: 110,
accessor: (row) => `${row.rank}_${row.created_time}_${row.status}`,
Cell: row => {
@ -519,15 +519,15 @@ ORDER BY "rank" DESC, "created_time" DESC`);
const previewCount = countBy(previewValues);
return <span>{Object.keys(previewCount).sort().map(v => `${v} (${previewCount[v]})`).join(', ')}</span>;
},
show: taskTableColumnSelectionHandler.showColumn("Status")
show: taskTableColumnSelectionHandler.showColumn('Status')
},
{
Header: "Duration",
accessor: "duration",
Header: 'Duration',
accessor: 'duration',
filterable: false,
Cell: (row) => row.value > 0 ? formatDuration(row.value) : '',
Aggregated: () => '',
show: taskTableColumnSelectionHandler.showColumn("Duration")
show: taskTableColumnSelectionHandler.showColumn('Duration')
},
{
Header: 'Actions',
@ -549,7 +549,7 @@ ORDER BY "rank" DESC, "created_time" DESC`);
</div>;
},
Aggregated: row => '',
show: taskTableColumnSelectionHandler.showColumn("Actions")
show: taskTableColumnSelectionHandler.showColumn('Actions')
}
]}
defaultPageSize={20}

View File

@ -1,125 +1,18 @@
{
"extends": [
"tslint:recommended",
"tslint-react"
],
"extends": "awesome-code-style/tslint.json",
"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
"no-conditional-assignment": true,
"no-string-literal": false,
"object-literal-shorthand": false,
"no-require-imports": false,
"arrow-return-shorthand": false,
"no-var-requires": false,
"no-unused-variable": false
},
"linterOptions": {
"format": "useful"
}
}