@gadmin2n/schematics 0.0.64 → 0.0.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/dist/lib/application/files/gadmin2-game-angle-demo/.dockerignore +2 -2
  2. package/dist/lib/application/files/gadmin2-game-angle-demo/Dockerfile +40 -26
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/Jenkinsfile +30 -4
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/example.prisma +33 -0
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/system.prisma +170 -0
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Event.ts +70 -0
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Game.ts +6 -6
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/ITActivityDay.ts +70 -0
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Log.ts +2 -2
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Role.ts +2 -2
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/server/.env +20 -9
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/server/.env.local +1 -0
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/server/.eslintrc.js +1 -0
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/server/.prettierignore +1 -0
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/server/README.md +2 -18
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/server/gadmin-cli.json +1 -1
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/server/migrate-between-pg-schemas.js +1232 -0
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +65 -38
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/server/prisma/.generator.prisma +4 -3
  20. package/dist/lib/application/files/gadmin2-game-angle-demo/server/prisma.config.ts +16 -0
  21. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/games.ts +1 -71
  22. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/index.ts +17 -21
  23. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/permissions.ts +278 -0
  24. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/seedDataMngtPages.ts +258 -0
  25. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/users.ts +7 -0
  26. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/alias.config.ts +7 -0
  27. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/app.controller.ts +151 -11
  28. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/app.module.ts +29 -13
  29. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/app.service.ts +151 -12
  30. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/auth.guard.ts +87 -41
  31. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/http-cache.interceptor.ts +21 -0
  32. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/logger.ts +19 -0
  33. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/safe-log.util.ts +176 -0
  34. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/{yufuid.ts → taihu.ts} +49 -34
  35. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/tracing.ts +174 -0
  36. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/trim.pipe.ts +51 -0
  37. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/utils.ts +91 -0
  38. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/woaAuth.ts +25 -12
  39. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/main.ts +22 -12
  40. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.controller.spec.ts +20 -0
  41. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.controller.ts +190 -0
  42. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.module.ts +10 -0
  43. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.service.spec.ts +338 -0
  44. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.service.ts +83 -0
  45. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.controller.spec.ts +20 -0
  46. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.controller.ts +188 -0
  47. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.module.ts +10 -0
  48. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.service.spec.ts +18 -0
  49. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.service.ts +83 -0
  50. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.controller.spec.ts +20 -0
  51. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.controller.ts +250 -0
  52. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.module.ts +10 -0
  53. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.service.spec.ts +18 -0
  54. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.service.ts +1051 -0
  55. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.controller.spec.ts +20 -0
  56. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.controller.ts +196 -0
  57. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.module.ts +13 -0
  58. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.service.spec.ts +18 -0
  59. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.service.ts +219 -0
  60. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.controller.spec.ts +20 -0
  61. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.controller.ts +196 -0
  62. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.module.ts +10 -0
  63. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.service.spec.ts +18 -0
  64. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.service.ts +199 -0
  65. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.controller.spec.ts +20 -0
  66. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.controller.ts +210 -0
  67. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.module.ts +12 -0
  68. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.service.spec.ts +18 -0
  69. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.service.ts +849 -0
  70. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/roles-refresher.service.ts +133 -0
  71. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.controller.spec.ts +20 -0
  72. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.controller.ts +196 -0
  73. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.module.ts +10 -0
  74. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.service.spec.ts +18 -0
  75. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.service.ts +201 -0
  76. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.controller.spec.ts +20 -0
  77. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.controller.ts +196 -0
  78. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.module.ts +10 -0
  79. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.service.spec.ts +18 -0
  80. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.service.ts +216 -0
  81. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.controller.spec.ts +20 -0
  82. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.controller.ts +198 -0
  83. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.module.ts +10 -0
  84. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.service.spec.ts +18 -0
  85. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.service.ts +104 -0
  86. package/dist/lib/application/files/gadmin2-game-angle-demo/server/start-prod.sh +130 -0
  87. package/dist/lib/application/files/gadmin2-game-angle-demo/server/tsconfig.json +18 -3
  88. package/dist/lib/application/files/gadmin2-game-angle-demo/web/index.html +19 -0
  89. package/dist/lib/application/files/gadmin2-game-angle-demo/web/package.json +34 -42
  90. package/dist/lib/application/files/gadmin2-game-angle-demo/web/postcss.config.cjs +6 -0
  91. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/App.tsx +111 -185
  92. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/auditLogProvider.ts +5 -5
  93. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/authProvider.ts +2 -2
  94. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/SqlModal.tsx +419 -0
  95. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/contexts/business/index.tsx +1 -1
  96. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/contexts/color-mode/index.tsx +49 -51
  97. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/custom-avatar.tsx +38 -0
  98. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/index.ts +4 -0
  99. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/{header/index.tsx → header.tsx} +22 -31
  100. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/index.ts +3 -1
  101. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/layout.tsx +32 -0
  102. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/logo.tsx +19 -0
  103. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/sider.tsx +331 -166
  104. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/title.tsx +61 -0
  105. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/pagination-total.tsx +21 -0
  106. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/tags/index.ts +1 -0
  107. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/tags/role-tag.tsx +44 -0
  108. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/text.tsx +74 -0
  109. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/http.ts +28 -0
  110. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +258 -0
  111. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/constants/layout.ts +16 -0
  112. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/enums/audit-log.enum.ts +13 -0
  113. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/enums/index.ts +1 -0
  114. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/get-name-initials.ts +8 -0
  115. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/get-random-color.ts +27 -0
  116. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/http.ts +87 -0
  117. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/index.tsx +6 -1
  118. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/login.ts +22 -59
  119. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/utils.tsx +5 -0
  120. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx +211 -0
  121. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useFetchData.ts +33 -0
  122. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useRoles.ts +30 -0
  123. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useUserPageAccess.ts +339 -0
  124. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/i18n.ts +8 -4
  125. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/index.tsx +3 -11
  126. package/dist/lib/application/files/gadmin2-game-angle-demo/web/{public → src}/locales/en/common.json +1 -1
  127. package/dist/lib/application/files/gadmin2-game-angle-demo/web/{public → src}/locales/zh_CN/common.json +1 -1
  128. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/components/action-cell.css +3 -0
  129. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/components/action-cell.tsx +134 -0
  130. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/create.tsx +113 -0
  131. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/edit.tsx +122 -0
  132. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/index.ts +8 -0
  133. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/index.tsx +6 -0
  134. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/list.tsx +213 -0
  135. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/show.tsx +61 -0
  136. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/AssignRolesModal.tsx +168 -0
  137. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/CreatePageModal.tsx +42 -0
  138. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/EditPageModal.tsx +42 -0
  139. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/PageDetailDrawer.tsx +101 -0
  140. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/PageFormModal.tsx +731 -0
  141. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/hooks/usePageManagement.ts +36 -0
  142. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/index.ts +1 -0
  143. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/list.tsx +1215 -0
  144. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/queries.ts +17 -0
  145. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/types.ts +45 -0
  146. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/permissionReadme/index.tsx +1089 -0
  147. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/CreateModal.tsx +25 -0
  148. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/EditModal.tsx +28 -0
  149. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/ResourceDetailDrawer.tsx +160 -0
  150. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/modal.tsx +202 -0
  151. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/index.ts +2 -0
  152. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/list.tsx +212 -0
  153. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/queries.ts +10 -0
  154. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/types.ts +9 -0
  155. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/CreateModal.tsx +30 -0
  156. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/EditModal.tsx +47 -0
  157. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/RoleDetailDrawer.tsx +56 -0
  158. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/modal.tsx +302 -0
  159. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/hooks/useRolePage.ts +35 -0
  160. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/index.ts +1 -0
  161. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/list.tsx +431 -0
  162. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/queries.ts +8 -0
  163. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/types.ts +8 -0
  164. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/create-modal.tsx +17 -0
  165. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/edit-modal.tsx +19 -0
  166. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/form-modal.tsx +188 -0
  167. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/index.ts +5 -0
  168. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/role-tag.tsx +48 -0
  169. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/show-drawer.tsx +140 -0
  170. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/index.ts +1 -0
  171. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/list.tsx +372 -0
  172. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/queries.ts +14 -0
  173. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/antd.css +132 -0
  174. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/fc.css +58 -0
  175. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/index.css +128 -0
  176. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/show-drawer.module.css +18 -0
  177. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/show-page.module.css +21 -0
  178. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/types/audit-log.ts +1 -0
  179. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/types/index.ts +3 -0
  180. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/types/role.ts +7 -0
  181. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/types/user.ts +1 -0
  182. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/vite-env.d.ts +1 -0
  183. package/dist/lib/application/files/gadmin2-game-angle-demo/web/tsconfig.json +5 -4
  184. package/dist/lib/application/files/gadmin2-game-angle-demo/web/vite.config.ts +31 -0
  185. package/dist/lib/application/files/gadmin2-game-angle-demo/web/yarn.lock +8321 -0
  186. package/package.json +1 -1
  187. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/sample.prisma +0 -65
  188. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Source.ts +0 -76
  189. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Tasklog.ts +0 -76
  190. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/roles.ts +0 -4
  191. package/dist/lib/application/files/gadmin2-game-angle-demo/web/craco.config.js +0 -27
  192. package/dist/lib/application/files/gadmin2-game-angle-demo/web/public/index.html +0 -53
  193. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/styles.ts +0 -10
  194. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/utils.ts +0 -76
  195. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/react-app-env.d.ts +0 -1
  196. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/reportWebVitals.ts +0 -15
  197. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/antd.less +0 -79
  198. /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/VanillaJSONEditor/{index.js → index.jsx} +0 -0
@@ -0,0 +1,431 @@
1
+ import React, { useCallback, useMemo, useState } from "react";
2
+ import { useTable } from "@refinedev/antd";
3
+ import { useGetLocale, useGetIdentity } from "@refinedev/core";
4
+ import { Table, Button, Space, Tooltip, message } from "antd";
5
+
6
+ import { EditModal } from "./Components/EditModal";
7
+ import { CreateModal } from "./Components/CreateModal";
8
+ import type { RolePageTreeNode } from "./types";
9
+ import { useRolePage } from "./hooks/useRolePage";
10
+ import { EditOutlined, EyeOutlined, CodeOutlined } from "@ant-design/icons";
11
+ import { RoleDetailDrawer } from "./Components/RoleDetailDrawer";
12
+ import { SqlModal, generateRoleSql } from "../../components/SqlModal";
13
+ import { customRequest } from "@/helpers/http";
14
+
15
+ type RolePageInfo = {
16
+ id: number;
17
+ code: string;
18
+ name: string;
19
+ menuPath: string;
20
+ };
21
+
22
+ type RolePermissionSummary = {
23
+ pageIds: number[];
24
+ pageNames: string[];
25
+ pageInfos: RolePageInfo[];
26
+ actions: string[];
27
+ };
28
+
29
+ const PAGE_NAME_DISPLAY_LIMIT = 40;
30
+
31
+ const normalizeToNumber = (value: unknown): number | null => {
32
+ if (typeof value === "number" && !Number.isNaN(value)) {
33
+ return value;
34
+ }
35
+ if (typeof value === "string" && value.trim().length > 0) {
36
+ const parsedValue = Number(value);
37
+ return Number.isNaN(parsedValue) ? null : parsedValue;
38
+ }
39
+ return null;
40
+ };
41
+
42
+ const extractActionsFromRelation = (relation: any, pageRecord: any): string[] => {
43
+ const aggregatedActions = new Set<string>();
44
+ const relationActions = relation?.actions ?? relation?.actionList;
45
+
46
+ if (Array.isArray(relationActions)) {
47
+ relationActions.forEach((action: any) => {
48
+ if (typeof action === "string" && action) {
49
+ aggregatedActions.add(action);
50
+ } else if (typeof action === "object" && action?.name) {
51
+ aggregatedActions.add(action.name);
52
+ }
53
+ });
54
+ } else if (typeof relationActions === "string") {
55
+ relationActions
56
+ .split(",")
57
+ .map((action: string) => action.trim())
58
+ .filter(Boolean)
59
+ .forEach(action => aggregatedActions.add(action));
60
+ }
61
+
62
+ const pageResources =
63
+ relation?.pageResources ?? pageRecord?.pageResources ?? pageRecord?.resources ?? [];
64
+
65
+ if (Array.isArray(pageResources)) {
66
+ pageResources.forEach((resource: any) => {
67
+ const action = resource?.action ?? resource?.code ?? resource?.name ?? resource;
68
+ if (typeof action === "string" && action) {
69
+ aggregatedActions.add(action);
70
+ }
71
+ });
72
+ }
73
+
74
+ return Array.from(aggregatedActions);
75
+ };
76
+
77
+ export const RoleManagementListPage: React.FC = () => {
78
+ const getLocale = useGetLocale();
79
+ const currentLocale = getLocale();
80
+ const { data: identity } = useGetIdentity<any>();
81
+
82
+ const { tableProps } = useTable({
83
+ resource: "role",
84
+ pagination: {
85
+ pageSize: 20,
86
+ },
87
+ });
88
+
89
+ const { rolePagesData, refetchRolePages, rolePagesQuery, pageData, refetchPages, pageQuery } =
90
+ useRolePage();
91
+
92
+ const pageLookup = useMemo<Record<number, any>>(() => {
93
+ const pages: any[] = Array.isArray(pageData?.data) ? pageData.data : [];
94
+ const lookup: Record<number, any> = {};
95
+
96
+ pages.forEach((page: any) => {
97
+ const pageId = normalizeToNumber(page?.id ?? page?.pageId ?? page?.page_id);
98
+ if (pageId !== null) {
99
+ lookup[pageId] = page;
100
+ }
101
+ });
102
+
103
+ return lookup;
104
+ }, [pageData]);
105
+
106
+ const pageTreeData = useMemo<RolePageTreeNode[]>(() => {
107
+ const pages: any[] = Array.isArray(pageData?.data) ? pageData.data : [];
108
+ const isZh = currentLocale === "zh_CN" || currentLocale === "zh";
109
+
110
+ const getPageTitle = (page: any, pageId: number): string => {
111
+ if (isZh) {
112
+ return page?.zhName || page?.name || page?.code || `Page ${pageId}`;
113
+ }
114
+ return page?.enName || page?.name || page?.code || `Page ${pageId}`;
115
+ };
116
+
117
+ const nodeMap = new Map<number, { node: RolePageTreeNode; parentId: number | null; sortOrder: number | null }>();
118
+
119
+ pages.forEach((page: any) => {
120
+ const pageId = normalizeToNumber(page?.id ?? page?.pageId ?? page?.page_id);
121
+ if (pageId === null) {
122
+ return;
123
+ }
124
+
125
+ const parentId =
126
+ normalizeToNumber(page?.parentId ?? page?.parent_id ?? page?.parent?.id) ?? null;
127
+ const title = getPageTitle(page, pageId);
128
+ const sortOrder = normalizeToNumber(page?.sortOrder ?? page?.sort_order);
129
+
130
+ nodeMap.set(pageId, {
131
+ node: {
132
+ title,
133
+ value: String(pageId),
134
+ key: String(pageId),
135
+ children: [],
136
+ },
137
+ parentId,
138
+ sortOrder,
139
+ });
140
+ });
141
+
142
+ const roots: RolePageTreeNode[] = [];
143
+
144
+ nodeMap.forEach(({ node, parentId }) => {
145
+ if (parentId !== null && nodeMap.has(parentId)) {
146
+ nodeMap.get(parentId)?.node.children?.push(node);
147
+ } else {
148
+ roots.push(node);
149
+ }
150
+ });
151
+
152
+ // Build a map from node key to sortOrder for sorting
153
+ const sortOrderMap = new Map<string, number | null>();
154
+ nodeMap.forEach(({ sortOrder }, pageId) => {
155
+ sortOrderMap.set(String(pageId), sortOrder);
156
+ });
157
+
158
+ const sortNodes = (nodes: RolePageTreeNode[]) => {
159
+ nodes.sort((a, b) => {
160
+ const orderA = sortOrderMap.get(a.key) ?? Infinity;
161
+ const orderB = sortOrderMap.get(b.key) ?? Infinity;
162
+ return (orderA as number) - (orderB as number);
163
+ });
164
+ nodes.forEach(child => {
165
+ if (child.children && child.children.length) {
166
+ sortNodes(child.children);
167
+ }
168
+ });
169
+ };
170
+
171
+ const pruneEmptyChildren = (nodes: RolePageTreeNode[]): RolePageTreeNode[] =>
172
+ nodes.map(node => {
173
+ if (node.children && node.children.length) {
174
+ return {
175
+ ...node,
176
+ children: pruneEmptyChildren(node.children),
177
+ };
178
+ }
179
+ const { children, ...rest } = node;
180
+ return rest as RolePageTreeNode;
181
+ });
182
+
183
+ sortNodes(roots);
184
+ return pruneEmptyChildren(roots);
185
+ }, [pageData, currentLocale]);
186
+
187
+ const rolePermissionSummary = useMemo<Record<number, RolePermissionSummary>>(() => {
188
+ const relations: any[] = Array.isArray(rolePagesData?.data) ? rolePagesData.data : [];
189
+ const isZh = currentLocale === "zh_CN" || currentLocale === "zh";
190
+
191
+ const getLocalizedName = (pageRecord: any, fallback: string): string => {
192
+ if (isZh) {
193
+ return pageRecord?.zhName || pageRecord?.name || pageRecord?.code || fallback;
194
+ }
195
+ return pageRecord?.enName || pageRecord?.name || pageRecord?.code || fallback;
196
+ };
197
+
198
+ const buildMenuPath = (pageId: number): string => {
199
+ const parts: string[] = [];
200
+ let currentId: number | null = pageId;
201
+ const visited = new Set<number>();
202
+ while (currentId !== null && !visited.has(currentId)) {
203
+ visited.add(currentId);
204
+ const record: any = pageLookup[currentId];
205
+ if (!record) break;
206
+ parts.unshift(getLocalizedName(record, record?.name || `Page ${currentId}`));
207
+ currentId = normalizeToNumber(record?.parentId ?? record?.parent_id) ?? null;
208
+ }
209
+ return parts.join(" / ");
210
+ };
211
+
212
+ const summaryMap: Record<number, RolePermissionSummary> = {};
213
+
214
+ relations.forEach((relation: any) => {
215
+ const roleId = normalizeToNumber(relation?.roleId);
216
+ const pageId = normalizeToNumber(relation?.pageId);
217
+
218
+ if (roleId === null || pageId === null) {
219
+ return;
220
+ }
221
+
222
+ if (!summaryMap[roleId]) {
223
+ summaryMap[roleId] = {
224
+ pageIds: [],
225
+ pageNames: [],
226
+ pageInfos: [],
227
+ actions: [],
228
+ };
229
+ }
230
+
231
+ const summary = summaryMap[roleId];
232
+
233
+ if (!summary.pageIds.includes(pageId)) {
234
+ summary.pageIds.push(pageId);
235
+ }
236
+
237
+ const pageRecord = relation?.page ?? pageLookup[pageId];
238
+ const pageName = pageRecord?.name || pageRecord?.code || `Page ${pageId}`;
239
+
240
+ if (pageName && !summary.pageNames.includes(pageName)) {
241
+ summary.pageNames.push(pageName);
242
+ }
243
+
244
+ const localizedName = getLocalizedName(pageRecord, pageName);
245
+ if (!summary.pageInfos.some(p => p.id === pageId)) {
246
+ summary.pageInfos.push({
247
+ id: pageId,
248
+ code: pageRecord?.code ?? "",
249
+ name: localizedName,
250
+ menuPath: buildMenuPath(pageId),
251
+ });
252
+ }
253
+
254
+ extractActionsFromRelation(relation, pageRecord).forEach(action => {
255
+ if (action && !summary.actions.includes(action)) {
256
+ summary.actions.push(action);
257
+ }
258
+ });
259
+ });
260
+
261
+ // Build ancestor sort-order chain for hierarchical sorting
262
+ const getSortChain = (pageId: number): number[] => {
263
+ const chain: number[] = [];
264
+ let currentId: number | null = pageId;
265
+ const visited = new Set<number>();
266
+ while (currentId !== null && !visited.has(currentId)) {
267
+ visited.add(currentId);
268
+ const record: any = pageLookup[currentId];
269
+ if (!record) break;
270
+ chain.unshift(record?.sortOrder ?? record?.sort_order ?? Infinity);
271
+ currentId = normalizeToNumber(record?.parentId ?? record?.parent_id) ?? null;
272
+ }
273
+ return chain;
274
+ };
275
+
276
+ // Sort pageInfos by full ancestor sort-order chain
277
+ Object.values(summaryMap).forEach(summary => {
278
+ summary.pageInfos.sort((a, b) => {
279
+ const chainA = getSortChain(a.id);
280
+ const chainB = getSortChain(b.id);
281
+ const len = Math.max(chainA.length, chainB.length);
282
+ for (let i = 0; i < len; i++) {
283
+ const valA = chainA[i] ?? Infinity;
284
+ const valB = chainB[i] ?? Infinity;
285
+ if (valA !== valB) return valA - valB;
286
+ }
287
+ return chainA.length - chainB.length;
288
+ });
289
+ });
290
+
291
+ return summaryMap;
292
+ }, [rolePagesData, pageLookup, currentLocale]);
293
+
294
+ const [drawerRole, setDrawerRole] = useState<any>(null);
295
+
296
+ const [showModal, setShowModal] = useState<{
297
+ type: "show" | "edit" | "create" | null;
298
+ id: number | null;
299
+ }>({
300
+ type: null,
301
+ id: null,
302
+ });
303
+
304
+ const [sqlModal, setSqlModal] = useState<{
305
+ open: boolean;
306
+ title: string;
307
+ sql: string;
308
+ }>({ open: false, title: "", sql: "" });
309
+
310
+ const handleShowSql = useCallback(async (record: any) => {
311
+ const summary = rolePermissionSummary[record.id];
312
+ const rolePages = summary?.pageInfos?.map(p => ({ pageId: p.id, pageCode: p.code, pageName: p.name })) ?? [];
313
+
314
+ let roleResources: Array<{ resourceCode: string; resourceName: string; actions: string[] }> = [];
315
+ try {
316
+ const resp: any = await customRequest("roleResource/findMany", "post", {
317
+ where: { roleId: record.id },
318
+ include: { resource: true },
319
+ });
320
+ const items: any[] = Array.isArray(resp?.data) ? resp.data : [];
321
+ roleResources = items.map(item => ({
322
+ resourceCode: item.resource?.code ?? String(item.resourceId),
323
+ resourceName: item.resource?.name ?? String(item.resourceId),
324
+ actions: Array.isArray(item.actions) ? item.actions : [],
325
+ }));
326
+ } catch {
327
+ message.warning("Could not fetch role resource details; SQL will omit permissions.");
328
+ }
329
+
330
+ const sql = generateRoleSql(record, rolePages, roleResources, { authorId: identity?.userid, authorName: identity?.username });
331
+ setSqlModal({ open: true, title: `SQL — Role: ${record.name}`, sql });
332
+ }, [rolePermissionSummary]);
333
+
334
+ const refreshRoleRelatedData = useCallback(() => {
335
+ refetchRolePages(rolePagesQuery ?? {});
336
+ refetchPages(pageQuery ?? {});
337
+ }, [refetchRolePages, rolePagesQuery, refetchPages, pageQuery]);
338
+
339
+ const handleModalClose = useCallback(() => {
340
+ setShowModal({ type: null, id: null });
341
+ }, []);
342
+
343
+ const handleModalSuccess = useCallback(() => {
344
+ handleModalClose();
345
+ refreshRoleRelatedData();
346
+ }, [refreshRoleRelatedData, handleModalClose]);
347
+
348
+ return (
349
+ <div>
350
+ <Space style={{ marginBottom: 16 }}>
351
+ <Button
352
+ type="primary"
353
+ onClick={() =>
354
+ setShowModal({
355
+ type: "create",
356
+ id: null,
357
+ })
358
+ }
359
+ >
360
+ Create Role
361
+ </Button>
362
+ </Space>
363
+ <Table {...tableProps} rowKey="id">
364
+ <Table.Column dataIndex="name" title="Name" />
365
+ <Table.Column dataIndex="description" title="Description" />
366
+ <Table.Column dataIndex="creator" title="Creator" />
367
+ <Table.Column
368
+ title="Actions"
369
+ render={(_, record: any) => (
370
+ <Space>
371
+ <Tooltip title="View details">
372
+ <Button
373
+ type="default"
374
+ size="small"
375
+ icon={<EyeOutlined />}
376
+ onClick={() => setDrawerRole(record)}
377
+ />
378
+ </Tooltip>
379
+ <Tooltip title="Edit">
380
+ <Button
381
+ type="default"
382
+ size="small"
383
+ icon={<EditOutlined />}
384
+ onClick={() => setShowModal({ type: "edit", id: record.id })}
385
+ />
386
+ </Tooltip>
387
+ <Tooltip title="Generate SQL">
388
+ <Button
389
+ type="default"
390
+ size="small"
391
+ icon={<CodeOutlined />}
392
+ onClick={() => handleShowSql(record)}
393
+ />
394
+ </Tooltip>
395
+ </Space>
396
+ )}
397
+ />
398
+ </Table>
399
+ {drawerRole && (
400
+ <RoleDetailDrawer
401
+ role={drawerRole}
402
+ pages={rolePermissionSummary[drawerRole.id]?.pageInfos ?? []}
403
+ open={!!drawerRole}
404
+ onClose={() => setDrawerRole(null)}
405
+ />
406
+ )}
407
+ {showModal.type === "edit" && showModal.id && (
408
+ <EditModal
409
+ id={showModal.id}
410
+ onClose={handleModalClose}
411
+ onSuccess={handleModalSuccess}
412
+ pageTreeData={pageTreeData}
413
+ rolePermissionSummary={rolePermissionSummary[showModal.id]}
414
+ />
415
+ )}
416
+ {showModal.type === "create" && (
417
+ <CreateModal
418
+ onClose={handleModalClose}
419
+ onSuccess={handleModalSuccess}
420
+ pageTreeData={pageTreeData}
421
+ />
422
+ )}
423
+ <SqlModal
424
+ open={sqlModal.open}
425
+ onClose={() => setSqlModal({ open: false, title: "", sql: "" })}
426
+ title={sqlModal.title}
427
+ sql={sqlModal.sql}
428
+ />
429
+ </div>
430
+ );
431
+ };
@@ -0,0 +1,8 @@
1
+ export const RoleSelect = {
2
+ id: true,
3
+ name: true,
4
+ description: true,
5
+ creator: true,
6
+ createdAt: true,
7
+ updatedAt: true,
8
+ };
@@ -0,0 +1,8 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ export type RolePageTreeNode = {
4
+ title: ReactNode;
5
+ value: string;
6
+ key: string;
7
+ children?: RolePageTreeNode[];
8
+ };
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+
3
+ import { UserFormModal } from "./form-modal";
4
+
5
+ interface CreateModalProps {
6
+ onClose: () => void;
7
+ }
8
+
9
+ export const CreateModal: React.FC<CreateModalProps> = ({ onClose }) => {
10
+ return (
11
+ <UserFormModal
12
+ action="create"
13
+ onCancel={onClose}
14
+ onMutationSuccess={onClose}
15
+ />
16
+ );
17
+ };
@@ -0,0 +1,19 @@
1
+ import React from "react";
2
+
3
+ import { UserFormModal } from "./form-modal";
4
+
5
+ interface EditModalProps {
6
+ id?: number;
7
+ onClose: () => void;
8
+ }
9
+
10
+ export const EditModal: React.FC<EditModalProps> = ({ id, onClose }) => {
11
+ return (
12
+ <UserFormModal
13
+ action="edit"
14
+ id={id}
15
+ onCancel={onClose}
16
+ onMutationSuccess={onClose}
17
+ />
18
+ );
19
+ };
@@ -0,0 +1,188 @@
1
+ import React, { useState } from "react";
2
+
3
+ import { useModalForm } from "@refinedev/antd";
4
+ import { type HttpError, type RedirectAction } from "@refinedev/core";
5
+
6
+ import { Button, Form, Input, Modal, Select, Space, Switch } from "antd";
7
+ import { ReloadOutlined } from "@ant-design/icons";
8
+
9
+ import { useRoles } from "@/hooks/useRoles";
10
+ import { User } from "@/types";
11
+
12
+ import { UserSelect } from "../queries";
13
+
14
+ const generateApiKey = () => crypto.randomUUID();
15
+
16
+ type Props = {
17
+ action: "create" | "edit";
18
+ id?: number;
19
+ redirect?: RedirectAction;
20
+ onMutationSuccess?: () => void;
21
+ onCancel?: () => void;
22
+ };
23
+
24
+ export const UserFormModal: React.FC<Props> = ({
25
+ action,
26
+ id,
27
+ redirect,
28
+ onCancel,
29
+ onMutationSuccess,
30
+ }) => {
31
+ const [isApiKey, setIsApiKey] = useState(false);
32
+ const [usernameTouched, setUsernameTouched] = useState(false);
33
+
34
+ // Fetch roles from backend using custom hook
35
+ const { roleOptions, loading: rolesLoading } = useRoles();
36
+
37
+ const { formProps, modalProps, onFinish, close, form } = useModalForm<
38
+ User,
39
+ HttpError,
40
+ Partial<User>
41
+ >({
42
+ resource: "user",
43
+ action,
44
+ id,
45
+ defaultVisible: true,
46
+ redirect,
47
+ onMutationSuccess: () => {
48
+ onMutationSuccess?.();
49
+ },
50
+ meta: {
51
+ select: UserSelect,
52
+ },
53
+ });
54
+
55
+ // fix react-query cache data type error
56
+ if (
57
+ formProps.initialValues?.roles &&
58
+ typeof formProps.initialValues.roles === "string"
59
+ ) {
60
+ formProps.initialValues.roles = JSON.parse(formProps.initialValues.roles);
61
+ }
62
+
63
+ // sync isApiKey state with form initial values
64
+ React.useEffect(() => {
65
+ if (formProps.initialValues?.isApiKey !== undefined) {
66
+ setIsApiKey(formProps.initialValues.isApiKey);
67
+ }
68
+ }, [formProps.initialValues?.isApiKey]);
69
+
70
+ const handleGenerateApiKey = () => {
71
+ const newKey = generateApiKey();
72
+ form.setFieldsValue({ apiKey: newKey });
73
+ };
74
+
75
+ const handleIsApiKeyChange = (checked: boolean) => {
76
+ setIsApiKey(checked);
77
+ if (checked && !form.getFieldValue("apiKey")) {
78
+ handleGenerateApiKey();
79
+ }
80
+ if (checked) {
81
+ form.setFieldsValue({ isActive: true });
82
+ }
83
+ };
84
+
85
+ formProps.onFinish = (values) => {
86
+ onFinish({ ...values, roles: JSON.stringify(values.roles) });
87
+ };
88
+
89
+ return (
90
+ <Modal
91
+ {...modalProps}
92
+ width={560}
93
+ onCancel={() => {
94
+ if (onCancel) {
95
+ onCancel();
96
+ return;
97
+ }
98
+ //TODO: modalProps.onCancel expect an event so, I used close. Actually both of them are same.
99
+ close();
100
+ }}
101
+ title={action === "create" ? "Create User" : "Edit User"}
102
+ >
103
+ <Form {...formProps} layout="vertical">
104
+ <Form.Item rules={[{ required: true }]} name="userid" label="User ID(WecomId 或者 太湖帐号名)">
105
+ <Input
106
+ placeholder="Please enter user ID"
107
+ onChange={(e) => {
108
+ if (action === "create" && !usernameTouched) {
109
+ form.setFieldsValue({ username: e.target.value });
110
+ }
111
+ }}
112
+ />
113
+ </Form.Item>
114
+
115
+ <Form.Item
116
+ rules={[{ required: true }]}
117
+ name="username"
118
+ label="Username(一般设置为和上面的 User ID 一样)"
119
+ >
120
+ <Input
121
+ placeholder="Please enter username"
122
+ onChange={() => {
123
+ if (!usernameTouched) setUsernameTouched(true);
124
+ }}
125
+ />
126
+ </Form.Item>
127
+
128
+ <Form.Item rules={[{ required: true }]} name="roles" label="Roles">
129
+ <Select
130
+ mode="multiple"
131
+ placeholder="Please select roles"
132
+ options={roleOptions}
133
+ loading={rolesLoading}
134
+ />
135
+ </Form.Item>
136
+
137
+ <Form.Item
138
+ name="isActive"
139
+ label="Is Active"
140
+ valuePropName="checked"
141
+ initialValue={true}
142
+ >
143
+ <Switch />
144
+ </Form.Item>
145
+
146
+ <Form.Item
147
+ name="isApiKey"
148
+ label="Is API Key User(用来提供给其他开发者以apikey的方式来访问)"
149
+ valuePropName="checked"
150
+ >
151
+ <Switch onChange={handleIsApiKeyChange} />
152
+ </Form.Item>
153
+
154
+ {isApiKey && (
155
+ <>
156
+ <Form.Item
157
+ label="API Key"
158
+ rules={[{ required: isApiKey, message: "Please generate API Key" }]}
159
+ >
160
+ <Space.Compact style={{ width: "100%" }}>
161
+ <Form.Item name="apiKey" noStyle>
162
+ <Input
163
+ placeholder="Click button to generate API Key"
164
+ style={{ fontFamily: "monospace" }}
165
+ />
166
+ </Form.Item>
167
+ <Button
168
+ type="primary"
169
+ icon={<ReloadOutlined />}
170
+ onClick={handleGenerateApiKey}
171
+ >
172
+ {form.getFieldValue("apiKey") ? "Regenerate" : "Generate"}
173
+ </Button>
174
+ </Space.Compact>
175
+ </Form.Item>
176
+
177
+ <Form.Item name="description" label="Description">
178
+ <Input.TextArea
179
+ rows={2}
180
+ placeholder="Please enter description for this API Key"
181
+ />
182
+ </Form.Item>
183
+ </>
184
+ )}
185
+ </Form>
186
+ </Modal>
187
+ );
188
+ };
@@ -0,0 +1,5 @@
1
+ export * from "./create-modal";
2
+ export * from "./edit-modal";
3
+ export * from "./form-modal";
4
+ export * from "./role-tag";
5
+ export * from "./show-drawer";