mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 13:15:43 +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:
		| @@ -1,10 +1,12 @@ | ||||
| import { ApiEndpoints } from '../../../../enums/ApiEndpoints'; | ||||
| import { ModelType } from '../../../../enums/ModelType'; | ||||
| import { TemplateTable } from '../../../../tables/settings/TemplateTable'; | ||||
|  | ||||
| export default function LabelTemplatePanel() { | ||||
|   return ( | ||||
|     <TemplateTable | ||||
|       templateProps={{ | ||||
|         modelType: ModelType.labeltemplate, | ||||
|         templateEndpoint: ApiEndpoints.label_list, | ||||
|         printingEndpoint: ApiEndpoints.label_print, | ||||
|         additionalFormFields: { | ||||
|   | ||||
| @@ -1,10 +1,12 @@ | ||||
| import { ApiEndpoints } from '../../../../enums/ApiEndpoints'; | ||||
| import { ModelType } from '../../../../enums/ModelType'; | ||||
| import { TemplateTable } from '../../../../tables/settings/TemplateTable'; | ||||
|  | ||||
| export default function ReportTemplateTable() { | ||||
|   return ( | ||||
|     <TemplateTable | ||||
|       templateProps={{ | ||||
|         modelType: ModelType.reporttemplate, | ||||
|         templateEndpoint: ApiEndpoints.report_list, | ||||
|         printingEndpoint: ApiEndpoints.report_print, | ||||
|         additionalFormFields: { | ||||
|   | ||||
| @@ -14,6 +14,8 @@ export default function UserManagementPanel() { | ||||
|       </Title> | ||||
|       <UserTable /> | ||||
|  | ||||
|       <Divider /> | ||||
|  | ||||
|       <Title order={5}> | ||||
|         <Trans>Groups</Trans> | ||||
|       </Title> | ||||
|   | ||||
| @@ -25,6 +25,7 @@ import { | ||||
| import { useInstance } from '../../hooks/UseInstance'; | ||||
| import { useTable } from '../../hooks/UseTable'; | ||||
| import { apiUrl } from '../../states/ApiState'; | ||||
| import { useUserState } from '../../states/UserState'; | ||||
| import { TableColumn } from '../Column'; | ||||
| import { InvenTreeTable } from '../InvenTreeTable'; | ||||
| import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; | ||||
| @@ -127,10 +128,15 @@ export function GroupDrawer({ | ||||
| export function GroupTable() { | ||||
|   const table = useTable('groups'); | ||||
|   const navigate = useNavigate(); | ||||
|   const user = useUserState(); | ||||
|  | ||||
|   const openDetailDrawer = useCallback( | ||||
|     (pk: number) => navigate(`group-${pk}/`), | ||||
|     [] | ||||
|     (pk: number) => { | ||||
|       if (user.hasChangePermission(ModelType.group)) { | ||||
|         navigate(`group-${pk}/`); | ||||
|       } | ||||
|     }, | ||||
|     [user] | ||||
|   ); | ||||
|  | ||||
|   const columns: TableColumn<GroupDetailI>[] = useMemo(() => { | ||||
| @@ -138,24 +144,30 @@ export function GroupTable() { | ||||
|       { | ||||
|         accessor: 'name', | ||||
|         sortable: true, | ||||
|         title: t`Name` | ||||
|         title: t`Name`, | ||||
|         switchable: false | ||||
|       } | ||||
|     ]; | ||||
|   }, []); | ||||
|  | ||||
|   const rowActions = useCallback((record: GroupDetailI): RowAction[] => { | ||||
|     return [ | ||||
|       RowEditAction({ | ||||
|         onClick: () => openDetailDrawer(record.pk) | ||||
|       }), | ||||
|       RowDeleteAction({ | ||||
|         onClick: () => { | ||||
|           setSelectedGroup(record.pk); | ||||
|           deleteGroup.open(); | ||||
|         } | ||||
|       }) | ||||
|     ]; | ||||
|   }, []); | ||||
|   const rowActions = useCallback( | ||||
|     (record: GroupDetailI): RowAction[] => { | ||||
|       return [ | ||||
|         RowEditAction({ | ||||
|           onClick: () => openDetailDrawer(record.pk), | ||||
|           hidden: !user.hasChangePermission(ModelType.group) | ||||
|         }), | ||||
|         RowDeleteAction({ | ||||
|           hidden: !user.hasDeletePermission(ModelType.group), | ||||
|           onClick: () => { | ||||
|             setSelectedGroup(record.pk); | ||||
|             deleteGroup.open(); | ||||
|           } | ||||
|         }) | ||||
|       ]; | ||||
|     }, | ||||
|     [user] | ||||
|   ); | ||||
|  | ||||
|   const [selectedGroup, setSelectedGroup] = useState<number>(-1); | ||||
|  | ||||
| @@ -183,11 +195,12 @@ export function GroupTable() { | ||||
|         key={'add-group'} | ||||
|         onClick={() => newGroup.open()} | ||||
|         tooltip={t`Add group`} | ||||
|         hidden={!user.hasAddPermission(ModelType.group)} | ||||
|       /> | ||||
|     ); | ||||
|  | ||||
|     return actions; | ||||
|   }, []); | ||||
|   }, [user]); | ||||
|  | ||||
|   return ( | ||||
|     <> | ||||
|   | ||||
| @@ -48,6 +48,7 @@ export type TemplateI = { | ||||
| }; | ||||
|  | ||||
| export interface TemplateProps { | ||||
|   modelType: ModelType; | ||||
|   templateEndpoint: ApiEndpoints; | ||||
|   printingEndpoint: ApiEndpoints; | ||||
|   additionalFormFields?: ApiFormFieldSet; | ||||
| @@ -175,18 +176,22 @@ export function TemplateTable({ | ||||
|           title: t`Modify`, | ||||
|           tooltip: t`Modify template file`, | ||||
|           icon: <IconFileCode />, | ||||
|           onClick: () => openDetailDrawer(record.pk) | ||||
|           onClick: () => openDetailDrawer(record.pk), | ||||
|           hidden: !user.hasChangePermission(templateProps.modelType) | ||||
|         }, | ||||
|         RowEditAction({ | ||||
|           hidden: !user.hasChangePermission(templateProps.modelType), | ||||
|           onClick: () => { | ||||
|             setSelectedTemplate(record.pk); | ||||
|             editTemplate.open(); | ||||
|           } | ||||
|         }), | ||||
|         RowDuplicateAction({ | ||||
|           hidden: true | ||||
|           // TODO: Duplicate selected template | ||||
|         }), | ||||
|         RowDeleteAction({ | ||||
|           hidden: !user.hasDeletePermission(templateProps.modelType), | ||||
|           onClick: () => { | ||||
|             setSelectedTemplate(record.pk); | ||||
|             deleteTemplate.open(); | ||||
| @@ -252,9 +257,10 @@ export function TemplateTable({ | ||||
|         key="add-template" | ||||
|         onClick={() => newTemplate.open()} | ||||
|         tooltip={t`Add template`} | ||||
|         hidden={!user.hasAddPermission(templateProps.modelType)} | ||||
|       /> | ||||
|     ]; | ||||
|   }, []); | ||||
|   }, [user]); | ||||
|  | ||||
|   const modelTypeFilters = useFilters({ | ||||
|     url: apiUrl(templateEndpoint), | ||||
|   | ||||
| @@ -19,6 +19,8 @@ import { | ||||
|   DetailDrawerLink | ||||
| } from '../../components/nav/DetailDrawer'; | ||||
| import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||
| import { ModelType } from '../../enums/ModelType'; | ||||
| import { UserPermissions } from '../../enums/Roles'; | ||||
| import { | ||||
|   useCreateApiFormModal, | ||||
|   useDeleteApiFormModal | ||||
| @@ -29,6 +31,7 @@ import { apiUrl } from '../../states/ApiState'; | ||||
| import { useUserState } from '../../states/UserState'; | ||||
| import { TableColumn } from '../Column'; | ||||
| import { BooleanColumn } from '../ColumnRenderers'; | ||||
| import { TableFilter } from '../Filter'; | ||||
| import { InvenTreeTable } from '../InvenTreeTable'; | ||||
| import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; | ||||
| import { GroupDetailI } from './GroupTable'; | ||||
| @@ -163,18 +166,19 @@ export function UserDrawer({ | ||||
| export function UserTable() { | ||||
|   const table = useTable('users'); | ||||
|   const navigate = useNavigate(); | ||||
|   const user = useUserState(); | ||||
|  | ||||
|   const openDetailDrawer = useCallback( | ||||
|     (pk: number) => navigate(`user-${pk}/`), | ||||
|     [] | ||||
|     (pk: number) => { | ||||
|       if (user.hasChangePermission(ModelType.user)) { | ||||
|         navigate(`user-${pk}/`); | ||||
|       } | ||||
|     }, | ||||
|     [user] | ||||
|   ); | ||||
|  | ||||
|   const columns: TableColumn[] = useMemo(() => { | ||||
|     return [ | ||||
|       { | ||||
|         accessor: 'email', | ||||
|         sortable: true | ||||
|       }, | ||||
|       { | ||||
|         accessor: 'username', | ||||
|         sortable: true, | ||||
| @@ -188,8 +192,13 @@ export function UserTable() { | ||||
|         accessor: 'last_name', | ||||
|         sortable: true | ||||
|       }, | ||||
|       { | ||||
|         accessor: 'email', | ||||
|         sortable: true | ||||
|       }, | ||||
|       { | ||||
|         accessor: 'groups', | ||||
|         title: t`Groups`, | ||||
|         sortable: true, | ||||
|         switchable: true, | ||||
|         render: (record: any) => { | ||||
| @@ -211,19 +220,24 @@ export function UserTable() { | ||||
|   // Row Actions | ||||
|   const [selectedUser, setSelectedUser] = useState<number>(-1); | ||||
|  | ||||
|   const rowActions = useCallback((record: UserDetailI): RowAction[] => { | ||||
|     return [ | ||||
|       RowEditAction({ | ||||
|         onClick: () => openDetailDrawer(record.pk) | ||||
|       }), | ||||
|       RowDeleteAction({ | ||||
|         onClick: () => { | ||||
|           setSelectedUser(record.pk); | ||||
|           deleteUser.open(); | ||||
|         } | ||||
|       }) | ||||
|     ]; | ||||
|   }, []); | ||||
|   const rowActions = useCallback( | ||||
|     (record: UserDetailI): RowAction[] => { | ||||
|       return [ | ||||
|         RowEditAction({ | ||||
|           onClick: () => openDetailDrawer(record.pk), | ||||
|           hidden: !user.hasChangePermission(ModelType.user) | ||||
|         }), | ||||
|         RowDeleteAction({ | ||||
|           hidden: !user.hasDeletePermission(ModelType.user), | ||||
|           onClick: () => { | ||||
|             setSelectedUser(record.pk); | ||||
|             deleteUser.open(); | ||||
|           } | ||||
|         }) | ||||
|       ]; | ||||
|     }, | ||||
|     [user] | ||||
|   ); | ||||
|  | ||||
|   const deleteUser = useDeleteApiFormModal({ | ||||
|     url: ApiEndpoints.user_list, | ||||
| @@ -256,10 +270,31 @@ export function UserTable() { | ||||
|         key="add-user" | ||||
|         onClick={newUser.open} | ||||
|         tooltip={t`Add user`} | ||||
|         hidden={!user.hasAddPermission(ModelType.user)} | ||||
|       /> | ||||
|     ); | ||||
|  | ||||
|     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 ( | ||||
| @@ -285,6 +320,7 @@ export function UserTable() { | ||||
|         props={{ | ||||
|           rowActions: rowActions, | ||||
|           tableActions: tableActions, | ||||
|           tableFilters: tableFilters, | ||||
|           onRowClick: (record) => openDetailDrawer(record.pk) | ||||
|         }} | ||||
|       /> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user