feat: Abort Query Execution (#15775)
* Snaps response view to certain height and adds abort query execution feature * make raw string a constant * Add cypress tests * Remove theme variable * move raw strings to constants in messages.ts file * Fix test case description * Comment out query abort action execution * cy fix * Fix abortion of parallel action execution like onPageLoad Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
This commit is contained in:
parent
a5733da363
commit
0e36569b06
|
|
@ -0,0 +1,47 @@
|
||||||
|
const commonlocators = require("../../../../locators/commonlocators.json");
|
||||||
|
const queryLocators = require("../../../../locators/QueryEditor.json");
|
||||||
|
const datasource = require("../../../../locators/DatasourcesEditor.json");
|
||||||
|
const formControls = require("../../../../locators/FormControl.json");
|
||||||
|
|
||||||
|
const testApiUrl = "https://jsonplaceholder.typicode.com/photos";
|
||||||
|
|
||||||
|
const ERROR_ACTION_EXECUTE_FAIL = (actionName) =>
|
||||||
|
`${actionName} action returned an error response`;
|
||||||
|
|
||||||
|
describe("Abort Action Execution", function() {
|
||||||
|
it("Cancel Request button should abort API action execution", function() {
|
||||||
|
cy.createAndFillApi(testApiUrl, "");
|
||||||
|
cy.RunAPIWithoutWaitingForResolution();
|
||||||
|
cy.get(commonlocators.cancelActionExecution).click();
|
||||||
|
cy.VerifyErrorMsgPresence(ERROR_ACTION_EXECUTE_FAIL("Api1"));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Queries were resolving quicker than we could cancel them
|
||||||
|
// Commenting this out till we can find a query that resolves slow enough for us to cancel its execution.
|
||||||
|
|
||||||
|
// it("Cancel Request button should abort Query action execution", function() {
|
||||||
|
// cy.NavigateToDatasourceEditor();
|
||||||
|
// cy.get(datasource.MongoDB).click();
|
||||||
|
// cy.fillMongoDatasourceForm();
|
||||||
|
// cy.testSaveDatasource();
|
||||||
|
// cy.get("@createDatasource").then(
|
||||||
|
// (httpResponse) => httpResponse.response.body.data.name,
|
||||||
|
// );
|
||||||
|
// cy.NavigateToQueryEditor();
|
||||||
|
// cy.NavigateToActiveTab();
|
||||||
|
// cy.get(queryLocators.createQuery)
|
||||||
|
// .last()
|
||||||
|
// .click();
|
||||||
|
// cy.get(queryLocators.queryNameField).type("AbortQuery");
|
||||||
|
// cy.ValidateAndSelectDropdownOption(
|
||||||
|
// formControls.commandDropdown,
|
||||||
|
// "Find Document(s)",
|
||||||
|
// );
|
||||||
|
|
||||||
|
// cy.typeValueNValidate("friends", formControls.mongoCollection);
|
||||||
|
// cy.typeValueNValidate("300", formControls.mongoFindLimit);
|
||||||
|
// cy.RunQueryWithoutWaitingForResolution();
|
||||||
|
// cy.get(commonlocators.cancelActionExecution).click();
|
||||||
|
// cy.VerifyErrorMsgPresence(ERROR_ACTION_EXECUTE_FAIL("AbortQuery"));
|
||||||
|
// });
|
||||||
|
});
|
||||||
|
|
@ -183,5 +183,6 @@
|
||||||
"selectThemeBackBtn": ".t--theme-select-back-btn",
|
"selectThemeBackBtn": ".t--theme-select-back-btn",
|
||||||
"themeAppBorderRadiusBtn": ".t--theme-appBorderRadius",
|
"themeAppBorderRadiusBtn": ".t--theme-appBorderRadius",
|
||||||
"codeEditorWrapper": ".unfocused-code-editor",
|
"codeEditorWrapper": ".unfocused-code-editor",
|
||||||
"textWidgetContainer": ".t--text-widget-container"
|
"textWidgetContainer": ".t--text-widget-container",
|
||||||
}
|
"cancelActionExecution": ".t--cancel-action-button"
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,10 @@ Cypress.Commands.add("RunAPI", () => {
|
||||||
cy.wait("@postExecute");
|
cy.wait("@postExecute");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add("RunAPIWithoutWaitingForResolution", () => {
|
||||||
|
cy.get(ApiEditor.ApiRunBtn).click({ force: true });
|
||||||
|
});
|
||||||
|
|
||||||
Cypress.Commands.add("SaveAndRunAPI", () => {
|
Cypress.Commands.add("SaveAndRunAPI", () => {
|
||||||
cy.WaitAutoSave();
|
cy.WaitAutoSave();
|
||||||
cy.RunAPI();
|
cy.RunAPI();
|
||||||
|
|
|
||||||
|
|
@ -1536,6 +1536,17 @@ Cypress.Commands.add("VerifyErrorMsgAbsence", (errorMsgToVerifyAbsence) => {
|
||||||
).should("not.exist");
|
).should("not.exist");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add("VerifyErrorMsgPresence", (errorMsgToVerifyAbsence) => {
|
||||||
|
// Give this element 10 seconds to appear
|
||||||
|
//cy.wait(10000)
|
||||||
|
cy.xpath(
|
||||||
|
"//div[@class='Toastify']//span[contains(text(),'" +
|
||||||
|
errorMsgToVerifyAbsence +
|
||||||
|
"')]",
|
||||||
|
{ timeout: 0 },
|
||||||
|
).should("exist");
|
||||||
|
});
|
||||||
|
|
||||||
Cypress.Commands.add("setQueryTimeout", (timeout) => {
|
Cypress.Commands.add("setQueryTimeout", (timeout) => {
|
||||||
cy.get(queryLocators.settings).click();
|
cy.get(queryLocators.settings).click();
|
||||||
cy.xpath(queryLocators.queryTimeout)
|
cy.xpath(queryLocators.queryTimeout)
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,12 @@ Cypress.Commands.add("onlyQueryRun", () => {
|
||||||
.wait(1000);
|
.wait(1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add("RunQueryWithoutWaitingForResolution", () => {
|
||||||
|
cy.xpath(queryEditor.runQuery)
|
||||||
|
.last()
|
||||||
|
.click({ force: true });
|
||||||
|
});
|
||||||
|
|
||||||
Cypress.Commands.add("hoverAndClick", () => {
|
Cypress.Commands.add("hoverAndClick", () => {
|
||||||
cy.xpath(apiwidget.popover)
|
cy.xpath(apiwidget.popover)
|
||||||
.last()
|
.last()
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,7 @@ class ActionAPI extends API {
|
||||||
static url = "v1/actions";
|
static url = "v1/actions";
|
||||||
static apiUpdateCancelTokenSource: CancelTokenSource;
|
static apiUpdateCancelTokenSource: CancelTokenSource;
|
||||||
static queryUpdateCancelTokenSource: CancelTokenSource;
|
static queryUpdateCancelTokenSource: CancelTokenSource;
|
||||||
|
static abortActionExecutionTokenSource: CancelTokenSource;
|
||||||
|
|
||||||
static createAction(
|
static createAction(
|
||||||
apiConfig: Partial<Action>,
|
apiConfig: Partial<Action>,
|
||||||
|
|
@ -169,12 +170,14 @@ class ActionAPI extends API {
|
||||||
executeAction: FormData,
|
executeAction: FormData,
|
||||||
timeout?: number,
|
timeout?: number,
|
||||||
): AxiosPromise<ActionExecutionResponse> {
|
): AxiosPromise<ActionExecutionResponse> {
|
||||||
|
ActionAPI.abortActionExecutionTokenSource = axios.CancelToken.source();
|
||||||
return API.post(ActionAPI.url + "/execute", executeAction, undefined, {
|
return API.post(ActionAPI.url + "/execute", executeAction, undefined, {
|
||||||
timeout: timeout || DEFAULT_EXECUTE_ACTION_TIMEOUT_MS,
|
timeout: timeout || DEFAULT_EXECUTE_ACTION_TIMEOUT_MS,
|
||||||
headers: {
|
headers: {
|
||||||
accept: "application/json",
|
accept: "application/json",
|
||||||
"Content-Type": "multipart/form-data",
|
"Content-Type": "multipart/form-data",
|
||||||
},
|
},
|
||||||
|
cancelToken: ActionAPI.abortActionExecutionTokenSource.token,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -254,6 +254,16 @@ export const OAUTH_2_0 = () => "OAuth 2.0";
|
||||||
export const ENABLE = () => "ENABLE";
|
export const ENABLE = () => "ENABLE";
|
||||||
export const UPGRADE = () => "UPGRADE";
|
export const UPGRADE = () => "UPGRADE";
|
||||||
export const EDIT = () => "EDIT";
|
export const EDIT = () => "EDIT";
|
||||||
|
export const UNEXPECTED_ERROR = () => "An unexpected error occurred";
|
||||||
|
export const EXPECTED_ERROR = () => "An error occurred";
|
||||||
|
export const NO_DATASOURCE_FOR_QUERY = () =>
|
||||||
|
`Seems like you don’t have any Datasources to create a query`;
|
||||||
|
export const ACTION_EDITOR_REFRESH = () => "Refresh";
|
||||||
|
export const INVALID_FORM_CONFIGURATION = () => "Invalid form configuration";
|
||||||
|
export const ACTION_RUN_BUTTON_MESSAGE_FIRST_HALF = () => "🙌 Click on";
|
||||||
|
export const ACTION_RUN_BUTTON_MESSAGE_SECOND_HALF = () =>
|
||||||
|
"after adding your query";
|
||||||
|
export const CREATE_NEW_DATASOURCE = () => "Create new datasource";
|
||||||
|
|
||||||
export const ERROR_EVAL_ERROR_GENERIC = () =>
|
export const ERROR_EVAL_ERROR_GENERIC = () =>
|
||||||
`Unexpected error occurred while evaluating the application`;
|
`Unexpected error occurred while evaluating the application`;
|
||||||
|
|
@ -913,6 +923,8 @@ export const API_EDITOR_TAB_TITLES = {
|
||||||
AUTHENTICATION: () => "Authentication",
|
AUTHENTICATION: () => "Authentication",
|
||||||
SETTINGS: () => "Settings",
|
SETTINGS: () => "Settings",
|
||||||
};
|
};
|
||||||
|
export const ACTION_EXECUTION_MESSAGE = (actionType: string) =>
|
||||||
|
`Sending the ${actionType} request`;
|
||||||
|
|
||||||
export const WELCOME_FORM_HEADER = () => "Let us get to know you better!";
|
export const WELCOME_FORM_HEADER = () => "Let us get to know you better!";
|
||||||
export const WELCOME_FORM_FULL_NAME = () => "Full Name";
|
export const WELCOME_FORM_FULL_NAME = () => "Full Name";
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import {
|
||||||
EMPTY_RESPONSE_FIRST_HALF,
|
EMPTY_RESPONSE_FIRST_HALF,
|
||||||
EMPTY_RESPONSE_LAST_HALF,
|
EMPTY_RESPONSE_LAST_HALF,
|
||||||
INSPECT_ENTITY,
|
INSPECT_ENTITY,
|
||||||
|
ACTION_EXECUTION_MESSAGE,
|
||||||
} from "@appsmith/constants/messages";
|
} from "@appsmith/constants/messages";
|
||||||
import { Text, TextType } from "design-system";
|
import { Text, TextType } from "design-system";
|
||||||
import { Text as BlueprintText } from "@blueprintjs/core";
|
import { Text as BlueprintText } from "@blueprintjs/core";
|
||||||
|
|
@ -32,7 +33,7 @@ import Resizer, { ResizerCSS } from "./Debugger/Resizer";
|
||||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||||
import { DebugButton } from "./Debugger/DebugCTA";
|
import { DebugButton } from "./Debugger/DebugCTA";
|
||||||
import EntityDeps from "./Debugger/EntityDependecies";
|
import EntityDeps from "./Debugger/EntityDependecies";
|
||||||
import Button, { Size } from "components/ads/Button";
|
import Button, { Size, Category } from "components/ads/Button";
|
||||||
import EntityBottomTabs from "./EntityBottomTabs";
|
import EntityBottomTabs from "./EntityBottomTabs";
|
||||||
import { DEBUGGER_TAB_KEYS } from "./Debugger/helpers";
|
import { DEBUGGER_TAB_KEYS } from "./Debugger/helpers";
|
||||||
import { setCurrentTab } from "actions/debuggerActions";
|
import { setCurrentTab } from "actions/debuggerActions";
|
||||||
|
|
@ -43,6 +44,7 @@ import {
|
||||||
UpdateActionPropertyActionPayload,
|
UpdateActionPropertyActionPayload,
|
||||||
} from "actions/pluginActionActions";
|
} from "actions/pluginActionActions";
|
||||||
import { isHtml } from "./utils";
|
import { isHtml } from "./utils";
|
||||||
|
import ActionAPI from "api/ActionAPI";
|
||||||
|
|
||||||
type TextStyleProps = {
|
type TextStyleProps = {
|
||||||
accent: "primary" | "secondary" | "error";
|
accent: "primary" | "secondary" | "error";
|
||||||
|
|
@ -105,7 +107,7 @@ const TabbedViewWrapper = styled.div`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const SectionDivider = styled.div`
|
export const SectionDivider = styled.div`
|
||||||
height: 1px;
|
height: 1px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: ${(props) => props.theme.colors.apiPane.dividerBg};
|
background: ${(props) => props.theme.colors.apiPane.dividerBg};
|
||||||
|
|
@ -174,6 +176,23 @@ const ResponseBodyContainer = styled.div`
|
||||||
display: grid;
|
display: grid;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const CancelRequestButton = styled(Button)`
|
||||||
|
margin-top: 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const LoadingOverlayContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background-color: transparent;
|
||||||
|
position: relative;
|
||||||
|
z-index: 20;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin-top: 5px;
|
||||||
|
`;
|
||||||
|
|
||||||
interface ReduxStateProps {
|
interface ReduxStateProps {
|
||||||
responses: Record<string, ActionResponse | undefined>;
|
responses: Record<string, ActionResponse | undefined>;
|
||||||
isRunning: Record<string, boolean>;
|
isRunning: Record<string, boolean>;
|
||||||
|
|
@ -237,6 +256,8 @@ const ResponseDataContainer = styled.div`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const TableCellHeight = 39;
|
export const TableCellHeight = 39;
|
||||||
|
// When action execution is triggered, open response container to height specified by this variable.
|
||||||
|
export const ActionExecutionResizerHeight = 307;
|
||||||
|
|
||||||
export const responseTabComponent = (
|
export const responseTabComponent = (
|
||||||
responseType: string,
|
responseType: string,
|
||||||
|
|
@ -271,6 +292,10 @@ export const responseTabComponent = (
|
||||||
}[responseType];
|
}[responseType];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const handleCancelActionExecution = () => {
|
||||||
|
ActionAPI.abortActionExecutionTokenSource.cancel();
|
||||||
|
};
|
||||||
|
|
||||||
function ApiResponseView(props: Props) {
|
function ApiResponseView(props: Props) {
|
||||||
const {
|
const {
|
||||||
match: {
|
match: {
|
||||||
|
|
@ -506,17 +531,37 @@ function ApiResponseView(props: Props) {
|
||||||
return (
|
return (
|
||||||
<ResponseContainer ref={panelRef}>
|
<ResponseContainer ref={panelRef}>
|
||||||
<Resizer
|
<Resizer
|
||||||
|
openResizer={isRunning}
|
||||||
panelRef={panelRef}
|
panelRef={panelRef}
|
||||||
setContainerDimensions={(height: number) =>
|
setContainerDimensions={(height: number) =>
|
||||||
// TableCellHeight in this case is the height of one table cell in pixels.
|
// TableCellHeight in this case is the height of one table cell in pixels.
|
||||||
setTableBodyHeightHeight(height - TableCellHeight)
|
setTableBodyHeightHeight(height - TableCellHeight)
|
||||||
}
|
}
|
||||||
|
snapToHeight={ActionExecutionResizerHeight}
|
||||||
/>
|
/>
|
||||||
<SectionDivider />
|
<SectionDivider />
|
||||||
{isRunning && (
|
{isRunning && (
|
||||||
<LoadingOverlayScreen theme={props.theme}>
|
<>
|
||||||
Sending Request
|
<LoadingOverlayScreen theme={props.theme} />
|
||||||
</LoadingOverlayScreen>
|
<LoadingOverlayContainer>
|
||||||
|
<div>
|
||||||
|
<Text textAlign={"center"} type={TextType.P1}>
|
||||||
|
{createMessage(ACTION_EXECUTION_MESSAGE, "API")}
|
||||||
|
</Text>
|
||||||
|
<CancelRequestButton
|
||||||
|
category={Category.tertiary}
|
||||||
|
className={`t--cancel-action-button`}
|
||||||
|
onClick={() => {
|
||||||
|
handleCancelActionExecution();
|
||||||
|
}}
|
||||||
|
size={Size.medium}
|
||||||
|
tag="button"
|
||||||
|
text="Cancel Request"
|
||||||
|
type="button"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</LoadingOverlayContainer>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
<TabbedViewWrapper>
|
<TabbedViewWrapper>
|
||||||
{response.statusCode && (
|
{response.statusCode && (
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ const Top = styled.div`
|
||||||
type ResizerProps = {
|
type ResizerProps = {
|
||||||
panelRef: RefObject<HTMLDivElement>;
|
panelRef: RefObject<HTMLDivElement>;
|
||||||
setContainerDimensions?: (height: number) => void;
|
setContainerDimensions?: (height: number) => void;
|
||||||
|
snapToHeight?: number;
|
||||||
|
openResizer?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
function Resizer(props: ResizerProps) {
|
function Resizer(props: ResizerProps) {
|
||||||
|
|
@ -51,6 +53,23 @@ function Resizer(props: ResizerProps) {
|
||||||
handleResize(0);
|
handleResize(0);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// if the resizer is configured to open and the user is not actively controlling it
|
||||||
|
// snap the resizer to a specific height as specified by the snapToHeight prop.
|
||||||
|
if (props.openResizer && !mouseDown) {
|
||||||
|
const panel = props.panelRef.current;
|
||||||
|
if (!panel) return;
|
||||||
|
|
||||||
|
const { height } = panel.getBoundingClientRect();
|
||||||
|
|
||||||
|
if (props?.snapToHeight && height < props?.snapToHeight) {
|
||||||
|
panel.style.height = `${props?.snapToHeight}px`;
|
||||||
|
props.setContainerDimensions &&
|
||||||
|
props.setContainerDimensions(props?.snapToHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [props?.openResizer]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleMouseMove = (e: MouseEvent) => {
|
const handleMouseMove = (e: MouseEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
|
||||||
|
|
@ -56,12 +56,21 @@ import {
|
||||||
DOCUMENTATION,
|
DOCUMENTATION,
|
||||||
DOCUMENTATION_TOOLTIP,
|
DOCUMENTATION_TOOLTIP,
|
||||||
INSPECT_ENTITY,
|
INSPECT_ENTITY,
|
||||||
|
ACTION_EXECUTION_MESSAGE,
|
||||||
|
UNEXPECTED_ERROR,
|
||||||
|
NO_DATASOURCE_FOR_QUERY,
|
||||||
|
ACTION_EDITOR_REFRESH,
|
||||||
|
EXPECTED_ERROR,
|
||||||
|
INVALID_FORM_CONFIGURATION,
|
||||||
|
ACTION_RUN_BUTTON_MESSAGE_FIRST_HALF,
|
||||||
|
ACTION_RUN_BUTTON_MESSAGE_SECOND_HALF,
|
||||||
|
CREATE_NEW_DATASOURCE,
|
||||||
} from "@appsmith/constants/messages";
|
} from "@appsmith/constants/messages";
|
||||||
import { useParams } from "react-router";
|
import { useParams } from "react-router";
|
||||||
import { AppState } from "reducers";
|
import { AppState } from "reducers";
|
||||||
import { ExplorerURLParams } from "../Explorer/helpers";
|
import { ExplorerURLParams } from "../Explorer/helpers";
|
||||||
import MoreActionsMenu from "../Explorer/Actions/MoreActionsMenu";
|
import MoreActionsMenu from "../Explorer/Actions/MoreActionsMenu";
|
||||||
import Button, { Size } from "components/ads/Button";
|
import Button, { Size, Category } from "components/ads/Button";
|
||||||
import { thinScrollbar } from "constants/DefaultTheme";
|
import { thinScrollbar } from "constants/DefaultTheme";
|
||||||
import ActionRightPane, {
|
import ActionRightPane, {
|
||||||
useEntityDependencies,
|
useEntityDependencies,
|
||||||
|
|
@ -90,7 +99,14 @@ import {
|
||||||
responseTabComponent,
|
responseTabComponent,
|
||||||
InlineButton,
|
InlineButton,
|
||||||
TableCellHeight,
|
TableCellHeight,
|
||||||
|
SectionDivider,
|
||||||
|
CancelRequestButton,
|
||||||
|
LoadingOverlayContainer,
|
||||||
|
handleCancelActionExecution,
|
||||||
|
ActionExecutionResizerHeight,
|
||||||
} from "components/editorComponents/ApiResponseView";
|
} from "components/editorComponents/ApiResponseView";
|
||||||
|
import LoadingOverlayScreen from "components/editorComponents/LoadingOverlayScreen";
|
||||||
|
import { EditorTheme } from "components/editorComponents/CodeEditor/EditorConfig";
|
||||||
|
|
||||||
const QueryFormContainer = styled.form`
|
const QueryFormContainer = styled.form`
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
@ -517,7 +533,7 @@ export function EditorJSONtoForm(props: Props) {
|
||||||
<components.MenuList {...props}>{props.children}</components.MenuList>
|
<components.MenuList {...props}>{props.children}</components.MenuList>
|
||||||
<CreateDatasource onClick={() => onCreateDatasourceClick()}>
|
<CreateDatasource onClick={() => onCreateDatasourceClick()}>
|
||||||
<Icon className="createIcon" icon="plus" iconSize={11} />
|
<Icon className="createIcon" icon="plus" iconSize={11} />
|
||||||
Create new datasource
|
{createMessage(CREATE_NEW_DATASOURCE)}
|
||||||
</CreateDatasource>
|
</CreateDatasource>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
@ -594,7 +610,9 @@ export function EditorJSONtoForm(props: Props) {
|
||||||
Sentry.captureException(e);
|
Sentry.captureException(e);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ErrorMessage>Invalid form configuration</ErrorMessage>
|
<ErrorMessage>
|
||||||
|
{createMessage(INVALID_FORM_CONFIGURATION)}
|
||||||
|
</ErrorMessage>
|
||||||
<Tag
|
<Tag
|
||||||
intent="warning"
|
intent="warning"
|
||||||
interactive
|
interactive
|
||||||
|
|
@ -602,7 +620,7 @@ export function EditorJSONtoForm(props: Props) {
|
||||||
onClick={() => window.location.reload()}
|
onClick={() => window.location.reload()}
|
||||||
round
|
round
|
||||||
>
|
>
|
||||||
Refresh
|
{createMessage(ACTION_EDITOR_REFRESH)}
|
||||||
</Tag>
|
</Tag>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
@ -753,7 +771,7 @@ export function EditorJSONtoForm(props: Props) {
|
||||||
<ErrorContainer>
|
<ErrorContainer>
|
||||||
<AdsIcon keepColors name="warning-triangle" />
|
<AdsIcon keepColors name="warning-triangle" />
|
||||||
<Text style={{ color: "#F22B2B" }} type={TextType.H3}>
|
<Text style={{ color: "#F22B2B" }} type={TextType.H3}>
|
||||||
An error occurred
|
{createMessage(EXPECTED_ERROR)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<ErrorDescriptionText
|
<ErrorDescriptionText
|
||||||
|
|
@ -804,7 +822,7 @@ export function EditorJSONtoForm(props: Props) {
|
||||||
<NoResponseContainer>
|
<NoResponseContainer>
|
||||||
<AdsIcon name="no-response" />
|
<AdsIcon name="no-response" />
|
||||||
<Text type={TextType.P1}>
|
<Text type={TextType.P1}>
|
||||||
🙌 Click on
|
{createMessage(ACTION_RUN_BUTTON_MESSAGE_FIRST_HALF)}
|
||||||
<InlineButton
|
<InlineButton
|
||||||
isLoading={isRunning}
|
isLoading={isRunning}
|
||||||
onClick={responeTabOnRunClick}
|
onClick={responeTabOnRunClick}
|
||||||
|
|
@ -813,7 +831,7 @@ export function EditorJSONtoForm(props: Props) {
|
||||||
text="Run"
|
text="Run"
|
||||||
type="button"
|
type="button"
|
||||||
/>
|
/>
|
||||||
after adding your query
|
{createMessage(ACTION_RUN_BUTTON_MESSAGE_SECOND_HALF)}
|
||||||
</Text>
|
</Text>
|
||||||
</NoResponseContainer>
|
</NoResponseContainer>
|
||||||
)}
|
)}
|
||||||
|
|
@ -953,7 +971,7 @@ export function EditorJSONtoForm(props: Props) {
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<ErrorMessage>
|
<ErrorMessage>
|
||||||
An unexpected error occurred
|
{createMessage(UNEXPECTED_ERROR)}
|
||||||
</ErrorMessage>
|
</ErrorMessage>
|
||||||
<Tag
|
<Tag
|
||||||
intent="warning"
|
intent="warning"
|
||||||
|
|
@ -962,15 +980,14 @@ export function EditorJSONtoForm(props: Props) {
|
||||||
onClick={() => window.location.reload()}
|
onClick={() => window.location.reload()}
|
||||||
round
|
round
|
||||||
>
|
>
|
||||||
Refresh
|
{createMessage(ACTION_EDITOR_REFRESH)}
|
||||||
</Tag>
|
</Tag>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{dataSources.length === 0 && (
|
{dataSources.length === 0 && (
|
||||||
<NoDataSourceContainer>
|
<NoDataSourceContainer>
|
||||||
<p className="font18">
|
<p className="font18">
|
||||||
Seems like you don’t have any Datasources to
|
{createMessage(NO_DATASOURCE_FOR_QUERY)}
|
||||||
create a query
|
|
||||||
</p>
|
</p>
|
||||||
<EditorButton
|
<EditorButton
|
||||||
filled
|
filled
|
||||||
|
|
@ -1003,12 +1020,39 @@ export function EditorJSONtoForm(props: Props) {
|
||||||
|
|
||||||
<TabbedViewContainer ref={panelRef}>
|
<TabbedViewContainer ref={panelRef}>
|
||||||
<Resizable
|
<Resizable
|
||||||
|
openResizer={isRunning}
|
||||||
panelRef={panelRef}
|
panelRef={panelRef}
|
||||||
setContainerDimensions={(height: number) =>
|
setContainerDimensions={(height: number) =>
|
||||||
// TableCellHeight in this case is the height of one table cell in pixels.
|
// TableCellHeight in this case is the height of one table cell in pixels.
|
||||||
setTableBodyHeightHeight(height - TableCellHeight)
|
setTableBodyHeightHeight(height - TableCellHeight)
|
||||||
}
|
}
|
||||||
|
snapToHeight={ActionExecutionResizerHeight}
|
||||||
/>
|
/>
|
||||||
|
<SectionDivider />
|
||||||
|
{isRunning && (
|
||||||
|
<>
|
||||||
|
<LoadingOverlayScreen theme={EditorTheme.LIGHT} />
|
||||||
|
<LoadingOverlayContainer>
|
||||||
|
<div>
|
||||||
|
<Text textAlign={"center"} type={TextType.P1}>
|
||||||
|
{createMessage(ACTION_EXECUTION_MESSAGE, "Query")}
|
||||||
|
</Text>
|
||||||
|
<CancelRequestButton
|
||||||
|
category={Category.tertiary}
|
||||||
|
className={`t--cancel-action-button`}
|
||||||
|
onClick={() => {
|
||||||
|
handleCancelActionExecution();
|
||||||
|
}}
|
||||||
|
size={Size.medium}
|
||||||
|
tag="button"
|
||||||
|
text="Cancel Request"
|
||||||
|
type="button"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</LoadingOverlayContainer>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{output && !!output.length && (
|
{output && !!output.length && (
|
||||||
<ResultsCount>
|
<ResultsCount>
|
||||||
<Text type={TextType.P3}>
|
<Text type={TextType.P3}>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user