diff --git a/package-lock.json b/package-lock.json index c48f9d3..1648ee8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,8 @@ "observable-hooks": "^4.2.3", "react": "17.0.2", "react-dom": "17.0.2", - "tslib": "2.5.3" + "tslib": "2.5.3", + "usehooks-ts": "^3.1.0" }, "devDependencies": { "@babel/core": "^7.21.4", @@ -17923,8 +17924,7 @@ "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, "node_modules/lodash.memoize": { "version": "4.1.2", @@ -24354,6 +24354,20 @@ } } }, + "node_modules/usehooks-ts": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-3.1.0.tgz", + "integrity": "sha512-bBIa7yUyPhE1BCc0GmR96VU/15l/9gP1Ch5mYdLcFBaFGQsdmXkvjV0TtOqW1yUd6VjIwDunm+flSciCQXujiw==", + "dependencies": { + "lodash.debounce": "^4.0.8" + }, + "engines": { + "node": ">=16.15.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", @@ -38141,8 +38155,7 @@ "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, "lodash.memoize": { "version": "4.1.2", @@ -42812,6 +42825,14 @@ "tslib": "^2.0.0" } }, + "usehooks-ts": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-3.1.0.tgz", + "integrity": "sha512-bBIa7yUyPhE1BCc0GmR96VU/15l/9gP1Ch5mYdLcFBaFGQsdmXkvjV0TtOqW1yUd6VjIwDunm+flSciCQXujiw==", + "requires": { + "lodash.debounce": "^4.0.8" + } + }, "util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", diff --git a/package.json b/package.json index 7d12db6..35efbc6 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,8 @@ "observable-hooks": "^4.2.3", "react": "17.0.2", "react-dom": "17.0.2", - "tslib": "2.5.3" + "tslib": "2.5.3", + "usehooks-ts": "^3.1.0" }, "packageManager": "npm@8.19.2" } diff --git a/src/components/QueryEditor/index.tsx b/src/components/QueryEditor/index.tsx index 44d9034..773c435 100644 --- a/src/components/QueryEditor/index.tsx +++ b/src/components/QueryEditor/index.tsx @@ -1,9 +1,11 @@ import { css } from '@emotion/css'; -import React, { createContext } from 'react'; +import React, { createContext, useRef } from 'react'; import { debounceTime, throttleTime } from 'rxjs'; import { useObservableCallback, useSubscription } from 'observable-hooks' +import { useEventListener } from 'usehooks-ts' + import { CoreApp, Field, getDefaultTimeRange, GrafanaTheme2, QueryEditorProps } from '@grafana/data'; import { InlineLabel, useStyles2 } from '@grafana/ui'; @@ -84,6 +86,15 @@ export const ElasticSearchQueryField = ({ value, onChange, onSubmit }: ElasticSe }; const QueryEditorForm = ({ value, onRunQuery }: Props) => { + const editorRef = useRef(null) + const handleKeyBindings = (e: KeyboardEvent) => { + // Shift+Enter triggers onRunQuery if the active element is inside the editor + if (e.key === "Enter" && e.shiftKey && editorRef.current?.contains(document.activeElement)) { + onRunQuery() + } + e.stopPropagation(); + } + useEventListener("keypress", handleKeyBindings) const dispatch = useDispatch(); const nextId = useNextId(); @@ -108,8 +119,8 @@ const QueryEditorForm = ({ value, onRunQuery }: Props) => { useSubscription(submitted$, onSubmit) return ( - <> -
+
+
Query type
@@ -125,6 +136,6 @@ const QueryEditorForm = ({ value, onRunQuery }: Props) => { {showBucketAggregationsEditor && } - +
); };