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

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 (80) 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/seeders/seed-data/solid-core-metadata.json +73 -3
  14. package/dist/services/authentication.service.d.ts.map +1 -1
  15. package/dist/services/authentication.service.js +16 -12
  16. package/dist/services/authentication.service.js.map +1 -1
  17. package/dist/services/chatter-message.service.d.ts +0 -1
  18. package/dist/services/chatter-message.service.d.ts.map +1 -1
  19. package/dist/services/chatter-message.service.js +22 -19
  20. package/dist/services/chatter-message.service.js.map +1 -1
  21. package/dist/services/dashboard-question.service.d.ts +4 -0
  22. package/dist/services/dashboard-question.service.d.ts.map +1 -1
  23. package/dist/services/dashboard-question.service.js +22 -8
  24. package/dist/services/dashboard-question.service.js.map +1 -1
  25. package/dist/services/model-metadata.service.d.ts.map +1 -1
  26. package/dist/services/model-metadata.service.js +101 -6
  27. package/dist/services/model-metadata.service.js.map +1 -1
  28. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts +2 -4
  29. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts.map +1 -1
  30. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js +2 -1
  31. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js.map +1 -1
  32. package/dist/services/question-data-providers/interfaces.d.ts +1 -0
  33. package/dist/services/question-data-providers/interfaces.d.ts.map +1 -0
  34. package/dist/services/question-data-providers/interfaces.js +1 -0
  35. package/dist/services/question-data-providers/interfaces.js.map +1 -0
  36. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts +2 -5
  37. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts.map +1 -1
  38. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js +2 -1
  39. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js.map +1 -1
  40. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts +2 -5
  41. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts.map +1 -1
  42. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js +2 -1
  43. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js.map +1 -1
  44. package/dist/services/queues/database-subscriber.service.d.ts +4 -2
  45. package/dist/services/queues/database-subscriber.service.d.ts.map +1 -1
  46. package/dist/services/queues/database-subscriber.service.js +9 -1
  47. package/dist/services/queues/database-subscriber.service.js.map +1 -1
  48. package/dist/services/queues/publisher-factory.service.d.ts.map +1 -1
  49. package/dist/services/queues/publisher-factory.service.js +4 -6
  50. package/dist/services/queues/publisher-factory.service.js.map +1 -1
  51. package/dist/services/queues/rabbitmq-subscriber.service.d.ts +4 -2
  52. package/dist/services/queues/rabbitmq-subscriber.service.d.ts.map +1 -1
  53. package/dist/services/queues/rabbitmq-subscriber.service.js +9 -1
  54. package/dist/services/queues/rabbitmq-subscriber.service.js.map +1 -1
  55. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.d.ts.map +1 -1
  56. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js +4 -1
  57. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js.map +1 -1
  58. package/dist/transformers/typeorm/local-date-time-transformer.d.ts +4 -4
  59. package/dist/transformers/typeorm/local-date-time-transformer.d.ts.map +1 -1
  60. package/dist/transformers/typeorm/local-date-time-transformer.js +25 -28
  61. package/dist/transformers/typeorm/local-date-time-transformer.js.map +1 -1
  62. package/package.json +1 -1
  63. package/src/entities/chatter-message-details.entity.ts +3 -0
  64. package/src/entities/common.entity.ts +2 -2
  65. package/src/entities/legacy-common.entity.ts +3 -4
  66. package/src/interfaces.ts +7 -1
  67. package/src/seeders/seed-data/solid-core-metadata.json +73 -3
  68. package/src/services/authentication.service.ts +18 -14
  69. package/src/services/chatter-message.service.ts +21 -21
  70. package/src/services/dashboard-question.service.ts +23 -4
  71. package/src/services/model-metadata.service.ts +109 -7
  72. package/src/services/question-data-providers/chartjs-sql-data-provider.service.ts +3 -7
  73. package/src/services/question-data-providers/interfaces.ts +0 -0
  74. package/src/services/question-data-providers/prime-react-datatable-sql-data-provider.service.ts +4 -8
  75. package/src/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.ts +4 -8
  76. package/src/services/queues/database-subscriber.service.ts +12 -1
  77. package/src/services/queues/publisher-factory.service.ts +8 -6
  78. package/src/services/queues/rabbitmq-subscriber.service.ts +12 -1
  79. package/src/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.ts +4 -1
  80. package/src/transformers/typeorm/local-date-time-transformer.ts +41 -33
