From 943def6d7c1e2789c0de777388a454be9010010b Mon Sep 17 00:00:00 2001
From: Kamran Ahmed
Date: Mon, 11 Mar 2024 03:30:20 +0000
Subject: [PATCH] Add open ai saving
---
.../GenerateRoadmap/GenerateRoadmap.tsx | 10 ++++--
.../GenerateRoadmap/OpenAISettings.tsx | 14 ++++-----
.../GenerateRoadmap/RoadmapSearch.tsx | 6 ++--
.../GenerateRoadmap/RoadmapTopicDetail.tsx | 31 ++++++++++++++++---
src/lib/jwt.ts | 6 ++--
5 files changed, 46 insertions(+), 21 deletions(-)
diff --git a/src/components/GenerateRoadmap/GenerateRoadmap.tsx b/src/components/GenerateRoadmap/GenerateRoadmap.tsx
index d22c8e2d2..3b68e9467 100644
--- a/src/components/GenerateRoadmap/GenerateRoadmap.tsx
+++ b/src/components/GenerateRoadmap/GenerateRoadmap.tsx
@@ -13,7 +13,7 @@ import { renderFlowJSON } from '../../../editor/renderer/renderer';
import { replaceChildren } from '../../lib/dom';
import { readAIRoadmapStream } from '../../helper/read-stream';
import {
- getOpenAPIKey,
+ getOpenAIKey,
isLoggedIn,
removeAuthToken,
visitAIRoadmap,
@@ -103,7 +103,7 @@ export function GenerateRoadmap() {
const [roadmapTopicLimitUsed, setRoadmapTopicLimitUsed] = useState(0);
const [isConfiguring, setIsConfiguring] = useState(false);
- const openAPIKey = getOpenAPIKey();
+ const openAPIKey = getOpenAIKey();
const renderRoadmap = async (roadmap: string) => {
const { nodes, edges } = generateAIRoadmapFromText(roadmap);
@@ -401,6 +401,10 @@ export function GenerateRoadmap() {
nodeType={selectedNode.nodeType}
nodeTitle={selectedNode.nodeTitle}
parentTitle={selectedNode.parentTitle}
+ onConfigureOpenAI={() => {
+ setSelectedNode(null);
+ setIsConfiguring(true);
+ }}
onClose={() => {
setSelectedNode(null);
loadAIRoadmapLimit().finally(() => {});
@@ -470,7 +474,7 @@ export function GenerateRoadmap() {
className="flex flex-row items-center gap-1 rounded-xl border border-current px-2 py-0.5 text-sm text-blue-500 transition-colors hover:bg-blue-400 hover:text-white"
>
- Configure OpenAI API key
+ Configure OpenAI key
)}
diff --git a/src/components/GenerateRoadmap/OpenAISettings.tsx b/src/components/GenerateRoadmap/OpenAISettings.tsx
index ced58b7cb..2e361111b 100644
--- a/src/components/GenerateRoadmap/OpenAISettings.tsx
+++ b/src/components/GenerateRoadmap/OpenAISettings.tsx
@@ -1,9 +1,9 @@
import { Modal } from '../Modal.tsx';
import { useEffect, useState } from 'react';
import {
- deleteOpenAPIKey,
- getOpenAPIKey,
- saveOpenAPIKey,
+ deleteOpenAIKey,
+ getOpenAIKey,
+ saveOpenAIKey,
} from '../../lib/jwt.ts';
import { cn } from '../../lib/classname.ts';
import { CloseIcon } from '../ReactIcons/CloseIcon.tsx';
@@ -26,7 +26,7 @@ export function OpenAISettings(props: OpenAISettingsProps) {
const toast = useToast();
useEffect(() => {
- const apiKey = getOpenAPIKey();
+ const apiKey = getOpenAIKey();
setOpenaiApiKey(apiKey || '');
setDefaultOpenAIKey(apiKey || '');
}, []);
@@ -59,7 +59,7 @@ export function OpenAISettings(props: OpenAISettingsProps) {
const normalizedKey = openaiApiKey.trim();
if (!normalizedKey) {
- deleteOpenAPIKey();
+ deleteOpenAIKey();
toast.success('OpenAI API key removed');
onClose();
return;
@@ -85,7 +85,7 @@ export function OpenAISettings(props: OpenAISettingsProps) {
}
// Save the API key to cookies
- saveOpenAPIKey(normalizedKey);
+ saveOpenAIKey(normalizedKey);
toast.success('OpenAI API key saved');
onClose();
}}
@@ -151,7 +151,7 @@ export function OpenAISettings(props: OpenAISettingsProps) {
)}
diff --git a/src/components/GenerateRoadmap/RoadmapTopicDetail.tsx b/src/components/GenerateRoadmap/RoadmapTopicDetail.tsx
index 184203e82..f3db8525c 100644
--- a/src/components/GenerateRoadmap/RoadmapTopicDetail.tsx
+++ b/src/components/GenerateRoadmap/RoadmapTopicDetail.tsx
@@ -3,13 +3,14 @@ import { useEffect, useMemo, useRef, useState } from 'react';
import { useKeydown } from '../../hooks/use-keydown';
import { useOutsideClick } from '../../hooks/use-outside-click';
import { markdownToHtml } from '../../lib/markdown';
-import { Ban, FileText, X } from 'lucide-react';
+import { Ban, Cog, FileText, X } from 'lucide-react';
import { Spinner } from '../ReactIcons/Spinner';
import type { RoadmapNodeDetails } from './GenerateRoadmap';
-import { isLoggedIn, removeAuthToken } from '../../lib/jwt';
+import { getOpenAIKey, isLoggedIn, removeAuthToken } from '../../lib/jwt';
import { readAIRoadmapContentStream } from '../../helper/read-stream';
import { cn } from '../../lib/classname';
import { showLoginPopup } from '../../lib/popup';
+import { OpenAISettings } from './OpenAISettings.tsx';
type RoadmapTopicDetailProps = RoadmapNodeDetails & {
onClose?: () => void;
@@ -17,6 +18,7 @@ type RoadmapTopicDetailProps = RoadmapNodeDetails & {
topicLimitUsed: number;
topicLimit: number;
onTopicContentGenerateComplete?: () => void;
+ onConfigureOpenAI?: () => void;
};
export function RoadmapTopicDetail(props: RoadmapTopicDetailProps) {
@@ -28,6 +30,7 @@ export function RoadmapTopicDetail(props: RoadmapTopicDetailProps) {
topicLimit,
topicLimitUsed,
onTopicContentGenerateComplete,
+ onConfigureOpenAI,
} = props;
const [isLoading, setIsLoading] = useState(false);
@@ -121,6 +124,7 @@ export function RoadmapTopicDetail(props: RoadmapTopicDetailProps) {
}, []);
const hasContent = topicHtml?.length > 0;
+ const openAIKey = getOpenAIKey();
return (
@@ -129,7 +133,7 @@ export function RoadmapTopicDetail(props: RoadmapTopicDetailProps) {
tabIndex={0}
className="fixed right-0 top-0 z-40 h-screen w-full overflow-y-auto bg-white p-4 focus:outline-0 sm:max-w-[600px] sm:p-6"
>
-
+
- Generate more by{' '}
- logging in
+ Generate more by logging in
+
+ )}
+ {isLoggedIn() && !openAIKey && (
+
+ )}
+ {isLoggedIn() && openAIKey && (
+
)}
diff --git a/src/lib/jwt.ts b/src/lib/jwt.ts
index 22643b589..d3206b083 100644
--- a/src/lib/jwt.ts
+++ b/src/lib/jwt.ts
@@ -64,14 +64,14 @@ export function visitAIRoadmap(roadmapId: string) {
});
}
-export function deleteOpenAPIKey() {
+export function deleteOpenAIKey() {
Cookies.remove('oak', {
path: '/',
domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',
});
}
-export function saveOpenAPIKey(apiKey: string) {
+export function saveOpenAIKey(apiKey: string) {
Cookies.set('oak', apiKey, {
path: '/',
expires: 365,
@@ -81,6 +81,6 @@ export function saveOpenAPIKey(apiKey: string) {
});
}
-export function getOpenAPIKey() {
+export function getOpenAIKey() {
return Cookies.get('oak');
}