feat(ui): comment insert / close
This commit is contained in:
parent
9300f4b670
commit
a985af3f4a
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
|
|
||||||
import { ExternalLink, Loader2, MessageSquarePlus, Pencil } from "lucide-react";
|
import { ExternalLink, Loader2, MessageSquarePlus, Pencil, XCircle } from "lucide-react";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
|
|
@ -20,8 +20,9 @@ import {
|
||||||
type ForgejoIssue,
|
type ForgejoIssue,
|
||||||
type ForgejoIssueDetail,
|
type ForgejoIssueDetail,
|
||||||
} from "@/lib/api-forgejo";
|
} from "@/lib/api-forgejo";
|
||||||
import { PostForgejoCommentDialog } from "@/components/git/PostForgejoCommentDialog";
|
import { CloseForgejoIssueDialog } from "@/components/git/CloseForgejoIssueDialog";
|
||||||
import { EditForgejoIssueDialog } from "@/components/git/EditForgejoIssueDialog";
|
import { EditForgejoIssueDialog } from "@/components/git/EditForgejoIssueDialog";
|
||||||
|
import { PostForgejoCommentDialog } from "@/components/git/PostForgejoCommentDialog";
|
||||||
|
|
||||||
type ForgejoIssueDetailDialogProps = {
|
type ForgejoIssueDetailDialogProps = {
|
||||||
issue: ForgejoIssue | null;
|
issue: ForgejoIssue | null;
|
||||||
|
|
@ -29,6 +30,7 @@ type ForgejoIssueDetailDialogProps = {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
onRefresh?: () => void;
|
onRefresh?: () => void;
|
||||||
|
canClose?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatDateTime = (value: string | null | undefined): string => {
|
const formatDateTime = (value: string | null | undefined): string => {
|
||||||
|
|
@ -58,6 +60,7 @@ export function ForgejoIssueDetailDialog({
|
||||||
open,
|
open,
|
||||||
onOpenChange,
|
onOpenChange,
|
||||||
onRefresh,
|
onRefresh,
|
||||||
|
canClose = false,
|
||||||
}: ForgejoIssueDetailDialogProps) {
|
}: ForgejoIssueDetailDialogProps) {
|
||||||
const [detail, setDetail] = useState<ForgejoIssueDetail | null>(null);
|
const [detail, setDetail] = useState<ForgejoIssueDetail | null>(null);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
@ -66,6 +69,7 @@ export function ForgejoIssueDetailDialog({
|
||||||
|
|
||||||
const [isCommentDialogOpen, setIsCommentDialogOpen] = useState(false);
|
const [isCommentDialogOpen, setIsCommentDialogOpen] = useState(false);
|
||||||
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
|
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
|
||||||
|
const [isCloseIssueDialogOpen, setIsCloseIssueDialogOpen] = useState(false);
|
||||||
|
|
||||||
const loadDetail = (id: string) => {
|
const loadDetail = (id: string) => {
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
|
|
@ -113,6 +117,12 @@ export function ForgejoIssueDetailDialog({
|
||||||
const body = detail?.body ?? issue.body ?? issue.body_preview ?? "";
|
const body = detail?.body ?? issue.body ?? issue.body_preview ?? "";
|
||||||
const stateVariant = active.state === "open" ? "success" : "default";
|
const stateVariant = active.state === "open" ? "success" : "default";
|
||||||
|
|
||||||
|
const handleCloseIssueSuccess = () => {
|
||||||
|
if (detail) setDetail({ ...detail, state: "closed" });
|
||||||
|
if (issue) loadDetail(issue.id);
|
||||||
|
onRefresh?.();
|
||||||
|
};
|
||||||
|
|
||||||
const handleCommentSuccess = () => {
|
const handleCommentSuccess = () => {
|
||||||
if (issue) loadDetail(issue.id);
|
if (issue) loadDetail(issue.id);
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
|
|
@ -179,6 +189,17 @@ export function ForgejoIssueDetailDialog({
|
||||||
<MessageSquarePlus className="h-3.5 w-3.5" />
|
<MessageSquarePlus className="h-3.5 w-3.5" />
|
||||||
Comment
|
Comment
|
||||||
</Button>
|
</Button>
|
||||||
|
{canClose && active.state === "open" ? (
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
className="h-9 gap-2 rounded-xl border-[color:rgba(248,113,113,0.45)] px-3 text-xs font-semibold text-[color:var(--danger)] hover:bg-[color:rgba(248,113,113,0.08)]"
|
||||||
|
onClick={() => setIsCloseIssueDialogOpen(true)}
|
||||||
|
>
|
||||||
|
<XCircle className="h-3.5 w-3.5" />
|
||||||
|
Close Issue
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
<a
|
<a
|
||||||
href={active.html_url}
|
href={active.html_url}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
|
@ -357,12 +378,20 @@ export function ForgejoIssueDetailDialog({
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
||||||
Close
|
Dismiss
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
|
<CloseForgejoIssueDialog
|
||||||
|
issue={issue}
|
||||||
|
repositoryName={repositoryName}
|
||||||
|
open={isCloseIssueDialogOpen}
|
||||||
|
onOpenChange={setIsCloseIssueDialogOpen}
|
||||||
|
onCloseSuccess={handleCloseIssueSuccess}
|
||||||
|
/>
|
||||||
|
|
||||||
<PostForgejoCommentDialog
|
<PostForgejoCommentDialog
|
||||||
issue={issue}
|
issue={issue}
|
||||||
repositoryName={repositoryName}
|
repositoryName={repositoryName}
|
||||||
|
|
|
||||||
|
|
@ -421,6 +421,7 @@ export function ForgejoIssuesTable({
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onRefresh={onRefresh}
|
onRefresh={onRefresh}
|
||||||
|
canClose={canClose}
|
||||||
/>
|
/>
|
||||||
<EditForgejoIssueDialog
|
<EditForgejoIssueDialog
|
||||||
issue={issueToEdit}
|
issue={issueToEdit}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue