mirror of https://github.com/apache/superset.git
Hotkeys in Explore View (#6526)
* working .... hotkeys in example of hotkeys in explore
* added save functionality
* Added proper overwrite functions
* cleanup
* cleanup
* cleanu
* fixe linting
* add global
* move match to utils
* linting
* change some stuff
* Delete example_filter_immune_slice_fields.json
* hide annoying blue bar
* switch hotkeys to reference s
* remove console.log
* have hotkey generate help
* 🚢
* move functions out of component
* refactor
* Delete yarn.lock
* addressed comments
* remove comments
* remove Hotkeys component from ChartView
* Add hotkeys button next to save&run
* moved keyboard
* cleanup
* checkout package.json
* checkout chart panel
* reference apache
* remove style change
* whitespace
* clean up on hotkey popup
* fds
* linting
* fix all linting errors
This commit is contained in:
parent
88283dc2cb
commit
d628907be3
|
@ -28,6 +28,7 @@ const propTypes = {
|
||||||
func: PropTypes.func.isRequired,
|
func: PropTypes.func.isRequired,
|
||||||
})).isRequired,
|
})).isRequired,
|
||||||
header: PropTypes.string,
|
header: PropTypes.string,
|
||||||
|
placement: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
|
@ -42,7 +43,6 @@ export default class Hotkeys extends React.PureComponent {
|
||||||
}
|
}
|
||||||
renderPopover() {
|
renderPopover() {
|
||||||
const { header, hotkeys } = this.props;
|
const { header, hotkeys } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover id="hotkey-popover" title={header} style={{ width: '300px' }}>
|
<Popover id="hotkey-popover" title={header} style={{ width: '300px' }}>
|
||||||
<table className="table table-condensed">
|
<table className="table table-condensed">
|
||||||
|
@ -68,7 +68,7 @@ export default class Hotkeys extends React.PureComponent {
|
||||||
<OverlayTrigger
|
<OverlayTrigger
|
||||||
overlay={this.renderPopover()}
|
overlay={this.renderPopover()}
|
||||||
trigger={['hover', 'focus']}
|
trigger={['hover', 'focus']}
|
||||||
placement="top"
|
placement={this.props.placement || 'top'}
|
||||||
>
|
>
|
||||||
<i className="fa fa-keyboard-o fa-lg" />
|
<i className="fa fa-keyboard-o fa-lg" />
|
||||||
</OverlayTrigger>
|
</OverlayTrigger>
|
||||||
|
|
|
@ -35,6 +35,25 @@ import * as saveModalActions from '../actions/saveModalActions';
|
||||||
import * as chartActions from '../../chart/chartAction';
|
import * as chartActions from '../../chart/chartAction';
|
||||||
import { fetchDatasourceMetadata } from '../../dashboard/actions/datasources';
|
import { fetchDatasourceMetadata } from '../../dashboard/actions/datasources';
|
||||||
import { Logger, ActionLog, EXPLORE_EVENT_NAMES, LOG_ACTIONS_MOUNT_EXPLORER } from '../../logger';
|
import { Logger, ActionLog, EXPLORE_EVENT_NAMES, LOG_ACTIONS_MOUNT_EXPLORER } from '../../logger';
|
||||||
|
import Hotkeys from '../../components/Hotkeys';
|
||||||
|
|
||||||
|
// Prolly need to move this to a global context
|
||||||
|
const keymap = {
|
||||||
|
RUN: 'ctrl + r, ctrl + enter',
|
||||||
|
SAVE: 'ctrl + s',
|
||||||
|
};
|
||||||
|
|
||||||
|
const getHotKeys = () => {
|
||||||
|
const d = [];
|
||||||
|
Object.keys(keymap).forEach((k) => {
|
||||||
|
d.push({
|
||||||
|
name: k,
|
||||||
|
descr: keymap[k],
|
||||||
|
key: k,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
actions: PropTypes.object.isRequired,
|
actions: PropTypes.object.isRequired,
|
||||||
|
@ -75,11 +94,13 @@ class ExploreViewContainer extends React.Component {
|
||||||
this.onStop = this.onStop.bind(this);
|
this.onStop = this.onStop.bind(this);
|
||||||
this.onQuery = this.onQuery.bind(this);
|
this.onQuery = this.onQuery.bind(this);
|
||||||
this.toggleModal = this.toggleModal.bind(this);
|
this.toggleModal = this.toggleModal.bind(this);
|
||||||
|
this.handleKeydown = this.handleKeydown.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
window.addEventListener('resize', this.handleResize);
|
window.addEventListener('resize', this.handleResize);
|
||||||
window.addEventListener('popstate', this.handlePopstate);
|
window.addEventListener('popstate', this.handlePopstate);
|
||||||
|
document.addEventListener('keydown', this.handleKeydown);
|
||||||
this.addHistory({ isReplace: true });
|
this.addHistory({ isReplace: true });
|
||||||
Logger.append(LOG_ACTIONS_MOUNT_EXPLORER);
|
Logger.append(LOG_ACTIONS_MOUNT_EXPLORER);
|
||||||
}
|
}
|
||||||
|
@ -129,6 +150,7 @@ class ExploreViewContainer extends React.Component {
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
window.removeEventListener('resize', this.handleResize);
|
window.removeEventListener('resize', this.handleResize);
|
||||||
window.removeEventListener('popstate', this.handlePopstate);
|
window.removeEventListener('popstate', this.handlePopstate);
|
||||||
|
document.removeEventListener('keydown', this.handleKeydown);
|
||||||
}
|
}
|
||||||
|
|
||||||
onQuery() {
|
onQuery() {
|
||||||
|
@ -158,6 +180,29 @@ class ExploreViewContainer extends React.Component {
|
||||||
return `${window.innerHeight - navHeight}px`;
|
return `${window.innerHeight - navHeight}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleKeydown(event) {
|
||||||
|
const controlOrCommand = event.ctrlKey || event.metaKey;
|
||||||
|
if (controlOrCommand) {
|
||||||
|
const isEnter = event.key === 'Enter' || event.keyCode === 13;
|
||||||
|
const isS = event.key === 's' || event.keyCode === 83;
|
||||||
|
if (isEnter) {
|
||||||
|
this.onQuery();
|
||||||
|
} else if (isS) {
|
||||||
|
if (this.props.slice) {
|
||||||
|
this.props.actions.saveSlice(this.props.form_data, {
|
||||||
|
action: 'overwrite',
|
||||||
|
slice_id: this.props.slice.slice_id,
|
||||||
|
slice_name: this.props.slice.slice_name,
|
||||||
|
add_to_dash: 'noSave',
|
||||||
|
goto_dash: false,
|
||||||
|
}).then(({ data }) => {
|
||||||
|
window.location = data.slice.slice_url;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
findChangedControlKeys(prevControls, currentControls) {
|
findChangedControlKeys(prevControls, currentControls) {
|
||||||
return Object.keys(currentControls).filter(
|
return Object.keys(currentControls).filter(
|
||||||
key =>
|
key =>
|
||||||
|
@ -273,10 +318,7 @@ class ExploreViewContainer extends React.Component {
|
||||||
<div
|
<div
|
||||||
id="explore-container"
|
id="explore-container"
|
||||||
className="container-fluid"
|
className="container-fluid"
|
||||||
style={{
|
style={{ height: this.state.height, overflow: 'hidden' }}
|
||||||
height: this.state.height,
|
|
||||||
overflow: 'hidden',
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{this.state.showModal && (
|
{this.state.showModal && (
|
||||||
<SaveModal
|
<SaveModal
|
||||||
|
@ -287,16 +329,25 @@ class ExploreViewContainer extends React.Component {
|
||||||
)}
|
)}
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-sm-4">
|
<div className="col-sm-4">
|
||||||
<QueryAndSaveBtns
|
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||||
canAdd="True"
|
<QueryAndSaveBtns
|
||||||
onQuery={this.onQuery}
|
canAdd="True"
|
||||||
onSave={this.toggleModal}
|
onQuery={this.onQuery}
|
||||||
onStop={this.onStop}
|
onSave={this.toggleModal}
|
||||||
loading={this.props.chart.chartStatus === 'loading'}
|
onStop={this.onStop}
|
||||||
chartIsStale={this.state.chartIsStale}
|
loading={this.props.chart.chartStatus === 'loading'}
|
||||||
errorMessage={this.renderErrorMessage()}
|
chartIsStale={this.state.chartIsStale}
|
||||||
datasourceType={this.props.datasource_type}
|
errorMessage={this.renderErrorMessage()}
|
||||||
/>
|
datasourceType={this.props.datasource_type}
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<Hotkeys
|
||||||
|
header="Keyboard shortcuts"
|
||||||
|
hotkeys={getHotKeys()}
|
||||||
|
placement="right"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<ControlPanelsContainer
|
<ControlPanelsContainer
|
||||||
actions={this.props.actions}
|
actions={this.props.actions}
|
||||||
|
|
Loading…
Reference in New Issue