/* eslint-disable no-return-assign, react/jsx-props-no-spreading */ import React, { useState, useEffect } from "react"; import { createClient } from "@supabase/supabase-js"; import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; import { v4 as uuidv4 } from "uuid"; const useCookie = () => { /** * Function to set a cookie * @param {string} name The name of the cookie to set * @param {string} value The value of the cookie * @param {number} days the number of days until the cookie expires */ const setCookie = (name, value, days) => { const d = new Date(); d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000); const expires = `expires=${d.toUTCString()}`; document.cookie = `${name}=${value};${expires};path=/`; }; /** * Function to get a cookie by name * @param {string} name The name of the cookie to get * @returns {string} The value of the cookie */ const getCookie = (name) => { const ca = document.cookie.split(";"); const caLen = ca.length; const cookieName = `${name}=`; let c; for (let i = 0; i < caLen; i += 1) { c = ca[i].replace(/^\s+/g, ""); if (c.indexOf(cookieName) === 0) { return c.substring(cookieName.length, c.length); } } return ""; }; /** * Function to check cookie existence * @param {string} name The name of the cookie to check for * @returns {boolean} Whether or not the cookie exists */ const checkCookie = (name) => { const cookie = getCookie(name); if (cookie !== "") { return true; } return false; }; return { setCookie, checkCookie }; }; function SvgThumbsUp() { return ( ); } function SvgThumbsDown() { return ( ); } /** * Generated type for the Supabase DB schema. * @typedef {import('../supabase').Database} Database */ const FEEDBACK_COOKIE_PREFIX = "feedbackSent"; /** @type {Database["public"]["Enums"]["project_type"]} */ const LANGCHAIN_PROJECT_NAME = "langchain_py_docs"; /** * @returns {Promise} */ const getIpAddress = async () => { const response = await fetch("https://api.ipify.org?format=json"); return (await response.json()).ip; }; export default function Feedback() { const { setCookie, checkCookie } = useCookie(); const [feedbackId, setFeedbackId] = useState(null); const [feedbackSent, setFeedbackSent] = useState(false); const [feedbackDetailsSent, setFeedbackDetailsSent] = useState(false); const { siteConfig } = useDocusaurusContext(); const [pathname, setPathname] = useState(""); /** @param {"good" | "bad"} feedback */ const handleFeedback = async (feedback) => { if (process.env.NODE_ENV !== "production") { console.log("Feedback (dev)"); return; } const cookieName = `${FEEDBACK_COOKIE_PREFIX}_${window.location.pathname}`; if (checkCookie(cookieName)) { return; } /** @type {Database} */ const supabase = createClient( siteConfig.customFields.supabaseUrl, siteConfig.customFields.supabasePublicKey ); try { const ipAddress = await getIpAddress(); const rowId = uuidv4(); setFeedbackId(rowId); const params = { id: rowId, is_good: feedback === "good", url: window.location.pathname, user_ip: ipAddress, project: LANGCHAIN_PROJECT_NAME, }; const { error } = await supabase.from("feedback").insert(params); if (error) { throw error; } } catch (e) { console.error("Failed to send feedback", e); return; } // Set a cookie to prevent feedback from being sent multiple times setCookie(cookieName, window.location.pathname, 1); setFeedbackSent(true); }; const handleFeedbackDetails = async (e) => { e.preventDefault(); if (!feedbackId) { setFeedbackDetailsSent(true); return; } const details = e.target.elements .namedItem("details") ?.value.slice(0, 1024); if (!details) { return; } const supabase = createClient( siteConfig.customFields.supabaseUrl, siteConfig.customFields.supabasePublicKey ); const { error } = await supabase.from("feedback_details").insert({ feedback_id: feedbackId, details, }); if (error) { console.error("Failed to add feedback details", error); return; } setFeedbackDetailsSent(true); }; useEffect(() => { if (typeof window !== "undefined") { // If the cookie exists, set feedback sent to // true so the user can not send feedback again // (cookies exp in 24hrs) const cookieName = `${FEEDBACK_COOKIE_PREFIX}_${window.location.pathname}`; setFeedbackSent(checkCookie(cookieName)); setPathname(window.location.pathname); } }, []); const defaultFields = { style: { display: "flex", alignItems: "center", paddingTop: "10px", paddingBottom: "10px", paddingLeft: "22px", paddingRight: "22px", border: "1px solid gray", borderRadius: "6px", gap: "10px", cursor: "pointer", fontSize: "16px", fontWeight: "600", }, onMouseEnter: (e) => (e.currentTarget.style.backgroundColor = "#f0f0f0"), onMouseLeave: (e) => (e.currentTarget.style.backgroundColor = "transparent"), onMouseDown: (e) => (e.currentTarget.style.backgroundColor = "#d0d0d0"), onMouseUp: (e) => (e.currentTarget.style.backgroundColor = "#f0f0f0"), }; return (

{feedbackSent ? ( <>

Thanks for your feedback!

{!feedbackDetailsSent && feedbackId && (

Do you have any specific comments?