1
0
forked from baron/baron-sso

Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
2026-05-12 18:03:08 +09:00
86 changed files with 3749 additions and 2834 deletions

View File

@@ -21,6 +21,12 @@ import {
} from "lucide-react";
import * as React from "react";
import { Link, useNavigate } from "react-router-dom";
import {
sortItems,
toggleSort,
type SortConfig,
type SortResolverMap,
} from "../../../../../common/core/utils";
import { RoleGuard } from "../../../components/auth/RoleGuard";
import { Badge } from "../../../components/ui/badge";
import { Button } from "../../../components/ui/button";
@@ -82,10 +88,7 @@ import {
const tenantCSVTemplate =
"name,type,parent_tenant_slug,slug,memo,email_domain,visibility,org_unit_type\n";
type SortConfig = {
key: keyof TenantSummary | "recursiveMemberCount";
direction: "asc" | "desc";
};
type TenantSortKey = keyof TenantSummary | "recursiveMemberCount";
const getTenantIcon = (type?: string) => {
switch (type?.toUpperCase()) {
@@ -225,7 +228,8 @@ function TenantListPage() {
const [viewMode, setViewMode] = React.useState<"list" | "hierarchy">("list");
const [selectedIds, setSelectedIds] = React.useState<string[]>([]);
const [search, setSearch] = React.useState("");
const [sortConfig, setSortConfig] = React.useState<SortConfig | null>(null);
const [sortConfig, setSortConfig] =
React.useState<SortConfig<TenantSortKey> | null>(null);
const fileInputRef = React.useRef<HTMLInputElement | null>(null);
const [importMessage, setImportMessage] = React.useState("");
const [previewRows, setPreviewRows] = React.useState<
@@ -363,6 +367,17 @@ function TenantListPage() {
const allTenants = query.data?.items ?? [];
const importParentOptionGroups =
buildTenantImportParentOptionGroups(allTenants);
const tenantSortResolvers = React.useMemo<
SortResolverMap<
TenantSummary & { recursiveMemberCount: number },
TenantSortKey
>
>(
() => ({
recursiveMemberCount: (tenant) => tenant.recursiveMemberCount,
}),
[],
);
const tenants = React.useMemo(() => {
// 1. Calculate recursive counts
// buildTenantFullTree returns subTree which represents roots, but it also mutates the mapped nodes internally.
@@ -396,38 +411,14 @@ function TenantListPage() {
);
}
if (sortConfig) {
enriched.sort((a, b) => {
const aValue = a[sortConfig.key as keyof typeof a];
const bValue = b[sortConfig.key as keyof typeof b];
return sortItems(enriched, sortConfig, tenantSortResolvers);
}, [allTenants, search, sortConfig, tenantSortResolvers]);
if (aValue === bValue) return 0;
if (aValue === null || aValue === undefined) return 1;
if (bValue === null || bValue === undefined) return -1;
if (sortConfig.direction === "asc") {
return aValue < bValue ? -1 : 1;
}
return aValue > bValue ? -1 : 1;
});
}
return enriched;
}, [allTenants, search, sortConfig]);
const requestSort = (key: SortConfig["key"]) => {
let direction: "asc" | "desc" = "asc";
if (
sortConfig &&
sortConfig.key === key &&
sortConfig.direction === "asc"
) {
direction = "desc";
}
setSortConfig({ key, direction });
const requestSort = (key: TenantSortKey) => {
setSortConfig((current) => toggleSort(current, key));
};
const getSortIcon = (key: SortConfig["key"]) => {
const getSortIcon = (key: TenantSortKey) => {
if (!sortConfig || sortConfig.key !== key) {
return <ArrowUpDown size={14} className="ml-1 opacity-50" />;
}