351 lines
12 KiB
TypeScript
351 lines
12 KiB
TypeScript
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
import {
|
|
issueAssigneeList,
|
|
issueAssigneeAdd,
|
|
issueAssigneeRemove,
|
|
issueClose,
|
|
issueDelete as apiIssueDelete,
|
|
issueReopen,
|
|
issueUpdate,
|
|
issueLabelList,
|
|
issueLabelAdd,
|
|
issueLabelAddBulk,
|
|
issueLabelRemove,
|
|
issuePullRequestList,
|
|
issuePullRequestLink,
|
|
issuePullRequestUnlink,
|
|
issueReactionList,
|
|
issueRepoList,
|
|
issueRepoLink,
|
|
issueRepoUnlink,
|
|
issueSubscriberList,
|
|
issueSubscribe,
|
|
issueUnsubscribe,
|
|
projectLabels,
|
|
labelCreate,
|
|
labelList as apiLabelList,
|
|
labelDelete as apiLabelDelete,
|
|
} from "@/client/api";
|
|
import type {
|
|
IssueAssigneeResponse,
|
|
IssueLabelResponse,
|
|
IssuePullRequestResponse,
|
|
IssueRepoResponse,
|
|
IssueSubscriberResponse,
|
|
ReactionListResponse,
|
|
LabelResponse,
|
|
CreateLabelRequest,
|
|
IssueUpdateRequest,
|
|
} from "@/client/model";
|
|
|
|
const ISSUE_QUERY_KEY = "issue";
|
|
|
|
interface IssueParams {
|
|
projectName: string;
|
|
issueNumber: number;
|
|
}
|
|
|
|
// Assignees
|
|
export function useIssueAssigneesQuery({ projectName, issueNumber }: IssueParams) {
|
|
return useQuery({
|
|
queryKey: [ISSUE_QUERY_KEY, projectName, issueNumber, "assignees"],
|
|
queryFn: async (): Promise<IssueAssigneeResponse[]> => {
|
|
const res = await issueAssigneeList(projectName, issueNumber);
|
|
return res.data.data ?? [];
|
|
},
|
|
enabled: !!projectName && !!issueNumber,
|
|
});
|
|
}
|
|
|
|
export function useAddAssigneeMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber, userId }: IssueParams & { userId: string }) => {
|
|
await issueAssigneeAdd(projectName, issueNumber, { user_id: userId });
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber, "assignees"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useRemoveAssigneeMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber, userId }: IssueParams & { userId: string }) => {
|
|
await issueAssigneeRemove(projectName, issueNumber, userId);
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber, "assignees"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
// Labels
|
|
export function useIssueLabelsQuery({ projectName, issueNumber }: IssueParams) {
|
|
return useQuery({
|
|
queryKey: [ISSUE_QUERY_KEY, projectName, issueNumber, "labels"],
|
|
queryFn: async (): Promise<IssueLabelResponse[]> => {
|
|
const res = await issueLabelList(projectName, issueNumber);
|
|
return res.data.data ?? [];
|
|
},
|
|
enabled: !!projectName && !!issueNumber,
|
|
});
|
|
}
|
|
|
|
export function useAddIssueLabelMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber, labelId }: IssueParams & { labelId: number }) => {
|
|
await issueLabelAdd(projectName, issueNumber, { label_id: labelId });
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber, "labels"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useRemoveIssueLabelMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber, labelId }: IssueParams & { labelId: number }) => {
|
|
await issueLabelRemove(projectName, issueNumber, labelId);
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber, "labels"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
// Project Labels
|
|
export function useProjectLabelsQuery(projectName: string) {
|
|
return useQuery({
|
|
queryKey: ["project", projectName, "labels"],
|
|
queryFn: async (): Promise<LabelResponse[]> => {
|
|
const res = await projectLabels(projectName);
|
|
return res.data.data?.labels ?? [];
|
|
},
|
|
enabled: !!projectName,
|
|
});
|
|
}
|
|
|
|
export function useCreateLabelMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, req }: { projectName: string, req: CreateLabelRequest }) => {
|
|
await labelCreate(projectName, req);
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: ["project", variables.projectName, "labels"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
// Reactions
|
|
export function useIssueReactionsQuery({ projectName, issueNumber }: IssueParams) {
|
|
return useQuery({
|
|
queryKey: [ISSUE_QUERY_KEY, projectName, issueNumber, "reactions"],
|
|
queryFn: async (): Promise<ReactionListResponse | null> => {
|
|
const res = await issueReactionList(projectName, issueNumber);
|
|
return res.data.data ?? null;
|
|
},
|
|
enabled: !!projectName && !!issueNumber,
|
|
});
|
|
}
|
|
|
|
// Subscribers
|
|
export function useIssueSubscribersQuery({ projectName, issueNumber }: IssueParams) {
|
|
return useQuery({
|
|
queryKey: [ISSUE_QUERY_KEY, projectName, issueNumber, "subscribers"],
|
|
queryFn: async (): Promise<IssueSubscriberResponse[]> => {
|
|
const res = await issueSubscriberList(projectName, issueNumber);
|
|
return res.data.data ?? [];
|
|
},
|
|
enabled: !!projectName && !!issueNumber,
|
|
});
|
|
}
|
|
|
|
export function useIssueSubscribeMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber }: IssueParams) => {
|
|
await issueSubscribe(projectName, issueNumber);
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber, "subscribers"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
// PRs & Repos
|
|
export function useIssuePRsQuery({ projectName, issueNumber }: IssueParams) {
|
|
return useQuery({
|
|
queryKey: [ISSUE_QUERY_KEY, projectName, issueNumber, "prs"],
|
|
queryFn: async (): Promise<IssuePullRequestResponse[]> => {
|
|
const res = await issuePullRequestList(projectName, issueNumber);
|
|
return res.data.data ?? [];
|
|
},
|
|
enabled: !!projectName && !!issueNumber,
|
|
});
|
|
}
|
|
|
|
export function useIssueReposQuery({ projectName, issueNumber }: IssueParams) {
|
|
return useQuery({
|
|
queryKey: [ISSUE_QUERY_KEY, projectName, issueNumber, "repos"],
|
|
queryFn: async (): Promise<IssueRepoResponse[]> => {
|
|
const res = await issueRepoList(projectName, issueNumber);
|
|
return res.data.data ?? [];
|
|
},
|
|
enabled: !!projectName && !!issueNumber,
|
|
});
|
|
}
|
|
|
|
// Close/Reopen/Update/Delete
|
|
export function useCloseIssueMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber }: IssueParams) => {
|
|
await issueClose(projectName, issueNumber);
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useReopenIssueMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber }: IssueParams) => {
|
|
await issueReopen(projectName, issueNumber);
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useUpdateIssueMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber, req }: IssueParams & { req: IssueUpdateRequest }) => {
|
|
await issueUpdate(projectName, issueNumber, req);
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useDeleteIssueMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber }: IssueParams) => {
|
|
await apiIssueDelete(projectName, issueNumber);
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber] });
|
|
},
|
|
});
|
|
}
|
|
|
|
// Bulk Label Add
|
|
export function useAddIssueLabelsBulkMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber, labelNames }: IssueParams & { labelNames: string[] }) => {
|
|
await issueLabelAddBulk(projectName, issueNumber, { names: labelNames });
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber, "labels"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
// PR Link/Unlink
|
|
export function useLinkPRMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber, repo, prNumber }: IssueParams & { repo: string; prNumber: number }) => {
|
|
await issuePullRequestLink(projectName, issueNumber, { repo, number: prNumber });
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber, "prs"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useUnlinkPRMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber, repo, prNumber }: IssueParams & { repo: string; prNumber: number }) => {
|
|
await issuePullRequestUnlink(projectName, issueNumber, repo, prNumber);
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber, "prs"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
// Repo Link/Unlink
|
|
export function useLinkRepoMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber, repo }: IssueParams & { repo: string }) => {
|
|
await issueRepoLink(projectName, issueNumber, { repo });
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber, "repos"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useUnlinkRepoMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber, repoId }: IssueParams & { repoId: string }) => {
|
|
await issueRepoUnlink(projectName, issueNumber, repoId);
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber, "repos"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
// Unsubscribe
|
|
export function useIssueUnsubscribeMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, issueNumber }: IssueParams) => {
|
|
await issueUnsubscribe(projectName, issueNumber);
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: [ISSUE_QUERY_KEY, variables.projectName, variables.issueNumber, "subscribers"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
// Label List/Delete (project level)
|
|
export function useLabelsQuery(projectName: string) {
|
|
return useQuery({
|
|
queryKey: ["project", projectName, "labels"],
|
|
queryFn: async () => {
|
|
const res = await apiLabelList(projectName);
|
|
return res.data.data ?? [];
|
|
},
|
|
enabled: !!projectName,
|
|
});
|
|
}
|
|
|
|
export function useDeleteLabelMutation() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ projectName, labelId }: { projectName: string; labelId: number }) => {
|
|
await apiLabelDelete(projectName, labelId);
|
|
},
|
|
onSuccess: (_, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: ["project", variables.projectName, "labels"] });
|
|
},
|
|
});
|
|
}
|