1
0
forked from baron/baron-sso

kratos SSOT 재설계

This commit is contained in:
2026-06-12 18:36:18 +09:00
parent b96c8100e0
commit 8e9d015443
39 changed files with 3960 additions and 501 deletions

View File

@@ -66,6 +66,7 @@ import {
filterWorksmobileComparisonRowsBySearch,
formatWorksmobileOrgDetails,
formatWorksmobilePersonName,
formatWorksmobileSelectionFailureDescription,
formatWorksmobileUpdateDetails,
getDefaultGroupComparisonFilters,
getDefaultUserComparisonFilters,
@@ -77,10 +78,12 @@ import {
getWorksmobileSelectedUpdateUserIds,
getWorksmobileSelectedWorksOnlyOrgUnitIds,
summarizeWorksmobileComparison,
type WorksmobileAccountStatusFilter,
type WorksmobileComparisonColumnKey,
type WorksmobileComparisonColumnVisibility,
type WorksmobileComparisonFilter,
type WorksmobileComparisonSummary,
worksmobileAccountStatusFilterOptions,
} from "./worksmobileComparison";
function worksmobileJobPayloadString(job: WorksmobileOutboxItem, key: string) {
@@ -183,6 +186,8 @@ export function TenantWorksmobilePage() {
const [groupFilters, setGroupFilters] = React.useState<
WorksmobileComparisonFilter[]
>(getDefaultGroupComparisonFilters);
const [userAccountStatusFilter, setUserAccountStatusFilter] =
React.useState<WorksmobileAccountStatusFilter>("all");
const [includeUserMissingExternalKey, setIncludeUserMissingExternalKey] =
React.useState(false);
const [includeGroupMissingExternalKey, setIncludeGroupMissingExternalKey] =
@@ -323,10 +328,11 @@ export function TenantWorksmobilePage() {
return {
resourceKind,
count: successCount,
failures,
failureCount: failures.length,
};
},
onSuccess: ({ resourceKind, count, failureCount }) => {
onSuccess: ({ resourceKind, count, failureCount, failures }) => {
if (resourceKind === "users") {
setSelectedUserRowKeys([]);
} else {
@@ -334,7 +340,10 @@ export function TenantWorksmobilePage() {
}
if (failureCount > 0) {
toast.error("일부 WORKS 생성 작업 등록 실패", {
description: `성공 ${count}건, 실패 ${failureCount}`,
description: formatWorksmobileSelectionFailureDescription(
count,
failures,
),
});
} else {
toast.success("WORKS 생성 작업을 등록했습니다.", {
@@ -418,6 +427,7 @@ export function TenantWorksmobilePage() {
comparisonUsers,
userFilters,
includeUserMissingExternalKey,
userAccountStatusFilter,
),
userSearch,
);
@@ -643,6 +653,11 @@ export function TenantWorksmobilePage() {
setUserFilters(nextFilters);
setSelectedUserRowKeys([]);
}}
accountStatusFilter={userAccountStatusFilter}
onAccountStatusFilterChange={(nextStatus) => {
setUserAccountStatusFilter(nextStatus);
setSelectedUserRowKeys([]);
}}
baronOrgColumnLabel="대표 Baron 조직"
includeMissingExternalKey={includeUserMissingExternalKey}
onIncludeMissingExternalKeyChange={(checked) => {
@@ -988,6 +1003,8 @@ function ComparisonTable({
searchPlaceholder = "이름 또는 UUID 검색",
filters,
onFiltersChange,
accountStatusFilter,
onAccountStatusFilterChange,
baronOrgColumnLabel = "Baron 조직",
includeMissingExternalKey,
onIncludeMissingExternalKeyChange,
@@ -1018,6 +1035,10 @@ function ComparisonTable({
searchPlaceholder?: string;
filters?: WorksmobileComparisonFilter[];
onFiltersChange?: (filters: WorksmobileComparisonFilter[]) => void;
accountStatusFilter?: WorksmobileAccountStatusFilter;
onAccountStatusFilterChange?: (
status: WorksmobileAccountStatusFilter,
) => void;
baronOrgColumnLabel?: string;
includeMissingExternalKey?: boolean;
onIncludeMissingExternalKeyChange?: (checked: boolean) => void;
@@ -1277,6 +1298,29 @@ function ComparisonTable({
) : null
}
/>
{accountStatusFilter && onAccountStatusFilterChange ? (
<div
className="flex flex-wrap items-center gap-2"
role="tablist"
aria-label="WORKS 계정 상태"
>
{worksmobileAccountStatusFilterOptions.map((option) => (
<Button
key={option.value}
type="button"
role="tab"
size="sm"
variant={
accountStatusFilter === option.value ? "default" : "outline"
}
aria-selected={accountStatusFilter === option.value}
onClick={() => onAccountStatusFilterChange(option.value)}
>
{option.label}
</Button>
))}
</div>
) : null}
</div>
<div className="flex shrink-0 flex-wrap items-center justify-end gap-2">
<Dialog
@@ -1603,6 +1647,13 @@ function ComparisonTable({
>
{getWorksmobileComparisonStatusLabel(row.status)}
</Badge>
{row.worksmobileAccountStatus && (
<div className="mt-1">
<Badge variant="outline">
WORKS {row.worksmobileAccountStatus}
</Badge>
</div>
)}
{formatWorksmobileUpdateDetails(row).map((detail) => (
<div
key={detail}