@@ -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.5",
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
  /**
@@ -5721,7 +5721,7 @@
5721
5721
  "modelUserKey": "listOfValues"
5722
5722
  },
5723
5723
  {
5724
- "displayName": "Import Transactions List Action",
5724
+ "displayName": "Import Transactions",
5725
5725
  "name": "importTransaction-list-action",
5726
5726
  "type": "solid",
5727
5727
  "domain": "",
@@ -5734,7 +5734,7 @@
5734
5734
  "modelUserKey": "importTransaction"
5735
5735
  },
5736
5736
  {
5737
- "displayName": "User Activity History List Action",
5737
+ "displayName": "User Activity History",
5738
5738
  "name": "userActivityHistory-list-action",
5739
5739
  "type": "solid",
5740
5740
  "domain": "",
@@ -5746,6 +5746,19 @@
5746
5746
  "moduleUserKey": "solid-core",
5747
5747
  "modelUserKey": "userActivityHistory"
5748
5748
  },
5749
+ {
5750
+ "displayName": "User Activity History",
5751
+ "name": "userActivityHistory-tree-action",
5752
+ "type": "solid",
5753
+ "domain": "",
5754
+ "context": "",
5755
+ "customComponent": "",
5756
+ "customIsModal": true,
5757
+ "serverEndpoint": "",
5758
+ "viewUserKey": "userActivityHistory-tree-view",
5759
+ "moduleUserKey": "solid-core",
5760
+ "modelUserKey": "userActivityHistory"
5761
+ },
5749
5762
  {
5750
5763
  "displayName": "App Settings",
5751
5764
  "name": "appSettings-action",
@@ -11157,7 +11170,64 @@
11157
11170
  {
11158
11171
  "type": "field",
11159
11172
  "attrs": {
11160
- "name": "userAgent",
11173
+ "name": "createdAt",
11174
+ "sortable": true,
11175
+ "filterable": true
11176
+ }
11177
+ }
11178
+ ]
11179
+ }
11180
+ },
11181
+ {
11182
+ "name": "userActivityHistory-tree-view",
11183
+ "displayName": "User Activity History",
11184
+ "type": "tree",
11185
+ "context": "{}",
11186
+ "moduleUserKey": "solid-core",
11187
+ "modelUserKey": "userActivityHistory",
11188
+ "layout": {
11189
+ "type": "tree",
11190
+ "attrs": {
11191
+ "pagination": true,
11192
+ "pageSizeOptions": [
11193
+ 10,
11194
+ 25,
11195
+ 50
11196
+ ],
11197
+ "enableGlobalSearch": true,
11198
+ "create": true,
11199
+ "edit": true,
11200
+ "delete": true
11201
+ },
11202
+ "children": [
11203
+ {
11204
+ "type": "field",
11205
+ "attrs": {
11206
+ "name": "id",
11207
+ "sortable": true,
11208
+ "filterable": true
11209
+ }
11210
+ },
11211
+ {
11212
+ "type": "field",
11213
+ "attrs": {
11214
+ "name": "user",
11215
+ "sortable": true,
11216
+ "filterable": true
11217
+ }
11218
+ },
11219
+ {
11220
+ "type": "field",
11221
+ "attrs": {
11222
+ "name": "event",
11223
+ "sortable": true,
11224
+ "filterable": true
11225
+ }
11226
+ },
11227
+ {
11228
+ "type": "field",
11229
+ "attrs": {
11230
+ "name": "ipAddress",
11161
11231
  "sortable": true,
11162
11232
  "filterable": true
11163
11233
  }
@@ -464,10 +464,6 @@ export class AuthenticationService {
464
464
 
465
465
  private async notifyUserOnOtpInitiateRegistration(user: User, registrationValidationSource: string) {
466
466
  const companyLogo = await this.getCompanyLogo();
467
- const dummyOtp = this.getDummyOtpForUser(user);
468
-
469
- if (dummyOtp)
470
- return; // Do nothing if dummy otp is configured.
471
467
  if (registrationValidationSource === PasswordlessLoginValidateWhatSources.EMAIL) {
472
468
  const mailService = this.mailServiceFactory.getMailService();
473
469
  mailService.sendEmailUsingTemplate(
@@ -594,13 +590,12 @@ export class AuthenticationService {
594
590
  return true;
595
591
  }
596
592
 
597
- private async otp(user?: User): Promise<otp> {
593
+ private async otp(): Promise<otp> {
598
594
  const now = new Date();
599
595
  const otpExpiry = this.settingService.getConfigValue<SolidCoreSetting>('otpExpiry');
600
- const dummyOtp = this.getDummyOtpForUser(user);
601
596
  now.setMinutes(now.getMinutes() + otpExpiry);
602
597
  return {
603
- token: dummyOtp ? dummyOtp : randomInt(100000, 999999).toString(),
598
+ token: randomInt(100000, 999999).toString(),
604
599
  expiresAt: now,
605
600
  };
606
601
  }
@@ -692,8 +687,11 @@ export class AuthenticationService {
692
687
 
693
688
  const type = this.resolveLoginType(signInDto);
694
689
  const user = await this.findUserForLogin(type, signInDto.identifier);
695
- await this.assignLoginOtp(user, type);
696
- this.notifyUserOnOtpInititateLogin(user, type);
690
+ const dummyOtp = this.getDummyOtpForUser(user);
691
+ if (!dummyOtp) {
692
+ await this.assignLoginOtp(user, type);
693
+ this.notifyUserOnOtpInititateLogin(user, type);
694
+ }
697
695
  return this.buildLoginOtpResponse(user, type);
698
696
  }
699
697
 
@@ -738,7 +736,7 @@ export class AuthenticationService {
738
736
  }
739
737
 
740
738
  private async assignLoginOtp(user: User, type: PasswordlessLoginValidateWhatSources): Promise<void> {
741
- const { token, expiresAt } = await this.otp(user);
739
+ const { token, expiresAt } = await this.otp();
742
740
  if (type === PasswordlessLoginValidateWhatSources.EMAIL) {
743
741
  user.emailVerificationTokenOnLogin = token;
744
742
  user.emailVerificationTokenOnLoginExpiresAt = expiresAt;
@@ -815,6 +813,15 @@ export class AuthenticationService {
815
813
 
816
814
  const user = await this.findUserForLogin(type, identifier, { withRoles: true });
817
815
  this.checkAccountBlocked(user);
816
+ const dummyOtp = this.getDummyOtpForUser(user);
817
+
818
+ if (dummyOtp) {
819
+ if (otp !== dummyOtp) {
820
+ throw new UnauthorizedException(ERROR_MESSAGES.INVALID_OTP);
821
+ }
822
+ return this.buildLoginTokenResponse(user);
823
+ }
824
+
818
825
  try {
819
826
  this.validateLoginOtp(user, otp, type);
820
827
  } catch (e) {
@@ -822,10 +829,7 @@ export class AuthenticationService {
822
829
  throw e;
823
830
  }
824
831
 
825
- // we do not need to clear the otp when dummy otp is configured...
826
- const dummyOtp = this.getDummyOtpForUser(user);
827
- if (!dummyOtp)
828
- this.clearLoginOtp(user, type);
832
+ this.clearLoginOtp(user, type);
829
833
 
830
834
  user.failedLoginAttempts = 0;
831
835
  await this.userActivityHistoryService.logEvent('login', user);
@@ -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