Skip to content

Commit

Permalink
docs[minor]: Swap gtag for supabase (langchain-ai#18937)
Browse files Browse the repository at this point in the history
Added deps:
- `@supabase/supabase-js` - for sending inserts
- `supabase` - dev dep, for generating types via cli
- `dotenv` for loading env vars

Added script:
- `yarn gen` - will auto generate the database schema types using the
supabase CLI. Not necessary for development, but is useful. Requires
authing with the supabase CLI (will error out w/ instructions if you're
not authed).

Added functionality:
- pulls users IP address (using a free endpoint: `https://api.ipify.org`
so we can filter out abuse down the line)

TODO:
- [x] add env vars to vercel
  • Loading branch information
bracesproul authored Mar 11, 2024
1 parent 5c2f7e6 commit 4ff6aa5
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 15,840 deletions.
1 change: 1 addition & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/.quarto/
src/supabase.d.ts
13 changes: 7 additions & 6 deletions docs/docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Note: type annotations allow type checking and IDEs autocompletion
// eslint-disable-next-line import/no-extraneous-dependencies
const { ProvidePlugin } = require("webpack");
const path = require("path");
require("dotenv").config();

const baseLightCodeBlockTheme = require("prism-react-renderer/themes/vsLight");
const baseDarkCodeBlockTheme = require("prism-react-renderer/themes/vsDark");
Expand Down Expand Up @@ -335,12 +335,13 @@ const config = {
src: "https://www.googletagmanager.com/gtag/js?id=G-9B66JQQH2F",
async: true,
},
{
src: "https://www.googletagmanager.com/gtag/js?id=G-WFT0J048RF",
async: true,
}
],


customFields: {
NEXT_PUBLIC_SUPABASE_PUBLIC_KEY:
process.env.NEXT_PUBLIC_SUPABASE_PUBLIC_KEY,
NEXT_PUBLIC_SUPABASE_URL: process.env.NEXT_PUBLIC_SUPABASE_URL,
},
};

module.exports = config;
15,800 changes: 0 additions & 15,800 deletions docs/package-lock.json

This file was deleted.

7 changes: 6 additions & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@
"lint:fix": "yarn lint --fix",
"precommit": "lint-staged",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,md,mdx}\"",
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,md,mdx}\""
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,md,mdx}\"",
"gen": "yarn gen:supabase",
"gen:supabase": "npx supabase gen types typescript --project-id 'xsqpnijvmbodcxyapnyq' --schema public > ./src/supabase.d.ts"
},
"dependencies": {
"@docusaurus/core": "2.4.3",
"@docusaurus/preset-classic": "2.4.3",
"@docusaurus/remark-plugin-npm2yarn": "^2.4.3",
"@docusaurus/theme-mermaid": "2.4.3",
"@mdx-js/react": "^1.6.22",
"@supabase/supabase-js": "^2.39.7",
"clsx": "^1.2.1",
"cookie": "^0.6.0",
"json-loader": "^0.5.7",
Expand All @@ -36,6 +39,7 @@
"devDependencies": {
"@babel/eslint-parser": "^7.18.2",
"docusaurus-plugin-typedoc": "next",
"dotenv": "^16.4.5",
"eslint": "^8.19.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^8.5.0",
Expand All @@ -45,6 +49,7 @@
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^4.6.0",
"prettier": "^2.7.1",
"supabase": "^1.148.6",
"typedoc": "^0.24.4",
"typedoc-plugin-markdown": "next",
"yaml-loader": "^0.8.0"
Expand Down
5 changes: 0 additions & 5 deletions docs/src/analytics.js

This file was deleted.

78 changes: 60 additions & 18 deletions docs/src/theme/Feedback.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable no-return-assign, react/jsx-props-no-spreading */
import React, { useState, useEffect } from "react";
import gtag from "../analytics";
import { createClient } from "@supabase/supabase-js";

const useCookie = () => {
/**
Expand Down Expand Up @@ -90,27 +90,69 @@ function SvgThumbsDown() {
);
}

/**
* 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<string>}
*/
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 [feedbackSent, setFeedbackSent] = useState(false);

/**
* @param {"good" | "bad"} feedback
*/
const handleFeedback = (feedback) => {
/** @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;
}

const feedbackEnv =
process.env.NODE_ENV === "production"
? "page_feedback"
: "page_feedback_dev";
/** @type {Database} */
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_PUBLIC_KEY
);
try {
const ipAddress = await getIpAddress();

/**
* "id" and "created_at" are automatically generated by Supabase
* @type {Omit<Database["public"]["Tables"]["feedback"]["Row"], "id" | "created_at">}
*/
const data = {
is_good: feedback === "good",
url: window.location.pathname,
user_ip: ipAddress,
project: LANGCHAIN_PROJECT_NAME,
};

const { error } = await supabase.from("feedback").insert(data);
if (error) {
throw error;
}
} catch (e) {
console.error("Failed to send feedback", {
e,
});
return;
}

gtag("event", `${feedbackEnv}_${feedback}`, {});
// Set a cookie to prevent feedback from being sent multiple times
setCookie(cookieName, window.location.pathname, 1);
setFeedbackSent(true);
Expand Down Expand Up @@ -161,16 +203,16 @@ export default function Feedback() {
{...defaultFields}
role="button" // Make it recognized as an interactive element
tabIndex={0} // Make it focusable
onKeyDown={(e) => {
onKeyDown={async (e) => {
// Handle keyboard interaction
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
handleFeedback("good");
await handleFeedback("good");
}
}}
onClick={(e) => {
onClick={async (e) => {
e.preventDefault();
handleFeedback("good");
await handleFeedback("good");
}}
>
<SvgThumbsUp />
Expand All @@ -179,16 +221,16 @@ export default function Feedback() {
{...defaultFields}
role="button" // Make it recognized as an interactive element
tabIndex={0} // Make it focusable
onKeyDown={(e) => {
onKeyDown={async (e) => {
// Handle keyboard interaction
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
handleFeedback("bad");
await handleFeedback("bad");
}
}}
onClick={(e) => {
onClick={async (e) => {
e.preventDefault();
handleFeedback("bad");
await handleFeedback("bad");
}}
>
<SvgThumbsDown />
Expand Down
6 changes: 0 additions & 6 deletions docs/static/js/google_analytics.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,3 @@ function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());

gtag('config', 'G-9B66JQQH2F');

// Only for feedback
function gtagFeedback(){dataLayer.push(arguments);}
gtagFeedback('js', new Date());

gtagFeedback('config', 'G-WFT0J048RF');
Loading

0 comments on commit 4ff6aa5

Please sign in to comment.