1
1
import * as Dialog from '@radix-ui/react-dialog'
2
2
import { useCallback , useEffect , useMemo , useRef , useState } from 'preact/hooks'
3
3
import { useTranslation } from 'react-i18next'
4
- import { archiveConversation , deleteConversation , fetchAllConversations , fetchConversation } from '../api'
4
+ import { archiveConversation , deleteConversation , fetchAllConversations , fetchConversation , fetchProjects } from '../api'
5
5
import { exportAllToHtml } from '../exporter/html'
6
6
import { exportAllToJson , exportAllToOfficialJson } from '../exporter/json'
7
7
import { exportAllToMarkdown } from '../exporter/markdown'
8
8
import { RequestQueue } from '../utils/queue'
9
9
import { CheckBox } from './CheckBox'
10
10
import { IconCross , IconUpload } from './Icons'
11
11
import { useSettingContext } from './SettingContext'
12
- import type { ApiConversationItem , ApiConversationWithId } from '../api'
12
+ import type { ApiConversationItem , ApiConversationWithId , ApiProjectInfo } from '../api'
13
13
import type { FC } from '../type'
14
14
import type { ChangeEvent } from 'preact/compat'
15
15
16
+ interface ProjectSelectProps {
17
+ projects : ApiProjectInfo [ ]
18
+ selected : ApiProjectInfo | null
19
+ setSelected : ( selected : ApiProjectInfo | null ) => void
20
+ disabled : boolean
21
+ }
22
+
23
+ const ProjectSelect : FC < ProjectSelectProps > = ( { projects, selected, setSelected, disabled } ) => {
24
+ const { t } = useTranslation ( )
25
+
26
+ return (
27
+ < div className = "flex items-center text-gray-600 dark:text-gray-300 flex justify-between mb-3" >
28
+ { t ( 'Select Project' ) }
29
+ < select
30
+ disabled = { disabled }
31
+ className = "Select"
32
+ value = { selected ?. id || '' }
33
+ onChange = { ( e ) => {
34
+ const projectId = e . currentTarget . value
35
+ const project = projects . find ( p => p . id === projectId )
36
+ setSelected ( project || null )
37
+ } }
38
+ >
39
+ < option value = "" > { t ( '(no project)' ) } </ option >
40
+ { projects . map ( project => (
41
+ < option key = { project . id } value = { project . id } > { project . display . name } </ option >
42
+ ) ) }
43
+ </ select >
44
+ </ div >
45
+ )
46
+ }
47
+
16
48
interface ConversationSelectProps {
17
49
conversations : ApiConversationItem [ ]
18
50
selected : ApiConversationItem [ ]
@@ -47,7 +79,8 @@ const ConversationSelect: FC<ConversationSelectProps> = ({
47
79
< ul className = "SelectList" >
48
80
{ loading && < li className = "SelectItem" > { t ( 'Loading' ) } ...</ li > }
49
81
{ error && < li className = "SelectItem" > { t ( 'Error' ) } : { error } </ li > }
50
- { conversations . map ( c => (
82
+ { ! loading && ! error
83
+ && conversations . map ( c => (
51
84
< li className = "SelectItem" key = { c . id } >
52
85
< CheckBox
53
86
label = { c . title }
@@ -90,9 +123,11 @@ const DialogContent: FC<DialogContentProps> = ({ format }) => {
90
123
const [ apiConversations , setApiConversations ] = useState < ApiConversationItem [ ] > ( [ ] )
91
124
const [ localConversations , setLocalConversations ] = useState < ApiConversationWithId [ ] > ( [ ] )
92
125
const conversations = exportSource === 'API' ? apiConversations : localConversations
126
+ const [ projects , setProjects ] = useState < ApiProjectInfo [ ] > ( [ ] )
93
127
const [ loading , setLoading ] = useState ( false )
94
128
const [ error , setError ] = useState ( '' )
95
129
const [ processing , setProcessing ] = useState ( false )
130
+ const [ selectedProject , setSelectedProject ] = useState < ApiProjectInfo | null > ( null )
96
131
97
132
const [ selected , setSelected ] = useState < ApiConversationItem [ ] > ( [ ] )
98
133
const [ exportType , setExportType ] = useState ( exportAllOptions [ 0 ] . label )
@@ -245,13 +280,19 @@ const DialogContent: FC<DialogContentProps> = ({ format }) => {
245
280
archiveQueue . start ( )
246
281
} , [ disabled , selected , archiveQueue , t ] )
247
282
283
+ useEffect ( ( ) => {
284
+ fetchProjects ( )
285
+ . then ( setProjects )
286
+ . catch ( err => setError ( err . toString ( ) ) )
287
+ } , [ ] )
288
+
248
289
useEffect ( ( ) => {
249
290
setLoading ( true )
250
- fetchAllConversations ( )
291
+ fetchAllConversations ( selectedProject ?. id )
251
292
. then ( setApiConversations )
252
- . catch ( setError )
293
+ . catch ( err => setError ( err . toString ( ) ) )
253
294
. finally ( ( ) => setLoading ( false ) )
254
- } , [ ] )
295
+ } , [ selectedProject ] )
255
296
256
297
return (
257
298
< >
@@ -276,6 +317,7 @@ const DialogContent: FC<DialogContentProps> = ({ format }) => {
276
317
{ t ( 'Export from API' ) }
277
318
</ div >
278
319
) }
320
+ < ProjectSelect projects = { projects } selected = { selectedProject } setSelected = { setSelectedProject } disabled = { processing || loading } />
279
321
< ConversationSelect
280
322
conversations = { conversations }
281
323
selected = { selected }
0 commit comments