forked from baron/baron-sso
Merge branch 'dev' into feature/tenant-user-list-ui-improvement
This commit is contained in:
@@ -27,6 +27,10 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "../../components/ui/table";
|
||||
import {
|
||||
commonTableShellClass,
|
||||
commonTableViewportClass,
|
||||
} from "../../../../common/ui/table";
|
||||
import type { AuditLog } from "../../lib/adminApi";
|
||||
import { fetchAuditLogs } from "../../lib/adminApi";
|
||||
import { t } from "../../lib/i18n";
|
||||
@@ -254,8 +258,8 @@ function AuditLogsPage() {
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
<div className="flex-1 rounded-md border overflow-hidden flex flex-col">
|
||||
<div className="flex-1 overflow-auto relative custom-scrollbar">
|
||||
<div className={commonTableShellClass}>
|
||||
<div className={commonTableViewportClass}>
|
||||
<Table className="table-fixed">
|
||||
<TableHeader className="sticky top-0 z-10 bg-secondary shadow-sm">
|
||||
<TableRow>
|
||||
|
||||
@@ -29,10 +29,19 @@ import {
|
||||
import * as React from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import {
|
||||
type SortConfig,
|
||||
type SortResolverMap,
|
||||
SortableTableHead,
|
||||
sortableTableHeadBaseClassName,
|
||||
sortableTableHeaderClassName,
|
||||
} from "../../../../../common/core/components/sort";
|
||||
import {
|
||||
commonTableShellClass,
|
||||
commonTableViewportClass,
|
||||
} from "../../../../../common/ui/table";
|
||||
import {
|
||||
sortItems,
|
||||
toggleSort,
|
||||
type SortConfig,
|
||||
type SortResolverMap,
|
||||
} from "../../../../../common/core/utils";
|
||||
import { RoleGuard } from "../../../components/auth/RoleGuard";
|
||||
import { Badge } from "../../../components/ui/badge";
|
||||
@@ -257,7 +266,10 @@ function TenantListPage() {
|
||||
const [selectedIds, setSelectedIds] = React.useState<string[]>([]);
|
||||
const [search, setSearch] = React.useState("");
|
||||
const [sortConfig, setSortConfig] =
|
||||
React.useState<SortConfig<TenantSortKey> | null>(null);
|
||||
React.useState<SortConfig<TenantSortKey> | null>({
|
||||
key: "createdAt",
|
||||
direction: "desc",
|
||||
});
|
||||
const fileInputRef = React.useRef<HTMLInputElement | null>(null);
|
||||
const [importMessage, setImportMessage] = React.useState("");
|
||||
const [previewRows, setPreviewRows] = React.useState<
|
||||
@@ -444,9 +456,8 @@ function TenantListPage() {
|
||||
}
|
||||
|
||||
if (
|
||||
profile &&
|
||||
profileRole === "tenant_admin" &&
|
||||
(profile.manageableTenants?.length ?? 0) <= 1
|
||||
(profile?.manageableTenants?.length ?? 0) <= 1
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
@@ -487,17 +498,6 @@ function TenantListPage() {
|
||||
setSortConfig((current) => toggleSort(current, key));
|
||||
};
|
||||
|
||||
const getSortIcon = (key: TenantSortKey) => {
|
||||
if (!sortConfig || sortConfig.key !== key) {
|
||||
return <ArrowUpDown size={14} className="ml-1 opacity-50" />;
|
||||
}
|
||||
return sortConfig.direction === "asc" ? (
|
||||
<ArrowUp size={14} className="ml-1" />
|
||||
) : (
|
||||
<ArrowDown size={14} className="ml-1" />
|
||||
);
|
||||
};
|
||||
|
||||
const deletableTenants = React.useMemo(
|
||||
() => allTenants.filter((tenant) => !isSeedTenant(tenant)),
|
||||
[allTenants],
|
||||
|
||||
@@ -24,6 +24,15 @@ import {
|
||||
sortItems,
|
||||
toggleSort,
|
||||
} from "../../../../common/core/utils";
|
||||
import {
|
||||
SortableTableHead,
|
||||
sortableTableHeadBaseClassName,
|
||||
sortableTableHeaderClassName,
|
||||
} from "../../../../common/core/components/sort";
|
||||
import {
|
||||
commonTableShellClass,
|
||||
commonTableViewportClass,
|
||||
} from "../../../../common/ui/table";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
@@ -294,17 +303,6 @@ function UserListPage() {
|
||||
setSortConfig((current) => toggleSort(current, key));
|
||||
};
|
||||
|
||||
const getSortIcon = (key: UserSortKey) => {
|
||||
if (!sortConfig || sortConfig.key !== key) {
|
||||
return <ArrowUpDown size={14} className="ml-1 opacity-50" />;
|
||||
}
|
||||
return sortConfig.direction === "asc" ? (
|
||||
<ArrowUp size={14} className="ml-1" />
|
||||
) : (
|
||||
<ArrowDown size={14} className="ml-1" />
|
||||
);
|
||||
};
|
||||
|
||||
const total = query.data?.total ?? 0;
|
||||
const totalPages = Math.ceil(total / limit);
|
||||
const canPromoteSuperAdmin = isSuperAdminRole(profile?.role);
|
||||
@@ -603,12 +601,14 @@ function UserListPage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex-1 rounded-md border overflow-hidden flex flex-col">
|
||||
<div className="flex-1 overflow-auto relative custom-scrollbar">
|
||||
<div className={commonTableShellClass}>
|
||||
<div className={commonTableViewportClass}>
|
||||
<Table>
|
||||
<TableHeader className="sticky top-0 z-10 bg-secondary shadow-sm">
|
||||
<TableHeader className={sortableTableHeaderClassName}>
|
||||
<TableRow>
|
||||
<TableHead className="w-12">
|
||||
<TableHead
|
||||
className={`${sortableTableHeadBaseClassName} w-12`}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
className="w-4 h-4 rounded border-gray-300 text-primary focus:ring-primary cursor-pointer"
|
||||
@@ -689,34 +689,30 @@ function UserListPage() {
|
||||
{userSchema.map(
|
||||
(field) =>
|
||||
visibleColumns[field.key] !== false && (
|
||||
<TableHead
|
||||
<SortableTableHead
|
||||
key={field.key}
|
||||
className="whitespace-nowrap uppercase cursor-pointer hover:bg-muted/50 transition-colors"
|
||||
onClick={() => requestSort(field.key)}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
{field.label}
|
||||
{getSortIcon(field.key)}
|
||||
</div>
|
||||
</TableHead>
|
||||
className="whitespace-nowrap"
|
||||
label={field.label}
|
||||
onSort={requestSort}
|
||||
sortConfig={sortConfig}
|
||||
sortKey={field.key}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
<TableHead
|
||||
className="whitespace-nowrap cursor-pointer hover:bg-muted/50 transition-colors"
|
||||
onClick={() => requestSort("createdAt")}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
{t("ui.admin.users.list.table.created", "CREATED")}
|
||||
{getSortIcon("createdAt")}
|
||||
</div>
|
||||
</TableHead>
|
||||
<SortableTableHead
|
||||
className="whitespace-nowrap"
|
||||
label={t("ui.admin.users.list.table.created", "CREATED")}
|
||||
onSort={requestSort}
|
||||
sortConfig={sortConfig}
|
||||
sortKey="createdAt"
|
||||
/>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{query.isLoading && (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
colSpan={6 + userSchema.length}
|
||||
colSpan={7 + userSchema.length}
|
||||
className="h-24 text-center"
|
||||
>
|
||||
{t("msg.common.loading", "로딩 중...")}
|
||||
@@ -726,7 +722,7 @@ function UserListPage() {
|
||||
{!query.isLoading && items.length === 0 && (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
colSpan={6 + userSchema.length}
|
||||
colSpan={7 + userSchema.length}
|
||||
className="h-24 text-center"
|
||||
>
|
||||
{t(
|
||||
|
||||
Reference in New Issue
Block a user