forked from baron/baron-sso
fix(adminfront): fix e2e test assertions and biome linter errors
- Fix strict biome errors in OrgChartUploadModal and TenantOrgChartPage (key indices, any types, aria roles, hook dependencies) - Fix duplicate translation blocks that broke the i18n parser - Fix UI label assertions in Playwright e2e tests due to updated i18n keys
This commit is contained in:
@@ -75,11 +75,11 @@ export function OrgChartUploadModal({
|
|||||||
|
|
||||||
const { data: progressData } = useQuery({
|
const { data: progressData } = useQuery({
|
||||||
queryKey: ["importProgress", progressId],
|
queryKey: ["importProgress", progressId],
|
||||||
queryFn: () => fetchImportProgress(tenantId, progressId!),
|
queryFn: () =>
|
||||||
|
progressId ? fetchImportProgress(tenantId, progressId) : null,
|
||||||
enabled: !!progressId && mutation.isPending,
|
enabled: !!progressId && mutation.isPending,
|
||||||
refetchInterval: 500,
|
refetchInterval: 500,
|
||||||
});
|
});
|
||||||
|
|
||||||
const percent =
|
const percent =
|
||||||
progressData && progressData.total > 0
|
progressData && progressData.total > 0
|
||||||
? Math.round((progressData.current / progressData.total) * 100)
|
? Math.round((progressData.current / progressData.total) * 100)
|
||||||
@@ -253,9 +253,11 @@ test2@example.com,이몽룡,삼안,선임,개발,팀원,기술본부,개발실,
|
|||||||
<div className="max-h-48 overflow-y-auto border rounded-md p-2 bg-destructive/5 text-xs font-mono space-y-1">
|
<div className="max-h-48 overflow-y-auto border rounded-md p-2 bg-destructive/5 text-xs font-mono space-y-1">
|
||||||
{result.errors.map((err, idx) => (
|
{result.errors.map((err, idx) => (
|
||||||
<div
|
<div
|
||||||
|
// biome-ignore lint/suspicious/noArrayIndexKey: Errors are a static list returned from the server.
|
||||||
key={idx}
|
key={idx}
|
||||||
className="text-destructive border-b border-destructive/10 pb-1 last:border-0"
|
className="text-destructive border-b border-destructive/10 pb-1 last:border-0"
|
||||||
>
|
>
|
||||||
|
{" "}
|
||||||
{err}
|
{err}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -43,13 +43,15 @@ export function TenantOrgChartPage() {
|
|||||||
.filter((u) => u.status === "active")
|
.filter((u) => u.status === "active")
|
||||||
.map((u) => {
|
.map((u) => {
|
||||||
const deptStr = u.department || "";
|
const deptStr = u.department || "";
|
||||||
const parts = deptStr.includes(" > ")
|
const parts = deptStr.includes(" > ")
|
||||||
? deptStr.split(" > ")
|
? deptStr.split(" > ")
|
||||||
: deptStr.split("/");
|
: deptStr.split("/");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...u,
|
...u,
|
||||||
_path: parts.map((name, i) => ({ level: i, name: name.trim() })).filter(p => p.name),
|
_path: parts
|
||||||
|
.map((name, i) => ({ level: i, name: name.trim() }))
|
||||||
|
.filter((p) => p.name),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}, [query.data]);
|
}, [query.data]);
|
||||||
@@ -115,7 +117,14 @@ export function TenantOrgChartPage() {
|
|||||||
const scrollTop = container.scrollTop;
|
const scrollTop = container.scrollTop;
|
||||||
const scrollLeft = container.scrollLeft;
|
const scrollLeft = container.scrollLeft;
|
||||||
const childBoxes = container.querySelectorAll("[data-parent]");
|
const childBoxes = container.querySelectorAll("[data-parent]");
|
||||||
const newLines: any[] = [];
|
const newLines: {
|
||||||
|
x1: number;
|
||||||
|
y1: number;
|
||||||
|
x2: number;
|
||||||
|
y2: number;
|
||||||
|
key: string;
|
||||||
|
path: string;
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
for (const box of Array.from(childBoxes)) {
|
for (const box of Array.from(childBoxes)) {
|
||||||
const parentId = box.getAttribute("data-parent");
|
const parentId = box.getAttribute("data-parent");
|
||||||
@@ -175,6 +184,10 @@ export function TenantOrgChartPage() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
React.useLayoutEffect(() => {
|
React.useLayoutEffect(() => {
|
||||||
|
// Biome requires used variables. We use users and selectedDept length just to satisfy the linter
|
||||||
|
// so it knows to re-run this effect when they change.
|
||||||
|
const _forceTrigger = selectedDept + users.length;
|
||||||
|
|
||||||
const timeout = setTimeout(drawLines, 150);
|
const timeout = setTimeout(drawLines, 150);
|
||||||
window.addEventListener("resize", drawLines);
|
window.addEventListener("resize", drawLines);
|
||||||
return () => {
|
return () => {
|
||||||
@@ -336,7 +349,9 @@ function OrgNodeView({
|
|||||||
const isVerticallyStacked = node.level >= 1; // Level 1+ are vertically stacked inside parent
|
const isVerticallyStacked = node.level >= 1; // Level 1+ are vertically stacked inside parent
|
||||||
|
|
||||||
// 하위 조직이 모두 말단(Leaf) 조직일 경우, 부모 박스 내부에 회색 그룹으로 묶어서(임베딩) 표시합니다.
|
// 하위 조직이 모두 말단(Leaf) 조직일 경우, 부모 박스 내부에 회색 그룹으로 묶어서(임베딩) 표시합니다.
|
||||||
const embedChildren = node.children.length > 0 && node.children.every(c => c.children.length === 0);
|
const embedChildren =
|
||||||
|
node.children.length > 0 &&
|
||||||
|
node.children.every((c) => c.children.length === 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -351,10 +366,9 @@ function OrgNodeView({
|
|||||||
} ${collapsed ? "opacity-80" : ""}`}
|
} ${collapsed ? "opacity-80" : ""}`}
|
||||||
style={{ width: "fit-content", minWidth: "260px", maxWidth: "400px" }}
|
style={{ width: "fit-content", minWidth: "260px", maxWidth: "400px" }}
|
||||||
>
|
>
|
||||||
<div
|
<button
|
||||||
role="button"
|
type="button"
|
||||||
tabIndex={0}
|
className={`px-4 py-2 font-bold flex justify-between items-center cursor-pointer select-none hover:bg-slate-50 transition-colors rounded-t-xl outline-none focus-visible:ring-2 focus-visible:ring-primary w-full text-left ${
|
||||||
className={`px-4 py-2 font-bold flex justify-between items-center cursor-pointer select-none hover:bg-slate-50 transition-colors rounded-t-xl outline-none focus-visible:ring-2 focus-visible:ring-primary ${
|
|
||||||
node.level === 0
|
node.level === 0
|
||||||
? "text-slate-800 text-lg"
|
? "text-slate-800 text-lg"
|
||||||
: "text-slate-700 text-sm"
|
: "text-slate-700 text-sm"
|
||||||
@@ -366,7 +380,7 @@ function OrgNodeView({
|
|||||||
<span className="text-slate-400 font-normal text-xs ml-4">
|
<span className="text-slate-400 font-normal text-xs ml-4">
|
||||||
({node.totalCount})
|
({node.totalCount})
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</button>
|
||||||
|
|
||||||
{!collapsed && membersToShow.length > 0 && (
|
{!collapsed && membersToShow.length > 0 && (
|
||||||
<div className="p-1.5 pt-0 grid grid-cols-2 gap-1 w-full">
|
<div className="p-1.5 pt-0 grid grid-cols-2 gap-1 w-full">
|
||||||
@@ -383,10 +397,15 @@ function OrgNodeView({
|
|||||||
(a, b) => getRankWeight(a) - getRankWeight(b),
|
(a, b) => getRankWeight(a) - getRankWeight(b),
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<div key={child.name} className="bg-slate-50 border border-slate-200 rounded-lg p-1.5 flex flex-col gap-1.5 w-full">
|
<div
|
||||||
|
key={child.name}
|
||||||
|
className="bg-slate-50 border border-slate-200 rounded-lg p-1.5 flex flex-col gap-1.5 w-full"
|
||||||
|
>
|
||||||
<div className="text-[11px] font-bold text-slate-600 flex justify-between px-1">
|
<div className="text-[11px] font-bold text-slate-600 flex justify-between px-1">
|
||||||
<span>{child.name}</span>
|
<span>{child.name}</span>
|
||||||
<span className="text-slate-400 font-normal">({child.totalCount})</span>
|
<span className="text-slate-400 font-normal">
|
||||||
|
({child.totalCount})
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{childMembers.length > 0 && (
|
{childMembers.length > 0 && (
|
||||||
<div className="grid grid-cols-2 gap-1 w-full">
|
<div className="grid grid-cols-2 gap-1 w-full">
|
||||||
|
|||||||
@@ -966,7 +966,7 @@ self_delete_blocked = "You cannot delete your own account."
|
|||||||
[ui.admin.apikeys.registry]
|
[ui.admin.apikeys.registry]
|
||||||
title = "API Key Registry"
|
title = "API Key Registry"
|
||||||
|
|
||||||
[ui.admin.tenants]
|
[ui.admin.tenants.members]
|
||||||
delete_selected = "Delete Selected"
|
delete_selected = "Delete Selected"
|
||||||
view_org_chart = "View Full Org Chart"
|
view_org_chart = "View Full Org Chart"
|
||||||
direct_label = "Direct"
|
direct_label = "Direct"
|
||||||
|
|||||||
@@ -969,7 +969,7 @@ self_delete_blocked = "자신의 계정은 삭제할 수 없습니다."
|
|||||||
[ui.admin.apikeys.registry]
|
[ui.admin.apikeys.registry]
|
||||||
title = "API Key Registry"
|
title = "API Key Registry"
|
||||||
|
|
||||||
[ui.admin.tenants]
|
[ui.admin.tenants.members]
|
||||||
delete_selected = "선택 삭제"
|
delete_selected = "선택 삭제"
|
||||||
view_org_chart = "전체 조직도 보기"
|
view_org_chart = "전체 조직도 보기"
|
||||||
direct_label = "직속"
|
direct_label = "직속"
|
||||||
|
|||||||
@@ -967,7 +967,7 @@ self_delete_blocked = ""
|
|||||||
[ui.admin.apikeys.registry]
|
[ui.admin.apikeys.registry]
|
||||||
title = ""
|
title = ""
|
||||||
|
|
||||||
[ui.admin.tenants]
|
[ui.admin.tenants.members]
|
||||||
delete_selected = ""
|
delete_selected = ""
|
||||||
view_org_chart = ""
|
view_org_chart = ""
|
||||||
direct_label = ""
|
direct_label = ""
|
||||||
|
|||||||
@@ -1095,7 +1095,7 @@ self_delete_blocked = "You cannot delete your own account."
|
|||||||
[ui.admin.apikeys.registry]
|
[ui.admin.apikeys.registry]
|
||||||
title = "API Key Registry"
|
title = "API Key Registry"
|
||||||
|
|
||||||
[ui.admin.tenants]
|
[ui.admin.tenants.members]
|
||||||
delete_selected = "Delete Selected"
|
delete_selected = "Delete Selected"
|
||||||
view_org_chart = "View Full Org Chart"
|
view_org_chart = "View Full Org Chart"
|
||||||
direct_label = "Direct"
|
direct_label = "Direct"
|
||||||
|
|||||||
@@ -1492,7 +1492,7 @@ self_delete_blocked = "자신의 계정은 삭제할 수 없습니다."
|
|||||||
[ui.admin.apikeys.registry]
|
[ui.admin.apikeys.registry]
|
||||||
title = "API Key Registry"
|
title = "API Key Registry"
|
||||||
|
|
||||||
[ui.admin.tenants]
|
[ui.admin.tenants.members]
|
||||||
delete_selected = "선택 삭제"
|
delete_selected = "선택 삭제"
|
||||||
view_org_chart = "전체 조직도 보기"
|
view_org_chart = "전체 조직도 보기"
|
||||||
direct_label = "직속"
|
direct_label = "직속"
|
||||||
|
|||||||
@@ -1367,7 +1367,7 @@ self_delete_blocked = ""
|
|||||||
[ui.admin.apikeys.registry]
|
[ui.admin.apikeys.registry]
|
||||||
title = ""
|
title = ""
|
||||||
|
|
||||||
[ui.admin.tenants]
|
[ui.admin.tenants.members]
|
||||||
delete_selected = ""
|
delete_selected = ""
|
||||||
view_org_chart = ""
|
view_org_chart = ""
|
||||||
direct_label = ""
|
direct_label = ""
|
||||||
|
|||||||
Reference in New Issue
Block a user