mirror of https://github.com/apache/druid.git
Web console: Data loader user feedback changes (#8770)
* init fixes * cleaning styling issues * more conversion types
This commit is contained in:
parent
3e9723e3ce
commit
a95e3d438e
|
@ -5,7 +5,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
||||||
class="auto-form"
|
class="auto-form"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="bp3-form-group"
|
class="bp3-form-group form-group-with-info"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="bp3-label"
|
class="bp3-label"
|
||||||
|
@ -90,7 +90,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="bp3-form-group"
|
class="bp3-form-group form-group-with-info"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="bp3-label"
|
class="bp3-label"
|
||||||
|
@ -175,7 +175,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="bp3-form-group"
|
class="bp3-form-group form-group-with-info"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="bp3-label"
|
class="bp3-label"
|
||||||
|
@ -202,7 +202,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="bp3-form-group"
|
class="bp3-form-group form-group-with-info"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="bp3-label"
|
class="bp3-label"
|
||||||
|
@ -243,7 +243,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="bp3-form-group"
|
class="bp3-form-group form-group-with-info"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="bp3-label"
|
class="bp3-label"
|
||||||
|
@ -284,7 +284,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="bp3-form-group"
|
class="bp3-form-group form-group-with-info"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="bp3-label"
|
class="bp3-label"
|
||||||
|
@ -304,7 +304,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="bp3-form-group"
|
class="bp3-form-group form-group-with-info"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="bp3-label"
|
class="bp3-label"
|
||||||
|
@ -410,7 +410,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="bp3-form-group"
|
class="bp3-form-group form-group-with-info"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="bp3-label"
|
class="bp3-label"
|
||||||
|
|
|
@ -16,20 +16,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { Button, ButtonGroup, FormGroup, Intent, NumericInput } from '@blueprintjs/core';
|
||||||
Button,
|
|
||||||
ButtonGroup,
|
|
||||||
FormGroup,
|
|
||||||
Icon,
|
|
||||||
Intent,
|
|
||||||
NumericInput,
|
|
||||||
Popover,
|
|
||||||
} from '@blueprintjs/core';
|
|
||||||
import { IconNames } from '@blueprintjs/icons';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { deepDelete, deepGet, deepSet } from '../../utils/object-change';
|
import { deepDelete, deepGet, deepSet } from '../../utils/object-change';
|
||||||
import { ArrayInput } from '../array-input/array-input';
|
import { ArrayInput } from '../array-input/array-input';
|
||||||
|
import { FormGroupWithInfo } from '../form-group-with-info/form-group-with-info';
|
||||||
import { JsonInput } from '../json-input/json-input';
|
import { JsonInput } from '../json-input/json-input';
|
||||||
import { SuggestibleInput, SuggestionGroup } from '../suggestible-input/suggestible-input';
|
import { SuggestibleInput, SuggestionGroup } from '../suggestible-input/suggestible-input';
|
||||||
|
|
||||||
|
@ -326,22 +318,13 @@ export class AutoForm<T extends Record<string, any>> extends React.PureComponent
|
||||||
|
|
||||||
const label = field.label || AutoForm.makeLabelName(field.name);
|
const label = field.label || AutoForm.makeLabelName(field.name);
|
||||||
return (
|
return (
|
||||||
<FormGroup
|
<FormGroupWithInfo
|
||||||
key={field.name}
|
key={field.name}
|
||||||
label={label}
|
label={label}
|
||||||
labelInfo={
|
info={field.info ? <div className="label-info-text">{field.info}</div> : undefined}
|
||||||
field.info && (
|
|
||||||
<Popover
|
|
||||||
content={<div className="label-info-text">{field.info}</div>}
|
|
||||||
position="left-bottom"
|
|
||||||
>
|
|
||||||
<Icon icon={IconNames.INFO_SIGN} iconSize={14} />
|
|
||||||
</Popover>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{this.renderFieldInput(field)}
|
{this.renderFieldInput(field)}
|
||||||
</FormGroup>
|
</FormGroupWithInfo>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`form group with info matches snapshot 1`] = `
|
||||||
|
<div
|
||||||
|
class="bp3-form-group form-group-with-info"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="bp3-label"
|
||||||
|
>
|
||||||
|
Goodies
|
||||||
|
|
||||||
|
<span
|
||||||
|
class="bp3-text-muted"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="bp3-popover-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="bp3-popover-target"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="bp3-icon bp3-icon-info-sign"
|
||||||
|
icon="info-sign"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
data-icon="info-sign"
|
||||||
|
height="14"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
width="14"
|
||||||
|
>
|
||||||
|
<desc>
|
||||||
|
info-sign
|
||||||
|
</desc>
|
||||||
|
<path
|
||||||
|
d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zM7 3h2v2H7V3zm3 10H6v-1h1V7H6V6h3v6h1v1z"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="bp3-form-content"
|
||||||
|
>
|
||||||
|
Some buttons and stuff
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.form-group-with-info {
|
||||||
|
.bp3-form-content {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
& > .bp3-popover-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { FormGroupWithInfo } from './form-group-with-info';
|
||||||
|
|
||||||
|
describe('form group with info', () => {
|
||||||
|
it('matches snapshot', () => {
|
||||||
|
const formGroupWithInfo = (
|
||||||
|
<FormGroupWithInfo label="Goodies" info={<div>Information is gold</div>}>
|
||||||
|
Some buttons and stuff
|
||||||
|
</FormGroupWithInfo>
|
||||||
|
);
|
||||||
|
|
||||||
|
const { container } = render(formGroupWithInfo);
|
||||||
|
expect(container.firstChild).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { FormGroup, Icon, Popover } from '@blueprintjs/core';
|
||||||
|
import { IconNames } from '@blueprintjs/icons';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import './form-group-with-info.scss';
|
||||||
|
|
||||||
|
export interface FormGroupWithInfoProps {
|
||||||
|
label?: React.ReactNode;
|
||||||
|
info?: JSX.Element | string;
|
||||||
|
inlineInfo?: boolean;
|
||||||
|
children?: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FormGroupWithInfo = React.memo(function FormGroupWithInfo(
|
||||||
|
props: FormGroupWithInfoProps,
|
||||||
|
) {
|
||||||
|
const { label, info, inlineInfo, children } = props;
|
||||||
|
|
||||||
|
const popover = (
|
||||||
|
<Popover content={info} position="left-bottom">
|
||||||
|
<Icon icon={IconNames.INFO_SIGN} iconSize={14} />
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormGroup
|
||||||
|
className="form-group-with-info"
|
||||||
|
label={label}
|
||||||
|
labelInfo={info && !inlineInfo && popover}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
{info && inlineInfo && popover}
|
||||||
|
</FormGroup>
|
||||||
|
);
|
||||||
|
});
|
|
@ -171,7 +171,7 @@ exports[`header bar matches snapshot 1`] = `
|
||||||
/>
|
/>
|
||||||
<Blueprint3.MenuItem
|
<Blueprint3.MenuItem
|
||||||
disabled={false}
|
disabled={false}
|
||||||
href="https://druid.apache.org/docs/latest"
|
href="https://druid.apache.org/docs/0.16.0-incubating"
|
||||||
icon="th"
|
icon="th"
|
||||||
multiline={false}
|
multiline={false}
|
||||||
popoverProps={Object {}}
|
popoverProps={Object {}}
|
||||||
|
|
|
@ -55,7 +55,7 @@ exports[`compaction dialog matches snapshot 1`] = `
|
||||||
class="auto-form"
|
class="auto-form"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="bp3-form-group"
|
class="bp3-form-group form-group-with-info"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="bp3-label"
|
class="bp3-label"
|
||||||
|
@ -168,7 +168,7 @@ exports[`compaction dialog matches snapshot 1`] = `
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="bp3-form-group"
|
class="bp3-form-group form-group-with-info"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="bp3-label"
|
class="bp3-label"
|
||||||
|
@ -223,7 +223,7 @@ exports[`compaction dialog matches snapshot 1`] = `
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="bp3-form-group"
|
class="bp3-form-group form-group-with-info"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="bp3-label"
|
class="bp3-label"
|
||||||
|
@ -336,7 +336,7 @@ exports[`compaction dialog matches snapshot 1`] = `
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="bp3-form-group"
|
class="bp3-form-group form-group-with-info"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="bp3-label"
|
class="bp3-label"
|
||||||
|
@ -470,7 +470,7 @@ exports[`compaction dialog matches snapshot 1`] = `
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="bp3-form-group"
|
class="bp3-form-group form-group-with-info"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="bp3-label"
|
class="bp3-label"
|
||||||
|
@ -583,7 +583,7 @@ exports[`compaction dialog matches snapshot 1`] = `
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="bp3-form-group"
|
class="bp3-form-group form-group-with-info"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="bp3-label"
|
class="bp3-label"
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { Button, Classes, Dialog, Intent } from '@blueprintjs/core';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { AutoForm, ExternalLink } from '../../components';
|
import { AutoForm, ExternalLink } from '../../components';
|
||||||
|
import { DRUID_DOCS_VERSION } from '../../variables';
|
||||||
|
|
||||||
import './compaction-dialog.scss';
|
import './compaction-dialog.scss';
|
||||||
|
|
||||||
|
@ -125,7 +126,9 @@ export class CompactionDialog extends React.PureComponent<
|
||||||
type: 'json',
|
type: 'json',
|
||||||
info: (
|
info: (
|
||||||
<p>
|
<p>
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/ingestion/tasks.html#task-context">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/tasks.html#task-context`}
|
||||||
|
>
|
||||||
Task context
|
Task context
|
||||||
</ExternalLink>{' '}
|
</ExternalLink>{' '}
|
||||||
for compaction tasks.
|
for compaction tasks.
|
||||||
|
@ -143,7 +146,9 @@ export class CompactionDialog extends React.PureComponent<
|
||||||
type: 'json',
|
type: 'json',
|
||||||
info: (
|
info: (
|
||||||
<p>
|
<p>
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/configuration/index.html#compact-task-tuningconfig">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/configuration/index.html#compact-task-tuningconfig`}
|
||||||
|
>
|
||||||
Tuning config
|
Tuning config
|
||||||
</ExternalLink>{' '}
|
</ExternalLink>{' '}
|
||||||
for compaction tasks.
|
for compaction tasks.
|
||||||
|
|
|
@ -58,7 +58,7 @@ exports[`coordinator dynamic config matches snapshot 1`] = `
|
||||||
Edit the coordinator dynamic configuration on the fly. For more information please refer to the
|
Edit the coordinator dynamic configuration on the fly. For more information please refer to the
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href="https://druid.apache.org/docs/latest/configuration/index.html#dynamic-configuration"
|
href="https://druid.apache.org/docs/0.16.0-incubating/configuration/index.html#dynamic-configuration"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
|
|
|
@ -24,6 +24,7 @@ import React from 'react';
|
||||||
import { AutoForm, ExternalLink } from '../../components';
|
import { AutoForm, ExternalLink } from '../../components';
|
||||||
import { AppToaster } from '../../singletons/toaster';
|
import { AppToaster } from '../../singletons/toaster';
|
||||||
import { getDruidErrorMessage, QueryManager } from '../../utils';
|
import { getDruidErrorMessage, QueryManager } from '../../utils';
|
||||||
|
import { DRUID_DOCS_VERSION } from '../../variables';
|
||||||
import { SnitchDialog } from '../snitch-dialog/snitch-dialog';
|
import { SnitchDialog } from '../snitch-dialog/snitch-dialog';
|
||||||
|
|
||||||
import './coordinator-dynamic-config-dialog.scss';
|
import './coordinator-dynamic-config-dialog.scss';
|
||||||
|
@ -126,7 +127,9 @@ export class CoordinatorDynamicConfigDialog extends React.PureComponent<
|
||||||
<p>
|
<p>
|
||||||
Edit the coordinator dynamic configuration on the fly. For more information please refer
|
Edit the coordinator dynamic configuration on the fly. For more information please refer
|
||||||
to the{' '}
|
to the{' '}
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/configuration/index.html#dynamic-configuration">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/configuration/index.html#dynamic-configuration`}
|
||||||
|
>
|
||||||
documentation
|
documentation
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
.
|
.
|
||||||
|
|
|
@ -19,7 +19,7 @@ exports[`history dialog matches snapshot 1`] = `
|
||||||
class="bp3-dialog history-dialog"
|
class="bp3-dialog history-dialog"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="history-record-container"
|
class="bp3-dialog-body history-record-container"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="history-dialog-title"
|
class="history-dialog-title"
|
||||||
|
@ -125,6 +125,13 @@ exports[`history dialog matches snapshot 1`] = `
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="bp3-dialog-footer"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="bp3-dialog-footer-actions"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Card, Dialog, Divider } from '@blueprintjs/core';
|
import { Card, Classes, Dialog, Divider } from '@blueprintjs/core';
|
||||||
|
import classNames from 'classnames';
|
||||||
import React, { ReactNode } from 'react';
|
import React, { ReactNode } from 'react';
|
||||||
|
|
||||||
import { JsonCollapse } from '../../components';
|
import { JsonCollapse } from '../../components';
|
||||||
|
@ -25,54 +26,50 @@ import './history-dialog.scss';
|
||||||
|
|
||||||
interface HistoryDialogProps {
|
interface HistoryDialogProps {
|
||||||
historyRecords: any[];
|
historyRecords: any[];
|
||||||
children?: ReactNode;
|
buttons?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const HistoryDialog = React.memo(function HistoryDialog(props: HistoryDialogProps) {
|
export const HistoryDialog = React.memo(function HistoryDialog(props: HistoryDialogProps) {
|
||||||
function renderRecords() {
|
const { buttons, historyRecords } = props;
|
||||||
const { children, historyRecords } = props;
|
|
||||||
let content;
|
|
||||||
if (historyRecords.length === 0) {
|
|
||||||
content = <div className="no-record">No history records available</div>;
|
|
||||||
} else {
|
|
||||||
content = (
|
|
||||||
<>
|
|
||||||
<span className="history-dialog-title">History</span>
|
|
||||||
<div className="history-record-entries">
|
|
||||||
{historyRecords.map((record, i) => {
|
|
||||||
const auditInfo = record.auditInfo;
|
|
||||||
const auditTime = record.auditTime;
|
|
||||||
const formattedTime = auditTime.replace('T', ' ').substring(0, auditTime.length - 5);
|
|
||||||
|
|
||||||
return (
|
let content;
|
||||||
<div key={i} className="history-record-entry">
|
if (historyRecords.length === 0) {
|
||||||
<Card>
|
content = <div className="no-record">No history records available</div>;
|
||||||
<div className="history-record-title">
|
} else {
|
||||||
<span className="history-record-title-change">Change</span>
|
content = (
|
||||||
<span>{formattedTime}</span>
|
<>
|
||||||
</div>
|
<span className="history-dialog-title">History</span>
|
||||||
<Divider />
|
<div className="history-record-entries">
|
||||||
<p>{auditInfo.comment === '' ? '(No comment)' : auditInfo.comment}</p>
|
{historyRecords.map((record, i) => {
|
||||||
<JsonCollapse stringValue={record.payload} buttonText="Payload" />
|
const auditInfo = record.auditInfo;
|
||||||
</Card>
|
const auditTime = record.auditTime;
|
||||||
</div>
|
const formattedTime = auditTime.replace('T', ' ').substring(0, auditTime.length - 5);
|
||||||
);
|
|
||||||
})}
|
return (
|
||||||
</div>
|
<div key={i} className="history-record-entry">
|
||||||
</>
|
<Card>
|
||||||
);
|
<div className="history-record-title">
|
||||||
}
|
<span className="history-record-title-change">Change</span>
|
||||||
return (
|
<span>{formattedTime}</span>
|
||||||
<div className="history-record-container">
|
</div>
|
||||||
{content}
|
<Divider />
|
||||||
{children}
|
<p>{auditInfo.comment === '' ? '(No comment)' : auditInfo.comment}</p>
|
||||||
</div>
|
<JsonCollapse stringValue={record.payload} buttonText="Payload" />
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog className="history-dialog" isOpen {...props}>
|
<Dialog className="history-dialog" isOpen {...props}>
|
||||||
{renderRecords()}
|
<div className={classNames(Classes.DIALOG_BODY, 'history-record-container')}>{content}</div>
|
||||||
|
<div className={Classes.DIALOG_FOOTER}>
|
||||||
|
<div className={Classes.DIALOG_FOOTER_ACTIONS}>{buttons}</div>
|
||||||
|
</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -58,7 +58,7 @@ exports[`overload dynamic config matches snapshot 1`] = `
|
||||||
Edit the overlord dynamic configuration on the fly. For more information please refer to the
|
Edit the overlord dynamic configuration on the fly. For more information please refer to the
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href="https://druid.apache.org/docs/latest/configuration/index.html#overlord-dynamic-configuration"
|
href="https://druid.apache.org/docs/0.16.0-incubating/configuration/index.html#overlord-dynamic-configuration"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
|
|
|
@ -24,6 +24,7 @@ import React from 'react';
|
||||||
import { AutoForm, ExternalLink } from '../../components';
|
import { AutoForm, ExternalLink } from '../../components';
|
||||||
import { AppToaster } from '../../singletons/toaster';
|
import { AppToaster } from '../../singletons/toaster';
|
||||||
import { getDruidErrorMessage, QueryManager } from '../../utils';
|
import { getDruidErrorMessage, QueryManager } from '../../utils';
|
||||||
|
import { DRUID_DOCS_VERSION } from '../../variables';
|
||||||
import { SnitchDialog } from '../snitch-dialog/snitch-dialog';
|
import { SnitchDialog } from '../snitch-dialog/snitch-dialog';
|
||||||
|
|
||||||
import './overlord-dynamic-config-dialog.scss';
|
import './overlord-dynamic-config-dialog.scss';
|
||||||
|
@ -129,7 +130,9 @@ export class OverlordDynamicConfigDialog extends React.PureComponent<
|
||||||
<p>
|
<p>
|
||||||
Edit the overlord dynamic configuration on the fly. For more information please refer to
|
Edit the overlord dynamic configuration on the fly. For more information please refer to
|
||||||
the{' '}
|
the{' '}
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/configuration/index.html#overlord-dynamic-configuration">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/configuration/index.html#overlord-dynamic-configuration`}
|
||||||
|
>
|
||||||
documentation
|
documentation
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
.
|
.
|
||||||
|
|
|
@ -58,7 +58,7 @@ exports[`retention dialog matches snapshot 1`] = `
|
||||||
Druid uses rules to determine what data should be retained in the cluster. The rules are evaluated in order from top to bottom. For more information please refer to the
|
Druid uses rules to determine what data should be retained in the cluster. The rules are evaluated in order from top to bottom. For more information please refer to the
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href="https://druid.apache.org/docs/latest/operations/rule-configuration.html"
|
href="https://druid.apache.org/docs/0.16.0-incubating/operations/rule-configuration.html"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
documentation
|
documentation
|
||||||
|
|
|
@ -23,6 +23,7 @@ import React from 'react';
|
||||||
|
|
||||||
import { RuleEditor } from '../../components';
|
import { RuleEditor } from '../../components';
|
||||||
import { QueryManager } from '../../utils';
|
import { QueryManager } from '../../utils';
|
||||||
|
import { DRUID_DOCS_VERSION } from '../../variables';
|
||||||
import { SnitchDialog } from '../snitch-dialog/snitch-dialog';
|
import { SnitchDialog } from '../snitch-dialog/snitch-dialog';
|
||||||
|
|
||||||
import './retention-dialog.scss';
|
import './retention-dialog.scss';
|
||||||
|
@ -183,7 +184,7 @@ export class RetentionDialog extends React.PureComponent<
|
||||||
Druid uses rules to determine what data should be retained in the cluster. The rules are
|
Druid uses rules to determine what data should be retained in the cluster. The rules are
|
||||||
evaluated in order from top to bottom. For more information please refer to the{' '}
|
evaluated in order from top to bottom. For more information please refer to the{' '}
|
||||||
<a
|
<a
|
||||||
href="https://druid.apache.org/docs/latest/operations/rule-configuration.html"
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/operations/rule-configuration.html`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
documentation
|
documentation
|
||||||
|
|
|
@ -116,13 +116,15 @@ export class SnitchDialog extends React.PureComponent<SnitchDialogProps, SnitchD
|
||||||
if (!historyRecords) return null;
|
if (!historyRecords) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HistoryDialog {...this.props} historyRecords={historyRecords}>
|
<HistoryDialog
|
||||||
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
{...this.props}
|
||||||
|
historyRecords={historyRecords}
|
||||||
|
buttons={
|
||||||
<Button onClick={this.back} icon={IconNames.ARROW_LEFT}>
|
<Button onClick={this.back} icon={IconNames.ARROW_LEFT}>
|
||||||
Back
|
Back
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
}
|
||||||
</HistoryDialog>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,17 +62,3 @@ svg {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.bp3-form-group {
|
|
||||||
.bp3-form-content {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
& > .bp3-popover-wrapper {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 7px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some SplitterLayout globals
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import React from 'react';
|
||||||
|
|
||||||
import { Field } from '../components/auto-form/auto-form';
|
import { Field } from '../components/auto-form/auto-form';
|
||||||
import { ExternalLink } from '../components/external-link/external-link';
|
import { ExternalLink } from '../components/external-link/external-link';
|
||||||
|
import { DRUID_DOCS_VERSION } from '../variables';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BASIC_TIME_FORMATS,
|
BASIC_TIME_FORMATS,
|
||||||
|
@ -162,13 +163,13 @@ export function getIngestionDocLink(spec: IngestionSpec): string {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'kafka':
|
case 'kafka':
|
||||||
return 'https://druid.apache.org/docs/latest/development/extensions-core/kafka-ingestion.html';
|
return `https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/development/extensions-core/kafka-ingestion.html`;
|
||||||
|
|
||||||
case 'kinesis':
|
case 'kinesis':
|
||||||
return 'https://druid.apache.org/docs/latest/development/extensions-core/kinesis-ingestion.html';
|
return `https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/development/extensions-core/kinesis-ingestion.html`;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 'https://druid.apache.org/docs/latest/ingestion/native-batch.html#firehoses';
|
return `https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/native-batch.html#firehoses`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +307,9 @@ const PARSE_SPEC_FORM_FIELDS: Field<ParseSpec>[] = [
|
||||||
<p>The parser used to parse the data.</p>
|
<p>The parser used to parse the data.</p>
|
||||||
<p>
|
<p>
|
||||||
For more information see{' '}
|
For more information see{' '}
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/ingestion/data-formats.html">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/data-formats.html`}
|
||||||
|
>
|
||||||
the documentation
|
the documentation
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
.
|
.
|
||||||
|
@ -573,7 +576,9 @@ const FLATTEN_FIELD_FORM_FIELDS: Field<FlattenField>[] = [
|
||||||
info: (
|
info: (
|
||||||
<>
|
<>
|
||||||
Specify a flatten{' '}
|
Specify a flatten{' '}
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/ingestion/flatten-json">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/flatten-json`}
|
||||||
|
>
|
||||||
expression
|
expression
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
.
|
.
|
||||||
|
@ -618,7 +623,9 @@ const TRANSFORM_FORM_FIELDS: Field<Transform>[] = [
|
||||||
info: (
|
info: (
|
||||||
<>
|
<>
|
||||||
A valid Druid{' '}
|
A valid Druid{' '}
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/misc/math-expr.html">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/misc/math-expr.html`}
|
||||||
|
>
|
||||||
expression
|
expression
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
.
|
.
|
||||||
|
@ -820,7 +827,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
||||||
info: (
|
info: (
|
||||||
<p>
|
<p>
|
||||||
Druid connects to raw data through{' '}
|
Druid connects to raw data through{' '}
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/ingestion/firehose.html">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/firehose.html`}
|
||||||
|
>
|
||||||
firehoses
|
firehoses
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
. You can change your selected firehose here.
|
. You can change your selected firehose here.
|
||||||
|
@ -873,7 +882,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
||||||
required: true,
|
required: true,
|
||||||
info: (
|
info: (
|
||||||
<>
|
<>
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/ingestion/firehose.html#localfirehose">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/firehose.html#localfirehose`}
|
||||||
|
>
|
||||||
firehose.baseDir
|
firehose.baseDir
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
<p>Specifies the directory to search recursively for files to be ingested.</p>
|
<p>Specifies the directory to search recursively for files to be ingested.</p>
|
||||||
|
@ -888,7 +899,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
||||||
suggestions: ['*', '*.json', '*.json.gz', '*.csv', '*.tsv'],
|
suggestions: ['*', '*.json', '*.json.gz', '*.csv', '*.tsv'],
|
||||||
info: (
|
info: (
|
||||||
<>
|
<>
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/ingestion/firehose.html#localfirehose">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/firehose.html#localfirehose`}
|
||||||
|
>
|
||||||
firehose.filter
|
firehose.filter
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
<p>
|
<p>
|
||||||
|
@ -963,7 +976,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
||||||
info: (
|
info: (
|
||||||
<p>
|
<p>
|
||||||
The{' '}
|
The{' '}
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/querying/filters.html">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/querying/filters.html`}
|
||||||
|
>
|
||||||
filter
|
filter
|
||||||
</ExternalLink>{' '}
|
</ExternalLink>{' '}
|
||||||
to apply to the data as part of querying.
|
to apply to the data as part of querying.
|
||||||
|
@ -1026,7 +1041,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
||||||
<>
|
<>
|
||||||
<p>
|
<p>
|
||||||
JSON array of{' '}
|
JSON array of{' '}
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/development/extensions-contrib/google.html">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/development/extensions-contrib/google.html`}
|
||||||
|
>
|
||||||
Google Blobs
|
Google Blobs
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
.
|
.
|
||||||
|
@ -1057,7 +1074,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
||||||
required: true,
|
required: true,
|
||||||
info: (
|
info: (
|
||||||
<>
|
<>
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/development/extensions-core/kafka-ingestion#kafkasupervisorioconfig">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/development/extensions-core/kafka-ingestion#kafkasupervisorioconfig`}
|
||||||
|
>
|
||||||
consumerProperties
|
consumerProperties
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
<p>
|
<p>
|
||||||
|
@ -1079,7 +1098,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
||||||
defaultValue: {},
|
defaultValue: {},
|
||||||
info: (
|
info: (
|
||||||
<>
|
<>
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/development/extensions-core/kafka-ingestion#kafkasupervisorioconfig">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/development/extensions-core/kafka-ingestion#kafkasupervisorioconfig`}
|
||||||
|
>
|
||||||
consumerProperties
|
consumerProperties
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
<p>A map of properties to be passed to the Kafka consumer.</p>
|
<p>A map of properties to be passed to the Kafka consumer.</p>
|
||||||
|
@ -1129,7 +1150,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
||||||
info: (
|
info: (
|
||||||
<>
|
<>
|
||||||
The Amazon Kinesis stream endpoint for a region. You can find a list of endpoints{' '}
|
The Amazon Kinesis stream endpoint for a region. You can find a list of endpoints{' '}
|
||||||
<ExternalLink href="http://docs.aws.amazon.com/general/latest/gr/rande.html#ak_region">
|
<ExternalLink
|
||||||
|
href={`http://docs.aws.amazon.com/general/${DRUID_DOCS_VERSION}/gr/rande.html#ak_region`}
|
||||||
|
>
|
||||||
here
|
here
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
.
|
.
|
||||||
|
|
|
@ -19,13 +19,16 @@
|
||||||
export const LEGACY_COORDINATOR_CONSOLE = '/index.html';
|
export const LEGACY_COORDINATOR_CONSOLE = '/index.html';
|
||||||
export const LEGACY_OVERLORD_CONSOLE = '/console.html';
|
export const LEGACY_OVERLORD_CONSOLE = '/console.html';
|
||||||
|
|
||||||
|
// This is set to the latest available version and should be updated to the next version before release
|
||||||
|
export const DRUID_DOCS_VERSION = '0.16.0-incubating';
|
||||||
|
|
||||||
export const DRUID_WEBSITE = 'https://druid.apache.org';
|
export const DRUID_WEBSITE = 'https://druid.apache.org';
|
||||||
export const DRUID_GITHUB = 'https://github.com/apache/druid';
|
export const DRUID_GITHUB = 'https://github.com/apache/druid';
|
||||||
export const DRUID_DOCS = 'https://druid.apache.org/docs/latest';
|
export const DRUID_DOCS = `https://druid.apache.org/docs/${DRUID_DOCS_VERSION}`;
|
||||||
export const DRUID_DOCS_SQL = 'https://druid.apache.org/docs/latest/querying/sql.html';
|
export const DRUID_DOCS_SQL = `https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/querying/sql.html`;
|
||||||
export const DRUID_DOCS_RUNE = 'https://druid.apache.org/docs/latest/querying/querying.html';
|
export const DRUID_DOCS_RUNE = `https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/querying/querying.html`;
|
||||||
export const DRUID_COMMUNITY = 'https://druid.apache.org/community/';
|
export const DRUID_COMMUNITY = 'https://druid.apache.org/community/';
|
||||||
export const DRUID_USER_GROUP = 'https://groups.google.com/forum/#!forum/druid-user';
|
export const DRUID_USER_GROUP = 'https://groups.google.com/forum/#!forum/druid-user';
|
||||||
export const DRUID_ASF_SLACK = 'https://druid.apache.org/community/join-slack';
|
export const DRUID_ASF_SLACK = 'https://druid.apache.org/community/join-slack';
|
||||||
export const DRUID_DEVELOPER_GROUP = 'https://lists.apache.org/list.html?dev@druid.apache.org';
|
export const DRUID_DEVELOPER_GROUP = 'https://lists.apache.org/list.html?dev@druid.apache.org';
|
||||||
export const DRUID_DOCS_API = 'https://druid.apache.org/docs/latest/operations/api-reference.html';
|
export const DRUID_DOCS_API = `https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/operations/api-reference.html`;
|
||||||
|
|
|
@ -5,7 +5,7 @@ exports[`learn more matches snapshot 1`] = `
|
||||||
class="learn-more"
|
class="learn-more"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
href="https://druid.apache.org/docs/latest/development/extensions-core/kinesis-ingestion.html"
|
href="https://druid.apache.org/docs"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
|
|
|
@ -23,9 +23,7 @@ import { LearnMore } from './learn-more';
|
||||||
|
|
||||||
describe('learn more', () => {
|
describe('learn more', () => {
|
||||||
it('matches snapshot', () => {
|
it('matches snapshot', () => {
|
||||||
const learnMore = (
|
const learnMore = <LearnMore href={`https://druid.apache.org/docs`} />;
|
||||||
<LearnMore href="https://druid.apache.org/docs/latest/development/extensions-core/kinesis-ingestion.html" />
|
|
||||||
);
|
|
||||||
|
|
||||||
const { container } = render(learnMore);
|
const { container } = render(learnMore);
|
||||||
expect(container.firstChild).toMatchSnapshot();
|
expect(container.firstChild).toMatchSnapshot();
|
||||||
|
|
|
@ -88,7 +88,7 @@
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
content: '';
|
content: '';
|
||||||
border: 2px solid #48aff0;
|
border: 2px solid #008adc;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
content: '';
|
content: '';
|
||||||
border: 2px solid #ff5d10;
|
border: 2px solid #008adc;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.used {
|
&.used {
|
||||||
background: rgba(24, 201, 201, 0.5);
|
background: rgba(99, 129, 137, 0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.used {
|
&.used {
|
||||||
background: rgba(24, 201, 201, 0.15);
|
background: rgba(99, 129, 137, 0.15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,12 +243,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.apply-button-bar {
|
|
||||||
.revert {
|
|
||||||
margin-left: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.next-bar {
|
.next-bar {
|
||||||
grid-area: next;
|
grid-area: next;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
@ -268,19 +262,19 @@
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.control-buttons {
|
.control-buttons {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.bp3-button {
|
.bp3-button {
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cancel {
|
.right {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,8 @@ import {
|
||||||
Icon,
|
Icon,
|
||||||
IconName,
|
IconName,
|
||||||
Intent,
|
Intent,
|
||||||
|
Menu,
|
||||||
|
MenuItem,
|
||||||
Popover,
|
Popover,
|
||||||
Switch,
|
Switch,
|
||||||
TextArea,
|
TextArea,
|
||||||
|
@ -49,6 +51,7 @@ import {
|
||||||
JsonInput,
|
JsonInput,
|
||||||
Loader,
|
Loader,
|
||||||
} from '../../components';
|
} from '../../components';
|
||||||
|
import { FormGroupWithInfo } from '../../components/form-group-with-info/form-group-with-info';
|
||||||
import { AsyncActionDialog } from '../../dialogs';
|
import { AsyncActionDialog } from '../../dialogs';
|
||||||
import { AppToaster } from '../../singletons/toaster';
|
import { AppToaster } from '../../singletons/toaster';
|
||||||
import { UrlBaser } from '../../singletons/url-baser';
|
import { UrlBaser } from '../../singletons/url-baser';
|
||||||
|
@ -140,6 +143,7 @@ import {
|
||||||
SampleStrategy,
|
SampleStrategy,
|
||||||
} from '../../utils/sampler';
|
} from '../../utils/sampler';
|
||||||
import { computeFlattenPathsForData } from '../../utils/spec-utils';
|
import { computeFlattenPathsForData } from '../../utils/spec-utils';
|
||||||
|
import { DRUID_DOCS_VERSION } from '../../variables';
|
||||||
|
|
||||||
import { ExamplePicker } from './example-picker/example-picker';
|
import { ExamplePicker } from './example-picker/example-picker';
|
||||||
import { FilterTable, filterTableSelectedColumnName } from './filter-table/filter-table';
|
import { FilterTable, filterTableSelectedColumnName } from './filter-table/filter-table';
|
||||||
|
@ -555,7 +559,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
const previewSpecSame = this.isPreviewSpecSame();
|
const previewSpecSame = this.isPreviewSpecSame();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormGroup className="apply-button-bar">
|
<FormGroup className="control-buttons">
|
||||||
<Button
|
<Button
|
||||||
text="Apply"
|
text="Apply"
|
||||||
disabled={previewSpecSame}
|
disabled={previewSpecSame}
|
||||||
|
@ -564,8 +568,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
/>
|
/>
|
||||||
{!previewSpecSame && (
|
{!previewSpecSame && (
|
||||||
<Button
|
<Button
|
||||||
className="revert"
|
text="Cancel"
|
||||||
icon={IconNames.UNDO}
|
|
||||||
disabled={this.isPreviewSpecSame()}
|
disabled={this.isPreviewSpecSame()}
|
||||||
onClick={this.revertPreviewSpec}
|
onClick={this.revertPreviewSpec}
|
||||||
/>
|
/>
|
||||||
|
@ -791,7 +794,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
return (
|
return (
|
||||||
<p>
|
<p>
|
||||||
If you do not see your source of raw data here, you can try to ingest it by submitting a{' '}
|
If you do not see your source of raw data here, you can try to ingest it by submitting a{' '}
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/ingestion/index.html">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/index.html`}
|
||||||
|
>
|
||||||
JSON task or supervisor spec
|
JSON task or supervisor spec
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
.
|
.
|
||||||
|
@ -893,7 +898,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
For more information please refer to the{' '}
|
For more information please refer to the{' '}
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/operations/including-extensions">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/operations/including-extensions`}
|
||||||
|
>
|
||||||
documentation on loading extensions
|
documentation on loading extensions
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
.
|
.
|
||||||
|
@ -1029,7 +1036,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
<Callout className="intro">
|
<Callout className="intro">
|
||||||
<p>
|
<p>
|
||||||
Druid ingests raw data and converts it into a custom,{' '}
|
Druid ingests raw data and converts it into a custom,{' '}
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/design/segments.html">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/design/segments.html`}
|
||||||
|
>
|
||||||
indexed format
|
indexed format
|
||||||
</ExternalLink>{' '}
|
</ExternalLink>{' '}
|
||||||
that is optimized for analytic queries.
|
that is optimized for analytic queries.
|
||||||
|
@ -1264,7 +1273,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
{canFlatten && (
|
{canFlatten && (
|
||||||
<p>
|
<p>
|
||||||
If you have nested data, you can{' '}
|
If you have nested data, you can{' '}
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/ingestion/index.html#flattenspec">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/index.html#flattenspec`}
|
||||||
|
>
|
||||||
flatten
|
flatten
|
||||||
</ExternalLink>{' '}
|
</ExternalLink>{' '}
|
||||||
it here. If the provided flattening capabilities are not sufficient, please
|
it here. If the provided flattening capabilities are not sufficient, please
|
||||||
|
@ -1272,7 +1283,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
<p>Ensure that your data appears correctly in a row/column orientation.</p>
|
<p>Ensure that your data appears correctly in a row/column orientation.</p>
|
||||||
<LearnMore href="https://druid.apache.org/docs/latest/ingestion/data-formats.html" />
|
<LearnMore
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/data-formats.html`}
|
||||||
|
/>
|
||||||
</Callout>
|
</Callout>
|
||||||
{!selectedFlattenField && (
|
{!selectedFlattenField && (
|
||||||
<>
|
<>
|
||||||
|
@ -1362,8 +1375,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
/>
|
/>
|
||||||
<div className="control-buttons">
|
<div className="control-buttons">
|
||||||
<Button
|
<Button
|
||||||
className="add-update"
|
text="Apply"
|
||||||
text={selectedFlattenFieldIndex === -1 ? 'Add' : 'Update'}
|
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
this.updateSpec(
|
this.updateSpec(
|
||||||
|
@ -1376,8 +1388,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
close();
|
close();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Button text="Cancel" onClick={close} />
|
||||||
{selectedFlattenFieldIndex !== -1 && (
|
{selectedFlattenFieldIndex !== -1 && (
|
||||||
<Button
|
<Button
|
||||||
|
className="right"
|
||||||
icon={IconNames.TRASH}
|
icon={IconNames.TRASH}
|
||||||
intent={Intent.DANGER}
|
intent={Intent.DANGER}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -1391,7 +1405,6 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Button className="cancel" text="Cancel" onClick={close} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1409,7 +1422,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
/>
|
/>
|
||||||
<AnchorButton
|
<AnchorButton
|
||||||
icon={IconNames.INFO_SIGN}
|
icon={IconNames.INFO_SIGN}
|
||||||
href="https://druid.apache.org/docs/latest/ingestion/flatten-json.html"
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/flatten-json.html`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
minimal
|
minimal
|
||||||
/>
|
/>
|
||||||
|
@ -1529,7 +1542,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
column. If you do not have any time columns, you can choose "Constant value" to create
|
column. If you do not have any time columns, you can choose "Constant value" to create
|
||||||
a default one.
|
a default one.
|
||||||
</p>
|
</p>
|
||||||
<LearnMore href="https://druid.apache.org/docs/latest/ingestion/index.html#timestampspec" />
|
<LearnMore
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/index.html#timestampspec`}
|
||||||
|
/>
|
||||||
</Callout>
|
</Callout>
|
||||||
<FormGroup label="Timestamp spec">
|
<FormGroup label="Timestamp spec">
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
|
@ -1692,12 +1707,16 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
<p className="optional">Optional</p>
|
<p className="optional">Optional</p>
|
||||||
<p>
|
<p>
|
||||||
Druid can perform per-row{' '}
|
Druid can perform per-row{' '}
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/ingestion/transform-spec.html#transforms">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/transform-spec.html#transforms`}
|
||||||
|
>
|
||||||
transforms
|
transforms
|
||||||
</ExternalLink>{' '}
|
</ExternalLink>{' '}
|
||||||
of column values allowing you to create new derived columns or alter existing column.
|
of column values allowing you to create new derived columns or alter existing column.
|
||||||
</p>
|
</p>
|
||||||
<LearnMore href="https://druid.apache.org/docs/latest/ingestion/index.html#transforms" />
|
<LearnMore
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/index.html#transforms`}
|
||||||
|
/>
|
||||||
</Callout>
|
</Callout>
|
||||||
{Boolean(transformQueryState.error && transforms.length) && (
|
{Boolean(transformQueryState.error && transforms.length) && (
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
|
@ -1758,8 +1777,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
/>
|
/>
|
||||||
<div className="control-buttons">
|
<div className="control-buttons">
|
||||||
<Button
|
<Button
|
||||||
className="add-update"
|
text="Apply"
|
||||||
text={selectedTransformIndex === -1 ? 'Add' : 'Update'}
|
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
this.updateSpec(
|
this.updateSpec(
|
||||||
|
@ -1772,8 +1790,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
close();
|
close();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Button text="Cancel" onClick={close} />
|
||||||
{selectedTransformIndex !== -1 && (
|
{selectedTransformIndex !== -1 && (
|
||||||
<Button
|
<Button
|
||||||
|
className="right"
|
||||||
icon={IconNames.TRASH}
|
icon={IconNames.TRASH}
|
||||||
intent={Intent.DANGER}
|
intent={Intent.DANGER}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -1787,7 +1807,6 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Button className="cancel" text="Cancel" onClick={close} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1935,12 +1954,16 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
<p className="optional">Optional</p>
|
<p className="optional">Optional</p>
|
||||||
<p>
|
<p>
|
||||||
Druid can{' '}
|
Druid can{' '}
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/querying/filters.html">
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/querying/filters.html`}
|
||||||
|
>
|
||||||
filter
|
filter
|
||||||
</ExternalLink>{' '}
|
</ExternalLink>{' '}
|
||||||
out unwanted data by applying per-row filters.
|
out unwanted data by applying per-row filters.
|
||||||
</p>
|
</p>
|
||||||
<LearnMore href="https://druid.apache.org/docs/latest/ingestion/index.html#filter" />
|
<LearnMore
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/index.html#filter`}
|
||||||
|
/>
|
||||||
</Callout>
|
</Callout>
|
||||||
{!showGlobalFilter && this.renderColumnFilterControls()}
|
{!showGlobalFilter && this.renderColumnFilterControls()}
|
||||||
{!selectedFilter && this.renderGlobalFilterControls()}
|
{!selectedFilter && this.renderGlobalFilterControls()}
|
||||||
|
@ -1982,8 +2005,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
/>
|
/>
|
||||||
<div className="control-buttons">
|
<div className="control-buttons">
|
||||||
<Button
|
<Button
|
||||||
className="add-update"
|
text="Apply"
|
||||||
text={selectedFilterIndex === -1 ? 'Add' : 'Update'}
|
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const curFilter = splitFilter(deepGet(spec, 'dataSchema.transformSpec.filter'));
|
const curFilter = splitFilter(deepGet(spec, 'dataSchema.transformSpec.filter'));
|
||||||
|
@ -1994,8 +2016,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
close();
|
close();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Button text="Cancel" onClick={close} />
|
||||||
{selectedFilterIndex !== -1 && (
|
{selectedFilterIndex !== -1 && (
|
||||||
<Button
|
<Button
|
||||||
|
className="right"
|
||||||
icon={IconNames.TRASH}
|
icon={IconNames.TRASH}
|
||||||
intent={Intent.DANGER}
|
intent={Intent.DANGER}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -2008,7 +2032,6 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Button className="cancel" text="Cancel" onClick={close} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -2068,17 +2091,8 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<div className="control-buttons">
|
<div className="control-buttons">
|
||||||
<Button
|
<Button text="Apply" intent={Intent.PRIMARY} onClick={() => this.queryForFilter()} />
|
||||||
className="add-update"
|
<Button text="Cancel" onClick={() => this.setState({ showGlobalFilter: false })} />
|
||||||
text="Apply"
|
|
||||||
intent={Intent.PRIMARY}
|
|
||||||
onClick={() => this.queryForFilter()}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
className="cancel"
|
|
||||||
text="Close"
|
|
||||||
onClick={() => this.setState({ showGlobalFilter: false })}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -2205,11 +2219,36 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
want to change the type, click on the column header.
|
want to change the type, click on the column header.
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
<LearnMore href="https://druid.apache.org/docs/latest/ingestion/schema-design.html" />
|
<LearnMore
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/schema-design.html`}
|
||||||
|
/>
|
||||||
</Callout>
|
</Callout>
|
||||||
{!somethingSelected && (
|
{!somethingSelected && (
|
||||||
<>
|
<>
|
||||||
<FormGroup>
|
<FormGroupWithInfo
|
||||||
|
inlineInfo
|
||||||
|
info={
|
||||||
|
<div className="label-info-text">
|
||||||
|
<p>
|
||||||
|
Select whether or not you want to set an explicit list of{' '}
|
||||||
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/ingestion-spec.html#dimensionsspec`}
|
||||||
|
>
|
||||||
|
dimensions
|
||||||
|
</ExternalLink>{' '}
|
||||||
|
and{' '}
|
||||||
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/querying/aggregations.html`}
|
||||||
|
>
|
||||||
|
metrics
|
||||||
|
</ExternalLink>
|
||||||
|
. Explicitly setting dimensions and metrics can lead to better compression and
|
||||||
|
performance. If you disable this option, Druid will try to auto-detect fields
|
||||||
|
in your data and treat them as individual columns.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Switch
|
<Switch
|
||||||
checked={dimensionMode === 'specific'}
|
checked={dimensionMode === 'specific'}
|
||||||
onChange={() =>
|
onChange={() =>
|
||||||
|
@ -2219,29 +2258,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
}
|
}
|
||||||
label="Explicitly specify dimension list"
|
label="Explicitly specify dimension list"
|
||||||
/>
|
/>
|
||||||
<Popover
|
</FormGroupWithInfo>
|
||||||
content={
|
|
||||||
<div className="label-info-text">
|
|
||||||
<p>
|
|
||||||
Select whether or not you want to set an explicit list of{' '}
|
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/ingestion/ingestion-spec.html#dimensionsspec">
|
|
||||||
dimensions
|
|
||||||
</ExternalLink>{' '}
|
|
||||||
and{' '}
|
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/querying/aggregations.html">
|
|
||||||
metrics
|
|
||||||
</ExternalLink>
|
|
||||||
. Explicitly setting dimensions and metrics can lead to better compression
|
|
||||||
and performance. If you disable this option, Druid will try to auto-detect
|
|
||||||
fields in your data and treat them as individual columns.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
position="left-bottom"
|
|
||||||
>
|
|
||||||
<Icon icon={IconNames.INFO_SIGN} iconSize={14} />
|
|
||||||
</Popover>
|
|
||||||
</FormGroup>
|
|
||||||
{dimensionMode === 'auto-detect' && (
|
{dimensionMode === 'auto-detect' && (
|
||||||
<AutoForm
|
<AutoForm
|
||||||
fields={[
|
fields={[
|
||||||
|
@ -2261,43 +2278,45 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
onChange={s => this.updateSpec(s)}
|
onChange={s => this.updateSpec(s)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<FormGroup>
|
<FormGroupWithInfo
|
||||||
|
inlineInfo
|
||||||
|
info={
|
||||||
|
<div className="label-info-text">
|
||||||
|
<p>
|
||||||
|
If you enable{' '}
|
||||||
|
<ExternalLink
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/tutorials/tutorial-rollup.html`}
|
||||||
|
>
|
||||||
|
roll-up
|
||||||
|
</ExternalLink>
|
||||||
|
, Druid will try to pre-aggregate data before indexing it to conserve storage.
|
||||||
|
The primary timestamp will be truncated to the specified query granularity,
|
||||||
|
and rows containing the same string field values will be aggregated together.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you enable rollup, you must specify which columns are{' '}
|
||||||
|
<a
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/ingestion-spec.html#dimensionsspec`}
|
||||||
|
>
|
||||||
|
dimensions
|
||||||
|
</a>{' '}
|
||||||
|
(fields you want to group and filter on), and which are{' '}
|
||||||
|
<a
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/querying/aggregations.html`}
|
||||||
|
>
|
||||||
|
metrics
|
||||||
|
</a>{' '}
|
||||||
|
(fields you want to aggregate on).
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Switch
|
<Switch
|
||||||
checked={rollup}
|
checked={rollup}
|
||||||
onChange={() => this.setState({ newRollup: !rollup })}
|
onChange={() => this.setState({ newRollup: !rollup })}
|
||||||
labelElement="Rollup"
|
labelElement="Rollup"
|
||||||
/>
|
/>
|
||||||
<Popover
|
</FormGroupWithInfo>
|
||||||
content={
|
|
||||||
<div className="label-info-text">
|
|
||||||
<p>
|
|
||||||
If you enable{' '}
|
|
||||||
<ExternalLink href="https://druid.apache.org/docs/latest/tutorials/tutorial-rollup.html">
|
|
||||||
roll-up
|
|
||||||
</ExternalLink>
|
|
||||||
, Druid will try to pre-aggregate data before indexing it to conserve
|
|
||||||
storage. The primary timestamp will be truncated to the specified query
|
|
||||||
granularity, and rows containing the same string field values will be
|
|
||||||
aggregated together.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
If you enable rollup, you must specify which columns are{' '}
|
|
||||||
<a href="https://druid.apache.org/docs/latest/ingestion/ingestion-spec.html#dimensionsspec">
|
|
||||||
dimensions
|
|
||||||
</a>{' '}
|
|
||||||
(fields you want to group and filter on), and which are{' '}
|
|
||||||
<a href="https://druid.apache.org/docs/latest/querying/aggregations.html">
|
|
||||||
metrics
|
|
||||||
</a>{' '}
|
|
||||||
(fields you want to aggregate on).
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
position="left-bottom"
|
|
||||||
>
|
|
||||||
<Icon icon={IconNames.INFO_SIGN} iconSize={14} />
|
|
||||||
</Popover>
|
|
||||||
</FormGroup>
|
|
||||||
<AutoForm
|
<AutoForm
|
||||||
fields={[
|
fields={[
|
||||||
{
|
{
|
||||||
|
@ -2425,6 +2444,33 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
const curDimensions =
|
const curDimensions =
|
||||||
deepGet(spec, `dataSchema.parser.parseSpec.dimensionsSpec.dimensions`) || EMPTY_ARRAY;
|
deepGet(spec, `dataSchema.parser.parseSpec.dimensionsSpec.dimensions`) || EMPTY_ARRAY;
|
||||||
|
|
||||||
|
const convertToMetricMenu = (
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text="Convert to hyperUnique metric"
|
||||||
|
onClick={() => {
|
||||||
|
const specWithoutDimension = deepDelete(
|
||||||
|
spec,
|
||||||
|
`dataSchema.parser.parseSpec.dimensionsSpec.dimensions.${selectedDimensionSpecIndex}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const specWithMetric = deepSet(
|
||||||
|
specWithoutDimension,
|
||||||
|
`dataSchema.metricsSpec.[append]`,
|
||||||
|
{
|
||||||
|
name: `unique_${selectedDimensionSpec.name}`,
|
||||||
|
type: 'hyperUnique',
|
||||||
|
fieldName: selectedDimensionSpec.name,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
this.updateSpec(specWithMetric);
|
||||||
|
close();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="edit-controls">
|
<div className="edit-controls">
|
||||||
<AutoForm
|
<AutoForm
|
||||||
|
@ -2432,10 +2478,20 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
model={selectedDimensionSpec}
|
model={selectedDimensionSpec}
|
||||||
onChange={selectedDimensionSpec => this.setState({ selectedDimensionSpec })}
|
onChange={selectedDimensionSpec => this.setState({ selectedDimensionSpec })}
|
||||||
/>
|
/>
|
||||||
|
{selectedDimensionSpecIndex !== -1 && deepGet(spec, 'dataSchema.metricsSpec') && (
|
||||||
|
<FormGroup>
|
||||||
|
<Popover content={convertToMetricMenu}>
|
||||||
|
<Button
|
||||||
|
icon={IconNames.EXCHANGE}
|
||||||
|
text="Convert to metric..."
|
||||||
|
disabled={curDimensions.length <= 1}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
</FormGroup>
|
||||||
|
)}
|
||||||
<div className="control-buttons">
|
<div className="control-buttons">
|
||||||
<Button
|
<Button
|
||||||
className="add-update"
|
text="Apply"
|
||||||
text={selectedDimensionSpecIndex === -1 ? 'Add' : 'Update'}
|
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
this.updateSpec(
|
this.updateSpec(
|
||||||
|
@ -2448,8 +2504,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
close();
|
close();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Button text="Cancel" onClick={close} />
|
||||||
{selectedDimensionSpecIndex !== -1 && (
|
{selectedDimensionSpecIndex !== -1 && (
|
||||||
<Button
|
<Button
|
||||||
|
className="right"
|
||||||
icon={IconNames.TRASH}
|
icon={IconNames.TRASH}
|
||||||
intent={Intent.DANGER}
|
intent={Intent.DANGER}
|
||||||
disabled={curDimensions.length <= 1}
|
disabled={curDimensions.length <= 1}
|
||||||
|
@ -2466,7 +2524,6 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Button className="cancel" text="Cancel" onClick={close} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -2502,6 +2559,39 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
};
|
};
|
||||||
|
|
||||||
if (selectedMetricSpec) {
|
if (selectedMetricSpec) {
|
||||||
|
const convertToDimension = (type: string) => {
|
||||||
|
const specWithoutMetric = deepDelete(
|
||||||
|
spec,
|
||||||
|
`dataSchema.metricsSpec.${selectedMetricSpecIndex}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const specWithDimension = deepSet(
|
||||||
|
specWithoutMetric,
|
||||||
|
`dataSchema.parser.parseSpec.dimensionsSpec.dimensions.[append]`,
|
||||||
|
{
|
||||||
|
type,
|
||||||
|
name: selectedMetricSpec.fieldName,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
this.updateSpec(specWithDimension);
|
||||||
|
close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertToDimensionMenu = (
|
||||||
|
<Menu>
|
||||||
|
<MenuItem
|
||||||
|
text="Convert to STRING dimension"
|
||||||
|
onClick={() => convertToDimension('STRING')}
|
||||||
|
/>
|
||||||
|
<MenuItem text="Convert to LONG dimension" onClick={() => convertToDimension('LONG')} />
|
||||||
|
<MenuItem
|
||||||
|
text="Convert to DOUBLE dimension"
|
||||||
|
onClick={() => convertToDimension('DOUBLE')}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="edit-controls">
|
<div className="edit-controls">
|
||||||
<AutoForm
|
<AutoForm
|
||||||
|
@ -2509,10 +2599,16 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
model={selectedMetricSpec}
|
model={selectedMetricSpec}
|
||||||
onChange={selectedMetricSpec => this.setState({ selectedMetricSpec })}
|
onChange={selectedMetricSpec => this.setState({ selectedMetricSpec })}
|
||||||
/>
|
/>
|
||||||
|
{selectedMetricSpecIndex !== -1 && (
|
||||||
|
<FormGroup>
|
||||||
|
<Popover content={convertToDimensionMenu}>
|
||||||
|
<Button icon={IconNames.EXCHANGE} text="Convert to dimension..." />
|
||||||
|
</Popover>
|
||||||
|
</FormGroup>
|
||||||
|
)}
|
||||||
<div className="control-buttons">
|
<div className="control-buttons">
|
||||||
<Button
|
<Button
|
||||||
className="add-update"
|
text="Apply"
|
||||||
text={selectedMetricSpecIndex === -1 ? 'Add' : 'Update'}
|
|
||||||
intent={Intent.PRIMARY}
|
intent={Intent.PRIMARY}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
this.updateSpec(
|
this.updateSpec(
|
||||||
|
@ -2525,8 +2621,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
close();
|
close();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Button text="Cancel" onClick={close} />
|
||||||
{selectedMetricSpecIndex !== -1 && (
|
{selectedMetricSpecIndex !== -1 && (
|
||||||
<Button
|
<Button
|
||||||
|
className="right"
|
||||||
icon={IconNames.TRASH}
|
icon={IconNames.TRASH}
|
||||||
intent={Intent.DANGER}
|
intent={Intent.DANGER}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -2537,7 +2635,6 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Button className="cancel" text="Cancel" onClick={close} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -2633,7 +2730,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
<Callout className="intro">
|
<Callout className="intro">
|
||||||
<p className="optional">Optional</p>
|
<p className="optional">Optional</p>
|
||||||
<p>Configure how Druid will partition data.</p>
|
<p>Configure how Druid will partition data.</p>
|
||||||
<LearnMore href="https://druid.apache.org/docs/latest/ingestion/index.html#partitioning" />
|
<LearnMore
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/index.html#partitioning`}
|
||||||
|
/>
|
||||||
</Callout>
|
</Callout>
|
||||||
{this.renderParallelPickerIfNeeded()}
|
{this.renderParallelPickerIfNeeded()}
|
||||||
</div>
|
</div>
|
||||||
|
@ -2698,7 +2797,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
<Callout className="intro">
|
<Callout className="intro">
|
||||||
<p className="optional">Optional</p>
|
<p className="optional">Optional</p>
|
||||||
<p>Fine tune how Druid will ingest data.</p>
|
<p>Fine tune how Druid will ingest data.</p>
|
||||||
<LearnMore href="https://druid.apache.org/docs/latest/ingestion/index.html#tuningconfig" />
|
<LearnMore
|
||||||
|
href={`https://druid.apache.org/docs/${DRUID_DOCS_VERSION}/ingestion/index.html#tuningconfig`}
|
||||||
|
/>
|
||||||
</Callout>
|
</Callout>
|
||||||
{this.renderParallelPickerIfNeeded()}
|
{this.renderParallelPickerIfNeeded()}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue