@team-codeme/crud-forge 0.0.0-stage → 1.0.1

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 (415) hide show
  1. package/.cursor/agents/generator-engineer.md +31 -0
  2. package/.cursor/agents/keycloak-engineer.md +33 -0
  3. package/.cursor/agents/qa-engineer.md +32 -0
  4. package/.cursor/agents/security-reviewer.md +30 -0
  5. package/.cursor/mcp.json +13 -0
  6. package/.cursor/rules/crudforge-precautions.mdc +16 -0
  7. package/.cursor/rules/playwright-browser.mdc +30 -0
  8. package/.cursor/rules/readme-todo-sync.mdc +13 -0
  9. package/.env.qa.example +19 -0
  10. package/.github/workflows/qa-live.yml +32 -0
  11. package/.github/workflows/qa.yml +27 -0
  12. package/.vscode/settings.json +32 -0
  13. package/QA/IAM-PLAN.md +25 -0
  14. package/QA/IAM-RESULTS.md +39 -0
  15. package/QA/IAM-TESTCASES.md +36 -0
  16. package/QA/IAM-TODO.md +7 -0
  17. package/QA/KEYCLOAK-BOOTSTRAP.md +105 -0
  18. package/QA/PLAN.md +43 -0
  19. package/QA/RESULTS.md +59 -0
  20. package/QA/TESTCASES.md +65 -0
  21. package/QA/TODO.md +14 -0
  22. package/QA/pmb-dev/README.md +49 -0
  23. package/QA/pmb-dev/config/config.yml +152 -0
  24. package/QA/pmb-dev/gdl/i.gdl +17 -0
  25. package/README.md +851 -2
  26. package/Todo.md +207 -0
  27. package/assets/branding/crudforge-logo.png +0 -0
  28. package/assets/branding/crudforge-mark.png +0 -0
  29. package/branding/poster-crudforge.jpg +0 -0
  30. package/chat/last-chat/Investigating Mock Data Configuration.md +428 -0
  31. package/cli.js +167 -0
  32. package/config/default-config.yml +245 -0
  33. package/docs/performance/README.md +217 -0
  34. package/docs/performance/after.json +111 -0
  35. package/docs/performance/before.json +111 -0
  36. package/docs/quality/README.md +276 -0
  37. package/e2e/crudforge.e2e.yml +47 -0
  38. package/e2e/crudforge.field-profile.yml +33 -0
  39. package/e2e/crudforge.iam-live.yml +124 -0
  40. package/e2e/crudforge.iam.yml +62 -0
  41. package/e2e/tests/field-profile.spec.js +152 -0
  42. package/e2e/tests/generated-crud.spec.js +251 -0
  43. package/e2e/tests/iam-live.spec.js +149 -0
  44. package/e2e/tests/iam-pack.spec.js +151 -0
  45. package/e2e/tests/list-state.spec.js +73 -0
  46. package/features.csv +27 -0
  47. package/fuse-starter-pack/branding/crudforge-mark-source.jpg +0 -0
  48. package/fuse-starter-pack/branding/crudforge-mark-source.png +0 -0
  49. package/fuse-starter-pack/branding/crudforge-mark.png +0 -0
  50. package/fuse-starter-pack/branding/crudforge-wordmark-source.jpg +0 -0
  51. package/fuse-starter-pack/branding/crudforge-wordmark-source.png +0 -0
  52. package/fuse-starter-pack/branding/crudforge-wordmark.png +0 -0
  53. package/fuse-starter-pack/fuse-v21.1/Dockerfile +14 -0
  54. package/fuse-starter-pack/fuse-v21.1/LICENSE.md +6 -0
  55. package/fuse-starter-pack/fuse-v21.1/README.md +59 -0
  56. package/fuse-starter-pack/fuse-v21.1/angular.json +113 -0
  57. package/fuse-starter-pack/fuse-v21.1/eslint.config.ts +150 -0
  58. package/fuse-starter-pack/fuse-v21.1/nginx.conf +23 -0
  59. package/fuse-starter-pack/fuse-v21.1/nginx.dev.conf +18 -0
  60. package/fuse-starter-pack/fuse-v21.1/package-lock.json +11513 -0
  61. package/fuse-starter-pack/fuse-v21.1/package.json +69 -0
  62. package/fuse-starter-pack/fuse-v21.1/postcss.config.json +5 -0
  63. package/fuse-starter-pack/fuse-v21.1/prettier.config.ts +15 -0
  64. package/fuse-starter-pack/fuse-v21.1/proxy.conf.json +8 -0
  65. package/fuse-starter-pack/fuse-v21.1/proxy.dev.conf.json +8 -0
  66. package/fuse-starter-pack/fuse-v21.1/public/favicon.png +0 -0
  67. package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/Geist-Italic.woff2 +0 -0
  68. package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/Geist.woff2 +0 -0
  69. package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/GeistMono-Italic.woff2 +0 -0
  70. package/fuse-starter-pack/fuse-v21.1/public/fonts/geist/GeistMono.woff2 +0 -0
  71. package/fuse-starter-pack/fuse-v21.1/public/i18n/en.json +8 -0
  72. package/fuse-starter-pack/fuse-v21.1/public/i18n/es.json +8 -0
  73. package/fuse-starter-pack/fuse-v21.1/public/images/flags/ES.svg +79 -0
  74. package/fuse-starter-pack/fuse-v21.1/public/images/flags/US.svg +14 -0
  75. package/fuse-starter-pack/fuse-v21.1/public/images/flags/where-to-find-other-flags.txt +5 -0
  76. package/fuse-starter-pack/fuse-v21.1/public/images/logo/logo-mark.png +0 -0
  77. package/fuse-starter-pack/fuse-v21.1/public/images/logo/logo.png +0 -0
  78. package/fuse-starter-pack/fuse-v21.1/push.sh +27 -0
  79. package/fuse-starter-pack/fuse-v21.1/src/app/app.config.server.ts +10 -0
  80. package/fuse-starter-pack/fuse-v21.1/src/app/app.config.ts +64 -0
  81. package/fuse-starter-pack/fuse-v21.1/src/app/app.routes.server.ts +8 -0
  82. package/fuse-starter-pack/fuse-v21.1/src/app/app.routes.ts +39 -0
  83. package/fuse-starter-pack/fuse-v21.1/src/app/app.ts +22 -0
  84. package/fuse-starter-pack/fuse-v21.1/src/app/core/icons/index.ts +1 -0
  85. package/fuse-starter-pack/fuse-v21.1/src/app/core/icons/lucide.ts +1 -0
  86. package/fuse-starter-pack/fuse-v21.1/src/app/core/icons/provider.ts +23 -0
  87. package/fuse-starter-pack/fuse-v21.1/src/app/core/local-storage/index.ts +2 -0
  88. package/fuse-starter-pack/fuse-v21.1/src/app/core/local-storage/local-storage.ts +109 -0
  89. package/fuse-starter-pack/fuse-v21.1/src/app/core/local-storage/provider.ts +15 -0
  90. package/fuse-starter-pack/fuse-v21.1/src/app/core/media/index.ts +2 -0
  91. package/fuse-starter-pack/fuse-v21.1/src/app/core/media/media.ts +64 -0
  92. package/fuse-starter-pack/fuse-v21.1/src/app/core/media/provider.ts +15 -0
  93. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/index.ts +3 -0
  94. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/models/theming.ts +13 -0
  95. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/palette.ts +209 -0
  96. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/provider.ts +24 -0
  97. package/fuse-starter-pack/fuse-v21.1/src/app/core/theming/theming.ts +129 -0
  98. package/fuse-starter-pack/fuse-v21.1/src/app/core/transloco/transloco-http-loader.ts +12 -0
  99. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/data/navigation.ts +176 -0
  100. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/layout.ts +77 -0
  101. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/language-switcher.ts +91 -0
  102. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/navigation.ts +238 -0
  103. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/notifications.ts +252 -0
  104. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/scheme-switcher.ts +58 -0
  105. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/sidebar.ts +31 -0
  106. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/layout/ui/user.ts +132 -0
  107. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/data/academy.ts +753 -0
  108. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/data/model.ts +27 -0
  109. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/features/course.ts +318 -0
  110. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/features/courses.ts +228 -0
  111. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/academy/routes.ts +14 -0
  112. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/data/contacts.ts +4372 -0
  113. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/data/model.ts +34 -0
  114. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/features/contact.ts +239 -0
  115. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/features/contacts.ts +185 -0
  116. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/contacts/routes.ts +16 -0
  117. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/data/file-manager.ts +261 -0
  118. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/data/model.ts +12 -0
  119. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/features/file-manager.ts +131 -0
  120. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/routes.ts +15 -0
  121. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/file-manager/ui/list.ts +164 -0
  122. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/faq.ts +288 -0
  123. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/guide.ts +134 -0
  124. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/home.ts +219 -0
  125. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/features/support.ts +161 -0
  126. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/help-center/routes.ts +33 -0
  127. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/data/model.ts +18 -0
  128. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/data/notes.ts +324 -0
  129. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/features/note.ts +152 -0
  130. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/features/notes.ts +118 -0
  131. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/notes/routes.ts +16 -0
  132. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/data/model.ts +17 -0
  133. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/data/tasks.ts +562 -0
  134. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/features/task.ts +195 -0
  135. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/features/tasks.ts +271 -0
  136. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/apps/tasks/routes.ts +16 -0
  137. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/data/analytics.ts +1620 -0
  138. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/data/finance.ts +1065 -0
  139. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/data/project.ts +376 -0
  140. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/analytics/analytics.ts +1096 -0
  141. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/finance/finance.ts +658 -0
  142. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/project/budget-table.ts +188 -0
  143. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/features/project/project.ts +565 -0
  144. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/dashboards/routes.ts +23 -0
  145. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/changelog/changelog.ts +932 -0
  146. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/getting-started/building.ts +33 -0
  147. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/getting-started/development.ts +42 -0
  148. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/features/getting-started/installation.ts +47 -0
  149. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/layout.ts +9 -0
  150. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/documentation/routes.ts +45 -0
  151. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/error/features/error-page.ts +70 -0
  152. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/error/routes.ts +21 -0
  153. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/notifications/features/notifications.ts +262 -0
  154. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/notifications/routes.ts +10 -0
  155. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/account.ts +238 -0
  156. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/notifications.ts +134 -0
  157. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/plan-and-billing.ts +238 -0
  158. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/security.ts +211 -0
  159. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/features/team.ts +188 -0
  160. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/layout.ts +109 -0
  161. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/settings/routes.ts +37 -0
  162. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/modules/extras/welcome/welcome.component.ts +22 -0
  163. package/fuse-starter-pack/fuse-v21.1/src/app/domains/admin/routes.ts +95 -0
  164. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/forgot-password/forgot-password.html +54 -0
  165. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/forgot-password/forgot-password.ts +51 -0
  166. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/reset-password/reset-password.html +82 -0
  167. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/reset-password/reset-password.ts +69 -0
  168. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-in/sign-in.html +132 -0
  169. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-in/sign-in.ts +54 -0
  170. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-up/sign-up.html +183 -0
  171. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/features/sign-up/sign-up.ts +56 -0
  172. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/layout.ts +9 -0
  173. package/fuse-starter-pack/fuse-v21.1/src/app/domains/auth/routes.ts +34 -0
  174. package/fuse-starter-pack/fuse-v21.1/src/app/domains/coming-soon/features/coming-soon.ts +156 -0
  175. package/fuse-starter-pack/fuse-v21.1/src/app/domains/coming-soon/layout.ts +9 -0
  176. package/fuse-starter-pack/fuse-v21.1/src/app/domains/coming-soon/routes.ts +16 -0
  177. package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/layout/layout.ts +9 -0
  178. package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/modules/home/features/home.ts +23 -0
  179. package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/modules/home/routes.ts +10 -0
  180. package/fuse-starter-pack/fuse-v21.1/src/app/domains/website/routes.ts +30 -0
  181. package/fuse-starter-pack/fuse-v21.1/src/environments/environment.mock.ts +5 -0
  182. package/fuse-starter-pack/fuse-v21.1/src/environments/environment.prod.ts +5 -0
  183. package/fuse-starter-pack/fuse-v21.1/src/environments/environment.ts +5 -0
  184. package/fuse-starter-pack/fuse-v21.1/src/index.html +66 -0
  185. package/fuse-starter-pack/fuse-v21.1/src/main.server.ts +11 -0
  186. package/fuse-starter-pack/fuse-v21.1/src/main.ts +5 -0
  187. package/fuse-starter-pack/fuse-v21.1/src/server.ts +70 -0
  188. package/fuse-starter-pack/fuse-v21.1/src/styles/base/base.css +63 -0
  189. package/fuse-starter-pack/fuse-v21.1/src/styles/base/typography.css +54 -0
  190. package/fuse-starter-pack/fuse-v21.1/src/styles/components/a.css +18 -0
  191. package/fuse-starter-pack/fuse-v21.1/src/styles/components/input.css +22 -0
  192. package/fuse-starter-pack/fuse-v21.1/src/styles/components/kbd.css +55 -0
  193. package/fuse-starter-pack/fuse-v21.1/src/styles/components/material.css +1149 -0
  194. package/fuse-starter-pack/fuse-v21.1/src/styles/styles.css +31 -0
  195. package/fuse-starter-pack/fuse-v21.1/src/styles/tailwind/theme.css +147 -0
  196. package/fuse-starter-pack/fuse-v21.1/src/styles/tailwind/utilities.css +563 -0
  197. package/fuse-starter-pack/fuse-v21.1/src/styles/tailwind/variants.css +4 -0
  198. package/fuse-starter-pack/fuse-v21.1/src/styles/third-party/lucide-icons.css +12 -0
  199. package/fuse-starter-pack/fuse-v21.1/tsconfig.app.json +16 -0
  200. package/fuse-starter-pack/fuse-v21.1/tsconfig.json +37 -0
  201. package/fuse-starter-pack/fuse-v21.1/tsconfig.spec.json +10 -0
  202. package/generator/README.md +12 -0
  203. package/generator/issues/.gitkeep +0 -0
  204. package/package.json +56 -4
  205. package/playwright.config.js +29 -0
  206. package/playwright.field-profile.config.js +6 -0
  207. package/playwright.iam-live.config.js +31 -0
  208. package/playwright.iam.config.js +29 -0
  209. package/playwright.list-state.config.js +6 -0
  210. package/playwright.performance.config.js +1 -0
  211. package/run-config-tests.sh +5 -0
  212. package/scripts/e2e-paths.js +89 -0
  213. package/scripts/e2e-prepare-field-profile.js +17 -0
  214. package/scripts/e2e-prepare-iam-live.js +135 -0
  215. package/scripts/e2e-prepare-iam.js +65 -0
  216. package/scripts/e2e-prepare.js +72 -0
  217. package/scripts/e2e-serve-iam-live.js +28 -0
  218. package/scripts/e2e-serve-iam.js +28 -0
  219. package/scripts/e2e-serve.js +28 -0
  220. package/scripts/performance/generate.js +17 -0
  221. package/scripts/performance/measure.js +55 -0
  222. package/scripts/postinstall.js +9 -0
  223. package/scripts/prepare-quality-apps.js +34 -0
  224. package/scripts/run-config-tests.js +63 -0
  225. package/src/assets/logo-with-lable.jpeg +0 -0
  226. package/src/assets/logo.jpeg +0 -0
  227. package/src/commands/bootstrap.js +92 -0
  228. package/src/commands/doctor.js +403 -0
  229. package/src/commands/generate.js +301 -0
  230. package/src/commands/init-config.js +310 -0
  231. package/src/commands/keycloak-options.js +182 -0
  232. package/src/commands/validate.js +52 -0
  233. package/src/config/auth-config.js +183 -0
  234. package/src/config/default-values.js +235 -0
  235. package/src/config/env-refs.js +71 -0
  236. package/src/config/field-preferences.js +99 -0
  237. package/src/config/input-sources.js +104 -0
  238. package/src/config/load-config.js +166 -0
  239. package/src/config/proxy-routes.js +44 -0
  240. package/src/generator/access-control-tools.js +334 -0
  241. package/src/generator/ai-docs.js +691 -0
  242. package/src/generator/application-tests.js +252 -0
  243. package/src/generator/auth-pack.js +965 -0
  244. package/src/generator/embed-config.js +431 -0
  245. package/src/generator/entity-layout.js +30 -0
  246. package/src/generator/fuse-build.js +57 -0
  247. package/src/generator/fuse-runtime.js +344 -0
  248. package/src/generator/generated-banner.js +137 -0
  249. package/src/generator/index.js +874 -0
  250. package/src/generator/project-output.js +126 -0
  251. package/src/generator/team-pack.js +220 -0
  252. package/src/index.js +68 -0
  253. package/src/parser/gdl-parser.js +169 -0
  254. package/src/parser/jdl-parser.js +171 -0
  255. package/src/presets/pmb-test.js +139 -0
  256. package/src/presets/static-source.js +73 -0
  257. package/src/presets/store.js +96 -0
  258. package/src/provision/admin-service.js +148 -0
  259. package/src/provision/bootstrap.js +147 -0
  260. package/src/provision/http.js +123 -0
  261. package/src/provision/keycloak-admin-rest.js +335 -0
  262. package/src/provision/state.js +51 -0
  263. package/src/provision/token.js +52 -0
  264. package/src/templates/angular/auth/access-control.service.ts.ejs +179 -0
  265. package/src/templates/angular/auth/access-ctrl.pipe.ts.ejs +20 -0
  266. package/src/templates/angular/auth/auth.guard.ts.ejs +27 -0
  267. package/src/templates/angular/auth/auth.interceptor.ts.ejs +53 -0
  268. package/src/templates/angular/auth/auth.service.ts.ejs +594 -0
  269. package/src/templates/angular/auth/auth.utils.ts.ejs +28 -0
  270. package/src/templates/angular/auth/current-user.ts.ejs +24 -0
  271. package/src/templates/angular/auth/disabled-account-overlay.component.css.ejs +95 -0
  272. package/src/templates/angular/auth/disabled-account-overlay.component.html.ejs +33 -0
  273. package/src/templates/angular/auth/disabled-account-overlay.component.ts.ejs +23 -0
  274. package/src/templates/angular/auth/fuse-account.ts.ejs +234 -0
  275. package/src/templates/angular/auth/fuse-user.ts.ejs +264 -0
  276. package/src/templates/angular/auth/has-permission.directive.ts.ejs +51 -0
  277. package/src/templates/angular/auth/index.ts.ejs +24 -0
  278. package/src/templates/angular/auth/keycloak-admin.service.ts.ejs +670 -0
  279. package/src/templates/angular/auth/landing.guard.ts.ejs +61 -0
  280. package/src/templates/angular/auth/no-auth.guard.ts.ejs +19 -0
  281. package/src/templates/angular/auth/permission-attribute.util.ts.ejs +182 -0
  282. package/src/templates/angular/auth/sign-in.ts.ejs +60 -0
  283. package/src/templates/angular/entity/_entity_.model.ts.ejs +64 -0
  284. package/src/templates/angular/entity/_entity_.routes.ts.ejs +9 -0
  285. package/src/templates/angular/entity/components/forms/form/_entity_-form.component.html.ejs +168 -0
  286. package/src/templates/angular/entity/components/forms/form/_entity_-form.component.ts.ejs +175 -0
  287. package/src/templates/angular/entity/components/forms/form-page/_entity_-form-page.component.html.ejs +10 -0
  288. package/src/templates/angular/entity/components/forms/form-page/_entity_-form-page.component.ts.ejs +86 -0
  289. package/src/templates/angular/entity/components/forms/update/_entity_-form.service.ts.ejs +136 -0
  290. package/src/templates/angular/entity/components/interaction/actions/_entity_-actions.component.html.ejs +68 -0
  291. package/src/templates/angular/entity/components/interaction/actions/_entity_-actions.component.ts.ejs +69 -0
  292. package/src/templates/angular/entity/components/interaction/filter/_entity_-filter.component.html.ejs +111 -0
  293. package/src/templates/angular/entity/components/interaction/filter/_entity_-filter.component.ts.ejs +102 -0
  294. package/src/templates/angular/entity/components/presentation/card/_entity_-card.component.css.ejs +33 -0
  295. package/src/templates/angular/entity/components/presentation/card/_entity_-card.component.html.ejs +29 -0
  296. package/src/templates/angular/entity/components/presentation/card/_entity_-card.component.ts.ejs +93 -0
  297. package/src/templates/angular/entity/components/presentation/detail/_entity_-detail.component.css.ejs +54 -0
  298. package/src/templates/angular/entity/components/presentation/detail/_entity_-detail.component.html.ejs +58 -0
  299. package/src/templates/angular/entity/components/presentation/detail/_entity_-detail.component.ts.ejs +47 -0
  300. package/src/templates/angular/entity/components/presentation/list/_entity_-list.component.html.ejs +419 -0
  301. package/src/templates/angular/entity/components/presentation/list/_entity_-list.component.scss.ejs +48 -0
  302. package/src/templates/angular/entity/components/presentation/list/_entity_-list.component.ts.ejs +592 -0
  303. package/src/templates/angular/entity/service/_entity_.service.ts.ejs +153 -0
  304. package/src/templates/angular/entity/settings/_entity_.settings.ts.ejs +49 -0
  305. package/src/templates/angular/enums/_enum_.model.ts.ejs +11 -0
  306. package/src/templates/angular/iam/change-password.component.html.ejs +39 -0
  307. package/src/templates/angular/iam/change-password.component.ts.ejs +44 -0
  308. package/src/templates/angular/iam/no-access.component.ts.ejs +17 -0
  309. package/src/templates/angular/iam/role-list.component.html.ejs +331 -0
  310. package/src/templates/angular/iam/role-list.component.scss.ejs +107 -0
  311. package/src/templates/angular/iam/role-list.component.ts.ejs +597 -0
  312. package/src/templates/angular/iam/role-management/role-header.component.html.ejs +51 -0
  313. package/src/templates/angular/iam/role-management/role-header.component.ts.ejs +45 -0
  314. package/src/templates/angular/iam/role-management/role-inheritance.component.html.ejs +15 -0
  315. package/src/templates/angular/iam/role-management/role-inheritance.component.ts.ejs +19 -0
  316. package/src/templates/angular/iam/role-management/role-permissions-panel.component.css.ejs +24 -0
  317. package/src/templates/angular/iam/role-management/role-permissions-panel.component.html.ejs +108 -0
  318. package/src/templates/angular/iam/role-management/role-permissions-panel.component.ts.ejs +122 -0
  319. package/src/templates/angular/iam/role-management/role-users.component.html.ejs +104 -0
  320. package/src/templates/angular/iam/role-management/role-users.component.ts.ejs +53 -0
  321. package/src/templates/angular/iam/role-management/user-select-dialog.component.html.ejs +113 -0
  322. package/src/templates/angular/iam/role-management/user-select-dialog.component.ts.ejs +157 -0
  323. package/src/templates/angular/iam/role-permission-matrix.component.html.ejs +355 -0
  324. package/src/templates/angular/iam/role-permission-matrix.component.scss.ejs +217 -0
  325. package/src/templates/angular/iam/role-permission-matrix.component.ts.ejs +800 -0
  326. package/src/templates/angular/iam/screen-catalog.ts.ejs +147 -0
  327. package/src/templates/angular/iam/shared/confirm-dialog.component.ts.ejs +83 -0
  328. package/src/templates/angular/iam/shared/matrix-hierarchy.util.ts.ejs +196 -0
  329. package/src/templates/angular/iam/shared/permission-matrix-sound.ts.ejs +59 -0
  330. package/src/templates/angular/iam/shared/role-display.util.ts.ejs +43 -0
  331. package/src/templates/angular/iam/shared/role-permission-skeleton.component.ts.ejs +54 -0
  332. package/src/templates/angular/iam/shared/screen-matrix.util.ts.ejs +554 -0
  333. package/src/templates/angular/iam/shared/screen-navigation-map.ts.ejs +187 -0
  334. package/src/templates/angular/iam/shared/screen-navigation.registry.ts.ejs +64 -0
  335. package/src/templates/angular/iam/shared/text-highlight.pipe.ts.ejs +39 -0
  336. package/src/templates/angular/iam/user-access-matrix.component.html.ejs +212 -0
  337. package/src/templates/angular/iam/user-access-matrix.component.scss.ejs +34 -0
  338. package/src/templates/angular/iam/user-access-matrix.component.ts.ejs +239 -0
  339. package/src/templates/angular/iam/user-detail.component.html.ejs +143 -0
  340. package/src/templates/angular/iam/user-detail.component.ts.ejs +108 -0
  341. package/src/templates/angular/iam/user-form.component.html.ejs +63 -0
  342. package/src/templates/angular/iam/user-form.component.ts.ejs +100 -0
  343. package/src/templates/angular/iam/user-list.component.html.ejs +369 -0
  344. package/src/templates/angular/iam/user-list.component.scss.ejs +242 -0
  345. package/src/templates/angular/iam/user-list.component.ts.ejs +446 -0
  346. package/src/templates/angular/iam/user-management.routes.ts.ejs +47 -0
  347. package/src/templates/angular/iam/user-permission-matrix.component.html.ejs +231 -0
  348. package/src/templates/angular/iam/user-permission-matrix.component.scss.ejs +216 -0
  349. package/src/templates/angular/iam/user-permission-matrix.component.ts.ejs +516 -0
  350. package/src/templates/angular/shared/base/audit-user-name.pipe.ts.ejs +69 -0
  351. package/src/templates/angular/shared/base/base-filter.component.ts.ejs +245 -0
  352. package/src/templates/angular/shared/base/base-form.component.ts.ejs +109 -0
  353. package/src/templates/angular/shared/base/base-list.component.ts.ejs +507 -0
  354. package/src/templates/angular/shared/base/filter-types.ts.ejs +55 -0
  355. package/src/templates/angular/shared/base/input-format.directive.ts.ejs +47 -0
  356. package/src/templates/angular/shared/base/input-format.ts.ejs +15 -0
  357. package/src/templates/angular/shared/confirm-with-input-dialog.component.ts.ejs +91 -0
  358. package/src/templates/angular/shared/confirmation-dialog.component.ts.ejs +80 -0
  359. package/src/templates/angular/shared/list-styles.css.ejs +103 -0
  360. package/src/templates/angular/shared/loading-overlay.component.ts.ejs +24 -0
  361. package/src/templates/angular/shared/resizable.directive.ts.ejs +115 -0
  362. package/src/templates/angular/shared/snackbar-styles.css.ejs +11 -0
  363. package/src/templates/fuse-packs/access-control-tools/access-control-sync.js +819 -0
  364. package/src/templates/fuse-packs/access-control-tools/build-rename-map.js +67 -0
  365. package/src/templates/fuse-packs/access-control-tools/inject-qa-ids.js +14 -0
  366. package/src/templates/fuse-packs/access-control-tools/lib/hierarchy-scanner.js +628 -0
  367. package/src/templates/fuse-packs/access-control-tools/lib/hierarchy-scanner.test.js +323 -0
  368. package/src/templates/fuse-packs/access-control-tools/lib/html-scanner.js +362 -0
  369. package/src/templates/fuse-packs/access-control-tools/lib/id-rules.duplicate.test.js +136 -0
  370. package/src/templates/fuse-packs/access-control-tools/lib/id-rules.js +1095 -0
  371. package/src/templates/fuse-packs/access-control-tools/lib/ts-component-index.js +482 -0
  372. package/src/templates/fuse-packs/access-control-tools/output/.gitkeep +0 -0
  373. package/src/templates/fuse-packs/access-control-tools/run.sh +223 -0
  374. package/src/templates/fuse-packs/access-control-tools/scan-access-control.js +14 -0
  375. package/src/templates/fuse-packs/iam-assets/sound/apple-play.mp3 +0 -0
  376. package/src/templates/fuse-packs/iam-assets/sound/remove.mp3 +0 -0
  377. package/src/templates/generator/README.md +12 -0
  378. package/src/templates/testing/ci.cjs +45 -0
  379. package/src/templates/testing/mock.cjs +149 -0
  380. package/src/templates/testing/playwright.config.cjs +25 -0
  381. package/src/templates/testing/serve.cjs +22 -0
  382. package/src/templates/testing/smoke.spec.cjs +180 -0
  383. package/src/utils/branding.js +39 -0
  384. package/src/utils/colors.js +18 -0
  385. package/src/utils/diff.js +109 -0
  386. package/src/utils/merger.js +115 -0
  387. package/src/validator/backend-diagnostics.js +30 -0
  388. package/src/validator/blueprint-validator.js +276 -0
  389. package/src/validator/diagnostics.js +608 -0
  390. package/src/validator/pattern.js +28 -0
  391. package/test/auth-interceptor.js +84 -0
  392. package/test/auth-provision-checks.js +297 -0
  393. package/test/field-preferences.js +145 -0
  394. package/test/fixtures/field-profile.gdl +7 -0
  395. package/test/fixtures/mock.jdl +17 -0
  396. package/test/fixtures/mock.png +0 -0
  397. package/test/fixtures/performance/config.yml +33 -0
  398. package/test/fixtures/performance/large.gdl +199 -0
  399. package/test/fixtures/performance/small.gdl +7 -0
  400. package/test/fixtures/quality/custom.yml +22 -0
  401. package/test/fixtures/quality/go-duck.yml +22 -0
  402. package/test/fixtures/quality/jhipster.yml +30 -0
  403. package/test/fixtures/quality/representative.gdl +14 -0
  404. package/test/list-state.js +138 -0
  405. package/test/micro-functions-layout.js +95 -0
  406. package/test/performance-generation.js +32 -0
  407. package/test/pmb-preset.js +127 -0
  408. package/test/project-workflow.js +111 -0
  409. package/test/quality-features.js +250 -0
  410. package/test/verify-commands.js +83 -0
  411. package/test/verify.js +959 -0
  412. package/test-files/GDL/example.gdl +15 -0
  413. package/test-files/JDL/example.jdl +15 -0
  414. package/test-files/config/crudforge.config.yml +127 -0
  415. package/test-run.sh +272 -0
@@ -0,0 +1,1096 @@
1
+ import { DecimalPipe } from '@angular/common';
2
+ import { Component, computed, inject, Signal } from '@angular/core';
3
+ import { MatButtonModule } from '@angular/material/button';
4
+ import { MatButtonToggleModule } from '@angular/material/button-toggle';
5
+ import { MatCard } from '@angular/material/card';
6
+ import { MatDivider } from '@angular/material/divider';
7
+ import { MatIconModule } from '@angular/material/icon';
8
+ import { MatMenuModule } from '@angular/material/menu';
9
+ import { MatTooltipModule } from '@angular/material/tooltip';
10
+ import {
11
+ ApexAxisChartSeries,
12
+ ApexChart,
13
+ ApexDataLabels,
14
+ ApexFill,
15
+ ApexGrid,
16
+ ApexLegend,
17
+ ApexNonAxisChartSeries,
18
+ ApexPlotOptions,
19
+ ApexStates,
20
+ ApexStroke,
21
+ ApexTooltip,
22
+ ApexXAxis,
23
+ ApexYAxis,
24
+ ChartComponent,
25
+ } from 'ng-apexcharts';
26
+ import { Theming } from '@/app/core/theming';
27
+ import { AnalyticsDashboardService } from '@/app/domains/admin/modules/dashboards/data/analytics';
28
+
29
+ @Component({
30
+ selector: 'analytics-dashboard',
31
+ imports: [
32
+ MatButtonModule,
33
+ MatIconModule,
34
+ MatMenuModule,
35
+ MatButtonToggleModule,
36
+ MatTooltipModule,
37
+ DecimalPipe,
38
+ MatCard,
39
+ MatDivider,
40
+ ChartComponent,
41
+ ],
42
+ template: `
43
+ <div
44
+ class="@container mx-auto flex w-full max-w-7xl flex-auto flex-col gap-4 p-6 sm:gap-6 lg:p-10 lg:pt-8"
45
+ >
46
+ <!-- Header -->
47
+ <div class="flex items-center justify-between gap-x-3">
48
+ <div class="flex flex-col gap-y-0.5">
49
+ <div class="text-xl font-semibold tracking-tighter sm:text-2xl">
50
+ Overview
51
+ </div>
52
+ <div class="text-neutral-500">
53
+ A quick glance at the most important metrics and trends related to
54
+ your website visitors.
55
+ </div>
56
+ </div>
57
+
58
+ <!-- Spacer -->
59
+ <div class="flex-auto"></div>
60
+
61
+ <button matButton="outlined">
62
+ <mat-icon svgIcon="upload" />
63
+ Export
64
+ </button>
65
+ </div>
66
+
67
+ <!-- Visitors -->
68
+ <mat-card
69
+ class="overflow-hidden"
70
+ appearance="outlined"
71
+ >
72
+ <div class="flex items-center justify-between gap-x-4 p-6 pb-0">
73
+ <div class="text-xl font-semibold sm:text-2xl">Visitors</div>
74
+
75
+ <mat-button-toggle-group
76
+ value="this-year"
77
+ #visitorsYearSelector="matButtonToggleGroup"
78
+ >
79
+ <mat-button-toggle value="last-year">Last Year</mat-button-toggle>
80
+ <mat-button-toggle value="this-year">This Year</mat-button-toggle>
81
+ </mat-button-toggle-group>
82
+ </div>
83
+
84
+ <div class="flex flex-auto flex-col">
85
+ <apx-chart
86
+ class="h-80"
87
+ [chart]="visitorsChart.chart"
88
+ [colors]="visitorsChart.colors"
89
+ [dataLabels]="visitorsChart.dataLabels"
90
+ [fill]="visitorsChart.fill"
91
+ [grid]="visitorsChart.grid"
92
+ [series]="visitorsChart.series[visitorsYearSelector.value]"
93
+ [stroke]="visitorsChart.stroke"
94
+ [tooltip]="visitorsChart.tooltip()"
95
+ [xaxis]="visitorsChart.xaxis"
96
+ [yaxis]="visitorsChart.yaxis"
97
+ ></apx-chart>
98
+ </div>
99
+ </mat-card>
100
+
101
+ <div class="grid w-full grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3">
102
+ <!-- Conversions -->
103
+ <mat-card
104
+ class="overflow-hidden"
105
+ appearance="outlined"
106
+ >
107
+ <div class="flex flex-col gap-y-2 p-6 pb-0">
108
+ <div class="truncate text-lg font-medium tracking-tight">
109
+ Conversions
110
+ </div>
111
+
112
+ <div class="text-4xl font-semibold">
113
+ {{ data.conversions.amount | number: '1.0-0' }}
114
+ </div>
115
+ <div class="flex items-center gap-x-1">
116
+ <mat-icon
117
+ class="text-red-600"
118
+ svgIcon="trending-down"
119
+ />
120
+ <div class="font-medium text-red-600">2%</div>
121
+ <div class="text-neutral-500">below target</div>
122
+ </div>
123
+ </div>
124
+
125
+ <div class="flex flex-auto flex-col">
126
+ <apx-chart
127
+ class="h-20"
128
+ [chart]="conversionsChart.chart"
129
+ [colors]="conversionsChart.colors"
130
+ [fill]="conversionsChart.fill"
131
+ [series]="conversionsChart.series"
132
+ [stroke]="conversionsChart.stroke"
133
+ [tooltip]="conversionsChart.tooltip"
134
+ ></apx-chart>
135
+ </div>
136
+ </mat-card>
137
+
138
+ <!-- Impressions -->
139
+ <mat-card
140
+ class="overflow-hidden"
141
+ appearance="outlined"
142
+ >
143
+ <div class="flex flex-col gap-y-2 p-6 pb-0">
144
+ <div class="truncate text-lg font-medium tracking-tight">
145
+ Impressions
146
+ </div>
147
+
148
+ <div class="text-4xl font-semibold">
149
+ {{ data.impressions.amount | number: '1.0-0' }}
150
+ </div>
151
+ <div class="flex items-center gap-x-1">
152
+ <mat-icon
153
+ class="text-red-600"
154
+ svgIcon="trending-down"
155
+ />
156
+ <div class="font-medium text-red-600">2%</div>
157
+ <div class="text-neutral-500">below target</div>
158
+ </div>
159
+ </div>
160
+
161
+ <div class="flex flex-auto flex-col">
162
+ <apx-chart
163
+ class="h-20"
164
+ [chart]="impressionsChart.chart"
165
+ [colors]="impressionsChart.colors"
166
+ [fill]="impressionsChart.fill"
167
+ [series]="impressionsChart.series"
168
+ [stroke]="impressionsChart.stroke"
169
+ [tooltip]="impressionsChart.tooltip"
170
+ ></apx-chart>
171
+ </div>
172
+ </mat-card>
173
+
174
+ <!-- Visits -->
175
+ <mat-card
176
+ class="overflow-hidden"
177
+ appearance="outlined"
178
+ >
179
+ <div class="flex flex-col gap-y-2 p-6 pb-0">
180
+ <div class="truncate text-lg font-medium tracking-tight">
181
+ Visits
182
+ </div>
183
+
184
+ <div class="text-4xl font-semibold">
185
+ {{ data.visits.amount | number: '1.0-0' }}
186
+ </div>
187
+ <div class="flex items-center gap-x-1">
188
+ <mat-icon
189
+ class="text-green-600"
190
+ svgIcon="trending-up"
191
+ />
192
+ <div class="font-medium text-green-600">3%</div>
193
+ <div class="text-neutral-500">above target</div>
194
+ </div>
195
+ </div>
196
+
197
+ <div class="flex flex-auto flex-col">
198
+ <apx-chart
199
+ class="h-20"
200
+ [chart]="visitsChart.chart"
201
+ [colors]="visitsChart.colors"
202
+ [fill]="visitsChart.fill"
203
+ [series]="visitsChart.series"
204
+ [stroke]="visitsChart.stroke"
205
+ [tooltip]="visitsChart.tooltip"
206
+ ></apx-chart>
207
+ </div>
208
+ </mat-card>
209
+ </div>
210
+
211
+ <!-- Section title -->
212
+ <div class="mt-12 w-full">
213
+ <div class="text-xl font-semibold tracking-tighter sm:text-2xl">
214
+ Your Audience
215
+ </div>
216
+ <div class="text-neutral-500">
217
+ Demographic properties of your users and how they interact with your
218
+ content.
219
+ </div>
220
+ </div>
221
+
222
+ <!-- Visitors vs. Page Views -->
223
+ <mat-card
224
+ class="overflow-hidden"
225
+ appearance="outlined"
226
+ >
227
+ <div class="flex flex-col items-start justify-between gap-y-4 p-6 pb-0">
228
+ <div class="truncate text-lg leading-6 font-medium tracking-tight">
229
+ Visitors vs. Page Views
230
+ </div>
231
+
232
+ <div class="grid grid-cols-1 gap-8 sm:grid-cols-3 sm:gap-12">
233
+ <div class="flex flex-col">
234
+ <div class="flex items-center">
235
+ <div class="leading-5 font-medium text-neutral-500">
236
+ Overall Score
237
+ </div>
238
+ <mat-icon
239
+ class="ml-1.5 size-4 text-neutral-500"
240
+ svgIcon="info"
241
+ [matTooltip]="'Score is calculated by using the historical ratio between Page Views and Visitors. Best score is 1000, worst score is 0.'"
242
+ />
243
+ </div>
244
+ <div class="mt-2 flex items-end gap-x-2">
245
+ <div class="text-4xl leading-none font-bold tracking-tight">
246
+ {{ data.visitorsVsPageViews.overallScore }}
247
+ </div>
248
+ <div class="flex items-center gap-x-1">
249
+ <mat-icon
250
+ class="text-green-600"
251
+ svgIcon="arrow-up"
252
+ />
253
+ <div class="font-medium text-green-600">42.9%</div>
254
+ </div>
255
+ </div>
256
+ </div>
257
+ <div class="flex flex-col">
258
+ <div class="flex items-center">
259
+ <div class="leading-5 font-medium text-neutral-500">
260
+ Average Ratio
261
+ </div>
262
+ <mat-icon
263
+ class="ml-1.5 size-4 text-neutral-500"
264
+ svgIcon="info"
265
+ [matTooltip]="'Average Ratio is the average ratio between Page Views and Visitors'"
266
+ />
267
+ </div>
268
+ <div class="mt-2 flex items-end gap-x-2">
269
+ <div class="text-4xl leading-none font-bold tracking-tight">
270
+ {{ data.visitorsVsPageViews.averageRatio | number: '1.0-0' }}%
271
+ </div>
272
+ <div class="flex items-center gap-x-1">
273
+ <mat-icon
274
+ class="text-red-600"
275
+ svgIcon="arrow-down"
276
+ />
277
+ <div class="font-medium text-red-600">13.1%</div>
278
+ </div>
279
+ </div>
280
+ </div>
281
+ <div class="flex flex-col">
282
+ <div class="flex items-center">
283
+ <div class="leading-5 font-medium text-neutral-500">
284
+ Predicted Ratio
285
+ </div>
286
+ <mat-icon
287
+ class="ml-1.5 size-4 text-neutral-500"
288
+ svgIcon="info"
289
+ [matTooltip]="'Predicted Ratio is calculated by using historical ratio, current trends and your goal targets.'"
290
+ />
291
+ </div>
292
+ <div class="mt-2 flex items-end gap-x-2">
293
+ <div class="text-4xl leading-none font-bold tracking-tight">
294
+ {{
295
+ data.visitorsVsPageViews.predictedRatio | number: '1.0-0'
296
+ }}%
297
+ </div>
298
+ <div class="flex items-center gap-x-1">
299
+ <mat-icon
300
+ class="text-green-600"
301
+ svgIcon="arrow-up"
302
+ />
303
+ <div class="font-medium text-green-600">22.2%</div>
304
+ </div>
305
+ </div>
306
+ </div>
307
+ </div>
308
+ </div>
309
+
310
+ <div class="flex flex-auto flex-col">
311
+ <apx-chart
312
+ class="h-80"
313
+ [chart]="visitorsVsPageViewsChart.chart"
314
+ [colors]="visitorsVsPageViewsChart.colors"
315
+ [dataLabels]="visitorsVsPageViewsChart.dataLabels"
316
+ [grid]="visitorsVsPageViewsChart.grid"
317
+ [legend]="visitorsVsPageViewsChart.legend"
318
+ [series]="visitorsVsPageViewsChart.series"
319
+ [stroke]="visitorsVsPageViewsChart.stroke"
320
+ [tooltip]="visitorsVsPageViewsChart.tooltip()"
321
+ [xaxis]="visitorsVsPageViewsChart.xaxis"
322
+ [yaxis]="visitorsVsPageViewsChart.yaxis"
323
+ ></apx-chart>
324
+ </div>
325
+ </mat-card>
326
+
327
+ <div
328
+ class="mt-6 grid w-full grid-cols-1 gap-8 sm:grid-cols-2 md:mt-8 lg:grid-cols-4"
329
+ >
330
+ <!-- New vs. Returning -->
331
+ <mat-card
332
+ class="p-6"
333
+ appearance="outlined"
334
+ >
335
+ <div class="truncate text-lg font-medium tracking-tighter">
336
+ New vs. Returning
337
+ </div>
338
+
339
+ <div class="mt-6 flex flex-auto flex-col items-center">
340
+ <apx-chart
341
+ class="h-44"
342
+ [chart]="newVsReturningChart.chart"
343
+ [colors]="newVsReturningChart.colors"
344
+ [labels]="newVsReturningChart.labels"
345
+ [plotOptions]="newVsReturningChart.plotOptions"
346
+ [series]="newVsReturningChart.series"
347
+ [states]="newVsReturningChart.states"
348
+ [tooltip]="newVsReturningChart.tooltip()"
349
+ ></apx-chart>
350
+ </div>
351
+ <div class="mt-8 grid grid-cols-2">
352
+ @for (
353
+ dataset of data.newVsReturning.series;
354
+ track dataset;
355
+ let i = $index;
356
+ let last = $last
357
+ ) {
358
+ <div class="truncate">
359
+ {{ data.newVsReturning.labels[i] }}
360
+ </div>
361
+ <div class="text-right font-medium">
362
+ {{
363
+ (data.newVsReturning.uniqueVisitors * dataset) / 100
364
+ | number: '1.0-0'
365
+ }}
366
+ </div>
367
+
368
+ @if (!last) {
369
+ <mat-divider class="col-span-full my-2" />
370
+ }
371
+ }
372
+ </div>
373
+ </mat-card>
374
+
375
+ <!-- Gender -->
376
+ <mat-card
377
+ class="p-6"
378
+ appearance="outlined"
379
+ >
380
+ <div class="truncate text-lg font-medium tracking-tighter">
381
+ Gender
382
+ </div>
383
+
384
+ <div class="mt-6 flex flex-auto flex-col items-center">
385
+ <apx-chart
386
+ class="h-44"
387
+ [chart]="genderChart.chart"
388
+ [colors]="genderChart.colors"
389
+ [labels]="genderChart.labels"
390
+ [plotOptions]="genderChart.plotOptions"
391
+ [series]="genderChart.series"
392
+ [states]="genderChart.states"
393
+ [tooltip]="genderChart.tooltip()"
394
+ ></apx-chart>
395
+ </div>
396
+ <div class="mt-8 grid grid-cols-2">
397
+ @for (
398
+ dataset of data.gender.series;
399
+ track dataset;
400
+ let i = $index;
401
+ let last = $last
402
+ ) {
403
+ <div class="truncate">
404
+ {{ data.gender.labels[i] }}
405
+ </div>
406
+ <div class="text-right font-medium">
407
+ {{
408
+ (data.gender.uniqueVisitors * dataset) / 100 | number: '1.0-0'
409
+ }}
410
+ </div>
411
+
412
+ @if (!last) {
413
+ <mat-divider class="col-span-full my-2" />
414
+ }
415
+ }
416
+ </div>
417
+ </mat-card>
418
+
419
+ <!-- Age -->
420
+ <mat-card
421
+ class="p-6"
422
+ appearance="outlined"
423
+ >
424
+ <div class="truncate text-lg font-medium tracking-tighter">Age</div>
425
+
426
+ <div class="mt-6 flex flex-auto flex-col items-center">
427
+ <apx-chart
428
+ class="h-44"
429
+ [chart]="ageChart.chart"
430
+ [colors]="ageChart.colors"
431
+ [labels]="ageChart.labels"
432
+ [plotOptions]="ageChart.plotOptions"
433
+ [series]="ageChart.series"
434
+ [states]="ageChart.states"
435
+ [tooltip]="ageChart.tooltip()"
436
+ ></apx-chart>
437
+ </div>
438
+ <div class="mt-8 grid grid-cols-2">
439
+ @for (
440
+ dataset of data.age.series;
441
+ track dataset;
442
+ let i = $index;
443
+ let last = $last
444
+ ) {
445
+ <div class="truncate">
446
+ {{ data.age.labels[i] }}
447
+ </div>
448
+ <div class="text-right font-medium">
449
+ {{
450
+ (data.age.uniqueVisitors * dataset) / 100 | number: '1.0-0'
451
+ }}
452
+ </div>
453
+
454
+ @if (!last) {
455
+ <mat-divider class="col-span-full my-2" />
456
+ }
457
+ }
458
+ </div>
459
+ </mat-card>
460
+
461
+ <!-- Language -->
462
+ <mat-card
463
+ class="p-6"
464
+ appearance="outlined"
465
+ >
466
+ <div class="truncate text-lg font-medium tracking-tighter">
467
+ Language
468
+ </div>
469
+
470
+ <div class="mt-6 flex flex-auto flex-col items-center">
471
+ <apx-chart
472
+ class="h-44"
473
+ [chart]="languageChart.chart"
474
+ [colors]="languageChart.colors"
475
+ [labels]="languageChart.labels"
476
+ [plotOptions]="languageChart.plotOptions"
477
+ [series]="languageChart.series"
478
+ [states]="languageChart.states"
479
+ [tooltip]="languageChart.tooltip()"
480
+ ></apx-chart>
481
+ </div>
482
+ <div class="mt-8 grid grid-cols-2">
483
+ @for (
484
+ dataset of data.language.series;
485
+ track dataset;
486
+ let i = $index;
487
+ let last = $last
488
+ ) {
489
+ <div class="truncate">
490
+ {{ data.language.labels[i] }}
491
+ </div>
492
+ <div class="text-right font-medium">
493
+ {{
494
+ (data.language.uniqueVisitors * dataset) / 100
495
+ | number: '1.0-0'
496
+ }}
497
+ </div>
498
+
499
+ @if (!last) {
500
+ <mat-divider class="col-span-full my-2" />
501
+ }
502
+ }
503
+ </div>
504
+ </mat-card>
505
+ </div>
506
+ </div>
507
+ `,
508
+ })
509
+ export default class AnalyticsDashboard {
510
+ // Dependencies
511
+ private analyticsDashboardService = inject(AnalyticsDashboardService);
512
+ private theming = inject(Theming);
513
+
514
+ // Data
515
+ protected data = this.analyticsDashboardService.data;
516
+
517
+ // Visitors
518
+ protected visitorsChart: {
519
+ chart: ApexChart;
520
+ colors: string[];
521
+ dataLabels: ApexDataLabels;
522
+ fill: ApexFill;
523
+ grid: ApexGrid;
524
+ series: Record<string, ApexAxisChartSeries>;
525
+ stroke: ApexStroke;
526
+ tooltip: Signal<ApexTooltip>;
527
+ xaxis: ApexXAxis;
528
+ yaxis: ApexYAxis;
529
+ } = {
530
+ chart: {
531
+ animations: {
532
+ speed: 400,
533
+ animateGradually: {
534
+ enabled: false,
535
+ },
536
+ },
537
+ fontFamily: 'inherit',
538
+ foreColor: 'inherit',
539
+ width: '100%',
540
+ height: '100%',
541
+ type: 'area',
542
+ toolbar: {
543
+ show: false,
544
+ },
545
+ zoom: {
546
+ enabled: false,
547
+ },
548
+ },
549
+ colors: ['light-dark(var(--color-primary-600), var(--color-primary-500))'],
550
+ dataLabels: {
551
+ enabled: false,
552
+ },
553
+ fill: {
554
+ colors: ['light-dark(var(--color-primary-200), var(--color-primary-600)'],
555
+ gradient: {
556
+ gradientToColors: [
557
+ 'light-dark(var(--color-primary-50), var(--color-primary-800)',
558
+ ],
559
+ },
560
+ },
561
+ grid: {
562
+ show: true,
563
+ borderColor:
564
+ 'light-dark(var(--color-neutral-200), var(--color-neutral-700))',
565
+ padding: {
566
+ top: -4,
567
+ bottom: -40,
568
+ left: 0,
569
+ right: 0,
570
+ },
571
+ position: 'back',
572
+ xaxis: {
573
+ lines: {
574
+ show: true,
575
+ },
576
+ },
577
+ },
578
+ series: this.data.visitors.series,
579
+ stroke: {
580
+ width: 2,
581
+ },
582
+ tooltip: computed(() => ({
583
+ theme: this.theming.isDark() ? 'dark' : 'light',
584
+ x: {
585
+ format: 'MMM dd, yyyy',
586
+ },
587
+ y: {
588
+ formatter: (value: number): string => `${value}`,
589
+ },
590
+ })),
591
+ xaxis: {
592
+ axisBorder: {
593
+ show: false,
594
+ },
595
+ axisTicks: {
596
+ show: false,
597
+ },
598
+ crosshairs: {
599
+ stroke: {
600
+ color:
601
+ 'light-dark(var(--color-neutral-200), var(--color-neutral-400))',
602
+ dashArray: 0,
603
+ width: 2,
604
+ },
605
+ },
606
+ labels: {
607
+ offsetY: -20,
608
+ style: {
609
+ colors:
610
+ 'light-dark(var(--color-neutral-500), var(--color-neutral-400))',
611
+ },
612
+ },
613
+ tickAmount: 20,
614
+ tooltip: {
615
+ enabled: false,
616
+ },
617
+ type: 'datetime',
618
+ },
619
+ yaxis: {
620
+ axisTicks: {
621
+ show: false,
622
+ },
623
+ axisBorder: {
624
+ show: false,
625
+ },
626
+ min: (min): number => min - 750,
627
+ max: (max): number => max + 250,
628
+ tickAmount: 5,
629
+ show: false,
630
+ },
631
+ };
632
+
633
+ // Conversions
634
+ protected conversionsChart: {
635
+ chart: ApexChart;
636
+ colors: string[];
637
+ fill: ApexFill;
638
+ series: ApexAxisChartSeries;
639
+ stroke: ApexStroke;
640
+ tooltip: ApexTooltip;
641
+ } = {
642
+ chart: {
643
+ animations: {
644
+ enabled: false,
645
+ },
646
+ fontFamily: 'inherit',
647
+ foreColor: 'inherit',
648
+ height: '101%',
649
+ width: '101%',
650
+ type: 'area',
651
+ sparkline: {
652
+ enabled: true,
653
+ },
654
+ },
655
+ colors: ['light-dark(var(--color-neutral-600), var(--color-neutral-400)'],
656
+ fill: {
657
+ colors: ['light-dark(var(--color-neutral-200), var(--color-neutral-600)'],
658
+ gradient: {
659
+ gradientToColors: [
660
+ 'light-dark(var(--color-neutral-100), var(--color-neutral-700)',
661
+ ],
662
+ },
663
+ },
664
+ series: this.data.conversions.series,
665
+ stroke: {
666
+ curve: 'smooth',
667
+ width: 2,
668
+ },
669
+ tooltip: {
670
+ enabled: false,
671
+ },
672
+ };
673
+
674
+ // Impressions
675
+ protected impressionsChart: {
676
+ chart: ApexChart;
677
+ colors: string[];
678
+ fill: ApexFill;
679
+ series: ApexAxisChartSeries;
680
+ stroke: ApexStroke;
681
+ tooltip: ApexTooltip;
682
+ } = {
683
+ chart: {
684
+ animations: {
685
+ enabled: false,
686
+ },
687
+ fontFamily: 'inherit',
688
+ foreColor: 'inherit',
689
+ height: '101%',
690
+ width: '101%',
691
+ type: 'area',
692
+ sparkline: {
693
+ enabled: true,
694
+ },
695
+ },
696
+ colors: ['light-dark(var(--color-neutral-600), var(--color-neutral-400)'],
697
+ fill: {
698
+ colors: ['light-dark(var(--color-neutral-200), var(--color-neutral-600)'],
699
+ gradient: {
700
+ gradientToColors: [
701
+ 'light-dark(var(--color-neutral-100), var(--color-neutral-700)',
702
+ ],
703
+ },
704
+ },
705
+ series: this.data.impressions.series,
706
+ stroke: {
707
+ curve: 'smooth',
708
+ width: 2,
709
+ },
710
+ tooltip: {
711
+ enabled: false,
712
+ },
713
+ };
714
+
715
+ // Visits
716
+ protected visitsChart: {
717
+ chart: ApexChart;
718
+ colors: string[];
719
+ fill: ApexFill;
720
+ series: ApexAxisChartSeries;
721
+ stroke: ApexStroke;
722
+ tooltip: ApexTooltip;
723
+ } = {
724
+ chart: {
725
+ animations: {
726
+ enabled: false,
727
+ },
728
+ fontFamily: 'inherit',
729
+ foreColor: 'inherit',
730
+ height: '101%',
731
+ width: '101%',
732
+ type: 'area',
733
+ sparkline: {
734
+ enabled: true,
735
+ },
736
+ },
737
+ colors: ['light-dark(var(--color-neutral-600), var(--color-neutral-400)'],
738
+ fill: {
739
+ colors: ['light-dark(var(--color-neutral-200), var(--color-neutral-600)'],
740
+ gradient: {
741
+ gradientToColors: [
742
+ 'light-dark(var(--color-neutral-100), var(--color-neutral-700)',
743
+ ],
744
+ },
745
+ },
746
+ series: this.data.visits.series,
747
+ stroke: {
748
+ curve: 'smooth',
749
+ width: 2,
750
+ },
751
+ tooltip: {
752
+ enabled: false,
753
+ },
754
+ };
755
+
756
+ // Visitors vs Page Views
757
+ protected visitorsVsPageViewsChart: {
758
+ chart: ApexChart;
759
+ colors: string[];
760
+ dataLabels: ApexDataLabels;
761
+ fill: ApexFill;
762
+ grid: ApexGrid;
763
+ legend: ApexLegend;
764
+ series: ApexAxisChartSeries;
765
+ stroke: ApexStroke;
766
+ tooltip: Signal<ApexTooltip>;
767
+ xaxis: ApexXAxis;
768
+ yaxis: ApexYAxis;
769
+ } = {
770
+ chart: {
771
+ animations: {
772
+ enabled: false,
773
+ },
774
+ fontFamily: 'inherit',
775
+ foreColor: 'inherit',
776
+ height: '100%',
777
+ type: 'area',
778
+ toolbar: {
779
+ show: false,
780
+ },
781
+ zoom: {
782
+ enabled: false,
783
+ },
784
+ },
785
+ colors: ['#64748B', '#94A3B8'],
786
+ dataLabels: {
787
+ enabled: false,
788
+ },
789
+ fill: {
790
+ colors: ['#64748B', '#94A3B8'],
791
+ opacity: 0.5,
792
+ },
793
+ grid: {
794
+ show: false,
795
+ padding: {
796
+ bottom: -40,
797
+ left: 0,
798
+ right: 0,
799
+ },
800
+ },
801
+ legend: {
802
+ show: false,
803
+ },
804
+ series: this.data.visitorsVsPageViews.series,
805
+ stroke: {
806
+ curve: 'smooth',
807
+ width: 2,
808
+ },
809
+ tooltip: computed(() => ({
810
+ theme: this.theming.isDark() ? 'dark' : 'light',
811
+ x: {
812
+ format: 'MMM dd, yyyy',
813
+ },
814
+ })),
815
+ xaxis: {
816
+ axisBorder: {
817
+ show: false,
818
+ },
819
+ labels: {
820
+ offsetY: -20,
821
+ rotate: 0,
822
+ style: {
823
+ colors: 'var(--mat-sys-on-surface)',
824
+ },
825
+ },
826
+ tickAmount: 3,
827
+ tooltip: {
828
+ enabled: false,
829
+ },
830
+ type: 'datetime',
831
+ },
832
+ yaxis: {
833
+ labels: {
834
+ style: {
835
+ colors: 'var(--mat-sys-on-surface)',
836
+ },
837
+ },
838
+ max: (max): number => max + 250,
839
+ min: (min): number => min - 250,
840
+ show: false,
841
+ tickAmount: 5,
842
+ },
843
+ };
844
+
845
+ // New vs. returning
846
+ protected newVsReturningChart: {
847
+ chart: ApexChart;
848
+ colors: string[];
849
+ labels: string[];
850
+ plotOptions: ApexPlotOptions;
851
+ series: ApexNonAxisChartSeries;
852
+ states: ApexStates;
853
+ tooltip: Signal<ApexTooltip>;
854
+ } = {
855
+ chart: {
856
+ animations: {
857
+ speed: 400,
858
+ animateGradually: {
859
+ enabled: false,
860
+ },
861
+ },
862
+ fontFamily: 'inherit',
863
+ foreColor: 'inherit',
864
+ height: '100%',
865
+ type: 'donut',
866
+ sparkline: {
867
+ enabled: true,
868
+ },
869
+ },
870
+ colors: ['#3182CE', '#63B3ED'],
871
+ labels: this.data.newVsReturning.labels,
872
+ plotOptions: {
873
+ pie: {
874
+ customScale: 0.9,
875
+ expandOnClick: false,
876
+ donut: {
877
+ size: '70%',
878
+ },
879
+ },
880
+ },
881
+ series: this.data.newVsReturning.series,
882
+ states: {
883
+ hover: {
884
+ filter: {
885
+ type: 'none',
886
+ },
887
+ },
888
+ active: {
889
+ filter: {
890
+ type: 'none',
891
+ },
892
+ },
893
+ },
894
+ tooltip: computed(() => ({
895
+ theme: this.theming.isDark() ? 'dark' : 'light',
896
+ fillSeriesColor: false,
897
+ custom: ({
898
+ seriesIndex,
899
+ w,
900
+ }): string => `<div class="flex items-center h-8 min-h-8 max-h-8 px-3">
901
+ <div class="w-3 h-3 rounded-full" style="background-color: ${w.config.colors[seriesIndex]};"></div>
902
+ <div class="ml-2 leading-none">${w.config.labels[seriesIndex]}:</div>
903
+ <div class="ml-2 font-bold leading-none">${w.config.series[seriesIndex]}%</div>
904
+ </div>`,
905
+ })),
906
+ };
907
+
908
+ // Gender
909
+ protected genderChart: {
910
+ chart: ApexChart;
911
+ colors: string[];
912
+ labels: string[];
913
+ plotOptions: ApexPlotOptions;
914
+ series: ApexNonAxisChartSeries;
915
+ states: ApexStates;
916
+ tooltip: Signal<ApexTooltip>;
917
+ } = {
918
+ chart: {
919
+ animations: {
920
+ speed: 400,
921
+ animateGradually: {
922
+ enabled: false,
923
+ },
924
+ },
925
+ fontFamily: 'inherit',
926
+ foreColor: 'inherit',
927
+ height: '100%',
928
+ type: 'donut',
929
+ sparkline: {
930
+ enabled: true,
931
+ },
932
+ },
933
+ colors: ['#319795', '#4FD1C5'],
934
+ labels: this.data.gender.labels,
935
+ plotOptions: {
936
+ pie: {
937
+ customScale: 0.9,
938
+ expandOnClick: false,
939
+ donut: {
940
+ size: '70%',
941
+ },
942
+ },
943
+ },
944
+ series: this.data.gender.series,
945
+ states: {
946
+ hover: {
947
+ filter: {
948
+ type: 'none',
949
+ },
950
+ },
951
+ active: {
952
+ filter: {
953
+ type: 'none',
954
+ },
955
+ },
956
+ },
957
+ tooltip: computed(() => ({
958
+ theme: this.theming.isDark() ? 'dark' : 'light',
959
+ fillSeriesColor: false,
960
+ custom: ({
961
+ seriesIndex,
962
+ w,
963
+ }): string => `<div class="flex items-center h-8 min-h-8 max-h-8 px-3">
964
+ <div class="w-3 h-3 rounded-full" style="background-color: ${w.config.colors[seriesIndex]};"></div>
965
+ <div class="ml-2 leading-none">${w.config.labels[seriesIndex]}:</div>
966
+ <div class="ml-2 font-bold leading-none">${w.config.series[seriesIndex]}%</div>
967
+ </div>`,
968
+ })),
969
+ };
970
+
971
+ // Age
972
+ protected ageChart: {
973
+ chart: ApexChart;
974
+ colors: string[];
975
+ labels: string[];
976
+ plotOptions: ApexPlotOptions;
977
+ series: ApexNonAxisChartSeries;
978
+ states: ApexStates;
979
+ tooltip: Signal<ApexTooltip>;
980
+ } = {
981
+ chart: {
982
+ animations: {
983
+ speed: 400,
984
+ animateGradually: {
985
+ enabled: false,
986
+ },
987
+ },
988
+ fontFamily: 'inherit',
989
+ foreColor: 'inherit',
990
+ height: '100%',
991
+ type: 'donut',
992
+ sparkline: {
993
+ enabled: true,
994
+ },
995
+ },
996
+ colors: ['#DD6B20', '#F6AD55'],
997
+ labels: this.data.age.labels,
998
+ plotOptions: {
999
+ pie: {
1000
+ customScale: 0.9,
1001
+ expandOnClick: false,
1002
+ donut: {
1003
+ size: '70%',
1004
+ },
1005
+ },
1006
+ },
1007
+ series: this.data.age.series,
1008
+ states: {
1009
+ hover: {
1010
+ filter: {
1011
+ type: 'none',
1012
+ },
1013
+ },
1014
+ active: {
1015
+ filter: {
1016
+ type: 'none',
1017
+ },
1018
+ },
1019
+ },
1020
+ tooltip: computed(() => ({
1021
+ theme: this.theming.isDark() ? 'dark' : 'light',
1022
+ fillSeriesColor: false,
1023
+ custom: ({
1024
+ seriesIndex,
1025
+ w,
1026
+ }): string => `<div class="flex items-center h-8 min-h-8 max-h-8 px-3">
1027
+ <div class="w-3 h-3 rounded-full" style="background-color: ${w.config.colors[seriesIndex]};"></div>
1028
+ <div class="ml-2 leading-none">${w.config.labels[seriesIndex]}:</div>
1029
+ <div class="ml-2 font-bold leading-none">${w.config.series[seriesIndex]}%</div>
1030
+ </div>`,
1031
+ })),
1032
+ };
1033
+
1034
+ // Language
1035
+ protected languageChart: {
1036
+ chart: ApexChart;
1037
+ colors: string[];
1038
+ labels: string[];
1039
+ plotOptions: ApexPlotOptions;
1040
+ series: ApexNonAxisChartSeries;
1041
+ states: ApexStates;
1042
+ tooltip: Signal<ApexTooltip>;
1043
+ } = {
1044
+ chart: {
1045
+ animations: {
1046
+ speed: 400,
1047
+ animateGradually: {
1048
+ enabled: false,
1049
+ },
1050
+ },
1051
+ fontFamily: 'inherit',
1052
+ foreColor: 'inherit',
1053
+ height: '100%',
1054
+ type: 'donut',
1055
+ sparkline: {
1056
+ enabled: true,
1057
+ },
1058
+ },
1059
+ colors: ['#805AD5', '#B794F4'],
1060
+ labels: this.data.language.labels,
1061
+ plotOptions: {
1062
+ pie: {
1063
+ customScale: 0.9,
1064
+ expandOnClick: false,
1065
+ donut: {
1066
+ size: '70%',
1067
+ },
1068
+ },
1069
+ },
1070
+ series: this.data.language.series,
1071
+ states: {
1072
+ hover: {
1073
+ filter: {
1074
+ type: 'none',
1075
+ },
1076
+ },
1077
+ active: {
1078
+ filter: {
1079
+ type: 'none',
1080
+ },
1081
+ },
1082
+ },
1083
+ tooltip: computed(() => ({
1084
+ theme: this.theming.isDark() ? 'dark' : 'light',
1085
+ fillSeriesColor: false,
1086
+ custom: ({
1087
+ seriesIndex,
1088
+ w,
1089
+ }): string => `<div class="flex items-center h-8 min-h-8 max-h-8 px-3">
1090
+ <div class="w-3 h-3 rounded-full" style="background-color: ${w.config.colors[seriesIndex]};"></div>
1091
+ <div class="ml-2 leading-none">${w.config.labels[seriesIndex]}:</div>
1092
+ <div class="ml-2 font-bold leading-none">${w.config.series[seriesIndex]}%</div>
1093
+ </div>`,
1094
+ })),
1095
+ };
1096
+ }