@solidstarters/solid-core 1.2.133 → 1.2.135

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 (278) hide show
  1. package/dist/controllers/ai-interaction.controller.d.ts +45 -0
  2. package/dist/controllers/ai-interaction.controller.d.ts.map +1 -0
  3. package/dist/controllers/ai-interaction.controller.js +192 -0
  4. package/dist/controllers/ai-interaction.controller.js.map +1 -0
  5. package/dist/controllers/dashboard-variable.controller.d.ts +43 -0
  6. package/dist/controllers/dashboard-variable.controller.d.ts.map +1 -0
  7. package/dist/controllers/dashboard-variable.controller.js +179 -0
  8. package/dist/controllers/dashboard-variable.controller.js.map +1 -0
  9. package/dist/controllers/dashboard.controller.d.ts +45 -0
  10. package/dist/controllers/dashboard.controller.d.ts.map +1 -0
  11. package/dist/controllers/dashboard.controller.js +192 -0
  12. package/dist/controllers/dashboard.controller.js.map +1 -0
  13. package/dist/controllers/question-sql-dataset-config.controller.d.ts +43 -0
  14. package/dist/controllers/question-sql-dataset-config.controller.d.ts.map +1 -0
  15. package/dist/controllers/question-sql-dataset-config.controller.js +179 -0
  16. package/dist/controllers/question-sql-dataset-config.controller.js.map +1 -0
  17. package/dist/controllers/question.controller.d.ts +45 -0
  18. package/dist/controllers/question.controller.d.ts.map +1 -0
  19. package/dist/controllers/question.controller.js +194 -0
  20. package/dist/controllers/question.controller.js.map +1 -0
  21. package/dist/controllers/test.controller.d.ts.map +1 -1
  22. package/dist/controllers/test.controller.js.map +1 -1
  23. package/dist/decorators/dashboard-question-data-provider.decorator.d.ts +3 -0
  24. package/dist/decorators/dashboard-question-data-provider.decorator.d.ts.map +1 -0
  25. package/dist/decorators/dashboard-question-data-provider.decorator.js +11 -0
  26. package/dist/decorators/dashboard-question-data-provider.decorator.js.map +1 -0
  27. package/dist/decorators/dashboard-selection-provider.decorator.d.ts +3 -0
  28. package/dist/decorators/dashboard-selection-provider.decorator.d.ts.map +1 -0
  29. package/dist/decorators/dashboard-selection-provider.decorator.js +11 -0
  30. package/dist/decorators/dashboard-selection-provider.decorator.js.map +1 -0
  31. package/dist/dtos/create-ai-interaction.dto.d.ts +14 -0
  32. package/dist/dtos/create-ai-interaction.dto.d.ts.map +1 -0
  33. package/dist/dtos/create-ai-interaction.dto.js +90 -0
  34. package/dist/dtos/create-ai-interaction.dto.js.map +1 -0
  35. package/dist/dtos/create-dashboard-variable.dto.d.ts +18 -0
  36. package/dist/dtos/create-dashboard-variable.dto.d.ts.map +1 -0
  37. package/dist/dtos/create-dashboard-variable.dto.js +97 -0
  38. package/dist/dtos/create-dashboard-variable.dto.js.map +1 -0
  39. package/dist/dtos/create-dashboard.dto.d.ts +15 -0
  40. package/dist/dtos/create-dashboard.dto.d.ts.map +1 -0
  41. package/dist/dtos/create-dashboard.dto.js +90 -0
  42. package/dist/dtos/create-dashboard.dto.js.map +1 -0
  43. package/dist/dtos/create-question-sql-dataset-config.dto.d.ts +12 -0
  44. package/dist/dtos/create-question-sql-dataset-config.dto.d.ts.map +1 -0
  45. package/dist/dtos/create-question-sql-dataset-config.dto.js +77 -0
  46. package/dist/dtos/create-question-sql-dataset-config.dto.js.map +1 -0
  47. package/dist/dtos/create-question.dto.d.ts +16 -0
  48. package/dist/dtos/create-question.dto.d.ts.map +1 -0
  49. package/dist/dtos/create-question.dto.js +99 -0
  50. package/dist/dtos/create-question.dto.js.map +1 -0
  51. package/dist/dtos/dashboard-variable-selection-dynamic-query.dto.d.ts +8 -0
  52. package/dist/dtos/dashboard-variable-selection-dynamic-query.dto.d.ts.map +1 -0
  53. package/dist/dtos/dashboard-variable-selection-dynamic-query.dto.js +52 -0
  54. package/dist/dtos/dashboard-variable-selection-dynamic-query.dto.js.map +1 -0
  55. package/dist/dtos/invoke-ai-prompt.dto.d.ts +4 -0
  56. package/dist/dtos/invoke-ai-prompt.dto.d.ts.map +1 -0
  57. package/dist/dtos/invoke-ai-prompt.dto.js +25 -0
  58. package/dist/dtos/invoke-ai-prompt.dto.js.map +1 -0
  59. package/dist/dtos/update-ai-interaction.dto.d.ts +15 -0
  60. package/dist/dtos/update-ai-interaction.dto.d.ts.map +1 -0
  61. package/dist/dtos/update-ai-interaction.dto.js +96 -0
  62. package/dist/dtos/update-ai-interaction.dto.js.map +1 -0
  63. package/dist/dtos/update-dashboard-variable.dto.d.ts +15 -0
  64. package/dist/dtos/update-dashboard-variable.dto.d.ts.map +1 -0
  65. package/dist/dtos/update-dashboard-variable.dto.js +95 -0
  66. package/dist/dtos/update-dashboard-variable.dto.js.map +1 -0
  67. package/dist/dtos/update-dashboard.dto.d.ts +16 -0
  68. package/dist/dtos/update-dashboard.dto.d.ts.map +1 -0
  69. package/dist/dtos/update-dashboard.dto.js +96 -0
  70. package/dist/dtos/update-dashboard.dto.js.map +1 -0
  71. package/dist/dtos/update-question-sql-dataset-config.dto.d.ts +13 -0
  72. package/dist/dtos/update-question-sql-dataset-config.dto.d.ts.map +1 -0
  73. package/dist/dtos/update-question-sql-dataset-config.dto.js +86 -0
  74. package/dist/dtos/update-question-sql-dataset-config.dto.js.map +1 -0
  75. package/dist/dtos/update-question.dto.d.ts +17 -0
  76. package/dist/dtos/update-question.dto.d.ts.map +1 -0
  77. package/dist/dtos/update-question.dto.js +106 -0
  78. package/dist/dtos/update-question.dto.js.map +1 -0
  79. package/dist/entities/ai-interaction.entity.d.ts +15 -0
  80. package/dist/entities/ai-interaction.entity.d.ts.map +1 -0
  81. package/dist/entities/ai-interaction.entity.js +70 -0
  82. package/dist/entities/ai-interaction.entity.js.map +1 -0
  83. package/dist/entities/dashboard-variable.entity.d.ts +15 -0
  84. package/dist/entities/dashboard-variable.entity.d.ts.map +1 -0
  85. package/dist/entities/dashboard-variable.entity.js +73 -0
  86. package/dist/entities/dashboard-variable.entity.js.map +1 -0
  87. package/dist/entities/dashboard.entity.d.ts +12 -0
  88. package/dist/entities/dashboard.entity.d.ts.map +1 -0
  89. package/dist/entities/dashboard.entity.js +50 -0
  90. package/dist/entities/dashboard.entity.js.map +1 -0
  91. package/dist/entities/question-sql-dataset-config.entity.d.ts +13 -0
  92. package/dist/entities/question-sql-dataset-config.entity.d.ts.map +1 -0
  93. package/dist/entities/question-sql-dataset-config.entity.js +60 -0
  94. package/dist/entities/question-sql-dataset-config.entity.js.map +1 -0
  95. package/dist/entities/question.entity.d.ts +15 -0
  96. package/dist/entities/question.entity.d.ts.map +1 -0
  97. package/dist/entities/question.entity.js +67 -0
  98. package/dist/entities/question.entity.js.map +1 -0
  99. package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.d.ts +1 -0
  100. package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.d.ts.map +1 -1
  101. package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.js +32 -7
  102. package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.js.map +1 -1
  103. package/dist/helpers/field-crud-managers/SelectionStaticFieldCrudManager.d.ts +1 -0
  104. package/dist/helpers/field-crud-managers/SelectionStaticFieldCrudManager.d.ts.map +1 -1
  105. package/dist/helpers/field-crud-managers/SelectionStaticFieldCrudManager.js +32 -7
  106. package/dist/helpers/field-crud-managers/SelectionStaticFieldCrudManager.js.map +1 -1
  107. package/dist/helpers/solid-registry.d.ts +9 -1
  108. package/dist/helpers/solid-registry.d.ts.map +1 -1
  109. package/dist/helpers/solid-registry.js +32 -0
  110. package/dist/helpers/solid-registry.js.map +1 -1
  111. package/dist/index.d.ts +5 -0
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +5 -0
  114. package/dist/index.js.map +1 -1
  115. package/dist/interfaces.d.ts +12 -1
  116. package/dist/interfaces.d.ts.map +1 -1
  117. package/dist/interfaces.js.map +1 -1
  118. package/dist/mappers/dashboard-mapper.d.ts +6 -0
  119. package/dist/mappers/dashboard-mapper.d.ts.map +1 -0
  120. package/dist/mappers/dashboard-mapper.js +60 -0
  121. package/dist/mappers/dashboard-mapper.js.map +1 -0
  122. package/dist/repository/dashboard.repository.d.ts +11 -0
  123. package/dist/repository/dashboard.repository.d.ts.map +1 -0
  124. package/dist/repository/dashboard.repository.js +93 -0
  125. package/dist/repository/dashboard.repository.js.map +1 -0
  126. package/dist/seeders/module-metadata-seeder.service.d.ts +5 -1
  127. package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
  128. package/dist/seeders/module-metadata-seeder.service.js +18 -2
  129. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  130. package/dist/seeders/seed-data/solid-core-metadata.json +4222 -2418
  131. package/dist/services/ai-interaction.service.d.ts +23 -0
  132. package/dist/services/ai-interaction.service.d.ts.map +1 -0
  133. package/dist/services/ai-interaction.service.js +147 -0
  134. package/dist/services/ai-interaction.service.js.map +1 -0
  135. package/dist/services/dashboard-selection-providers/dashboard-variable-sql-dynamic-provider.service.d.ts +12 -0
  136. package/dist/services/dashboard-selection-providers/dashboard-variable-sql-dynamic-provider.service.d.ts.map +1 -0
  137. package/dist/services/dashboard-selection-providers/dashboard-variable-sql-dynamic-provider.service.js +55 -0
  138. package/dist/services/dashboard-selection-providers/dashboard-variable-sql-dynamic-provider.service.js.map +1 -0
  139. package/dist/services/dashboard-selection-providers/dashboard-variable-test-dynamic-provider.service.d.ts +11 -0
  140. package/dist/services/dashboard-selection-providers/dashboard-variable-test-dynamic-provider.service.d.ts.map +1 -0
  141. package/dist/services/dashboard-selection-providers/dashboard-variable-test-dynamic-provider.service.js +45 -0
  142. package/dist/services/dashboard-selection-providers/dashboard-variable-test-dynamic-provider.service.js.map +1 -0
  143. package/dist/services/dashboard-variable.service.d.ts +23 -0
  144. package/dist/services/dashboard-variable.service.d.ts.map +1 -0
  145. package/dist/services/dashboard-variable.service.js +57 -0
  146. package/dist/services/dashboard-variable.service.js.map +1 -0
  147. package/dist/services/dashboard.service.d.ts +38 -0
  148. package/dist/services/dashboard.service.d.ts.map +1 -0
  149. package/dist/services/dashboard.service.js +179 -0
  150. package/dist/services/dashboard.service.js.map +1 -0
  151. package/dist/services/import-transaction.service.d.ts.map +1 -1
  152. package/dist/services/import-transaction.service.js +2 -1
  153. package/dist/services/import-transaction.service.js.map +1 -1
  154. package/dist/services/menu-item-metadata.service.d.ts.map +1 -1
  155. package/dist/services/menu-item-metadata.service.js +1 -1
  156. package/dist/services/menu-item-metadata.service.js.map +1 -1
  157. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts +36 -0
  158. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts.map +1 -0
  159. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js +85 -0
  160. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js.map +1 -0
  161. package/dist/services/question-data-providers/helpers.d.ts +4 -0
  162. package/dist/services/question-data-providers/helpers.d.ts.map +1 -0
  163. package/dist/services/question-data-providers/helpers.js +10 -0
  164. package/dist/services/question-data-providers/helpers.js.map +1 -0
  165. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts +17 -0
  166. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts.map +1 -0
  167. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js +64 -0
  168. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js.map +1 -0
  169. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts +19 -0
  170. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts.map +1 -0
  171. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js +84 -0
  172. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js.map +1 -0
  173. package/dist/services/question-sql-dataset-config.service.d.ts +22 -0
  174. package/dist/services/question-sql-dataset-config.service.d.ts.map +1 -0
  175. package/dist/services/question-sql-dataset-config.service.js +56 -0
  176. package/dist/services/question-sql-dataset-config.service.js.map +1 -0
  177. package/dist/services/question.service.d.ts +29 -0
  178. package/dist/services/question.service.d.ts.map +1 -0
  179. package/dist/services/question.service.js +117 -0
  180. package/dist/services/question.service.js.map +1 -0
  181. package/dist/services/scheduled-jobs/scheduler.service.d.ts.map +1 -1
  182. package/dist/services/scheduled-jobs/scheduler.service.js +22 -11
  183. package/dist/services/scheduled-jobs/scheduler.service.js.map +1 -1
  184. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.d.ts +11 -0
  185. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.d.ts.map +1 -0
  186. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js +46 -0
  187. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js.map +1 -0
  188. package/dist/services/selection-providers/list-of-dashboard-variable-providers-selection-provider.service.d.ts +11 -0
  189. package/dist/services/selection-providers/list-of-dashboard-variable-providers-selection-provider.service.d.ts.map +1 -0
  190. package/dist/services/selection-providers/list-of-dashboard-variable-providers-selection-provider.service.js +47 -0
  191. package/dist/services/selection-providers/list-of-dashboard-variable-providers-selection-provider.service.js.map +1 -0
  192. package/dist/services/solid-introspect.service.d.ts +2 -0
  193. package/dist/services/solid-introspect.service.d.ts.map +1 -1
  194. package/dist/services/solid-introspect.service.js +28 -0
  195. package/dist/services/solid-introspect.service.js.map +1 -1
  196. package/dist/services/sql-expression-resolver.service.d.ts +9 -0
  197. package/dist/services/sql-expression-resolver.service.d.ts.map +1 -0
  198. package/dist/services/sql-expression-resolver.service.js +105 -0
  199. package/dist/services/sql-expression-resolver.service.js.map +1 -0
  200. package/dist/solid-core.module.d.ts.map +1 -1
  201. package/dist/solid-core.module.js +61 -0
  202. package/dist/solid-core.module.js.map +1 -1
  203. package/dist/subscribers/dashboard-variable.subscriber.d.ts +16 -0
  204. package/dist/subscribers/dashboard-variable.subscriber.d.ts.map +1 -0
  205. package/dist/subscribers/dashboard-variable.subscriber.js +72 -0
  206. package/dist/subscribers/dashboard-variable.subscriber.js.map +1 -0
  207. package/dist/subscribers/dashboard.subscriber.d.ts +15 -0
  208. package/dist/subscribers/dashboard.subscriber.d.ts.map +1 -0
  209. package/dist/subscribers/dashboard.subscriber.js +56 -0
  210. package/dist/subscribers/dashboard.subscriber.js.map +1 -0
  211. package/dist/subscribers/question-sql-dataset-config.subscriber.d.ts +16 -0
  212. package/dist/subscribers/question-sql-dataset-config.subscriber.d.ts.map +1 -0
  213. package/dist/subscribers/question-sql-dataset-config.subscriber.js +72 -0
  214. package/dist/subscribers/question-sql-dataset-config.subscriber.js.map +1 -0
  215. package/dist/subscribers/question.subscriber.d.ts +16 -0
  216. package/dist/subscribers/question.subscriber.d.ts.map +1 -0
  217. package/dist/subscribers/question.subscriber.js +72 -0
  218. package/dist/subscribers/question.subscriber.js.map +1 -0
  219. package/dist/tsconfig.tsbuildinfo +1 -1
  220. package/package.json +1 -1
  221. package/src/controllers/ai-interaction.controller.ts +98 -0
  222. package/src/controllers/dashboard-variable.controller.ts +93 -0
  223. package/src/controllers/dashboard.controller.ts +99 -0
  224. package/src/controllers/question-sql-dataset-config.controller.ts +93 -0
  225. package/src/controllers/question.controller.ts +104 -0
  226. package/src/controllers/test.controller.ts +1 -2
  227. package/src/decorators/dashboard-question-data-provider.decorator.ts +7 -0
  228. package/src/decorators/dashboard-selection-provider.decorator.ts +7 -0
  229. package/src/dtos/create-ai-interaction.dto.ts +60 -0
  230. package/src/dtos/create-dashboard-variable.dto.ts +56 -0
  231. package/src/dtos/create-dashboard.dto.ts +53 -0
  232. package/src/dtos/create-question-sql-dataset-config.dto.ts +42 -0
  233. package/src/dtos/create-question.dto.ts +58 -0
  234. package/src/dtos/dashboard-variable-selection-dynamic-query.dto.ts +29 -0
  235. package/src/dtos/invoke-ai-prompt.dto.ts +6 -0
  236. package/src/dtos/update-ai-interaction.dto.ts +65 -0
  237. package/src/dtos/update-dashboard-variable.dto.ts +54 -0
  238. package/src/dtos/update-dashboard.dto.ts +57 -0
  239. package/src/dtos/update-question-sql-dataset-config.dto.ts +49 -0
  240. package/src/dtos/update-question.dto.ts +63 -0
  241. package/src/entities/ai-interaction.entity.ts +39 -0
  242. package/src/entities/dashboard-variable.entity.ts +30 -0
  243. package/src/entities/dashboard.entity.ts +21 -0
  244. package/src/entities/question-sql-dataset-config.entity.ts +25 -0
  245. package/src/entities/question.entity.ts +30 -0
  246. package/src/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.ts +44 -18
  247. package/src/helpers/field-crud-managers/SelectionStaticFieldCrudManager.ts +43 -15
  248. package/src/helpers/solid-registry.ts +44 -2
  249. package/src/index.ts +5 -0
  250. package/src/interfaces.ts +41 -29
  251. package/src/mappers/dashboard-mapper.ts +52 -0
  252. package/src/repository/dashboard.repository.ts +100 -0
  253. package/src/seeders/module-metadata-seeder.service.ts +21 -1
  254. package/src/seeders/seed-data/solid-core-metadata.json +4225 -2421
  255. package/src/services/1. Create a context menu option i.py +12 -0
  256. package/src/services/ai-interaction.service.ts +127 -0
  257. package/src/services/dashboard-selection-providers/dashboard-variable-sql-dynamic-provider.service.ts +56 -0
  258. package/src/services/dashboard-selection-providers/dashboard-variable-test-dynamic-provider.service.ts +37 -0
  259. package/src/services/dashboard-variable.service.ts +36 -0
  260. package/src/services/dashboard.service.ts +147 -0
  261. package/src/services/import-transaction.service.ts +2 -1
  262. package/src/services/menu-item-metadata.service.ts +2 -1
  263. package/src/services/question-data-providers/chartjs-sql-data-provider.service.ts +121 -0
  264. package/src/services/question-data-providers/helpers.ts +11 -0
  265. package/src/services/question-data-providers/prime-react-datatable-sql-data-provider.service.ts +72 -0
  266. package/src/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.ts +110 -0
  267. package/src/services/question-sql-dataset-config.service.ts +34 -0
  268. package/src/services/question.service.ts +115 -0
  269. package/src/services/scheduled-jobs/scheduler.service.ts +32 -64
  270. package/src/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.ts +41 -0
  271. package/src/services/selection-providers/list-of-dashboard-variable-providers-selection-provider.service.ts +41 -0
  272. package/src/services/solid-introspect.service.ts +42 -0
  273. package/src/services/sql-expression-resolver.service.ts +125 -0
  274. package/src/solid-core.module.ts +61 -1
  275. package/src/subscribers/dashboard-variable.subscriber.ts +63 -0
  276. package/src/subscribers/dashboard.subscriber.ts +43 -0
  277. package/src/subscribers/question-sql-dataset-config.subscriber.ts +63 -0
  278. package/src/subscribers/question.subscriber.ts +65 -0
