hunk.code_window:     icon: "share-2",
       text: createMessage(DEBUGGER_SEARCH_GOOGLE),
       onSelect: (error: Message) => {
         window.open("http://google.com/search?q=" + error.message);
       },
     },
  
hunk.labels: keep keep add keep keep keep
hunk.after_edit:       AnalyticsUtil.logEvent("DEBUGGER_CONTEXT_MENU_CLICK", {
           menuItem: CONTEXT_MENU_ACTIONS.GOOGLE,
         });
  
hunk.file_path: app/client/src/components/editorComponents/Debugger/ContextualMenu.tsx
hunk.type: add
file: import React from "react";
  import copy from "copy-to-clipboard";
  import styled from "styled-components";
  import { Classes as BPClasses, Position } from "@blueprintjs/core";
  import { Popover2, IPopover2Props } from "@blueprintjs/popover2";
  import { Dispatch } from "redux";
  import { useDispatch } from "react-redux";
  import Text, { FontWeight, TextType } from "components/ads/Text";
  import { Message, SourceEntity } from "entities/AppsmithConsole";
  import { PropertyEvaluationErrorType } from "utils/DynamicBindingUtils";
  import AnalyticsUtil from "utils/AnalyticsUtil";
  import {
    setGlobalSearchQuery,
    toggleShowGlobalSearchModal,
  } from "actions/globalSearchActions";
  import { filterCategories, SEARCH_CATEGORY_ID } from "../GlobalSearch/utils";
  import { getAppsmithConfigs } from "configs";
  import {
    createMessage,
    DEBUGGER_APPSMITH_SUPPORT,
    DEBUGGER_COPY_MESSAGE,
    DEBUGGER_INTERCOM_TEXT,
    DEBUGGER_OPEN_DOCUMENTATION,
    DEBUGGER_SEARCH_GOOGLE,
    DEBUGGER_SEARCH_SNIPPET,
  } from "constants/messages";
  import Icon, { IconName, IconSize } from "components/ads/Icon";
  import { Classes } from "components/ads/common";
  import { Colors } from "constants/Colors";
  import { executeCommandAction } from "actions/apiPaneActions";
  import { SlashCommand } from "entities/Action";
  import { FieldEntityInformation } from "../CodeEditor/EditorConfig";
  const { intercomAppID } = getAppsmithConfigs();
  
  enum CONTEXT_MENU_ACTIONS {
    COPY = "COPY",
    DOCS = "DOCS",
    SNIPPET = "SNIPPET",
    GOOGLE = "GOOGLE",
    INTERCOM = "INTERCOM",
  }
  
  enum PLUGIN_EXECUTION_ERRORS {
    DATASOURCE_CONFIGURATION_ERROR = "DATASOURCE_CONFIGURATION_ERROR",
    PLUGIN_ERROR = "PLUGIN_ERROR",
    CONNECTIVITY_ERROR = "CONNECTIVITY_ERROR",
    ACTION_CONFIGURATION_ERROR = "ACTION_CONFIGURATION_ERROR",
  }
  
  const getOptions = (type?: string, subType?: string) => {
    const defaultOptions = [
      CONTEXT_MENU_ACTIONS.COPY,
      CONTEXT_MENU_ACTIONS.DOCS,
      CONTEXT_MENU_ACTIONS.SNIPPET,
      CONTEXT_MENU_ACTIONS.GOOGLE,
      CONTEXT_MENU_ACTIONS.INTERCOM,
    ];
  
    if (subType) {
      switch (subType) {
        // These types are sent by the server
        case PLUGIN_EXECUTION_ERRORS.DATASOURCE_CONFIGURATION_ERROR:
          return [
            CONTEXT_MENU_ACTIONS.COPY,
            CONTEXT_MENU_ACTIONS.GOOGLE,
            CONTEXT_MENU_ACTIONS.INTERCOM,
          ];
        case PLUGIN_EXECUTION_ERRORS.PLUGIN_ERROR:
          return [
            CONTEXT_MENU_ACTIONS.COPY,
            CONTEXT_MENU_ACTIONS.GOOGLE,
            CONTEXT_MENU_ACTIONS.INTERCOM,
          ];
        case PLUGIN_EXECUTION_ERRORS.CONNECTIVITY_ERROR:
          return [CONTEXT_MENU_ACTIONS.COPY, CONTEXT_MENU_ACTIONS.DOCS];
        case PLUGIN_EXECUTION_ERRORS.ACTION_CONFIGURATION_ERROR:
          return [
            CONTEXT_MENU_ACTIONS.COPY,
            CONTEXT_MENU_ACTIONS.DOCS,
            CONTEXT_MENU_ACTIONS.INTERCOM,
          ];
        default:
          return defaultOptions;
      }
    } else {
      switch (type) {
        case PropertyEvaluationErrorType.VALIDATION:
          return [
            CONTEXT_MENU_ACTIONS.COPY,
            CONTEXT_MENU_ACTIONS.DOCS,
            CONTEXT_MENU_ACTIONS.SNIPPET,
            CONTEXT_MENU_ACTIONS.INTERCOM,
          ];
        case PropertyEvaluationErrorType.PARSE:
          return [
            CONTEXT_MENU_ACTIONS.COPY,
            CONTEXT_MENU_ACTIONS.SNIPPET,
            CONTEXT_MENU_ACTIONS.GOOGLE,
          ];
        case PropertyEvaluationErrorType.LINT:
          return [
            CONTEXT_MENU_ACTIONS.COPY,
            CONTEXT_MENU_ACTIONS.SNIPPET,
            CONTEXT_MENU_ACTIONS.GOOGLE,
          ];
        default:
          return defaultOptions;
      }
    }
  };
  
  const isFieldEntityInformation = (
    entity: FieldEntityInformation | SourceEntity,
  ): entity is FieldEntityInformation => {
    return entity.hasOwnProperty("entityType");
  };
  
  const getSnippetArgs = function(
    entity?: FieldEntityInformation | SourceEntity,
  ) {
    if (!entity) return {};
    if (isFieldEntityInformation(entity)) {
      return {
        entityId: entity.entityId,
        entityType: entity.entityType,
      };
    } else {
      return {
        entityId: entity.id,
        entityType: entity.type,
      };
    }
  };
  
  type ContextualMenuProps = {
    error: Message;
    children: JSX.Element;
    position?: Position;
    modifiers?: IPopover2Props["modifiers"];
    entity?: FieldEntityInformation | SourceEntity;
  };
  
  const searchAction: Record<
    CONTEXT_MENU_ACTIONS,
    {
      icon: IconName;
      text: string;
      onSelect: (
        error: Message,
        dispatch: Dispatch,
        entity?: FieldEntityInformation | SourceEntity,
      ) => void;
    }
  > = {
    [CONTEXT_MENU_ACTIONS.COPY]: {
      icon: "duplicate",
      text: createMessage(DEBUGGER_COPY_MESSAGE),
      onSelect: (error: Message) => {
        copy(error.message);
      },
    },
    [CONTEXT_MENU_ACTIONS.GOOGLE]: {
      icon: "share-2",
      text: createMessage(DEBUGGER_SEARCH_GOOGLE),
      onSelect: (error: Message) => {
        window.open("http://google.com/search?q=" + error.message);
      },
    },
    [CONTEXT_MENU_ACTIONS.DOCS]: {
      icon: "book-line",
      text: createMessage(DEBUGGER_OPEN_DOCUMENTATION),
      onSelect: (error: Message, dispatch: Dispatch) => {
        // Search through the omnibar
        AnalyticsUtil.logEvent("OPEN_OMNIBAR", {
          source: "DEBUGGER",
          searchTerm: error.message,
          errorType: error.type,
        });
        dispatch(setGlobalSearchQuery(error.message || ""));
        dispatch(
          toggleShowGlobalSearchModal(filterCategories[SEARCH_CATEGORY_ID.INIT]),
        );
      },
    },
    [CONTEXT_MENU_ACTIONS.INTERCOM]: {
      icon: "support",
      text: createMessage(DEBUGGER_APPSMITH_SUPPORT),
      onSelect: (error: Message) => {
        // Search through the omnibar
        if (intercomAppID && window.Intercom) {
          window.Intercom(
            "showNewMessage",
            createMessage(DEBUGGER_INTERCOM_TEXT, error.message),
          );
        }
      },
    },
    [CONTEXT_MENU_ACTIONS.SNIPPET]: {
      icon: "play",
      text: createMessage(DEBUGGER_SEARCH_SNIPPET),
      onSelect: (error: Message, dispatch: Dispatch, entity) => {
        /// Search through the omnibar
        AnalyticsUtil.logEvent("OPEN_OMNIBAR", {
          source: "DEBUGGER",
          searchTerm: error.message,
          errorType: error.type,
        });
        dispatch(setGlobalSearchQuery(""));
        dispatch(
          executeCommandAction({
            actionType: SlashCommand.NEW_SNIPPET,
            args: getSnippetArgs(entity),
          }),
        );
      },
    },
  };
  
  const IconContainer = styled.span`
    display: flex;
    align-items: center;
  
    .${Classes.ICON} {
      margin-right: ${(props) => props.theme.spaces[4]}px;
    }
  `;
  
  const MenuItem = styled.a`
    display: flex;
    align-items: center;
    justify-content: space-between;
    text-decoration: none;
    padding: 0px ${(props) => props.theme.spaces[6]}px;
    height: 28px;
  
    .${Classes.TEXT} {
      color: ${Colors.CODE_GRAY};
    }
  
    .${Classes.ICON} {
      path {
        fill: ${Colors.CODE_GRAY};
      }
    }
  
    &:hover {
      text-decoration: none;
      cursor: pointer;
      background-color: ${(props) => props.theme.colors.menuItem.hoverBg};
  
      .${Classes.TEXT} {
        color: ${(props) => props.theme.colors.menuItem.hoverText};
      }
      .${Classes.ICON} {
        path {
          fill: ${(props) => props.theme.colors.menuItem.hoverIcon};
        }
      }
    }
  `;
  
  const MenuWrapper = styled.div<{ width: string }>`
    width: ${(props) => props.width};
    background: ${(props) => props.theme.colors.menu.background};
    box-shadow: ${(props) =>
      `${props.theme.spaces[0]}px ${props.theme.spaces[5]}px ${props.theme
        .spaces[12] - 2}px ${props.theme.colors.menu.shadow}`};
  `;
  
  export default function ContextualMenu(props: ContextualMenuProps) {
    const options = getOptions(props.error.type, props.error.subType);
    const dispatch = useDispatch();
  
    return (
      <Popover2
        className="t--debugger-contextual-error-menu"
        content={
          <MenuWrapper width={"175px"}>
            {options.map((e) => {
              const menuProps = searchAction[e];
              const onSelect = () => {
                menuProps.onSelect(props.error, dispatch, props.entity);
              };
  
              if (
                e === CONTEXT_MENU_ACTIONS.INTERCOM &&
                !(intercomAppID && window.Intercom)
              ) {
                return null;
              }
  
              return (
                <MenuItem
                  className={`${BPClasses.POPOVER_DISMISS} t--debugger-contextual-menuitem`}
                  key={e}
                  onClick={onSelect}
                >
                  <IconContainer>
                    <Icon name={menuProps.icon} size={IconSize.XS} />
                    <Text type={TextType.P3} weight={FontWeight.NORMAL}>
                      {menuProps.text}
                    </Text>
                  </IconContainer>
                </MenuItem>
              );
            })}
          </MenuWrapper>
        }
        modifiers={
          props.modifiers || {
            offset: {
              enabled: true,
              options: {
                offset: [25, 5],
              },
            },
            arrow: {
              enabled: false,
            },
          }
        }
        position={props.position || Position.RIGHT}
      >
        {props.children}
      </Popover2>
    );
  }
  