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"
|
||||
>
|
||||
<div
|
||||
class="bp3-form-group"
|
||||
class="bp3-form-group form-group-with-info"
|
||||
>
|
||||
<label
|
||||
class="bp3-label"
|
||||
|
@ -90,7 +90,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bp3-form-group"
|
||||
class="bp3-form-group form-group-with-info"
|
||||
>
|
||||
<label
|
||||
class="bp3-label"
|
||||
|
@ -175,7 +175,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bp3-form-group"
|
||||
class="bp3-form-group form-group-with-info"
|
||||
>
|
||||
<label
|
||||
class="bp3-label"
|
||||
|
@ -202,7 +202,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bp3-form-group"
|
||||
class="bp3-form-group form-group-with-info"
|
||||
>
|
||||
<label
|
||||
class="bp3-label"
|
||||
|
@ -243,7 +243,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bp3-form-group"
|
||||
class="bp3-form-group form-group-with-info"
|
||||
>
|
||||
<label
|
||||
class="bp3-label"
|
||||
|
@ -284,7 +284,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bp3-form-group"
|
||||
class="bp3-form-group form-group-with-info"
|
||||
>
|
||||
<label
|
||||
class="bp3-label"
|
||||
|
@ -304,7 +304,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bp3-form-group"
|
||||
class="bp3-form-group form-group-with-info"
|
||||
>
|
||||
<label
|
||||
class="bp3-label"
|
||||
|
@ -410,7 +410,7 @@ exports[`auto-form snapshot matches snapshot 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bp3-form-group"
|
||||
class="bp3-form-group form-group-with-info"
|
||||
>
|
||||
<label
|
||||
class="bp3-label"
|
||||
|
|
|
@ -16,20 +16,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
FormGroup,
|
||||
Icon,
|
||||
Intent,
|
||||
NumericInput,
|
||||
Popover,
|
||||
} from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { Button, ButtonGroup, FormGroup, Intent, NumericInput } from '@blueprintjs/core';
|
||||
import React from 'react';
|
||||
|
||||
import { deepDelete, deepGet, deepSet } from '../../utils/object-change';
|
||||
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 { 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);
|
||||
return (
|
||||
<FormGroup
|
||||
<FormGroupWithInfo
|
||||
key={field.name}
|
||||
label={label}
|
||||
labelInfo={
|
||||
field.info && (
|
||||
<Popover
|
||||
content={<div className="label-info-text">{field.info}</div>}
|
||||
position="left-bottom"
|
||||
>
|
||||
<Icon icon={IconNames.INFO_SIGN} iconSize={14} />
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
info={field.info ? <div className="label-info-text">{field.info}</div> : undefined}
|
||||
>
|
||||
{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
|
||||
disabled={false}
|
||||
href="https://druid.apache.org/docs/latest"
|
||||
href="https://druid.apache.org/docs/0.16.0-incubating"
|
||||
icon="th"
|
||||
multiline={false}
|
||||
popoverProps={Object {}}
|
||||
|
|
|
@ -55,7 +55,7 @@ exports[`compaction dialog matches snapshot 1`] = `
|
|||
class="auto-form"
|
||||
>
|
||||
<div
|
||||
class="bp3-form-group"
|
||||
class="bp3-form-group form-group-with-info"
|
||||
>
|
||||
<label
|
||||
class="bp3-label"
|
||||
|
@ -168,7 +168,7 @@ exports[`compaction dialog matches snapshot 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bp3-form-group"
|
||||
class="bp3-form-group form-group-with-info"
|
||||
>
|
||||
<label
|
||||
class="bp3-label"
|
||||
|
@ -223,7 +223,7 @@ exports[`compaction dialog matches snapshot 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bp3-form-group"
|
||||
class="bp3-form-group form-group-with-info"
|
||||
>
|
||||
<label
|
||||
class="bp3-label"
|
||||
|
@ -336,7 +336,7 @@ exports[`compaction dialog matches snapshot 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bp3-form-group"
|
||||
class="bp3-form-group form-group-with-info"
|
||||
>
|
||||
<label
|
||||
class="bp3-label"
|
||||
|
@ -470,7 +470,7 @@ exports[`compaction dialog matches snapshot 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bp3-form-group"
|
||||
class="bp3-form-group form-group-with-info"
|
||||
>
|
||||
<label
|
||||
class="bp3-label"
|
||||
|
@ -583,7 +583,7 @@ exports[`compaction dialog matches snapshot 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bp3-form-group"
|
||||
class="bp3-form-group form-group-with-info"
|
||||
>
|
||||
<label
|
||||
class="bp3-label"
|
||||
|
|
|
@ -20,6 +20,7 @@ import { Button, Classes, Dialog, Intent } from '@blueprintjs/core';
|
|||
import React from 'react';
|
||||
|
||||
import { AutoForm, ExternalLink } from '../../components';
|
||||
import { DRUID_DOCS_VERSION } from '../../variables';
|
||||
|
||||
import './compaction-dialog.scss';
|
||||
|
||||
|
@ -125,7 +126,9 @@ export class CompactionDialog extends React.PureComponent<
|
|||
type: 'json',
|
||||
info: (
|
||||
<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
|
||||
</ExternalLink>{' '}
|
||||
for compaction tasks.
|
||||
|
@ -143,7 +146,9 @@ export class CompactionDialog extends React.PureComponent<
|
|||
type: 'json',
|
||||
info: (
|
||||
<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
|
||||
</ExternalLink>{' '}
|
||||
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
|
||||
|
||||
<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"
|
||||
target="_blank"
|
||||
>
|
||||
|
|
|
@ -24,6 +24,7 @@ import React from 'react';
|
|||
import { AutoForm, ExternalLink } from '../../components';
|
||||
import { AppToaster } from '../../singletons/toaster';
|
||||
import { getDruidErrorMessage, QueryManager } from '../../utils';
|
||||
import { DRUID_DOCS_VERSION } from '../../variables';
|
||||
import { SnitchDialog } from '../snitch-dialog/snitch-dialog';
|
||||
|
||||
import './coordinator-dynamic-config-dialog.scss';
|
||||
|
@ -126,7 +127,9 @@ export class CoordinatorDynamicConfigDialog extends React.PureComponent<
|
|||
<p>
|
||||
Edit the coordinator dynamic configuration on the fly. For more information please refer
|
||||
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
|
||||
</ExternalLink>
|
||||
.
|
||||
|
|
|
@ -19,7 +19,7 @@ exports[`history dialog matches snapshot 1`] = `
|
|||
class="bp3-dialog history-dialog"
|
||||
>
|
||||
<div
|
||||
class="history-record-container"
|
||||
class="bp3-dialog-body history-record-container"
|
||||
>
|
||||
<span
|
||||
class="history-dialog-title"
|
||||
|
@ -125,6 +125,13 @@ exports[`history dialog matches snapshot 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bp3-dialog-footer"
|
||||
>
|
||||
<div
|
||||
class="bp3-dialog-footer-actions"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
* 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 { JsonCollapse } from '../../components';
|
||||
|
@ -25,54 +26,50 @@ import './history-dialog.scss';
|
|||
|
||||
interface HistoryDialogProps {
|
||||
historyRecords: any[];
|
||||
children?: ReactNode;
|
||||
buttons?: ReactNode;
|
||||
}
|
||||
|
||||
export const HistoryDialog = React.memo(function HistoryDialog(props: HistoryDialogProps) {
|
||||
function renderRecords() {
|
||||
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);
|
||||
const { buttons, historyRecords } = props;
|
||||
|
||||
return (
|
||||
<div key={i} className="history-record-entry">
|
||||
<Card>
|
||||
<div className="history-record-title">
|
||||
<span className="history-record-title-change">Change</span>
|
||||
<span>{formattedTime}</span>
|
||||
</div>
|
||||
<Divider />
|
||||
<p>{auditInfo.comment === '' ? '(No comment)' : auditInfo.comment}</p>
|
||||
<JsonCollapse stringValue={record.payload} buttonText="Payload" />
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="history-record-container">
|
||||
{content}
|
||||
{children}
|
||||
</div>
|
||||
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 (
|
||||
<div key={i} className="history-record-entry">
|
||||
<Card>
|
||||
<div className="history-record-title">
|
||||
<span className="history-record-title-change">Change</span>
|
||||
<span>{formattedTime}</span>
|
||||
</div>
|
||||
<Divider />
|
||||
<p>{auditInfo.comment === '' ? '(No comment)' : auditInfo.comment}</p>
|
||||
<JsonCollapse stringValue={record.payload} buttonText="Payload" />
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
||||
<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"
|
||||
target="_blank"
|
||||
>
|
||||
|
|
|
@ -24,6 +24,7 @@ import React from 'react';
|
|||
import { AutoForm, ExternalLink } from '../../components';
|
||||
import { AppToaster } from '../../singletons/toaster';
|
||||
import { getDruidErrorMessage, QueryManager } from '../../utils';
|
||||
import { DRUID_DOCS_VERSION } from '../../variables';
|
||||
import { SnitchDialog } from '../snitch-dialog/snitch-dialog';
|
||||
|
||||
import './overlord-dynamic-config-dialog.scss';
|
||||
|
@ -129,7 +130,9 @@ export class OverlordDynamicConfigDialog extends React.PureComponent<
|
|||
<p>
|
||||
Edit the overlord dynamic configuration on the fly. For more information please refer to
|
||||
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
|
||||
</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
|
||||
|
||||
<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"
|
||||
>
|
||||
documentation
|
||||
|
|
|
@ -23,6 +23,7 @@ import React from 'react';
|
|||
|
||||
import { RuleEditor } from '../../components';
|
||||
import { QueryManager } from '../../utils';
|
||||
import { DRUID_DOCS_VERSION } from '../../variables';
|
||||
import { SnitchDialog } from '../snitch-dialog/snitch-dialog';
|
||||
|
||||
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
|
||||
evaluated in order from top to bottom. For more information please refer to the{' '}
|
||||
<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"
|
||||
>
|
||||
documentation
|
||||
|
|
|
@ -116,13 +116,15 @@ export class SnitchDialog extends React.PureComponent<SnitchDialogProps, SnitchD
|
|||
if (!historyRecords) return null;
|
||||
|
||||
return (
|
||||
<HistoryDialog {...this.props} historyRecords={historyRecords}>
|
||||
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||
<HistoryDialog
|
||||
{...this.props}
|
||||
historyRecords={historyRecords}
|
||||
buttons={
|
||||
<Button onClick={this.back} icon={IconNames.ARROW_LEFT}>
|
||||
Back
|
||||
</Button>
|
||||
</div>
|
||||
</HistoryDialog>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,17 +62,3 @@ svg {
|
|||
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 { ExternalLink } from '../components/external-link/external-link';
|
||||
import { DRUID_DOCS_VERSION } from '../variables';
|
||||
|
||||
import {
|
||||
BASIC_TIME_FORMATS,
|
||||
|
@ -162,13 +163,13 @@ export function getIngestionDocLink(spec: IngestionSpec): string {
|
|||
|
||||
switch (type) {
|
||||
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':
|
||||
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:
|
||||
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>
|
||||
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
|
||||
</ExternalLink>
|
||||
.
|
||||
|
@ -573,7 +576,9 @@ const FLATTEN_FIELD_FORM_FIELDS: Field<FlattenField>[] = [
|
|||
info: (
|
||||
<>
|
||||
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
|
||||
</ExternalLink>
|
||||
.
|
||||
|
@ -618,7 +623,9 @@ const TRANSFORM_FORM_FIELDS: Field<Transform>[] = [
|
|||
info: (
|
||||
<>
|
||||
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
|
||||
</ExternalLink>
|
||||
.
|
||||
|
@ -820,7 +827,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
|||
info: (
|
||||
<p>
|
||||
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
|
||||
</ExternalLink>
|
||||
. You can change your selected firehose here.
|
||||
|
@ -873,7 +882,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
|||
required: true,
|
||||
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
|
||||
</ExternalLink>
|
||||
<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'],
|
||||
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
|
||||
</ExternalLink>
|
||||
<p>
|
||||
|
@ -963,7 +976,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
|||
info: (
|
||||
<p>
|
||||
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
|
||||
</ExternalLink>{' '}
|
||||
to apply to the data as part of querying.
|
||||
|
@ -1026,7 +1041,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
|||
<>
|
||||
<p>
|
||||
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
|
||||
</ExternalLink>
|
||||
.
|
||||
|
@ -1057,7 +1074,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
|||
required: true,
|
||||
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
|
||||
</ExternalLink>
|
||||
<p>
|
||||
|
@ -1079,7 +1098,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
|||
defaultValue: {},
|
||||
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
|
||||
</ExternalLink>
|
||||
<p>A map of properties to be passed to the Kafka consumer.</p>
|
||||
|
@ -1129,7 +1150,9 @@ export function getIoConfigFormFields(ingestionComboType: IngestionComboType): F
|
|||
info: (
|
||||
<>
|
||||
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
|
||||
</ExternalLink>
|
||||
.
|
||||
|
|
|
@ -19,13 +19,16 @@
|
|||
export const LEGACY_COORDINATOR_CONSOLE = '/index.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_GITHUB = 'https://github.com/apache/druid';
|
||||
export const DRUID_DOCS = 'https://druid.apache.org/docs/latest';
|
||||
export const DRUID_DOCS_SQL = 'https://druid.apache.org/docs/latest/querying/sql.html';
|
||||
export const DRUID_DOCS_RUNE = 'https://druid.apache.org/docs/latest/querying/querying.html';
|
||||
export const DRUID_DOCS = `https://druid.apache.org/docs/${DRUID_DOCS_VERSION}`;
|
||||
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/${DRUID_DOCS_VERSION}/querying/querying.html`;
|
||||
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_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_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"
|
||||
>
|
||||
<a
|
||||
href="https://druid.apache.org/docs/latest/development/extensions-core/kinesis-ingestion.html"
|
||||
href="https://druid.apache.org/docs"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
|
|
|
@ -23,9 +23,7 @@ import { LearnMore } from './learn-more';
|
|||
|
||||
describe('learn more', () => {
|
||||
it('matches snapshot', () => {
|
||||
const learnMore = (
|
||||
<LearnMore href="https://druid.apache.org/docs/latest/development/extensions-core/kinesis-ingestion.html" />
|
||||
);
|
||||
const learnMore = <LearnMore href={`https://druid.apache.org/docs`} />;
|
||||
|
||||
const { container } = render(learnMore);
|
||||
expect(container.firstChild).toMatchSnapshot();
|
||||
|
|
|
@ -88,7 +88,7 @@
|
|||
bottom: 0;
|
||||
left: 0;
|
||||
content: '';
|
||||
border: 2px solid #48aff0;
|
||||
border: 2px solid #008adc;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@
|
|||
left: 0;
|
||||
right: 0;
|
||||
content: '';
|
||||
border: 2px solid #ff5d10;
|
||||
border: 2px solid #008adc;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@
|
|||
}
|
||||
|
||||
&.used {
|
||||
background: rgba(24, 201, 201, 0.5);
|
||||
background: rgba(99, 129, 137, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,7 +218,7 @@
|
|||
}
|
||||
|
||||
&.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 {
|
||||
grid-area: next;
|
||||
text-align: right;
|
||||
|
@ -268,19 +262,19 @@
|
|||
padding: 10px;
|
||||
border-radius: 2px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.control-buttons {
|
||||
position: relative;
|
||||
.control-buttons {
|
||||
position: relative;
|
||||
|
||||
.bp3-button {
|
||||
margin-right: 15px;
|
||||
}
|
||||
.bp3-button {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.cancel {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
.right {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@ import {
|
|||
Icon,
|
||||
IconName,
|
||||
Intent,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Popover,
|
||||
Switch,
|
||||
TextArea,
|
||||
|
@ -49,6 +51,7 @@ import {
|
|||
JsonInput,
|
||||
Loader,
|
||||
} from '../../components';
|
||||
import { FormGroupWithInfo } from '../../components/form-group-with-info/form-group-with-info';
|
||||
import { AsyncActionDialog } from '../../dialogs';
|
||||
import { AppToaster } from '../../singletons/toaster';
|
||||
import { UrlBaser } from '../../singletons/url-baser';
|
||||
|
@ -140,6 +143,7 @@ import {
|
|||
SampleStrategy,
|
||||
} from '../../utils/sampler';
|
||||
import { computeFlattenPathsForData } from '../../utils/spec-utils';
|
||||
import { DRUID_DOCS_VERSION } from '../../variables';
|
||||
|
||||
import { ExamplePicker } from './example-picker/example-picker';
|
||||
import { FilterTable, filterTableSelectedColumnName } from './filter-table/filter-table';
|
||||
|
@ -555,7 +559,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
const previewSpecSame = this.isPreviewSpecSame();
|
||||
|
||||
return (
|
||||
<FormGroup className="apply-button-bar">
|
||||
<FormGroup className="control-buttons">
|
||||
<Button
|
||||
text="Apply"
|
||||
disabled={previewSpecSame}
|
||||
|
@ -564,8 +568,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
/>
|
||||
{!previewSpecSame && (
|
||||
<Button
|
||||
className="revert"
|
||||
icon={IconNames.UNDO}
|
||||
text="Cancel"
|
||||
disabled={this.isPreviewSpecSame()}
|
||||
onClick={this.revertPreviewSpec}
|
||||
/>
|
||||
|
@ -791,7 +794,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
return (
|
||||
<p>
|
||||
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
|
||||
</ExternalLink>
|
||||
.
|
||||
|
@ -893,7 +898,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
</p>
|
||||
<p>
|
||||
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
|
||||
</ExternalLink>
|
||||
.
|
||||
|
@ -1029,7 +1036,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
<Callout className="intro">
|
||||
<p>
|
||||
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
|
||||
</ExternalLink>{' '}
|
||||
that is optimized for analytic queries.
|
||||
|
@ -1264,7 +1273,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
{canFlatten && (
|
||||
<p>
|
||||
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
|
||||
</ExternalLink>{' '}
|
||||
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>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>
|
||||
{!selectedFlattenField && (
|
||||
<>
|
||||
|
@ -1362,8 +1375,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
/>
|
||||
<div className="control-buttons">
|
||||
<Button
|
||||
className="add-update"
|
||||
text={selectedFlattenFieldIndex === -1 ? 'Add' : 'Update'}
|
||||
text="Apply"
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={() => {
|
||||
this.updateSpec(
|
||||
|
@ -1376,8 +1388,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
close();
|
||||
}}
|
||||
/>
|
||||
<Button text="Cancel" onClick={close} />
|
||||
{selectedFlattenFieldIndex !== -1 && (
|
||||
<Button
|
||||
className="right"
|
||||
icon={IconNames.TRASH}
|
||||
intent={Intent.DANGER}
|
||||
onClick={() => {
|
||||
|
@ -1391,7 +1405,6 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
}}
|
||||
/>
|
||||
)}
|
||||
<Button className="cancel" text="Cancel" onClick={close} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1409,7 +1422,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
/>
|
||||
<AnchorButton
|
||||
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"
|
||||
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
|
||||
a default one.
|
||||
</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>
|
||||
<FormGroup label="Timestamp spec">
|
||||
<ButtonGroup>
|
||||
|
@ -1692,12 +1707,16 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
<p className="optional">Optional</p>
|
||||
<p>
|
||||
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
|
||||
</ExternalLink>{' '}
|
||||
of column values allowing you to create new derived columns or alter existing column.
|
||||
</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>
|
||||
{Boolean(transformQueryState.error && transforms.length) && (
|
||||
<FormGroup>
|
||||
|
@ -1758,8 +1777,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
/>
|
||||
<div className="control-buttons">
|
||||
<Button
|
||||
className="add-update"
|
||||
text={selectedTransformIndex === -1 ? 'Add' : 'Update'}
|
||||
text="Apply"
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={() => {
|
||||
this.updateSpec(
|
||||
|
@ -1772,8 +1790,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
close();
|
||||
}}
|
||||
/>
|
||||
<Button text="Cancel" onClick={close} />
|
||||
{selectedTransformIndex !== -1 && (
|
||||
<Button
|
||||
className="right"
|
||||
icon={IconNames.TRASH}
|
||||
intent={Intent.DANGER}
|
||||
onClick={() => {
|
||||
|
@ -1787,7 +1807,6 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
}}
|
||||
/>
|
||||
)}
|
||||
<Button className="cancel" text="Cancel" onClick={close} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1935,12 +1954,16 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
<p className="optional">Optional</p>
|
||||
<p>
|
||||
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
|
||||
</ExternalLink>{' '}
|
||||
out unwanted data by applying per-row filters.
|
||||
</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>
|
||||
{!showGlobalFilter && this.renderColumnFilterControls()}
|
||||
{!selectedFilter && this.renderGlobalFilterControls()}
|
||||
|
@ -1982,8 +2005,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
/>
|
||||
<div className="control-buttons">
|
||||
<Button
|
||||
className="add-update"
|
||||
text={selectedFilterIndex === -1 ? 'Add' : 'Update'}
|
||||
text="Apply"
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={() => {
|
||||
const curFilter = splitFilter(deepGet(spec, 'dataSchema.transformSpec.filter'));
|
||||
|
@ -1994,8 +2016,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
close();
|
||||
}}
|
||||
/>
|
||||
<Button text="Cancel" onClick={close} />
|
||||
{selectedFilterIndex !== -1 && (
|
||||
<Button
|
||||
className="right"
|
||||
icon={IconNames.TRASH}
|
||||
intent={Intent.DANGER}
|
||||
onClick={() => {
|
||||
|
@ -2008,7 +2032,6 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
}}
|
||||
/>
|
||||
)}
|
||||
<Button className="cancel" text="Cancel" onClick={close} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -2068,17 +2091,8 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
/>
|
||||
</FormGroup>
|
||||
<div className="control-buttons">
|
||||
<Button
|
||||
className="add-update"
|
||||
text="Apply"
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={() => this.queryForFilter()}
|
||||
/>
|
||||
<Button
|
||||
className="cancel"
|
||||
text="Close"
|
||||
onClick={() => this.setState({ showGlobalFilter: false })}
|
||||
/>
|
||||
<Button text="Apply" intent={Intent.PRIMARY} onClick={() => this.queryForFilter()} />
|
||||
<Button text="Cancel" onClick={() => this.setState({ showGlobalFilter: false })} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -2205,11 +2219,36 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
want to change the type, click on the column header.
|
||||
</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>
|
||||
{!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
|
||||
checked={dimensionMode === 'specific'}
|
||||
onChange={() =>
|
||||
|
@ -2219,29 +2258,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
}
|
||||
label="Explicitly specify dimension list"
|
||||
/>
|
||||
<Popover
|
||||
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>
|
||||
</FormGroupWithInfo>
|
||||
{dimensionMode === 'auto-detect' && (
|
||||
<AutoForm
|
||||
fields={[
|
||||
|
@ -2261,43 +2278,45 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
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
|
||||
checked={rollup}
|
||||
onChange={() => this.setState({ newRollup: !rollup })}
|
||||
labelElement="Rollup"
|
||||
/>
|
||||
<Popover
|
||||
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>
|
||||
</FormGroupWithInfo>
|
||||
<AutoForm
|
||||
fields={[
|
||||
{
|
||||
|
@ -2425,6 +2444,33 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
const curDimensions =
|
||||
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 (
|
||||
<div className="edit-controls">
|
||||
<AutoForm
|
||||
|
@ -2432,10 +2478,20 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
model={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">
|
||||
<Button
|
||||
className="add-update"
|
||||
text={selectedDimensionSpecIndex === -1 ? 'Add' : 'Update'}
|
||||
text="Apply"
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={() => {
|
||||
this.updateSpec(
|
||||
|
@ -2448,8 +2504,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
close();
|
||||
}}
|
||||
/>
|
||||
<Button text="Cancel" onClick={close} />
|
||||
{selectedDimensionSpecIndex !== -1 && (
|
||||
<Button
|
||||
className="right"
|
||||
icon={IconNames.TRASH}
|
||||
intent={Intent.DANGER}
|
||||
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>
|
||||
);
|
||||
|
@ -2502,6 +2559,39 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
};
|
||||
|
||||
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 (
|
||||
<div className="edit-controls">
|
||||
<AutoForm
|
||||
|
@ -2509,10 +2599,16 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
model={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">
|
||||
<Button
|
||||
className="add-update"
|
||||
text={selectedMetricSpecIndex === -1 ? 'Add' : 'Update'}
|
||||
text="Apply"
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={() => {
|
||||
this.updateSpec(
|
||||
|
@ -2525,8 +2621,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
close();
|
||||
}}
|
||||
/>
|
||||
<Button text="Cancel" onClick={close} />
|
||||
{selectedMetricSpecIndex !== -1 && (
|
||||
<Button
|
||||
className="right"
|
||||
icon={IconNames.TRASH}
|
||||
intent={Intent.DANGER}
|
||||
onClick={() => {
|
||||
|
@ -2537,7 +2635,6 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
}}
|
||||
/>
|
||||
)}
|
||||
<Button className="cancel" text="Cancel" onClick={close} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -2633,7 +2730,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
<Callout className="intro">
|
||||
<p className="optional">Optional</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>
|
||||
{this.renderParallelPickerIfNeeded()}
|
||||
</div>
|
||||
|
@ -2698,7 +2797,9 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
|||
<Callout className="intro">
|
||||
<p className="optional">Optional</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>
|
||||
{this.renderParallelPickerIfNeeded()}
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue