@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,5 @@
1
+ import React from "react";
2
+
3
+ export const renderLongColumnValue = (value: string) => {
4
+ return <div style={{ whiteSpace: "pre-wrap", wordBreak: "break-word" }}>{value}</div>;
5
+ };
@@ -0,0 +1,211 @@
1
+ import { useMemo, useRef } from "react";
2
+ import type { IResourceItem, ResourceProps } from "@refinedev/core";
3
+ import {
4
+ DashboardOutlined,
5
+ SettingOutlined,
6
+ } from "@ant-design/icons";
7
+ import { getRoutePath } from "config/routeRegistry";
8
+ import { useUserPageAccess } from "./useUserPageAccess";
9
+ import generatedResources from "generated/resources";
10
+
11
+ /**
12
+ * Dynamic Resources Hook for erp-backend/web
13
+ *
14
+ * Features:
15
+ * 1. Get user accessible page resources from backend (via useUserPageAccess)
16
+ * 2. Convert backend data to Refine's IResourceItem[] format
17
+ * 3. Auto-generate show/edit/create paths for all pages
18
+ *
19
+ * Data Flow:
20
+ * useUserPageAccess → Accessible Pages → Resources → Sider Menu
21
+ *
22
+ * Performance:
23
+ * - Uses module-level cache - computed ONCE per page load
24
+ * - Returns same reference on every call after initial computation
25
+ * - Does NOT rebuild on route navigation or component re-renders
26
+ * - Permission changes require page refresh (handled by user)
27
+ */
28
+
29
+ // Module-level cache - computed once per page load
30
+ let cachedResources: IResourceItem[] | null = null;
31
+ let isComputing = false;
32
+
33
+ // 将 snake_case 转换为 camelCase
34
+ function snakeToCamel(str: string): string {
35
+ return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
36
+ }
37
+
38
+ // Icon 映射:page.code 到 React Icon 组件
39
+ export const iconMapping: Record<string, React.ReactNode> = {
40
+ dashboard: <DashboardOutlined />,
41
+ administration: <SettingOutlined />,
42
+ };
43
+
44
+ // Pages whose children are tabs (not separate menu items)
45
+ const PAGES_WITH_TABS: string[] = [];
46
+
47
+ export const useDynamicResources = (): IResourceItem[] => {
48
+ // Use shared page access data (single call, reused below)
49
+ const { accessiblePageIds, pagesData, pageMap, isLoading, roleNames } = useUserPageAccess();
50
+
51
+ // If we already have cached resources, return immediately
52
+ if (cachedResources !== null) {
53
+ return cachedResources;
54
+ }
55
+
56
+ // Return empty array while loading (will retry on next render)
57
+ if (isLoading || !pagesData || isComputing) {
58
+ return [];
59
+ }
60
+
61
+ // Mark as computing to prevent concurrent computation
62
+ isComputing = true;
63
+
64
+ if (import.meta.env.DEV) {
65
+ console.log('[useDynamicResources] 🔨 Computing resources (first time)');
66
+ }
67
+
68
+ // Filter accessible pages and build hierarchical sorted list
69
+ const accessiblePages = pagesData.filter(page => accessiblePageIds.has(page.id));
70
+
71
+ // Group pages by parentId
72
+ const pagesByParent = new Map<number | null, typeof accessiblePages>();
73
+ accessiblePages.forEach(page => {
74
+ const parentId = page.parentId ?? null;
75
+ if (!pagesByParent.has(parentId)) {
76
+ pagesByParent.set(parentId, []);
77
+ }
78
+ pagesByParent.get(parentId)!.push(page);
79
+ });
80
+
81
+ // Sort each group by sortOrder
82
+ pagesByParent.forEach(pages => {
83
+ pages.sort((a, b) => (a.sortOrder ?? Infinity) - (b.sortOrder ?? Infinity));
84
+ });
85
+
86
+ // Build sorted list using depth-first traversal
87
+ const sortedAccessiblePages: typeof accessiblePages = [];
88
+ const visited = new Set<number>();
89
+
90
+ const addPageWithChildren = (parentId: number | null) => {
91
+ const children = pagesByParent.get(parentId) || [];
92
+ children.forEach(page => {
93
+ if (visited.has(page.id)) return;
94
+ visited.add(page.id);
95
+ sortedAccessiblePages.push(page);
96
+ addPageWithChildren(page.id);
97
+ });
98
+ };
99
+
100
+ // Start from root level (parentId = null)
101
+ addPageWithChildren(null);
102
+
103
+ // Add any orphaned pages
104
+ accessiblePages.forEach(page => {
105
+ if (!visited.has(page.id)) {
106
+ sortedAccessiblePages.push(page);
107
+ }
108
+ });
109
+
110
+ // 检测哪些父页面有"index 子页面"(子页面路径与父页面相同,即 path: "" 的 index 路由)
111
+ // 这类父页面应作为纯分组节点(不注册 list 路径),否则 Refine 会优先选中父节点
112
+ // 导致 "全部" 等 index 子菜单项无法高亮
113
+ const parentIdsWithIndexChild = new Set<number>();
114
+ accessiblePages.forEach(childPage => {
115
+ if (!childPage.parentId) return;
116
+ const childPath = getRoutePath(childPage.code);
117
+ if (!childPath) return;
118
+ const parentPage = pageMap.get(childPage.parentId);
119
+ if (!parentPage) return;
120
+ const parentPath = getRoutePath(parentPage.code);
121
+ if (childPath === parentPath) {
122
+ parentIdsWithIndexChild.add(childPage.parentId);
123
+ }
124
+ });
125
+
126
+ // Build resources
127
+ const resultResources: IResourceItem[] = [];
128
+ const addedResourceNames = new Set<string>();
129
+
130
+ sortedAccessiblePages.forEach(page => {
131
+ if (!page) return;
132
+
133
+ // Skip virtual pages
134
+ if (page.isVirtual) return;
135
+
136
+ // Skip children of pages that use tabs
137
+ if (page.parentId) {
138
+ const parentPage = pageMap.get(page.parentId);
139
+ if (parentPage && PAGES_WITH_TABS.includes(parentPage.code)) {
140
+ return;
141
+ }
142
+ }
143
+
144
+ const permissionRes = snakeToCamel(page.code);
145
+
146
+ // Avoid duplicates
147
+ if (addedResourceNames.has(permissionRes)) return;
148
+
149
+ let parentPermissionRes: string | undefined;
150
+ if (page.parentId) {
151
+ const parentPage = pageMap.get(page.parentId);
152
+ if (parentPage) {
153
+ parentPermissionRes = snakeToCamel(parentPage.code);
154
+ }
155
+ }
156
+
157
+ // 优先从 routeRegistry 获取路径
158
+ // fallback 到 page.path(用于 gadmin2 页面)
159
+ const registryPath = getRoutePath(page.code);
160
+ const dbPath = page.path
161
+ ? page.path.startsWith("/") ? page.path : `/${page.path}`
162
+ : undefined;
163
+ const normalizedPath = registryPath ?? dbPath;
164
+
165
+ // 如果该页面是"有 index 子页面的父节点",则不注册 list/show/edit/create
166
+ // 使其成为纯分组节点(SubMenu),子页面(如"全部")的路径才负责 URL 匹配与菜单高亮
167
+ const isGroupParent = parentIdsWithIndexChild.has(page.id);
168
+
169
+ // Build resource item with auto-generated CRUD paths
170
+ // Store both zhLabel/enLabel in meta; Sider resolves at render time
171
+ const resource: IResourceItem = {
172
+ name: permissionRes,
173
+ ...(!isGroupParent && normalizedPath && {
174
+ list: normalizedPath,
175
+ show: `${normalizedPath}/show/:id`,
176
+ edit: `${normalizedPath}/edit/:id`,
177
+ create: `${normalizedPath}/create`,
178
+ }),
179
+ meta: {
180
+ label: page.enName || page.code,
181
+ zhLabel: page.zhName || page.code,
182
+ enLabel: page.enName || page.code,
183
+ icon: iconMapping[page.code] || "",
184
+ parent: parentPermissionRes,
185
+ route: normalizedPath,
186
+ pageCode: page.code,
187
+ parentPageCode: page.parentId
188
+ ? pageMap.get(page.parentId)?.code
189
+ : undefined,
190
+ },
191
+ };
192
+
193
+ resultResources.push(resource);
194
+ addedResourceNames.add(permissionRes);
195
+ });
196
+
197
+ // Build final resources array with auto-crud if needed
198
+ const dynamicResources = resultResources;
199
+ const allResources = dynamicResources;
200
+
201
+ // Cache the result - will be used for all subsequent calls
202
+ cachedResources = allResources;
203
+ isComputing = false;
204
+
205
+ if (import.meta.env.DEV) {
206
+ console.log('[useDynamicResources] ✅ Resources cached. Count:', cachedResources.length);
207
+ console.log('[useDynamicResources] 📌 This reference will be reused for all future calls');
208
+ }
209
+
210
+ return cachedResources;
211
+ };
@@ -0,0 +1,33 @@
1
+ import { useEffect, useState } from "react";
2
+
3
+ import { customRequest } from "helpers/login";
4
+
5
+ export const useFetchData = (
6
+ url: string,
7
+ type: "post" | "get",
8
+ defaultQuery?: any,
9
+ disableReq?: any,
10
+ errorCallBack?: () => void
11
+ ) => {
12
+ const [data, setData] = useState<any>();
13
+ const [reqQuery, setReqQuery] = useState<any>(defaultQuery);
14
+ const [loading, setLoading] = useState<boolean>(false);
15
+ const fetchData = async (query?: any) => {
16
+ if (!url) return;
17
+ setLoading(true);
18
+ try {
19
+ const res = await customRequest(url, type, query);
20
+ setData(res);
21
+ setReqQuery(query);
22
+ } catch (error) {
23
+ console.error(error);
24
+ errorCallBack && errorCallBack();
25
+ }
26
+ setLoading(false);
27
+ };
28
+
29
+ useEffect(() => {
30
+ !disableReq && url && fetchData(defaultQuery);
31
+ }, []);
32
+ return { data, loading, fetchData, reqQuery };
33
+ };
@@ -0,0 +1,30 @@
1
+ import { useEffect, useState } from "react";
2
+
3
+ import { useFetchData } from "./useFetchData";
4
+
5
+ export interface RoleOption {
6
+ label: string;
7
+ value: string;
8
+ }
9
+
10
+ export const useRoles = () => {
11
+ const { data: rolesData, loading } = useFetchData("role/findMany", "post", {});
12
+ const [roleOptions, setRoleOptions] = useState<RoleOption[]>([]);
13
+
14
+ useEffect(() => {
15
+ if (rolesData?.data) {
16
+ const roles = Array.isArray(rolesData.data) ? rolesData.data : [];
17
+ const options = roles.map((role: any) => ({
18
+ label: `${role.name} (${role.description || ""})`,
19
+ value: role.name,
20
+ }));
21
+ setRoleOptions(options);
22
+ }
23
+ }, [rolesData]);
24
+
25
+ return {
26
+ roleOptions,
27
+ loading: loading || !rolesData,
28
+ rolesData,
29
+ };
30
+ };
@@ -0,0 +1,339 @@
1
+ import { useMemo, useState, useEffect, useRef, useCallback } from "react";
2
+ import { customRequest } from "helpers/login";
3
+ import type { Role } from "types/role";
4
+
5
+ const RoleCacheKey = "oiterproles";
6
+ const PagesCacheKey = "oiterpages";
7
+ const RolePagesCacheKey = "oiterprolepages";
8
+ const RolesDataCacheKey = "oiterprolesdatacache";
9
+
10
+ /**
11
+ * Base Hook: User Page Access Data
12
+ *
13
+ * This hook fetches and provides user's accessible page data.
14
+ * It's designed to be reused by:
15
+ * - useDynamicResources (for menu generation)
16
+ * - Any other component that needs page access info
17
+ *
18
+ * Data Flow:
19
+ * SessionStorage(roles) → Role IDs → RolePages → Accessible Page IDs → Page Codes
20
+ */
21
+
22
+ export interface Page {
23
+ id: number;
24
+ code: string;
25
+ name: string;
26
+ description?: string;
27
+ zhName?: string;
28
+ enName?: string;
29
+ iframeUrl?: string;
30
+ externalRedirectUrl?: string;
31
+ icon?: string;
32
+ path: string;
33
+ parentId?: number | null;
34
+ isVirtual?: boolean;
35
+ sortOrder: number;
36
+ }
37
+
38
+ interface RolePage {
39
+ id: number;
40
+ roleId: number;
41
+ pageId: number;
42
+ }
43
+
44
+ export interface UseUserPageAccessResult {
45
+ /** Set of page IDs the user can access */
46
+ accessiblePageIds: Set<number>;
47
+ /** Set of page codes the user can access */
48
+ accessiblePageCodes: Set<string>;
49
+ /** All pages data from backend */
50
+ pagesData: Page[] | null;
51
+ /** Role pages mapping data */
52
+ rolePagesData: RolePage[] | null;
53
+ /** Map of pageId -> Page object */
54
+ pageMap: Map<number, Page>;
55
+ /** Map of pageCode -> Page object */
56
+ pageCodeMap: Map<string, Page>;
57
+ /** User's role names */
58
+ roleNames: string[];
59
+ /** User's role IDs */
60
+ roleIds: number[];
61
+ /** Whether data is still loading */
62
+ isLoading: boolean;
63
+ /** Check if user can access a page by code */
64
+ canAccessPage: (pageCode: string) => boolean;
65
+ }
66
+
67
+ function readCache<T>(key: string): T | null {
68
+ try {
69
+ const raw = sessionStorage.getItem(key);
70
+ return raw ? (JSON.parse(raw) as T) : null;
71
+ } catch {
72
+ return null;
73
+ }
74
+ }
75
+
76
+ function writeCache(key: string, value: unknown): void {
77
+ try {
78
+ sessionStorage.setItem(key, JSON.stringify(value));
79
+ } catch {
80
+ // ignore quota errors
81
+ }
82
+ }
83
+
84
+ export const useUserPageAccess = (): UseUserPageAccessResult => {
85
+ // Role names — initialise from cache so first render is non-empty
86
+ const [roleNames, setRoleNames] = useState<string[]>(
87
+ () => readCache<string[]>(RoleCacheKey) ?? []
88
+ );
89
+ // isRoleLoading only stays true while we wait for the live /userinfo response
90
+ const [isRoleLoading, setIsRoleLoading] = useState(true);
91
+
92
+ // Data states — initialise from cache for instant first render
93
+ const [rolesData, setRolesData] = useState<Role[] | null>(
94
+ () => readCache<Role[]>(RolesDataCacheKey)
95
+ );
96
+ const [rolePagesData, setRolePagesData] = useState<RolePage[] | null>(
97
+ () => readCache<RolePage[]>(RolePagesCacheKey)
98
+ );
99
+ const [pagesData, setPagesData] = useState<Page[] | null>(
100
+ () => readCache<Page[]>(PagesCacheKey)
101
+ );
102
+
103
+ // Track previous roles to detect changes
104
+ const prevRolesRef = useRef<string>("");
105
+
106
+ // Function to update roles in state and sessionStorage
107
+ const updateRoles = useCallback((newRoles: string[]) => {
108
+ const rolesKey = JSON.stringify(newRoles.sort());
109
+ if (rolesKey !== prevRolesRef.current) {
110
+ console.log("[useUserPageAccess] Roles changed:", newRoles);
111
+ prevRolesRef.current = rolesKey;
112
+ setRoleNames(newRoles);
113
+ writeCache(RoleCacheKey, newRoles);
114
+ }
115
+ }, []);
116
+
117
+ // Step 1: Fetch roles directly from backend to ensure fresh data
118
+ useEffect(() => {
119
+ const fetchRolesFromBackend = async () => {
120
+ try {
121
+ const res = await customRequest<any>("userinfo", "GET", {});
122
+ const roles = res?.configPerms?.roles;
123
+ if (roles && Array.isArray(roles)) {
124
+ updateRoles(roles as string[]);
125
+ }
126
+ } catch (error) {
127
+ console.error("[useUserPageAccess] Failed to fetch roles from backend:", error);
128
+ // Fallback to sessionStorage if backend request fails
129
+ try {
130
+ const cached = readCache<string[]>(RoleCacheKey);
131
+ if (cached) {
132
+ updateRoles(cached);
133
+ }
134
+ } catch (e) {
135
+ console.error("[useUserPageAccess] Failed to parse cached roles:", e);
136
+ }
137
+ } finally {
138
+ setIsRoleLoading(false);
139
+ }
140
+ };
141
+
142
+ fetchRolesFromBackend();
143
+ }, [updateRoles]);
144
+
145
+ // Step 2: Fetch all page definitions
146
+ useEffect(() => {
147
+ const fetchPages = async () => {
148
+ try {
149
+ const res = await customRequest<any>("page/findMany", "post", {});
150
+ const pages = res?.data as Page[];
151
+ // Keep existing reference if page IDs haven't changed — prevents
152
+ // downstream memos (accessiblePageIds, dynamicResources, allResources)
153
+ // from rebuilding and giving Refine a new resources prop.
154
+ setPagesData(prev => {
155
+ if (prev && prev.length === pages.length &&
156
+ prev.every((p, i) => p.id === pages[i].id)) {
157
+ return prev;
158
+ }
159
+ writeCache(PagesCacheKey, pages);
160
+ return pages;
161
+ });
162
+ } catch (error) {
163
+ console.error("[useUserPageAccess] Failed to fetch pages:", error);
164
+ }
165
+ };
166
+ fetchPages();
167
+ }, []);
168
+
169
+ // Step 3: Fetch role IDs when roleNames are available
170
+ useEffect(() => {
171
+ if (roleNames.length === 0) {
172
+ setRolesData(null);
173
+ return;
174
+ }
175
+
176
+ const fetchRoles = async () => {
177
+ try {
178
+ const query = {
179
+ where: { name: { in: roleNames } },
180
+ select: { id: true, name: true },
181
+ };
182
+ const res = await customRequest<any>("role/findMany", "post", query);
183
+ const roles = res?.data as Role[];
184
+ setRolesData(roles);
185
+ writeCache(RolesDataCacheKey, roles);
186
+ } catch (error) {
187
+ console.error("[useUserPageAccess] Failed to fetch roles:", error);
188
+ }
189
+ };
190
+ fetchRoles();
191
+ }, [roleNames.join(",")]);
192
+
193
+ // Calculate roleIds
194
+ const roleIds = useMemo(() => {
195
+ if (!rolesData) return [];
196
+ return rolesData.map(role => role.id);
197
+ }, [rolesData]);
198
+
199
+ // Step 4: Fetch role-page relationships when roleIds are available
200
+ useEffect(() => {
201
+ if (roleIds.length === 0) {
202
+ setRolePagesData(null);
203
+ return;
204
+ }
205
+
206
+ const fetchRolePages = async () => {
207
+ try {
208
+ const query = { where: { roleId: { in: roleIds } } };
209
+ const res = await customRequest<any>("rolePages/findMany", "post", query);
210
+ const rolePages = res?.data as RolePage[];
211
+ // Same stable-reference trick: keep existing ref if content unchanged.
212
+ setRolePagesData(prev => {
213
+ if (prev && prev.length === rolePages.length &&
214
+ prev.every((rp, i) => rp.id === rolePages[i].id)) {
215
+ return prev;
216
+ }
217
+ writeCache(RolePagesCacheKey, rolePages);
218
+ return rolePages;
219
+ });
220
+ } catch (error) {
221
+ console.error("[useUserPageAccess] Failed to fetch rolePages:", error);
222
+ }
223
+ };
224
+
225
+ fetchRolePages();
226
+ }, [roleIds.join(",")]);
227
+
228
+ // Build page maps
229
+ const { pageMap, pageCodeMap } = useMemo(() => {
230
+ const idMap = new Map<number, Page>();
231
+ const codeMap = new Map<string, Page>();
232
+
233
+ if (pagesData) {
234
+ pagesData.forEach(page => {
235
+ idMap.set(page.id, page);
236
+ codeMap.set(page.code, page);
237
+ });
238
+ }
239
+
240
+ return { pageMap: idMap, pageCodeMap: codeMap };
241
+ }, [pagesData]);
242
+
243
+ // Track previous accessiblePageIds to prevent unnecessary reference changes
244
+ const prevAccessiblePageIdsRef = useRef<Set<number>>(new Set());
245
+
246
+ // Build accessible page IDs (with ancestor pages)
247
+ const accessiblePageIds = useMemo(() => {
248
+ const ids = new Set<number>();
249
+
250
+ if (!rolePagesData || !pagesData) {
251
+ return prevAccessiblePageIdsRef.current;
252
+ }
253
+
254
+ // Add directly accessible pages
255
+ rolePagesData.forEach(rolePage => {
256
+ ids.add(rolePage.pageId);
257
+ });
258
+
259
+ // Recursively add ancestor pages
260
+ const addAncestorPages = (pageId: number, visited: Set<number>) => {
261
+ if (visited.has(pageId)) return;
262
+ visited.add(pageId);
263
+
264
+ const page = pageMap.get(pageId);
265
+ if (!page) return;
266
+
267
+ if (page.parentId) {
268
+ ids.add(page.parentId);
269
+ addAncestorPages(page.parentId, visited);
270
+ }
271
+ };
272
+
273
+ const originalIds = Array.from(ids);
274
+ const visited = new Set<number>();
275
+ originalIds.forEach(pageId => {
276
+ addAncestorPages(pageId, visited);
277
+ });
278
+
279
+ // Keep existing reference if IDs haven't changed
280
+ const prev = prevAccessiblePageIdsRef.current;
281
+ if (prev.size === ids.size && Array.from(ids).every(id => prev.has(id))) {
282
+ return prev;
283
+ }
284
+
285
+ prevAccessiblePageIdsRef.current = ids;
286
+ return ids;
287
+ }, [rolePagesData, pagesData, pageMap]);
288
+
289
+ // Build accessible page codes
290
+ const accessiblePageCodes = useMemo(() => {
291
+ const codes = new Set<string>();
292
+
293
+ accessiblePageIds.forEach(pageId => {
294
+ const page = pageMap.get(pageId);
295
+ if (page) {
296
+ codes.add(page.code);
297
+ }
298
+ });
299
+
300
+ return codes;
301
+ }, [accessiblePageIds, pageMap]);
302
+
303
+ // Check if user can access a specific page
304
+ const canAccessPage = useMemo(() => {
305
+ return (pageCode: string): boolean => {
306
+ return accessiblePageCodes.has(pageCode);
307
+ };
308
+ }, [accessiblePageCodes]);
309
+
310
+ // Calculate loading state
311
+ // If we have cached data, isLoading is false even while background-refreshing
312
+ const hasCache = useMemo(
313
+ () => !!(readCache(PagesCacheKey) && readCache(RolePagesCacheKey)),
314
+ // eslint-disable-next-line react-hooks/exhaustive-deps
315
+ []
316
+ );
317
+
318
+ const isLoading = useMemo(() => {
319
+ // If cache was available on mount, never block rendering
320
+ if (hasCache && pagesData && rolePagesData) return false;
321
+ if (isRoleLoading) return true;
322
+ if (!pagesData) return true;
323
+ if (roleNames.length > 0 && roleIds.length > 0 && !rolePagesData) return true;
324
+ return false;
325
+ }, [isRoleLoading, pagesData, roleNames, roleIds, rolePagesData, hasCache]);
326
+
327
+ return {
328
+ accessiblePageIds,
329
+ accessiblePageCodes,
330
+ pagesData,
331
+ rolePagesData,
332
+ pageMap,
333
+ pageCodeMap,
334
+ roleNames,
335
+ roleIds,
336
+ isLoading,
337
+ canAccessPage,
338
+ };
339
+ };
@@ -1,19 +1,23 @@
1
1
  import i18n from "i18next";
