hunk.code_window:       key: "body",
         title: "Response Body",
         panelComponent: (
           <ResponseTabWrapper>
             {hasFailed && !isRunning && requestDebugVisible && (
               <Callout
                 closeButton
                 fill
                 label={
                   <FailedMessage>
  
hunk.labels: keep keep keep keep replace replace replace keep keep keep
hunk.after_edit:           {hasFailed && !isRunning && (
               <StyledCallout
  
hunk.file_path: app/client/src/components/editorComponents/ApiResponseView.tsx
hunk.type: replace
file: import React, { useState, useRef, RefObject, useCallback } from "react";
  import { connect } from "react-redux";
  import { withRouter, RouteComponentProps } from "react-router";
  import { BaseText } from "components/designSystems/blueprint/TextComponent";
  import styled from "styled-components";
  import { AppState } from "reducers";
  import { ActionResponse } from "api/ActionAPI";
  import { formatBytes } from "utils/helpers";
  import { APIEditorRouteParams } from "constants/routes";
  import LoadingOverlayScreen from "components/editorComponents/LoadingOverlayScreen";
  import ReadOnlyEditor from "components/editorComponents/ReadOnlyEditor";
  import { getActionResponses } from "selectors/entitiesSelector";
  import { Colors } from "constants/Colors";
  import _ from "lodash";
  import { useLocalStorage } from "utils/hooks/localstorage";
  import {
    CHECK_REQUEST_BODY,
    createMessage,
    DEBUGGER_ERRORS,
    DEBUGGER_LOGS,
    INSPECT_ENTITY,
  } from "constants/messages";
  import { TabComponent } from "components/ads/Tabs";
  import Text, { TextType } from "components/ads/Text";
  import Icon from "components/ads/Icon";
  import { Classes, Variant } from "components/ads/common";
  import { EditorTheme } from "./CodeEditor/EditorConfig";
  import Callout from "components/ads/Callout";
  import DebuggerLogs from "./Debugger/DebuggerLogs";
  import ErrorLogs from "./Debugger/Errors";
  import Resizer, { ResizerCSS } from "./Debugger/Resizer";
  import AnalyticsUtil from "utils/AnalyticsUtil";
  import { DebugButton } from "./Debugger/DebugCTA";
  import EntityDeps from "./Debugger/EntityDependecies";
  
  const ResponseContainer = styled.div`
    ${ResizerCSS}
    // Initial height of bottom tabs
    height: 60%;
    width: 100%;
    // Minimum height of bottom tabs as it can be resized
    min-height: 36px;
    background-color: ${(props) => props.theme.colors.apiPane.responseBody.bg};
  
    .react-tabs__tab-panel {
      overflow: hidden;
    }
  `;
  const ResponseMetaInfo = styled.div`
    display: flex;
    ${BaseText} {
      color: #768896;
      margin-left: ${(props) => props.theme.spaces[9]}px;
    }
  `;
  
  const ResponseMetaWrapper = styled.div`
    align-items: center;
    display: flex;
    position: absolute;
    right: ${(props) => props.theme.spaces[12]}px;
    top: ${(props) => props.theme.spaces[4]}px;
  `;
  
  const ResponseTabWrapper = styled.div`
    display: flex;
    flex-direction: column;
    height: 100%;
    width: 100%;
  `;
  
  const TabbedViewWrapper = styled.div<{ isCentered: boolean }>`
    height: calc(100% - 30px);
  
    &&& {
      ul.react-tabs__tab-list {
        padding: 0px ${(props) => props.theme.spaces[12]}px;
      }
    }
  
    ${(props) =>
      props.isCentered
        ? `
      &&& {
        .react-tabs__tab-panel {
          display: flex;
          align-items: center;
          justify-content: center;
      }
      }
    `
        : null}
  `;
  
  const SectionDivider = styled.div`
    height: 2px;
    width: 100%;
    background: ${(props) => props.theme.colors.apiPane.dividerBg};
  `;
  
  const Flex = styled.div`
    display: flex;
    align-items: center;
    margin-left: 20px;
  
    span:first-child {
      margin-right: ${(props) => props.theme.spaces[1] + 1}px;
    }
  `;
  
  const NoResponseContainer = styled.div`
    height: 100%;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    .${Classes.ICON} {
      margin-right: 0px;
      svg {
        width: 150px;
        height: 150px;
      }
    }
  
    .${Classes.TEXT} {
      margin-top: ${(props) => props.theme.spaces[9]}px;
    }
  `;
  
  const FailedMessage = styled.div`
    display: flex;
    align-items: center;
    margin-left: 5px;
  `;
  
  interface ReduxStateProps {
    responses: Record<string, ActionResponse | undefined>;
    isRunning: Record<string, boolean>;
  }
  
  type Props = ReduxStateProps &
    RouteComponentProps<APIEditorRouteParams> & {
      theme?: EditorTheme;
      apiName: string;
    };
  
  export const EMPTY_RESPONSE: ActionResponse = {
    statusCode: "",
    duration: "",
    body: {},
    headers: {},
    request: {
      headers: {},
      body: {},
      httpMethod: "",
      url: "",
    },
    size: "",
  };
  
  const StatusCodeText = styled(BaseText)<{ code: string }>`
    color: ${(props) =>
      props.code.startsWith("2") ? props.theme.colors.primaryOld : Colors.RED};
  `;
  
  function ApiResponseView(props: Props) {
    const {
      match: {
        params: { apiId },
      },
      responses,
    } = props;
    let response: ActionResponse = EMPTY_RESPONSE;
    let isRunning = false;
    let hasFailed = false;
    if (apiId && apiId in responses) {
      response = responses[apiId] || EMPTY_RESPONSE;
      isRunning = props.isRunning[apiId];
      hasFailed = response.statusCode ? response.statusCode[0] !== "2" : false;
    }
    const panelRef: RefObject<HTMLDivElement> = useRef(null);
  
    const [requestDebugVisible, setRequestDebugVisible] = useLocalStorage(
      "requestDebugVisible",
      "true",
    );
  
    const onDebugClick = useCallback(() => {
      AnalyticsUtil.logEvent("OPEN_DEBUGGER", {
        source: "API",
      });
      setSelectedIndex(1);
    }, []);
  
    const [selectedIndex, setSelectedIndex] = useState(0);
    const tabs = [
      {
        key: "body",
        title: "Response Body",
        panelComponent: (
          <ResponseTabWrapper>
            {hasFailed && !isRunning && requestDebugVisible && (
              <Callout
                closeButton
                fill
                label={
                  <FailedMessage>
                    <DebugButton onClick={onDebugClick} />
                  </FailedMessage>
                }
                onClose={() => setRequestDebugVisible(false)}
                text={createMessage(CHECK_REQUEST_BODY)}
                variant={Variant.danger}
              />
            )}
            {_.isEmpty(response.statusCode) ? (
              <NoResponseContainer>
                <Icon name="no-response" />
                <Text type={TextType.P1}>Hit Run to get a Response</Text>
              </NoResponseContainer>
            ) : (
              <ReadOnlyEditor
                folding
                height={"100%"}
                input={{
                  value: response.body
                    ? JSON.stringify(response.body, null, 2)
                    : "",
                }}
              />
            )}
          </ResponseTabWrapper>
        ),
      },
      {
        key: "ERROR",
        title: createMessage(DEBUGGER_ERRORS),
        panelComponent: <ErrorLogs />,
      },
      {
        key: "LOGS",
        title: createMessage(DEBUGGER_LOGS),
        panelComponent: <DebuggerLogs searchQuery={props.apiName} />,
      },
      {
        key: "ENTITY_DEPENDENCIES",
        title: createMessage(INSPECT_ENTITY),
        panelComponent: <EntityDeps />,
      },
    ];
  
    const onTabSelect = (index: number) => {
      const debuggerTabKeys = ["ERROR", "LOGS"];
      if (
        debuggerTabKeys.includes(tabs[index].key) &&
        debuggerTabKeys.includes(tabs[selectedIndex].key)
      ) {
        AnalyticsUtil.logEvent("DEBUGGER_TAB_SWITCH", {
          tabName: tabs[index].key,
        });
      }
  
      setSelectedIndex(index);
    };
  
    return (
      <ResponseContainer ref={panelRef}>
        <Resizer panelRef={panelRef} />
        <SectionDivider />
        {isRunning && (
          <LoadingOverlayScreen theme={props.theme}>
            Sending Request
          </LoadingOverlayScreen>
        )}
        <TabbedViewWrapper
          isCentered={_.isEmpty(response.body) && selectedIndex === 0}
        >
          {response.statusCode && (
            <ResponseMetaWrapper>
              {response.statusCode && (
                <Flex>
                  <Text type={TextType.P3}>Status: </Text>
                  <StatusCodeText
                    accent="secondary"
                    code={response.statusCode.toString()}
                  >
                    {response.statusCode}
                  </StatusCodeText>
                </Flex>
              )}
              <ResponseMetaInfo>
                {response.duration && (
                  <Flex>
                    <Text type={TextType.P3}>Time: </Text>
                    <Text type={TextType.H5}>{response.duration} ms</Text>
                  </Flex>
                )}
                {response.size && (
                  <Flex>
                    <Text type={TextType.P3}>Size: </Text>
                    <Text type={TextType.H5}>
                      {formatBytes(parseInt(response.size))}
                    </Text>
                  </Flex>
                )}
                {!_.isEmpty(response.body) && Array.isArray(response.body) && (
                  <Flex>
                    <Text type={TextType.P3}>Result: </Text>
                    <Text type={TextType.H5}>
                      {`${response.body.length} Record${
                        response.body.length > 1 ? "s" : ""
                      }`}
                    </Text>
                  </Flex>
                )}
              </ResponseMetaInfo>
            </ResponseMetaWrapper>
          )}
          <TabComponent
            onSelect={onTabSelect}
            selectedIndex={selectedIndex}
            tabs={tabs}
          />
        </TabbedViewWrapper>
      </ResponseContainer>
    );
  }
  
  const mapStateToProps = (state: AppState): ReduxStateProps => {
    return {
      responses: getActionResponses(state),
      isRunning: state.ui.apiPane.isRunning,
    };
  };
  
  export default connect(mapStateToProps)(withRouter(ApiResponseView));
  