fix: Disable run button when there are empty fields (#24031)
When an API or SQL query is generated, we disable the run button if no input has been provided to the URL and BODY fields respectively. Fixes #23957 #### Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video > > #### Type of change > Please delete options that are not relevant. - Bug fix (non-breaking change which fixes an issue) - New feature (non-breaking change which adds functionality) - Breaking change (fix or feature that would cause existing functionality to not work as expected) - Chore (housekeeping or task changes that don't impact user perception) - This change requires a documentation update > > > ## Testing > #### How Has This Been Tested? > Please describe the tests that you ran to verify your changes. Also list any relevant details for your test configuration. > Delete anything that is not relevant - [x] Manual - [ ] Jest - [ ] Cypress > > #### Test Plan > https://github.com/appsmithorg/TestSmith/issues/2412 > > #### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) > > > ## Checklist: #### Dev activity - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Test-plan-implementation#speedbreaker-features-to-consider-for-every-change) have been covered - [x] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans/_edit#areas-of-interest) - [x] Test plan has been peer reviewed by project stakeholders and other QA members - [x] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed
This commit is contained in:
parent
0e0d19b195
commit
1e3a82522e
|
|
@ -28,7 +28,7 @@ describe("Addwidget from Query and bind with other widgets", function () {
|
||||||
.focus()
|
.focus()
|
||||||
.type("SELECT * FROM configs LIMIT 10;");
|
.type("SELECT * FROM configs LIMIT 10;");
|
||||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||||
cy.wait(500);
|
cy.wait(1000);
|
||||||
// Mock the response for this test
|
// Mock the response for this test
|
||||||
cy.intercept("/api/v1/actions/execute", {
|
cy.intercept("/api/v1/actions/execute", {
|
||||||
fixture: "addWidgetTable-mock",
|
fixture: "addWidgetTable-mock",
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ describe("Check Suggested Widgets Feature in Auto Layout", function () {
|
||||||
.focus()
|
.focus()
|
||||||
.type("SELECT * FROM configs LIMIT 10;");
|
.type("SELECT * FROM configs LIMIT 10;");
|
||||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||||
cy.wait(500);
|
cy.wait(1000);
|
||||||
// Mock the response for this test
|
// Mock the response for this test
|
||||||
cy.intercept("/api/v1/actions/execute", {
|
cy.intercept("/api/v1/actions/execute", {
|
||||||
fixture: "addWidgetTable-mock",
|
fixture: "addWidgetTable-mock",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { ObjectsRegistry } from "../../../../support/Objects/Registry";
|
||||||
|
|
||||||
|
const agHelper = ObjectsRegistry.AggregateHelper,
|
||||||
|
ee = ObjectsRegistry.EntityExplorer,
|
||||||
|
apiPage = ObjectsRegistry.ApiPage,
|
||||||
|
dataSources = ObjectsRegistry.DataSources;
|
||||||
|
|
||||||
|
const url = "https://www.google.com";
|
||||||
|
|
||||||
|
describe("Block Action Execution when no field is present", () => {
|
||||||
|
it("1. Ensure API Run button is disabled when no url is present", () => {
|
||||||
|
apiPage.CreateApi("FirstAPI", "GET");
|
||||||
|
apiPage.AssertRunButtonDisability(true);
|
||||||
|
apiPage.EnterURL(url);
|
||||||
|
apiPage.AssertRunButtonDisability(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("1. Ensure Run button is disabled when no SQL body field is present", () => {
|
||||||
|
let name: any;
|
||||||
|
dataSources.CreateDataSource("MySql", true, false);
|
||||||
|
cy.get("@dsName").then(($dsName) => {
|
||||||
|
name = $dsName;
|
||||||
|
|
||||||
|
agHelper.Sleep(1000);
|
||||||
|
dataSources.NavigateFromActiveDS(name, true);
|
||||||
|
agHelper.GetNClick(dataSources._templateMenu);
|
||||||
|
dataSources.EnterQuery("SELECT * from users");
|
||||||
|
dataSources.AssertRunButtonDisability(false);
|
||||||
|
dataSources.EnterQuery("");
|
||||||
|
dataSources.AssertRunButtonDisability(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -17,11 +17,9 @@ describe("API Panel Test Functionality ", function () {
|
||||||
cy.log("Navigation to API Panel screen successful");
|
cy.log("Navigation to API Panel screen successful");
|
||||||
cy.generateUUID().then((uid) => {
|
cy.generateUUID().then((uid) => {
|
||||||
cy.CreateAPI(`FirstAPI_${uid}`);
|
cy.CreateAPI(`FirstAPI_${uid}`);
|
||||||
cy.RunAPI();
|
|
||||||
cy.log("Creation of FirstAPI Action successful");
|
cy.log("Creation of FirstAPI Action successful");
|
||||||
cy.NavigateToAPI_Panel();
|
cy.NavigateToAPI_Panel();
|
||||||
cy.CreateAPI(`SecondAPI_${uid}`);
|
cy.CreateAPI(`SecondAPI_${uid}`);
|
||||||
cy.RunAPI();
|
|
||||||
cy.CheckAndUnfoldEntityItem("Queries/JS");
|
cy.CheckAndUnfoldEntityItem("Queries/JS");
|
||||||
cy.log("Creation of SecondAPI Action successful");
|
cy.log("Creation of SecondAPI Action successful");
|
||||||
cy.get(".t--entity-name").contains("FirstAPI");
|
cy.get(".t--entity-name").contains("FirstAPI");
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ describe("Addwidget from Query and bind with other widgets", function () {
|
||||||
.focus()
|
.focus()
|
||||||
.type("SELECT * FROM configs LIMIT 10;");
|
.type("SELECT * FROM configs LIMIT 10;");
|
||||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||||
cy.wait(500);
|
cy.wait(1000);
|
||||||
// Mock the response for this test
|
// Mock the response for this test
|
||||||
cy.intercept("/api/v1/actions/execute", {
|
cy.intercept("/api/v1/actions/execute", {
|
||||||
fixture: "addWidgetTable-mock",
|
fixture: "addWidgetTable-mock",
|
||||||
|
|
|
||||||
|
|
@ -113,10 +113,20 @@ export class ApiPage {
|
||||||
this.CreateApi(apiName, apiVerb, aftDSSaved);
|
this.CreateApi(apiName, apiVerb, aftDSSaved);
|
||||||
this.EnterURL(url);
|
this.EnterURL(url);
|
||||||
//this.agHelper.Sleep(2000);// Added because api name edit takes some time to reflect in api sidebar after the call passes.
|
//this.agHelper.Sleep(2000);// Added because api name edit takes some time to reflect in api sidebar after the call passes.
|
||||||
cy.get(this._apiRunBtn).should("not.be.disabled");
|
this.AssertRunButtonDisability();
|
||||||
if (queryTimeout != 10000) this.SetAPITimeout(queryTimeout);
|
if (queryTimeout != 10000) this.SetAPITimeout(queryTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssertRunButtonDisability(disabled = false) {
|
||||||
|
let query = "";
|
||||||
|
if (disabled) {
|
||||||
|
query = "be.disabled";
|
||||||
|
} else {
|
||||||
|
query = "not.be.disabled";
|
||||||
|
}
|
||||||
|
cy.get(this._apiRunBtn).should(query);
|
||||||
|
}
|
||||||
|
|
||||||
EnterURL(url: string) {
|
EnterURL(url: string) {
|
||||||
this.agHelper.EnterValue(url, {
|
this.agHelper.EnterValue(url, {
|
||||||
propFieldName: this._resourceUrl,
|
propFieldName: this._resourceUrl,
|
||||||
|
|
@ -397,7 +407,7 @@ export class ApiPage {
|
||||||
this.EnterURL(url);
|
this.EnterURL(url);
|
||||||
this.agHelper.AssertAutoSave();
|
this.agHelper.AssertAutoSave();
|
||||||
//this.agHelper.Sleep(2000);// Added because api name edit takes some time to reflect in api sidebar after the call passes.
|
//this.agHelper.Sleep(2000);// Added because api name edit takes some time to reflect in api sidebar after the call passes.
|
||||||
cy.get(this._apiRunBtn).should("not.be.disabled");
|
this.AssertRunButtonDisability();
|
||||||
if (queryTimeout != 10000) this.SetAPITimeout(queryTimeout);
|
if (queryTimeout != 10000) this.SetAPITimeout(queryTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -834,6 +834,16 @@ export class DataSources {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssertRunButtonDisability(disabled = false) {
|
||||||
|
let query = "";
|
||||||
|
if (disabled) {
|
||||||
|
query = "be.disabled";
|
||||||
|
} else {
|
||||||
|
query = "not.be.disabled";
|
||||||
|
}
|
||||||
|
cy.get(this._runQueryBtn).should(query);
|
||||||
|
}
|
||||||
|
|
||||||
public ReadQueryTableResponse(index: number, timeout = 100) {
|
public ReadQueryTableResponse(index: number, timeout = 100) {
|
||||||
//timeout can be sent higher values incase of larger tables
|
//timeout can be sent higher values incase of larger tables
|
||||||
this.agHelper.Sleep(timeout); //Settling time for table!
|
this.agHelper.Sleep(timeout); //Settling time for table!
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ import { TEMP_DATASOURCE_ID } from "constants/Datasource";
|
||||||
import LazyCodeEditor from "components/editorComponents/LazyCodeEditor";
|
import LazyCodeEditor from "components/editorComponents/LazyCodeEditor";
|
||||||
import { getCodeMirrorNamespaceFromEditor } from "utils/getCodeMirrorNamespace";
|
import { getCodeMirrorNamespaceFromEditor } from "utils/getCodeMirrorNamespace";
|
||||||
import { isDynamicValue } from "utils/DynamicBindingUtils";
|
import { isDynamicValue } from "utils/DynamicBindingUtils";
|
||||||
|
import { DEFAULT_DATASOURCE_NAME } from "constants/ApiEditorConstants/ApiEditorConstants";
|
||||||
|
|
||||||
type ReduxStateProps = {
|
type ReduxStateProps = {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
|
|
@ -527,7 +528,7 @@ class EmbeddedDatasourcePathComponent extends React.Component<
|
||||||
evaluatedValue={this.handleEvaluatedValue()}
|
evaluatedValue={this.handleEvaluatedValue()}
|
||||||
focusElementName={`${this.props.actionName}.url`}
|
focusElementName={`${this.props.actionName}.url`}
|
||||||
/>
|
/>
|
||||||
{datasource && datasource.name !== "DEFAULT_REST_DATASOURCE" && (
|
{datasource && datasource.name !== DEFAULT_DATASOURCE_NAME && (
|
||||||
<StyledTooltip
|
<StyledTooltip
|
||||||
id="custom-tooltip"
|
id="custom-tooltip"
|
||||||
width={this.state.highlightedElementWidth}
|
width={this.state.highlightedElementWidth}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ import {
|
||||||
|
|
||||||
const DEFAULT_METHOD_TYPE = HTTP_METHOD.GET;
|
const DEFAULT_METHOD_TYPE = HTTP_METHOD.GET;
|
||||||
|
|
||||||
|
export const DEFAULT_DATASOURCE_NAME = "DEFAULT_REST_DATASOURCE";
|
||||||
|
|
||||||
export const DEFAULT_API_ACTION_CONFIG: ApiActionConfig = {
|
export const DEFAULT_API_ACTION_CONFIG: ApiActionConfig = {
|
||||||
timeoutInMillisecond: DEFAULT_ACTION_TIMEOUT,
|
timeoutInMillisecond: DEFAULT_ACTION_TIMEOUT,
|
||||||
encodeParamsToggle: true,
|
encodeParamsToggle: true,
|
||||||
|
|
@ -30,7 +32,7 @@ export const DEFAULT_API_ACTION_CONFIG: ApiActionConfig = {
|
||||||
export const DEFAULT_CREATE_API_CONFIG = {
|
export const DEFAULT_CREATE_API_CONFIG = {
|
||||||
config: DEFAULT_API_ACTION_CONFIG,
|
config: DEFAULT_API_ACTION_CONFIG,
|
||||||
datasource: {
|
datasource: {
|
||||||
name: "DEFAULT_REST_DATASOURCE",
|
name: DEFAULT_DATASOURCE_NAME,
|
||||||
},
|
},
|
||||||
eventData: {
|
eventData: {
|
||||||
actionType: "API",
|
actionType: "API",
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,17 @@
|
||||||
import { PluginPackageName } from "entities/Action";
|
import { PluginPackageName, PluginName } from "entities/Action";
|
||||||
|
|
||||||
export const QUERY_BODY_FIELDS = [
|
export const QUERY_BODY_FIELDS = [
|
||||||
"actionConfiguration.body",
|
"actionConfiguration.body",
|
||||||
"actionConfiguration.formData.body.data",
|
"actionConfiguration.formData.body.data",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const SQL_DATASOURCES: Array<string> = [
|
||||||
|
PluginName.POSTGRES,
|
||||||
|
PluginName.MS_SQL,
|
||||||
|
PluginName.MY_SQL,
|
||||||
|
PluginName.ORACLE,
|
||||||
|
];
|
||||||
|
|
||||||
export const PLUGIN_PACKAGE_DBS = [
|
export const PLUGIN_PACKAGE_DBS = [
|
||||||
PluginPackageName.POSTGRES,
|
PluginPackageName.POSTGRES,
|
||||||
PluginPackageName.MONGO,
|
PluginPackageName.MONGO,
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,6 @@ export enum PluginType {
|
||||||
REMOTE = "REMOTE",
|
REMOTE = "REMOTE",
|
||||||
}
|
}
|
||||||
|
|
||||||
// more can be added subsequently.
|
|
||||||
export enum PluginName {
|
|
||||||
MONGO = "MongoDB",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum PluginPackageName {
|
export enum PluginPackageName {
|
||||||
POSTGRES = "postgres-plugin",
|
POSTGRES = "postgres-plugin",
|
||||||
MONGO = "mongo-plugin",
|
MONGO = "mongo-plugin",
|
||||||
|
|
@ -30,6 +25,17 @@ export enum PluginPackageName {
|
||||||
ORACLE = "oracle-plugin",
|
ORACLE = "oracle-plugin",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// more can be added subsequently.
|
||||||
|
export enum PluginName {
|
||||||
|
MONGO = "MongoDB",
|
||||||
|
POSTGRES = "PostgreSQL",
|
||||||
|
MY_SQL = "MySQL",
|
||||||
|
MS_SQL = "Microsoft SQL Server",
|
||||||
|
GOOGLE_SHEETS = "Google Sheets",
|
||||||
|
FIRESTORE = "Firestore",
|
||||||
|
ORACLE = "Oracle",
|
||||||
|
}
|
||||||
|
|
||||||
export enum PaginationType {
|
export enum PaginationType {
|
||||||
NONE = "NONE",
|
NONE = "NONE",
|
||||||
PAGE_NO = "PAGE_NO",
|
PAGE_NO = "PAGE_NO",
|
||||||
|
|
@ -110,6 +116,7 @@ export const isStoredDatasource = (val: any): val is StoredDatasource => {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
export interface StoredDatasource {
|
export interface StoredDatasource {
|
||||||
|
name?: string;
|
||||||
id: string;
|
id: string;
|
||||||
pluginId?: string;
|
pluginId?: string;
|
||||||
datasourceConfiguration?: { url?: string };
|
datasourceConfiguration?: { url?: string };
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ import SearchSnippets from "../../common/SearchSnippets";
|
||||||
import { DocsLink, openDoc } from "../../../constants/DocumentationLinks";
|
import { DocsLink, openDoc } from "../../../constants/DocumentationLinks";
|
||||||
import { getApiPaneConfigSelectedTabIndex } from "selectors/apiPaneSelectors";
|
import { getApiPaneConfigSelectedTabIndex } from "selectors/apiPaneSelectors";
|
||||||
import { noop } from "lodash";
|
import { noop } from "lodash";
|
||||||
|
import { DEFAULT_DATASOURCE_NAME } from "constants/ApiEditorConstants/ApiEditorConstants";
|
||||||
|
|
||||||
const Form = styled.form`
|
const Form = styled.form`
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
@ -554,6 +555,7 @@ function CommonEditorForm(props: CommonFormPropsWithExtraParams) {
|
||||||
(state: AppState) => state.entities.actions.map((action) => action.config),
|
(state: AppState) => state.entities.actions.map((action) => action.config),
|
||||||
equal,
|
equal,
|
||||||
);
|
);
|
||||||
|
|
||||||
const currentActionConfig: Action | undefined = actions.find(
|
const currentActionConfig: Action | undefined = actions.find(
|
||||||
(action) => action.id === params.apiId || action.id === params.queryId,
|
(action) => action.id === params.apiId || action.id === params.queryId,
|
||||||
);
|
);
|
||||||
|
|
@ -572,6 +574,20 @@ function CommonEditorForm(props: CommonFormPropsWithExtraParams) {
|
||||||
getPlugin(state, pluginId ?? ""),
|
getPlugin(state, pluginId ?? ""),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// this gets the url of the current action's datasource
|
||||||
|
const actionDatasourceUrl =
|
||||||
|
currentActionConfig?.datasource?.datasourceConfiguration?.url || "";
|
||||||
|
// this gets the name of the current action's datasource
|
||||||
|
const actionDatasourceName = currentActionConfig?.datasource.name || "";
|
||||||
|
|
||||||
|
// if the url is empty and the action's datasource name is the default datasource name (this means the api does not have a datasource attached)
|
||||||
|
// or the user does not have permission,
|
||||||
|
// we block action execution.
|
||||||
|
const blockExecution =
|
||||||
|
(!actionDatasourceUrl &&
|
||||||
|
actionDatasourceName === DEFAULT_DATASOURCE_NAME) ||
|
||||||
|
!isExecutePermitted;
|
||||||
|
|
||||||
// Debugger render flag
|
// Debugger render flag
|
||||||
const showDebugger = useSelector(showDebuggerFlag);
|
const showDebugger = useSelector(showDebuggerFlag);
|
||||||
|
|
||||||
|
|
@ -621,7 +637,7 @@ function CommonEditorForm(props: CommonFormPropsWithExtraParams) {
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
className="t--apiFormRunBtn"
|
className="t--apiFormRunBtn"
|
||||||
isDisabled={!isExecutePermitted}
|
isDisabled={blockExecution}
|
||||||
isLoading={isRunning}
|
isLoading={isRunning}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onRunClick();
|
onRunClick();
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@ import type { InjectedFormProps } from "redux-form";
|
||||||
import { Tag } from "@blueprintjs/core";
|
import { Tag } from "@blueprintjs/core";
|
||||||
import { isString, noop } from "lodash";
|
import { isString, noop } from "lodash";
|
||||||
import type { Datasource } from "entities/Datasource";
|
import type { Datasource } from "entities/Datasource";
|
||||||
import { getPluginImages } from "selectors/entitiesSelector";
|
import {
|
||||||
|
getPluginImages,
|
||||||
|
getPluginNameFromId,
|
||||||
|
} from "selectors/entitiesSelector";
|
||||||
import FormControl from "../FormControl";
|
import FormControl from "../FormControl";
|
||||||
import type { Action, QueryAction, SaaSAction } from "entities/Action";
|
import type { Action, QueryAction, SaaSAction } from "entities/Action";
|
||||||
import { SlashCommand } from "entities/Action";
|
import { SlashCommand } from "entities/Action";
|
||||||
|
|
@ -81,7 +84,7 @@ import { getErrorAsString } from "sagas/ActionExecution/errorUtils";
|
||||||
import type { UpdateActionPropertyActionPayload } from "actions/pluginActionActions";
|
import type { UpdateActionPropertyActionPayload } from "actions/pluginActionActions";
|
||||||
import Guide from "pages/Editor/GuidedTour/Guide";
|
import Guide from "pages/Editor/GuidedTour/Guide";
|
||||||
import { inGuidedTour } from "selectors/onboardingSelectors";
|
import { inGuidedTour } from "selectors/onboardingSelectors";
|
||||||
import { EDITOR_TABS } from "constants/QueryEditorConstants";
|
import { EDITOR_TABS, SQL_DATASOURCES } from "constants/QueryEditorConstants";
|
||||||
import type { FormEvalOutput } from "reducers/evaluationReducers/formEvaluationReducer";
|
import type { FormEvalOutput } from "reducers/evaluationReducers/formEvaluationReducer";
|
||||||
import { isValidFormConfig } from "reducers/evaluationReducers/formEvaluationReducer";
|
import { isValidFormConfig } from "reducers/evaluationReducers/formEvaluationReducer";
|
||||||
import {
|
import {
|
||||||
|
|
@ -426,6 +429,19 @@ export function EditorJSONtoForm(props: Props) {
|
||||||
userWorkspacePermissions,
|
userWorkspacePermissions,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// get the current action's plugin name
|
||||||
|
const currentActionPluginName = useSelector((state: AppState) =>
|
||||||
|
getPluginNameFromId(state, currentActionConfig?.pluginId || ""),
|
||||||
|
);
|
||||||
|
|
||||||
|
// this gets the url of the current action
|
||||||
|
const actionBody = currentActionConfig?.actionConfiguration?.body || "";
|
||||||
|
|
||||||
|
// if (the body is empty and the action is an sql datasource) or the user does not have permission, block action execution.
|
||||||
|
const blockExecution =
|
||||||
|
(!actionBody && SQL_DATASOURCES.includes(currentActionPluginName)) ||
|
||||||
|
!isExecutePermitted;
|
||||||
|
|
||||||
// Query is executed even once during the session, show the response data.
|
// Query is executed even once during the session, show the response data.
|
||||||
if (executedQueryData) {
|
if (executedQueryData) {
|
||||||
if (!executedQueryData.isExecutionSuccess) {
|
if (!executedQueryData.isExecutionSuccess) {
|
||||||
|
|
@ -912,7 +928,7 @@ export function EditorJSONtoForm(props: Props) {
|
||||||
<Button
|
<Button
|
||||||
className="t--run-query"
|
className="t--run-query"
|
||||||
data-guided-tour-iid="run-query"
|
data-guided-tour-iid="run-query"
|
||||||
isDisabled={!isExecutePermitted}
|
isDisabled={blockExecution}
|
||||||
isLoading={isRunning}
|
isLoading={isRunning}
|
||||||
onClick={onRunClick}
|
onClick={onRunClick}
|
||||||
size="md"
|
size="md"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user