User.tsx 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. import { useContext, useEffect, useState } from 'react';
  2. import { useTranslation } from 'react-i18next';
  3. import { UserService } from '@/http';
  4. import AttuGrid from '@/components/grid/Grid';
  5. import { ColDefinitionsType, ToolBarConfig } from '@/components/grid/Types';
  6. import {
  7. CreateUserParams,
  8. DeleteUserParams,
  9. UpdateUserRoleParams,
  10. } from './Types';
  11. import DeleteTemplate from '@/components/customDialog/DeleteDialogTemplate';
  12. import Wrapper from '@/components/layout/Wrapper';
  13. import { rootContext } from '@/context';
  14. import { useNavigationHook, usePaginationHook } from '@/hooks';
  15. import CreateUser from './dialogs/CreateUserDialog';
  16. import UpdateUserRole from './dialogs/UpdateUserRole';
  17. import UpdateUser from './dialogs/UpdateUserPassDialog';
  18. import { ROUTE_PATHS } from '@/config/routes';
  19. import type { UserWithRoles } from '@server/types';
  20. import { getLabelDisplayedRows } from '@/pages/search/Utils';
  21. import { Typography } from '@mui/material';
  22. const Users = () => {
  23. useNavigationHook(ROUTE_PATHS.USERS);
  24. // ui states
  25. const [users, setUsers] = useState<UserWithRoles[]>([]);
  26. const [selectedUser, setSelectedUser] = useState<UserWithRoles[]>([]);
  27. const [loading, setLoading] = useState(true);
  28. const [hasPermission, setHasPermission] = useState(true);
  29. // context
  30. const { setDialog, handleCloseDialog, openSnackBar } =
  31. useContext(rootContext);
  32. // i18n
  33. const { t: successTrans } = useTranslation('success');
  34. const { t: userTrans } = useTranslation('user');
  35. const { t: btnTrans } = useTranslation('btn');
  36. const { t: dialogTrans } = useTranslation('dialog');
  37. const { t: commonTrans } = useTranslation();
  38. const fetchUsers = async () => {
  39. setLoading(true);
  40. try {
  41. const res = await UserService.getUsers();
  42. setUsers(res);
  43. } catch (error) {
  44. setHasPermission(false);
  45. } finally {
  46. setLoading(false);
  47. }
  48. };
  49. const {
  50. pageSize,
  51. handlePageSize,
  52. currentPage,
  53. handleCurrentPage,
  54. total,
  55. data: result,
  56. order,
  57. orderBy,
  58. handleGridSort,
  59. } = usePaginationHook(users || []);
  60. const handleCreate = async (data: CreateUserParams) => {
  61. const s: any = await UserService.createUser(data);
  62. // assign user role if
  63. await UserService.updateUserRole({
  64. username: data.username,
  65. roles: data.roles,
  66. });
  67. fetchUsers();
  68. openSnackBar(successTrans('create', { name: userTrans('user') }));
  69. handleCloseDialog();
  70. };
  71. const onUpdate = async (data: UpdateUserRoleParams) => {
  72. fetchUsers();
  73. openSnackBar(
  74. successTrans('update', { name: userTrans('updateRoleSuccess') })
  75. );
  76. handleCloseDialog();
  77. };
  78. const onUpdateUserPass = async (res: any) => {
  79. openSnackBar(successTrans('passwordChanged'));
  80. fetchUsers();
  81. handleCloseDialog();
  82. };
  83. const handleDelete = async () => {
  84. for (const user of selectedUser) {
  85. const param: DeleteUserParams = {
  86. username: user.username,
  87. };
  88. await UserService.deleteUser(param);
  89. }
  90. openSnackBar(successTrans('delete', { name: userTrans('user') }));
  91. fetchUsers();
  92. handleCloseDialog();
  93. };
  94. const toolbarConfigs: ToolBarConfig[] = [
  95. {
  96. label: userTrans('user'),
  97. onClick: async () => {
  98. const roles = await UserService.getRoles();
  99. setDialog({
  100. open: true,
  101. type: 'custom',
  102. params: {
  103. component: (
  104. <CreateUser
  105. handleCreate={handleCreate}
  106. handleClose={handleCloseDialog}
  107. roleOptions={roles.map(r => {
  108. return { label: r.roleName, value: r.roleName };
  109. })}
  110. />
  111. ),
  112. },
  113. });
  114. },
  115. icon: 'add',
  116. },
  117. {
  118. type: 'button',
  119. btnVariant: 'text',
  120. btnColor: 'secondary',
  121. label: userTrans('editPassword'),
  122. onClick: async () => {
  123. setDialog({
  124. open: true,
  125. type: 'custom',
  126. params: {
  127. component: (
  128. <UpdateUser
  129. username={selectedUser[0]!.username}
  130. onUpdate={onUpdateUserPass}
  131. handleClose={handleCloseDialog}
  132. />
  133. ),
  134. },
  135. });
  136. },
  137. icon: 'edit',
  138. disabled: () => selectedUser.length === 0 || selectedUser.length > 1,
  139. disabledTooltip: userTrans('editPassDisabledTip'),
  140. },
  141. {
  142. type: 'button',
  143. btnVariant: 'text',
  144. btnColor: 'secondary',
  145. label: userTrans('editRole'),
  146. onClick: async () => {
  147. setDialog({
  148. open: true,
  149. type: 'custom',
  150. params: {
  151. component: (
  152. <UpdateUserRole
  153. username={selectedUser[0]!.username}
  154. onUpdate={onUpdate}
  155. handleClose={handleCloseDialog}
  156. roles={
  157. users.filter(u => u.username === selectedUser[0].username)[0]
  158. .roles
  159. }
  160. />
  161. ),
  162. },
  163. });
  164. },
  165. icon: 'edit',
  166. disabled: () =>
  167. selectedUser.length === 0 ||
  168. selectedUser.length > 1 ||
  169. selectedUser.findIndex(v => v.username === 'root') > -1,
  170. disabledTooltip: userTrans('deleteEditRoleTip'),
  171. },
  172. {
  173. type: 'button',
  174. btnVariant: 'text',
  175. btnColor: 'secondary',
  176. onClick: () => {
  177. setDialog({
  178. open: true,
  179. type: 'custom',
  180. params: {
  181. component: (
  182. <DeleteTemplate
  183. label={btnTrans('drop')}
  184. title={dialogTrans('deleteTitle', { type: userTrans('user') })}
  185. text={userTrans('deleteWarning')}
  186. handleDelete={handleDelete}
  187. />
  188. ),
  189. },
  190. });
  191. },
  192. label: btnTrans('drop'),
  193. disabled: () =>
  194. selectedUser.length === 0 ||
  195. selectedUser.findIndex(v => v.username === 'root') > -1,
  196. disabledTooltip: userTrans('deleteTip'),
  197. icon: 'cross',
  198. },
  199. ];
  200. const colDefinitions: ColDefinitionsType[] = [
  201. {
  202. id: 'username',
  203. align: 'left',
  204. sortType: 'string',
  205. disablePadding: false,
  206. label: userTrans('user'),
  207. },
  208. {
  209. id: 'roles',
  210. align: 'left',
  211. notSort: true,
  212. disablePadding: true,
  213. label: userTrans('role'),
  214. formatter(rowData, cellData) {
  215. return (
  216. <Typography variant="body1">
  217. {rowData.username === 'root' ? 'admin' : cellData.join(', ')}
  218. </Typography>
  219. );
  220. },
  221. getStyle: () => {
  222. return { width: '80%', maxWidth: '80%' };
  223. },
  224. },
  225. ];
  226. const handleSelectChange = (value: UserWithRoles[]) => {
  227. setSelectedUser(value);
  228. };
  229. useEffect(() => {
  230. fetchUsers();
  231. }, []);
  232. const handlePageChange = (e: any, page: number) => {
  233. handleCurrentPage(page);
  234. };
  235. return (
  236. <Wrapper hasPermission={hasPermission}>
  237. <AttuGrid
  238. toolbarConfigs={toolbarConfigs}
  239. colDefinitions={colDefinitions}
  240. rows={result}
  241. rowCount={total}
  242. primaryKey="username"
  243. showPagination={true}
  244. selected={selectedUser}
  245. tableHeaderHeight={46}
  246. rowHeight={39}
  247. tableCellMaxWidth="100%"
  248. setSelected={handleSelectChange}
  249. page={currentPage}
  250. onPageChange={handlePageChange}
  251. rowsPerPage={pageSize}
  252. setRowsPerPage={handlePageSize}
  253. isLoading={loading}
  254. order={order}
  255. orderBy={orderBy}
  256. handleSort={handleGridSort}
  257. labelDisplayedRows={getLabelDisplayedRows(commonTrans('grid.users'))}
  258. />
  259. </Wrapper>
  260. );
  261. };
  262. export default Users;