add import/export (#71)

This commit is contained in:
Mckay Wrigley
2023-03-22 08:10:00 -06:00
committed by GitHub
parent 972a5aff23
commit f0c575b40d
6 changed files with 91 additions and 5 deletions
+34
View File
@@ -0,0 +1,34 @@
import { Conversation } from "@/types";
import { IconFileImport } from "@tabler/icons-react";
import { FC } from "react";
interface Props {
onImport: (conversations: Conversation[]) => void;
}
export const Import: FC<Props> = ({ onImport }) => {
return (
<div className="flex py-3 px-3 gap-3 rounded-md hover:bg-gray-500/10 transition-colors duration-200 text-white cursor-pointer w-full items-center">
<input
className="opacity-0 absolute w-[200px] cursor-pointer"
type="file"
accept=".json"
onChange={(e) => {
if (!e.target.files?.length) return;
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = (e) => {
const conversations: Conversation[] = JSON.parse(e.target?.result as string);
onImport(conversations);
};
reader.readAsText(file);
}}
/>
<div className="flex items-center gap-3 text-left">
<IconFileImport size={16} />
<div>Import conversations</div>
</div>
</div>
);
};
+6 -2
View File
@@ -19,9 +19,11 @@ interface Props {
onUpdateConversation: (conversation: Conversation, data: KeyValuePair) => void;
onApiKeyChange: (apiKey: string) => void;
onClearConversations: () => void;
onExportConversations: () => void;
onImportConversations: (conversations: Conversation[]) => void;
}
export const Sidebar: FC<Props> = ({ loading, conversations, lightMode, selectedConversation, apiKey, onNewConversation, onToggleLightMode, onSelectConversation, onDeleteConversation, onToggleSidebar, onUpdateConversation, onApiKeyChange, onClearConversations }) => {
export const Sidebar: FC<Props> = ({ loading, conversations, lightMode, selectedConversation, apiKey, onNewConversation, onToggleLightMode, onSelectConversation, onDeleteConversation, onToggleSidebar, onUpdateConversation, onApiKeyChange, onClearConversations, onExportConversations, onImportConversations }) => {
const [searchTerm, setSearchTerm] = useState<string>("");
const [filteredConversations, setFilteredConversations] = useState<Conversation[]>(conversations);
@@ -34,7 +36,7 @@ export const Sidebar: FC<Props> = ({ loading, conversations, lightMode, selected
}, [searchTerm, conversations]);
return (
<div className={`h-full flex flex-col flex-none space-y-2 p-2 flex-col bg-[#202123] w-[260px] z-10 sm:relative sm:top-0 absolute top-12 bottom-0`}>
<div className={`h-full flex flex-none space-y-2 p-2 flex-col bg-[#202123] w-[260px] z-10 sm:relative sm:top-0 absolute top-12 bottom-0`}>
<div className="flex items-center">
<button
className="flex gap-3 p-3 items-center w-full sm:w-[200px] rounded-md hover:bg-gray-500/10 transition-colors duration-200 text-white cursor-pointer text-sm flex-shrink-0 border border-white/20"
@@ -87,6 +89,8 @@ export const Sidebar: FC<Props> = ({ loading, conversations, lightMode, selected
onToggleLightMode={onToggleLightMode}
onApiKeyChange={onApiKeyChange}
onClearConversations={onClearConversations}
onExportConversations={onExportConversations}
onImportConversations={onImportConversations}
/>
</div>
);
+1 -1
View File
@@ -12,7 +12,7 @@ export const SidebarButton: FC<Props> = ({ text, icon, onClick }) => {
className="flex py-3 px-3 gap-3 rounded-md hover:bg-gray-500/10 transition-colors duration-200 text-white cursor-pointer w-full items-center"
onClick={onClick}
>
<div className="">{icon}</div>
<div>{icon}</div>
<div>{text}</div>
</div>
);
+15 -2
View File
@@ -1,6 +1,8 @@
import { IconMoon, IconSun } from "@tabler/icons-react";
import { Conversation } from "@/types";
import { IconFileExport, IconMoon, IconSun } from "@tabler/icons-react";
import { FC } from "react";
import { ClearConversations } from "./ClearConversations";
import { Import } from "./Import";
import { Key } from "./Key";
import { SidebarButton } from "./SidebarButton";
@@ -10,18 +12,29 @@ interface Props {
onToggleLightMode: (mode: "light" | "dark") => void;
onApiKeyChange: (apiKey: string) => void;
onClearConversations: () => void;
onExportConversations: () => void;
onImportConversations: (conversations: Conversation[]) => void;
}
export const SidebarSettings: FC<Props> = ({ lightMode, apiKey, onToggleLightMode, onApiKeyChange, onClearConversations }) => {
export const SidebarSettings: FC<Props> = ({ lightMode, apiKey, onToggleLightMode, onApiKeyChange, onClearConversations, onExportConversations, onImportConversations }) => {
return (
<div className="flex flex-col pt-1 items-center border-t border-white/20 text-sm space-y-1">
<ClearConversations onClearConversations={onClearConversations} />
<Import onImport={onImportConversations} />
<SidebarButton
text="Export conversations"
icon={<IconFileExport size={16} />}
onClick={() => onExportConversations()}
/>
<SidebarButton
text={lightMode === "light" ? "Dark mode" : "Light mode"}
icon={lightMode === "light" ? <IconMoon size={16} /> : <IconSun size={16} />}
onClick={() => onToggleLightMode(lightMode === "light" ? "dark" : "light")}
/>
<Key
apiKey={apiKey}
onApiKeyChange={onApiKeyChange}