mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-12 13:13:45 +01:00
168 lines
4.5 KiB
TypeScript
168 lines
4.5 KiB
TypeScript
import { useTranslation } from 'react-i18next'
|
|
import { FormEventHandler, useEffect, useState, useCallback } from 'react'
|
|
import { getJSON } from '@/infrastructure/fetch-json'
|
|
import { useFileTreeActionable } from '@/features/file-tree/contexts/file-tree-actionable'
|
|
import { useFileTreeCreateForm } from '@/features/file-tree/contexts/file-tree-create-form'
|
|
import { useFileTreeMainContext } from '@/features/file-tree/contexts/file-tree-main'
|
|
import FileTreeModalCreateFileMode from '@/features/file-tree/components/file-tree-create/file-tree-modal-create-file-mode'
|
|
import ErrorMessage from '@/features/file-tree/components/file-tree-create/error-message'
|
|
import OLFormGroup from '@/shared/components/ol/ol-form-group'
|
|
import OLFormLabel from '@/shared/components/ol/ol-form-label'
|
|
import OLFormControl from '@/shared/components/ol/ol-form-control'
|
|
import OLFormSelect from '@/shared/components/ol/ol-form-select'
|
|
import OLNotification from '@/shared/components/ol/ol-notification'
|
|
|
|
type ZoteroGroup = {
|
|
id: string
|
|
name: string
|
|
}
|
|
|
|
export function CreateFileMode() {
|
|
const { refProviders } = useFileTreeMainContext()
|
|
const isLinked = (refProviders as Record<string, boolean>)?.zotero
|
|
|
|
if (!isLinked) {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<FileTreeModalCreateFileMode
|
|
mode="zotero"
|
|
icon="library_books"
|
|
label="From Zotero"
|
|
/>
|
|
)
|
|
}
|
|
|
|
export function CreateFilePane() {
|
|
const { newFileCreateMode } = useFileTreeActionable()
|
|
|
|
if (newFileCreateMode !== 'zotero') {
|
|
return null
|
|
}
|
|
|
|
return <ZoteroCreateFilePane />
|
|
}
|
|
|
|
function ZoteroCreateFilePane() {
|
|
const { t } = useTranslation()
|
|
const { setValid } = useFileTreeCreateForm()
|
|
const { finishCreatingLinkedFile, error, inFlight } = useFileTreeActionable()
|
|
|
|
const [groups, setGroups] = useState<ZoteroGroup[]>([])
|
|
const [selectedGroupId, setSelectedGroupId] = useState<string>('')
|
|
const [name, setName] = useState('zotero.bib')
|
|
const [loadingGroups, setLoadingGroups] = useState(true)
|
|
const [groupsError, setGroupsError] = useState('')
|
|
|
|
useEffect(() => {
|
|
setValid(!!name && !loadingGroups)
|
|
}, [setValid, name, loadingGroups])
|
|
|
|
useEffect(() => {
|
|
let cancelled = false
|
|
|
|
setLoadingGroups(true)
|
|
setGroupsError('')
|
|
|
|
getJSON('/zotero/groups')
|
|
.then((data: { groups: ZoteroGroup[] }) => {
|
|
if (cancelled) return
|
|
|
|
setGroups(data.groups || [])
|
|
setLoadingGroups(false)
|
|
})
|
|
.catch(() => {
|
|
if (cancelled) return
|
|
|
|
setGroupsError(t('zotero_groups_loading_error'))
|
|
setLoadingGroups(false)
|
|
})
|
|
|
|
return () => {
|
|
cancelled = true
|
|
}
|
|
}, [t])
|
|
|
|
const handleSubmit: FormEventHandler = useCallback(
|
|
event => {
|
|
event.preventDefault()
|
|
|
|
if (!name || loadingGroups || inFlight) {
|
|
return
|
|
}
|
|
|
|
const data: Record<string, string> = {}
|
|
|
|
if (selectedGroupId) {
|
|
data.zoteroGroupId = selectedGroupId
|
|
}
|
|
|
|
finishCreatingLinkedFile({
|
|
name,
|
|
provider: 'zotero',
|
|
data,
|
|
})
|
|
},
|
|
[
|
|
name,
|
|
loadingGroups,
|
|
inFlight,
|
|
selectedGroupId,
|
|
finishCreatingLinkedFile,
|
|
]
|
|
)
|
|
|
|
return (
|
|
<form
|
|
className="form-controls"
|
|
id="create-file"
|
|
noValidate
|
|
onSubmit={handleSubmit}
|
|
>
|
|
{groupsError && (
|
|
<OLNotification type="error" content={groupsError} className="mb-3" />
|
|
)}
|
|
|
|
<OLFormGroup controlId="zotero-file-name">
|
|
<OLFormLabel>{t('file_name')}</OLFormLabel>
|
|
<OLFormControl
|
|
type="text"
|
|
placeholder="zotero.bib"
|
|
required
|
|
value={name}
|
|
disabled={inFlight}
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setName(e.target.value)
|
|
}
|
|
/>
|
|
</OLFormGroup>
|
|
|
|
<OLFormGroup controlId="zotero-library-select">
|
|
<OLFormLabel>Library</OLFormLabel>
|
|
{loadingGroups ? (
|
|
<p className="text-muted">{t('loading')}...</p>
|
|
) : (
|
|
<OLFormSelect
|
|
id="zotero-library-select"
|
|
value={selectedGroupId}
|
|
disabled={inFlight}
|
|
onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>
|
|
setSelectedGroupId(e.target.value)
|
|
}
|
|
>
|
|
<option value="">My Library</option>
|
|
{groups.map(g => (
|
|
<option key={g.id} value={g.id}>
|
|
{g.name}
|
|
</option>
|
|
))}
|
|
</OLFormSelect>
|
|
)}
|
|
</OLFormGroup>
|
|
|
|
{error && <ErrorMessage error={error} />}
|
|
</form>
|
|
)
|
|
}
|