2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-28 11:36:44 +00:00

[PUI] Admin tables (#7835)

* Check user permission for tables

* Update permissions for user table

* Fix permission checks for group table

* Permission check for group detail

* Add divider

* Fix permission for template tables
This commit is contained in:
Oliver 2024-08-08 12:16:36 +10:00 committed by GitHub
parent 09bc06108c
commit dce6cf6b01
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 99 additions and 38 deletions

View File

@ -1,10 +1,12 @@
import { ApiEndpoints } from '../../../../enums/ApiEndpoints'; import { ApiEndpoints } from '../../../../enums/ApiEndpoints';
import { ModelType } from '../../../../enums/ModelType';
import { TemplateTable } from '../../../../tables/settings/TemplateTable'; import { TemplateTable } from '../../../../tables/settings/TemplateTable';
export default function LabelTemplatePanel() { export default function LabelTemplatePanel() {
return ( return (
<TemplateTable <TemplateTable
templateProps={{ templateProps={{
modelType: ModelType.labeltemplate,
templateEndpoint: ApiEndpoints.label_list, templateEndpoint: ApiEndpoints.label_list,
printingEndpoint: ApiEndpoints.label_print, printingEndpoint: ApiEndpoints.label_print,
additionalFormFields: { additionalFormFields: {

View File

@ -1,10 +1,12 @@
import { ApiEndpoints } from '../../../../enums/ApiEndpoints'; import { ApiEndpoints } from '../../../../enums/ApiEndpoints';
import { ModelType } from '../../../../enums/ModelType';
import { TemplateTable } from '../../../../tables/settings/TemplateTable'; import { TemplateTable } from '../../../../tables/settings/TemplateTable';
export default function ReportTemplateTable() { export default function ReportTemplateTable() {
return ( return (
<TemplateTable <TemplateTable
templateProps={{ templateProps={{
modelType: ModelType.reporttemplate,
templateEndpoint: ApiEndpoints.report_list, templateEndpoint: ApiEndpoints.report_list,
printingEndpoint: ApiEndpoints.report_print, printingEndpoint: ApiEndpoints.report_print,
additionalFormFields: { additionalFormFields: {

View File

@ -14,6 +14,8 @@ export default function UserManagementPanel() {
</Title> </Title>
<UserTable /> <UserTable />
<Divider />
<Title order={5}> <Title order={5}>
<Trans>Groups</Trans> <Trans>Groups</Trans>
</Title> </Title>

View File

@ -25,6 +25,7 @@ import {
import { useInstance } from '../../hooks/UseInstance'; import { useInstance } from '../../hooks/UseInstance';
import { useTable } from '../../hooks/UseTable'; import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState'; import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column'; import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable'; import { InvenTreeTable } from '../InvenTreeTable';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
@ -127,10 +128,15 @@ export function GroupDrawer({
export function GroupTable() { export function GroupTable() {
const table = useTable('groups'); const table = useTable('groups');
const navigate = useNavigate(); const navigate = useNavigate();
const user = useUserState();
const openDetailDrawer = useCallback( const openDetailDrawer = useCallback(
(pk: number) => navigate(`group-${pk}/`), (pk: number) => {
[] if (user.hasChangePermission(ModelType.group)) {
navigate(`group-${pk}/`);
}
},
[user]
); );
const columns: TableColumn<GroupDetailI>[] = useMemo(() => { const columns: TableColumn<GroupDetailI>[] = useMemo(() => {
@ -138,24 +144,30 @@ export function GroupTable() {
{ {
accessor: 'name', accessor: 'name',
sortable: true, sortable: true,
title: t`Name` title: t`Name`,
switchable: false
} }
]; ];
}, []); }, []);
const rowActions = useCallback((record: GroupDetailI): RowAction[] => { const rowActions = useCallback(
return [ (record: GroupDetailI): RowAction[] => {
RowEditAction({ return [
onClick: () => openDetailDrawer(record.pk) RowEditAction({
}), onClick: () => openDetailDrawer(record.pk),
RowDeleteAction({ hidden: !user.hasChangePermission(ModelType.group)
onClick: () => { }),
setSelectedGroup(record.pk); RowDeleteAction({
deleteGroup.open(); hidden: !user.hasDeletePermission(ModelType.group),
} onClick: () => {
}) setSelectedGroup(record.pk);
]; deleteGroup.open();
}, []); }
})
];
},
[user]
);
const [selectedGroup, setSelectedGroup] = useState<number>(-1); const [selectedGroup, setSelectedGroup] = useState<number>(-1);
@ -183,11 +195,12 @@ export function GroupTable() {
key={'add-group'} key={'add-group'}
onClick={() => newGroup.open()} onClick={() => newGroup.open()}
tooltip={t`Add group`} tooltip={t`Add group`}
hidden={!user.hasAddPermission(ModelType.group)}
/> />
); );
return actions; return actions;
}, []); }, [user]);
return ( return (
<> <>

View File

@ -48,6 +48,7 @@ export type TemplateI = {
}; };
export interface TemplateProps { export interface TemplateProps {
modelType: ModelType;
templateEndpoint: ApiEndpoints; templateEndpoint: ApiEndpoints;
printingEndpoint: ApiEndpoints; printingEndpoint: ApiEndpoints;
additionalFormFields?: ApiFormFieldSet; additionalFormFields?: ApiFormFieldSet;
@ -175,18 +176,22 @@ export function TemplateTable({
title: t`Modify`, title: t`Modify`,
tooltip: t`Modify template file`, tooltip: t`Modify template file`,
icon: <IconFileCode />, icon: <IconFileCode />,
onClick: () => openDetailDrawer(record.pk) onClick: () => openDetailDrawer(record.pk),
hidden: !user.hasChangePermission(templateProps.modelType)
}, },
RowEditAction({ RowEditAction({
hidden: !user.hasChangePermission(templateProps.modelType),
onClick: () => { onClick: () => {
setSelectedTemplate(record.pk); setSelectedTemplate(record.pk);
editTemplate.open(); editTemplate.open();
} }
}), }),
RowDuplicateAction({ RowDuplicateAction({
hidden: true
// TODO: Duplicate selected template // TODO: Duplicate selected template
}), }),
RowDeleteAction({ RowDeleteAction({
hidden: !user.hasDeletePermission(templateProps.modelType),
onClick: () => { onClick: () => {
setSelectedTemplate(record.pk); setSelectedTemplate(record.pk);
deleteTemplate.open(); deleteTemplate.open();
@ -252,9 +257,10 @@ export function TemplateTable({
key="add-template" key="add-template"
onClick={() => newTemplate.open()} onClick={() => newTemplate.open()}
tooltip={t`Add template`} tooltip={t`Add template`}
hidden={!user.hasAddPermission(templateProps.modelType)}
/> />
]; ];
}, []); }, [user]);
const modelTypeFilters = useFilters({ const modelTypeFilters = useFilters({
url: apiUrl(templateEndpoint), url: apiUrl(templateEndpoint),

View File

@ -19,6 +19,8 @@ import {
DetailDrawerLink DetailDrawerLink
} from '../../components/nav/DetailDrawer'; } from '../../components/nav/DetailDrawer';
import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserPermissions } from '../../enums/Roles';
import { import {
useCreateApiFormModal, useCreateApiFormModal,
useDeleteApiFormModal useDeleteApiFormModal
@ -29,6 +31,7 @@ import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState'; import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column'; import { TableColumn } from '../Column';
import { BooleanColumn } from '../ColumnRenderers'; import { BooleanColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable'; import { InvenTreeTable } from '../InvenTreeTable';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
import { GroupDetailI } from './GroupTable'; import { GroupDetailI } from './GroupTable';
@ -163,18 +166,19 @@ export function UserDrawer({
export function UserTable() { export function UserTable() {
const table = useTable('users'); const table = useTable('users');
const navigate = useNavigate(); const navigate = useNavigate();
const user = useUserState();
const openDetailDrawer = useCallback( const openDetailDrawer = useCallback(
(pk: number) => navigate(`user-${pk}/`), (pk: number) => {
[] if (user.hasChangePermission(ModelType.user)) {
navigate(`user-${pk}/`);
}
},
[user]
); );
const columns: TableColumn[] = useMemo(() => { const columns: TableColumn[] = useMemo(() => {
return [ return [
{
accessor: 'email',
sortable: true
},
{ {
accessor: 'username', accessor: 'username',
sortable: true, sortable: true,
@ -188,8 +192,13 @@ export function UserTable() {
accessor: 'last_name', accessor: 'last_name',
sortable: true sortable: true
}, },
{
accessor: 'email',
sortable: true
},
{ {
accessor: 'groups', accessor: 'groups',
title: t`Groups`,
sortable: true, sortable: true,
switchable: true, switchable: true,
render: (record: any) => { render: (record: any) => {
@ -211,19 +220,24 @@ export function UserTable() {
// Row Actions // Row Actions
const [selectedUser, setSelectedUser] = useState<number>(-1); const [selectedUser, setSelectedUser] = useState<number>(-1);
const rowActions = useCallback((record: UserDetailI): RowAction[] => { const rowActions = useCallback(
return [ (record: UserDetailI): RowAction[] => {
RowEditAction({ return [
onClick: () => openDetailDrawer(record.pk) RowEditAction({
}), onClick: () => openDetailDrawer(record.pk),
RowDeleteAction({ hidden: !user.hasChangePermission(ModelType.user)
onClick: () => { }),
setSelectedUser(record.pk); RowDeleteAction({
deleteUser.open(); hidden: !user.hasDeletePermission(ModelType.user),
} onClick: () => {
}) setSelectedUser(record.pk);
]; deleteUser.open();
}, []); }
})
];
},
[user]
);
const deleteUser = useDeleteApiFormModal({ const deleteUser = useDeleteApiFormModal({
url: ApiEndpoints.user_list, url: ApiEndpoints.user_list,
@ -256,10 +270,31 @@ export function UserTable() {
key="add-user" key="add-user"
onClick={newUser.open} onClick={newUser.open}
tooltip={t`Add user`} tooltip={t`Add user`}
hidden={!user.hasAddPermission(ModelType.user)}
/> />
); );
return actions; return actions;
}, [user]);
const tableFilters: TableFilter[] = useMemo(() => {
return [
{
name: 'is_active',
label: t`Active`,
description: t`Show active users`
},
{
name: 'is_staff',
label: t`Staff`,
description: t`Show staff users`
},
{
name: 'is_superuser',
label: t`Superuser`,
description: t`Show superusers`
}
];
}, []); }, []);
return ( return (
@ -285,6 +320,7 @@ export function UserTable() {
props={{ props={{
rowActions: rowActions, rowActions: rowActions,
tableActions: tableActions, tableActions: tableActions,
tableFilters: tableFilters,
onRowClick: (record) => openDetailDrawer(record.pk) onRowClick: (record) => openDetailDrawer(record.pk)
}} }}
/> />