@solidxai/core 0.1.6-beta.2 → 0.1.6-beta.21

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 (303) hide show
  1. package/dist/controllers/dashboard-layout.controller.d.ts +47 -0
  2. package/dist/controllers/dashboard-layout.controller.d.ts.map +1 -0
  3. package/dist/controllers/dashboard-layout.controller.js +204 -0
  4. package/dist/controllers/dashboard-layout.controller.js.map +1 -0
  5. package/dist/controllers/scheduled-job.controller.d.ts +1 -0
  6. package/dist/controllers/scheduled-job.controller.d.ts.map +1 -1
  7. package/dist/controllers/scheduled-job.controller.js +12 -0
  8. package/dist/controllers/scheduled-job.controller.js.map +1 -1
  9. package/dist/dtos/create-dashboard-layout.dto.d.ts +8 -0
  10. package/dist/dtos/create-dashboard-layout.dto.d.ts.map +1 -0
  11. package/dist/dtos/create-dashboard-layout.dto.js +53 -0
  12. package/dist/dtos/create-dashboard-layout.dto.js.map +1 -0
  13. package/dist/dtos/create-dashboard-variable.dto.d.ts +1 -0
  14. package/dist/dtos/create-dashboard-variable.dto.d.ts.map +1 -1
  15. package/dist/dtos/create-dashboard-variable.dto.js +7 -1
  16. package/dist/dtos/create-dashboard-variable.dto.js.map +1 -1
  17. package/dist/dtos/update-dashboard-layout.dto.d.ts +8 -0
  18. package/dist/dtos/update-dashboard-layout.dto.d.ts.map +1 -0
  19. package/dist/dtos/update-dashboard-layout.dto.js +53 -0
  20. package/dist/dtos/update-dashboard-layout.dto.js.map +1 -0
  21. package/dist/dtos/update-dashboard-variable.dto.d.ts +1 -0
  22. package/dist/dtos/update-dashboard-variable.dto.d.ts.map +1 -1
  23. package/dist/dtos/update-dashboard-variable.dto.js +7 -1
  24. package/dist/dtos/update-dashboard-variable.dto.js.map +1 -1
  25. package/dist/entities/action-metadata.entity.d.ts.map +1 -1
  26. package/dist/entities/action-metadata.entity.js.map +1 -1
  27. package/dist/entities/ai-interaction.entity.d.ts.map +1 -1
  28. package/dist/entities/ai-interaction.entity.js +5 -4
  29. package/dist/entities/ai-interaction.entity.js.map +1 -1
  30. package/dist/entities/chatter-message-details.entity.d.ts +1 -0
  31. package/dist/entities/chatter-message-details.entity.d.ts.map +1 -1
  32. package/dist/entities/chatter-message-details.entity.js +9 -4
  33. package/dist/entities/chatter-message-details.entity.js.map +1 -1
  34. package/dist/entities/chatter-message.entity.d.ts.map +1 -1
  35. package/dist/entities/chatter-message.entity.js +4 -3
  36. package/dist/entities/chatter-message.entity.js.map +1 -1
  37. package/dist/entities/common.entity.js +1 -1
  38. package/dist/entities/common.entity.js.map +1 -1
  39. package/dist/entities/dashboard-layout.entity.d.ts +9 -0
  40. package/dist/entities/dashboard-layout.entity.d.ts.map +1 -0
  41. package/dist/entities/dashboard-layout.entity.js +41 -0
  42. package/dist/entities/dashboard-layout.entity.js.map +1 -0
  43. package/dist/entities/dashboard-question-sql-dataset-config.entity.d.ts.map +1 -1
  44. package/dist/entities/dashboard-question-sql-dataset-config.entity.js +5 -4
  45. package/dist/entities/dashboard-question-sql-dataset-config.entity.js.map +1 -1
  46. package/dist/entities/dashboard-question.entity.d.ts.map +1 -1
  47. package/dist/entities/dashboard-question.entity.js +5 -4
  48. package/dist/entities/dashboard-question.entity.js.map +1 -1
  49. package/dist/entities/dashboard-variable.entity.d.ts +1 -0
  50. package/dist/entities/dashboard-variable.entity.d.ts.map +1 -1
  51. package/dist/entities/dashboard-variable.entity.js +10 -4
  52. package/dist/entities/dashboard-variable.entity.js.map +1 -1
  53. package/dist/entities/dashboard.entity.d.ts +2 -0
  54. package/dist/entities/dashboard.entity.d.ts.map +1 -1
  55. package/dist/entities/dashboard.entity.js +9 -3
  56. package/dist/entities/dashboard.entity.js.map +1 -1
  57. package/dist/entities/email-attachment.entity.d.ts.map +1 -1
  58. package/dist/entities/email-attachment.entity.js +2 -1
  59. package/dist/entities/email-attachment.entity.js.map +1 -1
  60. package/dist/entities/email-template.entity.js +1 -1
  61. package/dist/entities/email-template.entity.js.map +1 -1
  62. package/dist/entities/export-transaction.entity.d.ts.map +1 -1
  63. package/dist/entities/export-transaction.entity.js +2 -1
  64. package/dist/entities/export-transaction.entity.js.map +1 -1
  65. package/dist/entities/field-metadata.entity.js +2 -2
  66. package/dist/entities/field-metadata.entity.js.map +1 -1
  67. package/dist/entities/import-transaction-error-log.entity.d.ts.map +1 -1
  68. package/dist/entities/import-transaction-error-log.entity.js +3 -2
  69. package/dist/entities/import-transaction-error-log.entity.js.map +1 -1
  70. package/dist/entities/import-transaction.entity.d.ts.map +1 -1
  71. package/dist/entities/import-transaction.entity.js +2 -1
  72. package/dist/entities/import-transaction.entity.js.map +1 -1
  73. package/dist/entities/legacy-common.entity.d.ts.map +1 -1
  74. package/dist/entities/legacy-common.entity.js +1 -1
  75. package/dist/entities/legacy-common.entity.js.map +1 -1
  76. package/dist/entities/mq-message.entity.d.ts.map +1 -1
  77. package/dist/entities/mq-message.entity.js +5 -3
  78. package/dist/entities/mq-message.entity.js.map +1 -1
  79. package/dist/entities/saved-filters.entity.d.ts.map +1 -1
  80. package/dist/entities/saved-filters.entity.js +3 -2
  81. package/dist/entities/saved-filters.entity.js.map +1 -1
  82. package/dist/entities/security-rule.entity.d.ts.map +1 -1
  83. package/dist/entities/security-rule.entity.js +2 -1
  84. package/dist/entities/security-rule.entity.js.map +1 -1
  85. package/dist/entities/sms-template.entity.js +1 -1
  86. package/dist/entities/sms-template.entity.js.map +1 -1
  87. package/dist/entities/user-view-metadata.entity.d.ts.map +1 -1
  88. package/dist/entities/user-view-metadata.entity.js +2 -1
  89. package/dist/entities/user-view-metadata.entity.js.map +1 -1
  90. package/dist/entities/user.entity.d.ts.map +1 -1
  91. package/dist/entities/user.entity.js +2 -0
  92. package/dist/entities/user.entity.js.map +1 -1
  93. package/dist/entities/view-metadata.entity.d.ts.map +1 -1
  94. package/dist/entities/view-metadata.entity.js.map +1 -1
  95. package/dist/helpers/bootstrap.helper.d.ts +14 -0
  96. package/dist/helpers/bootstrap.helper.d.ts.map +1 -0
  97. package/dist/helpers/bootstrap.helper.js +132 -0
  98. package/dist/helpers/bootstrap.helper.js.map +1 -0
  99. package/dist/helpers/cache.helper.d.ts +2 -0
  100. package/dist/helpers/cache.helper.d.ts.map +1 -0
  101. package/dist/helpers/cache.helper.js +8 -0
  102. package/dist/helpers/cache.helper.js.map +1 -0
  103. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts +1 -0
  104. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts.map +1 -1
  105. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js +8 -9
  106. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js.map +1 -1
  107. package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.d.ts +2 -2
  108. package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.d.ts.map +1 -1
  109. package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.js +8 -5
  110. package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.js.map +1 -1
  111. package/dist/helpers/solid-registry.d.ts.map +1 -1
  112. package/dist/helpers/solid-registry.js.map +1 -1
  113. package/dist/helpers/typeorm-db-helper.d.ts.map +1 -1
  114. package/dist/helpers/typeorm-db-helper.js +21 -0
  115. package/dist/helpers/typeorm-db-helper.js.map +1 -1
  116. package/dist/index.d.ts +3 -0
  117. package/dist/index.d.ts.map +1 -1
  118. package/dist/index.js +3 -0
  119. package/dist/index.js.map +1 -1
  120. package/dist/interfaces.d.ts +5 -1
  121. package/dist/interfaces.d.ts.map +1 -1
  122. package/dist/interfaces.js.map +1 -1
  123. package/dist/jobs/computed-field-evaluation-queue-options.d.ts +1 -0
  124. package/dist/jobs/computed-field-evaluation-queue-options.d.ts.map +1 -1
  125. package/dist/jobs/computed-field-evaluation-queue-options.js +1 -0
  126. package/dist/jobs/computed-field-evaluation-queue-options.js.map +1 -1
  127. package/dist/repository/dashboard-layout.repository.d.ts +12 -0
  128. package/dist/repository/dashboard-layout.repository.d.ts.map +1 -0
  129. package/dist/repository/dashboard-layout.repository.js +34 -0
  130. package/dist/repository/dashboard-layout.repository.js.map +1 -0
  131. package/dist/seeders/module-metadata-seeder.service.js +4 -4
  132. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  133. package/dist/seeders/seed-data/solid-core-metadata.json +445 -35
  134. package/dist/services/authentication.service.d.ts.map +1 -1
  135. package/dist/services/authentication.service.js +44 -21
  136. package/dist/services/authentication.service.js.map +1 -1
  137. package/dist/services/chatter-message.service.d.ts +0 -1
  138. package/dist/services/chatter-message.service.d.ts.map +1 -1
  139. package/dist/services/chatter-message.service.js +22 -19
  140. package/dist/services/chatter-message.service.js.map +1 -1
  141. package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.d.ts +7 -3
  142. package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.d.ts.map +1 -1
  143. package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.js +61 -22
  144. package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.js.map +1 -1
  145. package/dist/services/crud.service.js +1 -1
  146. package/dist/services/crud.service.js.map +1 -1
  147. package/dist/services/dashboard-layout.service.d.ts +20 -0
  148. package/dist/services/dashboard-layout.service.d.ts.map +1 -0
  149. package/dist/services/dashboard-layout.service.js +120 -0
  150. package/dist/services/dashboard-layout.service.js.map +1 -0
  151. package/dist/services/dashboard-question.service.d.ts +4 -0
  152. package/dist/services/dashboard-question.service.d.ts.map +1 -1
  153. package/dist/services/dashboard-question.service.js +22 -8
  154. package/dist/services/dashboard-question.service.js.map +1 -1
  155. package/dist/services/dashboard.service.d.ts +2 -0
  156. package/dist/services/dashboard.service.d.ts.map +1 -1
  157. package/dist/services/dashboard.service.js +4 -0
  158. package/dist/services/dashboard.service.js.map +1 -1
  159. package/dist/services/model-metadata.service.d.ts +6 -1
  160. package/dist/services/model-metadata.service.d.ts.map +1 -1
  161. package/dist/services/model-metadata.service.js +151 -8
  162. package/dist/services/model-metadata.service.js.map +1 -1
  163. package/dist/services/permission-metadata.service.d.ts +5 -1
  164. package/dist/services/permission-metadata.service.d.ts.map +1 -1
  165. package/dist/services/permission-metadata.service.js +66 -20
  166. package/dist/services/permission-metadata.service.js.map +1 -1
  167. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts +2 -4
  168. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts.map +1 -1
  169. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js +2 -1
  170. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js.map +1 -1
  171. package/dist/services/question-data-providers/interfaces.d.ts +1 -0
  172. package/dist/services/question-data-providers/interfaces.d.ts.map +1 -0
  173. package/dist/services/question-data-providers/interfaces.js +1 -0
  174. package/dist/services/question-data-providers/interfaces.js.map +1 -0
  175. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts +2 -5
  176. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts.map +1 -1
  177. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js +2 -1
  178. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js.map +1 -1
  179. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts +2 -5
  180. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts.map +1 -1
  181. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js +2 -1
  182. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js.map +1 -1
  183. package/dist/services/queues/database-subscriber.service.d.ts +4 -2
  184. package/dist/services/queues/database-subscriber.service.d.ts.map +1 -1
  185. package/dist/services/queues/database-subscriber.service.js +15 -2
  186. package/dist/services/queues/database-subscriber.service.js.map +1 -1
  187. package/dist/services/queues/publisher-factory.service.d.ts.map +1 -1
  188. package/dist/services/queues/publisher-factory.service.js +4 -6
  189. package/dist/services/queues/publisher-factory.service.js.map +1 -1
  190. package/dist/services/queues/rabbitmq-subscriber.service.d.ts +8 -3
  191. package/dist/services/queues/rabbitmq-subscriber.service.d.ts.map +1 -1
  192. package/dist/services/queues/rabbitmq-subscriber.service.js +78 -6
  193. package/dist/services/queues/rabbitmq-subscriber.service.js.map +1 -1
  194. package/dist/services/scheduled-job.service.d.ts +6 -1
  195. package/dist/services/scheduled-job.service.d.ts.map +1 -1
  196. package/dist/services/scheduled-job.service.js +26 -2
  197. package/dist/services/scheduled-job.service.js.map +1 -1
  198. package/dist/services/scheduled-jobs/scheduler.interface.d.ts +2 -0
  199. package/dist/services/scheduled-jobs/scheduler.interface.d.ts.map +1 -1
  200. package/dist/services/scheduled-jobs/scheduler.interface.js.map +1 -1
  201. package/dist/services/scheduled-jobs/scheduler.service.d.ts +6 -2
  202. package/dist/services/scheduled-jobs/scheduler.service.d.ts.map +1 -1
  203. package/dist/services/scheduled-jobs/scheduler.service.js +75 -17
  204. package/dist/services/scheduled-jobs/scheduler.service.js.map +1 -1
  205. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.d.ts.map +1 -1
  206. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js +4 -1
  207. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js.map +1 -1
  208. package/dist/services/solid-ts-morph.service.d.ts +9 -0
  209. package/dist/services/solid-ts-morph.service.d.ts.map +1 -1
  210. package/dist/services/solid-ts-morph.service.js +76 -0
  211. package/dist/services/solid-ts-morph.service.js.map +1 -1
  212. package/dist/solid-core.module.d.ts.map +1 -1
  213. package/dist/solid-core.module.js +8 -0
  214. package/dist/solid-core.module.js.map +1 -1
  215. package/dist/subscribers/computed-entity-field.subscriber.js +3 -1
  216. package/dist/subscribers/computed-entity-field.subscriber.js.map +1 -1
  217. package/dist/transformers/typeorm/local-date-time-transformer.d.ts +4 -4
  218. package/dist/transformers/typeorm/local-date-time-transformer.d.ts.map +1 -1
  219. package/dist/transformers/typeorm/local-date-time-transformer.js +25 -28
  220. package/dist/transformers/typeorm/local-date-time-transformer.js.map +1 -1
  221. package/dist-tests/api/authenticate.spec.js +119 -0
  222. package/dist-tests/api/authenticate.spec.js.map +1 -0
  223. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +97 -0
  224. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +1 -0
  225. package/dist-tests/api/ping.spec.js +21 -0
  226. package/dist-tests/api/ping.spec.js.map +1 -0
  227. package/dist-tests/helpers/auth.js +41 -0
  228. package/dist-tests/helpers/auth.js.map +1 -0
  229. package/dist-tests/helpers/env.js +11 -0
  230. package/dist-tests/helpers/env.js.map +1 -0
  231. package/package.json +3 -1
  232. package/sql/default/mariadb/proc_CleanupModelMetadata.sql +153 -0
  233. package/sql/default/mariadb/proc_CleanupModuleMetadata.sql +56 -0
  234. package/sql/default/mysql/proc_CleanupModelMetadata.sql +153 -0
  235. package/sql/default/mysql/proc_CleanupModuleMetadata.sql +56 -0
  236. package/src/controllers/dashboard-layout.controller.ts +106 -0
  237. package/src/controllers/scheduled-job.controller.ts +6 -0
  238. package/src/dtos/create-dashboard-layout.dto.ts +31 -0
  239. package/src/dtos/create-dashboard-variable.dto.ts +4 -0
  240. package/src/dtos/update-dashboard-layout.dto.ts +30 -0
  241. package/src/dtos/update-dashboard-variable.dto.ts +5 -1
  242. package/src/entities/action-metadata.entity.ts +3 -2
  243. package/src/entities/ai-interaction.entity.ts +5 -4
  244. package/src/entities/chatter-message-details.entity.ts +7 -3
  245. package/src/entities/chatter-message.entity.ts +4 -3
  246. package/src/entities/common.entity.ts +2 -2
  247. package/src/entities/dashboard-layout.entity.ts +18 -0
  248. package/src/entities/dashboard-question-sql-dataset-config.entity.ts +5 -4
  249. package/src/entities/dashboard-question.entity.ts +5 -4
  250. package/src/entities/dashboard-variable.entity.ts +9 -4
  251. package/src/entities/dashboard.entity.ts +7 -2
  252. package/src/entities/email-attachment.entity.ts +2 -1
  253. package/src/entities/email-template.entity.ts +1 -1
  254. package/src/entities/export-transaction.entity.ts +2 -1
  255. package/src/entities/field-metadata.entity.ts +2 -2
  256. package/src/entities/import-transaction-error-log.entity.ts +3 -2
  257. package/src/entities/import-transaction.entity.ts +2 -1
  258. package/src/entities/legacy-common.entity.ts +3 -4
  259. package/src/entities/mq-message.entity.ts +5 -3
  260. package/src/entities/saved-filters.entity.ts +3 -2
  261. package/src/entities/security-rule.entity.ts +2 -1
  262. package/src/entities/sms-template.entity.ts +1 -1
  263. package/src/entities/user-view-metadata.entity.ts +2 -1
  264. package/src/entities/user.entity.ts +37 -2
  265. package/src/entities/view-metadata.entity.ts +3 -0
  266. package/src/helpers/bootstrap.helper.ts +222 -0
  267. package/src/helpers/cache.helper.ts +5 -0
  268. package/src/helpers/field-crud-managers/MediaFieldCrudManager.ts +9 -9
  269. package/src/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.ts +9 -6
  270. package/src/helpers/solid-registry.ts +1 -5
  271. package/src/helpers/typeorm-db-helper.ts +26 -0
  272. package/src/index.ts +3 -0
  273. package/src/interfaces.ts +9 -1
  274. package/src/jobs/computed-field-evaluation-queue-options.ts +1 -0
  275. package/src/repository/dashboard-layout.repository.ts +17 -0
  276. package/src/seeders/module-metadata-seeder.service.ts +5 -5
  277. package/src/seeders/seed-data/solid-core-metadata.json +446 -36
  278. package/src/services/authentication.service.ts +46 -24
  279. package/src/services/chatter-message.service.ts +21 -21
  280. package/src/services/computed-fields/entity/sequence-num-computed-field-provider.ts +79 -40
  281. package/src/services/crud.service.ts +1 -1
  282. package/src/services/dashboard-layout.service.ts +111 -0
  283. package/src/services/dashboard-question.service.ts +23 -4
  284. package/src/services/dashboard.service.ts +7 -0
  285. package/src/services/model-metadata.service.ts +173 -50
  286. package/src/services/permission-metadata.service.ts +73 -20
  287. package/src/services/question-data-providers/chartjs-sql-data-provider.service.ts +3 -7
  288. package/src/services/question-data-providers/interfaces.ts +0 -0
  289. package/src/services/question-data-providers/prime-react-datatable-sql-data-provider.service.ts +4 -8
  290. package/src/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.ts +4 -8
  291. package/src/services/queues/database-subscriber.service.ts +19 -2
  292. package/src/services/queues/publisher-factory.service.ts +8 -6
  293. package/src/services/queues/rabbitmq-subscriber.service.ts +123 -6
  294. package/src/services/scheduled-job.service.ts +31 -2
  295. package/src/services/scheduled-jobs/scheduler.interface.ts +4 -1
  296. package/src/services/scheduled-jobs/scheduler.service.ts +82 -20
  297. package/src/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.ts +4 -1
  298. package/src/services/solid-ts-morph.service.ts +98 -0
  299. package/src/solid-core.module.ts +13 -0
  300. package/src/subscribers/computed-entity-field.subscriber.ts +3 -3
  301. package/src/transformers/typeorm/local-date-time-transformer.ts +41 -33
  302. package/.claude/settings.local.json +0 -15
  303. package/src/services/1.js +0 -6
