Skip to content
Snippets Groups Projects
Commit 8a113d8b authored by Tom Robinson's avatar Tom Robinson Committed by GitHub
Browse files

Merge pull request #3634 from metabase/run-on-command-enter

Make command-enter run the query
parents 9be545a2 4d030880
No related branches found
No related tags found
No related merge requests found
......@@ -64,6 +64,18 @@ export function isCardDirty(card, originalCard) {
}
}
export function isCardRunnable(card) {
if (!card) {
return false;
}
const query = card.dataset_query;
if (query.query) {
return Query.canRun(query.query);
} else {
return (query.database != undefined && query.native.query !== "");
}
}
export function serializeCardForUrl(card) {
// console.log(JSON.stringify(card, null, ' '));
var dataset_query = angular.copy(card.dataset_query);
......
......@@ -11,7 +11,6 @@ import VisualizationError from "./VisualizationError.jsx";
import VisualizationResult from "./VisualizationResult.jsx";
import ModalWithTrigger from "metabase/components/ModalWithTrigger.jsx";
import Query from "metabase/lib/query";
import cx from "classnames";
import _ from "underscore";
......@@ -40,6 +39,7 @@ export default class QueryVisualization extends Component {
cellIsClickableFn: PropTypes.func,
cellClickedFn: PropTypes.func,
isRunning: PropTypes.bool.isRequired,
isRunnable: PropTypes.bool.isRequired,
runQueryFn: PropTypes.func.isRequired,
cancelQueryFn: PropTypes.func
};
......@@ -79,15 +79,6 @@ export default class QueryVisualization extends Component {
this.props.runQueryFn();
}
canRun() {
var query = this.props.card.dataset_query;
if (query.query) {
return Query.canRun(query.query);
} else {
return (query.database != undefined && query.native.query !== "");
}
}
renderHeader() {
const { isObjectDetail, isRunning } = this.props;
return (
......@@ -97,7 +88,7 @@ export default class QueryVisualization extends Component {
</span>
<div className="absolute flex layout-centered left right z3">
<RunButton
canRun={this.canRun()}
canRun={this.props.isRunnable}
isDirty={this.queryIsDirty()}
isRunning={isRunning}
runFn={this.runQuery}
......
......@@ -38,6 +38,7 @@ import {
getSampleDatasetId,
getFullDatasetQuery,
getNativeDatabases,
getIsRunnable,
} from "../selectors";
import * as actions from "../actions";
......@@ -98,6 +99,8 @@ const mapStateToProps = (state, props) => {
isShowingTutorial: state.qb.uiControls.isShowingTutorial,
isEditing: state.qb.uiControls.isEditing,
isRunning: state.qb.uiControls.isRunning,
isRunnable: getIsRunnable(state),
cardApi: cardApi,
dashboardApi: dashboardApi,
revisionApi: revisionApi,
......@@ -122,8 +125,6 @@ export default class QueryBuilder extends Component {
constructor(props, context) {
super(props, context);
_.bindAll(this, "handleResize");
// TODO: React tells us that forceUpdate() is not the best thing to use, so ideally we can find a different way to trigger this
this.forceUpdateDebounced = _.debounce(this.forceUpdate.bind(this), 400);
}
......@@ -133,7 +134,8 @@ export default class QueryBuilder extends Component {
}
componentDidMount() {
window.addEventListener('resize', this.handleResize);
window.addEventListener("resize", this.handleResize);
document.addEventListener("keydown", this.handleKeyDown);
}
componentWillReceiveProps(nextProps) {
......@@ -161,12 +163,13 @@ export default class QueryBuilder extends Component {
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
window.removeEventListener("resize", this.handleResize);
document.addEventListener("keydown", this.handleKeyDown);
}
// When the window is resized we need to re-render, mainly so that our visualization pane updates
// Debounce the function to improve resizing performance.
handleResize(e) {
handleResize = (e) => {
this.forceUpdateDebounced();
let viz = ReactDOM.findDOMNode(this.refs.viz);
if (viz) {
......@@ -174,6 +177,13 @@ export default class QueryBuilder extends Component {
}
}
handleKeyDown = (e) => {
const ENTER_KEY = 13;
if (e.keyCode === ENTER_KEY && e.metaKey && this.props.isRunnable) {
this.props.runQueryFn();
}
}
render() {
const { card, isDirty, databases, uiControls } = this.props;
......
......@@ -4,7 +4,7 @@ import _ from "underscore";
import { getTemplateTags } from "metabase/meta/Card";
import { isCardDirty } from "metabase/lib/card";
import { isCardDirty, isCardRunnable } from "metabase/lib/card";
import * as DataGrid from "metabase/lib/data_grid";
import Query from "metabase/lib/query";
import { parseFieldTarget } from "metabase/lib/query_time";
......@@ -170,3 +170,8 @@ export const getFullDatasetQuery = createSelector(
(card, parameters, parameterValues) =>
card && applyParameters(card, parameters, parameterValues)
)
export const getIsRunnable = createSelector(
[card],
(card) => isCardRunnable(card)
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment