@gadmin2n/schematics 0.0.70 → 0.0.71

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 (474) hide show
  1. package/dist/lib/application/files/gadmin2-game-angle-demo/web/.npmrc +1 -0
  2. package/package.json +1 -1
  3. package/src/lib/application/application.schema.d.ts +59 -0
  4. package/src/lib/application/files/gadmin2-game-angle-demo/.dockerignore +33 -0
  5. package/src/lib/application/files/gadmin2-game-angle-demo/.gitignore +46 -0
  6. package/src/lib/application/files/gadmin2-game-angle-demo/.husky/_/.gitignore +1 -0
  7. package/src/lib/application/files/gadmin2-game-angle-demo/.husky/_/husky.sh +36 -0
  8. package/src/lib/application/files/gadmin2-game-angle-demo/.husky/pre-commit +10 -0
  9. package/src/lib/application/files/gadmin2-game-angle-demo/Dockerfile +63 -0
  10. package/src/lib/application/files/gadmin2-game-angle-demo/Jenkinsfile +70 -0
  11. package/src/lib/application/files/gadmin2-game-angle-demo/config/.types.d.ts +143 -0
  12. package/src/lib/application/files/gadmin2-game-angle-demo/config/prisma/canvas.prisma +45 -0
  13. package/src/lib/application/files/gadmin2-game-angle-demo/config/prisma/example.prisma +34 -0
  14. package/src/lib/application/files/gadmin2-game-angle-demo/config/prisma/system.prisma +173 -0
  15. package/src/lib/application/files/gadmin2-game-angle-demo/config/ui/Audit.ts +70 -0
  16. package/src/lib/application/files/gadmin2-game-angle-demo/config/ui/Event.ts +70 -0
  17. package/src/lib/application/files/gadmin2-game-angle-demo/config/ui/Game.ts +58 -0
  18. package/src/lib/application/files/gadmin2-game-angle-demo/config/ui/ITActivityDay.ts +70 -0
  19. package/src/lib/application/files/gadmin2-game-angle-demo/config/ui/Log.ts +56 -0
  20. package/src/lib/application/files/gadmin2-game-angle-demo/config/ui/Page.ts +70 -0
  21. package/src/lib/application/files/gadmin2-game-angle-demo/config/ui/PageResource.ts +70 -0
  22. package/src/lib/application/files/gadmin2-game-angle-demo/config/ui/Resource.ts +70 -0
  23. package/src/lib/application/files/gadmin2-game-angle-demo/config/ui/Role.ts +58 -0
  24. package/src/lib/application/files/gadmin2-game-angle-demo/config/ui/RolePages.ts +70 -0
  25. package/src/lib/application/files/gadmin2-game-angle-demo/config/ui/RoleResource.ts +70 -0
  26. package/src/lib/application/files/gadmin2-game-angle-demo/config/ui/SavedQuery.ts +70 -0
  27. package/src/lib/application/files/gadmin2-game-angle-demo/config/ui/User.ts +70 -0
  28. package/src/lib/application/files/gadmin2-game-angle-demo/config/ui/_common.ts +16 -0
  29. package/src/lib/application/files/gadmin2-game-angle-demo/readme.md +142 -0
  30. package/src/lib/application/files/gadmin2-game-angle-demo/server/.env +31 -0
  31. package/src/lib/application/files/gadmin2-game-angle-demo/server/.env.local +1 -0
  32. package/src/lib/application/files/gadmin2-game-angle-demo/server/.eslintrc.js +28 -0
  33. package/src/lib/application/files/gadmin2-game-angle-demo/server/.prettierignore +7 -0
  34. package/src/lib/application/files/gadmin2-game-angle-demo/server/.prettierrc +4 -0
  35. package/src/lib/application/files/gadmin2-game-angle-demo/server/README.md +55 -0
  36. package/src/lib/application/files/gadmin2-game-angle-demo/server/config/ac.config.ts +24 -0
  37. package/src/lib/application/files/gadmin2-game-angle-demo/server/config/index.ts +58 -0
  38. package/src/lib/application/files/gadmin2-game-angle-demo/server/gadmin-cli.json +25 -0
  39. package/src/lib/application/files/gadmin2-game-angle-demo/server/migrate-between-pg-schemas.js +1232 -0
  40. package/src/lib/application/files/gadmin2-game-angle-demo/server/package.json +143 -0
  41. package/src/lib/application/files/gadmin2-game-angle-demo/server/prisma/.generator.prisma +34 -0
  42. package/src/lib/application/files/gadmin2-game-angle-demo/server/prisma.config.ts +16 -0
  43. package/src/lib/application/files/gadmin2-game-angle-demo/server/scripts/lib/page-helpers.ts +157 -0
  44. package/src/lib/application/files/gadmin2-game-angle-demo/server/scripts/page-manage.ts +290 -0
  45. package/src/lib/application/files/gadmin2-game-angle-demo/server/scripts/permission-manage.ts +184 -0
  46. package/src/lib/application/files/gadmin2-game-angle-demo/server/scripts/prismaModels.ts +143 -0
  47. package/src/lib/application/files/gadmin2-game-angle-demo/server/scripts/sync-resources.ts +100 -0
  48. package/src/lib/application/files/gadmin2-game-angle-demo/server/scripts/syncDataMngtPages.ts +119 -0
  49. package/src/lib/application/files/gadmin2-game-angle-demo/server/seed/games.ts +1 -0
  50. package/src/lib/application/files/gadmin2-game-angle-demo/server/seed/index.ts +21 -0
  51. package/src/lib/application/files/gadmin2-game-angle-demo/server/seed/permissions.ts +244 -0
  52. package/src/lib/application/files/gadmin2-game-angle-demo/server/seed/users.ts +7 -0
  53. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/alias.config.ts +7 -0
  54. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/app.controller.spec.ts +22 -0
  55. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/app.controller.ts +192 -0
  56. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/app.module.ts +91 -0
  57. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/app.service.ts +189 -0
  58. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/lib/auth.guard.ts +154 -0
  59. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/lib/http-cache.interceptor.ts +21 -0
  60. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/lib/logger.ts +19 -0
  61. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/lib/roles.guard.ts +47 -0
  62. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/lib/safe-log.util.ts +176 -0
  63. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/lib/taihu.ts +175 -0
  64. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/lib/tracing.ts +174 -0
  65. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/lib/trim.pipe.ts +51 -0
  66. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/lib/utils.ts +145 -0
  67. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/lib/woaAuth.ts +95 -0
  68. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/main.ts +132 -0
  69. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.controller.spec.ts +20 -0
  70. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.controller.ts +190 -0
  71. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.module.ts +10 -0
  72. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.service.spec.ts +338 -0
  73. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.service.ts +83 -0
  74. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.controller.spec.ts +20 -0
  75. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.controller.ts +81 -0
  76. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.dto.ts +49 -0
  77. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.module.ts +11 -0
  78. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.service.spec.ts +334 -0
  79. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/canvas/canvas.service.ts +249 -0
  80. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.controller.spec.ts +20 -0
  81. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.controller.ts +188 -0
  82. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.module.ts +10 -0
  83. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.service.spec.ts +18 -0
  84. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.service.ts +83 -0
  85. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/index.ts +4 -0
  86. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.controller.spec.ts +20 -0
  87. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.controller.ts +250 -0
  88. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.module.ts +10 -0
  89. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.service.spec.ts +18 -0
  90. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.service.ts +1051 -0
  91. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.controller.spec.ts +20 -0
  92. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.controller.ts +196 -0
  93. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.module.ts +13 -0
  94. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.service.spec.ts +18 -0
  95. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.service.ts +219 -0
  96. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.controller.spec.ts +20 -0
  97. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.controller.ts +196 -0
  98. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.module.ts +10 -0
  99. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.service.spec.ts +18 -0
  100. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.service.ts +199 -0
  101. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.controller.spec.ts +20 -0
  102. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.controller.ts +210 -0
  103. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.module.ts +12 -0
  104. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.service.spec.ts +18 -0
  105. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.service.ts +862 -0
  106. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/roles-refresher.service.ts +133 -0
  107. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.controller.spec.ts +20 -0
  108. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.controller.ts +196 -0
  109. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.module.ts +10 -0
  110. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.service.spec.ts +18 -0
  111. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.service.ts +201 -0
  112. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.controller.spec.ts +20 -0
  113. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.controller.ts +196 -0
  114. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.module.ts +10 -0
  115. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.service.spec.ts +18 -0
  116. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.service.ts +216 -0
  117. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.controller.spec.ts +20 -0
  118. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.controller.ts +198 -0
  119. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.module.ts +10 -0
  120. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.service.spec.ts +18 -0
  121. package/src/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.service.ts +104 -0
  122. package/src/lib/application/files/gadmin2-game-angle-demo/server/start-prod.sh +130 -0
  123. package/src/lib/application/files/gadmin2-game-angle-demo/server/test/app.e2e-spec.ts +24 -0
  124. package/src/lib/application/files/gadmin2-game-angle-demo/server/test/jest-e2e.json +9 -0
  125. package/src/lib/application/files/gadmin2-game-angle-demo/server/tsconfig.build.json +4 -0
  126. package/src/lib/application/files/gadmin2-game-angle-demo/server/tsconfig.json +36 -0
  127. package/src/lib/application/files/gadmin2-game-angle-demo/server/yarn.lock +7737 -0
  128. package/src/lib/application/files/gadmin2-game-angle-demo/web/.env +2 -0
  129. package/src/lib/application/files/gadmin2-game-angle-demo/web/.eslintrc.json +38 -0
  130. package/src/lib/application/files/gadmin2-game-angle-demo/web/.npmrc +1 -0
  131. package/src/lib/application/files/gadmin2-game-angle-demo/web/.prettierignore +2 -0
  132. package/src/lib/application/files/gadmin2-game-angle-demo/web/.prettierrc +4 -0
  133. package/src/lib/application/files/gadmin2-game-angle-demo/web/README.MD +48 -0
  134. package/src/lib/application/files/gadmin2-game-angle-demo/web/dev-shell-entry.html +49 -0
  135. package/src/lib/application/files/gadmin2-game-angle-demo/web/index.html +19 -0
  136. package/src/lib/application/files/gadmin2-game-angle-demo/web/package.json +92 -0
  137. package/src/lib/application/files/gadmin2-game-angle-demo/web/postcss.config.cjs +6 -0
  138. package/src/lib/application/files/gadmin2-game-angle-demo/web/public/favicon.ico +0 -0
  139. package/src/lib/application/files/gadmin2-game-angle-demo/web/public/images/flags/en.svg +1 -0
  140. package/src/lib/application/files/gadmin2-game-angle-demo/web/public/images/flags/zh_CN.svg +11 -0
  141. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/App.tsx +137 -0
  142. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/auditLogProvider.ts +89 -0
  143. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/authProvider.ts +144 -0
  144. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/BulkActions.tsx +287 -0
  145. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/ListPageHeader.tsx +56 -0
  146. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/RowActions.tsx +318 -0
  147. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/SearchBar.tsx +323 -0
  148. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/SqlModal.tsx +495 -0
  149. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/VanillaJSONEditor/index.css +10 -0
  150. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/VanillaJSONEditor/index.jsx +53 -0
  151. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/AgentContext.tsx +375 -0
  152. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/ElementInspector.tsx +1133 -0
  153. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/agentAttributes.ts +70 -0
  154. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/index.ts +8 -0
  155. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/inspectorActions.ts +1034 -0
  156. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/pagePathUtils.ts +66 -0
  157. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/promptGenerator.ts +135 -0
  158. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/agentPanel/propPatcher.ts +84 -0
  159. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/components/eventList/index.tsx +58 -0
  160. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/components/index.ts +4 -0
  161. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/components/logButton/index.tsx +96 -0
  162. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/components/logList/index.tsx +72 -0
  163. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/components/modalDiffViewer/index.tsx +104 -0
  164. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/auditLog/index.tsx +2 -0
  165. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/BarChart/index.tsx +896 -0
  166. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/ChartSwitcher/index.tsx +219 -0
  167. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/ChartViewer/index.tsx +159 -0
  168. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Filter/index.tsx +192 -0
  169. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/LineChart/index.tsx +1034 -0
  170. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumCard/NumCard.module.css +8 -0
  171. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumCard/index.tsx +509 -0
  172. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumLineCard/index.tsx +66 -0
  173. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/PieChart/index.tsx +552 -0
  174. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/RadarChart/index.tsx +263 -0
  175. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Section/index.tsx +35 -0
  176. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Table/index.tsx +207 -0
  177. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/TreemapChart/index.tsx +382 -0
  178. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/WorldMap/index.tsx +135 -0
  179. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/chart-constants.ts +53 -0
  180. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/icon/InfoIcon.tsx +8 -0
  181. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/icon/index.ts +1 -0
  182. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/config.ts +31 -0
  183. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/nameMap.json +9 -0
  184. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/world.geo.json +39349 -0
  185. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/metric-info-tooltip/index.tsx +19 -0
  186. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/contexts/business/index.tsx +65 -0
  187. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/contexts/color-mode/index.tsx +54 -0
  188. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/custom-avatar.tsx +42 -0
  189. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/index.ts +8 -0
  190. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/header.tsx +106 -0
  191. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/index.ts +4 -0
  192. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/layout.tsx +32 -0
  193. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/logo.tsx +19 -0
  194. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/sider.tsx +431 -0
  195. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/title.tsx +61 -0
  196. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/offLayoutArea/index.tsx +5 -0
  197. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/pagination-total.tsx +21 -0
  198. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/tags/index.ts +1 -0
  199. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/tags/role-tag.tsx +44 -0
  200. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/components/text.tsx +78 -0
  201. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/config/http.ts +49 -0
  202. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +428 -0
  203. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/constants/layout.ts +16 -0
  204. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/AddDataModal.tsx +199 -0
  205. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/AddPageModal.tsx +335 -0
  206. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DeleteDataConfirm.tsx +56 -0
  207. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +401 -0
  208. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/EditDataModal.tsx +129 -0
  209. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/SkillMenu.tsx +202 -0
  210. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/UndoConfirm.tsx +36 -0
  211. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/index.tsx +8 -0
  212. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/style.css +835 -0
  213. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/enums/audit-log.enum.ts +13 -0
  214. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/enums/index.ts +1 -0
  215. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/form.tsx +471 -0
  216. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/get-name-initials.ts +8 -0
  217. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/get-random-color.ts +27 -0
  218. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/http.ts +84 -0
  219. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/index.tsx +8 -0
  220. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/list.tsx +491 -0
  221. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/login.ts +82 -0
  222. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/page-tree.ts +74 -0
  223. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/show.tsx +226 -0
  224. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/utils.tsx +9 -0
  225. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/index.ts +7 -0
  226. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/types.ts +138 -0
  227. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useBatchDelete.ts +191 -0
  228. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useBatchOperations.ts +153 -0
  229. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useBatchOperationsCore.ts +193 -0
  230. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useBatchUpdate.ts +182 -0
  231. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx +220 -0
  232. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useECharts.tsx +144 -0
  233. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useFetchData.ts +33 -0
  234. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useListPageState.ts +303 -0
  235. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useRoles.ts +34 -0
  236. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useRowSelection.ts +38 -0
  237. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useUserPageAccess.ts +353 -0
  238. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/i18n.ts +23 -0
  239. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/index.tsx +27 -0
  240. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +321 -0
  241. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +324 -0
  242. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/meta.json +4 -0
  243. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/plugins/devShellPlugin.ts +81 -0
  244. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/components/action-cell.css +3 -0
  245. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/components/action-cell.tsx +134 -0
  246. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/create.tsx +105 -0
  247. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/edit.tsx +121 -0
  248. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/index.ts +8 -0
  249. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/index.tsx +4 -0
  250. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/list.tsx +220 -0
  251. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/show.tsx +74 -0
  252. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasCell.tsx +87 -0
  253. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasEditPage.tsx +192 -0
  254. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasListPage.tsx +409 -0
  255. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasPage.tsx +1372 -0
  256. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx +384 -0
  257. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CodeFloatWindow.tsx +476 -0
  258. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/ComponentThumbnail.tsx +137 -0
  259. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/IsolatedLivePreview.tsx +101 -0
  260. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/LivePreview.tsx +236 -0
  261. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/PublishModal.tsx +200 -0
  262. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasApi.ts +92 -0
  263. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasConfigRegistry.tsx +25 -0
  264. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasContextMenuRegistry.tsx +875 -0
  265. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasDefaults.ts +126 -0
  266. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasI18n.ts +11 -0
  267. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/BarChartDataSourceModal.tsx +115 -0
  268. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/ChartViewerConfigModal.tsx +217 -0
  269. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/LineChartDataSourceModal.tsx +153 -0
  270. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/NumCardDataSourceModal.tsx +211 -0
  271. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/PromptModal.tsx +90 -0
  272. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/RadarChartDataSourceModal.tsx +87 -0
  273. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/TableDataSourceModal.tsx +204 -0
  274. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/demos.ts +1153 -0
  275. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/index.tsx +2 -0
  276. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/sectionCompactor.ts +45 -0
  277. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/types.ts +45 -0
  278. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas-page/index.tsx +108 -0
  279. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/create.tsx +105 -0
  280. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/edit.tsx +121 -0
  281. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/index.tsx +4 -0
  282. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/list.tsx +237 -0
  283. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/game/show.tsx +74 -0
  284. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/AssignRolesModal.tsx +177 -0
  285. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/CreatePageModal.tsx +42 -0
  286. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/EditPageModal.tsx +46 -0
  287. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/PageDetailDrawer.tsx +136 -0
  288. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/PageFormModal.tsx +815 -0
  289. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/hooks/usePageManagement.ts +40 -0
  290. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/index.ts +1 -0
  291. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/list.tsx +1370 -0
  292. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/queries.ts +17 -0
  293. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/types.ts +45 -0
  294. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/permissionReadme/index.tsx +1090 -0
  295. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/CreateModal.tsx +25 -0
  296. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/EditModal.tsx +28 -0
  297. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/ResourceDetailDrawer.tsx +177 -0
  298. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/modal.tsx +230 -0
  299. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/index.ts +2 -0
  300. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/list.tsx +250 -0
  301. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/queries.ts +10 -0
  302. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/types.ts +9 -0
  303. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/CreateModal.tsx +30 -0
  304. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/EditModal.tsx +47 -0
  305. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/RoleDetailDrawer.tsx +66 -0
  306. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/modal.tsx +300 -0
  307. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/hooks/useRolePage.ts +35 -0
  308. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/index.ts +1 -0
  309. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/list.tsx +405 -0
  310. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/queries.ts +8 -0
  311. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/types.ts +8 -0
  312. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/create-modal.tsx +17 -0
  313. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/edit-modal.tsx +19 -0
  314. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/form-modal.tsx +194 -0
  315. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/index.ts +5 -0
  316. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/role-tag.tsx +48 -0
  317. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/show-drawer.tsx +145 -0
  318. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/index.ts +1 -0
  319. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/list.tsx +377 -0
  320. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/queries.ts +14 -0
  321. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/setupTests.ts +5 -0
  322. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/styles/antd.css +132 -0
  323. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/styles/fc.css +58 -0
  324. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/styles/index.css +128 -0
  325. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/styles/show-drawer.module.css +18 -0
  326. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/styles/show-page.module.css +21 -0
  327. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/types/audit-log.ts +1 -0
  328. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/types/index.ts +3 -0
  329. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/types/role.ts +7 -0
  330. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/types/user.ts +1 -0
  331. package/src/lib/application/files/gadmin2-game-angle-demo/web/src/vite-env.d.ts +13 -0
  332. package/src/lib/application/files/gadmin2-game-angle-demo/web/tsconfig.json +28 -0
  333. package/src/lib/application/files/gadmin2-game-angle-demo/web/vite.config.ts +48 -0
  334. package/src/lib/application/files/gadmin2-game-angle-demo/web/yarn.lock +9482 -0
  335. package/src/lib/class/class.schema.d.ts +32 -0
  336. package/src/lib/class/files/js/__name__.js +1 -0
  337. package/src/lib/class/files/js/__name__.spec.js +7 -0
  338. package/src/lib/class/files/ts/__name__.spec.ts +7 -0
  339. package/src/lib/class/files/ts/__name__.ts +1 -0
  340. package/src/lib/client-app/angular/angular.schema.d.ts +32 -0
  341. package/src/lib/client-app/angular/files/angular.constants.ts +4 -0
  342. package/src/lib/client-app/angular/files/angular.module.ts +41 -0
  343. package/src/lib/client-app/angular/files/angular.providers.ts +27 -0
  344. package/src/lib/client-app/angular/files/angular.utils.ts +19 -0
  345. package/src/lib/client-app/angular/files/interfaces/angular-options.interface.ts +87 -0
  346. package/src/lib/client-app/angular/files/loaders/abstract.loader.ts +16 -0
  347. package/src/lib/client-app/angular/files/loaders/express.loader.ts +25 -0
  348. package/src/lib/client-app/angular/files/loaders/fastify.loader.ts +34 -0
  349. package/src/lib/client-app/angular/files/loaders/noop.loader.ts +12 -0
  350. package/src/lib/configuration/configuration.schema.d.ts +18 -0
  351. package/src/lib/configuration/files/js/nest-cli.json +6 -0
  352. package/src/lib/configuration/files/ts/nest-cli.json +5 -0
  353. package/src/lib/controller/controller.schema.d.ts +45 -0
  354. package/src/lib/controller/files/js/__name__.controller.js +4 -0
  355. package/src/lib/controller/files/js/__name__.controller.spec.js +18 -0
  356. package/src/lib/controller/files/ts/__name__.controller.spec.ts +18 -0
  357. package/src/lib/controller/files/ts/__name__.controller.ts +137 -0
  358. package/src/lib/decorator/decorator.schema.d.ts +24 -0
  359. package/src/lib/decorator/files/js/__name__.decorator.js +3 -0
  360. package/src/lib/decorator/files/ts/__name__.decorator.ts +3 -0
  361. package/src/lib/filter/files/js/__name__.filter.js +6 -0
  362. package/src/lib/filter/files/js/__name__.filter.spec.js +7 -0
  363. package/src/lib/filter/files/ts/__name__.filter.spec.ts +7 -0
  364. package/src/lib/filter/files/ts/__name__.filter.ts +6 -0
  365. package/src/lib/filter/filter.schema.d.ts +28 -0
  366. package/src/lib/gateway/files/js/__name__.gateway.js +9 -0
  367. package/src/lib/gateway/files/js/__name__.gateway.spec.js +18 -0
  368. package/src/lib/gateway/files/ts/__name__.gateway.spec.ts +18 -0
  369. package/src/lib/gateway/files/ts/__name__.gateway.ts +9 -0
  370. package/src/lib/gateway/gateway.schema.d.ts +36 -0
  371. package/src/lib/guard/files/js/__name__.guard.js +8 -0
  372. package/src/lib/guard/files/js/__name__.guard.spec.js +7 -0
  373. package/src/lib/guard/files/ts/__name__.guard.spec.ts +7 -0
  374. package/src/lib/guard/files/ts/__name__.guard.ts +11 -0
  375. package/src/lib/guard/guard.schema.d.ts +28 -0
  376. package/src/lib/interceptor/files/js/__name__.interceptor.js +8 -0
  377. package/src/lib/interceptor/files/js/__name__.interceptor.spec.js +7 -0
  378. package/src/lib/interceptor/files/ts/default/__name__.interceptor.spec.ts +7 -0
  379. package/src/lib/interceptor/files/ts/default/__name__.interceptor.ts +9 -0
  380. package/src/lib/interceptor/files/ts/generated/__name__.interceptor.spec.ts +7 -0
  381. package/src/lib/interceptor/files/ts/generated/__name__.interceptor.ts +13 -0
  382. package/src/lib/interceptor/interceptor.schema.d.ts +35 -0
  383. package/src/lib/interface/files/__name__.interface.ts +1 -0
  384. package/src/lib/interface/interface.schema.d.ts +20 -0
  385. package/src/lib/library/files/js/.babelrc +4 -0
  386. package/src/lib/library/files/js/jsconfig.json +9 -0
  387. package/src/lib/library/files/js/src/__name__.module.js +8 -0
  388. package/src/lib/library/files/js/src/__name__.service.js +4 -0
  389. package/src/lib/library/files/js/src/__name__.service.spec.js +18 -0
  390. package/src/lib/library/files/js/src/index.js +2 -0
  391. package/src/lib/library/files/ts/src/__name__.module.ts +8 -0
  392. package/src/lib/library/files/ts/src/__name__.service.spec.ts +18 -0
  393. package/src/lib/library/files/ts/src/__name__.service.ts +4 -0
  394. package/src/lib/library/files/ts/src/index.ts +2 -0
  395. package/src/lib/library/files/ts/tsconfig.lib.json +9 -0
  396. package/src/lib/library/library.schema.d.ts +24 -0
  397. package/src/lib/middleware/files/js/__name__.middleware.js +8 -0
  398. package/src/lib/middleware/files/js/__name__.middleware.spec.js +7 -0
  399. package/src/lib/middleware/files/ts/__name__.middleware.spec.ts +7 -0
  400. package/src/lib/middleware/files/ts/__name__.middleware.ts +8 -0
  401. package/src/lib/middleware/middleware.schema.d.ts +28 -0
  402. package/src/lib/module/files/js/__name__.module.js +4 -0
  403. package/src/lib/module/files/ts/__name__.module.ts +4 -0
  404. package/src/lib/module/module.schema.d.ts +40 -0
  405. package/src/lib/pipe/files/js/__name__.pipe.js +8 -0
  406. package/src/lib/pipe/files/js/__name__.pipe.spec.js +7 -0
  407. package/src/lib/pipe/files/ts/__name__.pipe.spec.ts +7 -0
  408. package/src/lib/pipe/files/ts/__name__.pipe.ts +8 -0
  409. package/src/lib/pipe/pipe.schema.d.ts +28 -0
  410. package/src/lib/prisma-resource/files/ts/__name__.controller.spec.ts +20 -0
  411. package/src/lib/prisma-resource/files/ts/__name__.controller.ts +63 -0
  412. package/src/lib/prisma-resource/files/ts/__name__.module.ts +9 -0
  413. package/src/lib/prisma-resource/files/ts/__name__.service.spec.ts +18 -0
  414. package/src/lib/prisma-resource/files/ts/__name__.service.ts +28 -0
  415. package/src/lib/prisma-resource/files/ts/dto/create-__name@singular__.dto.ts +1 -0
  416. package/src/lib/prisma-resource/files/ts/dto/create-__name@singular__.input.ts +7 -0
  417. package/src/lib/prisma-resource/files/ts/dto/update-__name@singular__.dto.ts +6 -0
  418. package/src/lib/prisma-resource/files/ts/dto/update-__name@singular__.input.ts +13 -0
  419. package/src/lib/prisma-resource/files/ts/entities/__name@singular@ent__.ts +7 -0
  420. package/src/lib/prisma-resource/prisma-resource.schema.d.ts +57 -0
  421. package/src/lib/provider/files/js/__name__.js +4 -0
  422. package/src/lib/provider/files/js/__name__.spec.js +18 -0
  423. package/src/lib/provider/files/ts/__name__.spec.ts +18 -0
  424. package/src/lib/provider/files/ts/__name__.ts +4 -0
  425. package/src/lib/provider/provider.schema.d.ts +48 -0
  426. package/src/lib/resolver/files/js/__name__.resolver.js +4 -0
  427. package/src/lib/resolver/files/js/__name__.resolver.spec.js +18 -0
  428. package/src/lib/resolver/files/ts/__name__.resolver.spec.ts +18 -0
  429. package/src/lib/resolver/files/ts/__name__.resolver.ts +4 -0
  430. package/src/lib/resolver/resolver.schema.d.ts +36 -0
  431. package/src/lib/resource/files/ts/__name__.controller.spec.ts +20 -0
  432. package/src/lib/resource/files/ts/__name__.controller.ts +63 -0
  433. package/src/lib/resource/files/ts/__name__.gateway.spec.ts +19 -0
  434. package/src/lib/resource/files/ts/__name__.gateway.ts +34 -0
  435. package/src/lib/resource/files/ts/__name__.graphql +24 -0
  436. package/src/lib/resource/files/ts/__name__.module.ts +9 -0
  437. package/src/lib/resource/files/ts/__name__.resolver.spec.ts +19 -0
  438. package/src/lib/resource/files/ts/__name__.resolver.ts +60 -0
  439. package/src/lib/resource/files/ts/__name__.service.spec.ts +18 -0
  440. package/src/lib/resource/files/ts/__name__.service.ts +28 -0
  441. package/src/lib/resource/files/ts/dto/create-__name@singular__.dto.ts +1 -0
  442. package/src/lib/resource/files/ts/dto/create-__name@singular__.input.ts +7 -0
  443. package/src/lib/resource/files/ts/dto/update-__name@singular__.dto.ts +6 -0
  444. package/src/lib/resource/files/ts/dto/update-__name@singular__.input.ts +13 -0
  445. package/src/lib/resource/files/ts/entities/__name@singular@ent__.ts +7 -0
  446. package/src/lib/resource/resource.schema.d.ts +57 -0
  447. package/src/lib/service/files/js/__name__.service.js +4 -0
  448. package/src/lib/service/files/js/__name__.service.spec.js +18 -0
  449. package/src/lib/service/files/ts/__name__.service.spec.ts +18 -0
  450. package/src/lib/service/files/ts/__name__.service.ts +4 -0
  451. package/src/lib/service/service.schema.d.ts +44 -0
  452. package/src/lib/sub-app/files/js/.babelrc +4 -0
  453. package/src/lib/sub-app/files/js/index.js +2 -0
  454. package/src/lib/sub-app/files/js/jsconfig.json +10 -0
  455. package/src/lib/sub-app/files/js/src/app.controller.js +15 -0
  456. package/src/lib/sub-app/files/js/src/app.controller.spec.js +22 -0
  457. package/src/lib/sub-app/files/js/src/app.module.js +10 -0
  458. package/src/lib/sub-app/files/js/src/app.service.js +8 -0
  459. package/src/lib/sub-app/files/js/src/main.js +8 -0
  460. package/src/lib/sub-app/files/js/test/app.e2e-spec.js +23 -0
  461. package/src/lib/sub-app/files/js/test/jest-e2e.json +5 -0
  462. package/src/lib/sub-app/files/ts/src/__name__.controller.spec.ts +22 -0
  463. package/src/lib/sub-app/files/ts/src/__name__.controller.ts +12 -0
  464. package/src/lib/sub-app/files/ts/src/__name__.module.ts +10 -0
  465. package/src/lib/sub-app/files/ts/src/__name__.service.ts +8 -0
  466. package/src/lib/sub-app/files/ts/src/main.ts +8 -0
  467. package/src/lib/sub-app/files/ts/test/app.e2e-spec.ts +24 -0
  468. package/src/lib/sub-app/files/ts/test/jest-e2e.json +9 -0
  469. package/src/lib/sub-app/files/ts/tsconfig.app.json +9 -0
  470. package/src/lib/sub-app/sub-app.schema.d.ts +21 -0
  471. package/src/lib/sub-app/workspace/js/.babelrc +4 -0
  472. package/src/lib/sub-app/workspace/js/index.js +2 -0
  473. package/src/lib/sub-app/workspace/js/jsconfig.json +10 -0
  474. package/src/lib/sub-app/workspace/ts/tsconfig.app.json +9 -0
