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

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 (60) hide show
  1. package/dist/entities/chatter-message-details.entity.d.ts +1 -0
  2. package/dist/entities/chatter-message-details.entity.d.ts.map +1 -1
  3. package/dist/entities/chatter-message-details.entity.js +5 -1
  4. package/dist/entities/chatter-message-details.entity.js.map +1 -1
  5. package/dist/entities/common.entity.js +1 -1
  6. package/dist/entities/common.entity.js.map +1 -1
  7. package/dist/entities/legacy-common.entity.d.ts.map +1 -1
  8. package/dist/entities/legacy-common.entity.js +1 -1
  9. package/dist/entities/legacy-common.entity.js.map +1 -1
  10. package/dist/interfaces.d.ts +4 -1
  11. package/dist/interfaces.d.ts.map +1 -1
  12. package/dist/interfaces.js.map +1 -1
  13. package/dist/services/chatter-message.service.d.ts +0 -1
  14. package/dist/services/chatter-message.service.d.ts.map +1 -1
  15. package/dist/services/chatter-message.service.js +22 -19
  16. package/dist/services/chatter-message.service.js.map +1 -1
  17. package/dist/services/dashboard-question.service.d.ts +4 -0
  18. package/dist/services/dashboard-question.service.d.ts.map +1 -1
  19. package/dist/services/dashboard-question.service.js +22 -8
  20. package/dist/services/dashboard-question.service.js.map +1 -1
  21. package/dist/services/model-metadata.service.d.ts.map +1 -1
  22. package/dist/services/model-metadata.service.js +101 -6
  23. package/dist/services/model-metadata.service.js.map +1 -1
  24. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts +2 -4
  25. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts.map +1 -1
  26. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js +2 -1
  27. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js.map +1 -1
  28. package/dist/services/question-data-providers/interfaces.d.ts +1 -0
  29. package/dist/services/question-data-providers/interfaces.d.ts.map +1 -0
  30. package/dist/services/question-data-providers/interfaces.js +1 -0
  31. package/dist/services/question-data-providers/interfaces.js.map +1 -0
  32. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts +2 -5
  33. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts.map +1 -1
  34. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js +2 -1
  35. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js.map +1 -1
  36. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts +2 -5
  37. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts.map +1 -1
  38. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js +2 -1
  39. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js.map +1 -1
  40. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.d.ts.map +1 -1
  41. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js +4 -1
  42. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js.map +1 -1
  43. package/dist/transformers/typeorm/local-date-time-transformer.d.ts +4 -4
  44. package/dist/transformers/typeorm/local-date-time-transformer.d.ts.map +1 -1
  45. package/dist/transformers/typeorm/local-date-time-transformer.js +25 -28
  46. package/dist/transformers/typeorm/local-date-time-transformer.js.map +1 -1
  47. package/package.json +1 -1
  48. package/src/entities/chatter-message-details.entity.ts +3 -0
  49. package/src/entities/common.entity.ts +2 -2
  50. package/src/entities/legacy-common.entity.ts +3 -4
  51. package/src/interfaces.ts +7 -1
  52. package/src/services/chatter-message.service.ts +21 -21
  53. package/src/services/dashboard-question.service.ts +23 -4
  54. package/src/services/model-metadata.service.ts +109 -7
  55. package/src/services/question-data-providers/chartjs-sql-data-provider.service.ts +3 -7
  56. package/src/services/question-data-providers/interfaces.ts +0 -0
  57. package/src/services/question-data-providers/prime-react-datatable-sql-data-provider.service.ts +4 -8
  58. package/src/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.ts +4 -8
  59. package/src/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.ts +4 -1
  60. package/src/transformers/typeorm/local-date-time-transformer.ts +41 -33
@@ -29,7 +29,8 @@ let PrimeReactDatatableSqlDataProvider = PrimeReactDatatableSqlDataProvider_1 =
29
29
  name() {
30
30
  return "PrimeReactDatatableSqlDataProvider";
31
31
  }
