@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,25 @@
1
+ import React from "react";
2
+ import { ResourceFormModal } from "./modal";
3
+
4
+ interface CreateModalProps {
5
+ onClose: () => void;
6
+ onSuccess?: () => void;
7
+ }
8
+
9
+ export const CreateModal: React.FC<CreateModalProps> = ({
10
+ onClose,
11
+ onSuccess,
12
+ }) => {
13
+ const handleMutationSuccess = () => {
14
+ onSuccess?.();
15
+ onClose?.();
16
+ };
17
+
18
+ return (
19
+ <ResourceFormModal
20
+ action="create"
21
+ onCancel={onClose}
22
+ onMutationSuccess={handleMutationSuccess}
23
+ />
24
+ );
25
+ };
@@ -0,0 +1,28 @@
1
+ import React from "react";
2
+ import { ResourceFormModal } from "./modal";
3
+
4
+ interface EditModalProps {
5
+ id?: number;
6
+ onClose: () => void;
7
+ onSuccess?: () => void;
8
+ }
9
+
10
+ export const EditModal: React.FC<EditModalProps> = ({
11
+ id,
12
+ onClose,
13
+ onSuccess,
14
+ }) => {
15
+ const handleMutationSuccess = () => {
16
+ onSuccess?.();
17
+ onClose?.();
18
+ };
19
+
20
+ return (
21
+ <ResourceFormModal
22
+ action="edit"
23
+ id={id}
24
+ onCancel={onClose}
25
+ onMutationSuccess={handleMutationSuccess}
26
+ />
27
+ );
28
+ };
@@ -0,0 +1,160 @@
1
+ import React, { useEffect, useMemo } from "react";
2
+ import { useTranslation } from "react-i18next";
3
+ import { Descriptions, Drawer, Space, Table, Tabs, Tag } from "antd";
4
+ import { useFetchData } from "@/hooks/useFetchData";
5
+ import type { Resource } from "../types";
6
+
7
+ interface ResourceDetailDrawerProps {
8
+ resource: Resource;
9
+ open: boolean;
10
+ onClose: () => void;
11
+ }
12
+
13
+ export const ResourceDetailDrawer: React.FC<ResourceDetailDrawerProps> = ({
14
+ resource,
15
+ open,
16
+ onClose,
17
+ }) => {
18
+ const { i18n } = useTranslation();
19
+ const isChinese = i18n.language === "zh_CN" || i18n.language === "zh";
20
+
21
+ const {
22
+ data: pageResourceData,
23
+ loading: pageLoading,
24
+ fetchData: fetchPageResources,
25
+ } = useFetchData("pageResource/findMany", "post", undefined, true);
26
+
27
+ const {
28
+ data: roleData,
29
+ loading: roleLoading,
30
+ fetchData: fetchRoles,
31
+ } = useFetchData("role/findMany", "post", undefined, true);
32
+
33
+ useEffect(() => {
34
+ if (open) {
35
+ fetchPageResources({
36
+ where: { resourceId: resource.id },
37
+ include: { page: { select: { id: true, name: true, code: true, zhName: true, enName: true } } },
38
+ take: 1000,
39
+ });
40
+ // Query roles with filtered roleResources for this resource
41
+ fetchRoles({
42
+ where: {
43
+ roleResources: {
44
+ some: { resourceId: resource.id },
45
+ },
46
+ },
47
+ include: {
48
+ roleResources: {
49
+ where: { resourceId: resource.id },
50
+ },
51
+ },
52
+ take: 1000,
53
+ });
54
+ }
55
+ }, [open, resource.id]);
56
+
57
+ const pages = useMemo(() => {
58
+ const list: any[] = Array.isArray(pageResourceData?.data)
59
+ ? pageResourceData.data
60
+ : [];
61
+ return list.map((item: any) => {
62
+ const page = item.page;
63
+ const pageName = isChinese
64
+ ? (page?.zhName || page?.name || "-")
65
+ : (page?.enName || page?.name || "-");
66
+ return {
67
+ key: item.id,
68
+ pageName,
69
+ pageCode: page?.code || "-",
70
+ actions: Array.isArray(item.actions) ? item.actions : [],
71
+ };
72
+ });
73
+ }, [pageResourceData]);
74
+
75
+ const roles = useMemo(() => {
76
+ const list: any[] = Array.isArray(roleData?.data) ? roleData.data : [];
77
+ return list.map((item: any) => {
78
+ const roleResource = item.roleResources?.[0];
79
+ const actions = roleResource?.actions;
80
+ return {
81
+ key: item.id,
82
+ roleName: item.name || "-",
83
+ roleCode: item.code || "-",
84
+ actions: Array.isArray(actions) ? actions : [],
85
+ };
86
+ });
87
+ }, [roleData]);
88
+
89
+ const permissionColumns = [
90
+ {
91
+ title: "Permissions",
92
+ dataIndex: "actions",
93
+ render: (actions: string[]) => (
94
+ <Space size={[0, 4]} wrap>
95
+ {actions.map(a => (
96
+ <Tag key={a}>{a}</Tag>
97
+ ))}
98
+ </Space>
99
+ ),
100
+ },
101
+ ];
102
+
103
+ return (
104
+ <Drawer
105
+ title={`Resource: ${resource.name}`}
106
+ open={open}
107
+ onClose={onClose}
108
+ width={560}
109
+ destroyOnClose
110
+ >
111
+ <Descriptions column={1} size="small" bordered style={{ marginBottom: 16 }}>
112
+ <Descriptions.Item label="Code">{resource.code}</Descriptions.Item>
113
+ <Descriptions.Item label="Name">{resource.name}</Descriptions.Item>
114
+ {resource.description && (
115
+ <Descriptions.Item label="Description">{resource.description}</Descriptions.Item>
116
+ )}
117
+ </Descriptions>
118
+
119
+ <Tabs
120
+ items={[
121
+ {
122
+ key: "pages",
123
+ label: `Referenced by Pages (${pages.length})`,
124
+ children: (
125
+ <Table
126
+ dataSource={pages}
127
+ loading={pageLoading}
128
+ rowKey="key"
129
+ size="small"
130
+ pagination={pages.length > 10 ? { pageSize: 10 } : false}
131
+ columns={[
132
+ { title: "Page Name", dataIndex: "pageName", width: "35%" },
133
+ { title: "Page Code", dataIndex: "pageCode", width: "25%" },
134
+ ...permissionColumns,
135
+ ]}
136
+ />
137
+ ),
138
+ },
139
+ {
140
+ key: "roles",
141
+ label: `Visible to Roles (${roles.length})`,
142
+ children: (
143
+ <Table
144
+ dataSource={roles}
145
+ loading={roleLoading}
146
+ rowKey="key"
147
+ size="small"
148
+ pagination={roles.length > 10 ? { pageSize: 10 } : false}
149
+ columns={[
150
+ { title: "Role Name", dataIndex: "roleName", width: "35%" },
151
+ ...permissionColumns,
152
+ ]}
153
+ />
154
+ ),
155
+ },
156
+ ]}
157
+ />
158
+ </Drawer>
159
+ );
160
+ };
@@ -0,0 +1,202 @@
1
+ import React from "react";
2
+ import { useModalForm } from "@refinedev/antd";
3
+ import { type HttpError, useList } from "@refinedev/core";
4
+ import { Checkbox, Form, Input, Modal, Select } from "antd";
5
+ import type { Resource } from "../types";
6
+ import { ResourceSelect } from "../queries";
7
+ import { PROTECTED_RESOURCES } from "../list";
8
+
9
+ type ResourceFormFields = Partial<Resource>;
10
+
11
+ type Props = {
12
+ action: "create" | "edit";
13
+ id?: number;
14
+ onMutationSuccess?: () => void;
15
+ onCancel?: () => void;
16
+ };
17
+
18
+ // Pattern to detect special characters - only allows letters, numbers, and underscores
19
+ const SPECIAL_CHAR_PATTERN = /[^a-zA-Z0-9_]/;
20
+
21
+ export const ResourceFormModal: React.FC<Props> = ({ action, id, onCancel, onMutationSuccess }) => {
22
+ const { formProps, modalProps, close } = useModalForm<Resource, HttpError, ResourceFormFields>({
23
+ resource: "resource",
24
+ action,
25
+ id,
26
+ defaultVisible: true,
27
+ onMutationSuccess: () => {
28
+ onMutationSuccess?.();
29
+ },
30
+ meta: {
31
+ select: ResourceSelect,
32
+ },
33
+ });
34
+
35
+ // Fetch all resources for code duplication check
36
+ const { data: resourcesData } = useList<Resource>({
37
+ resource: "resource",
38
+ pagination: {
39
+ mode: "off",
40
+ },
41
+ });
42
+
43
+ // Check if current resource is protected (for edit mode)
44
+ const currentResource = resourcesData?.data?.find(r => r.id === id);
45
+ const isProtectedResource = currentResource
46
+ ? PROTECTED_RESOURCES.includes(currentResource.code.toLowerCase())
47
+ : false;
48
+
49
+ return (
50
+ <Modal
51
+ {...modalProps}
52
+ width={560}
53
+ onCancel={() => {
54
+ if (onCancel) {
55
+ onCancel();
56
+ return;
57
+ }
58
+ close();
59
+ }}
60
+ title={action === "create" ? "Create Resource" : "Edit Resource"}
61
+ >
62
+ <Form {...formProps} layout="vertical">
63
+ {isProtectedResource && (
64
+ <div
65
+ style={{
66
+ padding: "12px",
67
+ marginBottom: "16px",
68
+ backgroundColor: "#fff7e6",
69
+ border: "1px solid #ffd591",
70
+ borderRadius: "4px",
71
+ color: "#d46b08",
72
+ }}
73
+ >
74
+ ⚠️ This is a system resource and cannot be modified.
75
+ </div>
76
+ )}
77
+ <Form.Item
78
+ rules={[
79
+ { required: true, message: "Resource Code is required" },
80
+ {
81
+ pattern: /^[a-zA-Z0-9_]+$/,
82
+ message: "Resource Code can only contain letters, numbers and underscores",
83
+ },
84
+ {
85
+ validator: async (_, value) => {
86
+ if (!value) {
87
+ return Promise.resolve();
88
+ }
89
+
90
+ const existingResources = resourcesData?.data || [];
91
+ const trimmedValue = value.trim();
92
+
93
+ // In edit mode, if value hasn't changed, skip validation
94
+ if (action === "edit" && currentResource && trimmedValue === currentResource.code) {
95
+ return Promise.resolve();
96
+ }
97
+
98
+ // Check if trying to use a protected resource code
99
+ if (PROTECTED_RESOURCES.includes(trimmedValue.toLowerCase())) {
100
+ return Promise.reject(
101
+ new Error("This resource code is reserved for system use and cannot be used."),
102
+ );
103
+ }
104
+
105
+ // Check if resource code already exists (case-insensitive)
106
+ const isDuplicate = existingResources.some(resource => {
107
+ // Skip current resource when editing
108
+ if (action === "edit" && resource.id === id) {
109
+ return false;
110
+ }
111
+ return resource.code.toLowerCase() === trimmedValue.toLowerCase();
112
+ });
113
+
114
+ if (isDuplicate) {
115
+ return Promise.reject(
116
+ new Error("Resource code already exists. Please use a different code."),
117
+ );
118
+ }
119
+
120
+ return Promise.resolve();
121
+ },
122
+ },
123
+ ]}
124
+ name="code"
125
+ label="Resource Code"
126
+ >
127
+ <Input
128
+ placeholder="Enter resource code (e.g., networkincidents, pageresources)"
129
+ disabled={isProtectedResource || action === "edit"}
130
+ />
131
+ </Form.Item>
132
+
133
+ <Form.Item
134
+ rules={[
135
+ { required: true, message: "Resource name is required" },
136
+ {
137
+ validator: (_, value) => {
138
+ if (!value || !SPECIAL_CHAR_PATTERN.test(value)) {
139
+ return Promise.resolve();
140
+ }
141
+ return Promise.reject(
142
+ new Error("Special characters are not allowed in resource name."),
143
+ );
144
+ },
145
+ },
146
+ {
147
+ validator: async (_, value) => {
148
+ if (!value) {
149
+ return Promise.resolve();
150
+ }
151
+
152
+ const existingResources = resourcesData?.data || [];
153
+ const trimmedValue = value.trim();
154
+
155
+ // In edit mode, if value hasn't changed, skip validation
156
+ if (action === "edit" && currentResource && trimmedValue === currentResource.name) {
157
+ return Promise.resolve();
158
+ }
159
+
160
+ // Check if resource name already exists (case-insensitive) - warning only
161
+ const isDuplicate = existingResources.some(resource => {
162
+ // Skip current resource when editing
163
+ if (action === "edit" && resource.id === id) {
164
+ return false;
165
+ }
166
+ return resource.name.toLowerCase() === trimmedValue.toLowerCase();
167
+ });
168
+
169
+ if (isDuplicate) {
170
+ return Promise.reject(
171
+ new Error(
172
+ "⚠️ Warning: Resource name already exists. It's recommended to use a different name.",
173
+ ),
174
+ );
175
+ }
176
+
177
+ return Promise.resolve();
178
+ },
179
+ },
180
+ ]}
181
+ name="name"
182
+ label="Resource Name"
183
+ >
184
+ <Input
185
+ placeholder="Enter resource name (e.g., User Read Permission)"
186
+ disabled={isProtectedResource}
187
+ />
188
+ </Form.Item>
189
+ <Form.Item name="isCommonResource" valuePropName="checked">
190
+ <Checkbox>Is Common Resource</Checkbox>
191
+ </Form.Item>
192
+ <Form.Item name="description" label="Description">
193
+ <Input.TextArea
194
+ rows={4}
195
+ placeholder="Enter resource description"
196
+ disabled={isProtectedResource}
197
+ />
198
+ </Form.Item>
199
+ </Form>
200
+ </Modal>
201
+ );
202
+ };
@@ -0,0 +1,2 @@
1
+ export { ResourceManagementListPage } from "./list";
2
+ export type { Resource } from "./types";
@@ -0,0 +1,212 @@
1
+ import React, { useState, useMemo } from "react";
2
+ import { useTable, FilterDropdown } from "@refinedev/antd";
3
+ import { Table, Button, Space, Tooltip, Input } from "antd";
4
+ import { EditOutlined, EyeOutlined, SearchOutlined, CodeOutlined } from "@ant-design/icons";
5
+ import { getDefaultFilter, type HttpError, useGetIdentity } from "@refinedev/core";
6
+ import type { Resource } from "./types";
7
+ import { EditModal } from "./Components/EditModal";
8
+ import { CreateModal } from "./Components/CreateModal";
9
+ import { ResourceDetailDrawer } from "./Components/ResourceDetailDrawer";
10
+ import { SqlModal, generateResourceSql } from "../../components/SqlModal";
11
+
12
+ // System resources that cannot be modified (use Set for O(1) lookup performance)
13
+ // System resources that cannot be modified
14
+ export const PROTECTED_RESOURCES = ["pageresource", "resource", "page", "rolepages", "role", "roleresource"];
15
+
16
+ export const ResourceManagementListPage: React.FC = () => {
17
+ const { data: identity } = useGetIdentity<any>();
18
+ const { tableProps, filters, tableQueryResult } = useTable<
19
+ Resource,
20
+ HttpError,
21
+ Partial<Resource>
22
+ >({
23
+ resource: "resource",
24
+ syncWithLocation: false, // Disable URL sync to keep URL clean
25
+ pagination: {
26
+ pageSize: 20,
27
+ },
28
+ onSearch: (values: Partial<Resource>) => {
29
+ return Object.entries(values)
30
+ .filter(([, value]) => value !== undefined && value !== "")
31
+ .map(([field, value]) => ({
32
+ field,
33
+ operator: "contains" as const,
34
+ value: value || "",
35
+ }));
36
+ },
37
+ filters: {
38
+ initial: [
39
+ { field: "code", operator: "contains", value: "" },
40
+ { field: "name", operator: "contains", value: "" },
41
+ ],
42
+ defaultBehavior: "merge",
43
+ },
44
+ sorters: {
45
+ },
46
+ });
47
+
48
+ const [showModal, setShowModal] = useState<{
49
+ type: "edit" | "create" | null;
50
+ id: number | null;
51
+ }>({
52
+ type: null,
53
+ id: null,
54
+ });
55
+
56
+ const [drawerResource, setDrawerResource] = useState<Resource | null>(null);
57
+
58
+ const [sqlModal, setSqlModal] = useState<{
59
+ open: boolean;
60
+ title: string;
61
+ sql: string;
62
+ }>({ open: false, title: "", sql: "" });
63
+
64
+ const handleShowSql = (record: Resource) => {
65
+ const operator = { authorId: identity?.userid, authorName: identity?.username };
66
+ const sql = generateResourceSql(record, operator);
67
+ setSqlModal({ open: true, title: `SQL — Resource: ${record.code}`, sql });
68
+ };
69
+
70
+ // fix for ant design filter dropdown contains operator
71
+ filters.map(filter => {
72
+ if (filter.operator === "contains" && Array.isArray(filter.value)) {
73
+ filter.value = filter.value.join(",");
74
+ }
75
+ });
76
+
77
+ // Pre-compute protected resources map for better performance
78
+ // This avoids repeated toLowerCase() and includes() calls during rendering
79
+ const protectedResourcesMap = useMemo(() => {
80
+ const dataSource = tableProps.dataSource || [];
81
+ const map = new Map<number, boolean>();
82
+ dataSource.forEach((record: Resource) => {
83
+ map.set(record.id, PROTECTED_RESOURCES.includes(record.code.toLowerCase()));
84
+ });
85
+ return map;
86
+ }, [tableProps.dataSource]);
87
+
88
+ const handleModalClose = () => {
89
+ setShowModal({ type: null, id: null });
90
+ };
91
+
92
+ const handleModalSuccess = () => {
93
+ handleModalClose();
94
+ tableQueryResult?.refetch();
95
+ };
96
+
97
+ return (
98
+ <div>
99
+ <Space style={{ marginBottom: 16 }}>
100
+ <Button
101
+ type="primary"
102
+ onClick={() =>
103
+ setShowModal({
104
+ type: "create",
105
+ id: null,
106
+ })
107
+ }
108
+ >
109
+ Create Resource
110
+ </Button>
111
+ </Space>
112
+ <Table {...tableProps} rowKey="id">
113
+ <Table.Column
114
+ dataIndex="code"
115
+ title="Code"
116
+ sorter={(a: Resource, b: Resource) => a.code.localeCompare(b.code)}
117
+ defaultFilteredValue={getDefaultFilter("code", filters, "contains")}
118
+ filterDropdown={props => (
119
+ <FilterDropdown
120
+ {...props}
121
+ clearFilters={() => {
122
+ props.setSelectedKeys([]);
123
+ props.confirm?.();
124
+ }}
125
+ >
126
+ <Input placeholder="Search Code" />
127
+ </FilterDropdown>
128
+ )}
129
+ filterIcon={<SearchOutlined />}
130
+ />
131
+ <Table.Column
132
+ dataIndex="name"
133
+ title="Name"
134
+ sorter={(a: Resource, b: Resource) => a.name.localeCompare(b.name)}
135
+ defaultFilteredValue={getDefaultFilter("name", filters, "contains")}
136
+ filterDropdown={props => (
137
+ <FilterDropdown
138
+ {...props}
139
+ clearFilters={() => {
140
+ props.setSelectedKeys([]);
141
+ props.confirm?.();
142
+ }}
143
+ >
144
+ <Input placeholder="Search Name" />
145
+ </FilterDropdown>
146
+ )}
147
+ filterIcon={<SearchOutlined />}
148
+ />
149
+ <Table.Column dataIndex="description" title="Description" />
150
+ <Table.Column
151
+ dataIndex="creator"
152
+ title="Creator"
153
+ sorter={(a: Resource, b: Resource) => (a.creator || "").localeCompare(b.creator || "")}
154
+ />
155
+ <Table.Column
156
+ title="Actions"
157
+ render={(_, record: Resource) => {
158
+ const isProtected = protectedResourcesMap.get(record.id) || false;
159
+ return (
160
+ <Space>
161
+ <Tooltip title="View details">
162
+ <Button
163
+ type="default"
164
+ size="small"
165
+ icon={<EyeOutlined />}
166
+ onClick={() => setDrawerResource(record)}
167
+ />
168
+ </Tooltip>
169
+ <Tooltip title={isProtected ? "This is a system resource and cannot be modified" : "Edit"}>
170
+ <Button
171
+ type="default"
172
+ size="small"
173
+ icon={<EditOutlined />}
174
+ disabled={isProtected}
175
+ onClick={() => setShowModal({ type: "edit", id: record.id })}
176
+ />
177
+ </Tooltip>
178
+ <Tooltip title="Generate SQL">
179
+ <Button
180
+ type="default"
181
+ size="small"
182
+ icon={<CodeOutlined />}
183
+ onClick={() => handleShowSql(record)}
184
+ />
185
+ </Tooltip>
186
+ </Space>
187
+ );
188
+ }}
189
+ />
190
+ </Table>
191
+ {showModal.type === "edit" && showModal.id && (
192
+ <EditModal id={showModal.id} onClose={handleModalClose} onSuccess={handleModalSuccess} />
193
+ )}
194
+ {showModal.type === "create" && (
195
+ <CreateModal onClose={handleModalClose} onSuccess={handleModalSuccess} />
196
+ )}
197
+ {drawerResource && (
198
+ <ResourceDetailDrawer
199
+ resource={drawerResource}
200
+ open={!!drawerResource}
201
+ onClose={() => setDrawerResource(null)}
202
+ />
203
+ )}
204
+ <SqlModal
205
+ open={sqlModal.open}
206
+ onClose={() => setSqlModal({ open: false, title: "", sql: "" })}
207
+ title={sqlModal.title}
208
+ sql={sqlModal.sql}
209
+ />
210
+ </div>
211
+ );
212
+ };
@@ -0,0 +1,10 @@
1
+ export const ResourceSelect = {
2
+ id: true,
3
+ name: true,
4
+ code: true,
5
+ description: true,
6
+ isCommonResource: true,
7
+ creator: true,
8
+ createdAt: true,
9
+ updatedAt: true,
10
+ };
@@ -0,0 +1,9 @@
1
+ export type Resource = {
2
+ id: number;
3
+ name: string;
4
+ code: string;
5
+ description?: string;
6
+ creator?: string;
7
+ createdAt?: Date;
8
+ updatedAt?: Date;
9
+ };
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+
3
+ import { RoleFormModal } from "./modal";
4
+ import type { RolePageTreeNode } from "../types";
5
+
6
+ interface CreateModalProps {
7
+ onClose: () => void;
8
+ onSuccess?: () => void;
9
+ pageTreeData?: RolePageTreeNode[];
10
+ }
11
+
12
+ export const CreateModal: React.FC<CreateModalProps> = ({
13
+ onClose,
14
+ onSuccess,
15
+ pageTreeData,
16
+ }) => {
17
+ const handleMutationSuccess = () => {
18
+ onSuccess?.();
19
+ onClose?.();
20
+ };
21
+
22
+ return (
23
+ <RoleFormModal
24
+ action="create"
25
+ onCancel={onClose}
26
+ onMutationSuccess={handleMutationSuccess}
27
+ pageTreeData={pageTreeData}
28
+ />
29
+ );
30
+ };