@@ -464,10 +464,6 @@ export class AuthenticationService {
464
464
 
465
465
  private async notifyUserOnOtpInitiateRegistration(user: User, registrationValidationSource: string) {
466
466
  const companyLogo = await this.getCompanyLogo();
467
- const dummyOtp = this.getDummyOtpForUser(user);
468
-
469
- if (dummyOtp)
470
- return; // Do nothing if dummy otp is configured.
471
467
  if (registrationValidationSource === PasswordlessLoginValidateWhatSources.EMAIL) {
472
468
  const mailService = this.mailServiceFactory.getMailService();
473
469
  mailService.sendEmailUsingTemplate(
@@ -594,13 +590,12 @@ export class AuthenticationService {
594
590
  return true;
595
591
  }
596
592
 
597
- private async otp(user?: User): Promise<otp> {
593
+ private async otp(): Promise<otp> {
598
594
  const now = new Date();
599
595
  const otpExpiry = this.settingService.getConfigValue<SolidCoreSetting>('otpExpiry');
600
- const dummyOtp = this.getDummyOtpForUser(user);
601
596
  now.setMinutes(now.getMinutes() + otpExpiry);
602
597
  return {
603
- token: dummyOtp ? dummyOtp : randomInt(100000, 999999).toString(),
598
+ token: randomInt(100000, 999999).toString(),
604
599
  expiresAt: now,
605
600
  };
606
601
  }
@@ -692,8 +687,11 @@ export class AuthenticationService {
692
687
 
693
688
  const type = this.resolveLoginType(signInDto);
694
689
  const user = await this.findUserForLogin(type, signInDto.identifier);
695
- await this.assignLoginOtp(user, type);
696
- this.notifyUserOnOtpInititateLogin(user, type);
690
+ const dummyOtp = this.getDummyOtpForUser(user);
691
+ if (!dummyOtp) {
692
+ await this.assignLoginOtp(user, type);
693
+ this.notifyUserOnOtpInititateLogin(user, type);
694
+ }
697
695
  return this.buildLoginOtpResponse(user, type);
698
696
  }
699
697
 
@@ -738,15 +736,22 @@ export class AuthenticationService {
738
736
  }
739
737
 
740
738
  private async assignLoginOtp(user: User, type: PasswordlessLoginValidateWhatSources): Promise<void> {
741
- const { token, expiresAt } = await this.otp(user);
739
+ const { token, expiresAt } = await this.otp();
742
740
  if (type === PasswordlessLoginValidateWhatSources.EMAIL) {
743
741
  user.emailVerificationTokenOnLogin = token;
744
742
  user.emailVerificationTokenOnLoginExpiresAt = expiresAt;
743
+ await this.userRepository.update(user.id, {
744
+ emailVerificationTokenOnLogin: token,
745
+ emailVerificationTokenOnLoginExpiresAt: expiresAt,
746
+ });
745
747
  } else {
746
748
  user.mobileVerificationTokenOnLogin = token;
747
749
  user.mobileVerificationTokenOnLoginExpiresAt = expiresAt;
750
+ await this.userRepository.update(user.id, {
751
+ mobileVerificationTokenOnLogin: token,
752
+ mobileVerificationTokenOnLoginExpiresAt: expiresAt,
753
+ });
748
754
  }
749
- await this.userRepository.save(user);
750
755
  }
751
756
 
752
757
  private buildLoginOtpResponse(user: User, type: PasswordlessLoginValidateWhatSources) {
@@ -815,6 +820,15 @@ export class AuthenticationService {
815
820
 
816
821
  const user = await this.findUserForLogin(type, identifier, { withRoles: true });
817
822
  this.checkAccountBlocked(user);
823
+ const dummyOtp = this.getDummyOtpForUser(user);
824
+
825
+ if (dummyOtp) {
826
+ if (otp !== dummyOtp) {
827
+ throw new UnauthorizedException(ERROR_MESSAGES.INVALID_OTP);
828
+ }
829
+ return this.buildLoginTokenResponse(user);
830
+ }
831
+
818
832
  try {
819
833
  this.validateLoginOtp(user, otp, type);
820
834
  } catch (e) {
@@ -822,14 +836,9 @@ export class AuthenticationService {
822
836
  throw e;
823
837
  }
824
838
 
825
- // we do not need to clear the otp when dummy otp is configured...
826
- const dummyOtp = this.getDummyOtpForUser(user);
827
- if (!dummyOtp)
828
- this.clearLoginOtp(user, type);
829
-
830
- user.failedLoginAttempts = 0;
839
+ await this.clearLoginOtp(user, type);
831
840
  await this.userActivityHistoryService.logEvent('login', user);
832
- await this.userRepository.save(user);
841
+ await this.resetFailedAttempts(user);
833
842
  return this.buildLoginTokenResponse(user);
834
843
  }
835
844
 
@@ -846,15 +855,27 @@ export class AuthenticationService {
846
855
  }
847
856
  }
848
857
 
849
- private clearLoginOtp(user: User, type: PasswordlessLoginValidateWhatSources): void {
858
+ private async clearLoginOtp(user: User, type: PasswordlessLoginValidateWhatSources): Promise<void> {
850
859
  if (type === PasswordlessLoginValidateWhatSources.EMAIL) {
851
- user.emailVerifiedOnLoginAt = new Date();
860
+ const verifiedAt = new Date();
861
+ user.emailVerifiedOnLoginAt = verifiedAt;
852
862
  user.emailVerificationTokenOnLogin = null;
853
863
  user.emailVerificationTokenOnLoginExpiresAt = null;
864
+ await this.userRepository.update(user.id, {
865
+ emailVerifiedOnLoginAt: verifiedAt,
866
+ emailVerificationTokenOnLogin: null,
867
+ emailVerificationTokenOnLoginExpiresAt: null,
868
+ });
854
869
  } else {
855
- user.mobileVerifiedOnLoginAt = new Date();
870
+ const verifiedAt = new Date();
871
+ user.mobileVerifiedOnLoginAt = verifiedAt;
856
872
  user.mobileVerificationTokenOnLogin = null;
857
873
  user.mobileVerificationTokenOnLoginExpiresAt = null;
874
+ await this.userRepository.update(user.id, {
875
+ mobileVerifiedOnLoginAt: verifiedAt,
876
+ mobileVerificationTokenOnLogin: null,
877
+ mobileVerificationTokenOnLoginExpiresAt: null,
878
+ });
858
879
  }
859
880
  }
860
881
 
@@ -1297,14 +1318,15 @@ export class AuthenticationService {
1297
1318
  }
1298
1319
 
1299
1320
  private async incrementFailedAttempts(user: User): Promise<void> {
1300
- user.failedLoginAttempts += 1;
1301
- await this.userRepository.save(user);
1321
+ const nextFailedAttempts = (user.failedLoginAttempts ?? 0) + 1;
1322
+ user.failedLoginAttempts = nextFailedAttempts;
1323
+ await this.userRepository.update(user.id, { failedLoginAttempts: nextFailedAttempts });
1302
1324
  }
1303
1325
 
1304
1326
  private async resetFailedAttempts(user: User): Promise<void> {
1305
1327
  if (user.failedLoginAttempts === 0) return;
1306
1328
  user.failedLoginAttempts = 0;
1307
- await this.userRepository.save(user);
1329
+ await this.userRepository.update(user.id, { failedLoginAttempts: 0 });
1308
1330
  }
1309
1331
 
1310
1332
  //FIXME - Pending implementation
@@ -1,4 +1,4 @@
1
- import dayjs from 'dayjs';
1
+ import { LocalDateTimeTransformer, serializeDate } from 'src/transformers/typeorm/local-date-time-transformer';
2
2
  import { forwardRef, Inject, Injectable } from '@nestjs/common';
3
3
  import { ModuleRef } from "@nestjs/core";
4
4
  import { InjectEntityManager } from '@nestjs/typeorm';
@@ -142,6 +142,7 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
142
142
  messageDetail.chatterMessage = savedMessage;
143
143
  messageDetail.fieldName = field.name;
144
144
  messageDetail.fieldDisplayName = field.displayName;
145
+ messageDetail.fieldType = field.type;
145
146
  messageDetail.oldValue = null;
146
147
  messageDetail.oldValueDisplay = null;
147
148
  messageDetail.newValue = this.formatFieldValue(field, fieldValue);
@@ -258,6 +259,7 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
258
259
  messageDetail.chatterMessage = savedMessage;
259
260
  messageDetail.fieldName = field.name;
260
261
  messageDetail.fieldDisplayName = field.displayName;
262
+ messageDetail.fieldType = field.type;
261
263
  messageDetail.oldValue = this.formatFieldValue(field, oldValue);
262
264
  messageDetail.newValue = this.formatFieldValue(field, newValue);
263
265
  messageDetail.oldValueDisplay = await this.formatFieldValueDisplay(field, oldValue);
@@ -322,30 +324,12 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
322
324
  }
323
325
 
324
326
  if (value instanceof Date) {
325
- return value.toISOString();
327
+ return serializeDate(value);
326
328
  }
327
329
 
328
330
  return value.toString();
329
331
  }
330
332
 
331
- private formatDateForDisplay(field: any, value: any): string {
332
- const date = dayjs(value);
333
-
334
- if (!date.isValid()) {
335
- return value?.toString?.() ?? '';
336
- }
337
-
338
- if (field.type === 'date') {
339
- return date.format('DD-MM-YYYY');
340
- }
341
-
342
- if (field.type === 'time') {
343
- return date.format('HH:mm');
344
- }
345
-
346
- return date.format('DD-MM-YYYY HH:mm');
347
- }
348
-
349
333
  private async formatFieldValueDisplay(field: any, value: any): Promise<string> {
350
334
  if (value === null || value === undefined) {
351
335
  return '';
@@ -356,7 +340,7 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
356
340
  }
357
341
 
358
342
  if (['date', 'datetime', 'time'].includes(field.type)) {
359
- return this.formatDateForDisplay(field, value);
343
+ return null;
360
344
  }
361
345
 
362
346
  if (field.type === 'relation') {
@@ -644,6 +628,22 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
644
628
  const [entities, count] = await qb.getManyAndCount();
645
629
  this.logHeapUsed('getChatterMessages-entitiesLoaded');
646
630
 
631
+ // Convert date strings in message details to ISO format for consistent handling on the frontend
632
+ const DATE_FIELD_TYPES = ['date', 'datetime', 'time'];
633
+ for (const entity of entities) {
634
+ for (const detail of entity.chatterMessageDetails ?? []) {
635
+ if (!detail.fieldType || !DATE_FIELD_TYPES.includes(detail.fieldType)) continue;
636
+ if (detail.oldValue) {
637
+ const d = LocalDateTimeTransformer.from(detail.oldValue);
638
+ if (d) detail.oldValue = d.toISOString();
639
+ }
640
+ if (detail.newValue) {
641
+ const d = LocalDateTimeTransformer.from(detail.newValue);
642
+ if (d) detail.newValue = d.toISOString();
643
+ }
644
+ }
645
+ }
646
+
647
647
  if (populateMedia && populateMedia.length > 0) {
648
648
  const normalizedPopulateMedia = this.crudHelperService.normalize(populateMedia);
649
649
  this.logHeapUsed('getChatterMessages-beforePopulateMedia');
@@ -1,20 +1,28 @@
1
+ import { classify } from "@angular-devkit/core/src/utils/strings";
1
2
  import { Injectable } from "@nestjs/common";
2
3
  import { InjectDataSource } from "@nestjs/typeorm";
4
+ import { ComputedFieldTriggerOperation } from "src/dtos/create-field-metadata.dto";
3
5
  import { ComputedFieldProvider } from "src/decorators/computed-field-provider.decorator";
4
6
  import { CommonEntity } from "src/entities/common.entity";
5
7
  import { ModelSequence } from "src/entities/model-sequence.entity";
6
8
  import { ComputedFieldMetadata } from "src/helpers/solid-registry";
7
- import { IEntityPreComputeFieldProvider } from "src/interfaces";
8
- import { DataSource, EntityTarget } from "typeorm";
9
+ import { IEntityPostComputeFieldProvider } from "src/interfaces";
10
+ import { DataSource, EntityManager } from "typeorm";
9
11
 
10
12
 
11
13
  export interface SequenceNumComputedFieldContext {
12
- sequenceName: string; // The separator to use between concatenated values
14
+ sequenceName: string;
15
+ /**
16
+ * - `'counter'` (default): increments the sequence's `currentValue` and uses it as the number.
17
+ * - `'entityId'`: uses the entity's own `id` as the number; does not update the counter.
18
+ * Only valid on `afterInsert` events.
19
+ */
20
+ mode?: 'counter' | 'entityId';
13
21
  }
14
22
 
15
23
  @ComputedFieldProvider()
16
24
  @Injectable()
17
- export class SequenceNumComputedFieldProvider<T extends CommonEntity> implements IEntityPreComputeFieldProvider<T, SequenceNumComputedFieldContext> {
25
+ export class SequenceNumComputedFieldProvider<T extends CommonEntity> implements IEntityPostComputeFieldProvider<T, SequenceNumComputedFieldContext> {
18
26
  constructor(
19
27
  @InjectDataSource()
20
28
  private readonly dataSource: DataSource
@@ -25,23 +33,21 @@ export class SequenceNumComputedFieldProvider<T extends CommonEntity> implements
25
33
  }
26
34
 
27
35
  help(): string {
28
- return "Computed field provider used to create fields whose value is based on some prefix, padding & sequence number.";
36
+ return "Computed field provider used to create fields whose value is based on some prefix, padding & sequence number. " +
37
+ "Use mode='counter' (default) to auto-increment the sequence's currentValue. " +
38
+ "Use mode='entityId' to use the entity's own id as the number (afterInsert only, does not update the counter).";
29
39
  }
30
40
 
31
- async preComputeValue(triggerEntity: T, computedFieldMetadata: ComputedFieldMetadata<SequenceNumComputedFieldContext>) {
32
- const { sequenceName } =
33
- computedFieldMetadata.computedFieldValueProviderCtxt ?? {};
34
-
35
- if (!sequenceName) {
36
- throw new Error("sequenceName is required for sequence computation");
37
- }
41
+ private buildSequenceString(modelSequence: ModelSequence, numericValue: number): string {
42
+ const prefix = modelSequence.prefix ?? "";
43
+ const separator = modelSequence.separator ?? "";
44
+ const padded = String(numericValue).padStart(modelSequence.padding ?? 5, "0");
45
+ return `${prefix}${separator}${padded}`;
46
+ }
38
47
 
39
- await this.dataSource.transaction(async (manager) => {
40
- /**
41
- * 1️⃣ Lock sequence row (prevents race conditions)
42
- */
43
- // 1️⃣ Fetch sequence row
44
- const modelSequenceRepo = manager.getRepository(ModelSequence)
48
+ private async generateCounterSequenceValue(sequenceName: string, manager?: EntityManager): Promise<{ sequenceString: string; currentValue: number; modelSingularName: string }> {
49
+ const run = async (mgr: EntityManager) => {
50
+ const modelSequenceRepo = mgr.getRepository(ModelSequence);
45
51
  const modelSequence = await modelSequenceRepo.findOne({
46
52
  where: { sequenceName },
47
53
  lock: { mode: "pessimistic_write" }
@@ -51,36 +57,69 @@ export class SequenceNumComputedFieldProvider<T extends CommonEntity> implements
51
57
  throw new Error(`ModelSequence not found for ${sequenceName}`);
52
58
  }
53
59
 
54
- // 2️⃣ Generate next sequence value
55
60
  const nextValue = modelSequence.currentValue + 1;
61
+ const sequenceString = this.buildSequenceString(modelSequence, nextValue);
56
62
 
57
- const paddedValue = String(nextValue).padStart(modelSequence.padding ?? 5, "0");
63
+ modelSequence.currentValue = nextValue;
64
+ await modelSequenceRepo.save(modelSequence);
58
65
 
59
- const prefix = modelSequence.prefix ?? "";
60
- const separator = modelSequence.separator ?? "";
66
+ // Load model relation in a separate query to avoid FOR UPDATE on joined relation.
67
+ const modelSequenceWithModel = await modelSequenceRepo.findOne({
68
+ where: { id: modelSequence.id },
69
+ relations: { model: true },
70
+ });
71
+ const modelSingularName = modelSequenceWithModel?.model?.singularName;
72
+ if (!modelSingularName) {
73
+ throw new Error(`Model singularName not found for sequence ${sequenceName}`);
74
+ }
61
75
 
62
- const sequenceString = `${prefix}${separator}${paddedValue}`;
76
+ return { sequenceString, currentValue: nextValue, modelSingularName };
77
+ };
63
78
 
64
- // 3️⃣ Duplicate check on TARGET ENTITY (extra safety)
65
- const entityRepo = manager.getRepository(triggerEntity.constructor as any);
79
+ return manager ? run(manager) : this.dataSource.transaction(run);
80
+ }
66
81
 
67
- const existing = await entityRepo.findOne({
68
- where: {
69
- [computedFieldMetadata.fieldName]: sequenceString,
70
- },
71
- });
82
+ private async generateEntityIdSequenceValue(sequenceName: string, entityId: number): Promise<{ sequenceString: string; modelSingularName: string }> {
83
+ const modelSequenceRepo = this.dataSource.manager.getRepository(ModelSequence);
84
+ const modelSequence = await modelSequenceRepo.findOne({
85
+ where: { sequenceName },
86
+ relations: { model: true },
87
+ });
72
88
 
73
- if (existing) {
74
- throw new Error(`Duplicate Sequence generated: ${sequenceString}`);
75
- }
89
+ if (!modelSequence) {
90
+ throw new Error(`ModelSequence not found for ${sequenceName}`);
91
+ }
76
92
 
77
- // 4️⃣ set the computed field on the entity
78
- (triggerEntity as any)[computedFieldMetadata.fieldName] = sequenceString;
93
+ const modelSingularName = modelSequence.model?.singularName;
94
+ if (!modelSingularName) {
95
+ throw new Error(`Model singularName not found for sequence ${sequenceName}`);
96
+ }
79
97
 
80
- // 5️⃣ Persist updated sequence current value
81
- modelSequence.currentValue = nextValue;
82
- await modelSequenceRepo.save(modelSequence);
83
- });
98
+ return { sequenceString: this.buildSequenceString(modelSequence, entityId), modelSingularName };
84
99
  }
85
100
 
86
- }
101
+ async postComputeAndSaveValue(triggerEntity: T, computedFieldMetadata: ComputedFieldMetadata<SequenceNumComputedFieldContext>): Promise<void> {
102
+ const { sequenceName, mode = 'counter' } = computedFieldMetadata.computedFieldValueProviderCtxt ?? {};
103
+
104
+ if (!sequenceName) {
105
+ throw new Error("sequenceName is required for sequence computation");
106
+ }
107
+
108
+ let sequenceString: string;
109
+ let modelSingularName: string;
110
+
111
+ if (mode === 'entityId') {
112
+ const eventType = computedFieldMetadata.eventContext?.eventType;
113
+ if (eventType !== ComputedFieldTriggerOperation.afterInsert) {
114
+ throw new Error(`SequenceNumComputedFieldProvider with mode='entityId' only supports "${ComputedFieldTriggerOperation.afterInsert}" events, but received "${eventType}"`);
115
+ }
116
+ ({ sequenceString, modelSingularName } = await this.generateEntityIdSequenceValue(sequenceName, triggerEntity.id));
117
+ } else {
118
+ ({ sequenceString, modelSingularName } = await this.generateCounterSequenceValue(sequenceName));
119
+ }
120
+
121
+ const entityName = classify(modelSingularName);
122
+ const entityRepo = this.dataSource.manager.getRepository(entityName);
123
+ await entityRepo.update(triggerEntity.id, { [computedFieldMetadata.fieldName]: sequenceString });
124
+ }
125
+ }
@@ -432,7 +432,7 @@ export class CRUDService<T extends CommonEntity> { // Add two generic value i.e
432
432
  // dataSource: string; // The name of the selection provider
433
433
  // filterSchema : json // This is a custom json object that every data source will handle accordingly. We could validate the query against the selection provider
434
434
  // values : string[]; // The values returned by the selection provider
435
- const options = { ...commonOptions, selectionDynamicProvider: fieldMetadata.selectionDynamicProvider, selectionDynamicProviderCtxt: fieldMetadata.selectionDynamicProviderCtxt, selectionValueType: fieldMetadata.selectionValueType as SelectionValueType, discoveryService: this.discoveryService, isMultiSelect: fieldMetadata.isMultiSelect };
435
+ const options = { ...commonOptions, selectionDynamicProvider: fieldMetadata.selectionDynamicProvider, selectionDynamicProviderCtxt: JSON.parse(fieldMetadata.selectionDynamicProviderCtxt), selectionValueType: fieldMetadata.selectionValueType as SelectionValueType, discoveryService: this.discoveryService, isMultiSelect: fieldMetadata.isMultiSelect };
436
436
  return new SelectionDynamicFieldCrudManager(options);
437
437
  }
438
438
  case SolidFieldType.uuid: {
@@ -0,0 +1,111 @@
1
+ import { Injectable, Logger } from '@nestjs/common';
2
+ import { ModuleRef } from "@nestjs/core";
3
+ import { InjectEntityManager } from '@nestjs/typeorm';
4
+ import { EntityManager } from 'typeorm';
5
+
6
+ import { CRUDService } from 'src/services/crud.service';
7
+ import { DashboardLayout } from 'src/entities/dashboard-layout.entity';
8
+ import { DashboardLayoutRepository } from 'src/repository/dashboard-layout.repository';
9
+ import { CreateDashboardLayoutDto } from 'src/dtos/create-dashboard-layout.dto';
10
+ import { RequestContextService } from './request-context.service';
11
+
12
+
13
+ @Injectable()
14
+ export class DashboardLayoutService extends CRUDService<DashboardLayout> {
15
+ private readonly logger = new Logger(this.constructor.name);
16
+ constructor(
17
+ @InjectEntityManager()
18
+ readonly entityManager: EntityManager,
19
+ readonly repo: DashboardLayoutRepository,
20
+ readonly requestContextService: RequestContextService,
21
+ readonly moduleRef: ModuleRef,
22
+ ) {
23
+ super(entityManager, repo, 'dashboardLayout', 'solid-core', moduleRef);
24
+ }
25
+
26
+ async upsertUserDashboardLayout(createDtos: CreateDashboardLayoutDto) {
27
+ const activeUser = this.requestContextService.getActiveUser();
28
+
29
+ if (!activeUser) {
30
+ throw new Error('User not found');
31
+ }
32
+
33
+ let userId = null;
34
+ if (activeUser.roles.includes('Admin')) {
35
+ userId = null;
36
+ } else {
37
+ userId = activeUser?.sub;
38
+ }
39
+ const existingLayout = await this.repo.findOne({
40
+ where: {
41
+ user: { id: userId },
42
+ dashboard: {
43
+ id: createDtos.dashboardId
44
+ }
45
+ },
46
+ relations: {
47
+ user: true,
48
+ dashboard: true,
49
+ }
50
+ });
51
+
52
+ if (existingLayout) {
53
+ return super.update(existingLayout.id, { layout: createDtos.layout }, [], true);
54
+ } else {
55
+ const createDto = {
56
+ layout: createDtos.layout,
57
+ dashboardId: createDtos.dashboardId,
58
+ uesrId: userId
59
+ }
60
+ return super.create(createDto, []);
61
+ }
62
+ }
63
+
64
+ async getUserDashboardLayoutByDashboardId(dashboardId: any) {
65
+ const activeUser = this.requestContextService.getActiveUser();
66
+
67
+ if (!activeUser) {
68
+ throw new Error('User not found');
69
+ }
70
+ const userId = activeUser?.sub;
71
+ const existingUserLayout = await this.repo.findOne({
72
+ where: {
73
+ user: { id: userId },
74
+ dashboard: {
75
+ id: dashboardId
76
+ }
77
+ },
78
+ relations: {
79
+ user: true,
80
+ dashboard: true,
81
+ }
82
+ });
83
+ if (existingUserLayout) {
84
+ // if dahsboard for userid exists
85
+ return existingUserLayout;
86
+ }
87
+
88
+ // if not then check for default dashboard
89
+ const defaultLayout = await this.repo.findOne({
90
+ where: {
91
+ user: { id: null },
92
+ dashboard: {
93
+ id: dashboardId
94
+ }
95
+ },
96
+ relations: {
97
+ user: true,
98
+ dashboard: true,
99
+ }
100
+ });
101
+ if (defaultLayout) {
102
+ // if default layout exists return it
103
+ return defaultLayout;
104
+ } else {
105
+ // if default layout does not exist return empty layout
106
+ return {
107
+ layout: null
108
+ }
109
+ }
110
+ }
111
+ }
@@ -11,15 +11,18 @@ import { SolidRegistry } from 'src/helpers/solid-registry';
11
11
  import { DashboardQuestion } from '../entities/dashboard-question.entity';
12
12
  import { SqlExpression, SqlExpressionOperator } from './question-data-providers/chartjs-sql-data-provider.service';
13
13
  import { DashboardQuestionRepository } from 'src/repository/dashboard-question.repository';
14
+ import { QuestionSqlDataProviderContext } from 'src';
14
15
 
15
16
  enum SOURCE_TYPE {
16
17
  SQL = 'sql',
17
18
  PROVIDER = 'provider',
18
19
  }
19
20
 
20
- const CHARTJS_SQL_DATA_PROVIDER_NAME = 'ChartJsSqlDataProvider';
21
- const PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME = 'PrimeReactMeterGroupSqlDataProvider';
22
- const PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME = 'PrimeReactDatatableSqlDataProvider';
21
+ export const CHARTJS_SQL_DATA_PROVIDER_NAME = 'ChartJsSqlDataProvider';
22
+ export const PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME = 'PrimeReactMeterGroupSqlDataProvider';
23
+ export const PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME = 'PrimeReactDatatableSqlDataProvider';
24
+
25
+ export const INBUILT_SQL_DATA_PROVIDERS = [CHARTJS_SQL_DATA_PROVIDER_NAME, PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME, PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME];
23
26
 
24
27
  @Injectable()
25
28
  export class DashboardQuestionService extends CRUDService<DashboardQuestion> {
@@ -50,22 +53,38 @@ export class DashboardQuestionService extends CRUDService<DashboardQuestion> {
50
53
 
51
54
  // Try to resolve the dataProvider based on a combination of sourceType and visualisedAs
52
55
  let dataProvider = null;
56
+ let context = {};
53
57
 
58
+ // Decide which data provider to use based on the question visualisation type if sourceType is SQL.
54
59
  if (question.sourceType === SOURCE_TYPE.SQL && ['bar', 'pie', 'line', 'donut'].includes(question.visualisedAs)) {
55
60
  dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(CHARTJS_SQL_DATA_PROVIDER_NAME);
61
+ context = {
62
+ expressions,
63
+ } as QuestionSqlDataProviderContext;
56
64
  }
57
65
  if (question.sourceType === SOURCE_TYPE.SQL && ['prime-meter-group'].includes(question.visualisedAs)) {
58
66
  dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME);
67
+ context = {
68
+ expressions,
69
+ } as QuestionSqlDataProviderContext;
59
70
  }
60
71
  if (question.sourceType === SOURCE_TYPE.SQL && ['prime-datatable'].includes(question.visualisedAs)) {
61
72
  dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME);
73
+ context = {
74
+ expressions,
75
+ } as QuestionSqlDataProviderContext;
76
+ }
77
+
78
+ // If a custom provider is specified, use that one instead
79
+ if (question.sourceType === SOURCE_TYPE.PROVIDER) {
80
+ dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(question.providerName);
62
81
  }
63
82
 
64
83
  if (!dataProvider) {
65
84
  throw new NotImplementedException(`Invalid data source type ${question.sourceType}`);
66
85
  }
67
86
 
68
- return await dataProvider.getData(question, expressions);
87
+ return await dataProvider.getData(question, context);
69
88
 
70
89
  }
71
90
 
@@ -15,6 +15,7 @@ import { SolidRegistry } from 'src/helpers/solid-registry';
15
15
  import { DashboardMapper } from 'src/mappers/dashboard-mapper';
16
16
  import { DashboardRepository } from 'src/repository/dashboard.repository';
17
17
  import { Dashboard } from '../entities/dashboard.entity';
18
+ import { CreateDashboardDto } from 'src/dtos/create-dashboard.dto';
18
19
 
19
20
 
20
21
  export const SQL_DYNAMIC_PROVIDER_NAME = 'DashboardVariableSQLDynamicProvider';
@@ -33,6 +34,12 @@ export class DashboardService extends CRUDService<Dashboard> {
33
34
  super(entityManager, repo, 'dashboard', 'solid-core', moduleRef);
34
35
  }
35
36
 
37
+
38
+ async create(createDto: CreateDashboardDto, files: Express.Multer.File[]) {
39
+ createDto.name = createDto.name.trim().replace(/\s+/g, '-').toLowerCase();
40
+ return super.create(createDto, files);
41
+ }
42
+
36
43
  async getSelectionDynamicValues(query: DashboardVariableSelectionDynamicQueryDto) {
37
44
  // Get the dashboard variable repo
38
45
  const dashboardVariable = await this.loadDashboardVariable(query.variableId);