fix: API Editor bug fixes (#8803)
* * Confirmation modal fixes * * header overflow fixed, API editor * * Delete truncate issue fix * Tabs count UI fix * * Removed hardcoded text from component and added in messages * * removed hardcoded size * * fixed scroll issue in appviewer * * eval field fixes * * design fix for key in API pane * * fixed test cases
This commit is contained in:
parent
2e2e0d1d51
commit
55df317211
|
|
@ -32,7 +32,7 @@ describe("Confirm run action", function() {
|
|||
|
||||
cy.get(queryEditor.runQuery).click();
|
||||
cy.get(".bp3-dialog")
|
||||
.find(".bp3-button")
|
||||
.find("button")
|
||||
.contains("Confirm")
|
||||
.click();
|
||||
cy.wait("@postExecute").should(
|
||||
|
|
|
|||
|
|
@ -90,11 +90,14 @@ export const TabTitle = styled.span`
|
|||
export const TabCount = styled.div`
|
||||
background-color: ${(props) => props.theme.colors.tabs.countBg};
|
||||
border-radius: 8px;
|
||||
width: 17px;
|
||||
min-width: 17px;
|
||||
height: 17px;
|
||||
font-size: 9px;
|
||||
line-height: 14px;
|
||||
margin-left: 2px;
|
||||
margin-left: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 2px;
|
||||
`;
|
||||
|
||||
const TabTitleWrapper = styled.div<{
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ const ContentWrapper = styled.div<{ colorTheme: EditorTheme }>`
|
|||
|
||||
const CurrentValueWrapper = styled.div<{ colorTheme: EditorTheme }>`
|
||||
max-height: 300px;
|
||||
min-height: 1rem;
|
||||
min-height: 28px;
|
||||
overflow-y: auto;
|
||||
-ms-overflow-style: none;
|
||||
padding: ${(props) => props.theme.spaces[3]}px;
|
||||
|
|
@ -101,6 +101,7 @@ const CopyIconWrapper = styled(Button)<{ colorTheme: EditorTheme }>`
|
|||
top: 0;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
`;
|
||||
|
||||
const CodeWrapper = styled.pre<{ colorTheme: EditorTheme }>`
|
||||
|
|
|
|||
|
|
@ -120,10 +120,7 @@ export const EditorWrapper = styled.div<{
|
|||
return Colors.GREY_5;
|
||||
}
|
||||
}};
|
||||
background: ${(props) =>
|
||||
props.isFocused
|
||||
? props.theme.colors.apiPane.requestTree.header.bg
|
||||
: props.theme.colors.apiPane.bg};
|
||||
background: ${(props) => props.theme.colors.apiPane.bg};
|
||||
color: ${Colors.CHARCOAL};
|
||||
& {
|
||||
span.cm-operator {
|
||||
|
|
|
|||
|
|
@ -18,9 +18,11 @@ import DynamicDropdownField from "./DynamicDropdownField";
|
|||
import {
|
||||
DEFAULT_MULTI_PART_DROPDOWN_PLACEHOLDER,
|
||||
DEFAULT_MULTI_PART_DROPDOWN_WIDTH,
|
||||
DEFAULT_MULTI_PART_DROPDOWN_HEIGHT,
|
||||
MULTI_PART_DROPDOWN_OPTIONS,
|
||||
} from "constants/ApiEditorConstants";
|
||||
import { Colors } from "constants/Colors";
|
||||
import { Classes as BlueprintClasses } from "@blueprintjs/core";
|
||||
|
||||
type CustomStack = {
|
||||
removeTopPadding?: boolean;
|
||||
|
|
@ -107,12 +109,18 @@ const FlexContainer = styled.div`
|
|||
const DynamicTextFieldWithDropdownWrapper = styled.div`
|
||||
display: flex;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
|
||||
&
|
||||
.${BlueprintClasses.POPOVER_TARGET},
|
||||
&
|
||||
.${BlueprintClasses.POPOVER_TARGET}
|
||||
> div {
|
||||
height: 100%;
|
||||
}
|
||||
`;
|
||||
|
||||
const DynamicDropdownFieldWrapper = styled.div`
|
||||
position: relative;
|
||||
top: 1px;
|
||||
margin-left: 5px;
|
||||
`;
|
||||
|
||||
|
|
@ -176,7 +184,6 @@ function KeyValueRow(props: Props & WrappedFieldArrayProps) {
|
|||
className={`t--${field}.key.${index}`}
|
||||
dataTreePath={`${props.dataTreePath}[${index}].key`}
|
||||
expected={expected}
|
||||
height="36px"
|
||||
hoverInteraction
|
||||
name={`${field}.key`}
|
||||
placeholder={`Key ${index + 1}`}
|
||||
|
|
@ -185,7 +192,7 @@ function KeyValueRow(props: Props & WrappedFieldArrayProps) {
|
|||
|
||||
<DynamicDropdownFieldWrapper>
|
||||
<DynamicDropdownField
|
||||
height="36px"
|
||||
height={DEFAULT_MULTI_PART_DROPDOWN_HEIGHT}
|
||||
name={`${field}.type`}
|
||||
options={MULTI_PART_DROPDOWN_OPTIONS}
|
||||
placeholder={DEFAULT_MULTI_PART_DROPDOWN_PLACEHOLDER}
|
||||
|
|
@ -199,7 +206,6 @@ function KeyValueRow(props: Props & WrappedFieldArrayProps) {
|
|||
className={`t--${field}.key.${index}`}
|
||||
dataTreePath={`${props.dataTreePath}[${index}].key`}
|
||||
expected={expected}
|
||||
height="36px"
|
||||
hoverInteraction
|
||||
name={`${field}.key`}
|
||||
placeholder={`Key ${index + 1}`}
|
||||
|
|
@ -215,7 +221,6 @@ function KeyValueRow(props: Props & WrappedFieldArrayProps) {
|
|||
className={`t--${field}.value.${index}`}
|
||||
dataTreePath={`${props.dataTreePath}[${index}].value`}
|
||||
expected={expected}
|
||||
height="36px"
|
||||
hoverInteraction
|
||||
name={`${field}.value`}
|
||||
placeholder={`Value ${index + 1}`}
|
||||
|
|
@ -236,7 +241,6 @@ function KeyValueRow(props: Props & WrappedFieldArrayProps) {
|
|||
)
|
||||
}
|
||||
expected={expected}
|
||||
height="36px"
|
||||
name={`${field}.value`}
|
||||
placeholder={
|
||||
props.placeholder
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ const StyledDynamicTextField = styled(DynamicTextField)`
|
|||
background-color: ${Colors.WHITE};
|
||||
}
|
||||
.CodeEditorTarget .CodeMirror.CodeMirror-wrap:hover {
|
||||
background-color: inherit;
|
||||
background-color: ${Colors.ALABASTER_ALT};
|
||||
}
|
||||
&&& .t--code-editor-wrapper {
|
||||
border: none;
|
||||
|
|
|
|||
|
|
@ -97,4 +97,5 @@ export const MULTI_PART_DROPDOWN_OPTIONS: MULTI_PART_DROPDOWN_OPTION[] = [
|
|||
];
|
||||
|
||||
export const DEFAULT_MULTI_PART_DROPDOWN_WIDTH = "77px";
|
||||
export const DEFAULT_MULTI_PART_DROPDOWN_HEIGHT = "100%";
|
||||
export const DEFAULT_MULTI_PART_DROPDOWN_PLACEHOLDER = "Type";
|
||||
|
|
|
|||
|
|
@ -2574,7 +2574,7 @@ export const light: ColorType = {
|
|||
border: "#E0DEDE",
|
||||
},
|
||||
apiPane: {
|
||||
bg: lightShades[0],
|
||||
bg: lightShades[11],
|
||||
tabBg: lightShades[11],
|
||||
text: lightShades[16],
|
||||
dividerBg: lightShades[13],
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ export const ReduxActionTypes = {
|
|||
LOAD_QUERY_RESPONSE: "LOAD_QUERY_RESPONSE",
|
||||
RUN_ACTION_SHORTCUT_REQUEST: "RUN_ACTION_SHORTCUT_REQUEST",
|
||||
RUN_ACTION_REQUEST: "RUN_ACTION_REQUEST",
|
||||
RUN_ACTION_CANCELLED: "RUN_ACTION_CANCELLED",
|
||||
RUN_ACTION_SUCCESS: "RUN_ACTION_SUCCESS",
|
||||
CLEAR_ACTION_RESPONSE: "CLEAR_ACTION_RESPONSE",
|
||||
INIT_API_PANE: "INIT_API_PANE",
|
||||
|
|
|
|||
|
|
@ -812,3 +812,5 @@ export const WELCOME_FORM_NON_SUPER_USER_ROLE_DROPDOWN = () =>
|
|||
export const WELCOME_FORM_NON_SUPER_USER_ROLE = () => "Role";
|
||||
export const WELCOME_FORM_NON_SUPER_USER_USE_CASE = () =>
|
||||
"What are you planning to use Appsmith for?";
|
||||
export const QUERY_CONFIRMATION_MODAL_MESSAGE = () =>
|
||||
"Are you sure you want to perform this action?";
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ const AppViewerBody = styled.section<{ hasPages: boolean }>`
|
|||
justify-content: flex-start;
|
||||
height: calc(
|
||||
100vh -
|
||||
${(props) => (!props.hasPages ? props.theme.smallHeaderHeight : "72px")}
|
||||
${(props) =>
|
||||
!props.hasPages ? `${props.theme.smallHeaderHeight} - 1px` : "72px"}
|
||||
);
|
||||
`;
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ import { Colors } from "constants/Colors";
|
|||
import SearchSnippets from "components/ads/SnippetButton";
|
||||
import { ENTITY_TYPE } from "entities/DataTree/dataTreeFactory";
|
||||
import ApiAuthentication from "./ApiAuthentication";
|
||||
import TooltipComponent from "components/ads/Tooltip";
|
||||
import { TOOLTIP_HOVER_ON_DELAY } from "constants/AppConstants";
|
||||
import { Position } from "@blueprintjs/core/lib/esnext/common";
|
||||
import { Classes as BluePrintClasses } from "@blueprintjs/core";
|
||||
|
||||
const Form = styled.form`
|
||||
display: flex;
|
||||
|
|
@ -290,6 +294,52 @@ const Flex = styled.div<{ size: number }>`
|
|||
color: #4b4848;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&.possible-overflow-key {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
|
||||
.${BluePrintClasses.POPOVER_WRAPPER} {
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.${BluePrintClasses.POPOVER_TARGET} > span {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&.possible-overflow {
|
||||
width: 0;
|
||||
max-height: 32px;
|
||||
|
||||
& > span.cs-text {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.${BluePrintClasses.POPOVER_TARGET} {
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.${BluePrintClasses.POPOVER_TARGET} > span {
|
||||
max-height: 32px;
|
||||
padding: 6px 12px;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding-left: 2px;
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const FlexContainer = styled.div`
|
||||
|
|
@ -297,6 +347,10 @@ const FlexContainer = styled.div`
|
|||
align-items: center;
|
||||
width: calc(100% - 30px);
|
||||
|
||||
&.header {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.key-value {
|
||||
.${Classes.TEXT} {
|
||||
color: ${(props) => props.theme.colors.apiPane.text};
|
||||
|
|
@ -337,11 +391,28 @@ function ImportedHeaderKeyValue(props: { headers: any }) {
|
|||
return (
|
||||
<FormRowWithLabel key={index}>
|
||||
<FlexContainer>
|
||||
<Flex className="key-value disabled" size={1}>
|
||||
<Text type={TextType.H6}>{header.key}</Text>
|
||||
<Flex
|
||||
className="key-value disabled possible-overflow-key"
|
||||
size={1}
|
||||
>
|
||||
<TooltipComponent
|
||||
content={header.key}
|
||||
hoverOpenDelay={TOOLTIP_HOVER_ON_DELAY}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Text type={TextType.H6}>{header.key}</Text>
|
||||
</TooltipComponent>
|
||||
</Flex>
|
||||
<Flex className="key-value disabled" size={3}>
|
||||
<Text type={TextType.H6}>{header.value}</Text>
|
||||
<Flex className="key-value disabled possible-overflow" size={3}>
|
||||
<Text type={TextType.H6}>
|
||||
<TooltipComponent
|
||||
content={header.value}
|
||||
hoverOpenDelay={TOOLTIP_HOVER_ON_DELAY}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
{header.value}
|
||||
</TooltipComponent>
|
||||
</Text>
|
||||
</Flex>
|
||||
</FlexContainer>
|
||||
</FormRowWithLabel>
|
||||
|
|
@ -426,7 +497,7 @@ function ImportedHeaders(props: { headers: any }) {
|
|||
)}
|
||||
<KeyValueStackContainer>
|
||||
<FormRowWithLabel>
|
||||
<FlexContainer>
|
||||
<FlexContainer className="header">
|
||||
<Flex className="key-value" size={1}>
|
||||
<Text case={Case.CAPITALIZE} type={TextType.H6}>
|
||||
Key
|
||||
|
|
@ -527,10 +598,10 @@ function ApiEditorForm(props: Props) {
|
|||
className="t--apiFormHttpMethod"
|
||||
height={"35px"}
|
||||
name="actionConfiguration.httpMethod"
|
||||
optionWidth={"102px"}
|
||||
optionWidth={"110px"}
|
||||
options={HTTP_METHOD_OPTIONS}
|
||||
placeholder="Method"
|
||||
width={"102px"}
|
||||
width={"110px"}
|
||||
/>
|
||||
</BoundaryContainer>
|
||||
<DatasourceWrapper className="t--dataSourceField">
|
||||
|
|
|
|||
|
|
@ -1,19 +1,37 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { AppState } from "reducers";
|
||||
import { Dialog, Classes } from "@blueprintjs/core";
|
||||
import Button from "components/editorComponents/Button";
|
||||
import {
|
||||
showRunActionConfirmModal,
|
||||
cancelRunActionConfirmModal,
|
||||
acceptRunActionConfirmModal,
|
||||
} from "actions/pluginActionActions";
|
||||
import DialogComponent from "components/ads/DialogComponent";
|
||||
import styled from "styled-components";
|
||||
import Button, { Category, Size } from "components/ads/Button";
|
||||
import {
|
||||
createMessage,
|
||||
QUERY_CONFIRMATION_MODAL_MESSAGE,
|
||||
} from "constants/messages";
|
||||
|
||||
type Props = {
|
||||
isModalOpen: boolean;
|
||||
dispatch: any;
|
||||
};
|
||||
|
||||
const ModalBody = styled.div`
|
||||
padding-bottom: 20px;
|
||||
`;
|
||||
|
||||
const ModalFooter = styled.div`
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
button {
|
||||
margin-left: 12px;
|
||||
}
|
||||
`;
|
||||
|
||||
class ConfirmRunModal extends React.Component<Props> {
|
||||
render() {
|
||||
const { dispatch, isModalOpen } = this.props;
|
||||
|
|
@ -24,34 +42,39 @@ class ConfirmRunModal extends React.Component<Props> {
|
|||
};
|
||||
|
||||
return (
|
||||
<Dialog isOpen={isModalOpen} onClose={handleClose} title="Confirm Action">
|
||||
<div className={Classes.DIALOG_BODY}>
|
||||
Are you sure you want to perform this action?
|
||||
</div>
|
||||
<div className={Classes.DIALOG_FOOTER}>
|
||||
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||
<Button
|
||||
filled
|
||||
onClick={() => {
|
||||
dispatch(cancelRunActionConfirmModal());
|
||||
|
||||
handleClose();
|
||||
}}
|
||||
text="Cancel"
|
||||
/>
|
||||
<Button
|
||||
filled
|
||||
intent="primary"
|
||||
onClick={() => {
|
||||
dispatch(acceptRunActionConfirmModal());
|
||||
|
||||
handleClose();
|
||||
}}
|
||||
text="Confirm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
<DialogComponent
|
||||
isOpen={isModalOpen}
|
||||
maxHeight={"80vh"}
|
||||
onClose={handleClose}
|
||||
title="Confirm Action"
|
||||
width={"580px"}
|
||||
>
|
||||
<ModalBody>{createMessage(QUERY_CONFIRMATION_MODAL_MESSAGE)}</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
category={Category.tertiary}
|
||||
onClick={() => {
|
||||
dispatch(cancelRunActionConfirmModal());
|
||||
handleClose();
|
||||
}}
|
||||
size={Size.medium}
|
||||
tag="button"
|
||||
text="Cancel"
|
||||
type="button"
|
||||
/>
|
||||
<Button
|
||||
category={Category.primary}
|
||||
onClick={() => {
|
||||
dispatch(acceptRunActionConfirmModal());
|
||||
handleClose();
|
||||
}}
|
||||
size={Size.medium}
|
||||
tag="button"
|
||||
text="Confirm"
|
||||
type="button"
|
||||
/>
|
||||
</ModalFooter>
|
||||
</DialogComponent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,6 +127,19 @@ const queryPaneReducer = createReducer(initialState, {
|
|||
};
|
||||
},
|
||||
|
||||
[ReduxActionTypes.RUN_ACTION_CANCELLED]: (
|
||||
state: any,
|
||||
action: ReduxAction<{ id: string }>,
|
||||
) => {
|
||||
return {
|
||||
...state,
|
||||
isRunning: {
|
||||
...state.isRunning,
|
||||
[action.payload.id]: false,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
[ReduxActionTypes.RUN_ACTION_SUCCESS]: (
|
||||
state: any,
|
||||
action: ReduxAction<{ [id: string]: ActionResponse }>,
|
||||
|
|
|
|||
|
|
@ -665,6 +665,10 @@ function* executePluginActionSaga(
|
|||
if (pluginAction.confirmBeforeExecute) {
|
||||
const confirmed = yield call(confirmRunActionSaga);
|
||||
if (!confirmed) {
|
||||
yield put({
|
||||
type: ReduxActionTypes.RUN_ACTION_CANCELLED,
|
||||
payload: { id: actionId },
|
||||
});
|
||||
throw new UserCancelledActionExecutionError();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user