diff --git a/client/app/pages/queries/QuerySource.jsx b/client/app/pages/queries/QuerySource.jsx index ae34192070..2aea634598 100644 --- a/client/app/pages/queries/QuerySource.jsx +++ b/client/app/pages/queries/QuerySource.jsx @@ -87,7 +87,15 @@ function QuerySource(props) { const parameters = useMemo(() => query.getParametersDefs(), [query]); const [dirtyParameters, setDirtyParameters] = useState(query.getParameters().hasPendingValues()); - const { queryResult, queryResultData, isQueryExecuting, executeQuery, executeAdhocQuery } = useQueryExecute(query); + const { + queryResult, + queryResultData, + isQueryExecuting, + isExecutionCancelling, + executeQuery, + executeAdhocQuery, + cancelExecution, + } = useQueryExecute(query); const editorRef = useRef(null); const autocompleteAvailable = useMemo(() => { @@ -454,7 +462,8 @@ function QuerySource(props) { status={queryResultData.status} updatedAt={queryResultData.updatedAt} error={queryResultData.error} - onCancel={() => console.log("Query execution cancelled")} + isCancelling={isExecutionCancelling} + onCancel={cancelExecution} /> )} diff --git a/client/app/pages/queries/components/QueryExecutionStatus.jsx b/client/app/pages/queries/components/QueryExecutionStatus.jsx index 2ce42ab6c7..5a1eeeb4e5 100644 --- a/client/app/pages/queries/components/QueryExecutionStatus.jsx +++ b/client/app/pages/queries/components/QueryExecutionStatus.jsx @@ -5,18 +5,22 @@ import Alert from "antd/lib/alert"; import Button from "antd/lib/button"; import { Timer } from "@/components/Timer"; -export default function QueryExecutionStatus({ status, updatedAt, error, onCancel }) { +export default function QueryExecutionStatus({ status, updatedAt, error, isCancelling, onCancel }) { const alertType = status === "failed" ? "error" : "info"; const showTimer = status !== "failed" && updatedAt; - const canCancel = includes(["waiting", "processing"], status); - let message = null; + const isCancelButtonAvailable = includes(["waiting", "processing"], status); + let message = isCancelling ? Cancelling… : null; switch (status) { case "waiting": - message = Query in queue…; + if (!isCancelling) { + message = Query in queue…; + } break; case "processing": - message = Executing query…; + if (!isCancelling) { + message = Executing query…; + } break; case "loading-result": message = Loading results…; @@ -40,8 +44,8 @@ export default function QueryExecutionStatus({ status, updatedAt, error, onCance {message} {showTimer && }
- {canCancel && ( - )} @@ -56,6 +60,7 @@ QueryExecutionStatus.propTypes = { status: PropTypes.string, updatedAt: PropTypes.any, error: PropTypes.string, + isCancelling: PropTypes.bool, onCancel: PropTypes.func, }; @@ -63,5 +68,6 @@ QueryExecutionStatus.defaultProps = { status: "waiting", updatedAt: null, error: null, + isCancelling: true, onCancel: () => {}, }; diff --git a/client/app/pages/queries/utils/useQueryExecute.js b/client/app/pages/queries/utils/useQueryExecute.js index 978e56257c..d28bccbe10 100644 --- a/client/app/pages/queries/utils/useQueryExecute.js +++ b/client/app/pages/queries/utils/useQueryExecute.js @@ -23,6 +23,8 @@ export default function useQueryExecute(query) { queryResultData.status, ]); + const [isExecutionCancelling, setIsExecutionCancelling] = useState(false); + const executeQuery = useCallback(() => { recordEvent("execute", "query", query.id); setQueryResult(query.getQueryResult(0)); @@ -36,12 +38,31 @@ export default function useQueryExecute(query) { [query] ); + const cancelExecution = useCallback(() => { + if (queryResult) { + recordEvent("cancel_execute", "query", query.id); + queryResult.cancelExecution(); + setIsExecutionCancelling(true); + } + }, [query, queryResult]); + useEffect(() => { - if (!isQueryExecuting && queryResult && queryResult.query_result.query === query.query) { - query.latest_query_data_id = queryResult.getId(); - query.queryResult = queryResult; + if (!isQueryExecuting) { + setIsExecutionCancelling(false); + if (queryResult && queryResult.query_result.query === query.query) { + query.latest_query_data_id = queryResult.getId(); + query.queryResult = queryResult; + } } }, [isQueryExecuting]); // eslint-disable-line react-hooks/exhaustive-deps - return { queryResult, queryResultData, isQueryExecuting, executeQuery, executeAdhocQuery }; + return { + queryResult, + queryResultData, + isQueryExecuting, + isExecutionCancelling, + executeQuery, + executeAdhocQuery, + cancelExecution, + }; }