mirror of
https://github.com/fosrl/pangolin.git
synced 2025-08-01 16:45:40 +02:00
add admin/user i18n
This commit is contained in:
parent
e38941adf1
commit
4dd9f4736d
4 changed files with 40 additions and 28 deletions
|
@ -285,5 +285,17 @@
|
||||||
"apiKeysDeleteConfirm": "Confirm Delete API Key",
|
"apiKeysDeleteConfirm": "Confirm Delete API Key",
|
||||||
"apiKeysDelete": "Delete API Key",
|
"apiKeysDelete": "Delete API Key",
|
||||||
"apiKeysManage": "Manage API Keys",
|
"apiKeysManage": "Manage API Keys",
|
||||||
"apiKeysDescription": "API keys are used to authenticate with the integration API"
|
"apiKeysDescription": "API keys are used to authenticate with the integration API",
|
||||||
|
"userTitle": "Manage All Users",
|
||||||
|
"userDescription": "View and manage all users in the system",
|
||||||
|
"userAbount": "About User Management",
|
||||||
|
"userAbountDescription": "This table displays all root user objects in the system. Each user may belong to multiple organizations. Removing a user from an organization does not delete their root user object - they will remain in the system. To completely remove a user from the system, you must delete their root user object using the delete action in this table.",
|
||||||
|
"userServer": "Server Users",
|
||||||
|
"userSearch": "Search server users...",
|
||||||
|
"userErrorDelete": "Error deleting user",
|
||||||
|
"userDeleteConfirm": "Confirm Delete User",
|
||||||
|
"userDeleteServer": "Delete User from Server",
|
||||||
|
"userMessageRemove": "The user will be removed from all organizations and be completely removed from the server.",
|
||||||
|
"userMessageConfirm": "To confirm, please type the name of the user below.",
|
||||||
|
"userQuestionRemove": "Are you sure you want to permanently delete {selectedUser} from the server?"
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {
|
||||||
ColumnDef,
|
ColumnDef,
|
||||||
} from "@tanstack/react-table";
|
} from "@tanstack/react-table";
|
||||||
import { DataTable } from "@app/components/ui/data-table";
|
import { DataTable } from "@app/components/ui/data-table";
|
||||||
|
import { useTranslations } from 'next-intl';
|
||||||
|
|
||||||
interface DataTableProps<TData, TValue> {
|
interface DataTableProps<TData, TValue> {
|
||||||
columns: ColumnDef<TData, TValue>[];
|
columns: ColumnDef<TData, TValue>[];
|
||||||
|
@ -14,12 +15,15 @@ export function UsersDataTable<TData, TValue>({
|
||||||
columns,
|
columns,
|
||||||
data
|
data
|
||||||
}: DataTableProps<TData, TValue>) {
|
}: DataTableProps<TData, TValue>) {
|
||||||
|
|
||||||
|
const t = useTranslations();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataTable
|
<DataTable
|
||||||
columns={columns}
|
columns={columns}
|
||||||
data={data}
|
data={data}
|
||||||
title="Server Users"
|
title={t('userServer')}
|
||||||
searchPlaceholder="Search server users..."
|
searchPlaceholder={t('userSearch')}
|
||||||
searchColumn="email"
|
searchColumn="email"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { toast } from "@app/hooks/useToast";
|
||||||
import { formatAxiosError } from "@app/lib/api";
|
import { formatAxiosError } from "@app/lib/api";
|
||||||
import { createApiClient } from "@app/lib/api";
|
import { createApiClient } from "@app/lib/api";
|
||||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||||
|
import { useTranslations } from 'next-intl';
|
||||||
|
|
||||||
export type GlobalUserRow = {
|
export type GlobalUserRow = {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -29,6 +30,7 @@ type Props = {
|
||||||
|
|
||||||
export default function UsersTable({ users }: Props) {
|
export default function UsersTable({ users }: Props) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const t = useTranslations();
|
||||||
|
|
||||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||||
const [selected, setSelected] = useState<GlobalUserRow | null>(null);
|
const [selected, setSelected] = useState<GlobalUserRow | null>(null);
|
||||||
|
@ -42,8 +44,8 @@ export default function UsersTable({ users }: Props) {
|
||||||
console.error("Error deleting user", e);
|
console.error("Error deleting user", e);
|
||||||
toast({
|
toast({
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
title: "Error deleting user",
|
title: t('userErrorDelete'),
|
||||||
description: formatAxiosError(e, "Error deleting user")
|
description: formatAxiosError(e, t('userErrorDelete'))
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -82,7 +84,7 @@ export default function UsersTable({ users }: Props) {
|
||||||
column.toggleSorting(column.getIsSorted() === "asc")
|
column.toggleSorting(column.getIsSorted() === "asc")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Username
|
{t('username')}
|
||||||
<ArrowUpDown className="ml-2 h-4 w-4" />
|
<ArrowUpDown className="ml-2 h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
@ -98,7 +100,7 @@ export default function UsersTable({ users }: Props) {
|
||||||
column.toggleSorting(column.getIsSorted() === "asc")
|
column.toggleSorting(column.getIsSorted() === "asc")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Email
|
{t('email')}
|
||||||
<ArrowUpDown className="ml-2 h-4 w-4" />
|
<ArrowUpDown className="ml-2 h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
@ -114,7 +116,7 @@ export default function UsersTable({ users }: Props) {
|
||||||
column.toggleSorting(column.getIsSorted() === "asc")
|
column.toggleSorting(column.getIsSorted() === "asc")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Name
|
{t('name')}
|
||||||
<ArrowUpDown className="ml-2 h-4 w-4" />
|
<ArrowUpDown className="ml-2 h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
@ -130,7 +132,7 @@ export default function UsersTable({ users }: Props) {
|
||||||
column.toggleSorting(column.getIsSorted() === "asc")
|
column.toggleSorting(column.getIsSorted() === "asc")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Identity Provider
|
{t('identityProvider')}
|
||||||
<ArrowUpDown className="ml-2 h-4 w-4" />
|
<ArrowUpDown className="ml-2 h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
@ -151,7 +153,7 @@ export default function UsersTable({ users }: Props) {
|
||||||
setIsDeleteModalOpen(true);
|
setIsDeleteModalOpen(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Delete
|
{t('delete')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -172,35 +174,26 @@ export default function UsersTable({ users }: Props) {
|
||||||
dialog={
|
dialog={
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<p>
|
<p>
|
||||||
Are you sure you want to permanently delete{" "}
|
{t('userQuestionRemove', {selectedUser: selected?.email || selected?.name || selected?.username})}
|
||||||
<b className="break-all">
|
|
||||||
{selected?.email ||
|
|
||||||
selected?.name ||
|
|
||||||
selected?.username}
|
|
||||||
</b>{" "}
|
|
||||||
from the server?
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<b>
|
<b>
|
||||||
The user will be removed from all
|
{t('userMessageRemove')}
|
||||||
organizations and be completely removed from
|
|
||||||
the server.
|
|
||||||
</b>
|
</b>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
To confirm, please type the name of the user
|
{t('userMessageConfirm')}
|
||||||
below.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
buttonText="Confirm Delete User"
|
buttonText={t('userDeleteConfirm')}
|
||||||
onConfirm={async () => deleteUser(selected!.id)}
|
onConfirm={async () => deleteUser(selected!.id)}
|
||||||
string={
|
string={
|
||||||
selected.email || selected.name || selected.username
|
selected.email || selected.name || selected.username
|
||||||
}
|
}
|
||||||
title="Delete User from Server"
|
title={t('userDeleteServer')}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { AdminListUsersResponse } from "@server/routers/user/adminListUsers";
|
||||||
import UsersTable, { GlobalUserRow } from "./AdminUsersTable";
|
import UsersTable, { GlobalUserRow } from "./AdminUsersTable";
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "@app/components/ui/alert";
|
||||||
import { InfoIcon } from "lucide-react";
|
import { InfoIcon } from "lucide-react";
|
||||||
|
import { getTranslations } from 'next-intl/server';
|
||||||
|
|
||||||
type PageProps = {
|
type PageProps = {
|
||||||
params: Promise<{ orgId: string }>;
|
params: Promise<{ orgId: string }>;
|
||||||
|
@ -39,17 +40,19 @@ export default async function UsersPage(props: PageProps) {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const t = await getTranslations();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SettingsSectionTitle
|
<SettingsSectionTitle
|
||||||
title="Manage All Users"
|
title={t('userTitle')}
|
||||||
description="View and manage all users in the system"
|
description={t('userDescription')}
|
||||||
/>
|
/>
|
||||||
<Alert variant="neutral" className="mb-6">
|
<Alert variant="neutral" className="mb-6">
|
||||||
<InfoIcon className="h-4 w-4" />
|
<InfoIcon className="h-4 w-4" />
|
||||||
<AlertTitle className="font-semibold">About User Management</AlertTitle>
|
<AlertTitle className="font-semibold">{t('userAbount')}</AlertTitle>
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
This table displays all root user objects in the system. Each user may belong to multiple organizations. Removing a user from an organization does not delete their root user object - they will remain in the system. To completely remove a user from the system, you must delete their root user object using the delete action in this table.
|
{t('userAbountDescription')}
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
<UsersTable users={userRows} />
|
<UsersTable users={userRows} />
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue