import React, { useState, useEffect } from "react"; import { GenericModal } from "../ui/GenericModal"; import { MenuItem, Typography, CircularProgress, Alert, AlertTitle, } from "@mui/material"; import Button from "@mui/material/Button"; import TextField from "@mui/material/TextField"; import axios from "axios"; import { useGlobalInfoStore } from "../../context/globalInfo"; import { getStoredRecording } from "../../api/storage"; import { apiUrl } from "../../apiConfig.js"; import Cookies from "js-cookie"; import { useTranslation } from "react-i18next"; interface IntegrationProps { isOpen: boolean; handleStart: (data: IntegrationSettings) => void; handleClose: () => void; } export interface IntegrationSettings { spreadsheetId: string; spreadsheetName: string; airtableBaseId: string; airtableBaseName: string; data: string; } // Helper functions to replace js-cookie functionality const getCookie = (name: string): string | null => { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) { return parts.pop()?.split(";").shift() || null; } return null; }; const removeCookie = (name: string): void => { document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`; }; export const IntegrationSettingsModal = ({ isOpen, handleStart, handleClose, }: IntegrationProps) => { const { t } = useTranslation(); const [settings, setSettings] = useState({ spreadsheetId: "", spreadsheetName: "", airtableBaseId: "", airtableBaseName: "", data: "", }); const [spreadsheets, setSpreadsheets] = useState<{ id: string; name: string }[]>([]); const [airtableBases, setAirtableBases] = useState<{ id: string; name: string }[]>([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const { recordingId, notify } = useGlobalInfoStore(); const [recording, setRecording] = useState(null); // Authenticate with Google const authenticateWithGoogle = () => { const redirectUri = `${window.location.origin}/google/callback`; window.location.href = `${apiUrl}/auth/google?robotId=${recordingId}&redirect_uri=${encodeURIComponent(redirectUri)}`; }; const authenticateWithAirtable = () => { const redirectUri = `${window.location.origin}/airtable/callback`; window.location.href = `${apiUrl}/auth/airtable?robotId=${recordingId}&redirect_uri=${encodeURIComponent(redirectUri)}`; }; // Handle OAuth callback const handleGoogleCallback = async () => { try { const urlParams = new URLSearchParams(window.location.search); const code = urlParams.get('code'); if (!code) { setError(t("integration_settings.errors.no_auth_code")); return; } const response = await axios.get( `${apiUrl}/auth/google/callback?code=${code}&robotId=${recordingId}` ); if (response.data.accessToken) { notify("success", t("integration_settings.notifications.google_auth_success")); await fetchSpreadsheetFiles(); } // Clear URL parameters window.history.replaceState({}, document.title, window.location.pathname); } catch (error) { setError(t("integration_settings.errors.google_auth_error")); } }; const handleAirtableCallback = async () => { try { const urlParams = new URLSearchParams(window.location.search); const code = urlParams.get('code'); if (!code) { setError(t("integration_settings.errors.no_auth_code")); return; } const response = await axios.get( `${apiUrl}/auth/airtable/callback?code=${code}&robotId=${recordingId}` ); if (response.data.accessToken) { notify("success", t("integration_settings.notifications.airtable_auth_success")); await fetchAirtableBases(); } // Clear URL parameters window.history.replaceState({}, document.title, window.location.pathname); } catch (error) { setError(t("integration_settings.errors.airtable_auth_error")); } }; // Fetch Google Sheets const fetchSpreadsheetFiles = async () => { try { const response = await axios.get(`${apiUrl}/auth/gsheets/files?robotId=${recordingId}`, { withCredentials: true, }); setSpreadsheets(response.data); } catch (error: any) { console.error("Error fetching spreadsheet files:", error.response?.data?.message || error.message); notify("error", t("integration_settings.errors.fetch_error", { message: error.response?.data?.message || error.message })); } }; // Fetch Airtable Bases const fetchAirtableBases = async () => { try { const response = await axios.get(`${apiUrl}/auth/airtable/bases?robotId=${recordingId}`, { withCredentials: true, }); setAirtableBases(response.data); } catch (error: any) { console.error("Error fetching Airtable bases:", error.response?.data?.message || error.message); notify("error", t("integration_settings.errors.fetch_error", { message: error.response?.data?.message || error.message })); } }; // Handle Google Sheet selection const handleSpreadsheetSelect = (e: React.ChangeEvent) => { const selectedSheet = spreadsheets.find((sheet) => sheet.id === e.target.value); if (selectedSheet) { setSettings({ ...settings, spreadsheetId: selectedSheet.id, spreadsheetName: selectedSheet.name, }); } }; // Handle Airtable Base selection const handleAirtableBaseSelect = (e: React.ChangeEvent) => { const selectedBase = airtableBases.find((base) => base.id === e.target.value); if (selectedBase) { setSettings({ ...settings, airtableBaseId: selectedBase.id, airtableBaseName: selectedBase.name, }); } }; // Update Google Sheet ID const updateGoogleSheetId = async () => { try { const response = await axios.post( `${apiUrl}/auth/gsheets/update`, { spreadsheetId: settings.spreadsheetId, spreadsheetName: settings.spreadsheetName, robotId: recordingId, }, { withCredentials: true } ); notify("success", t("integration_settings.notifications.sheet_selected")); console.log("Google Sheet ID updated:", response.data); } catch (error: any) { console.error("Error updating Google Sheet ID:", error.response?.data?.message || error.message); } }; // Update Airtable Base ID const updateAirtableBaseId = async () => { try { const response = await axios.post( `${apiUrl}/auth/airtable/update`, { baseId: settings.airtableBaseId, baseName: settings.airtableBaseName, robotId: recordingId, }, { withCredentials: true } ); notify("success", t("integration_settings.notifications.base_selected")); console.log("Airtable Base ID updated:", response.data); } catch (error: any) { console.error("Error updating Airtable Base ID:", error.response?.data?.message || error.message); } }; // Remove Integration const removeIntegration = async () => { try { await axios.post( `${apiUrl}/auth/gsheets/remove`, { robotId: recordingId }, { withCredentials: true } ); setRecording(null); setSpreadsheets([]); setAirtableBases([]); setSettings({ spreadsheetId: "", spreadsheetName: "", airtableBaseId: "", airtableBaseName: "", data: "" }); } catch (error: any) { console.error("Error removing integration:", error.response?.data?.message || error.message); } }; useEffect(() => { const checkAuthCallback = () => { const path = window.location.pathname; const urlParams = new URLSearchParams(window.location.search); const code = urlParams.get('code'); if (code) { if (path.includes('/google/callback')) { handleGoogleCallback(); } else if (path.includes('/airtable/callback')) { handleAirtableCallback(); } } }; checkAuthCallback(); // Cleanup function return () => { window.history.replaceState({}, document.title, window.location.pathname); }; }, []); return (
{t("integration_settings.title")} {recording && (recording.google_sheet_id || recording.airtable_base_id) ? ( <> {recording.google_sheet_id && ( {t("integration_settings.alerts.success.title")} {t("integration_settings.alerts.success.content", { sheetName: recording.google_sheet_name })} {t("integration_settings.alerts.success.here")} .
{t("integration_settings.alerts.success.note")} {t("integration_settings.alerts.success.sync_limitation")}
)} {recording.airtable_base_id && ( {t("integration_settings.alerts.success.title")} {t("integration_settings.alerts.success.content", { sheetName: recording.airtable_base_name })} {t("integration_settings.alerts.success.here")} .
{t("integration_settings.alerts.success.note")} {t("integration_settings.alerts.success.sync_limitation")}
)} ) : ( <> {!recording?.google_sheet_email && !recording?.airtable_email ? ( <>

{t("integration_settings.descriptions.sync_info")}

) : ( <> {(recording.google_sheet_email || recording.airtable_email) && ( {t("integration_settings.descriptions.authenticated_as", { email: recording.google_sheet_email || recording.airtable_email, })} )} {loading ? ( ) : error ? ( {error} ) : ( <> {recording.google_sheet_email && ( <> {spreadsheets.map((sheet) => ( {sheet.name} ))} {settings.spreadsheetId && ( {t("integration_settings.fields.selected_sheet", { name: spreadsheets.find((s) => s.id === settings.spreadsheetId)?.name, id: settings.spreadsheetId, })} )} )} {recording.airtable_email && ( <> {airtableBases.map((base) => ( {base.name} ))} {settings.airtableBaseId && ( {t("integration_settings.fields.selected_base", { name: airtableBases.find((b) => b.id === settings.airtableBaseId)?.name, id: settings.airtableBaseId, })} )} )} )} )} )}
); }; export const modalStyle = { top: "40%", left: "50%", transform: "translate(-50%, -50%)", width: "50%", backgroundColor: "background.paper", p: 4, height: "fit-content", display: "block", padding: "20px", };