2
2
  import { initReactI18next } from "react-i18next";
3
- import Backend from "i18next-xhr-backend";
4
3
  import detector from "i18next-browser-languagedetector";
4
+ import en from "./locales/en/common.json";
5
+ import zh_CN from "./locales/zh_CN/common.json";
5
6
 
6
7
  i18n
7
- .use(Backend)
8
8
  .use(detector)
9
9
  .use(initReactI18next)
10
10
  .init({
11
11
  supportedLngs: ["en", "zh_CN"],
12
- backend: {
13
- loadPath: "/locales/{{lng}}/{{ns}}.json",
12
+ resources: {
13
+ en: { common: en },
14
+ zh_CN: { common: zh_CN },
14
15
  },
15
16
  defaultNS: "common",
16
17
  fallbackLng: ["en", "zh_CN"],
18
+ react: {
19
+ useSuspense: false,
20
+ },
17
21
  });
18
22
 
19
23
  export default i18n;
@@ -1,7 +1,6 @@
1
1
  import React from 'react';
2
2
  import { createRoot } from 'react-dom/client';
3
3
 
4
- import reportWebVitals from './reportWebVitals';
5
4
  import App from './App';
6
5
  import './i18n';
7
6
 
@@ -14,15 +13,8 @@ if (!checkLogin()) {
14
13
  const root = createRoot(container);
15
14
 
16
15
  root.render(
17
- <React.StrictMode>
18
- <React.Suspense fallback='loading'>
19
- <App />
20
- </React.Suspense>
21
- </React.StrictMode>
16
+ <React.Suspense fallback='loading'>
17
+ <App />
18
+ </React.Suspense>
22
19
  );
23
20
  }
24
-
25
- // If you want to start measuring performance in your app, pass a function
26
- // to log results (for example: reportWebVitals(console.log))
27
- // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
28
- reportWebVitals();
@@ -15,7 +15,7 @@
15
15
  "buttons": {
16
16
  "submit": "Login",
17
17
  "forgotPassword": "Forgot password?",
18
- "noAccount": "Dont have an account?",
18
+ "noAccount": "Don't have an account?",
19
19
  "rememberMe": "Remember me"
20
20
  }
21
21
  },
@@ -15,7 +15,7 @@
15
15
  "buttons": {
16
16
  "submit": "Login",
17
17
  "forgotPassword": "Forgot password?",
18
- "noAccount": "Dont have an account?",
18
+ "noAccount": "Don't have an account?",
19
19
  "rememberMe": "Remember me"
20
20
  }
21
21
  },
@@ -0,0 +1,3 @@
1
+ .highlight-changed-row {
2
+ background-color: #fff2f0;
3
+ }