mirror of
https://github.com/portainer/portainer.git
synced 2025-08-02 20:35:25 +02:00
refactor(users): migrate users table to react [EE-4708] (#10759)
This commit is contained in:
parent
86f1b8df6e
commit
a439695248
19 changed files with 159 additions and 192 deletions
|
@ -26,7 +26,7 @@ export function WidgetTitle({
|
|||
<div className="widget-icon">
|
||||
<Icon icon={icon} className="space-right" />
|
||||
</div>
|
||||
<span>{title}</span>
|
||||
<h2 className="text-base m-0">{title}</h2>
|
||||
</span>
|
||||
<span className={clsx('pull-right', className)}>{children}</span>
|
||||
</div>
|
||||
|
|
|
@ -20,7 +20,7 @@ export function TableRow<D extends DefaultType = DefaultType>({
|
|||
onClick={onClick}
|
||||
>
|
||||
{cells.map((cell) => (
|
||||
<td key={cell.id}>
|
||||
<td key={cell.id} className={cell.column.columnDef.meta?.className}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</td>
|
||||
))}
|
||||
|
|
|
@ -72,11 +72,11 @@ export interface OAuthSettings {
|
|||
KubeSecretKey: string;
|
||||
}
|
||||
|
||||
enum AuthenticationMethod {
|
||||
export enum AuthenticationMethod {
|
||||
/**
|
||||
* Internal represents the internal authentication method (authentication against Portainer API)
|
||||
*/
|
||||
Internal,
|
||||
Internal = 1,
|
||||
/**
|
||||
* LDAP represents the LDAP authentication method (authentication against a LDAP server)
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import { User as UserIcon } from 'lucide-react';
|
||||
|
||||
import { Datatable } from '@@/datatables';
|
||||
import { useTableState } from '@@/datatables/useTableState';
|
||||
import { createPersistedStore } from '@@/datatables/types';
|
||||
import { DeleteButton } from '@@/buttons/DeleteButton';
|
||||
|
||||
import { columns } from './columns';
|
||||
import { DecoratedUser } from './types';
|
||||
|
||||
const store = createPersistedStore('users');
|
||||
|
||||
export function UsersDatatable({
|
||||
dataset,
|
||||
onRemove,
|
||||
}: {
|
||||
dataset?: Array<DecoratedUser>;
|
||||
onRemove: (selectedItems: Array<DecoratedUser>) => void;
|
||||
}) {
|
||||
const tableState = useTableState(store, 'users');
|
||||
|
||||
return (
|
||||
<Datatable
|
||||
columns={columns}
|
||||
dataset={dataset || []}
|
||||
isLoading={!dataset}
|
||||
title="Users"
|
||||
titleIcon={UserIcon}
|
||||
settingsManager={tableState}
|
||||
isRowSelectable={(row) => row.original.Id !== 1}
|
||||
renderTableActions={(selectedItems) => (
|
||||
<DeleteButton
|
||||
disabled={selectedItems.length === 0}
|
||||
confirmMessage="Do you want to remove the selected users? They will not be able to login into Portainer anymore."
|
||||
onConfirmed={() => onRemove(selectedItems)}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
import { helper } from './helper';
|
||||
|
||||
export const authentication = helper.accessor('authMethod', {
|
||||
header: 'Authentication',
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
import { createColumnHelper } from '@tanstack/react-table';
|
||||
|
||||
import { DecoratedUser } from '../types';
|
||||
|
||||
export const helper = createColumnHelper<DecoratedUser>();
|
|
@ -0,0 +1,5 @@
|
|||
import { authentication } from './authentication';
|
||||
import { name } from './name';
|
||||
import { role } from './role';
|
||||
|
||||
export const columns = [name, role, authentication];
|
|
@ -0,0 +1,32 @@
|
|||
import { CellContext } from '@tanstack/react-table';
|
||||
|
||||
import { useCurrentUser } from '@/react/hooks/useUser';
|
||||
|
||||
import { Link } from '@@/Link';
|
||||
|
||||
import { DecoratedUser } from '../types';
|
||||
|
||||
import { helper } from './helper';
|
||||
|
||||
export const name = helper.accessor('Username', {
|
||||
header: 'Name',
|
||||
cell: Cell,
|
||||
});
|
||||
|
||||
function Cell({
|
||||
getValue,
|
||||
row: { original: item },
|
||||
}: CellContext<DecoratedUser, 'string'>) {
|
||||
const { isPureAdmin } = useCurrentUser();
|
||||
const name = getValue();
|
||||
|
||||
if (!isPureAdmin) {
|
||||
return <>{name}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Link to=".user" params={{ id: item.Id }}>
|
||||
{name}
|
||||
</Link>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import { User, UserPlus } from 'lucide-react';
|
||||
|
||||
import { isEdgeAdmin } from '@/portainer/users/user.helpers';
|
||||
import { RoleNames } from '@/portainer/users/types';
|
||||
|
||||
import { Icon } from '@@/Icon';
|
||||
|
||||
import { helper } from './helper';
|
||||
|
||||
export const role = helper.accessor(
|
||||
(item) =>
|
||||
`${RoleNames[item.Role]} ${
|
||||
item.isTeamLeader ? ' - team leader' : ''
|
||||
}`.trim(),
|
||||
{
|
||||
header: 'Role',
|
||||
cell: ({ getValue, row: { original: item } }) => {
|
||||
const icon =
|
||||
isEdgeAdmin({ Role: item.Role }) || item.isTeamLeader ? User : UserPlus;
|
||||
|
||||
return (
|
||||
<span className="vertical-center">
|
||||
<Icon icon={icon} />
|
||||
{getValue() || '-'}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
|
@ -0,0 +1,6 @@
|
|||
import { type User } from '@/portainer/users/types';
|
||||
|
||||
export type DecoratedUser = User & {
|
||||
isTeamLeader?: boolean;
|
||||
authMethod: string;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue