diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..97d817a4c --- /dev/null +++ b/.env.example @@ -0,0 +1,6 @@ +BACKEND_URL= +NEXT_PUBLIC_GOOGLE_ANALYTICS_TRACKING_ID= +NEXT_PUBLIC_ALGOLIA_APP_ID= +NEXT_PUBLIC_ALGOLIA_API_KEY= +NEXT_PUBLIC_ALGOLIA_INDEX= +NEWSLETTER_BASE_URL= diff --git a/.env.local b/.env.local deleted file mode 100644 index 5026a3e51..000000000 --- a/.env.local +++ /dev/null @@ -1,2 +0,0 @@ -NEXT_PUBLIC_BACKEND_URL=https://profilio-staging.sandbox-london-b.fetch-ai.com -NEXT_PUBLIC_GOOGLE_ANALYTICS_TRACKING_ID=G-GYC9HYF1LD \ No newline at end of file diff --git a/.github/workflows/deploy-production.yml b/.github/workflows/deploy-production.yml index 1b417f6f2..11afdab88 100644 --- a/.github/workflows/deploy-production.yml +++ b/.github/workflows/deploy-production.yml @@ -39,6 +39,10 @@ jobs: env: BACKEND_URL: ${{ secrets.NEXT_PUBLIC_BACKEND_URL }} NEXT_PUBLIC_GOOGLE_ANALYTICS_TRACKING_ID: ${{ secrets.NEXT_PUBLIC_GOOGLE_ANALYTICS_TRACKING_ID }} + NEXT_PUBLIC_ALGOLIA_APP_ID: ${{ secrets.NEXT_PUBLIC_ALGOLIA_APP_ID }} + NEXT_PUBLIC_ALGOLIA_API_KEY: ${{ secrets.NEXT_PUBLIC_ALGOLIA_API_KEY }} + NEXT_PUBLIC_ALGOLIA_INDEX: ${{ secrets.NEXT_PUBLIC_ALGOLIA_INDEX }} + NEWSLETTER_BASE_URL: ${{ secrets.NEWSLETTER_BASE_URL }} SENDER_TOKEN: ${{ secrets.SENDER_TOKEN }} - name: Trigger Image Update diff --git a/.github/workflows/deploy-staging.yml b/.github/workflows/deploy-staging.yml index 41b77a13f..f401d162c 100644 --- a/.github/workflows/deploy-staging.yml +++ b/.github/workflows/deploy-staging.yml @@ -39,6 +39,10 @@ jobs: env: BACKEND_URL: ${{ secrets.STAGING_NEXT_PUBLIC_BACKEND_URL }} NEXT_PUBLIC_GOOGLE_ANALYTICS_TRACKING_ID: ${{ secrets.NEXT_PUBLIC_GOOGLE_ANALYTICS_TRACKING_ID }} + NEXT_PUBLIC_ALGOLIA_APP_ID: ${{ secrets.NEXT_PUBLIC_ALGOLIA_APP_ID }} + NEXT_PUBLIC_ALGOLIA_API_KEY: ${{ secrets.NEXT_PUBLIC_ALGOLIA_API_KEY }} + NEXT_PUBLIC_ALGOLIA_INDEX: ${{ secrets.NEXT_PUBLIC_ALGOLIA_INDEX }} + NEWSLETTER_BASE_URL: ${{ secrets.NEWSLETTER_BASE_URL }} SENDER_TOKEN: ${{ secrets.SENDER_TOKEN }} deploy: diff --git a/.github/workflows/ephemeral-deploy.yaml b/.github/workflows/ephemeral-deploy.yaml index bd420f991..032be3537 100644 --- a/.github/workflows/ephemeral-deploy.yaml +++ b/.github/workflows/ephemeral-deploy.yaml @@ -40,6 +40,10 @@ jobs: env: BACKEND_URL: ${{ secrets.STAGING_NEXT_PUBLIC_BACKEND_URL }} NEXT_PUBLIC_GOOGLE_ANALYTICS_TRACKING_ID: ${{ secrets.NEXT_PUBLIC_GOOGLE_ANALYTICS_TRACKING_ID }} + NEXT_PUBLIC_ALGOLIA_APP_ID: ${{ secrets.NEXT_PUBLIC_ALGOLIA_APP_ID }} + NEXT_PUBLIC_ALGOLIA_API_KEY: ${{ secrets.NEXT_PUBLIC_ALGOLIA_API_KEY }} + NEXT_PUBLIC_ALGOLIA_INDEX: ${{ secrets.NEXT_PUBLIC_ALGOLIA_INDEX }} + NEWSLETTER_BASE_URL: ${{ secrets.NEWSLETTER_BASE_URL }} SENDER_TOKEN: ${{ secrets.SENDER_TOKEN }} deploy: diff --git a/Dockerfile b/Dockerfile index a55f91123..d03607e29 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,11 @@ FROM node:18-alpine ARG BACKEND_URL="" +ARG NEXT_PUBLIC_GOOGLE_ANALYTICS_TRACKING_ID="" +ARG NEXT_PUBLIC_ALGOLIA_APP_ID="" +ARG NEXT_PUBLIC_ALGOLIA_API_KEY="" +ARG NEXT_PUBLIC_ALGOLIA_INDEX="" +ARG NEWSLETTER_BASE_URL="" ARG SENDER_TOKEN="" RUN apk add tree && corepack prepare pnpm@8.6.10 --activate && corepack enable @@ -17,6 +22,10 @@ ENV NODE_ENV="production" RUN echo BACKEND_URL="${BACKEND_URL}" > .env.local && \ echo SENDER_TOKEN="${SENDER_TOKEN}" > .env.local && \ echo NEXT_PUBLIC_GOOGLE_ANALYTICS_TRACKING_ID="${NEXT_PUBLIC_GOOGLE_ANALYTICS_TRACKING_ID}" >> .env.local && \ + echo NEXT_PUBLIC_ALGOLIA_APP_ID="${NEXT_PUBLIC_ALGOLIA_APP_ID}" >> .env.local && \ + echo NEXT_PUBLIC_ALGOLIA_API_KEY="${NEXT_PUBLIC_ALGOLIA_API_KEY}" >> .env.local && \ + echo NEXT_PUBLIC_ALGOLIA_INDEX="${NEXT_PUBLIC_ALGOLIA_INDEX}" >> .env.local && \ + echo NEWSLETTER_BASE_URL="${NEWSLETTER_BASE_URL}" >> .env.local && \ pnpm build ENTRYPOINT ["pnpm"] diff --git a/README.md b/README.md index 725c1f4b9..60a91642b 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,6 @@ Select the appropriate route, and create a new file ending in `.mdx`. Then, upda } ``` -## Deployments - -### Staging Website - -https://docs-staging.sandbox-london-b.fetch-ai.com/docs - ## Developing ### Install dependencies diff --git a/components/account-menu.tsx b/components/account-menu.tsx deleted file mode 100644 index 80e6d2422..000000000 --- a/components/account-menu.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import React, { useState, FC } from "react"; -import ProfileIcon from "../src/svgs/profile.svg"; -import Image from "next/image"; - -interface AccountMenuProps { - email: string; - logo: string; - signOut: () => void; -} - -const AccountMenu: FC = ({ email, logo, signOut }) => { - const [open, setOpen] = useState(false); - - const handleClick = () => { - setOpen(!open); - }; - return ( -
- - {open && ( -
-
- -

- You are signed in as -

-

- {email} -

-
-
- -
-
- )} -
- ); -}; - -export default AccountMenu; diff --git a/components/api-endpoint.tsx b/components/api-endpoint.tsx index db4a494a8..a961260e2 100644 --- a/components/api-endpoint.tsx +++ b/components/api-endpoint.tsx @@ -9,10 +9,8 @@ import { Tab, DropDownTabs, } from "./mdx"; -import { useUserContext } from "theme/fetch-ai-docs/contexts/context-provider"; import Tooltip from "./tooltip"; import Link from "next/link"; -import fetchJson from "src/lib/fetch-json"; interface PropertyType { name: string; @@ -347,29 +345,27 @@ export const ApiEndpointRequestResponse: React.FC<{ setIsModalOpen(false); }; - const context = useUserContext(); - - const hitRequest = async () => { + const hitRequestWithoutLogin = async () => { try { setLoading(true); setError(""); const requestPayloadJSON = JSON.parse(requestPayload || "{}"); const apiUrlWithParams = (properties.apiUrl + replacePathParameters(properties.path, pathParameters)) as string; - - const response: { data: unknown } = await fetchJson( - `/docs/api/api-requests?url=${apiUrlWithParams}`, - { - method: properties.method, - body: properties.method.includes("GET") ? null : requestPayloadJSON, + const response = await fetch(apiUrlWithParams, { + method: properties.method, + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${bearerToken}`, }, - ); - const responseText = JSON.stringify(response.data, null, 2); + body: properties.method.includes("GET") + ? null + : JSON.stringify(requestPayloadJSON), + }); + const data = await response.json(); + const responseText = JSON.stringify(data, null, 2); setActualResponse(responseText); } catch (error) { - if (error.response.status === 422) { - context.signOut(); - } setError(`Error: ${error.message}`); } finally { setLoading(false); @@ -420,7 +416,7 @@ export const ApiEndpointRequestResponse: React.FC<{
- {!context?.isLoggedIn && isBearerTokenRequired && ( + {isBearerTokenRequired && (

@@ -530,7 +526,7 @@ export const ApiEndpointRequestResponse: React.FC<{

diff --git a/components/footer.tsx b/components/footer.tsx index d2a6a4cf2..bbe7e76a8 100644 --- a/components/footer.tsx +++ b/components/footer.tsx @@ -208,7 +208,7 @@ const Footer: React.FC = () => {
- Sign up to for developer updates + Sign up for developer updates
str: diff --git a/pages/api/api-requests.ts b/pages/api/api-requests.ts deleted file mode 100644 index a878b76c3..000000000 --- a/pages/api/api-requests.ts +++ /dev/null @@ -1,101 +0,0 @@ -/* eslint-disable no-useless-catch */ -import axios from "axios"; -import { getCookie, setCookie, deleteCookie } from "cookies-next"; -import { NextApiRequest, NextApiResponse } from "next"; - -class CustomError extends Error { - status: number; - - constructor(message: string, status: number) { - super(message); - this.status = status; - } -} - -async function getNewAccessToken(refreshToken: string) { - try { - const response = await fetch(`https://accounts.fetch.ai/v1/tokens`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - grant_type: "refresh_token", - refresh_token: refreshToken, - }), - }); - const data = await response.json(); - if (response.ok && response.status === 200) { - return data.access_token; - } - if (response.status === 422) { - throw new CustomError("Refresh token expired", 422); - } - } catch (refreshError) { - throw new CustomError(refreshError.message, 422); - } -} - -async function retryRequest( - req: NextApiRequest, - res: NextApiResponse, - accessToken: string, - url: string, -) { - try { - const response = await axios({ - method: req.method, - url: url, - headers: { Authorization: `Bearer ${accessToken}` }, - data: req.body, - }); - return res.status(response.status).json({ data: response.data }); - } catch (error) { - return res - .status(error.response.status) - .json({ error: error.response.data }); - } -} - -export default async function handler( - req: NextApiRequest, - res: NextApiResponse, -) { - const { url } = req.query; - const accessToken = getCookie("fauna", { req, res }); - const refreshToken = getCookie("refresh_token", { req, res }); - - try { - const response = await axios({ - method: req.method, - url: url as string, - headers: { Authorization: `Bearer ${accessToken}` }, - data: req.body, - }); - deleteCookie("fauna", { req, res }); - return res.status(response.status).json({ data: response.data }); - } catch (error) { - if (error.response.status === 401) { - try { - const newAccessToken = await getNewAccessToken(refreshToken); - if (newAccessToken) { - setCookie("fauna", newAccessToken, { req, res }); - return await retryRequest(req, res, newAccessToken, url as string); - } else { - return res - .status(422) - .json({ message: "unable to got new access token" }); - } - } catch (Error) { - if (Error.status === 422) { - return res.status(Error.status).json({ message: Error }); - } - return res.status(500).json({ message: Error }); - } - } else { - return res - .status(error.response.status) - .json({ error: error.response.data }); - } - } -} diff --git a/pages/api/content-visited.ts b/pages/api/content-visited.ts deleted file mode 100644 index d7cc25581..000000000 --- a/pages/api/content-visited.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* eslint-disable no-useless-catch */ -import { NextApiRequest, NextApiResponse } from "next"; -import { getAccessToken } from "./utils/api"; - -export default async (req: NextApiRequest, res: NextApiResponse) => { - try { - const { user_email } = req.query; - - const accessToken = await getAccessToken(req, res); - - const myHeaders = new Headers(); - - myHeaders.append("Authorization", `Bearer ${accessToken}`); - - const response = await fetch( - `${process.env.BACKEND_URL}/api/page-view?user_email=${user_email}`, - { - method: "GET", - headers: myHeaders, - redirect: "follow", - mode: "cors", - }, - ); - const data = await response.json(); - - return res.status(response.status).json(data); - } catch (error) { - res.status(error.response.status || 500).json({ error: error.message }); - } -}; diff --git a/pages/api/get-bookmarks.ts b/pages/api/get-bookmarks.ts deleted file mode 100644 index 93084bccd..000000000 --- a/pages/api/get-bookmarks.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { NextApiRequest, NextApiResponse } from "next"; -import { getAccessToken } from "./utils/api"; - -export default async function handler( - req: NextApiRequest, - res: NextApiResponse, -) { - const { user_email, is_visible } = req.query; - const accessToken = await getAccessToken(req, res); - - const myHeaders = new Headers(); - myHeaders.append("Authorization", `Bearer ${accessToken}`); - try { - const response = await fetch( - `${process.env.BACKEND_URL}/api/bookmarks?user_email=${user_email}&is_visible=${is_visible}`, - { - method: "GET", - headers: myHeaders, - redirect: "follow", - mode: "cors", - }, - ); - const data = await response.json(); - return res.status(response.status).json(data); - } catch (error) { - console.error(error); - return res.status(500).json({ error: "Internal Server Error" }); - } -} diff --git a/pages/api/last-updated.ts b/pages/api/last-updated.ts deleted file mode 100644 index 72a4f8201..000000000 --- a/pages/api/last-updated.ts +++ /dev/null @@ -1,36 +0,0 @@ -// pages/api/last-updated.ts -import { NextApiRequest, NextApiResponse } from "next"; -import simpleGit from "simple-git"; - -async function getNoteLastUpdatedTimestamp(): Promise { - try { - const git = simpleGit(); - const log = await git.log({ file: `pages/notes.mdx`, n: 1 }); - - if (log && log.latest) { - const timestamp = new Date(log.latest.date); - return timestamp; - } else { - throw new Error("No commit history found for the specified file"); - } - } catch (error) { - console.error("Error getting last updated timestamp:", error); - throw new Error("Error getting last updated timestamp"); - } -} - -export default async function handler( - req: NextApiRequest, - res: NextApiResponse, -) { - try { - // Implement the logic to retrieve the last updated timestamp of the relevant docs file - // For demonstration purposes, a static timestamp is used here - const lastUpdatedTimestamp = await getNoteLastUpdatedTimestamp(); - - res.status(200).json({ lastUpdatedTimestamp }); - } catch (error) { - console.error("Error fetching last updated timestamp:", error); - res.status(500).json({ message: "Internal Server Error" }); - } -} diff --git a/pages/api/newsletter.ts b/pages/api/newsletter.ts index a5aa4e8d5..f99fba1fa 100644 --- a/pages/api/newsletter.ts +++ b/pages/api/newsletter.ts @@ -6,7 +6,7 @@ export default async function handler( ) { const email = req.body; try { - const url = new URL("https://api.sender.net/v2/subscribers"); + const url = new URL(`${process.env.NEWSLETTER_BASE_URL}/v2/subscribers`); const headers = { Authorization: `Bearer ${process.env.SENDER_TOKEN}`, "Content-Type": "application/json", diff --git a/pages/api/profile.ts b/pages/api/profile.ts deleted file mode 100644 index fb0b60933..000000000 --- a/pages/api/profile.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { withIronSessionApiRoute } from "iron-session/next"; -import { sessionOptions } from "src/core/session"; -import { NextApiRequest, NextApiResponse } from "next"; - -type User = { - email: string; - avatarHref: string; - id: string; - walletAddress?: string; -}; - -type Credentials = { - apiKey: string; - expiresAt: number; - group: string; - sub: string; -}; - -export type CombinedData = { - user?: User; - credentials?: Credentials; - isLoggedIn: boolean; -}; - -async function userRoute( - request: NextApiRequest, - response: NextApiResponse, -) { - response.setHeader("Cache-Control", "no-cache, maxage=0, must-revalidate"); - if (request.session.user || request.session.credentials) { - const user: User = { - email: request.session.user?.email ?? "", - walletAddress: request.session.user?.walletAddress ?? "", - avatarHref: request.session.user?.avatarHref ?? "", - id: request.session.user?.id ?? "", - }; - - const credentials: Credentials = { - apiKey: request.session.credentials?.apiKey ?? "", - expiresAt: request.session.credentials?.expiresAt ?? 0, - group: request.session.credentials?.group ?? "", - sub: request.session.credentials?.sub ?? "", - }; - - const combinedData: CombinedData = { - user, - credentials, - isLoggedIn: true, - }; - - response.json(combinedData); - } else { - response.json({ - isLoggedIn: false, - }); - } -} - -export default withIronSessionApiRoute(userRoute, sessionOptions); diff --git a/pages/api/search.ts b/pages/api/search.ts index bca506776..a2fc5bfc4 100644 --- a/pages/api/search.ts +++ b/pages/api/search.ts @@ -18,8 +18,7 @@ export default async function handler( }); const apiResponse = await response.json(); return res.status(response.status).json({ apiResponse }); - } catch (error) { - console.error(error); + } catch { return res.status(500).json({ error: "Internal Server Error" }); } } diff --git a/pages/api/set-bookmarks.ts b/pages/api/set-bookmarks.ts deleted file mode 100644 index 68b6bfccf..000000000 --- a/pages/api/set-bookmarks.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { NextApiRequest, NextApiResponse } from "next"; - -export default async function handler( - req: NextApiRequest, - res: NextApiResponse, -) { - const { user_email, saved_path, is_visible } = req.body; - try { - const response = await fetch(`${process.env.BACKEND_URL}/api/bookmark`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - user_email: user_email, - saved_path: saved_path, - is_visible: is_visible, - }), - }); - const apiResponse = await response.json(); - return res.status(response.status).json({ apiResponse }); - } catch (error) { - console.error(error); - return res.status(500).json({ error: "Internal Server Error" }); - } -} diff --git a/pages/api/set-content-visited.ts b/pages/api/set-content-visited.ts deleted file mode 100644 index 7c7349103..000000000 --- a/pages/api/set-content-visited.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { NextApiRequest, NextApiResponse } from "next"; - -export default async function handler( - req: NextApiRequest, - res: NextApiResponse, -) { - const { user_email, saved_path, is_visible } = req.body; - try { - const response = await fetch(`${process.env.BACKEND_URL}/api/page-view`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - user_email: user_email, - saved_path: saved_path, - is_visible: is_visible, - }), - }); - const apiResponse = await response.json(); - console.log(apiResponse); - return res.status(response.status).json({ apiResponse }); - } catch (error) { - console.error(error); - return res.status(500).json({ error: "Internal Server Error" }); - } -} diff --git a/pages/api/signout.ts b/pages/api/signout.ts deleted file mode 100644 index ecf6848d6..000000000 --- a/pages/api/signout.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { withIronSessionApiRoute } from "iron-session/next"; -import { sessionOptions } from "src/core/session"; -import { NextApiRequest, NextApiResponse } from "next"; -import { CombinedData } from "./profile"; - -async function userRoute( - request: NextApiRequest, - response: NextApiResponse, -) { - response.setHeader("Cache-Control", "no-cache, maxage=0, must-revalidate"); - request.session.destroy(); - response.json({ - isLoggedIn: false, - user: { email: "", avatarHref: "", id: "" }, - credentials: { apiKey: "", expiresAt: 0, group: "", sub: "" }, - }); -} - -export default withIronSessionApiRoute(userRoute, sessionOptions); diff --git a/pages/api/utils/api.ts b/pages/api/utils/api.ts deleted file mode 100644 index 24b95c109..000000000 --- a/pages/api/utils/api.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { setCookie, getCookie, deleteCookie } from "cookies-next"; -import { getNewAccessToken } from "src/core/fauna"; -import { parseJwt } from "src/core/jwt"; - -export const getAccessToken = async (req, res) => { - try { - let accessToken = getCookie("fauna", { req, res }); - const refreshToken = getCookie("refresh_token", { req, res }); - - if (!accessToken || !refreshToken) { - throw { message: "Access token or refresh token is missing" }; - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const decodedToken: any = parseJwt(accessToken); - if (!decodedToken) { - throw { message: "Invalid access token" }; - } - - if (decodedToken.expiry < Date.now() - 5000) { - // Access token expired, refresh it - const newAcessToken = await getNewAccessToken(refreshToken); - if (newAcessToken.accessToken) { - accessToken = newAcessToken.accessToken; - setCookie("fauna", accessToken, { req, res }); - } else { - deleteCookie("fauna"); - } - } - - return accessToken; - } catch (error) { - res.status(401).json({ error: error.message }); - } -}; diff --git a/pages/apis/ai-engine/_meta.json b/pages/apis/ai-engine/_meta.json index a1326eafe..99321108d 100644 --- a/pages/apis/ai-engine/_meta.json +++ b/pages/apis/ai-engine/_meta.json @@ -1,17 +1,5 @@ { "chat": "Chat API", "functions": "Functions API", - "function_groups": "Function Groups API", - "analytics": { - "title": "Analytics API", - "permission": ["fetch.ai"] - }, - "llm": { - "title": "LLM API", - "permission": ["fetch.ai"] - }, - "services": { - "title": "Services API (deprecated)", - "permission": ["fetch.ai"] - } + "function_groups": "Function Groups API" } diff --git a/pages/apis/ai-engine/analytics.mdx b/pages/apis/ai-engine/analytics.mdx deleted file mode 100644 index 926c736ca..000000000 --- a/pages/apis/ai-engine/analytics.mdx +++ /dev/null @@ -1,187 +0,0 @@ -import { Row, Col } from "../../../components/mdx"; -import { - ApiEndpointRequestResponse, -} from "../../../components/api-endpoint"; - - -# AI-Engine Analytics API - - -
- This API provides access to analytics of agents and functions. -
- -## Overview - - - - The Analytics API allows to access the data that can be used to analyze the performance of a function or an agent. - - - ```bash filename="Endpoints" - GET /v1beta1/engine/analytics/agent/:agent_address/performance/ - - GET /v1beta1/engine/analytics/:function_id/performance/ - - GET /v1beta1/engine/analytics/:function_id/insights/ - ``` - - - - -### Get agent's performance - - - -### Get function's performance - - - - -### Get function's interactions - - \ No newline at end of file diff --git a/pages/apis/ai-engine/llm.mdx b/pages/apis/ai-engine/llm.mdx deleted file mode 100644 index e37badc7a..000000000 --- a/pages/apis/ai-engine/llm.mdx +++ /dev/null @@ -1,111 +0,0 @@ -import { Row, Col } from "../../../components/mdx"; -import { - ApiEndpointRequestResponse, -} from "../../../components/api-endpoint"; - - -# AI-Engine LLM API - - -
- This API provides access to open source LLM models. - Available models: - * Mistral 7B: mistral-v0-7b-instruct - * LLama2 70B chat: llama2-v0-70b-chat-gptq -
- -## Overview - - - - The LLM API allows to use open source LLM for completion. - - - ```bash filename="Endpoints" - POST /v1beta1/engine/llm/completion - ``` - - - - -## Generate text using our API - -In order to get completion from LLM, similar to OpenAI completion API, you need to post a JSON, to the endpoint, -you will get back a json response. The response can be either the result or a 429 status message telling you our backend is scaling -GPU-s to fulfill your request. You should try again when you are getting scaling response, with exponential backoff -strategy. If the cluster needs to provision new GPU-s the startup time varies between 2-20 minutes. - -Two open source model is currently available in using this API (we will expand this to more models): - * Mistral 7B: the id you need to use in the request **mistral-v0-7b-instruct** - * LLama2 70B chat: the id you need to use in the request **llama2-v0-70b-chat-gptq** - -The **header** field in the request can be anything, usually general instruction for the LLM how to behave. For example: - -You are a helpful, respectful and honest assistant. Always answer as helpfully as possible, while being safe. Your answers should not include any harmful, unethical, racist, sexist, toxic, dangerous, or illegal content. Please ensure that your responses are socially unbiased and positive in nature. If a question does not make any sense, or is not factually coherent, explain why instead of answering something not correct. If you don't know the answer to a question, please don't share false information. -### LLM Completion - - \ No newline at end of file diff --git a/pages/apis/ai-engine/services.mdx b/pages/apis/ai-engine/services.mdx deleted file mode 100644 index 630cfee76..000000000 --- a/pages/apis/ai-engine/services.mdx +++ /dev/null @@ -1,409 +0,0 @@ -import { Row, Col } from "../../../components/mdx"; -import { - ApiEndpointRequestResponse, -} from "../../../components/api-endpoint"; - -# DeltaV Services API - -
- Most of the endpoints depends on various instances and are considered parameters for the actual endpoint, but these are not meant to be passed directly by the user. - -Instead, these instance-dependent elements are integrated and managed directly by the backend system. We refer to them as `*name_parameter`, where the asterisk (\*) is used to denote a specific instance-dependent parameter that the route relies on. - -Mind that: to access these APIs, user must be **authenticated** and have the **correct permissions**. - -
- -## Overview - - - - The DeltaV Services API allows you to interact with the DeltaV backend, allowing you to interact with your agents and more. - - - ```bash filename="Endpoints" - POST /v1beta1/services - - GET /v1beta1/services - - GET /v1beta1/services/:service_id - - PUT /v1beta1/services - - DELETE /v1beta1/services/:service_id - - POST /v1beta1/services/service-sg/ - - DELETE /v1beta1/services/service-sg/:service_id/:service_group_id - ``` - - - - -## Create a service - - - -## Get all services of a user - - - -## Fetch a service - - - -## Update a service - - - -## Delete a service - - - -## Create a service-service group connection - - - -## Delete a service-service group connection - - diff --git a/pages/auth.tsx b/pages/auth.tsx deleted file mode 100644 index 8351c629c..000000000 --- a/pages/auth.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import React from "react"; -import { withIronSessionSsr } from "iron-session/next"; -import { parseJwt } from "src/core/jwt"; -import { sessionOptions } from "src/core/session"; -import { getTokenFromAuthCode } from "src/core/fauna"; -import { setCookie } from "cookies-next"; - -export function flatten(normalized = ""): string { - if (Array.isArray(normalized)) { - return normalized.join(" "); - } - return normalized; -} - -const Page: React.FC = () => { - return <>This is the auth page; -}; - -export const getServerSideProps = withIronSessionSsr(async function ({ - req, - res, - query, -}) { - const authFailure = async () => { - req.session.user; - req.session.credentials; - await req.session.save(); - }; - - const authCode = flatten(query.code as string); - if (authCode === "") { - await authFailure(); - return { - redirect: { - destination: "/", - permanent: false, - }, - }; - } - - const token = await getTokenFromAuthCode(authCode); - setCookie("fauna", token.access_token, { req, res }); - setCookie("refresh_token", token.refresh_token, { req, res }); - - const r = await fetch(`https://accounts.fetch.ai/v1/profile`, { - method: "GET", - headers: { - Authorization: `bearer ${token.access_token}`, - }, - }); - if (!r.ok) { - await authFailure(); - return { - redirect: { - destination: "/", - permanent: false, - }, - }; - } - - const profile = await r.json(); - const email: string | undefined = profile.email; - const walletAddress: string | undefined = profile.wallet_address; - const givenName: string | undefined = profile.given_name; - const familyName: string | undefined = profile.family_name; - const avatarHref: string | undefined = profile.image_url; - const id: string | undefined = profile.client_id; - - const isEmailUser = email !== undefined; - const isWalletUser = walletAddress !== undefined; - const isValidUser = isEmailUser || isWalletUser; - - if (!isValidUser) { - await authFailure(); - return { - redirect: { - destination: "/", - permanent: false, - }, - }; - } - - req.session.user = { - email: email ?? "", - walletAddress: walletAddress ?? "", - avatarHref, - familyName, - givenName, - id, - }; - const metadata = parseJwt(token.access_token); - - req.session.credentials = { - apiKey: token.access_token, - expiresAt: metadata.expiry, - group: metadata.group, - sub: metadata.sub, - }; - - await req.session.save(); - - return { - redirect: { - destination: "/", - permanent: false, - }, - }; -}, sessionOptions); - -export default Page; diff --git a/src/core/fauna.tsx b/src/core/fauna.tsx deleted file mode 100644 index deea88ec2..000000000 --- a/src/core/fauna.tsx +++ /dev/null @@ -1,60 +0,0 @@ -export async function getTokenFromAuthCode(authCode: string): Promise<{ - access_token: string; - refresh_token: string; -}> { - const r = await fetch(`https://accounts.fetch.ai/v1/tokens`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - grant_type: "authorization_code", - code: authCode, - client_id: "docs", - }), - }); - - if (!r.ok) { - throw new Error("Failed to get token"); - } - - const { access_token, refresh_token } = await r.json(); - return { - access_token: access_token, - refresh_token: refresh_token, - }; -} - -export async function getNewAccessToken(currentToken: string) { - if (!currentToken) { - return; - } - const r = await fetch(`https://accounts.fetch.ai/v1/tokens`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - grant_type: "refresh_token", - refresh_token: currentToken, - }), - }); - - if (!r.ok) { - console.error("Could not request new token."); - return; - } - - const refresh_token = await r.json(); - - if (!refresh_token) { - return; - } - - return { - accessToken: refresh_token.access_token, - expiresIn: (refresh_token.expires_in as number) * 1000, - group: refresh_token.grp, - id: "", - }; -} diff --git a/src/core/jwt.tsx b/src/core/jwt.tsx deleted file mode 100644 index 38ca992a6..000000000 --- a/src/core/jwt.tsx +++ /dev/null @@ -1,15 +0,0 @@ -interface TokenInformation { - expiry: number; - group?: "internal"; - sub: string; -} - -export function parseJwt(token: string): TokenInformation { - const payload = JSON.parse( - Buffer.from(token.split(".")[1], "base64").toString(), - ); - - const expiry = (payload.exp as number) * 1000; - - return { expiry: expiry, group: payload.grp, sub: payload.sub }; -} diff --git a/src/core/session.tsx b/src/core/session.tsx deleted file mode 100644 index 5286022df..000000000 --- a/src/core/session.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import type { IronSessionOptions } from "iron-session"; -import { - Credentials, - User, -} from "theme/fetch-ai-docs/contexts/context-provider"; - -export const sessionOptions: IronSessionOptions = { - password: "temporary_wisidjsjddjdidkjdnd09393ndnmmddkmmdd", - cookieName: "docs", - cookieOptions: { - secure: process.env.NODE_ENV === "production", - }, -}; - -declare module "iron-session" { - interface IronSessionData { - user: User | null; - credentials: Credentials | null; - } -} diff --git a/theme/fetch-ai-docs/components/bookmark.tsx b/theme/fetch-ai-docs/components/bookmark.tsx deleted file mode 100644 index 0d058d9f9..000000000 --- a/theme/fetch-ai-docs/components/bookmark.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { GoBookmark } from "react-icons/go"; -import { BsBookmarkCheckFill } from "react-icons/bs"; -import { useUserContext } from "../contexts/context-provider"; -import { handleSignin } from "../helpers"; - -const Bookmark = ({ - onClickBookMark, - bookMark, - classes, -}: { - onClickBookMark: (isVisible: boolean) => void; - bookMark: boolean; - classes?: string; -}) => { - const [isVisible, setIsVisible] = useState(bookMark); - const context = useUserContext(); - - const pathname = typeof window !== "undefined" && window.location?.pathname; - - useEffect(() => { - setIsVisible(bookMark); - }, [bookMark, pathname]); - - const handleToggleBookmark = async () => { - const newVisibilityState = !isVisible; - onClickBookMark(newVisibilityState); - setIsVisible(newVisibilityState); - }; - - const handleClick = context.isLoggedIn ? handleToggleBookmark : handleSignin; - - const bookmarkIcon = isVisible ? ( - - ) : ( - - ); - - return ( -
- {bookmarkIcon} - Bookmark -
- ); -}; - -export default Bookmark; diff --git a/theme/fetch-ai-docs/components/instant-algolia-search.tsx b/theme/fetch-ai-docs/components/instant-algolia-search.tsx index 911995e79..9dac1d409 100644 --- a/theme/fetch-ai-docs/components/instant-algolia-search.tsx +++ b/theme/fetch-ai-docs/components/instant-algolia-search.tsx @@ -22,10 +22,10 @@ type MyItem = NormalItem & { }; const searchClient = algoliasearch( - "J27DIPDG4S", - "601cad4cf7041d99c1bdf42f4d4843d6", + `${process.env.NEXT_PUBLIC_ALGOLIA_APP_ID}`, + `${process.env.NEXT_PUBLIC_ALGOLIA_API_KEY}`, ); -const indexName = "12-6-24-index"; +const indexName = `${process.env.NEXT_PUBLIC_ALGOLIA_INDEX}`; const markdownToHTML = (markdownString) => { return remark().use(remarkHTML).processSync(markdownString).toString(); diff --git a/theme/fetch-ai-docs/components/nav-links.tsx b/theme/fetch-ai-docs/components/nav-links.tsx index ec5fbc488..7056c6bbd 100644 --- a/theme/fetch-ai-docs/components/nav-links.tsx +++ b/theme/fetch-ai-docs/components/nav-links.tsx @@ -6,13 +6,10 @@ import type { ReactElement } from "react"; import { useConfig } from "../contexts"; import type { DocsThemeConfig } from "../index"; import { Anchor } from "./anchor"; -import { isLinkInResponse } from "../helpers"; interface NavLinkProps { currentIndex: number; flatDirectories: Item[]; - onClickSetContentVisited: (contentPath: string) => void; - fetchedContentVisited: string[]; } const classes = { @@ -25,8 +22,6 @@ const classes = { export const NavLinks = ({ flatDirectories, currentIndex, - onClickSetContentVisited, - fetchedContentVisited, }: NavLinkProps): ReactElement | null => { const config = useConfig(); const nav = config.navigation; @@ -38,11 +33,6 @@ export const NavLinks = ({ // eslint-disable-next-line @typescript-eslint/no-explicit-any let next: any = navigation.next && flatDirectories[currentIndex + 1]; - const handleOnNavLinkClick = async () => { - const visitedContent = isLinkInResponse(fetchedContentVisited); - if (!visitedContent) onClickSetContentVisited(next.title); - }; - if (prev && !prev.isUnderCurrentDocsTree) prev = false; if (next && !next.isUnderCurrentDocsTree) next = false; @@ -74,7 +64,6 @@ export const NavLinks = ({ classes.link, "ltr:nx-ml-auto ltr:nx-pl-4 ltr:nx-text-right rtl:nx-mr-auto rtl:nx-pr-4 rtl:nx-text-left", )} - onClick={handleOnNavLinkClick} > {next.title} diff --git a/theme/fetch-ai-docs/components/navbar.tsx b/theme/fetch-ai-docs/components/navbar.tsx index 1562ff6dd..b883c5caa 100644 --- a/theme/fetch-ai-docs/components/navbar.tsx +++ b/theme/fetch-ai-docs/components/navbar.tsx @@ -1,6 +1,5 @@ import { Menu, Transition } from "@headlessui/react"; import cn from "clsx"; -import React, { useEffect, useState } from "react"; import { useFSRoute } from "nextra/hooks"; import { ArrowRightIcon, MenuIcon } from "nextra/icons"; import type { Item, MenuItem, PageItem } from "nextra/normalize-pages"; @@ -8,16 +7,12 @@ import type { ReactElement, ReactNode } from "react"; import { useConfig, useMenu } from "../contexts"; import { renderComponent } from "../utils"; import { Anchor } from "./anchor"; -import { useUserContext } from "../contexts/context-provider"; -import AccountMenu from "components/account-menu"; -import { useRouter } from "next/router"; -import { handleSignin } from "../helpers"; +import { useState } from "react"; +import React from "react"; export type NavBarProps = { flatDirectories: Item[]; items: (PageItem | MenuItem)[]; - bookMark: boolean; - fetchBookMarks: (context: unknown, isBookMark: unknown) => Promise<[string]>; }; const classes = { @@ -83,34 +78,11 @@ function NavbarMenu({ ); } -export function Navbar({ - flatDirectories, - items, - bookMark, - fetchBookMarks, -}: NavBarProps): ReactElement { +export function Navbar({ flatDirectories, items }: NavBarProps): ReactElement { const config = useConfig(); const activeRoute = useFSRoute(); - const { menu, setMenu } = useMenu(); - const context = useUserContext(); - const router = useRouter(); const [hoveredLink, setHoveredLink] = useState(null); - - const handleSignOut = () => { - context.signOut(); - router.push("/"); - }; - - const fetchBookMarksData = async (contextvalues) => { - await fetchBookMarks(contextvalues, true); - }; - - useEffect(() => { - if (context?.user?.email) { - fetchBookMarksData(context?.user?.email); - } - }, [bookMark, context?.user?.email]); - + const { menu, setMenu } = useMenu(); return (
) : null} - {context.isLoggedIn ? ( - - ) : ( - - )} {renderComponent(config.navbar.extraContent)}
-
{renderComponent(config.search.component, { directories: flatDirectories, diff --git a/theme/fetch-ai-docs/components/sidebar.tsx b/theme/fetch-ai-docs/components/sidebar.tsx index d701548bb..318443466 100644 --- a/theme/fetch-ai-docs/components/sidebar.tsx +++ b/theme/fetch-ai-docs/components/sidebar.tsx @@ -21,7 +21,6 @@ import { useActiveAnchor, useConfig, useMenu } from "../contexts"; import { renderComponent } from "../utils"; import { Anchor } from "./anchor"; import { Collapse } from "./collapse"; -import { useUserContext } from "../contexts/context-provider"; const TreeState: Record = Object.create(null); @@ -318,18 +317,6 @@ interface MenuProps { onlyCurrentDocs?: boolean; } -const checkPermission = (item, context) => { - if (item?.children) { - // If item.children exists, check if any child satisfies the condition - return item.children.some((child) => checkPermission(child, context)); - } else { - // If item.children is not present, perform the condition on item - return item?.permission?.length - ? item.permission.includes("fetch.ai") && context.isFetchAccount - : true; - } -}; - function Menu({ directories, anchors, @@ -337,20 +324,16 @@ function Menu({ onlyCurrentDocs, filesVisited, }: MenuProps): ReactElement { - const context = useUserContext(); return (
    {directories.map((item) => { - const permissionCheck = checkPermission(item, context); return !onlyCurrentDocs || !item.theme || (item.theme && item.theme.isUnderCurrentDocsTree) ? item.type === "menu" || (item.children && (item.children.length > 0 || !item.withIndexPage)) - ? permissionCheck && ( - - ) - : permissionCheck && + ? true && + : true && !item?.name?.includes("integrations") && ( Promise<[string]>; } export function Sidebar({ @@ -381,7 +362,6 @@ export function Sidebar({ asPopover = false, headings, includePlaceholder, - contentVisited, }: SideBarProps): ReactElement { const config = useConfig(); const { menu, setMenu } = useMenu(); @@ -476,7 +456,6 @@ export function Sidebar({ directories={docsDirectories} // When the viewport size is larger than `md`, hide the anchors in // the sidebar when `floatTOC` is enabled. - filesVisited={contentVisited} anchors={config.toc.float ? [] : anchors} onlyCurrentDocs /> @@ -487,7 +466,6 @@ export function Sidebar({ // The mobile dropdown menu, shows all the directories. directories={docsDirectories} // Always show the anchor links on mobile (`md`). - filesVisited={contentVisited} anchors={anchors} />
diff --git a/theme/fetch-ai-docs/contexts/context-provider.tsx b/theme/fetch-ai-docs/contexts/context-provider.tsx deleted file mode 100644 index d638a86e8..000000000 --- a/theme/fetch-ai-docs/contexts/context-provider.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import React, { useContext, useEffect, useState } from "react"; -import { useRouter } from "next/navigation"; -import fetchJson from "src/lib/fetch-json"; -import useSWR, { mutate } from "swr"; -import { deleteCookie } from "cookies-next"; -export interface User { - email: string; - id?: string; - walletAddress?: string; - givenName?: string; - familyName?: string; - avatarHref?: string; -} - -export interface Credentials { - apiKey: string; - expiresAt: number; - group?: "internal"; - sub?: string; -} - -interface UserContextData { - user: User; - credentials: Credentials; -} - -export interface UserContextProperties { - session?: UserContextData; -} - -export interface UserInformation { - user: User; - credentials: Credentials; - signOut(): void; - isLoading: boolean; - isLoggedIn: boolean; - isFetchAccount: boolean; -} - -const DEFAULT_USER: User = { - email: "", - walletAddress: "", -}; - -const DEFAULT_CREDENTIALS: Credentials = { - apiKey: "", - expiresAt: 0, - group: undefined, - sub: undefined, -}; - -export const UserContext = React.createContext({ - user: DEFAULT_USER, - credentials: DEFAULT_CREDENTIALS, - // eslint-disable-next-line unicorn/empty-brace-spaces - signOut: () => {}, - isLoading: false, - isLoggedIn: false, - isFetchAccount: false, -}); - -export function useUserContext() { - return useContext(UserContext); -} - -export const UserInfoProvider: React.FC<{ - children?: React.ReactNode | undefined; -}> = ({ children }) => { - const { data, isLoading } = useSWR("/docs/api/profile", fetchJson); - const context = data as UserInformation; - - const [user, setUser] = useState(context?.user ?? DEFAULT_USER); - const [isFetchAccount, setIsFetchAccount] = useState(false); - const [credentials, setCredentials] = useState( - context?.credentials ?? DEFAULT_CREDENTIALS, - ); - const [isLoggedIn, setIsLoggedIn] = useState(context?.isLoggedIn); - const router = useRouter(); - - const signOut = async () => { - deleteCookie("fauna"); - deleteCookie("refresh_token"); - setUser(DEFAULT_USER); - setCredentials(DEFAULT_CREDENTIALS); - mutate(await fetchJson("/docs/api/signout", { method: "POST" }), { - revalidate: true, - }); - setIsLoggedIn(false); - }; - - const resetUserName = () => { - setUser(DEFAULT_USER); - setCredentials(DEFAULT_CREDENTIALS); - }; - - const userEmail = context?.user?.email; - useEffect(() => { - if ( - context?.user != undefined && - context?.credentials != undefined && - context?.isLoggedIn !== undefined && - context?.credentials?.expiresAt > credentials?.expiresAt && - context?.credentials.expiresAt > Date.now() - ) { - setUser(context?.user); - setCredentials(context?.credentials); - setIsLoggedIn(context?.isLoggedIn); - } else if ( - !context?.credentials || - (context?.credentials?.expiresAt > 0 && - context?.credentials?.expiresAt <= Date.now()) - ) { - resetUserName(); - } - if (userEmail && userEmail.includes("fetch.ai")) { - setIsFetchAccount(true); - } else { - setIsFetchAccount(false); - } - }, [context, router]); - - useEffect(() => { - setUser({ - ...user, - email: context?.user?.email, - walletAddress: context?.user?.walletAddress, - avatarHref: context?.user?.avatarHref, - }); - setCredentials({ - ...credentials, - apiKey: context?.credentials?.apiKey, - expiresAt: context?.credentials?.expiresAt, - sub: context?.credentials?.sub, - }); - setIsLoggedIn(context?.isLoggedIn); - }, [ - context?.credentials?.apiKey, - context?.user?.email, - context?.user?.walletAddress, - context?.isLoggedIn, - ]); - - return ( - - {children} - - ); -}; diff --git a/theme/fetch-ai-docs/contexts/refresh-token.tsx b/theme/fetch-ai-docs/contexts/refresh-token.tsx deleted file mode 100644 index 8fb3a7499..000000000 --- a/theme/fetch-ai-docs/contexts/refresh-token.tsx +++ /dev/null @@ -1,53 +0,0 @@ -const minTokenExpiration = 15; - -export async function getNewAccessToken(currentToken: string) { - if (!currentToken) { - return; - } - const r = await fetch(`https://accounts.fetch.ai/v1/tokens`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - grant_type: "refresh_token", - refresh_token: currentToken, - }), - }); - - if (!r.ok) { - console.error("Could not request new token."); - return; - } - - const refresh_token = await r.json(); - - if (!refresh_token) { - return; - } - - return { - accessToken: refresh_token.access_token, - expiresIn: (refresh_token.expires_in as number) * 1000, - group: refresh_token.grp, - id: "", - }; -} - -export const refreshAccessToken = async ( - credentials?: { - apiKey: string; - expiresAt: number; - group?: "internal"; - } | null, -) => { - if (credentials == undefined) { - return; - } - const diff = credentials.expiresAt - Date.now(); - const diffInMinutes = diff / (1000 * 60); - - if (diffInMinutes < minTokenExpiration) { - return await getNewAccessToken(credentials.apiKey); - } -}; diff --git a/theme/fetch-ai-docs/helpers.ts b/theme/fetch-ai-docs/helpers.ts index ab45ec2d4..bfb48080c 100644 --- a/theme/fetch-ai-docs/helpers.ts +++ b/theme/fetch-ai-docs/helpers.ts @@ -1,19 +1,3 @@ -import router from "next/router"; - -export const handleSignin = () => { - const currentProtocol = window.location.protocol; - const currentHostname = window.location.hostname; - const currentPort = window.location.port; - const redirectUri = `${currentProtocol}//${currentHostname}:${currentPort}/docs/auth`; - const loginUrl = - `https://accounts.fetch.ai/login/` + - `?redirect_uri=${encodeURIComponent(redirectUri)}` + - `&client_id=docs` + - `&response_type=code` + - `&sso=`; - router.push(loginUrl); -}; - export const isLinkInResponse = (response) => { const flattenedArray = response?.flat(); const isPresent = flattenedArray?.includes( @@ -22,12 +6,6 @@ export const isLinkInResponse = (response) => { return isPresent; }; -export const capitalizeWords = (str: string) => { - return str.replaceAll(/(?:^|-)([a-z])/g, function (char) { - return char.toUpperCase().replace("-", " "); - }); -}; - export const addUnderscoreInText = (text) => { const lowercasedText = text.toLowerCase(); const snakecasedText = lowercasedText.replaceAll(/\s+/g, "_"); diff --git a/theme/fetch-ai-docs/index.tsx b/theme/fetch-ai-docs/index.tsx index 29ff5c8a8..d2ced8369 100644 --- a/theme/fetch-ai-docs/index.tsx +++ b/theme/fetch-ai-docs/index.tsx @@ -10,8 +10,6 @@ import "./polyfill"; import type { PageTheme } from "nextra/normalize-pages"; import { normalizePages } from "nextra/normalize-pages"; import { ErrorBoundary } from "react-error-boundary"; -import { motion } from "framer-motion"; -import { useActiveAnchor } from "./contexts"; import { Banner, Breadcrumb, @@ -30,11 +28,8 @@ import React from "react"; import FeedbackComponent from "components/feedback"; import type { Item } from "nextra/normalize-pages"; import { setCookie } from "cookies-next"; -import { UserInfoProvider, useUserContext } from "./contexts/context-provider"; -import useBookMark from "theme/use-book-mark"; -import { isLinkInResponse } from "./helpers"; -import useContentVisited from "theme/use-content-visited"; import Error404 from "components/error-404"; +import { useActiveAnchor } from "./contexts"; type MyItem = Item & { // Add or modify properties as needed @@ -49,8 +44,6 @@ interface BodyProps { navigation: ReactNode; tags: string[] | null; children: ReactNode; - onClickBookMark: (val: boolean) => void; - bookMark: boolean; directoriesWithTags: { route: string; tags: string[]; @@ -71,8 +64,6 @@ const Body = ({ navigation, tags, children, - // bookMark, - // onClickBookMark, directoriesWithTags, }: BodyProps): ReactElement => { const config = useConfig(); @@ -215,19 +206,9 @@ const InnerLayout = ({ timestamp, children, }: PageOpts & { children: ReactNode }): ReactElement => { - const context = useUserContext(); - const { - state: { bookMarks, bookMarkSuccess }, - action: { onClickBookMark, fetchBookMarks }, - } = useBookMark(context); - const { - state: { contentVisited }, - action: { onClickSetContentVisited, fetchContentVisited }, - } = useContentVisited(context); const config = useConfig(); const { locale = DEFAULT_LOCALE, defaultLocale } = useRouter(); const fsPath = useFSRoute(); - const bookMark = isLinkInResponse(bookMarks); useEffect(() => { setLastVisitedTimestamp(); @@ -284,11 +265,6 @@ const InnerLayout = ({ ? localeConfig.direction === "rtl" : config.direction === "rtl"; const direction = isRTL ? "rtl" : "ltr"; - - const check = activePath.at(-1)?.permission?.length - ? activePath.at(-1)?.permission.includes("fetch.ai") && - context.isFetchAccount - : true; return ( // This makes sure that selectors like `[dir=ltr] .nextra-container` work // before hydration as Tailwind expects the `dir` attribute to exist on the @@ -322,8 +298,6 @@ const InnerLayout = ({ renderComponent(config.navbar.component, { flatDirectories, items: docsDirectories, - bookMark, - fetchBookMarks, })}
@@ -334,45 +308,36 @@ const InnerLayout = ({ headings={headings} asPopover={hideSidebar} includePlaceholder={themeContext.layout === "default"} - contentVisited={contentVisited} - fetchContentVisited={fetchContentVisited} /> - {bookMarkSuccess && Toast(bookMarkSuccess)} - {check && ( - - ) : null - } - timestamp={timestamp} - navigation={ - activeType !== "page" && themeContext.pagination ? ( - - ) : null - } - tags={activePath.at(-1)?.tags ?? undefined} - onClickBookMark={onClickBookMark} - bookMark={bookMark} - directoriesWithTags={directoriesWithTags} + + ) : null + } + timestamp={timestamp} + navigation={ + activeType !== "page" && themeContext.pagination ? ( + + ) : null + } + tags={activePath.at(-1)?.tags ?? undefined} + directoriesWithTags={directoriesWithTags} + > + - - {children} - - - )} + {children} + +
{themeContext.footer && @@ -381,46 +346,15 @@ const InnerLayout = ({ ); }; -const Toast = (bookMarkSuccess: string) => ( - -
- - Check icon -
-
{bookMarkSuccess}
-
-); - export default function Layout({ children, ...context }: NextraThemeLayoutProps): ReactElement { return ( - - - {children} - - + + {children} + ); } @@ -441,7 +375,6 @@ export { Collapse, NotFoundPage, ServerSideErrorPage, - Navbar, SkipNavContent, SkipNavLink, ThemeSwitch, diff --git a/theme/use-book-mark.ts b/theme/use-book-mark.ts deleted file mode 100644 index 49c883418..000000000 --- a/theme/use-book-mark.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { useEffect, useState } from "react"; - -const useBookMark = (context) => { - const [bookMarks, setBookMarks] = useState([]); - const [bookMarkSuccess, setBookMarkSuccess] = useState(""); - const fetchBookMarks = async (email, isBookMark) => { - try { - const response = await fetch( - `/docs/api/get-bookmarks?user_email=${email}&is_visible=${isBookMark}`, - { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }, - ); - - if (response.status === 200) { - const bookmark = await response.json(); - setBookMarks(bookmark); - return bookmark; - } else { - setBookMarks([]); - return []; - } - } catch (error) { - setBookMarks([]); - console.log("oops, something went wrong", error); - return []; - } - }; - - const pathname = typeof window !== "undefined" && window?.location?.pathname; - - useEffect(() => { - if (context?.user?.email) { - fetchBookMarks(context?.user?.email, true); - } - }, [context?.user?.email, pathname]); - - const onClickBookMark = async (newVisibilityState: boolean) => { - try { - const resp = await fetch(`/docs/api/set-bookmarks`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - user_email: context?.user?.email, - saved_path: window.location.pathname, - is_visible: newVisibilityState, - }), - }); - - if (resp.status === 200) { - if (newVisibilityState) { - setBookMarkSuccess("Bookmark updated successfully"); - } else { - setBookMarkSuccess("Bookmark removed successfully"); - } - } - const bookmark = await fetchBookMarks( - context?.user?.email, - newVisibilityState, - ); - setBookMarks(bookmark); - setTimeout(() => { - setBookMarkSuccess(""); - }, 2000); - } catch (error) { - console.log("something went wrong", error); - } - }; - return { - state: { bookMarks, bookMarkSuccess, setBookMarkSuccess }, - action: { onClickBookMark, fetchBookMarks }, - }; -}; - -export default useBookMark; diff --git a/theme/use-content-visited.ts b/theme/use-content-visited.ts deleted file mode 100644 index fe3cc0fe1..000000000 --- a/theme/use-content-visited.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { useEffect, useState } from "react"; - -const useContentVisited = (context) => { - const [contentVisited, setContentVisited] = useState(); - - const fetchContentVisited = async (context) => { - try { - const response = await fetch( - `/docs/api/content-visited/?user_email=${context?.user?.email}`, - { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }, - ); - const apiResponse = await response.json(); - setContentVisited(apiResponse); - return apiResponse; - } catch (error) { - console.log("oops, something went wrong", error); - } - }; - - const pathname = typeof window !== "undefined" && window?.location?.pathname; - - useEffect(() => { - if (context?.user?.email) { - fetchContentVisited(context); - } - }, [context?.user?.email, pathname]); - - const onClickSetContentVisited = async (contentPath: string) => { - try { - await fetch(`/docs/api/set-content-visited`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - user_email: context?.user?.email, - saved_path: contentPath, - is_visible: true, - }), - }); - - const visitedContent = await fetchContentVisited(context); - setContentVisited(visitedContent); - } catch (error) { - console.log("something went wrong", error); - } - }; - return { - state: { contentVisited }, - action: { onClickSetContentVisited, fetchContentVisited }, - }; -}; - -export default useContentVisited;