@@ -0,0 +1,1370 @@
1
+ import React, {
2
+ useCallback,
3
+ useEffect,
4
+ useMemo,
5
+ useRef,
6
+ useState,
7
+ } from 'react';
8
+ import { DeleteButton, EditButton, useTable } from '@refinedev/antd';
9
+ import { useGetIdentity } from '@refinedev/core';
10
+ import {
11
+ Table,
12
+ Button,
13
+ Space,
14
+ Tooltip,
15
+ Tag,
16
+ Alert,
17
+ Modal,
18
+ message,
19
+ Tabs,
20
+ } from 'antd';
21
+ import {
22
+ SaveOutlined,
23
+ UndoOutlined,
24
+ HolderOutlined,
25
+ RightOutlined,
26
+ DownOutlined,
27
+ PlusOutlined,
28
+ EyeOutlined,
29
+ TeamOutlined,
30
+ CodeOutlined,
31
+ } from '@ant-design/icons';
32
+ import {
33
+ DndContext,
34
+ closestCenter,
35
+ KeyboardSensor,
36
+ PointerSensor,
37
+ useSensor,
38
+ useSensors,
39
+ DragEndEvent,
40
+ DragOverEvent,
41
+ } from '@dnd-kit/core';
42
+ import {
43
+ SortableContext,
44
+ arrayMove,
45
+ sortableKeyboardCoordinates,
46
+ useSortable,
47
+ verticalListSortingStrategy,
48
+ } from '@dnd-kit/sortable';
49
+ import { CSS } from '@dnd-kit/utilities';
50
+ import { restrictToVerticalAxis } from '@dnd-kit/modifiers';
51
+
52
+ import { customRequest } from '@/helpers/http';
53
+
54
+ import { AssignRolesModal } from './Components/AssignRolesModal';
55
+ import { EditPageModal } from './Components/EditPageModal';
56
+ import { CreatePageModal } from './Components/CreatePageModal';
57
+ import { PageDetailDrawer } from './Components/PageDetailDrawer';
58
+ import type {
59
+ PageMenuTreeNode,
60
+ PageResourceAssignment,
61
+ PageResourcePermissionSummary,
62
+ ResourceDefinition,
63
+ } from './types';
64
+ import { usePageManagement } from './hooks/usePageManagement';
65
+ import { useTranslation } from 'react-i18next';
66
+ import { SqlModal, generatePageSql } from '../../components/SqlModal';
67
+
68
+ const RESOURCE_NAME_DISPLAY_TRUNCATION_LIMIT = 40;
69
+
70
+ // Sparse number gap for sortOrder (allows inserting items between existing ones)
71
+ const SORT_ORDER_GAP = 10000;
72
+
73
+ // API function for updating page order (sortOrder and parentId)
74
+ const updatePageOrder = async (
75
+ pageId: number,
76
+ updateData: { sortOrder?: number; parentId?: number | null },
77
+ ): Promise<any> => {
78
+ return customRequest(`page/updateUnique/${pageId}`, 'PATCH', updateData);
79
+ };
80
+
81
+ const safelyConvertToNumber = (value: unknown): number | null => {
82
+ if (typeof value === 'number' && !Number.isNaN(value)) {
83
+ return value;
84
+ }
85
+ if (typeof value === 'string' && value.trim().length > 0) {
86
+ const parsedNumericValue = Number(value);
87
+ return Number.isNaN(parsedNumericValue) ? null : parsedNumericValue;
88
+ }
89
+ return null;
90
+ };
91
+
92
+ const extractPermissionActionsFromAssociation = (
93
+ associationRecord: any,
94
+ resourceRecord: any,
95
+ ): string[] => {
96
+ const aggregatedPermissionActions = new Set<string>();
97
+
98
+ const associationActions =
99
+ associationRecord?.actions ??
100
+ associationRecord?.actionList ??
101
+ associationRecord?.permissions;
102
+
103
+ if (Array.isArray(associationActions)) {
104
+ associationActions.forEach((action: any) => {
105
+ if (typeof action === 'string' && action) {
106
+ aggregatedPermissionActions.add(action);
107
+ } else if (typeof action === 'object' && action?.name) {
108
+ aggregatedPermissionActions.add(action.name);
109
+ } else if (typeof action === 'object' && action?.code) {
110
+ aggregatedPermissionActions.add(action.code);
111
+ }
112
+ });
113
+ } else if (typeof associationActions === 'string') {
114
+ associationActions
115
+ .split(',')
116
+ .map((action: string) => action.trim())
117
+ .filter(Boolean)
118
+ .forEach((action) => aggregatedPermissionActions.add(action));
119
+ }
120
+
121
+ return Array.from(aggregatedPermissionActions);
122
+ };
123
+
124
+ // Draggable row component for dnd-kit
125
+ interface DraggableRowProps extends React.HTMLAttributes<HTMLTableRowElement> {
126
+ 'data-row-key': string;
127
+ }
128
+
129
+ const DraggableRow: React.FC<DraggableRowProps> = ({ children, ...props }) => {
130
+ const id = props['data-row-key'];
131
+ const {
132
+ attributes,
133
+ listeners,
134
+ setNodeRef,
135
+ transform,
136
+ transition,
137
+ isDragging,
138
+ } = useSortable({
139
+ id,
140
+ });
141
+
142
+ const style: React.CSSProperties = {
143
+ ...props.style,
144
+ transform: CSS.Transform.toString(transform && { ...transform, scaleY: 1 }),
145
+ transition: transition ?? 'transform 200ms ease',
146
+ ...(isDragging
147
+ ? {
148
+ position: 'relative',
149
+ zIndex: 9999,
150
+ background: '#bae0ff',
151
+ boxShadow: '0 8px 24px rgba(22, 119, 255, 0.25)',
152
+ borderLeft: '3px solid #1677ff',
153
+ opacity: 0.95,
154
+ outline: '1px solid #1677ff',
155
+ }
156
+ : {}),
157
+ };
158
+
159
+ return (
160
+ <tr {...props} ref={setNodeRef} style={style} {...attributes}>
161
+ {React.Children.map(children, (child) => {
162
+ if ((child as React.ReactElement).key === 'drag-handle') {
163
+ return React.cloneElement(child as React.ReactElement, {
164
+ children: (
165
+ <HolderOutlined
166
+ {...listeners}
167
+ style={{ cursor: 'grab', color: '#999', touchAction: 'none' }}
168
+ />
169
+ ),
170
+ });
171
+ }
172
+ return child;
173
+ })}
174
+ </tr>
175
+ );
176
+ };
177
+
178
+ export const PageManagementListPage: React.FC = () => {
179
+ const { i18n } = useTranslation();
180
+ const { data: identity } = useGetIdentity<any>();
181
+ const { tableProps } = useTable({
182
+ resource: 'page',
183
+ pagination: {
184
+ pageSize: 20,
185
+ },
186
+ });
187
+
188
+ const {
189
+ pageListData,
190
+ refetchPageList,
191
+ pageListRequestQuery,
192
+ availableResourcesData,
193
+ refetchAvailableResources,
194
+ resourceListRequestQuery,
195
+ pageResourceAssociationsData,
196
+ refetchPageResourceAssociations,
197
+ pageResourceAssociationRequestQuery,
198
+ } = usePageManagement();
199
+
200
+ const resourceLookupByIdMap = useMemo<
201
+ Record<number, ResourceDefinition>
202
+ >(() => {
203
+ const resourcesArray: any[] = Array.isArray(availableResourcesData?.data)
204
+ ? availableResourcesData.data
205
+ : [];
206
+ const lookupMap: Record<number, ResourceDefinition> = {};
207
+
208
+ resourcesArray.forEach((resource: any) => {
209
+ const resourceId = safelyConvertToNumber(resource?.id);
210
+ if (resourceId !== null) {
211
+ lookupMap[resourceId] = {
212
+ id: resourceId,
213
+ code: resource?.code ?? String(resourceId),
214
+ name: resource?.name || resource?.code || `Resource ${resourceId}`,
215
+ description: resource?.description,
216
+ type: resource?.type,
217
+ };
218
+ }
219
+ });
220
+
221
+ return lookupMap;
222
+ }, [availableResourcesData]);
223
+
224
+ const availableResourcesListForModal = useMemo<ResourceDefinition[]>(() => {
225
+ return Object.values(resourceLookupByIdMap);
226
+ }, [resourceLookupByIdMap]);
227
+
228
+ const pageMenuTreeOptionsData = useMemo<PageMenuTreeNode[]>(() => {
229
+ const pagesArray: any[] = Array.isArray(pageListData?.data)
230
+ ? pageListData.data
231
+ : [];
232
+ const nodeMapByPageId = new Map<
233
+ number,
234
+ { treeNode: PageMenuTreeNode; parentPageId: number | null }
235
+ >();
236
+
237
+ pagesArray.forEach((page: any) => {
238
+ const pageId = safelyConvertToNumber(
239
+ page?.id ?? page?.pageId ?? page?.page_id,
240
+ );
241
+ if (pageId === null) {
242
+ return;
243
+ }
244
+
245
+ const parentPageId =
246
+ safelyConvertToNumber(
247
+ page?.parentId ?? page?.parent_id ?? page?.parent?.id,
248
+ ) ?? null;
249
+ const pageDisplayTitle = page?.name || page?.code || `Page ${pageId}`;
250
+
251
+ nodeMapByPageId.set(pageId, {
252
+ treeNode: {
253
+ title: pageDisplayTitle,
254
+ value: String(pageId),
255
+ key: String(pageId),
256
+ children: [],
257
+ },
258
+ parentPageId,
259
+ });
260
+ });
261
+
262
+ const rootLevelNodes: PageMenuTreeNode[] = [];
263
+
264
+ nodeMapByPageId.forEach(({ treeNode, parentPageId }) => {
265
+ if (parentPageId !== null && nodeMapByPageId.has(parentPageId)) {
266
+ nodeMapByPageId.get(parentPageId)?.treeNode.children?.push(treeNode);
267
+ } else {
268
+ rootLevelNodes.push(treeNode);
269
+ }
270
+ });
271
+
272
+ const sortTreeNodesAlphabetically = (nodes: PageMenuTreeNode[]) => {
273
+ nodes.sort((nodeA, nodeB) => {
274
+ const titleA =
275
+ typeof nodeA.title === 'string' ? nodeA.title : String(nodeA.key);
276
+ const titleB =
277
+ typeof nodeB.title === 'string' ? nodeB.title : String(nodeB.key);
278
+ return titleA.localeCompare(titleB);
279
+ });
280
+ nodes.forEach((node) => {
281
+ if (node.children && node.children.length) {
282
+ sortTreeNodesAlphabetically(node.children);
283
+ }
284
+ });
285
+ };
286
+
287
+ const removeEmptyChildrenArrays = (
288
+ nodes: PageMenuTreeNode[],
289
+ ): PageMenuTreeNode[] =>
290
+ nodes.map((node) => {
291
+ if (node.children && node.children.length) {
292
+ return {
293
+ ...node,
294
+ children: removeEmptyChildrenArrays(node.children),
295
+ };
296
+ }
297
+ const { children, ...nodeWithoutChildren } = node;
298
+ return nodeWithoutChildren as PageMenuTreeNode;
299
+ });
300
+
301
+ sortTreeNodesAlphabetically(rootLevelNodes);
302
+ return removeEmptyChildrenArrays(rootLevelNodes);
303
+ }, [pageListData]);
304
+
305
+ const pageResourcePermissionSummaryMap = useMemo<
306
+ Record<number, PageResourcePermissionSummary>
307
+ >(() => {
308
+ const associationsArray: any[] = Array.isArray(
309
+ pageResourceAssociationsData?.data,
310
+ )
311
+ ? pageResourceAssociationsData.data
312
+ : [];
313
+ const summaryMapByPageId: Record<number, PageResourcePermissionSummary> =
314
+ {};
315
+
316
+ associationsArray.forEach((association: any) => {
317
+ const pageId = safelyConvertToNumber(association?.pageId);
318
+ const resourceId = safelyConvertToNumber(association?.resourceId);
319
+
320
+ if (pageId === null || resourceId === null) {
321
+ return;
322
+ }
323
+
324
+ if (!summaryMapByPageId[pageId]) {
325
+ summaryMapByPageId[pageId] = {
326
+ resourceIds: [],
327
+ resourceNames: [],
328
+ allPermissionActions: [],
329
+ };
330
+ }
331
+
332
+ const pageSummary = summaryMapByPageId[pageId];
333
+
334
+ if (!pageSummary.resourceIds.includes(resourceId)) {
335
+ pageSummary.resourceIds.push(resourceId);
336
+ }
337
+
338
+ const resourceRecord =
339
+ association?.resource ?? resourceLookupByIdMap[resourceId];
340
+ const resourceDisplayName =
341
+ resourceRecord?.name ||
342
+ resourceRecord?.code ||
343
+ `Resource ${resourceId}`;
344
+
345
+ if (
346
+ resourceDisplayName &&
347
+ !pageSummary.resourceNames.includes(resourceDisplayName)
348
+ ) {
349
+ pageSummary.resourceNames.push(resourceDisplayName);
350
+ }
351
+
352
+ extractPermissionActionsFromAssociation(
353
+ association,
354
+ resourceRecord,
355
+ ).forEach((permissionAction) => {
356
+ if (
357
+ permissionAction &&
358
+ !pageSummary.allPermissionActions.includes(permissionAction)
359
+ ) {
360
+ pageSummary.allPermissionActions.push(permissionAction);
361
+ }
362
+ });
363
+ });
364
+
365
+ return summaryMapByPageId;
366
+ }, [pageResourceAssociationsData, resourceLookupByIdMap]);
367
+
368
+ const getPageResourceAssignmentsForModal = useCallback(
369
+ (pageId: number): PageResourceAssignment[] => {
370
+ console.log(
371
+ 'Getting resource assignments for page ID:',
372
+ pageId,
373
+ pageResourceAssociationsData,
374
+ );
375
+ const associationsArray: any[] = Array.isArray(
376
+ pageResourceAssociationsData?.data,
377
+ )
378
+ ? pageResourceAssociationsData.data
379
+ : [];
380
+
381
+ const pageAssignments: PageResourceAssignment[] = [];
382
+
383
+ associationsArray.forEach((association: any) => {
384
+ const associationPageId = safelyConvertToNumber(association?.pageId);
385
+ const resourceId = safelyConvertToNumber(association?.resourceId);
386
+
387
+ if (associationPageId !== pageId || resourceId === null) {
388
+ return;
389
+ }
390
+
391
+ const resourceRecord =
392
+ association?.resource ?? resourceLookupByIdMap[resourceId];
393
+ const resourceDisplayName =
394
+ resourceRecord?.name ||
395
+ resourceRecord?.code ||
396
+ `Resource ${resourceId}`;
397
+
398
+ pageAssignments.push({
399
+ resourceId,
400
+ resourceName: resourceDisplayName,
401
+ assignedPermissions: extractPermissionActionsFromAssociation(
402
+ association,
403
+ resourceRecord,
404
+ ),
405
+ });
406
+ });
407
+
408
+ return pageAssignments;
409
+ },
410
+ [pageResourceAssociationsData, resourceLookupByIdMap],
411
+ );
412
+
413
+ const [activeModalState, setActiveModalState] = useState<{
414
+ modalType: 'view' | 'edit' | 'create' | null;
415
+ targetPageId: number | null;
416
+ defaultParentId?: number | null;
417
+ defaultPathPrefix?: string;
418
+ }>({
419
+ modalType: null,
420
+ targetPageId: null,
421
+ defaultParentId: null,
422
+ defaultPathPrefix: '',
423
+ });
424
+
425
+ // State for draggable table
426
+ const [pendingChanges, setPendingChanges] = useState<
427
+ Map<number, { sortOrder?: number; parentId?: number | null }>
428
+ >(new Map());
429
+ const [isSavingOrder, setIsSavingOrder] = useState(false);
430
+
431
+ // State for tree expand/collapse
432
+ const [expandedKeys, setExpandedKeys] = useState<Set<number>>(new Set());
433
+
434
+ // State for detail drawer
435
+ const [drawerPage, setDrawerPage] = useState<any>(null);
436
+
437
+ // State for assign roles modal
438
+ const [assignRolesTarget, setAssignRolesTarget] = useState<{
439
+ pageId: number;
440
+ pageName: string;
441
+ } | null>(null);
442
+
443
+ // State for active tab
444
+ const [activeTab, setActiveTab] = useState<string>('regular');
445
+
446
+ // State for SQL modal
447
+ const [sqlModal, setSqlModal] = useState<{
448
+ open: boolean;
449
+ title: string;
450
+ sql: string;
451
+ }>({ open: false, title: '', sql: '' });
452
+
453
+ const handleShowSql = useCallback(
454
+ (record: any, hasChildren: boolean) => {
455
+ const pagesArray: any[] = Array.isArray(pageListData?.data)
456
+ ? pageListData.data
457
+ : [];
458
+
459
+ // Build pageResources for the given page
460
+ const buildPageResources = (pageId: number) => {
461
+ const associationsArray: any[] = Array.isArray(
462
+ pageResourceAssociationsData?.data,
463
+ )
464
+ ? pageResourceAssociationsData.data
465
+ : [];
466
+ return associationsArray
467
+ .filter(
468
+ (assoc: any) => safelyConvertToNumber(assoc?.pageId) === pageId,
469
+ )
470
+ .map((assoc: any) => {
471
+ const resourceId = safelyConvertToNumber(assoc?.resourceId);
472
+ // Prefer nested resource object, then fall back to the id-keyed lookup map (which includes code).
473
+ // The final fallback `String(resourceId)` should never be reached if availableResourcesData is loaded.
474
+ const resourceRecord =
475
+ assoc?.resource ??
476
+ (resourceId !== null ? resourceLookupByIdMap[resourceId] : null);
477
+ const resourceCode =
478
+ resourceRecord?.code ??
479
+ (resourceId !== null ? String(resourceId) : 'unknown');
480
+ const resourceName =
481
+ resourceRecord?.name ||
482
+ resourceRecord?.code ||
483
+ `Resource ${resourceId}`;
484
+ const actions = extractPermissionActionsFromAssociation(
485
+ assoc,
486
+ resourceRecord,
487
+ );
488
+ return { resourceCode, resourceName, actions };
489
+ });
490
+ };
491
+
492
+ const pageResources = buildPageResources(record.id);
493
+
494
+ // Collect child pages if this is a parent
495
+ const children: Array<{
496
+ page: any;
497
+ pageResources: Array<{
498
+ resourceCode: string;
499
+ resourceName: string;
500
+ actions: string[];
501
+ }>;
502
+ }> = [];
503
+ if (hasChildren) {
504
+ const childPages = pagesArray.filter(
505
+ (p: any) =>
506
+ safelyConvertToNumber(p?.parentId ?? p?.parent_id) === record.id,
507
+ );
508
+ for (const child of childPages) {
509
+ const childId = safelyConvertToNumber(child?.id);
510
+ if (childId === null) continue;
511
+ children.push({
512
+ page: child,
513
+ pageResources: buildPageResources(childId),
514
+ });
515
+ }
516
+ }
517
+
518
+ // Resolve parent's code from the in-memory page list so the SQL uses a
519
+ // portable subquery (SELECT id … WHERE code = '…') instead of a raw
520
+ // numeric parentId that differs between environments.
521
+ const parentId = safelyConvertToNumber(
522
+ record?.parentId ?? record?.parent_id,
523
+ );
524
+ const parentPage =
525
+ parentId !== null
526
+ ? pagesArray.find(
527
+ (p: any) => safelyConvertToNumber(p?.id) === parentId,
528
+ )
529
+ : null;
530
+ const recordWithParentCode = {
531
+ ...record,
532
+ parentCode: parentPage?.code ?? null,
533
+ };
534
+
535
+ const sql = generatePageSql(
536
+ recordWithParentCode,
537
+ pageResources,
538
+ children,
539
+ { authorId: identity?.userid, authorName: identity?.username },
540
+ );
541
+ setSqlModal({ open: true, title: `SQL — Page: ${record.name}`, sql });
542
+ },
543
+ [pageListData, pageResourceAssociationsData, resourceLookupByIdMap],
544
+ );
545
+
546
+ // Ref for expand button click/double-click disambiguation
547
+ const expandClickTimer = useRef<number | null>(null);
548
+
549
+ const refreshAllPageRelatedData = useCallback(() => {
550
+ refetchPageList(pageListRequestQuery ?? {});
551
+ refetchAvailableResources(resourceListRequestQuery ?? {});
552
+ refetchPageResourceAssociations(pageResourceAssociationRequestQuery ?? {});
553
+ }, [
554
+ refetchPageList,
555
+ pageListRequestQuery,
556
+ refetchAvailableResources,
557
+ resourceListRequestQuery,
558
+ refetchPageResourceAssociations,
559
+ pageResourceAssociationRequestQuery,
560
+ ]);
561
+
562
+ const handleModalClose = useCallback(() => {
563
+ setActiveModalState({
564
+ modalType: null,
565
+ targetPageId: null,
566
+ defaultParentId: null,
567
+ defaultPathPrefix: '',
568
+ });
569
+ }, []);
570
+
571
+ const handleModalOperationSuccess = useCallback(() => {
572
+ handleModalClose();
573
+ refreshAllPageRelatedData();
574
+ }, [refreshAllPageRelatedData, handleModalClose]);
575
+
576
+ // Calculate new sortOrder when dropping a node
577
+ const calculateNewSortOrder = useCallback(
578
+ (siblings: any[], dropIndex: number, dragNodeId: number): number => {
579
+ // Filter out the dragged node from siblings
580
+ const filteredSiblings = siblings.filter(
581
+ (s) => safelyConvertToNumber(s.id) !== dragNodeId,
582
+ );
583
+
584
+ if (filteredSiblings.length === 0) {
585
+ // First item in this parent
586
+ return SORT_ORDER_GAP;
587
+ }
588
+
589
+ if (dropIndex === 0) {
590
+ // Dropped at the beginning
591
+ const firstSibling = filteredSiblings[0];
592
+ const firstOrder = firstSibling?.sortOrder ?? SORT_ORDER_GAP;
593
+ return Math.max(1, Math.floor(firstOrder / 2));
594
+ }
595
+
596
+ if (dropIndex >= filteredSiblings.length) {
597
+ // Dropped at the end
598
+ const lastSibling = filteredSiblings[filteredSiblings.length - 1];
599
+ const lastOrder = lastSibling?.sortOrder ?? 0;
600
+ return lastOrder + SORT_ORDER_GAP;
601
+ }
602
+
603
+ // Dropped in the middle
604
+ const prevSibling = filteredSiblings[dropIndex - 1];
605
+ const nextSibling = filteredSiblings[dropIndex];
606
+ const prevOrder = prevSibling?.sortOrder ?? 0;
607
+ const nextOrder =
608
+ nextSibling?.sortOrder ?? prevOrder + SORT_ORDER_GAP * 2;
609
+
610
+ // Calculate middle value
611
+ const newOrder = Math.floor((prevOrder + nextOrder) / 2);
612
+
613
+ // If there's no room (gap too small), we need to redistribute
614
+ if (newOrder <= prevOrder || newOrder >= nextOrder) {
615
+ // Return a value that signals we need redistribution
616
+ // For now, just use prevOrder + 1 and let batch save handle redistribution
617
+ return prevOrder + 1;
618
+ }
619
+
620
+ return newOrder;
621
+ },
622
+ [],
623
+ );
624
+
625
+ // Toggle expand/collapse for a node
626
+ const handleToggleExpand = useCallback((pageId: number) => {
627
+ setExpandedKeys((prev) => {
628
+ const newSet = new Set(prev);
629
+ if (newSet.has(pageId)) {
630
+ newSet.delete(pageId);
631
+ } else {
632
+ newSet.add(pageId);
633
+ }
634
+ return newSet;
635
+ });
636
+ }, []);
637
+
638
+ // Separate regular pages and virtual pages
639
+ const { regularPagesData, virtualPagesData } = useMemo(() => {
640
+ const pagesArray: any[] = Array.isArray(pageListData?.data)
641
+ ? pageListData.data
642
+ : [];
643
+ const regular: any[] = [];
644
+ const virtual: any[] = [];
645
+
646
+ pagesArray.forEach((page: any) => {
647
+ if (page.isVirtual) {
648
+ virtual.push(page);
649
+ } else {
650
+ regular.push(page);
651
+ }
652
+ });
653
+
654
+ return { regularPagesData: regular, virtualPagesData: virtual };
655
+ }, [pageListData]);
656
+
657
+ // Flatten tree data for table display (with depth info for indentation) - only for regular (non-virtual) pages
658
+ const flattenedTableData = useMemo(() => {
659
+ const nodeMapById = new Map<number, any>();
660
+
661
+ // First pass: create all nodes with pending changes applied (only regular pages)
662
+ regularPagesData.forEach((page: any) => {
663
+ const pageId = safelyConvertToNumber(page?.id);
664
+ if (pageId === null) return;
665
+
666
+ const pendingChange = pendingChanges.get(pageId);
667
+ const sortOrder = pendingChange?.sortOrder ?? page.sortOrder;
668
+ const parentId =
669
+ pendingChange?.parentId !== undefined
670
+ ? pendingChange.parentId
671
+ : (page.parentId ?? null);
672
+
673
+ nodeMapById.set(pageId, {
674
+ ...page,
675
+ id: pageId,
676
+ sortOrder,
677
+ parentId,
678
+ children: [],
679
+ });
680
+ });
681
+
682
+ // Second pass: build tree structure
683
+ const rootNodes: any[] = [];
684
+ nodeMapById.forEach((node) => {
685
+ const parentId = node.parentId;
686
+ if (parentId !== null && nodeMapById.has(parentId)) {
687
+ nodeMapById.get(parentId).children.push(node);
688
+ } else {
689
+ rootNodes.push(node);
690
+ }
691
+ });
692
+
693
+ // Sort children by sortOrder
694
+ const sortNodes = (nodes: any[]) => {
695
+ nodes.sort(
696
+ (a, b) => (a.sortOrder ?? Infinity) - (b.sortOrder ?? Infinity),
697
+ );
698
+ nodes.forEach((node) => {
699
+ if (node.children?.length > 0) {
700
+ sortNodes(node.children);
701
+ }
702
+ });
703
+ };
704
+ sortNodes(rootNodes);
705
+
706
+ // Flatten tree to array with depth info (respecting expanded state)
707
+ const result: any[] = [];
708
+ const flatten = (nodes: any[], depth: number, parentExpanded: boolean) => {
709
+ nodes.forEach((node) => {
710
+ // Only show node if its parent is expanded (or it's a root node)
711
+ if (!parentExpanded && depth > 0) return;
712
+
713
+ const { children, ...nodeWithoutChildren } = node;
714
+ const hasChildren = children?.length > 0;
715
+ const isExpanded = expandedKeys.has(node.id);
716
+
717
+ result.push({
718
+ ...nodeWithoutChildren,
719
+ _depth: depth,
720
+ _hasChildren: hasChildren,
721
+ _isExpanded: isExpanded,
722
+ _isModified: pendingChanges.has(node.id),
723
+ });
724
+
725
+ if (hasChildren) {
726
+ flatten(children, depth + 1, isExpanded);
727
+ }
728
+ });
729
+ };
730
+ flatten(rootNodes, 0, true);
731
+
732
+ return result;
733
+ }, [regularPagesData, pendingChanges, expandedKeys]);
734
+
735
+ // Get sortable item IDs for dnd-kit
736
+ const sortableIds = useMemo(() => {
737
+ return flattenedTableData.map((item) => String(item.id));
738
+ }, [flattenedTableData]);
739
+
740
+ // Live-reordered IDs during drag (for visual feedback)
741
+ const [activeSortableIds, setActiveSortableIds] = useState<string[]>([]);
742
+
743
+ // Sync activeSortableIds when base list changes (e.g. after save/refresh)
744
+ useEffect(() => {
745
+ setActiveSortableIds(sortableIds);
746
+ }, [sortableIds]);
747
+
748
+ // dnd-kit sensors
749
+ const sensors = useSensors(
750
+ useSensor(PointerSensor, {
751
+ activationConstraint: {
752
+ distance: 1,
753
+ },
754
+ }),
755
+ useSensor(KeyboardSensor, {
756
+ coordinateGetter: sortableKeyboardCoordinates,
757
+ }),
758
+ );
759
+
760
+ // Reorder the visual list live during drag for smooth feedback
761
+ const handleDragOver = useCallback((event: DragOverEvent) => {
762
+ const { active, over } = event;
763
+ if (!over || active.id === over.id) return;
764
+ setActiveSortableIds((prev) => {
765
+ const oldIndex = prev.indexOf(String(active.id));
766
+ const newIndex = prev.indexOf(String(over.id));
767
+ if (oldIndex === -1 || newIndex === -1) return prev;
768
+ return arrayMove(prev, oldIndex, newIndex);
769
+ });
770
+ }, []);
771
+
772
+ // Handle drag end for dnd-kit
773
+ const handleDragEnd = useCallback(
774
+ (event: DragEndEvent) => {
775
+ const { active, over } = event;
776
+
777
+ if (!over || active.id === over.id) return;
778
+
779
+ const draggedId = safelyConvertToNumber(active.id);
780
+ const overId = safelyConvertToNumber(over.id);
781
+
782
+ if (draggedId === null || overId === null) return;
783
+
784
+ const pagesArray: any[] = Array.isArray(pageListData?.data)
785
+ ? pageListData.data
786
+ : [];
787
+ const draggedPage = pagesArray.find(
788
+ (p) => safelyConvertToNumber(p.id) === draggedId,
789
+ );
790
+ const overPage = pagesArray.find(
791
+ (p) => safelyConvertToNumber(p.id) === overId,
792
+ );
793
+
794
+ if (!draggedPage || !overPage) return;
795
+
796
+ // Get target's parentId (with pending changes applied)
797
+ const overPendingChange = pendingChanges.get(overId);
798
+ const targetParentId =
799
+ overPendingChange?.parentId !== undefined
800
+ ? overPendingChange.parentId
801
+ : (overPage.parentId ?? null);
802
+
803
+ // Get dragged item's current parentId
804
+ const draggedPendingChange = pendingChanges.get(draggedId);
805
+ const currentParentId =
806
+ draggedPendingChange?.parentId !== undefined
807
+ ? draggedPendingChange.parentId
808
+ : (draggedPage.parentId ?? null);
809
+
810
+ // Determine new parentId - when dropping on an item, take its parentId (same level)
811
+ const newParentId = targetParentId;
812
+
813
+ // Get all siblings at the target parent level (with pending changes)
814
+ const getSiblingsWithPendingChanges = (parentId: number | null) => {
815
+ return pagesArray
816
+ .map((page) => {
817
+ const pageId = safelyConvertToNumber(page.id);
818
+ if (pageId === null) return null;
819
+ const pending = pendingChanges.get(pageId);
820
+ return {
821
+ ...page,
822
+ id: pageId,
823
+ parentId:
824
+ pending?.parentId !== undefined
825
+ ? pending.parentId
826
+ : (page.parentId ?? null),
827
+ sortOrder: pending?.sortOrder ?? page.sortOrder ?? 0,
828
+ };
829
+ })
830
+ .filter(
831
+ (page): page is NonNullable<typeof page> =>
832
+ page !== null && page.parentId === parentId,
833
+ )
834
+ .sort((a, b) => a.sortOrder - b.sortOrder);
835
+ };
836
+
837
+ const siblings = getSiblingsWithPendingChanges(newParentId);
838
+
839
+ // Find the position of the over item in siblings
840
+ const overIndex = siblings.findIndex((s) => s.id === overId);
841
+ const dragIndex = siblings.findIndex((s) => s.id === draggedId);
842
+
843
+ // Calculate drop index
844
+ let dropIndex: number;
845
+ if (dragIndex === -1) {
846
+ // Dragged item is not in this parent group (moving to new parent)
847
+ dropIndex = overIndex;
848
+ } else if (dragIndex < overIndex) {
849
+ // Moving down
850
+ dropIndex = overIndex;
851
+ } else {
852
+ // Moving up
853
+ dropIndex = overIndex;
854
+ }
855
+
856
+ // Calculate new sort order
857
+ const newSortOrder = calculateNewSortOrder(
858
+ siblings,
859
+ dropIndex,
860
+ draggedId,
861
+ );
862
+
863
+ // Check if anything changed
864
+ const parentChanged = newParentId !== currentParentId;
865
+ const orderChanged =
866
+ newSortOrder !==
867
+ (draggedPendingChange?.sortOrder ?? draggedPage.sortOrder ?? 0);
868
+
869
+ if (!parentChanged && !orderChanged) return;
870
+
871
+ // Update pending changes
872
+ setPendingChanges((prev) => {
873
+ const newChanges = new Map(prev);
874
+ const existingChange = newChanges.get(draggedId) || {};
875
+
876
+ newChanges.set(draggedId, {
877
+ ...existingChange,
878
+ ...(parentChanged && { parentId: newParentId }),
879
+ sortOrder: newSortOrder,
880
+ });
881
+
882
+ return newChanges;
883
+ });
884
+
885
+ message.info(
886
+ `Page "${draggedPage.name}" moved. Click "Save Order" to apply changes.`,
887
+ );
888
+ },
889
+ [pageListData, pendingChanges, calculateNewSortOrder],
890
+ );
891
+
892
+ // Discard all pending changes
893
+ const handleDiscardChanges = useCallback(() => {
894
+ if (pendingChanges.size === 0) return;
895
+
896
+ Modal.confirm({
897
+ title: 'Discard Changes',
898
+ content: `Are you sure you want to discard ${pendingChanges.size} pending change(s)?`,
899
+ okText: 'Discard',
900
+ okType: 'danger',
901
+ styles: { body: { padding: '16px 24px' } },
902
+ onOk: () => {
903
+ setPendingChanges(new Map());
904
+ message.success('Changes discarded');
905
+ },
906
+ });
907
+ }, [pendingChanges]);
908
+
909
+ // Save all pending changes
910
+ const handleSaveOrder = useCallback(async () => {
911
+ if (pendingChanges.size === 0) {
912
+ message.info('No changes to save');
913
+ return;
914
+ }
915
+
916
+ setIsSavingOrder(true);
917
+
918
+ try {
919
+ const updatePromises: Promise<any>[] = [];
920
+
921
+ pendingChanges.forEach((change, pageId) => {
922
+ const updateData: { sortOrder?: number; parentId?: number | null } = {};
923
+
924
+ if (change.sortOrder !== undefined) {
925
+ updateData.sortOrder = change.sortOrder;
926
+ }
927
+ if (change.parentId !== undefined) {
928
+ updateData.parentId = change.parentId;
929
+ }
930
+
931
+ if (Object.keys(updateData).length > 0) {
932
+ updatePromises.push(updatePageOrder(pageId, updateData));
933
+ }
934
+ });
935
+
936
+ await Promise.all(updatePromises);
937
+
938
+ message.success(`Successfully updated ${pendingChanges.size} page(s)`);
939
+ setPendingChanges(new Map());
940
+ refreshAllPageRelatedData();
941
+ } catch (error) {
942
+ console.error('Failed to save order:', error);
943
+ message.error('Failed to save some changes. Please try again.');
944
+ } finally {
945
+ setIsSavingOrder(false);
946
+ }
947
+ }, [pendingChanges, refreshAllPageRelatedData]);
948
+
949
+ // Build parent-children lookup for expand operations
950
+ const parentChildrenMap = useMemo(() => {
951
+ const childrenOf = new Map<number | null, number[]>(); // parentId -> childIds
952
+ for (const page of regularPagesData) {
953
+ const pageId = safelyConvertToNumber(page?.id);
954
+ if (pageId === null) continue;
955
+ const pendingChange = pendingChanges.get(pageId);
956
+ const parentId =
957
+ pendingChange?.parentId !== undefined
958
+ ? pendingChange.parentId
959
+ : (page.parentId ?? null);
960
+ if (!childrenOf.has(parentId)) childrenOf.set(parentId, []);
961
+ childrenOf.get(parentId)!.push(pageId);
962
+ }
963
+ return childrenOf;
964
+ }, [regularPagesData, pendingChanges]);
965
+
966
+ // Expand to N levels (single click = 2 levels)
967
+ const handleExpandLevels = useCallback(
968
+ (maxDepth: number) => {
969
+ const keysToExpand = new Set<number>();
970
+ const expand = (parentId: number | null, depth: number) => {
971
+ if (depth >= maxDepth) return;
972
+ const children = parentChildrenMap.get(parentId);
973
+ if (!children) return;
974
+ for (const childId of children) {
975
+ // Only expand nodes that have children
976
+ if (parentChildrenMap.has(childId)) {
977
+ keysToExpand.add(childId);
978
+ expand(childId, depth + 1);
979
+ }
980
+ }
981
+ };
982
+ expand(null, 0);
983
+ setExpandedKeys(keysToExpand);
984
+ },
985
+ [parentChildrenMap],
986
+ );
987
+
988
+ // Expand all nodes (double click)
989
+ const handleExpandAll = useCallback(() => {
990
+ // Expand every node that has children
991
+ const keysToExpand = new Set<number>();
992
+ for (const [parentId] of parentChildrenMap) {
993
+ if (parentId !== null) keysToExpand.add(parentId);
994
+ }
995
+ setExpandedKeys(keysToExpand);
996
+ }, [parentChildrenMap]);
997
+
998
+ // Collapse all nodes
999
+ const handleCollapseAll = useCallback(() => {
1000
+ setExpandedKeys(new Set());
1001
+ }, []);
1002
+
1003
+ // Common column renderers for both tables
1004
+ const renderAssignedResourcesColumn = (record: any) => {
1005
+ const permissionSummary = pageResourcePermissionSummaryMap[record.id];
1006
+
1007
+ if (!permissionSummary?.resourceNames.length) {
1008
+ return <span style={{ color: '#999' }}>No resources assigned</span>;
1009
+ }
1010
+
1011
+ const joinedResourceNames = permissionSummary.resourceNames.join(', ');
1012
+ const shouldTruncateDisplay =
1013
+ joinedResourceNames.length > RESOURCE_NAME_DISPLAY_TRUNCATION_LIMIT;
1014
+ const truncatedDisplayValue = shouldTruncateDisplay
1015
+ ? `${joinedResourceNames.slice(0, RESOURCE_NAME_DISPLAY_TRUNCATION_LIMIT)}...`
1016
+ : joinedResourceNames;
1017
+
1018
+ return (
1019
+ <Tooltip title={joinedResourceNames}>
1020
+ <span>{truncatedDisplayValue}</span>
1021
+ </Tooltip>
1022
+ );
1023
+ };
1024
+
1025
+ const renderPermissionActionsColumn = (record: any) => {
1026
+ const permissionSummary = pageResourcePermissionSummaryMap[record.id];
1027
+
1028
+ if (!permissionSummary?.allPermissionActions.length) {
1029
+ return <span style={{ color: '#999' }}>-</span>;
1030
+ }
1031
+
1032
+ return (
1033
+ <Space size={[4, 4]} wrap>
1034
+ {permissionSummary.allPermissionActions.map((permissionAction) => (
1035
+ <Tag key={`${record.id}-${permissionAction}`} color="blue">
1036
+ {permissionAction}
1037
+ </Tag>
1038
+ ))}
1039
+ </Space>
1040
+ );
1041
+ };
1042
+
1043
+ // Handle click on add child page button
1044
+ const handleAddChildPage = useCallback((parentPage: any) => {
1045
+ const parentPath = parentPage.path || '';
1046
+ const pathPrefix = parentPath.endsWith('/') ? parentPath : `${parentPath}/`;
1047
+ setActiveModalState({
1048
+ modalType: 'create',
1049
+ targetPageId: null,
1050
+ defaultParentId: parentPage.id,
1051
+ defaultPathPrefix: pathPrefix,
1052
+ });
1053
+ }, []);
1054
+
1055
+ const renderActionsColumn = (record: any, hasChildren: boolean = false) => (
1056
+ <Space>
1057
+ <Tooltip title="Add child page">
1058
+ <Button
1059
+ type="default"
1060
+ size="small"
1061
+ icon={<PlusOutlined />}
1062
+ onClick={() => handleAddChildPage(record)}
1063
+ />
1064
+ </Tooltip>
1065
+ <EditButton
1066
+ hideText
1067
+ size="small"
1068
+ recordItemId={record.id}
1069
+ onClick={() =>
1070
+ setActiveModalState({ modalType: 'edit', targetPageId: record.id })
1071
+ }
1072
+ />
1073
+ <Tooltip title="Generate SQL">
1074
+ <Button
1075
+ type="default"
1076
+ size="small"
1077
+ icon={<CodeOutlined />}
1078
+ onClick={() => handleShowSql(record, hasChildren)}
1079
+ />
1080
+ </Tooltip>
1081
+ {/* Only show delete button for leaf nodes (pages without children) */}
1082
+ {!hasChildren && (
1083
+ <>
1084
+ <Tooltip title="Assign roles">
1085
+ <Button
1086
+ type="default"
1087
+ size="small"
1088
+ icon={<TeamOutlined />}
1089
+ onClick={() =>
1090
+ setAssignRolesTarget({
1091
+ pageId: record.id,
1092
+ pageName: record.name,
1093
+ })
1094
+ }
1095
+ />
1096
+ </Tooltip>
1097
+ <Tooltip title="View details">
1098
+ <Button
1099
+ type="default"
1100
+ size="small"
1101
+ icon={<EyeOutlined />}
1102
+ onClick={() => setDrawerPage(record)}
1103
+ />
1104
+ </Tooltip>
1105
+ <DeleteButton
1106
+ hideText
1107
+ size="small"
1108
+ recordItemId={record.id}
1109
+ resource="page"
1110
+ onSuccess={() => refreshAllPageRelatedData()}
1111
+ />
1112
+ </>
1113
+ )}
1114
+ </Space>
1115
+ );
1116
+
1117
+ // Render regular pages table with drag-drop
1118
+ const renderRegularPagesTable = () => (
1119
+ <>
1120
+ <Space style={{ marginBottom: 16 }}>
1121
+ <Tooltip title="Click: expand 2 levels / Double-click: expand all">
1122
+ <Button
1123
+ onClick={() => {
1124
+ expandClickTimer.current = window.setTimeout(
1125
+ () => handleExpandLevels(1),
1126
+ 200,
1127
+ );
1128
+ }}
1129
+ onDoubleClick={() => {
1130
+ if (expandClickTimer.current)
1131
+ clearTimeout(expandClickTimer.current);
1132
+ handleExpandAll();
1133
+ }}
1134
+ >
1135
+ Expand All
1136
+ </Button>
1137
+ </Tooltip>
1138
+ <Button onClick={handleCollapseAll}>Collapse All</Button>
1139
+ {pendingChanges.size > 0 && (
1140
+ <>
1141
+ <Button
1142
+ type="primary"
1143
+ icon={<SaveOutlined />}
1144
+ onClick={handleSaveOrder}
1145
+ loading={isSavingOrder}
1146
+ >
1147
+ Save Order ({pendingChanges.size} change
1148
+ {pendingChanges.size > 1 ? 's' : ''})
1149
+ </Button>
1150
+ <Button
1151
+ icon={<UndoOutlined />}
1152
+ onClick={handleDiscardChanges}
1153
+ disabled={isSavingOrder}
1154
+ >
1155
+ Discard Changes
1156
+ </Button>
1157
+ </>
1158
+ )}
1159
+ </Space>
1160
+
1161
+ {/* Info alert about drag and drop */}
1162
+ <Alert
1163
+ message="Drag and drop rows using the handle (⋮⋮) to reorder pages. Changes are saved in batch when you click 'Save Order'."
1164
+ type="info"
1165
+ showIcon
1166
+ style={{ marginBottom: 16 }}
1167
+ closable
1168
+ />
1169
+
1170
+ {/* Table with dnd-kit drag and drop */}
1171
+ <DndContext
1172
+ sensors={sensors}
1173
+ collisionDetection={closestCenter}
1174
+ modifiers={[restrictToVerticalAxis]}
1175
+ onDragOver={handleDragOver}
1176
+ onDragEnd={handleDragEnd}
1177
+ >
1178
+ <SortableContext
1179
+ items={activeSortableIds}
1180
+ strategy={verticalListSortingStrategy}
1181
+ >
1182
+ <Table
1183
+ {...tableProps}
1184
+ rowKey="id"
1185
+ dataSource={flattenedTableData}
1186
+ pagination={false}
1187
+ components={{
1188
+ body: {
1189
+ row: DraggableRow,
1190
+ },
1191
+ }}
1192
+ >
1193
+ {/* Drag handle column */}
1194
+ <Table.Column key="drag-handle" width={50} render={() => null} />
1195
+ <Table.Column
1196
+ dataIndex="name"
1197
+ title="Page Name"
1198
+ render={(text, record: any) => (
1199
+ <span
1200
+ style={{
1201
+ paddingLeft: record._depth * 20,
1202
+ display: 'inline-flex',
1203
+ alignItems: 'center',
1204
+ }}
1205
+ >
1206
+ {record._hasChildren ? (
1207
+ <span
1208
+ onClick={(e) => {
1209
+ e.stopPropagation();
1210
+ handleToggleExpand(record.id);
1211
+ }}
1212
+ style={{
1213
+ cursor: 'pointer',
1214
+ marginRight: 8,
1215
+ display: 'inline-flex',
1216
+ alignItems: 'center',
1217
+ }}
1218
+ >
1219
+ {record._isExpanded ? (
1220
+ <DownOutlined style={{ fontSize: 10 }} />
1221
+ ) : (
1222
+ <RightOutlined style={{ fontSize: 10 }} />
1223
+ )}
1224
+ </span>
1225
+ ) : (
1226
+ <span style={{ width: 18 }} />
1227
+ )}
1228
+ {i18n.language === 'zh_CN'
1229
+ ? record.zhName || text
1230
+ : record.enName || text}
1231
+ {record._isModified && (
1232
+ <Tag color="orange" style={{ marginLeft: 8, fontSize: 10 }}>
1233
+ Modified
1234
+ </Tag>
1235
+ )}
1236
+ </span>
1237
+ )}
1238
+ />
1239
+ <Table.Column dataIndex="path" title="Page Path" />
1240
+ <Table.Column
1241
+ dataIndex="description"
1242
+ title="Description"
1243
+ ellipsis={{ showTitle: true }}
1244
+ onCell={() => ({ style: { maxWidth: 200 } })}
1245
+ />
1246
+ <Table.Column dataIndex="creator" title="Creator" />
1247
+ <Table.Column
1248
+ title="Actions"
1249
+ render={(_, record: any) =>
1250
+ renderActionsColumn(record, record._hasChildren)
1251
+ }
1252
+ />
1253
+ </Table>
1254
+ </SortableContext>
1255
+ </DndContext>
1256
+ </>
1257
+ );
1258
+
1259
+ // Render virtual pages table (simple table without drag-drop and tree structure)
1260
+ const renderVirtualPagesTable = () => (
1261
+ <Table
1262
+ rowKey="id"
1263
+ dataSource={virtualPagesData}
1264
+ pagination={{ pageSize: 20 }}
1265
+ >
1266
+ <Table.Column dataIndex="name" title="Page Name" />
1267
+ <Table.Column dataIndex="creator" title="Creator" />
1268
+ <Table.Column
1269
+ dataIndex="description"
1270
+ title="Description"
1271
+ ellipsis={{ showTitle: true }}
1272
+ onCell={() => ({ style: { maxWidth: 200 } })}
1273
+ />
1274
+ <Table.Column
1275
+ title="Actions"
1276
+ render={(_, record: any) => renderActionsColumn(record, false)}
1277
+ />
1278
+ </Table>
1279
+ );
1280
+
1281
+ return (
1282
+ <div>
1283
+ <Space style={{ marginBottom: 16 }}>
1284
+ <Button
1285
+ type="primary"
1286
+ onClick={() =>
1287
+ setActiveModalState({
1288
+ modalType: 'create',
1289
+ targetPageId: null,
1290
+ })
1291
+ }
1292
+ >
1293
+ Create Page
1294
+ </Button>
1295
+ </Space>
1296
+
1297
+ <Tabs
1298
+ activeKey={activeTab}
1299
+ onChange={setActiveTab}
1300
+ items={[
1301
+ {
1302
+ key: 'regular',
1303
+ label: `Regular Pages (${regularPagesData.length})`,
1304
+ children: renderRegularPagesTable(),
1305
+ },
1306
+ {
1307
+ key: 'virtual',
1308
+ label: `Virtual Pages (${virtualPagesData.length})`,
1309
+ children: renderVirtualPagesTable(),
1310
+ },
1311
+ ]}
1312
+ />
1313
+
1314
+ {activeModalState.modalType === 'edit' &&
1315
+ activeModalState.targetPageId && (
1316
+ <EditPageModal
1317
+ pageIdToEdit={activeModalState.targetPageId}
1318
+ onModalClose={handleModalClose}
1319
+ onPageEditSuccess={handleModalOperationSuccess}
1320
+ parentPageTreeOptions={pageMenuTreeOptionsData}
1321
+ allAvailableResources={availableResourcesListForModal}
1322
+ currentPageResourceAssignments={getPageResourceAssignmentsForModal(
1323
+ activeModalState.targetPageId,
1324
+ )}
1325
+ allPagesData={pageListData?.data || []}
1326
+ />
1327
+ )}
1328
+
1329
+ {drawerPage && (
1330
+ <PageDetailDrawer
1331
+ page={drawerPage}
1332
+ open={!!drawerPage}
1333
+ onClose={() => setDrawerPage(null)}
1334
+ />
1335
+ )}
1336
+
1337
+ {assignRolesTarget && (
1338
+ <AssignRolesModal
1339
+ pageId={assignRolesTarget.pageId}
1340
+ pageName={assignRolesTarget.pageName}
1341
+ open={!!assignRolesTarget}
1342
+ onClose={() => setAssignRolesTarget(null)}
1343
+ onSuccess={() => {
1344
+ setAssignRolesTarget(null);
1345
+ refreshAllPageRelatedData();
1346
+ }}
1347
+ />
1348
+ )}
1349
+
1350
+ {activeModalState.modalType === 'create' && (
1351
+ <CreatePageModal
1352
+ onModalClose={handleModalClose}
1353
+ onPageCreationSuccess={handleModalOperationSuccess}
1354
+ parentPageTreeOptions={pageMenuTreeOptionsData}
1355
+ allAvailableResources={availableResourcesListForModal}
1356
+ allPagesData={pageListData?.data || []}
1357
+ defaultParentId={activeModalState.defaultParentId}
1358
+ defaultPathPrefix={activeModalState.defaultPathPrefix}
1359
+ />
1360
+ )}
1361
+
1362
+ <SqlModal
1363
+ open={sqlModal.open}
1364
+ onClose={() => setSqlModal({ open: false, title: '', sql: '' })}
1365
+ title={sqlModal.title}
1366
+ sql={sqlModal.sql}
1367
+ />
1368
+ </div>
1369
+ );
1370
+ };