forked from baron/baron-sso
adminfront: React Query Optimistic Updates 적용하여 세부 권한 매트릭스 UI 0ms 즉각 반응하도록 속도 고도화 완료
This commit is contained in:
@@ -75,24 +75,74 @@ export function TenantFineGrainedPermissionsPage() {
|
|||||||
const addSystemRelationMutation = useMutation({
|
const addSystemRelationMutation = useMutation({
|
||||||
mutationFn: (payload: { userId: string; relation: string }) =>
|
mutationFn: (payload: { userId: string; relation: string }) =>
|
||||||
addSystemRelation(payload.userId, payload.relation),
|
addSystemRelation(payload.userId, payload.relation),
|
||||||
|
onMutate: async (newRelation) => {
|
||||||
|
await queryClient.cancelQueries({ queryKey: ["system-relations"] });
|
||||||
|
const previousRelations = queryClient.getQueryData<TenantRelation[]>(["system-relations"]);
|
||||||
|
|
||||||
|
queryClient.setQueryData<TenantRelation[]>(["system-relations"], (old) => {
|
||||||
|
if (!old) return [];
|
||||||
|
return old.map((user) => {
|
||||||
|
if (user.userId === newRelation.userId) {
|
||||||
|
return {
|
||||||
|
...user,
|
||||||
|
relations: user.relations.includes(newRelation.relation)
|
||||||
|
? user.relations
|
||||||
|
: [...user.relations, newRelation.relation],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return { previousRelations };
|
||||||
|
},
|
||||||
|
onError: (err: AxiosError<{ error?: string }>, _, context) => {
|
||||||
|
if (context?.previousRelations) {
|
||||||
|
queryClient.setQueryData(["system-relations"], context.previousRelations);
|
||||||
|
}
|
||||||
|
toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다."));
|
||||||
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ["system-relations"] });
|
|
||||||
toast.success(t("msg.admin.system.relations.add_success", "시스템 메뉴 권한이 추가되었습니다."));
|
toast.success(t("msg.admin.system.relations.add_success", "시스템 메뉴 권한이 추가되었습니다."));
|
||||||
},
|
},
|
||||||
onError: (err: AxiosError<{ error?: string }>) => {
|
onSettled: () => {
|
||||||
toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다."));
|
queryClient.invalidateQueries({ queryKey: ["system-relations"] });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const removeSystemRelationMutation = useMutation({
|
const removeSystemRelationMutation = useMutation({
|
||||||
mutationFn: (payload: { userId: string; relation: string }) =>
|
mutationFn: (payload: { userId: string; relation: string }) =>
|
||||||
removeSystemRelation(payload.userId, payload.relation),
|
removeSystemRelation(payload.userId, payload.relation),
|
||||||
|
onMutate: async (targetRelation) => {
|
||||||
|
await queryClient.cancelQueries({ queryKey: ["system-relations"] });
|
||||||
|
const previousRelations = queryClient.getQueryData<TenantRelation[]>(["system-relations"]);
|
||||||
|
|
||||||
|
queryClient.setQueryData<TenantRelation[]>(["system-relations"], (old) => {
|
||||||
|
if (!old) return [];
|
||||||
|
return old.map((user) => {
|
||||||
|
if (user.userId === targetRelation.userId) {
|
||||||
|
return {
|
||||||
|
...user,
|
||||||
|
relations: user.relations.filter((r) => r !== targetRelation.relation),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return { previousRelations };
|
||||||
|
},
|
||||||
|
onError: (err: AxiosError<{ error?: string }>, _, context) => {
|
||||||
|
if (context?.previousRelations) {
|
||||||
|
queryClient.setQueryData(["system-relations"], context.previousRelations);
|
||||||
|
}
|
||||||
|
toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다."));
|
||||||
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ["system-relations"] });
|
|
||||||
toast.success(t("msg.admin.system.relations.remove_success", "시스템 메뉴 권한이 회수되었습니다."));
|
toast.success(t("msg.admin.system.relations.remove_success", "시스템 메뉴 권한이 회수되었습니다."));
|
||||||
},
|
},
|
||||||
onError: (err: AxiosError<{ error?: string }>) => {
|
onSettled: () => {
|
||||||
toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다."));
|
queryClient.invalidateQueries({ queryKey: ["system-relations"] });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -68,24 +68,74 @@ export function TenantFineGrainedPermissionsTab({ tenantIdProp }: TenantFineGrai
|
|||||||
const addRelationMutation = useMutation({
|
const addRelationMutation = useMutation({
|
||||||
mutationFn: (payload: { userId: string; relation: string }) =>
|
mutationFn: (payload: { userId: string; relation: string }) =>
|
||||||
addTenantRelation(tenantId, payload.userId, payload.relation),
|
addTenantRelation(tenantId, payload.userId, payload.relation),
|
||||||
|
onMutate: async (newRelation) => {
|
||||||
|
await queryClient.cancelQueries({ queryKey: ["tenant-relations", tenantId] });
|
||||||
|
const previousRelations = queryClient.getQueryData<TenantRelation[]>(["tenant-relations", tenantId]);
|
||||||
|
|
||||||
|
queryClient.setQueryData<TenantRelation[]>(["tenant-relations", tenantId], (old) => {
|
||||||
|
if (!old) return [];
|
||||||
|
return old.map((user) => {
|
||||||
|
if (user.userId === newRelation.userId) {
|
||||||
|
return {
|
||||||
|
...user,
|
||||||
|
relations: user.relations.includes(newRelation.relation)
|
||||||
|
? user.relations
|
||||||
|
: [...user.relations, newRelation.relation],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return { previousRelations };
|
||||||
|
},
|
||||||
|
onError: (err: AxiosError<{ error?: string }>, _, context) => {
|
||||||
|
if (context?.previousRelations) {
|
||||||
|
queryClient.setQueryData(["tenant-relations", tenantId], context.previousRelations);
|
||||||
|
}
|
||||||
|
toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다."));
|
||||||
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ["tenant-relations", tenantId] });
|
|
||||||
toast.success(t("msg.admin.tenants.relations.add_success", "세부 권한이 추가되었습니다."));
|
toast.success(t("msg.admin.tenants.relations.add_success", "세부 권한이 추가되었습니다."));
|
||||||
},
|
},
|
||||||
onError: (err: AxiosError<{ error?: string }>) => {
|
onSettled: () => {
|
||||||
toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다."));
|
queryClient.invalidateQueries({ queryKey: ["tenant-relations", tenantId] });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const removeRelationMutation = useMutation({
|
const removeRelationMutation = useMutation({
|
||||||
mutationFn: (payload: { userId: string; relation: string }) =>
|
mutationFn: (payload: { userId: string; relation: string }) =>
|
||||||
removeTenantRelation(tenantId, payload.userId, payload.relation),
|
removeTenantRelation(tenantId, payload.userId, payload.relation),
|
||||||
|
onMutate: async (targetRelation) => {
|
||||||
|
await queryClient.cancelQueries({ queryKey: ["tenant-relations", tenantId] });
|
||||||
|
const previousRelations = queryClient.getQueryData<TenantRelation[]>(["tenant-relations", tenantId]);
|
||||||
|
|
||||||
|
queryClient.setQueryData<TenantRelation[]>(["tenant-relations", tenantId], (old) => {
|
||||||
|
if (!old) return [];
|
||||||
|
return old.map((user) => {
|
||||||
|
if (user.userId === targetRelation.userId) {
|
||||||
|
return {
|
||||||
|
...user,
|
||||||
|
relations: user.relations.filter((r) => r !== targetRelation.relation),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return { previousRelations };
|
||||||
|
},
|
||||||
|
onError: (err: AxiosError<{ error?: string }>, _, context) => {
|
||||||
|
if (context?.previousRelations) {
|
||||||
|
queryClient.setQueryData(["tenant-relations", tenantId], context.previousRelations);
|
||||||
|
}
|
||||||
|
toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다."));
|
||||||
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ["tenant-relations", tenantId] });
|
|
||||||
toast.success(t("msg.admin.tenants.relations.remove_success", "세부 권한이 회수되었습니다."));
|
toast.success(t("msg.admin.tenants.relations.remove_success", "세부 권한이 회수되었습니다."));
|
||||||
},
|
},
|
||||||
onError: (err: AxiosError<{ error?: string }>) => {
|
onSettled: () => {
|
||||||
toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다."));
|
queryClient.invalidateQueries({ queryKey: ["tenant-relations", tenantId] });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user