32
- async getData(question, expressions, context) {
32
+ async getData(question, context) {
33
+ const expressions = context?.expressions || [];
33
34
  const kpi = await (0, helpers_1.getKpi)(question, expressions, this.entityManager, this.sqlExpressionResolver);
34
35
  const labelSql = question.labelSql;
35
36
  const labelResults = await this.entityManager.query(labelSql);
@@ -1 +1 @@
1
- {"version":3,"file":"prime-react-datatable-sql-data-provider.service.js","sourceRoot":"","sources":["../../../src/services/question-data-providers/prime-react-datatable-sql-data-provider.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,4HAA0G;AAG1G,qCAAwC;AACxC,wFAAkF;AAClF,2CAAwC;AAExC,uCAAmC;AAU5B,IAAM,kCAAkC,0CAAxC,MAAM,kCAAkC;IAG3C,YAA6B,aAA4B,EAAmB,qBAAmD;QAAlG,kBAAa,GAAb,aAAa,CAAe;QAAmB,0BAAqB,GAArB,qBAAqB,CAA8B;QAF9G,WAAM,GAAG,IAAI,eAAM,CAAC,oCAAkC,CAAC,IAAI,CAAC,CAAC;IAEqD,CAAC;IAEpI,IAAI;QACA,OAAO,qLAAqL,CAAC;IACjM,CAAC;IAED,IAAI;QACA,OAAO,oCAAoC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAA2B,EAAE,WAA6B,EAAE,OAAwC;QAK9G,MAAM,GAAG,GAAW,MAAM,IAAA,gBAAM,EAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAExG,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;QACnC,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAG,EAAE,CAAC;QACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC;gBACT,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC;gBAC3B,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;aAChC,CAAC,CAAC;QACP,CAAC;QAKD,MAAM,MAAM,GAAG,EAAE,CAAA;QAGjB,MAAM,wBAAwB,GAAG,QAAQ,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC;QAEvE,MAAM,GAAG,GAAG,wBAAwB,CAAC,GAAG,CAAC;QACzC,IAAI,CAAC,GAAG,EAAE,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,eAAe,wBAAwB,CAAC,WAAW,oDAAoD,CAAC,CAAC;QAC7H,CAAC;QAED,MAAM,oBAAoB,GAAG,IAAI,CAAC,qBAAqB,CAAC,yBAAyB,CAAC,GAAG,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;QAC1G,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,wBAAwB,CAAC,WAAW,eAAe,oBAAoB,CAAC,MAAM,GAAG,CAAC,CAAC;QACrI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,wBAAwB,CAAC,WAAW,oBAAoB,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAC9J,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAE7G,OAAO;YACH,GAAG;YACH,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,iBAAiB,EAAE;gBACf,OAAO;gBACP,IAAI,EAAE,OAAO;aAChB;SACJ,CAAC;IAEN,CAAC;CACJ,CAAA;AA3DY,gFAAkC;6CAAlC,kCAAkC;IAF9C,IAAA,0EAA6B,GAAE;IAC/B,IAAA,mBAAU,GAAE;qCAImC,uBAAa,EAA0C,8DAA4B;GAHtH,kCAAkC,CA2D9C","sourcesContent":["import { Injectable } from \"@nestjs/common\";\nimport { DashboardQuestionDataProvider } from \"src/decorators/dashboard-question-data-provider.decorator\";\nimport { DashboardQuestion } from \"src/entities/dashboard-question.entity\";\nimport { IDashboardQuestionDataProvider } from \"src/interfaces\";\nimport { EntityManager } from \"typeorm\";\nimport { SqlExpressionResolverService } from \"../sql-expression-resolver.service\";\nimport { Logger } from '@nestjs/common';\nimport { SqlExpression } from \"./chartjs-sql-data-provider.service\";\nimport { getKpi } from \"./helpers\";\n\nexport interface QuestionSqlDataProviderContext {\n // questionSqlDatasetConfig: QuestionSqlDatasetConfig;\n // questionId: number;\n // question: Question;\n}\n\n@DashboardQuestionDataProvider()\n@Injectable()\nexport class PrimeReactDatatableSqlDataProvider implements IDashboardQuestionDataProvider<QuestionSqlDataProviderContext, any> {\n private readonly logger = new Logger(PrimeReactDatatableSqlDataProvider.name);\n\n constructor(private readonly entityManager: EntityManager, private readonly sqlExpressionResolver: SqlExpressionResolverService) { }\n\n help(): string {\n return \"Provides data for dashboard questions using a SQL dataset configuration. Configure your SQL dataset in the admin panel, then reference it in your dashboard question to fetch data.\";\n }\n\n name(): string {\n return \"PrimeReactDatatableSqlDataProvider\";\n }\n\n async getData(question: DashboardQuestion, expressions?: SqlExpression[], context?: QuestionSqlDataProviderContext): Promise<any> {\n // TODO: put some validation to check if the results of each SQL in each dataset returns the same number of rows \n\n // Check the expected response for prime react data tables to understand what is going on here...\n\n const kpi: string = await getKpi(question, expressions, this.entityManager, this.sqlExpressionResolver);\n // TODO: Load the set of labels by using a separate field on the question entity.\n const labelSql = question.labelSql;\n const labelResults = await this.entityManager.query(labelSql);\n const columns = [];\n for (let i = 0; i < labelResults.length; i++) {\n const labelResult = labelResults[i];\n columns.push({\n field: labelResult['field'],\n header: labelResult['header'],\n });\n }\n\n // Load the chart options as a JSON \n // const chartOptions = JSON.parse(question.barChartLabelOptions || '{}');\n\n const values = []\n\n // For meter group we can assume that we only have one sql dataset config.\n const questionSqlDatasetConfig = question.questionSqlDatasetConfigs[0];\n\n const sql = questionSqlDatasetConfig.sql;\n if (!sql) {\n throw new Error(`SQL dataset ${questionSqlDatasetConfig.datasetName} configuration does not contain a valid SQL query.`);\n }\n\n const sqlReplacementResult = this.sqlExpressionResolver.resolveSqlWithExpressions(sql, expressions || []);\n this.logger.debug(`Final Sql query for dataset [${questionSqlDatasetConfig.datasetName}] is query=[${sqlReplacementResult.rawSql}]`);\n this.logger.debug(`Final Sql query for dataset [${questionSqlDatasetConfig.datasetName}] is parameters=[${JSON.stringify(sqlReplacementResult.parameters)}]`);\n const results = await this.entityManager.query(sqlReplacementResult.rawSql, sqlReplacementResult.parameters);\n\n return {\n kpi,\n visualisedAs: question.visualisedAs,\n visualizationData: {\n columns,\n rows: results,\n }\n };\n\n }\n}"]}
1
+ {"version":3,"file":"prime-react-datatable-sql-data-provider.service.js","sourceRoot":"","sources":["../../../src/services/question-data-providers/prime-react-datatable-sql-data-provider.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,4HAA0G;AAG1G,qCAAwC;AACxC,wFAAkF;AAClF,2CAAwC;AAExC,uCAAmC;AAI5B,IAAM,kCAAkC,0CAAxC,MAAM,kCAAkC;IAG3C,YAA6B,aAA4B,EAAmB,qBAAmD;QAAlG,kBAAa,GAAb,aAAa,CAAe;QAAmB,0BAAqB,GAArB,qBAAqB,CAA8B;QAF9G,WAAM,GAAG,IAAI,eAAM,CAAC,oCAAkC,CAAC,IAAI,CAAC,CAAC;IAEqD,CAAC;IAEpI,IAAI;QACA,OAAO,qLAAqL,CAAC;IACjM,CAAC;IAED,IAAI;QACA,OAAO,oCAAoC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAA2B,EAAE,OAAwC;QAC/E,MAAM,WAAW,GAAoB,OAAO,EAAE,WAAW,IAAI,EAAE,CAAC;QAMhE,MAAM,GAAG,GAAW,MAAM,IAAA,gBAAM,EAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAExG,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;QACnC,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAG,EAAE,CAAC;QACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC;gBACT,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC;gBAC3B,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;aAChC,CAAC,CAAC;QACP,CAAC;QAKD,MAAM,MAAM,GAAG,EAAE,CAAA;QAGjB,MAAM,wBAAwB,GAAG,QAAQ,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC;QAEvE,MAAM,GAAG,GAAG,wBAAwB,CAAC,GAAG,CAAC;QACzC,IAAI,CAAC,GAAG,EAAE,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,eAAe,wBAAwB,CAAC,WAAW,oDAAoD,CAAC,CAAC;QAC7H,CAAC;QAED,MAAM,oBAAoB,GAAG,IAAI,CAAC,qBAAqB,CAAC,yBAAyB,CAAC,GAAG,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;QAC1G,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,wBAAwB,CAAC,WAAW,eAAe,oBAAoB,CAAC,MAAM,GAAG,CAAC,CAAC;QACrI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,wBAAwB,CAAC,WAAW,oBAAoB,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAC9J,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAE7G,OAAO;YACH,GAAG;YACH,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,iBAAiB,EAAE;gBACf,OAAO;gBACP,IAAI,EAAE,OAAO;aAChB;SACJ,CAAC;IAEN,CAAC;CACJ,CAAA;AA7DY,gFAAkC;6CAAlC,kCAAkC;IAF9C,IAAA,0EAA6B,GAAE;IAC/B,IAAA,mBAAU,GAAE;qCAImC,uBAAa,EAA0C,8DAA4B;GAHtH,kCAAkC,CA6D9C","sourcesContent":["import { Injectable } from \"@nestjs/common\";\nimport { DashboardQuestionDataProvider } from \"src/decorators/dashboard-question-data-provider.decorator\";\nimport { DashboardQuestion } from \"src/entities/dashboard-question.entity\";\nimport { IDashboardQuestionDataProvider, QuestionSqlDataProviderContext } from \"src/interfaces\";\nimport { EntityManager } from \"typeorm\";\nimport { SqlExpressionResolverService } from \"../sql-expression-resolver.service\";\nimport { Logger } from '@nestjs/common';\nimport { SqlExpression } from \"./chartjs-sql-data-provider.service\";\nimport { getKpi } from \"./helpers\";\n\n@DashboardQuestionDataProvider()\n@Injectable()\nexport class PrimeReactDatatableSqlDataProvider implements IDashboardQuestionDataProvider<QuestionSqlDataProviderContext, any> {\n private readonly logger = new Logger(PrimeReactDatatableSqlDataProvider.name);\n\n constructor(private readonly entityManager: EntityManager, private readonly sqlExpressionResolver: SqlExpressionResolverService) { }\n\n help(): string {\n return \"Provides data for dashboard questions using a SQL dataset configuration. Configure your SQL dataset in the admin panel, then reference it in your dashboard question to fetch data.\";\n }\n\n name(): string {\n return \"PrimeReactDatatableSqlDataProvider\";\n }\n\n async getData(question: DashboardQuestion, context?: QuestionSqlDataProviderContext): Promise<any> {\n const expressions: SqlExpression[] = context?.expressions || [];\n\n // TODO: put some validation to check if the results of each SQL in each dataset returns the same number of rows \n\n // Check the expected response for prime react data tables to understand what is going on here...\n\n const kpi: string = await getKpi(question, expressions, this.entityManager, this.sqlExpressionResolver);\n // TODO: Load the set of labels by using a separate field on the question entity.\n const labelSql = question.labelSql;\n const labelResults = await this.entityManager.query(labelSql);\n const columns = [];\n for (let i = 0; i < labelResults.length; i++) {\n const labelResult = labelResults[i];\n columns.push({\n field: labelResult['field'],\n header: labelResult['header'],\n });\n }\n\n // Load the chart options as a JSON \n // const chartOptions = JSON.parse(question.barChartLabelOptions || '{}');\n\n const values = []\n\n // For meter group we can assume that we only have one sql dataset config.\n const questionSqlDatasetConfig = question.questionSqlDatasetConfigs[0];\n\n const sql = questionSqlDatasetConfig.sql;\n if (!sql) {\n throw new Error(`SQL dataset ${questionSqlDatasetConfig.datasetName} configuration does not contain a valid SQL query.`);\n }\n\n const sqlReplacementResult = this.sqlExpressionResolver.resolveSqlWithExpressions(sql, expressions || []);\n this.logger.debug(`Final Sql query for dataset [${questionSqlDatasetConfig.datasetName}] is query=[${sqlReplacementResult.rawSql}]`);\n this.logger.debug(`Final Sql query for dataset [${questionSqlDatasetConfig.datasetName}] is parameters=[${JSON.stringify(sqlReplacementResult.parameters)}]`);\n const results = await this.entityManager.query(sqlReplacementResult.rawSql, sqlReplacementResult.parameters);\n\n return {\n kpi,\n visualisedAs: question.visualisedAs,\n visualizationData: {\n columns,\n rows: results,\n }\n };\n\n }\n}"]}
@@ -1,10 +1,7 @@
1
1
  import { DashboardQuestion } from "src/entities/dashboard-question.entity";
2
- import { IDashboardQuestionDataProvider } from "src/interfaces";
2
+ import { IDashboardQuestionDataProvider, QuestionSqlDataProviderContext } from "src/interfaces";
3
3
  import { EntityManager } from "typeorm";
4
4
  import { SqlExpressionResolverService } from "../sql-expression-resolver.service";
5
- import { SqlExpression } from "./chartjs-sql-data-provider.service";
6
- export interface QuestionSqlDataProviderContext {
7
- }
8
5
  export declare class PrimeReactMeterGroupSqlDataProvider implements IDashboardQuestionDataProvider<QuestionSqlDataProviderContext, any> {
9
6
  private readonly entityManager;
10
7
  private readonly sqlExpressionResolver;
@@ -14,6 +11,6 @@ export declare class PrimeReactMeterGroupSqlDataProvider implements IDashboardQu
14
11
  name(): string;
15
12
  hslToHex(h: number, s: number, l: number): string;
16
13
  generateDistinctColors(count: number): string[];
17
- getData(question: DashboardQuestion, expressions?: SqlExpression[], context?: QuestionSqlDataProviderContext): Promise<any>;
14
+ getData(question: DashboardQuestion, context?: QuestionSqlDataProviderContext): Promise<any>;
18
15
  }
19
16
  //# sourceMappingURL=prime-react-meter-group-sql-data-provider.service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prime-react-meter-group-sql-data-provider.service.d.ts","sourceRoot":"","sources":["../../../src/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AAElF,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAGpE,MAAM,WAAW,8BAA8B;CAI9C;AAED,qBAEa,mCAAoC,YAAW,8BAA8B,CAAC,8BAA8B,EAAE,GAAG,CAAC;IAG/G,OAAO,CAAC,QAAQ,CAAC,aAAa;IAAiB,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IAFjG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwD;gBAElD,aAAa,EAAE,aAAa,EAAmB,qBAAqB,EAAE,4BAA4B;IAE/H,IAAI,IAAI,MAAM;IAId,IAAI,IAAI,MAAM;IAId,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;IAcjD,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAezC,OAAO,CAAC,QAAQ,EAAE,iBAAiB,EAAE,WAAW,CAAC,EAAE,aAAa,EAAE,EAAE,OAAO,CAAC,EAAE,8BAA8B,GAAG,OAAO,CAAC,GAAG,CAAC;CA0DpI"}
1
+ {"version":3,"file":"prime-react-meter-group-sql-data-provider.service.d.ts","sourceRoot":"","sources":["../../../src/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,8BAA8B,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAC;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,4BAA4B,EAAE,MAAM,oCAAoC,CAAC;AAKlF,qBAEa,mCAAoC,YAAW,8BAA8B,CAAC,8BAA8B,EAAE,GAAG,CAAC;IAG/G,OAAO,CAAC,QAAQ,CAAC,aAAa;IAAiB,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IAFjG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwD;gBAElD,aAAa,EAAE,aAAa,EAAmB,qBAAqB,EAAE,4BAA4B;IAE/H,IAAI,IAAI,MAAM;IAId,IAAI,IAAI,MAAM;IAId,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;IAcjD,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAezC,OAAO,CAAC,QAAQ,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,8BAA8B,GAAG,OAAO,CAAC,GAAG,CAAC;CA4DrG"}
@@ -50,7 +50,8 @@ let PrimeReactMeterGroupSqlDataProvider = PrimeReactMeterGroupSqlDataProvider_1
50
50
  }
51
51
  return colors;
52
52
  }
53
- async getData(question, expressions, context) {
53
+ async getData(question, context) {
54
+ const expressions = context?.expressions || [];
54
55
  const kpi = await (0, helpers_1.getKpi)(question, expressions, this.entityManager, this.sqlExpressionResolver);
55
56
  const chartOptions = JSON.parse(question.chartOptions || '{}');
56
57
  const values = [];
@@ -1 +1 @@
1
- {"version":3,"file":"prime-react-meter-group-sql-data-provider.service.js","sourceRoot":"","sources":["../../../src/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from \"@nestjs/common\";\nimport { DashboardQuestionDataProvider } from \"src/decorators/dashboard-question-data-provider.decorator\";\nimport { DashboardQuestion } from \"src/entities/dashboard-question.entity\";\nimport { IDashboardQuestionDataProvider } from \"src/interfaces\";\nimport { EntityManager } from \"typeorm\";\nimport { SqlExpressionResolverService } from \"../sql-expression-resolver.service\";\nimport { Logger } from '@nestjs/common';\nimport { SqlExpression } from \"./chartjs-sql-data-provider.service\";\nimport { getKpi } from \"./helpers\";\n\nexport interface QuestionSqlDataProviderContext {\n // questionSqlDatasetConfig: QuestionSqlDatasetConfig;\n // questionId: number;\n // question: Question;\n}\n\n@DashboardQuestionDataProvider()\n@Injectable()\nexport class PrimeReactMeterGroupSqlDataProvider implements IDashboardQuestionDataProvider<QuestionSqlDataProviderContext, any> {\n private readonly logger = new Logger(PrimeReactMeterGroupSqlDataProvider.name);\n\n constructor(private readonly entityManager: EntityManager, private readonly sqlExpressionResolver: SqlExpressionResolverService) { }\n\n help(): string {\n return \"Provides data for dashboard questions using a SQL dataset configuration. Configure your SQL dataset in the admin panel, then reference it in your dashboard question to fetch data.\";\n }\n\n name(): string {\n return \"PrimeReactMeterGroupSqlDataProvider\";\n }\n\n hslToHex(h: number, s: number, l: number): string {\n l /= 100;\n s /= 100;\n\n const k = (n: number) => (n + h / 30) % 12;\n const a = s * Math.min(l, 1 - l);\n const f = (n: number) =>\n Math.round(255 * (l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)))));\n\n return `#${f(0).toString(16).padStart(2, '0')}${f(8).toString(16).padStart(2, '0')}${f(4)\n .toString(16)\n .padStart(2, '0')}`;\n }\n\n generateDistinctColors(count: number): string[] {\n const colors: string[] = [];\n\n const hueStep = 360 / count;\n const saturation = 65; // keep it vibrant\n const lightness = 55; // balanced for both light/dark themes\n\n for (let i = 0; i < count; i++) {\n const hue = Math.round(i * hueStep);\n colors.push(this.hslToHex(hue, saturation, lightness));\n }\n\n return colors;\n }\n\n async getData(question: DashboardQuestion, expressions?: SqlExpression[], context?: QuestionSqlDataProviderContext): Promise<any> {\n // TODO: put some validation to check if the results of each SQL in each dataset returns the same number of rows \n\n // This is what we have to return.\n // const values = [\n // { label: 'Apps', color: '#34d399', value: 16 },\n // { label: 'Messages', color: '#fbbf24', value: 8 },\n // { label: 'Media', color: '#60a5fa', value: 24 },\n // { label: 'System', color: '#c084fc', value: 10 }\n // ];\n\n // TODO: Load the set of labels by using a separate field on the question entity.\n\n const kpi: string = await getKpi(question, expressions, this.entityManager, this.sqlExpressionResolver);\n \n // Load the chart options as a JSON \n const chartOptions = JSON.parse(question.chartOptions || '{}');\n\n const values = []\n\n // For meter group we can assume that we only have one sql dataset config.\n const questionSqlDatasetConfig = question.questionSqlDatasetConfigs[0];\n\n const sql = questionSqlDatasetConfig.sql;\n if (!sql) {\n throw new Error(`SQL dataset ${questionSqlDatasetConfig.datasetName} configuration does not contain a valid SQL query.`);\n }\n\n const sqlReplacementResult = this.sqlExpressionResolver.resolveSqlWithExpressions(sql, expressions || []);\n this.logger.debug(`Final Sql query for dataset [${questionSqlDatasetConfig.datasetName}] is query=[${sqlReplacementResult.rawSql}]`);\n this.logger.debug(`Final Sql query for dataset [${questionSqlDatasetConfig.datasetName}] is parameters=[${JSON.stringify(sqlReplacementResult.parameters)}]`);\n const results = await this.entityManager.query(sqlReplacementResult.rawSql, sqlReplacementResult.parameters);\n\n const colors = this.generateDistinctColors(results.length);\n\n // Also for each data set we create the dataset object as is expected by ChartJs.\n for (let i = 0; i < results.length; i++) {\n const result = results[i];\n\n const colorFromChartOptions = chartOptions?.colors?.[result[questionSqlDatasetConfig.labelColumnName]];\n const color = typeof colorFromChartOptions === 'string' ? colorFromChartOptions : colors[i];\n\n values.push({\n label: result[questionSqlDatasetConfig.labelColumnName],\n color: color,\n value: result[questionSqlDatasetConfig.valueColumnName]\n })\n }\n\n return {\n kpi,\n visualizedAs: question.visualisedAs,\n visualizationData: {\n dataset: values\n },\n };\n\n }\n}"]}
1
+ {"version":3,"file":"prime-react-meter-group-sql-data-provider.service.js","sourceRoot":"","sources":["../../../src/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,4HAA0G;AAG1G,qCAAwC;AACxC,wFAAkF;AAClF,2CAAwC;AAExC,uCAAmC;AAI5B,IAAM,mCAAmC,2CAAzC,MAAM,mCAAmC;IAG5C,YAA6B,aAA4B,EAAmB,qBAAmD;QAAlG,kBAAa,GAAb,aAAa,CAAe;QAAmB,0BAAqB,GAArB,qBAAqB,CAA8B;QAF9G,WAAM,GAAG,IAAI,eAAM,CAAC,qCAAmC,CAAC,IAAI,CAAC,CAAC;IAEoD,CAAC;IAEpI,IAAI;QACA,OAAO,qLAAqL,CAAC;IACjM,CAAC;IAED,IAAI;QACA,OAAO,qCAAqC,CAAC;IACjD,CAAC;IAED,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;QACpC,CAAC,IAAI,GAAG,CAAC;QACT,CAAC,IAAI,GAAG,CAAC;QAET,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CACpB,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAExF,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;aACpF,QAAQ,CAAC,EAAE,CAAC;aACZ,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;IAC5B,CAAC;IAED,sBAAsB,CAAC,KAAa;QAChC,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,MAAM,OAAO,GAAG,GAAG,GAAG,KAAK,CAAC;QAC5B,MAAM,UAAU,GAAG,EAAE,CAAC;QACtB,MAAM,SAAS,GAAG,EAAE,CAAC;QAErB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC;YACpC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;QAC3D,CAAC;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAA2B,EAAE,OAAwC;QAC/E,MAAM,WAAW,GAAoB,OAAO,EAAE,WAAW,IAAI,EAAE,CAAC;QAchE,MAAM,GAAG,GAAW,MAAM,IAAA,gBAAM,EAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAGxG,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC;QAE/D,MAAM,MAAM,GAAG,EAAE,CAAA;QAGjB,MAAM,wBAAwB,GAAG,QAAQ,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC;QAEvE,MAAM,GAAG,GAAG,wBAAwB,CAAC,GAAG,CAAC;QACzC,IAAI,CAAC,GAAG,EAAE,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,eAAe,wBAAwB,CAAC,WAAW,oDAAoD,CAAC,CAAC;QAC7H,CAAC;QAED,MAAM,oBAAoB,GAAG,IAAI,CAAC,qBAAqB,CAAC,yBAAyB,CAAC,GAAG,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;QAC1G,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,wBAAwB,CAAC,WAAW,eAAe,oBAAoB,CAAC,MAAM,GAAG,CAAC,CAAC;QACrI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,wBAAwB,CAAC,WAAW,oBAAoB,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAC9J,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAE7G,MAAM,MAAM,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAG3D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YAE1B,MAAM,qBAAqB,GAAG,YAAY,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,wBAAwB,CAAC,eAAe,CAAC,CAAC,CAAC;YACvG,MAAM,KAAK,GAAG,OAAO,qBAAqB,KAAK,QAAQ,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAE5F,MAAM,CAAC,IAAI,CAAC;gBACR,KAAK,EAAE,MAAM,CAAC,wBAAwB,CAAC,eAAe,CAAC;gBACvD,KAAK,EAAE,KAAK;gBACZ,KAAK,EAAE,MAAM,CAAC,wBAAwB,CAAC,eAAe,CAAC;aAC1D,CAAC,CAAA;QACN,CAAC;QAED,OAAO;YACH,GAAG;YACH,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,iBAAiB,EAAE;gBACf,OAAO,EAAE,MAAM;aAClB;SACJ,CAAC;IAEN,CAAC;CACJ,CAAA;AAtGY,kFAAmC;8CAAnC,mCAAmC;IAF/C,IAAA,0EAA6B,GAAE;IAC/B,IAAA,mBAAU,GAAE;qCAImC,uBAAa,EAA0C,8DAA4B;GAHtH,mCAAmC,CAsG/C","sourcesContent":["import { Injectable } from \"@nestjs/common\";\nimport { DashboardQuestionDataProvider } from \"src/decorators/dashboard-question-data-provider.decorator\";\nimport { DashboardQuestion } from \"src/entities/dashboard-question.entity\";\nimport { IDashboardQuestionDataProvider, QuestionSqlDataProviderContext } from \"src/interfaces\";\nimport { EntityManager } from \"typeorm\";\nimport { SqlExpressionResolverService } from \"../sql-expression-resolver.service\";\nimport { Logger } from '@nestjs/common';\nimport { SqlExpression } from \"./chartjs-sql-data-provider.service\";\nimport { getKpi } from \"./helpers\";\n\n@DashboardQuestionDataProvider()\n@Injectable()\nexport class PrimeReactMeterGroupSqlDataProvider implements IDashboardQuestionDataProvider<QuestionSqlDataProviderContext, any> {\n private readonly logger = new Logger(PrimeReactMeterGroupSqlDataProvider.name);\n\n constructor(private readonly entityManager: EntityManager, private readonly sqlExpressionResolver: SqlExpressionResolverService) { }\n\n help(): string {\n return \"Provides data for dashboard questions using a SQL dataset configuration. Configure your SQL dataset in the admin panel, then reference it in your dashboard question to fetch data.\";\n }\n\n name(): string {\n return \"PrimeReactMeterGroupSqlDataProvider\";\n }\n\n hslToHex(h: number, s: number, l: number): string {\n l /= 100;\n s /= 100;\n\n const k = (n: number) => (n + h / 30) % 12;\n const a = s * Math.min(l, 1 - l);\n const f = (n: number) =>\n Math.round(255 * (l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)))));\n\n return `#${f(0).toString(16).padStart(2, '0')}${f(8).toString(16).padStart(2, '0')}${f(4)\n .toString(16)\n .padStart(2, '0')}`;\n }\n\n generateDistinctColors(count: number): string[] {\n const colors: string[] = [];\n\n const hueStep = 360 / count;\n const saturation = 65; // keep it vibrant\n const lightness = 55; // balanced for both light/dark themes\n\n for (let i = 0; i < count; i++) {\n const hue = Math.round(i * hueStep);\n colors.push(this.hslToHex(hue, saturation, lightness));\n }\n\n return colors;\n }\n\n async getData(question: DashboardQuestion, context?: QuestionSqlDataProviderContext): Promise<any> {\n const expressions: SqlExpression[] = context?.expressions || [];\n\n // TODO: put some validation to check if the results of each SQL in each dataset returns the same number of rows \n\n // This is what we have to return.\n // const values = [\n // { label: 'Apps', color: '#34d399', value: 16 },\n // { label: 'Messages', color: '#fbbf24', value: 8 },\n // { label: 'Media', color: '#60a5fa', value: 24 },\n // { label: 'System', color: '#c084fc', value: 10 }\n // ];\n\n // TODO: Load the set of labels by using a separate field on the question entity.\n\n const kpi: string = await getKpi(question, expressions, this.entityManager, this.sqlExpressionResolver);\n \n // Load the chart options as a JSON \n const chartOptions = JSON.parse(question.chartOptions || '{}');\n\n const values = []\n\n // For meter group we can assume that we only have one sql dataset config.\n const questionSqlDatasetConfig = question.questionSqlDatasetConfigs[0];\n\n const sql = questionSqlDatasetConfig.sql;\n if (!sql) {\n throw new Error(`SQL dataset ${questionSqlDatasetConfig.datasetName} configuration does not contain a valid SQL query.`);\n }\n\n const sqlReplacementResult = this.sqlExpressionResolver.resolveSqlWithExpressions(sql, expressions || []);\n this.logger.debug(`Final Sql query for dataset [${questionSqlDatasetConfig.datasetName}] is query=[${sqlReplacementResult.rawSql}]`);\n this.logger.debug(`Final Sql query for dataset [${questionSqlDatasetConfig.datasetName}] is parameters=[${JSON.stringify(sqlReplacementResult.parameters)}]`);\n const results = await this.entityManager.query(sqlReplacementResult.rawSql, sqlReplacementResult.parameters);\n\n const colors = this.generateDistinctColors(results.length);\n\n // Also for each data set we create the dataset object as is expected by ChartJs.\n for (let i = 0; i < results.length; i++) {\n const result = results[i];\n\n const colorFromChartOptions = chartOptions?.colors?.[result[questionSqlDatasetConfig.labelColumnName]];\n const color = typeof colorFromChartOptions === 'string' ? colorFromChartOptions : colors[i];\n\n values.push({\n label: result[questionSqlDatasetConfig.labelColumnName],\n color: color,\n value: result[questionSqlDatasetConfig.valueColumnName]\n })\n }\n\n return {\n kpi,\n visualizedAs: question.visualisedAs,\n visualizationData: {\n dataset: values\n },\n };\n\n }\n}"]}
@@ -1 +1 @@
1
- {"version":3,"file":"list-of-dashboard-question-providers-selection-provider.service.d.ts","sourceRoot":"","sources":["../../../src/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAuE,kBAAkB,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAIhL,qBAEa,iDAAkD,YAAW,kBAAkB,CAAC,yBAAyB,CAAC;IAG/G,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAAb,aAAa,EAAE,aAAa;IAIjD,IAAI,IAAI,MAAM;IAId,IAAI,IAAI,MAAM;IAIR,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,GAAG,GAAG,CAAC;IASpG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,SAAS,wBAAwB,EAAE,CAAC;CAO7G"}
1
+ {"version":3,"file":"list-of-dashboard-question-providers-selection-provider.service.d.ts","sourceRoot":"","sources":["../../../src/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAuE,kBAAkB,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAKhL,qBAEa,iDAAkD,YAAW,kBAAkB,CAAC,yBAAyB,CAAC;IAG/G,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAAb,aAAa,EAAE,aAAa;IAIjD,IAAI,IAAI,MAAM;IAId,IAAI,IAAI,MAAM;IAIR,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,GAAG,GAAG,CAAC;IASpG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,SAAS,wBAAwB,EAAE,CAAC;CAS7G"}
@@ -13,6 +13,7 @@ exports.ListOfDashboardQuestionProvidersSelectionProvider = void 0;
13
13
  const common_1 = require("@nestjs/common");
14
14
  const selection_provider_decorator_1 = require("../../decorators/selection-provider.decorator");
15
15
  const solid_registry_1 = require("../../helpers/solid-registry");
16
+ const dashboard_question_service_1 = require("../dashboard-question.service");
16
17
  let ListOfDashboardQuestionProvidersSelectionProvider = class ListOfDashboardQuestionProvidersSelectionProvider {
17
18
  constructor(solidRegistry) {
18
19
  this.solidRegistry = solidRegistry;
@@ -32,7 +33,9 @@ let ListOfDashboardQuestionProvidersSelectionProvider = class ListOfDashboardQue
32
33
  }
33
34
  async values(query, ctxt) {
34
35
  const dashboardSelectionProviders = this.solidRegistry.getDashboardQuestionDataProviders();
35
- return dashboardSelectionProviders.map(i => {
36
+ return dashboardSelectionProviders
37
+ .filter(provider => !dashboard_question_service_1.INBUILT_SQL_DATA_PROVIDERS.includes(provider.name()))
38
+ .map(i => {
36
39
  return { label: i.name, value: i.name };
37
40
  });
38
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"list-of-dashboard-question-providers-selection-provider.service.js","sourceRoot":"","sources":["../../../src/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,gGAAgF;AAChF,iEAA2D;AAOpD,IAAM,iDAAiD,GAAvD,MAAM,iDAAiD;IAE1D,YACqB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IAEjD,CAAC;IAED,IAAI;QACA,OAAO,mGAAmG,CAAC;IAC/G,CAAC;IAED,IAAI;QACA,OAAO,mDAAmD,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,WAAmB,EAAE,IAA+B;QAC5D,MAAM,0BAA0B,GAAyD,IAAI,CAAC,aAAa,CAAC,wCAAwC,CAAC,WAAW,CAAC,CAAC;QAClK,IAAI,CAAC,0BAA0B,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,0BAA0B,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,0BAA0B,CAAC,IAAI,EAAE,EAAE,CAAC;IAClG,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,IAA+B;QACvD,MAAM,2BAA2B,GAAG,IAAI,CAAC,aAAa,CAAC,iCAAiC,EAAE,CAAA;QAE1F,OAAO,2BAA2B,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YACvC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5C,CAAC,CAAC,CAAC;IACP,CAAC;CACJ,CAAA;AA/BY,8GAAiD;4DAAjD,iDAAiD;IAF7D,IAAA,gDAAiB,GAAE;IACnB,IAAA,mBAAU,GAAE;qCAI2B,8BAAa;GAHxC,iDAAiD,CA+B7D","sourcesContent":["import { Injectable } from \"@nestjs/common\";\nimport { SelectionProvider } from \"src/decorators/selection-provider.decorator\";\nimport { SolidRegistry } from \"src/helpers/solid-registry\";\nimport { IDashboardQuestionDataProvider, IDashboardVariableSelectionProvider, ISelectionProvider, ISelectionProviderContext, ISelectionProviderValues } from \"../../interfaces\";\nimport { SQL_DYNAMIC_PROVIDER_NAME } from \"../dashboard.service\";\n\n\n@SelectionProvider()\n@Injectable()\nexport class ListOfDashboardQuestionProvidersSelectionProvider implements ISelectionProvider<ISelectionProviderContext> {\n\n constructor(\n private readonly solidRegistry: SolidRegistry,\n ) {\n }\n\n help(): string {\n return \"# Allows one to dynamically fetch all the dashboard providers that are registered in the system. \";\n }\n\n name(): string {\n return 'ListOfDashboardQuestionProvidersSelectionProvider';\n }\n\n async value(optionValue: string, ctxt: ISelectionProviderContext): Promise<ISelectionProviderValues | any> {\n const dashboardSelectionProvider: IDashboardQuestionDataProvider<any, any> | undefined = this.solidRegistry.getDashboardQuestionDataProviderInstance(optionValue);\n if (!dashboardSelectionProvider) {\n return null;\n }\n\n return { label: dashboardSelectionProvider.name(), value: dashboardSelectionProvider.name() };\n }\n\n async values(query: string, ctxt: ISelectionProviderContext): Promise<readonly ISelectionProviderValues[]> {\n const dashboardSelectionProviders = this.solidRegistry.getDashboardQuestionDataProviders()\n //Exclude the SQL dynamic provider from the list, (since although it is a dashboard selection provider, it is not a valid option for the user to select)\n return dashboardSelectionProviders.map(i => {\n return { label: i.name, value: i.name };\n });\n }\n}"]}
1
+ {"version":3,"file":"list-of-dashboard-question-providers-selection-provider.service.js","sourceRoot":"","sources":["../../../src/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,gGAAgF;AAChF,iEAA2D;AAG3D,8EAAyM;AAKlM,IAAM,iDAAiD,GAAvD,MAAM,iDAAiD;IAE1D,YACqB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IAEjD,CAAC;IAED,IAAI;QACA,OAAO,mGAAmG,CAAC;IAC/G,CAAC;IAED,IAAI;QACA,OAAO,mDAAmD,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,WAAmB,EAAE,IAA+B;QAC5D,MAAM,0BAA0B,GAAyD,IAAI,CAAC,aAAa,CAAC,wCAAwC,CAAC,WAAW,CAAC,CAAC;QAClK,IAAI,CAAC,0BAA0B,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,0BAA0B,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,0BAA0B,CAAC,IAAI,EAAE,EAAE,CAAC;IAClG,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,IAA+B;QACvD,MAAM,2BAA2B,GAAG,IAAI,CAAC,aAAa,CAAC,iCAAiC,EAAE,CAAA;QAE1F,OAAO,2BAA2B;aACjC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,uDAA0B,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;aACzE,GAAG,CAAC,CAAC,CAAC,EAAE;YACL,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5C,CAAC,CAAC,CAAC;IACP,CAAC;CACJ,CAAA;AAjCY,8GAAiD;4DAAjD,iDAAiD;IAF7D,IAAA,gDAAiB,GAAE;IACnB,IAAA,mBAAU,GAAE;qCAI2B,8BAAa;GAHxC,iDAAiD,CAiC7D","sourcesContent":["import { Injectable } from \"@nestjs/common\";\nimport { SelectionProvider } from \"src/decorators/selection-provider.decorator\";\nimport { SolidRegistry } from \"src/helpers/solid-registry\";\nimport { IDashboardQuestionDataProvider, IDashboardVariableSelectionProvider, ISelectionProvider, ISelectionProviderContext, ISelectionProviderValues } from \"../../interfaces\";\nimport { SQL_DYNAMIC_PROVIDER_NAME } from \"../dashboard.service\";\nimport { CHARTJS_SQL_DATA_PROVIDER_NAME, INBUILT_SQL_DATA_PROVIDERS, PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME, PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME } from \"../dashboard-question.service\";\n\n\n@SelectionProvider()\n@Injectable()\nexport class ListOfDashboardQuestionProvidersSelectionProvider implements ISelectionProvider<ISelectionProviderContext> {\n\n constructor(\n private readonly solidRegistry: SolidRegistry,\n ) {\n }\n\n help(): string {\n return \"# Allows one to dynamically fetch all the dashboard providers that are registered in the system. \";\n }\n\n name(): string {\n return 'ListOfDashboardQuestionProvidersSelectionProvider';\n }\n\n async value(optionValue: string, ctxt: ISelectionProviderContext): Promise<ISelectionProviderValues | any> {\n const dashboardSelectionProvider: IDashboardQuestionDataProvider<any, any> | undefined = this.solidRegistry.getDashboardQuestionDataProviderInstance(optionValue);\n if (!dashboardSelectionProvider) {\n return null;\n }\n\n return { label: dashboardSelectionProvider.name(), value: dashboardSelectionProvider.name() };\n }\n\n async values(query: string, ctxt: ISelectionProviderContext): Promise<readonly ISelectionProviderValues[]> {\n const dashboardSelectionProviders = this.solidRegistry.getDashboardQuestionDataProviders()\n //Exclude the SQL dynamic provider from the list, (since although it is a dashboard selection provider, it is not a valid option for the user to select)\n return dashboardSelectionProviders\n .filter(provider => !INBUILT_SQL_DATA_PROVIDERS.includes(provider.name())) \n .map(i => {\n return { label: i.name, value: i.name };\n });\n }\n}"]}
@@ -1,6 +1,6 @@
1
+ import dayjs from "dayjs";
1
2
  import { ValueTransformer } from "typeorm";
2
- export declare const LocalDateTimeTransformer: ValueTransformer & {
3
- utc: ValueTransformer;
4
- };
5
- export declare const UtcDateTimeTransformer: ValueTransformer;
3
+ export declare function parseDate(date: Date): dayjs.Dayjs;
4
+ export declare function serializeDate(date: Date): string;
5
+ export declare const LocalDateTimeTransformer: ValueTransformer;
6
6
  //# sourceMappingURL=local-date-time-transformer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"local-date-time-transformer.d.ts","sourceRoot":"","sources":["../../../src/transformers/typeorm/local-date-time-transformer.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAsB3C,eAAO,MAAM,wBAAwB,EAAE,gBAAgB,GAAG;IAAE,GAAG,EAAE,gBAAgB,CAAA;CAiDhF,CAAC;AAEF,eAAO,MAAM,sBAAsB,kBAA+B,CAAC"}
1
+ {"version":3,"file":"local-date-time-transformer.d.ts","sourceRoot":"","sources":["../../../src/transformers/typeorm/local-date-time-transformer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAmC3C,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,KAAK,CAAC,KAAK,CAIjD;AAQD,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAIhD;AAED,eAAO,MAAM,wBAAwB,EAAE,gBA2BtC,CAAC"}
@@ -3,7 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.UtcDateTimeTransformer = exports.LocalDateTimeTransformer = void 0;
6
+ exports.LocalDateTimeTransformer = void 0;
7
+ exports.parseDate = parseDate;
8
+ exports.serializeDate = serializeDate;
7
9
  const dayjs_1 = __importDefault(require("dayjs"));
8
10
  const utc_1 = __importDefault(require("dayjs/plugin/utc"));
9
11
  const timezone_1 = __importDefault(require("dayjs/plugin/timezone"));
@@ -20,49 +22,44 @@ function dateToUtcComponentString(d) {
20
22
  const ms = pad(d.getUTCMilliseconds(), 3);
21
23
  return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}.${ms}`;
22
24
  }
25
+ function getWallClockConfig() {
26
+ return {
27
+ tz: process.env.SOLIDX_WALL_TIME_TIMEZONE || process.env.SOLIDX_TIMEZONE || "UTC",
28
+ wallTimeMode: (process.env.SOLIDX_TIME_STORED_AS_WALL_TIME || "").toLowerCase() === "true",
29
+ };
30
+ }
31
+ function parseDate(date) {
32
+ const { tz, wallTimeMode } = getWallClockConfig();
33
+ if (!wallTimeMode)
34
+ return dayjs_1.default.utc(date);
35
+ return (0, dayjs_1.default)(date).tz(tz);
36
+ }
37
+ function serializeDate(date) {
38
+ const { wallTimeMode } = getWallClockConfig();
39
+ if (!wallTimeMode)
40
+ return date.toISOString();
41
+ return parseDate(date).format("YYYY-MM-DD HH:mm:ss.SSS");
42
+ }
23
43
  exports.LocalDateTimeTransformer = {
24
44
  from(value) {
25
- const SOLIDX_WALL_TIME_TZ = process.env.SOLIDX_WALL_TIME_TIMEZONE || process.env.SOLIDX_TIMEZONE || "UTC";
26
- const SOLIDX_TIME_STORED_AS_WALL_TIME = (process.env.SOLIDX_TIME_STORED_AS_WALL_TIME || "").toLowerCase() === "true";
27
45
  if (value === undefined)
28
46
  return undefined;
29
47
  if (value === null)
30
48
  return null;
31
- if (!SOLIDX_TIME_STORED_AS_WALL_TIME) {
49
+ const { tz, wallTimeMode } = getWallClockConfig();
50
+ if (!wallTimeMode) {
32
51
  return (0, dayjs_1.default)(value).toDate();
33
52
  }
34
53
  const naive = value instanceof Date ? dateToUtcComponentString(value) : String(value);
35
- return dayjs_1.default.tz(naive, SOLIDX_WALL_TIME_TZ).utc().toDate();
54
+ return dayjs_1.default.tz(naive, tz).utc().toDate();
36
55
  },
37
56
  to(value) {
38
- const SOLIDX_WALL_TIME_TZ = process.env.SOLIDX_WALL_TIME_TIMEZONE || process.env.SOLIDX_TIMEZONE || "UTC";
39
- const SOLIDX_TIME_STORED_AS_WALL_TIME = (process.env.SOLIDX_TIME_STORED_AS_WALL_TIME || "").toLowerCase() === "true";
40
57
  if (value === undefined)
41
58
  return undefined;
42
59
  if (value === null)
43
60
  return null;
44
- if (!SOLIDX_TIME_STORED_AS_WALL_TIME) {
45
- return (0, dayjs_1.default)(value).toDate();
46
- }
47
- const wallTimeStr = (0, dayjs_1.default)(value).tz(SOLIDX_WALL_TIME_TZ).format("YYYY-MM-DD HH:mm:ss.SSS");
61
+ const wallTimeStr = serializeDate(value);
48
62
  return dayjs_1.default.utc(wallTimeStr).toDate();
49
63
  },
50
- utc: {
51
- from(value) {
52
- if (value === undefined)
53
- return undefined;
54
- if (value === null)
55
- return null;
56
- return (0, dayjs_1.default)(value).toDate();
57
- },
58
- to(value) {
59
- if (value === undefined)
60
- return undefined;
61
- if (value === null)
62
- return null;
63
- return (0, dayjs_1.default)(value).toDate();
64
- }
65
- }
66
64
  };
67
- exports.UtcDateTimeTransformer = exports.LocalDateTimeTransformer.utc;
68
65
  //# sourceMappingURL=local-date-time-transformer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"local-date-time-transformer.js","sourceRoot":"","sources":["../../../src/transformers/typeorm/local-date-time-transformer.ts"],"names":[],"mappings":"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","sourcesContent":["import dayjs from \"dayjs\";\nimport utc from \"dayjs/plugin/utc\";\nimport timezone from \"dayjs/plugin/timezone\";\n\nimport { ValueTransformer } from \"typeorm\";\n\ndayjs.extend(utc);\ndayjs.extend(timezone);\n\nfunction dateToUtcComponentString(d: Date): string {\n // Requires MSSQL driver option: useUTC: true\n // so that DB \"2026-01-08 10:00:00\" -> Date with UTC parts 2026-01-08 10:00:00\n const pad = (n: number, w = 2) => String(n).padStart(w, \"0\");\n\n const yyyy = d.getUTCFullYear();\n const mm = pad(d.getUTCMonth() + 1);\n const dd = pad(d.getUTCDate());\n const hh = pad(d.getUTCHours());\n const mi = pad(d.getUTCMinutes());\n const ss = pad(d.getUTCSeconds());\n const ms = pad(d.getUTCMilliseconds(), 3);\n\n // A naive timestamp string representing the DB wall-clock components\n return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}.${ms}`;\n}\n\nexport const LocalDateTimeTransformer: ValueTransformer & { utc: ValueTransformer } = {\n // DB → Entity\n from(value: Date | string | null | undefined): Date | null | undefined {\n\n const SOLIDX_WALL_TIME_TZ = process.env.SOLIDX_WALL_TIME_TIMEZONE || process.env.SOLIDX_TIMEZONE || \"UTC\";\n const SOLIDX_TIME_STORED_AS_WALL_TIME = (process.env.SOLIDX_TIME_STORED_AS_WALL_TIME || \"\").toLowerCase() === \"true\";\n\n // critical... super important to return undefined here \n if (value === undefined) return undefined;\n if (value === null) return null;\n\n if (!SOLIDX_TIME_STORED_AS_WALL_TIME) {\n return dayjs(value).toDate();\n }\n\n const naive = value instanceof Date ? dateToUtcComponentString(value) : String(value);\n return dayjs.tz(naive, SOLIDX_WALL_TIME_TZ).utc().toDate();\n },\n\n // Entity DB\n to(value: Date | null | undefined): Date | null | undefined {\n\n const SOLIDX_WALL_TIME_TZ = process.env.SOLIDX_WALL_TIME_TIMEZONE || process.env.SOLIDX_TIMEZONE || \"UTC\";\n const SOLIDX_TIME_STORED_AS_WALL_TIME = (process.env.SOLIDX_TIME_STORED_AS_WALL_TIME || \"\").toLowerCase() === \"true\";\n\n // critical... super important to return undefined here \n if (value === undefined) return undefined;\n if (value === null) return null;\n\n if (!SOLIDX_TIME_STORED_AS_WALL_TIME) {\n return dayjs(value).toDate();\n }\n\n const wallTimeStr = dayjs(value).tz(SOLIDX_WALL_TIME_TZ).format(\"YYYY-MM-DD HH:mm:ss.SSS\");\n return dayjs.utc(wallTimeStr).toDate();\n },\n\n utc: {\n from(value: Date | string | null | undefined): Date | null | undefined {\n if (value === undefined) return undefined;\n if (value === null) return null;\n return dayjs(value).toDate();\n },\n to(value: Date | null | undefined): Date | null | undefined {\n if (value === undefined) return undefined;\n if (value === null) return null;\n return dayjs(value).toDate();\n }\n }\n};\n\nexport const UtcDateTimeTransformer = LocalDateTimeTransformer.utc;"]}
1
+ {"version":3,"file":"local-date-time-transformer.js","sourceRoot":"","sources":["../../../src/transformers/typeorm/local-date-time-transformer.ts"],"names":[],"mappings":"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","sourcesContent":["import dayjs from \"dayjs\";\nimport utc from \"dayjs/plugin/utc\";\nimport timezone from \"dayjs/plugin/timezone\";\n\nimport { ValueTransformer } from \"typeorm\";\n\ndayjs.extend(utc);\ndayjs.extend(timezone);\n\nfunction dateToUtcComponentString(d: Date): string {\n // Requires MSSQL driver option: useUTC: true\n // so that DB \"2026-01-08 10:00:00\" -> Date with UTC parts 2026-01-08 10:00:00\n const pad = (n: number, w = 2) => String(n).padStart(w, \"0\");\n\n const yyyy = d.getUTCFullYear();\n const mm = pad(d.getUTCMonth() + 1);\n const dd = pad(d.getUTCDate());\n const hh = pad(d.getUTCHours());\n const mi = pad(d.getUTCMinutes());\n const ss = pad(d.getUTCSeconds());\n const ms = pad(d.getUTCMilliseconds(), 3);\n\n // A \"naive\" timestamp string representing the DB wall-clock components\n return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}.${ms}`;\n}\n\nfunction getWallClockConfig(): { tz: string; wallTimeMode: boolean } {\n return {\n tz: process.env.SOLIDX_WALL_TIME_TIMEZONE || process.env.SOLIDX_TIMEZONE || \"UTC\",\n wallTimeMode: (process.env.SOLIDX_TIME_STORED_AS_WALL_TIME || \"\").toLowerCase() === \"true\",\n };\n}\n\n/**\n * Returns a dayjs instance positioned at the wall-clock time for the given Date.\n * - Wall-clock mode ON: dayjs in the configured timezone (components = wall-clock components)\n * - Wall-clock mode OFF: dayjs in UTC\n * Counterpart to serializeDate — use this to format/display a date value correctly.\n */\nexport function parseDate(date: Date): dayjs.Dayjs {\n const { tz, wallTimeMode } = getWallClockConfig();\n if (!wallTimeMode) return dayjs.utc(date);\n return dayjs(date).tz(tz);\n}\n\n/**\n * Converts a Date to a string for storage in plain text columns (e.g. audit values).\n * - Wall-clock mode ON: \"YYYY-MM-DD HH:mm:ss.SSS\" in the configured timezone (no Z suffix)\n * - Wall-clock mode OFF: ISO 8601 UTC string with Z suffix\n * The presence/absence of the Z suffix lets consumers distinguish the two cases.\n */\nexport function serializeDate(date: Date): string {\n const { wallTimeMode } = getWallClockConfig();\n if (!wallTimeMode) return date.toISOString();\n return parseDate(date).format(\"YYYY-MM-DD HH:mm:ss.SSS\");\n}\n\nexport const LocalDateTimeTransformer: ValueTransformer = {\n // DB -> Entity\n from(value: Date | string | null | undefined): Date | null | undefined {\n // critical... super important to return undefined here\n if (value === undefined) return undefined;\n if (value === null) return null;\n\n const { tz, wallTimeMode } = getWallClockConfig();\n\n if (!wallTimeMode) {\n return dayjs(value).toDate();\n }\n\n const naive = value instanceof Date ? dateToUtcComponentString(value) : String(value);\n return dayjs.tz(naive, tz).utc().toDate();\n },\n\n // Entity -> DB\n to(value: Date | null | undefined): Date | null | undefined {\n // critical... super important to return undefined here\n if (value === undefined) return undefined;\n if (value === null) return null;\n\n const wallTimeStr = serializeDate(value);\n return dayjs.utc(wallTimeStr).toDate();\n },\n\n};\n\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidxai/core",
3
- "version": "0.1.6-beta.2",
3
+ "version": "0.1.6-beta.3",
4
4
  "description": "This module is a NestJS module containing all the required core providers required by a Solid application",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -26,4 +26,7 @@ export class ChatterMessageDetails extends CommonEntity {
26
26
 
27
27
  @Column({ type: "text", nullable: true })
28
28
  fieldDisplayName: string;
29
+
30
+ @Column({ type: "varchar", nullable: true })
31
+ fieldType: string;
29
32
  }
@@ -1,6 +1,6 @@
1
- import { Column, CreateDateColumn, DeleteDateColumn, Index, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";
2
1
  import { Exclude, Expose } from "class-transformer";
3
- import { LocalDateTimeTransformer, UtcDateTimeTransformer } from "src/transformers/typeorm/local-date-time-transformer";
2
+ import { LocalDateTimeTransformer } from "src/transformers/typeorm/local-date-time-transformer";
3
+ import { Column, CreateDateColumn, DeleteDateColumn, Index, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";
4
4
 
5
5
  @Exclude()
6
6
  export abstract class CommonEntity {
@@ -1,7 +1,6 @@
1
- import { Exclude, Expose, Type } from "class-transformer";
2
- import { Column, CreateDateColumn, DeleteDateColumn, Index, JoinColumn, ManyToOne, UpdateDateColumn } from "typeorm";
3
- import type { User } from "./user.entity";
4
- import { LocalDateTimeTransformer, UtcDateTimeTransformer } from "src/transformers/typeorm/local-date-time-transformer";
1
+ import { Exclude, Expose } from "class-transformer";
2
+ import { LocalDateTimeTransformer } from "src/transformers/typeorm/local-date-time-transformer";
3
+ import { Column, CreateDateColumn, DeleteDateColumn, Index, UpdateDateColumn } from "typeorm";
5
4
 
6
5
  export const LEGACY_TABLE_FIELDS_PREFIX = 'ss';
7
6
 
package/src/interfaces.ts CHANGED
@@ -136,12 +136,18 @@ export interface IMcpToolResponseHandler {
136
136
  apply(aiInteraction: AiInteraction);
137
137
  }
138
138
 
139
+ export interface QuestionSqlDataProviderContext {
140
+ // questionSqlDatasetConfig: QuestionSqlDatasetConfig;
141
+ // questionId: number;
142
+ // question: Question;
143
+ expressions?: SqlExpression[]
144
+ }
139
145
  export interface IDashboardQuestionDataProvider<TContext, TData> {
140
146
  help(): string;
141
147
 
142
148
  name(): string;
143
149
 
144
- getData(question: DashboardQuestion, expressions?: SqlExpression[], ctxt?: TContext): Promise<TData[] | TData>;
150
+ getData(question: DashboardQuestion, ctxt?: TContext): Promise<TData[] | TData>;
145
151
  }
146
152
 
147
153
  /**
@@ -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');
@@ -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