@@ -20,31 +20,57 @@ export class SelectionDynamicFieldCrudManager implements FieldCrudManager {
20
20
 
21
21
  async validate(dto: any): Promise<ValidationError[]> {
22
22
  const fieldValue: any = dto[this.options.fieldName];
23
+ // return this.applyValidations(fieldValue);
23
24
  const isMultiSelect = this.options?.isMultiSelect;
25
+ if (isMultiSelect && fieldValue) {
26
+ const arrayCheck = this.parseAndValidateArray(fieldValue);
24
27
 
25
- // return this.applyValidations(fieldValue);
26
- // Handle multi-select scenario
27
- if (isMultiSelect) {
28
- let values: any[];
28
+ if (!arrayCheck.isValid) {
29
+ return [
30
+ {
31
+ field: this.options.fieldName,
32
+ error: `Field: ${this.options.fieldName} must be a valid array`,
33
+ },
34
+ ];
35
+ }
29
36
 
30
- try {
31
- // Try to parse the field value, which should be a JSON stringified array
32
- values = JSON.parse(fieldValue);
33
- } catch {
34
- // If parsing fails, fallback to a single value
35
- values = [fieldValue];
36
- }
37
+ const values = arrayCheck.values;
37
38
 
38
- // Apply validations to each value asynchronously
39
- const allErrors = await Promise.all(values.map(value => this.applyValidations(value)));
39
+ if (this.isApplyRequiredValidation() && values.length === 0) {
40
+ return [
41
+ {
42
+ field: this.options.fieldName,
43
+ error: `Field: ${this.options.fieldName} is required`,
44
+ },
45
+ ];
46
+ }
40
47
 
41
- // Flatten the array of errors and return
42
- return allErrors.flat();
43
- } else {
44
- // For non-multi-select, apply validations to the single field value
45
- return this.applyValidations(fieldValue);
48
+ // Apply validations to each value
49
+ const allErrors = await Promise.all(values.map((val) => this.applyValidations(val)));
50
+ return allErrors.flat();
51
+ } else {
52
+ // For non-multi-select, apply validations to the single field value
53
+ return this.applyValidations(fieldValue);
54
+ }
46
55
  }
56
+
57
+ private parseAndValidateArray(fieldValue: any): { isValid: boolean; values: any[] } {
58
+ if (Array.isArray(fieldValue)) {
59
+ return { isValid: true, values: fieldValue };
60
+ }
61
+
62
+ try {
63
+ const parsed = typeof fieldValue === 'string' ? JSON.parse(fieldValue) : null;
64
+ if (Array.isArray(parsed)) {
65
+ return { isValid: true, values: parsed };
66
+ }
67
+ } catch {
68
+ // fall through
69
+ }
70
+
71
+ return { isValid: false, values: [] };
47
72
  }
73
+
48
74
 
49
75
  private async applyValidations(fieldValue: any): Promise<ValidationError[]> {
50
76
  const errors: ValidationError[] = [];
@@ -16,24 +16,34 @@ export class SelectionStaticFieldCrudManager implements FieldCrudManager {
16
16
  }
17
17
 
18
18
  async validate(dto: any): Promise<ValidationError[]> {
19
- const fieldValue: any = dto[this.options.fieldName];
19
+ const fieldValue: any = dto[this.options.fieldName];
20
20
  // return this.applyValidations(fieldValue);
21
21
  const isMultiSelect = this.options?.isMultiSelect;
22
- if (isMultiSelect) {
23
- let values: any[];
24
-
25
- try {
26
- // Try to parse the field value, which should be a JSON stringified array
27
- values = JSON.parse(fieldValue);
28
- } catch {
29
- // If parsing fails, fallback to a single value
30
- values = [fieldValue];
22
+ if (isMultiSelect && fieldValue) {
23
+ const arrayCheck = this.parseAndValidateArray(fieldValue);
24
+
25
+ if (!arrayCheck.isValid) {
26
+ return [
27
+ {
28
+ field: this.options.fieldName,
29
+ error: `Field: ${this.options.fieldName} must be a valid array`,
30
+ },
31
+ ];
31
32
  }
32
-
33
- // Apply validations to each value asynchronously
34
- const allErrors = await Promise.all(values.map(value => this.applyValidations(value)));
35
-
36
- // Flatten the array of errors and return
33
+
34
+ const values = arrayCheck.values;
35
+
36
+ if (this.isApplyRequiredValidation() && values.length === 0) {
37
+ return [
38
+ {
39
+ field: this.options.fieldName,
40
+ error: `Field: ${this.options.fieldName} is required`,
41
+ },
42
+ ];
43
+ }
44
+
45
+ // Apply validations to each value
46
+ const allErrors = await Promise.all(values.map((val) => this.applyValidations(val)));
37
47
  return allErrors.flat();
38
48
  } else {
39
49
  // For non-multi-select, apply validations to the single field value
@@ -41,6 +51,24 @@ export class SelectionStaticFieldCrudManager implements FieldCrudManager {
41
51
  }
42
52
  }
43
53
 
54
+ private parseAndValidateArray(fieldValue: any): { isValid: boolean; values: any[] } {
55
+ if (Array.isArray(fieldValue)) {
56
+ return { isValid: true, values: fieldValue };
57
+ }
58
+
59
+ try {
60
+ const parsed = typeof fieldValue === 'string' ? JSON.parse(fieldValue) : null;
61
+ if (Array.isArray(parsed)) {
62
+ return { isValid: true, values: parsed };
63
+ }
64
+ } catch {
65
+ // fall through
66
+ }
67
+
68
+ return { isValid: false, values: [] };
69
+ }
70
+
71
+
44
72
  private applyValidations(fieldValue: any): ValidationError[] {
45
73
  const errors: ValidationError[] = [];
46
74
  this.isApplyRequiredValidation() && isEmpty(fieldValue) ? errors.push({ field: this.options.fieldName, error: `Field: ${this.options.fieldName} is required` }) : "no errors";
@@ -5,7 +5,7 @@ import { CommonEntity } from 'src/entities/common.entity';
5
5
  import { Locale } from 'src/entities/locale.entity';
6
6
  import { SecurityRule } from 'src/entities/security-rule.entity';
7
7
  import { IScheduledJob } from 'src/services/scheduled-jobs/scheduled-job.interface';
8
- import { ISelectionProvider, ISelectionProviderContext } from "../interfaces";
8
+ import { IDashboardQuestionDataProvider, IDashboardVariableSelectionProvider, ISelectionProvider, ISelectionProviderContext } from "../interfaces";
9
9
 
10
10
  type ControllerMetadata = {
11
11
  name: string;
@@ -63,6 +63,8 @@ export class SolidRegistry {
63
63
  private securityRules: SecurityRule[] = [];
64
64
  private locales: Locale[] = [];
65
65
  private computedFieldMetadata: ComputedFieldMetadata[] = [];
66
+ private dashboardVariableSelectionProviders: Set<InstanceWrapper> = new Set();
67
+ private dashboardQuestionDataProviders: Set<InstanceWrapper> = new Set();
66
68
 
67
69
  registerController(name: string, methodNames: string[]): void {
68
70
  this.controllers.add({ name: name, methods: methodNames });
@@ -80,6 +82,14 @@ export class SolidRegistry {
80
82
  this.selectionProviders.add(selectionProvider);
81
83
  }
82
84
 
85
+ registerDashboardVariableSelectionProvider(dashboardSelectionProvider: InstanceWrapper): void {
86
+ this.dashboardVariableSelectionProviders.add(dashboardSelectionProvider);
87
+ }
88
+
89
+ registerDashboardQuestionDataProvider(dashboardQuestionDataProvider: InstanceWrapper): void {
90
+ this.dashboardQuestionDataProviders.add(dashboardQuestionDataProvider);
91
+ }
92
+
83
93
  registerComputedFieldProvider(computedFieldProvider: InstanceWrapper): void {
84
94
  this.computedFieldProviders.add(computedFieldProvider);
85
95
  }
@@ -119,6 +129,38 @@ export class SolidRegistry {
119
129
  }
120
130
  }
121
131
 
132
+ getDashboardVariableSelectionProviders(): Array<InstanceWrapper> {
133
+ return Array.from(this.dashboardVariableSelectionProviders);
134
+ }
135
+
136
+ getDashboardVariableSelectionProviderInstance<T extends ISelectionProviderContext>(name: string): IDashboardVariableSelectionProvider<T> {
137
+ const dashboardSelectionProviders = this.getDashboardVariableSelectionProviders();
138
+
139
+ for (let i = 0; i < dashboardSelectionProviders.length; i++) {
140
+ const dashboardSelectionProvider = dashboardSelectionProviders[i];
141
+ if (dashboardSelectionProvider.instance.name() === name) {
142
+ return dashboardSelectionProvider.instance;
143
+ }
144
+ }
145
+ }
146
+
147
+ getDashboardQuestionDataProviders(): Array<InstanceWrapper> {
148
+ return Array.from(this.dashboardQuestionDataProviders)
149
+ }
150
+
151
+ getDashboardQuestionDataProviderInstance<TContext, TData>(name: string): IDashboardQuestionDataProvider<TContext, TData> {
152
+ const dashboardQuestionDataProviders = this.getDashboardQuestionDataProviders();
153
+
154
+ for (let i = 0; i < dashboardQuestionDataProviders.length; i++) {
155
+ const dasbhoardQuestionDataProvider = dashboardQuestionDataProviders[i];
156
+ if (dasbhoardQuestionDataProvider.instance.name() === name) {
157
+ return dasbhoardQuestionDataProvider.instance;
158
+ }
159
+ }
160
+
161
+ }
162
+
163
+
122
164
  getComputedFieldProviders(): Array<InstanceWrapper> {
123
165
  return Array.from(this.computedFieldProviders);
124
166
  }
@@ -137,7 +179,7 @@ export class SolidRegistry {
137
179
  }
138
180
  }
139
181
  }
140
-
182
+
141
183
  getComputedFieldProvider(name: string): InstanceWrapper {
142
184
  const provider = this.getComputedFieldProviders().filter((provider) => provider.name === name).pop();
143
185
  if (!provider) {
package/src/index.ts CHANGED
@@ -125,6 +125,11 @@ export * from './entities/import-transaction.entity'
125
125
  export * from './entities/import-transaction-error-log.entity'
126
126
  export * from './entities/locale.entity'
127
127
  export * from './entities/user-activity-history.entity'
128
+ export * from './entities/dashboard.entity'
129
+ export * from './entities/dashboard-variable.entity'
130
+ export * from './entities/question.entity'
131
+ export * from './entities/question-sql-dataset-config.entity'
132
+ export * from './entities/ai-interaction.entity'
128
133
 
129
134
  export * from './enums/auth-type.enum'
130
135
 
package/src/interfaces.ts CHANGED
@@ -1,18 +1,18 @@
1
1
  import { CreateEmailTemplateDto } from 'src/dtos/create-email-template.dto';
2
2
  import { CreateSmsTemplateDto } from 'src/dtos/create-sms-template.dto';
3
3
  import { SignUpDto } from 'src/dtos/sign-up.dto';
4
- import { CreateActionMetadataDto } from './dtos/create-action-metadata.dto';
4
+ import { Readable } from 'stream';
5
5
  import { CreateMediaStorageProviderMetadataDto } from './dtos/create-media-storage-provider-metadata.dto';
6
- import { CreateMenuItemMetadataDto } from './dtos/create-menu-item-metadata.dto';
7
6
  import { DatasourceType } from './dtos/create-model-metadata.dto';
8
7
  import { CreateModuleMetadataDto } from './dtos/create-module-metadata.dto';
9
8
  import { CreateRoleMetadataDto } from './dtos/create-role-metadata.dto';
10
9
  import { CreateSecurityRuleDto } from './dtos/create-security-rule.dto';
11
- import { CreateViewMetadataDto } from './dtos/create-view-metadata.dto';
12
10
  import { FieldMetadata } from './entities/field-metadata.entity';
13
11
  import { Media } from './entities/media.entity';
14
- import { Readable } from 'stream';
12
+ import { Question } from './entities/question.entity';
15
13
  import { ComputedFieldMetadata } from './helpers/solid-registry';
14
+ import { SqlExpression } from './services/question-data-providers/chartjs-sql-data-provider.service';
15
+ import { CreateDashboardDto } from './dtos/create-dashboard.dto';
16
16
 
17
17
  export interface FieldCrudManager {
18
18
  // fieldMetadata: FieldMetadata;
@@ -27,39 +27,40 @@ export interface FieldCrudManager {
27
27
  }
28
28
 
29
29
  export interface ValidationError {
30
- field: string;
31
- error: string;
30
+ field: string;
31
+ error: string;
32
32
  }
33
33
 
34
34
  // export interface MediaStorage
35
35
  export interface MediaStorageProvider<T> {
36
- store(files: Express.Multer.File[], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;
37
- delete(entity: T, mediaFieldMetadata: FieldMetadata): Promise<void>;
38
- retrieve(entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;
39
- storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;
40
- // delete(file: string): Promise<void>;
36
+ store(files: Express.Multer.File[], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;
37
+ delete(entity: T, mediaFieldMetadata: FieldMetadata): Promise<void>;
38
+ retrieve(entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;
39
+ storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]>;
40
+ // delete(file: string): Promise<void>;
41
41
  }
42
42
 
43
43
  export interface ModuleMetadataConfiguration {
44
- moduleMetadata?: CreateModuleMetadataDto,
45
- roles?: CreateRoleMetadataDto[],
46
- users?: SignUpDto[],
47
- actions?: any[],
48
- menus?: any[],
49
- views?: any[],
50
- emailTemplates?: CreateEmailTemplateDto[],
51
- smsTemplates?: CreateSmsTemplateDto[],
52
- mediaStorageProviders?: CreateMediaStorageProviderMetadataDto[]
53
- securityRules?: CreateSecurityRuleDto[],
44
+ moduleMetadata?: CreateModuleMetadataDto,
45
+ roles?: CreateRoleMetadataDto[],
46
+ users?: SignUpDto[],
47
+ actions?: any[],
48
+ menus?: any[],
49
+ views?: any[],
50
+ emailTemplates?: CreateEmailTemplateDto[],
51
+ smsTemplates?: CreateSmsTemplateDto[],
52
+ mediaStorageProviders?: CreateMediaStorageProviderMetadataDto[]
53
+ securityRules?: CreateSecurityRuleDto[],
54
+ dashboards?: CreateDashboardDto[],
54
55
  }
55
56
 
56
57
  export interface CodeGenerationOptions {
57
- moduleId?: number;
58
- moduleUserKey?: string;
59
- modelId?: number;
60
- modelUserKey?: string;
61
- fieldIdsForRemoval?: number[];
62
- dryRun?: boolean;
58
+ moduleId?: number;
59
+ moduleUserKey?: string;
60
+ modelId?: number;
61
+ modelUserKey?: string;
62
+ fieldIdsForRemoval?: number[];
63
+ dryRun?: boolean;
63
64
  }
64
65
 
65
66
  export interface ISelectionProviderContext {
@@ -81,6 +82,17 @@ export interface ISelectionProvider<T extends ISelectionProviderContext> {
81
82
  values(query: any, ctxt: T): Promise<readonly ISelectionProviderValues[]>;
82
83
  }
83
84
 
85
+ export interface IDashboardVariableSelectionProvider<T extends ISelectionProviderContext> extends ISelectionProvider<T> {
86
+ }
87
+
88
+ export interface IDashboardQuestionDataProvider<TContext, TData> {
89
+ help(): string;
90
+
91
+ name(): string;
92
+
93
+ getData(question: Question, expressions?: SqlExpression[], ctxt?: TContext): Promise<TData[] | TData>;
94
+ }
95
+
84
96
  /**
85
97
  * @deprecated Use `IEntityComputedFieldProvider` instead.
86
98
  */
@@ -94,7 +106,7 @@ export interface IComputedFieldProvider<T> {
94
106
  computeValue(dto: any, ctxt: T): Promise<string | number>; // FIXME : Improve the types to make it more specific using generics
95
107
  }
96
108
 
97
- export interface IEntityComputedFieldProvider {
109
+ export interface IEntityComputedFieldProvider {
98
110
  help(): string;
99
111
 
100
112
  name(): string;
@@ -122,7 +134,7 @@ export class EventDetails<T> {
122
134
  constructor(
123
135
  public type: any,
124
136
  public payload: T,
125
- ) {}
137
+ ) { }
126
138
  }
127
139
 
128
140
  export interface IMail {
@@ -0,0 +1,52 @@
1
+ import { Injectable } from "@nestjs/common";
2
+ import { SelectionDynamicSourceType } from "src/dtos/create-dashboard-variable.dto";
3
+ import { Dashboard } from "src/entities/dashboard.entity";
4
+
5
+ @Injectable()
6
+ export class DashboardMapper {
7
+ toDto(dashboard: Dashboard): any {
8
+ return {
9
+ name: dashboard.name,
10
+ layoutJson: this.safeParseJSON(dashboard.layoutJson, {}),
11
+ moduleUserKey: dashboard.module?.name ?? null, // safer fallback
12
+
13
+ dashboardVariables: (dashboard.dashboardVariables || []).map(variable => ({
14
+ variableName: variable.variableName,
15
+ variableType: variable.variableType,
16
+ selectionStaticValues: this.safeParseJSON(variable.selectionStaticValues, []),
17
+ selectionDynamicSourceType: variable.selectionDynamicSourceType as SelectionDynamicSourceType,
18
+ selectionDynamicSQL: variable.selectionDynamicSQL ?? null,
19
+ selectionDynamicProviderName: variable.selectionDynamicProviderName ?? null,
20
+ defaultValue: this.safeParseJSON(variable.defaultValue, []),
21
+ defaultOperator: variable.defaultOperator ?? null,
22
+ })),
23
+ questions: (dashboard.questions || []).map(question => ({
24
+ name: question.name,
25
+ sourceType: question.sourceType,
26
+ visualisedAs: question.visualisedAs,
27
+ providerName: question.providerName ?? null,
28
+ chartOptions: question.chartOptions ?? null,
29
+ labelSql: question.labelSql ?? null,
30
+ kpiSql: question.kpiSql ?? null,
31
+
32
+ questionSqlDatasetConfigs: (question.questionSqlDatasetConfigs || []).map(config => ({
33
+ sql: config.sql,
34
+ datasetName: config.datasetName,
35
+ datasetDisplayName: config.datasetDisplayName, // 🔧 fixed typo: `daataSetDisplayName`
36
+ description: config.description,
37
+ labelColumnName: config.labelColumnName,
38
+ valueColumnName: config.valueColumnName,
39
+ options: this.safeParseJSON(config.options, {}),
40
+ }))
41
+ }))
42
+ };
43
+ }
44
+
45
+ private safeParseJSON(json: string | null | undefined, fallback: any): any {
46
+ try {
47
+ return json ? JSON.parse(json) : fallback;
48
+ } catch {
49
+ return fallback;
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,100 @@
1
+ import { Injectable, Logger } from "@nestjs/common";
2
+ import { CreateDashboardDto } from "src/dtos/create-dashboard.dto";
3
+ import { DashboardVariable } from "src/entities/dashboard-variable.entity";
4
+ import { Dashboard } from "src/entities/dashboard.entity";
5
+ import { ModuleMetadata } from "src/entities/module-metadata.entity";
6
+ import { QuestionSqlDatasetConfig } from "src/entities/question-sql-dataset-config.entity";
7
+ import { Question } from "src/entities/question.entity";
8
+ import { DataSource, Repository } from "typeorm";
9
+
10
+ @Injectable()
11
+ export class DashboardRepository extends Repository<Dashboard> {
12
+ private readonly logger = new Logger(this.constructor.name);
13
+ constructor(
14
+ private dataSource: DataSource,
15
+ ) {
16
+ super(Dashboard, dataSource.createEntityManager());
17
+ }
18
+
19
+
20
+ async upsertWithDto(createDto: CreateDashboardDto) {
21
+ const moduleMetadataRepository = this.dataSource.getRepository(ModuleMetadata);
22
+ const module = await moduleMetadataRepository.findOneBy({ name: createDto.moduleUserKey });
23
+
24
+ if (!module) throw new Error(`Module with key ${createDto.moduleUserKey} not found`);
25
+
26
+ const existingDashboard = await this.findOne({
27
+ where: { name: createDto.name },
28
+ relations: ['dashboardVariables', 'questions', 'questions.questionSqlDatasetConfigs'],
29
+ });
30
+
31
+ const dashboardData = {
32
+ ...createDto,
33
+ module,
34
+ layoutJson: JSON.stringify(createDto.layoutJson ?? {}),
35
+ dashboardVariables: createDto.dashboardVariables?.map(variable => ({
36
+ ...variable,
37
+ selectionStaticValues: JSON.stringify(variable.selectionStaticValues ?? []),
38
+ defaultValue: JSON.stringify(variable.defaultValue ?? []),
39
+ })),
40
+ questions: createDto.questions?.map(question => ({
41
+ ...question,
42
+ questionSqlDatasetConfigs: question.questionSqlDatasetConfigs?.map(cfg => ({
43
+ ...cfg,
44
+ options: JSON.stringify(cfg.options ?? {}),
45
+ })),
46
+ })),
47
+ };
48
+
49
+ if (existingDashboard) {
50
+ // Optionally clean up stale children
51
+ await this.cleanupRemovedRelations(existingDashboard, createDto);
52
+
53
+ this.merge(existingDashboard, dashboardData);
54
+ return this.save(existingDashboard);
55
+ } else {
56
+ const newDashboard = this.create(dashboardData);
57
+ return this.save(newDashboard);
58
+ }
59
+ }
60
+
61
+ private async cleanupRemovedRelations(existing: Dashboard, dto: CreateDashboardDto) {
62
+ const dashboardVariableRepo = this.dataSource.getRepository(DashboardVariable);
63
+ const questionRepo = this.dataSource.getRepository(Question);
64
+ const datasetConfigRepo = this.dataSource.getRepository(QuestionSqlDatasetConfig); // 👈 make sure this is imported
65
+
66
+ // === 1. Clean up removed dashboardVariables ===
67
+ const dtoVariableNames = new Set(dto.dashboardVariables.map(v => v.variableName));
68
+ const variablesToRemove = existing.dashboardVariables.filter(
69
+ v => !dtoVariableNames.has(v.variableName)
70
+ );
71
+ if (variablesToRemove.length > 0) {
72
+ await dashboardVariableRepo.remove(variablesToRemove);
73
+ }
74
+
75
+ // === 2. Clean up removed questions and gather removed question IDs ===
76
+ const dtoQuestionNames = new Set(dto.questions.map(q => q.name));
77
+ const questionsToRemove = existing.questions.filter(
78
+ q => !dtoQuestionNames.has(q.name)
79
+ );
80
+
81
+ if (questionsToRemove.length > 0) {
82
+ await questionRepo.remove(questionsToRemove);
83
+ }
84
+
85
+ // === 3. Clean up removed questionSqlDatasetConfigs from existing (retained) questions ===
86
+ for (const existingQuestion of existing.questions) {
87
+ const dtoQuestion = dto.questions.find(q => q.name === existingQuestion.name);
88
+ if (!dtoQuestion) continue;
89
+
90
+ const dtoDatasetNames = new Set(dtoQuestion.questionSqlDatasetConfigs?.map(cfg => cfg.datasetName));
91
+ const configsToRemove = existingQuestion.questionSqlDatasetConfigs.filter(
92
+ cfg => !dtoDatasetNames.has(cfg.datasetName)
93
+ );
94
+
95
+ if (configsToRemove.length > 0) {
96
+ await datasetConfigRepo.remove(configsToRemove);
97
+ }
98
+ }
99
+ }
100
+ }
@@ -37,6 +37,8 @@ import { SecurityRuleRepository } from 'src/repository/security-rule.repository'
37
37
  import { ListOfValuesService } from 'src/services/list-of-values.service';
38
38
  import { CreateListOfValuesDto } from 'src/dtos/create-list-of-values.dto';
39
39
  import { SystemFieldsSeederService } from './system-fields-seeder.service';
40
+ import { CreateDashboardDto } from 'src/dtos/create-dashboard.dto';
41
+ import { DashboardRepository } from 'src/repository/dashboard.repository';
40
42
 
41
43
  @Injectable()
42
44
  export class ModuleMetadataSeederService {
@@ -69,7 +71,8 @@ export class ModuleMetadataSeederService {
69
71
  @InjectRepository(Setting, 'default')
70
72
  readonly settingsRepo: Repository<Setting>,
71
73
  readonly securityRuleRepo: SecurityRuleRepository,
72
- readonly systemFieldsSeederService: SystemFieldsSeederService
74
+ readonly systemFieldsSeederService: SystemFieldsSeederService,
75
+ readonly dashboardRepo: DashboardRepository,
73
76
  ) { }
74
77
 
75
78
  async seed() {
@@ -212,6 +215,13 @@ export class ModuleMetadataSeederService {
212
215
  await this.seedListOfValues(listOfValues);
213
216
  this.logger.debug(`[End] Processing List Of Values for ${moduleMetadata.name}`);
214
217
 
218
+ // Dashboards
219
+ this.logger.debug(`[Start] Processing dashboards for ${moduleMetadata.name}`);
220
+ const dashboards: CreateDashboardDto[] = overallMetadata.dashboards;
221
+ await this.seedDashboards(dashboards);
222
+ this.logger.debug(`[End] Processing dashboards for ${moduleMetadata.name}`);
223
+
224
+
215
225
  this.logger.debug(`[End] module seed data: ${overallMetadata}`);
216
226
 
217
227
  }
@@ -559,4 +569,14 @@ export class ModuleMetadataSeederService {
559
569
  }
560
570
  }
561
571
 
572
+ async seedDashboards(dashboardDtos: CreateDashboardDto[]) {
573
+ if (!dashboardDtos || dashboardDtos.length === 0) {
574
+ this.logger.debug(`No dashboards found to seed`);
575
+ return;
576
+ }
577
+ for (const dto of dashboardDtos) {
578
+ await this.dashboardRepo.upsertWithDto(dto);
579
+ }
580
+ }
581
+
562
582
  }