generated from kevisual/vite-react-template
- Implement CreateRepoDialog for creating new repositories with form validation. - Implement EditRepoDialog for editing existing repository details. - Implement SyncRepoDialog for syncing repositories with Gitea, including repository creation if necessary. - Implement WorkspaceDetailDialog for managing workspace links and actions. - Enhance the repo store with new state management for repository actions, including creating, editing, and syncing repositories. - Add build configuration utilities for repository synchronization. - Create a new page for repository management, integrating all dialogs and functionalities. - Add login route for authentication.
141 lines
3.8 KiB
TypeScript
141 lines
3.8 KiB
TypeScript
import { useEffect, useState } from 'react'
|
||
import { useForm } from 'react-hook-form'
|
||
import {
|
||
Dialog,
|
||
DialogContent,
|
||
DialogDescription,
|
||
DialogFooter,
|
||
DialogHeader,
|
||
DialogTitle,
|
||
} from '@/components/ui/dialog'
|
||
import { Button } from '@/components/ui/button'
|
||
import { Input } from '@/components/ui/input'
|
||
import { Label } from '@/components/ui/label'
|
||
import { Textarea } from '@/components/ui/textarea'
|
||
import { TagsInput } from '@/components/tags-input'
|
||
import { useRepoStore } from '../store'
|
||
|
||
interface EditRepoDialogProps {
|
||
open: boolean
|
||
onOpenChange: (open: boolean) => void
|
||
repo: {
|
||
id: string
|
||
path: string
|
||
description: string
|
||
site: string
|
||
topics: string
|
||
license: string
|
||
} | null
|
||
}
|
||
|
||
interface FormData {
|
||
description: string
|
||
site: string
|
||
topics: string
|
||
license: string
|
||
}
|
||
|
||
export function EditRepoDialog({ open, onOpenChange, repo }: EditRepoDialogProps) {
|
||
const { updateRepoInfo, getList } = useRepoStore()
|
||
const { register, handleSubmit, reset, setValue } = useForm<FormData>()
|
||
const [tags, setTags] = useState<string[]>([])
|
||
|
||
useEffect(() => {
|
||
if (repo) {
|
||
const topicsArray = repo.topics ? repo.topics.split(',').map(t => t.trim()).filter(Boolean) : []
|
||
setTags(topicsArray)
|
||
reset({
|
||
description: repo.description || '',
|
||
site: repo.site || '',
|
||
topics: repo.topics || '',
|
||
license: repo.license || ''
|
||
})
|
||
}
|
||
}, [repo, reset])
|
||
|
||
const onSubmit = async (data: FormData) => {
|
||
if (!repo) return
|
||
|
||
await updateRepoInfo({
|
||
path: repo.path,
|
||
description: data.description?.trim() || '',
|
||
site: data.site?.trim() || '',
|
||
topics: tags.join(','),
|
||
license: data.license?.trim() || '',
|
||
})
|
||
|
||
await getList(true)
|
||
onOpenChange(false)
|
||
}
|
||
|
||
if (!repo) return null
|
||
|
||
return (
|
||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||
<DialogContent className="max-w-2xl!">
|
||
<DialogHeader>
|
||
<DialogTitle>编辑仓库信息</DialogTitle>
|
||
<DialogDescription>{repo.path}</DialogDescription>
|
||
</DialogHeader>
|
||
|
||
<form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
|
||
<div className="space-y-2">
|
||
<Label htmlFor="description">描述</Label>
|
||
<Textarea
|
||
id="description"
|
||
{...register('description')}
|
||
placeholder="输入仓库描述"
|
||
className="w-full min-h-[100px]"
|
||
rows={4}
|
||
/>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<Label htmlFor="site">网站</Label>
|
||
<Input
|
||
id="site"
|
||
{...register('site')}
|
||
placeholder="https://example.com"
|
||
type="url"
|
||
className="w-full"
|
||
/>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<Label htmlFor="topics">标签</Label>
|
||
<TagsInput
|
||
value={tags}
|
||
onChange={setTags}
|
||
placeholder="输入标签后按 Enter 或逗号添加"
|
||
/>
|
||
<p className="text-xs text-gray-500">按 Enter 或逗号添加标签,点击 × 删除</p>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<Label htmlFor="license">许可证</Label>
|
||
<Input
|
||
id="license"
|
||
{...register('license')}
|
||
placeholder="MIT, Apache-2.0, GPL-3.0 等"
|
||
className="w-full"
|
||
/>
|
||
</div>
|
||
|
||
<DialogFooter>
|
||
<Button
|
||
type="button"
|
||
variant="outline"
|
||
onClick={() => onOpenChange(false)}
|
||
>
|
||
取消
|
||
</Button>
|
||
<Button type="submit">
|
||
保存
|
||
</Button>
|
||
</DialogFooter>
|
||
</form>
|
||
</DialogContent>
|
||
</Dialog>
|
||
)
|
||
}
|