blob: afa7d4ebf8e4d48329e681a2de2c95e97bbdf968 [file] [log] [blame]
/*
* 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 {
Button,
ButtonGroup,
Hotkey,
Hotkeys,
HotkeysTarget,
Intent,
Menu,
MenuDivider,
MenuItem,
Popover,
Position,
} from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import React from 'react';
import { MenuCheckbox } from '../../../components';
import { getLink } from '../../../links';
import { pluralIfNeeded } from '../../../utils';
import {
getUseApproximateCountDistinct,
getUseApproximateTopN,
getUseCache,
QueryContext,
setUseApproximateCountDistinct,
setUseApproximateTopN,
setUseCache,
} from '../../../utils/query-context';
import './run-button.scss';
export interface RunButtonProps {
runeMode: boolean;
queryContext: QueryContext;
onQueryContextChange: (newQueryContext: QueryContext) => void;
onRun: (() => void) | undefined;
loading: boolean;
onExplain: (() => void) | undefined;
onEditContext: () => void;
onHistory: () => void;
onPrettier: () => void;
}
@HotkeysTarget
export class RunButton extends React.PureComponent<RunButtonProps> {
public renderHotkeys() {
return (
<Hotkeys>
<Hotkey
allowInInput
global
combo="ctrl + enter"
label="run on click"
onKeyDown={this.handleRun}
/>
</Hotkeys>
);
}
private handleRun = () => {
const { onRun } = this.props;
if (!onRun) return;
onRun();
};
renderExtraMenu() {
const {
runeMode,
onExplain,
queryContext,
onQueryContextChange,
onEditContext,
onHistory,
onPrettier,
} = this.props;
const useCache = getUseCache(queryContext);
const useApproximateCountDistinct = getUseApproximateCountDistinct(queryContext);
const useApproximateTopN = getUseApproximateTopN(queryContext);
const numContextKeys = Object.keys(queryContext).length;
return (
<Menu>
<MenuItem
icon={IconNames.HELP}
text={runeMode ? 'Native query documentation' : 'DruidSQL documentation'}
href={getLink(runeMode ? 'DOCS_RUNE' : 'DOCS_SQL')}
target="_blank"
/>
<MenuItem icon={IconNames.HISTORY} text="Query history" onClick={onHistory} />
{!runeMode && onExplain && (
<MenuItem icon={IconNames.CLEAN} text="Explain SQL query" onClick={onExplain} />
)}
{runeMode && (
<MenuItem icon={IconNames.ALIGN_LEFT} text="Prettify JSON" onClick={onPrettier} />
)}
<MenuItem
icon={IconNames.PROPERTIES}
text="Edit context"
onClick={onEditContext}
label={numContextKeys ? pluralIfNeeded(numContextKeys, 'key') : undefined}
/>
<MenuDivider />
{!runeMode && (
<>
<MenuCheckbox
checked={useApproximateCountDistinct}
text="Use approximate COUNT(DISTINCT)"
onChange={() => {
onQueryContextChange(
setUseApproximateCountDistinct(queryContext, !useApproximateCountDistinct),
);
}}
/>
<MenuCheckbox
checked={useApproximateTopN}
text="Use approximate TopN"
onChange={() => {
onQueryContextChange(setUseApproximateTopN(queryContext, !useApproximateTopN));
}}
/>
</>
)}
<MenuCheckbox
checked={useCache}
text="Use cache"
onChange={() => {
onQueryContextChange(setUseCache(queryContext, !useCache));
}}
/>
</Menu>
);
}
render(): JSX.Element {
const { runeMode, onRun, loading } = this.props;
return (
<ButtonGroup className="run-button">
{onRun ? (
<Button
className={runeMode ? 'rune-button' : undefined}
disabled={loading}
icon={IconNames.CARET_RIGHT}
onClick={this.handleRun}
text="Run"
intent={Intent.PRIMARY}
/>
) : (
<Button
className={runeMode ? 'rune-button' : undefined}
icon={IconNames.CARET_RIGHT}
text="Run"
disabled
/>
)}
<Popover position={Position.BOTTOM_LEFT} content={this.renderExtraMenu()}>
<Button
className={runeMode ? 'rune-button' : undefined}
icon={IconNames.MORE}
intent={onRun ? Intent.PRIMARY : undefined}
/>
</Popover>
</ButtonGroup>
);
}
}