Skip to content

Commit

Permalink
App data should be importable and exportable
Browse files Browse the repository at this point in the history
  • Loading branch information
mrdjohnson committed Mar 2, 2024
1 parent 353c03e commit 149abaf
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 14 deletions.
94 changes: 80 additions & 14 deletions src/containers/SideBar.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { useEffect, useRef } from 'react'
import { ChangeEvent, useEffect, useRef, useState } from 'react'

Check failure on line 1 in src/containers/SideBar.tsx

View workflow job for this annotation

GitHub Actions / deploy

'useState' is declared but its value is never read.
import { observer } from 'mobx-react-lite'
import { applySnapshot, getSnapshot } from 'mobx-state-tree'

import { chatStore } from '../models/ChatStore'
import { IChatModel } from '../models/ChatModel'
import { settingStore } from '../models/SettingStore'
import { personaStore } from '../models/PersonaStore'

import Delete from '../icons/Delete'
import Options from '../icons/Options'
import Edit from '../icons/Edit'
import Check from '../icons/Check'
import DocumentArrowUp from '../icons/DocumentArrowUp'
import DocumentArrowDown from '../icons/DocumentArrowDown'

const ChatItem = observer(({ chat }: { chat: IChatModel }) => {
const inputRef = useRef<HTMLInputElement>(null)
Expand Down Expand Up @@ -70,22 +75,83 @@ const ChatItem = observer(({ chat }: { chat: IChatModel }) => {
})

export const SideBar = observer(() => {
const fileInputRef = useRef<HTMLInputElement>(null)

const chats = chatStore.chats

const exportAll = () => {
const data = JSON.stringify({
chatStore: getSnapshot(chatStore),
personaStore: getSnapshot(personaStore),
settingStore: getSnapshot(settingStore),
})

const link = document.createElement('a')
link.href = URL.createObjectURL(new Blob([data], { type: 'application/json' }))
link.download = 'llm-x-data.json'
link.click()
}

const importAll = async (event: ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0]

if (!file) {
return
}

// reset file input
event.target.value = ''

const data = JSON.parse(await file.text())

applySnapshot(chatStore, data.chatStore)
applySnapshot(personaStore, data.personaStore)
applySnapshot(settingStore, data.settingStore)
}

return (
<div className="flex h-full w-[260px] min-w-[260px] flex-1 flex-col flex-nowrap gap-2 rounded-md bg-base-300 p-2 ">
<button
className="btn btn-neutral mb-2 flex w-full flex-row items-center justify-center gap-2 p-2"
onClick={chatStore.createChat}
disabled={chatStore.hasEmptyChat}
>
New Chat
<Edit className='h-5 w-5' />
</button>

{chats.map(chat => (
<ChatItem chat={chat} key={chat.id} />
))}
<div className="flex h-auto w-[260px] min-w-[260px] flex-1 flex-col flex-nowrap gap-2 rounded-md bg-base-300 p-2 lg:h-full ">
<div className="flex h-full flex-1 flex-col">
<button
className="btn btn-neutral mb-2 flex w-full flex-row items-center justify-center gap-2 p-2"
onClick={chatStore.createChat}
disabled={chatStore.hasEmptyChat}
>
New Chat
<Edit className="h-5 w-5" />
</button>

{chats.map(chat => (
<ChatItem chat={chat} key={chat.id} />
))}
</div>

<div className="flex flex-col justify-center gap-2">
<label className=" text-center">Import / Export</label>

{/* hidden file input */}
<input
style={{ display: 'none' }}
ref={fileInputRef}
type="file"
accept=".json"
onChange={importAll}
/>

<div className="flex flex-row justify-center gap-2">
<button
className="btn btn-ghost btn-active"
title="Import All"
onClick={() => fileInputRef.current?.click()}
>
<DocumentArrowUp />
</button>

<button className="btn btn-ghost btn-active" title="Export All" onClick={exportAll}>
<DocumentArrowDown />
</button>
</div>
</div>
</div>
)
})
18 changes: 18 additions & 0 deletions src/icons/DocumentArrowDown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export default function DocumentArrowDown() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="h-5 w-5"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m.75 12 3 3m0 0 3-3m-3 3v-6m-1.5-9H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"
/>
</svg>
)
}
18 changes: 18 additions & 0 deletions src/icons/DocumentArrowUp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export default function DocumentArrowUp() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="h-5 w-5"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m6.75 12-3-3m0 0-3 3m3-3v6m-1.5-15H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"
/>
</svg>
)
}

0 comments on commit 149abaf

Please sign in to comment.