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, { useState, useEffect, ReactElement, useCallback } from "react";
  import { useSelector, useDispatch } from "react-redux";
  import { getEditorConfig } from "selectors/entitiesSelector";
  import { AppState } from "reducers/index";
  import Dropdown, { DropdownOption } from "components/ads/Dropdown";
  import { fetchPluginFormConfig } from "actions/pluginActions";
  import { DROPDOWN_DIMENSION, DEFAULT_DROPDOWN_OPTION } from "../constants";
  import { SelectWrapper, Label, Bold } from "./styles";
  import TextInput from "components/ads/TextInput";
  import { GeneratePagePayload } from "./types";
  import { getSheetUrl } from "./hooks";
  import Tooltip from "components/ads/Tooltip";
  import styled from "styled-components";
  import {
    UseSheetListReturn,
    UseSpreadSheetsReturn,
    UseSheetColumnHeadersReturn,
  } from "./hooks";
  import Icon, { IconSize } from "components/ads/Icon";
  import { Colors } from "constants/Colors";
  import { getTypographyByKey } from "constants/DefaultTheme";
  import { debounce } from "lodash";
  import Text, { TextType, FontWeight } from "components/ads/Text";
  import {
    createMessage,
    GEN_CRUD_TABLE_HEADER_LABEL,
    GEN_CRUD_COLUMN_HEADER_TITLE,
    GEN_CRUD_NO_COLUMNS,
    GEN_CRUD_TABLE_HEADER_TOOLTIP_DESC,
  } from "constants/messages";
  
  type Props = {
    googleSheetPluginId: string;
    selectedDatasource: DropdownOption;
    selectedSpreadsheet: DropdownOption;
    generatePageAction: (payload: GeneratePagePayload) => void;
    renderSubmitButton: ({
      disabled,
      isLoading,
      onSubmit,
    }: {
      onSubmit: () => void;
      disabled: boolean;
      isLoading: boolean;
    }) => ReactElement<any, any>;
    sheetsListProps: UseSheetListReturn;
    spreadSheetsProps: UseSpreadSheetsReturn;
    sheetColumnsHeaderProps: UseSheetColumnHeadersReturn;
  };
  
  // styles
  
  const RoundBg = styled.div`
    width: 16px;
    height: 16px;
    border-radius: 16px;
    background-color: ${Colors.GRAY};
    display: flex;
    justify-content: center;
    align-items: center;
  `;
  
  const Row = styled.div`
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
  `;
  
  const ColumnName = styled.span`
    ${(props) => `${getTypographyByKey(props, "p3")}`};
    color: ${Colors.GRAY};
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  `;
  
  const ColumnInfoWrapper = styled.div`
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    align-items: flex-start;
    padding: 0px 8px;
    margin-bottom: 10px;
    width: ${DROPDOWN_DIMENSION.WIDTH};
    overflow: hidden;
    flex-wrap: wrap;
  `;
  
  const ColumnNameWrapper = styled.div`
    display: flex;
  `;
  
  const TooltipWrapper = styled.div`
    margin-top: 2px;
  `;
  
  const RowHeading = styled.p`
    ${(props) => `${getTypographyByKey(props, "p1")}`};
    margin-right: 10px;
  `;
  
  // As TextInput with dataType as number allows `e` as input, hence adding a number validator
  // to check for only whole numbers.
  export function isNumberValidator(value: string) {
    const isValid = (/^\d+$/.test(value) && Number(value) > 0) || value === "";
    return {
      isValid: isValid,
      message: !isValid ? "Only numeric value allowed" : "",
    };
  }
  
  // constants
  
  const MAX_COLUMNS_VISIBLE = 3;
  
  // ---------- GoogleSheetForm Component -------
  
  function GoogleSheetForm(props: Props) {
    const {
      generatePageAction,
      googleSheetPluginId,
      renderSubmitButton,
      selectedDatasource,
      selectedSpreadsheet,
      sheetColumnsHeaderProps,
      sheetsListProps,
      spreadSheetsProps,
    } = props;
  
    const { fetchSheetsList, isFetchingSheetsList, sheetsList } = sheetsListProps;
    const { fetchAllSpreadsheets } = spreadSheetsProps;
    const {
      columnHeaderList,
      fetchColumnHeaderList,
      isFetchingColumnHeaderList,
    } = sheetColumnsHeaderProps;
  
    const [tableHeaderIndex, setTableHeaderIndex] = useState<string>("1");
    const [selectedSheet, setSelectedSheet] = useState<DropdownOption>(
      DEFAULT_DROPDOWN_OPTION,
    );
    const dispatch = useDispatch();
  
    const googleSheetEditorConfig = useSelector((state: AppState) =>
      getEditorConfig(state, googleSheetPluginId),
    );
  
    const [sheetQueryRequest, setSheetQueryRequest] = useState<
      Record<any, string>
    >({});
  
    useEffect(() => {
      // Check if google sheet editor config is fetched.
      // if not, fetch it.
  
      if (!googleSheetEditorConfig) {
        dispatch(
          fetchPluginFormConfig({
            pluginId: selectedDatasource.data?.pluginId,
          }),
        );
      }
    }, [googleSheetEditorConfig]);
  
    useEffect(() => {
      if (googleSheetEditorConfig && googleSheetEditorConfig[0]) {
        const requestObject: Record<any, string> = {};
        const configs = googleSheetEditorConfig[0]?.children;
        if (Array.isArray(configs)) {
          for (let index = 0; index < configs.length; index += 2) {
            const keyConfig = configs[index];
            const valueConfig = configs[index + 1];
            if (keyConfig && valueConfig) {
              const key = keyConfig?.initialValue;
              const value = valueConfig?.initialValue;
              if (key && value !== undefined) requestObject[key] = value;
            }
          }
        }
        setSheetQueryRequest(requestObject);
      }
    }, [googleSheetEditorConfig]);
  
    useEffect(() => {
      // On change of datasource selection
      // if googleSheetEditorConfig if fetched then get all spreadsheets
      if (
        selectedDatasource.value &&
        selectedDatasource.id &&
        googleSheetEditorConfig
      ) {
        fetchAllSpreadsheets({
          selectedDatasourceId: selectedDatasource.id,
          requestObject: sheetQueryRequest,
        });
      }
    }, [selectedDatasource.value, googleSheetEditorConfig, dispatch]);
  
    // When user selects a spreadsheet
    // Fetch all sheets inside that spreadsheet
    useEffect(() => {
      if (
        selectedDatasource.value &&
        selectedDatasource.id &&
        selectedSpreadsheet.value &&
        selectedSpreadsheet.id
      ) {
        setSelectedSheet(DEFAULT_DROPDOWN_OPTION);
        fetchSheetsList({
          requestObject: sheetQueryRequest,
          selectedDatasourceId: selectedDatasource.id,
          selectedSpreadsheetId: selectedSpreadsheet.id,
        });
      }
    }, [
      selectedSpreadsheet.id,
      selectedSpreadsheet.value,
      selectedDatasource.id,
      selectedDatasource.value,
      dispatch,
      fetchSheetsList,
    ]);
  
    const onSelectSheetOption = (
      sheetValue: string | undefined,
      sheetObj: DropdownOption | undefined,
    ) => {
      if (sheetValue && sheetObj) {
        setSelectedSheet(sheetObj);
        if (selectedDatasource.id && selectedSpreadsheet.id) {
          fetchColumnHeaderList({
            selectedDatasourceId: selectedDatasource.id,
            selectedSpreadsheetId: selectedSpreadsheet.id,
            sheetName: sheetValue,
            tableHeaderIndex,
            requestObject: sheetQueryRequest,
          });
        }
      }
    };
  
    const onSubmit = () => {
      if (selectedSpreadsheet.id) {
        const columns: string[] = [];
        columnHeaderList.forEach(({ value }) => {
          if (value) columns.push(value);
        });
        const payload = {
          columns,
          searchColumn: "",
          tableName: selectedSheet.value || "",
          pluginSpecificParams: {
            sheetUrl: getSheetUrl(selectedSpreadsheet.id),
            tableHeaderIndex,
            sheetName: selectedSheet.value,
          },
        };
        generatePageAction(payload);
      }
    };
  
    const debouncedFetchColumns = useCallback(
      debounce((value: string) => {
        if (
          selectedDatasource.id &&
          selectedSpreadsheet.id &&
          selectedSheet.value
        ) {
          fetchColumnHeaderList({
            selectedDatasourceId: selectedDatasource.id,
            selectedSpreadsheetId: selectedSpreadsheet.id,
            sheetName: selectedSheet.value,
            tableHeaderIndex: value,
            requestObject: sheetQueryRequest,
          });
        }
      }, 200),
      [selectedSheet, selectedDatasource, selectedSheet],
    );
  
    const tableHeaderIndexChangeHandler = (value: string) => {
      if (isNumberValidator(value).isValid) {
        setTableHeaderIndex(value);
        debouncedFetchColumns(value);
      }
    };
  
    return (
      <>
        {selectedSpreadsheet.value ? (
          <SelectWrapper width={DROPDOWN_DIMENSION.WIDTH}>
            <Label>
              Select sheet from <Bold>{selectedSpreadsheet.label}</Bold>
            </Label>
            <Dropdown
              cypressSelector="t--table-dropdown"
              dropdownMaxHeight={"300px"}
              height={DROPDOWN_DIMENSION.HEIGHT}
              isLoading={isFetchingSheetsList}
              onSelect={onSelectSheetOption}
              optionWidth={DROPDOWN_DIMENSION.WIDTH}
              options={sheetsList}
              selected={selectedSheet}
              showLabelOnly
              width={DROPDOWN_DIMENSION.WIDTH}
            />
          </SelectWrapper>
        ) : null}
  
        {selectedSheet.value ? (
          <>
            <SelectWrapper width={DROPDOWN_DIMENSION.WIDTH}>
              <Row>
                <RowHeading>
                  {createMessage(GEN_CRUD_TABLE_HEADER_LABEL)}
                </RowHeading>
                <TooltipWrapper>
                  <Tooltip
                    content={createMessage(GEN_CRUD_TABLE_HEADER_TOOLTIP_DESC)}
                    hoverOpenDelay={200}
                  >
                    <RoundBg>
                      <Icon
                        fillColor={Colors.WHITE}
                        hoverFillColor={Colors.WHITE}
                        name="help"
                        size={IconSize.XXS}
                      />
                    </RoundBg>
                  </Tooltip>
                </TooltipWrapper>
              </Row>
              <TextInput
                dataType="text"
                fill
                onChange={tableHeaderIndexChangeHandler}
                placeholder="Table Header Index"
                value={tableHeaderIndex}
              />
            </SelectWrapper>
            <ColumnInfoWrapper>
              {columnHeaderList.length ? (
                <>
                  <Text type={TextType.P3} weight={FontWeight.BOLD}>
                    {createMessage(GEN_CRUD_COLUMN_HEADER_TITLE)} :&nbsp;
                  </Text>
                  {columnHeaderList
                    .slice(0, MAX_COLUMNS_VISIBLE)
                    .map((column, index) => (
                      <ColumnNameWrapper key={column.id}>
                        <ColumnName>{column.label}</ColumnName>
                        {columnHeaderList.length - 1 === index ? null : (
                          <ColumnName>,&nbsp;</ColumnName>
                        )}
                      </ColumnNameWrapper>
                    ))}
                  {columnHeaderList.length > MAX_COLUMNS_VISIBLE ? (
                    <ColumnName>
                      and +{columnHeaderList.length - MAX_COLUMNS_VISIBLE} more.
                    </ColumnName>
                  ) : (
                    ""
                  )}
                </>
              ) : (
                <ColumnName>{createMessage(GEN_CRUD_NO_COLUMNS)}</ColumnName>
              )}
            </ColumnInfoWrapper>
          </>
        ) : null}
  
        {selectedSheet.value
          ? renderSubmitButton({
              onSubmit,
              disabled: !columnHeaderList.length || isFetchingColumnHeaderList,
              isLoading: isFetchingColumnHeaderList,
            })
          : null}
      </>
    );
  }
  
  export default GoogleSheetForm;
  