@solidstarters/solid-core 1.2.134 → 1.2.136
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.
- package/dist/controllers/ai-interaction.controller.d.ts +46 -0
- package/dist/controllers/ai-interaction.controller.d.ts.map +1 -0
- package/dist/controllers/ai-interaction.controller.js +204 -0
- package/dist/controllers/ai-interaction.controller.js.map +1 -0
- package/dist/controllers/dashboard-question-sql-dataset-config.controller.d.ts +43 -0
- package/dist/controllers/dashboard-question-sql-dataset-config.controller.d.ts.map +1 -0
- package/dist/controllers/dashboard-question-sql-dataset-config.controller.js +179 -0
- package/dist/controllers/dashboard-question-sql-dataset-config.controller.js.map +1 -0
- package/dist/controllers/dashboard-question.controller.d.ts +45 -0
- package/dist/controllers/dashboard-question.controller.d.ts.map +1 -0
- package/dist/controllers/dashboard-question.controller.js +194 -0
- package/dist/controllers/dashboard-question.controller.js.map +1 -0
- package/dist/controllers/dashboard-variable.controller.d.ts +43 -0
- package/dist/controllers/dashboard-variable.controller.d.ts.map +1 -0
- package/dist/controllers/dashboard-variable.controller.js +179 -0
- package/dist/controllers/dashboard-variable.controller.js.map +1 -0
- package/dist/controllers/dashboard.controller.d.ts +45 -0
- package/dist/controllers/dashboard.controller.d.ts.map +1 -0
- package/dist/controllers/dashboard.controller.js +192 -0
- package/dist/controllers/dashboard.controller.js.map +1 -0
- package/dist/controllers/test.controller.d.ts.map +1 -1
- package/dist/controllers/test.controller.js.map +1 -1
- package/dist/decorators/dashboard-question-data-provider.decorator.d.ts +3 -0
- package/dist/decorators/dashboard-question-data-provider.decorator.d.ts.map +1 -0
- package/dist/decorators/dashboard-question-data-provider.decorator.js +11 -0
- package/dist/decorators/dashboard-question-data-provider.decorator.js.map +1 -0
- package/dist/decorators/dashboard-selection-provider.decorator.d.ts +3 -0
- package/dist/decorators/dashboard-selection-provider.decorator.d.ts.map +1 -0
- package/dist/decorators/dashboard-selection-provider.decorator.js +11 -0
- package/dist/decorators/dashboard-selection-provider.decorator.js.map +1 -0
- package/dist/dtos/create-ai-interaction.dto.d.ts +14 -0
- package/dist/dtos/create-ai-interaction.dto.d.ts.map +1 -0
- package/dist/dtos/create-ai-interaction.dto.js +90 -0
- package/dist/dtos/create-ai-interaction.dto.js.map +1 -0
- package/dist/dtos/create-dashboard-question-sql-dataset-config.dto.d.ts +12 -0
- package/dist/dtos/create-dashboard-question-sql-dataset-config.dto.d.ts.map +1 -0
- package/dist/dtos/create-dashboard-question-sql-dataset-config.dto.js +77 -0
- package/dist/dtos/create-dashboard-question-sql-dataset-config.dto.js.map +1 -0
- package/dist/dtos/create-dashboard-question.dto.d.ts +17 -0
- package/dist/dtos/create-dashboard-question.dto.d.ts.map +1 -0
- package/dist/dtos/create-dashboard-question.dto.js +105 -0
- package/dist/dtos/create-dashboard-question.dto.js.map +1 -0
- package/dist/dtos/create-dashboard-variable.dto.d.ts +18 -0
- package/dist/dtos/create-dashboard-variable.dto.d.ts.map +1 -0
- package/dist/dtos/create-dashboard-variable.dto.js +97 -0
- package/dist/dtos/create-dashboard-variable.dto.js.map +1 -0
- package/dist/dtos/create-dashboard.dto.d.ts +15 -0
- package/dist/dtos/create-dashboard.dto.d.ts.map +1 -0
- package/dist/dtos/create-dashboard.dto.js +90 -0
- package/dist/dtos/create-dashboard.dto.js.map +1 -0
- package/dist/dtos/dashboard-variable-selection-dynamic-query.dto.d.ts +8 -0
- package/dist/dtos/dashboard-variable-selection-dynamic-query.dto.d.ts.map +1 -0
- package/dist/dtos/dashboard-variable-selection-dynamic-query.dto.js +52 -0
- package/dist/dtos/dashboard-variable-selection-dynamic-query.dto.js.map +1 -0
- package/dist/dtos/invoke-ai-prompt.dto.d.ts +4 -0
- package/dist/dtos/invoke-ai-prompt.dto.d.ts.map +1 -0
- package/dist/dtos/invoke-ai-prompt.dto.js +25 -0
- package/dist/dtos/invoke-ai-prompt.dto.js.map +1 -0
- package/dist/dtos/update-ai-interaction.dto.d.ts +15 -0
- package/dist/dtos/update-ai-interaction.dto.d.ts.map +1 -0
- package/dist/dtos/update-ai-interaction.dto.js +96 -0
- package/dist/dtos/update-ai-interaction.dto.js.map +1 -0
- package/dist/dtos/update-dashboard-question-sql-dataset-config.dto.d.ts +13 -0
- package/dist/dtos/update-dashboard-question-sql-dataset-config.dto.d.ts.map +1 -0
- package/dist/dtos/update-dashboard-question-sql-dataset-config.dto.js +86 -0
- package/dist/dtos/update-dashboard-question-sql-dataset-config.dto.js.map +1 -0
- package/dist/dtos/update-dashboard-question.dto.d.ts +18 -0
- package/dist/dtos/update-dashboard-question.dto.d.ts.map +1 -0
- package/dist/dtos/update-dashboard-question.dto.js +112 -0
- package/dist/dtos/update-dashboard-question.dto.js.map +1 -0
- package/dist/dtos/update-dashboard-variable.dto.d.ts +15 -0
- package/dist/dtos/update-dashboard-variable.dto.d.ts.map +1 -0
- package/dist/dtos/update-dashboard-variable.dto.js +95 -0
- package/dist/dtos/update-dashboard-variable.dto.js.map +1 -0
- package/dist/dtos/update-dashboard.dto.d.ts +16 -0
- package/dist/dtos/update-dashboard.dto.d.ts.map +1 -0
- package/dist/dtos/update-dashboard.dto.js +96 -0
- package/dist/dtos/update-dashboard.dto.js.map +1 -0
- package/dist/entities/ai-interaction.entity.d.ts +15 -0
- package/dist/entities/ai-interaction.entity.d.ts.map +1 -0
- package/dist/entities/ai-interaction.entity.js +70 -0
- package/dist/entities/ai-interaction.entity.js.map +1 -0
- package/dist/entities/dashboard-question-sql-dataset-config.entity.d.ts +13 -0
- package/dist/entities/dashboard-question-sql-dataset-config.entity.d.ts.map +1 -0
- package/dist/entities/dashboard-question-sql-dataset-config.entity.js +60 -0
- package/dist/entities/dashboard-question-sql-dataset-config.entity.js.map +1 -0
- package/dist/entities/dashboard-question.entity.d.ts +16 -0
- package/dist/entities/dashboard-question.entity.d.ts.map +1 -0
- package/dist/entities/dashboard-question.entity.js +71 -0
- package/dist/entities/dashboard-question.entity.js.map +1 -0
- package/dist/entities/dashboard-variable.entity.d.ts +15 -0
- package/dist/entities/dashboard-variable.entity.d.ts.map +1 -0
- package/dist/entities/dashboard-variable.entity.js +73 -0
- package/dist/entities/dashboard-variable.entity.js.map +1 -0
- package/dist/entities/dashboard.entity.d.ts +12 -0
- package/dist/entities/dashboard.entity.d.ts.map +1 -0
- package/dist/entities/dashboard.entity.js +50 -0
- package/dist/entities/dashboard.entity.js.map +1 -0
- package/dist/helpers/solid-registry.d.ts +9 -1
- package/dist/helpers/solid-registry.d.ts.map +1 -1
- package/dist/helpers/solid-registry.js +32 -0
- package/dist/helpers/solid-registry.js.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +26 -1
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/jobs/database/trigger-mcp-client-publisher-database.service.d.ts +11 -0
- package/dist/jobs/database/trigger-mcp-client-publisher-database.service.d.ts.map +1 -0
- package/dist/jobs/database/trigger-mcp-client-publisher-database.service.js +39 -0
- package/dist/jobs/database/trigger-mcp-client-publisher-database.service.js.map +1 -0
- package/dist/jobs/database/trigger-mcp-client-queue-options.d.ts +8 -0
- package/dist/jobs/database/trigger-mcp-client-queue-options.d.ts.map +1 -0
- package/dist/jobs/database/trigger-mcp-client-queue-options.js +10 -0
- package/dist/jobs/database/trigger-mcp-client-queue-options.js.map +1 -0
- package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.d.ts +16 -0
- package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.d.ts.map +1 -0
- package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.js +71 -0
- package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.js.map +1 -0
- package/dist/mappers/dashboard-mapper.d.ts +6 -0
- package/dist/mappers/dashboard-mapper.d.ts.map +1 -0
- package/dist/mappers/dashboard-mapper.js +60 -0
- package/dist/mappers/dashboard-mapper.js.map +1 -0
- package/dist/repository/dashboard.repository.d.ts +9 -0
- package/dist/repository/dashboard.repository.d.ts.map +1 -0
- package/dist/repository/dashboard.repository.js +98 -0
- package/dist/repository/dashboard.repository.js.map +1 -0
- package/dist/seeders/module-metadata-seeder.service.d.ts +5 -1
- package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.js +18 -2
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +4172 -2411
- package/dist/services/ai-interaction.service.d.ts +31 -0
- package/dist/services/ai-interaction.service.d.ts.map +1 -0
- package/dist/services/ai-interaction.service.js +182 -0
- package/dist/services/ai-interaction.service.js.map +1 -0
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +8 -6
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/dashboard-question-sql-dataset-config.service.d.ts +22 -0
- package/dist/services/dashboard-question-sql-dataset-config.service.d.ts.map +1 -0
- package/dist/services/dashboard-question-sql-dataset-config.service.js +56 -0
- package/dist/services/dashboard-question-sql-dataset-config.service.js.map +1 -0
- package/dist/services/dashboard-question.service.d.ts +29 -0
- package/dist/services/dashboard-question.service.d.ts.map +1 -0
- package/dist/services/dashboard-question.service.js +117 -0
- package/dist/services/dashboard-question.service.js.map +1 -0
- package/dist/services/dashboard-selection-providers/dashboard-variable-sql-dynamic-provider.service.d.ts +12 -0
- package/dist/services/dashboard-selection-providers/dashboard-variable-sql-dynamic-provider.service.d.ts.map +1 -0
- package/dist/services/dashboard-selection-providers/dashboard-variable-sql-dynamic-provider.service.js +55 -0
- package/dist/services/dashboard-selection-providers/dashboard-variable-sql-dynamic-provider.service.js.map +1 -0
- package/dist/services/dashboard-selection-providers/dashboard-variable-test-dynamic-provider.service.d.ts +11 -0
- package/dist/services/dashboard-selection-providers/dashboard-variable-test-dynamic-provider.service.d.ts.map +1 -0
- package/dist/services/dashboard-selection-providers/dashboard-variable-test-dynamic-provider.service.js +45 -0
- package/dist/services/dashboard-selection-providers/dashboard-variable-test-dynamic-provider.service.js.map +1 -0
- package/dist/services/dashboard-variable.service.d.ts +23 -0
- package/dist/services/dashboard-variable.service.d.ts.map +1 -0
- package/dist/services/dashboard-variable.service.js +57 -0
- package/dist/services/dashboard-variable.service.js.map +1 -0
- package/dist/services/dashboard.service.d.ts +38 -0
- package/dist/services/dashboard.service.d.ts.map +1 -0
- package/dist/services/dashboard.service.js +179 -0
- package/dist/services/dashboard.service.js.map +1 -0
- package/dist/services/field-metadata.service.d.ts.map +1 -1
- package/dist/services/field-metadata.service.js +1 -0
- package/dist/services/field-metadata.service.js.map +1 -1
- package/dist/services/import-transaction.service.d.ts +3 -1
- package/dist/services/import-transaction.service.d.ts.map +1 -1
- package/dist/services/import-transaction.service.js +22 -0
- package/dist/services/import-transaction.service.js.map +1 -1
- package/dist/services/list-of-values.service.d.ts +1 -0
- package/dist/services/list-of-values.service.d.ts.map +1 -1
- package/dist/services/list-of-values.service.js +3 -0
- package/dist/services/list-of-values.service.js.map +1 -1
- package/dist/services/menu-item-metadata.service.d.ts.map +1 -1
- package/dist/services/menu-item-metadata.service.js +1 -1
- package/dist/services/menu-item-metadata.service.js.map +1 -1
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts +36 -0
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts.map +1 -0
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js +89 -0
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js.map +1 -0
- package/dist/services/question-data-providers/helpers.d.ts +7 -0
- package/dist/services/question-data-providers/helpers.d.ts.map +1 -0
- package/dist/services/question-data-providers/helpers.js +25 -0
- package/dist/services/question-data-providers/helpers.js.map +1 -0
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts +17 -0
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts.map +1 -0
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js +70 -0
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js.map +1 -0
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts +19 -0
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts.map +1 -0
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js +92 -0
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js.map +1 -0
- package/dist/services/queues/publisher-factory.service.js +1 -1
- package/dist/services/queues/publisher-factory.service.js.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.service.d.ts.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.service.js +22 -11
- package/dist/services/scheduled-jobs/scheduler.service.js.map +1 -1
- package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.d.ts +11 -0
- package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.d.ts.map +1 -0
- package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js +46 -0
- package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js.map +1 -0
- package/dist/services/selection-providers/list-of-dashboard-variable-providers-selection-provider.service.d.ts +11 -0
- package/dist/services/selection-providers/list-of-dashboard-variable-providers-selection-provider.service.d.ts.map +1 -0
- package/dist/services/selection-providers/list-of-dashboard-variable-providers-selection-provider.service.js +47 -0
- package/dist/services/selection-providers/list-of-dashboard-variable-providers-selection-provider.service.js.map +1 -0
- package/dist/services/solid-introspect.service.d.ts +2 -0
- package/dist/services/solid-introspect.service.d.ts.map +1 -1
- package/dist/services/solid-introspect.service.js +28 -0
- package/dist/services/solid-introspect.service.js.map +1 -1
- package/dist/services/sql-expression-resolver.service.d.ts +9 -0
- package/dist/services/sql-expression-resolver.service.d.ts.map +1 -0
- package/dist/services/sql-expression-resolver.service.js +105 -0
- package/dist/services/sql-expression-resolver.service.js.map +1 -0
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +75 -1
- package/dist/solid-core.module.js.map +1 -1
- package/dist/subscribers/dashboard-question-sql-dataset-config.subscriber.d.ts +16 -0
- package/dist/subscribers/dashboard-question-sql-dataset-config.subscriber.d.ts.map +1 -0
- package/dist/subscribers/dashboard-question-sql-dataset-config.subscriber.js +72 -0
- package/dist/subscribers/dashboard-question-sql-dataset-config.subscriber.js.map +1 -0
- package/dist/subscribers/dashboard-question.subscriber.d.ts +16 -0
- package/dist/subscribers/dashboard-question.subscriber.d.ts.map +1 -0
- package/dist/subscribers/dashboard-question.subscriber.js +72 -0
- package/dist/subscribers/dashboard-question.subscriber.js.map +1 -0
- package/dist/subscribers/dashboard-variable.subscriber.d.ts +16 -0
- package/dist/subscribers/dashboard-variable.subscriber.d.ts.map +1 -0
- package/dist/subscribers/dashboard-variable.subscriber.js +72 -0
- package/dist/subscribers/dashboard-variable.subscriber.js.map +1 -0
- package/dist/subscribers/dashboard.subscriber.d.ts +15 -0
- package/dist/subscribers/dashboard.subscriber.d.ts.map +1 -0
- package/dist/subscribers/dashboard.subscriber.js +56 -0
- package/dist/subscribers/dashboard.subscriber.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/controllers/ai-interaction.controller.ts +104 -0
- package/src/controllers/dashboard-question-sql-dataset-config.controller.ts +93 -0
- package/src/controllers/dashboard-question.controller.ts +104 -0
- package/src/controllers/dashboard-variable.controller.ts +93 -0
- package/src/controllers/dashboard.controller.ts +99 -0
- package/src/controllers/test.controller.ts +1 -2
- package/src/decorators/dashboard-question-data-provider.decorator.ts +7 -0
- package/src/decorators/dashboard-selection-provider.decorator.ts +7 -0
- package/src/dtos/create-ai-interaction.dto.ts +60 -0
- package/src/dtos/create-dashboard-question-sql-dataset-config.dto.ts +42 -0
- package/src/dtos/create-dashboard-question.dto.ts +63 -0
- package/src/dtos/create-dashboard-variable.dto.ts +56 -0
- package/src/dtos/create-dashboard.dto.ts +53 -0
- package/src/dtos/dashboard-variable-selection-dynamic-query.dto.ts +29 -0
- package/src/dtos/invoke-ai-prompt.dto.ts +6 -0
- package/src/dtos/update-ai-interaction.dto.ts +65 -0
- package/src/dtos/update-dashboard-question-sql-dataset-config.dto.ts +49 -0
- package/src/dtos/update-dashboard-question.dto.ts +68 -0
- package/src/dtos/update-dashboard-variable.dto.ts +54 -0
- package/src/dtos/update-dashboard.dto.ts +57 -0
- package/src/entities/ai-interaction.entity.ts +39 -0
- package/src/entities/dashboard-question-sql-dataset-config.entity.ts +25 -0
- package/src/entities/dashboard-question.entity.ts +33 -0
- package/src/entities/dashboard-variable.entity.ts +30 -0
- package/src/entities/dashboard.entity.ts +21 -0
- package/src/helpers/solid-registry.ts +44 -2
- package/src/index.ts +10 -2
- package/src/interfaces.ts +57 -29
- package/src/jobs/database/trigger-mcp-client-publisher-database.service.ts +22 -0
- package/src/jobs/database/trigger-mcp-client-queue-options.ts +9 -0
- package/src/jobs/database/trigger-mcp-client-subscriber-database.service.ts +71 -0
- package/src/mappers/dashboard-mapper.ts +52 -0
- package/src/repository/dashboard.repository.ts +101 -0
- package/src/seeders/module-metadata-seeder.service.ts +21 -1
- package/src/seeders/seed-data/solid-core-metadata.json +4175 -2414
- package/src/services/ai-interaction.service.ts +163 -0
- package/src/services/chatter-message.service.ts +12 -6
- package/src/services/dashboard-question-sql-dataset-config.service.ts +34 -0
- package/src/services/dashboard-question.service.ts +115 -0
- package/src/services/dashboard-selection-providers/dashboard-variable-sql-dynamic-provider.service.ts +56 -0
- package/src/services/dashboard-selection-providers/dashboard-variable-test-dynamic-provider.service.ts +37 -0
- package/src/services/dashboard-variable.service.ts +36 -0
- package/src/services/dashboard.service.ts +147 -0
- package/src/services/field-metadata.service.ts +1 -0
- package/src/services/import-transaction.service.ts +29 -1
- package/src/services/list-of-values.service.ts +5 -0
- package/src/services/menu-item-metadata.service.ts +2 -1
- package/src/services/question-data-providers/chartjs-sql-data-provider.service.ts +125 -0
- package/src/services/question-data-providers/helpers.ts +30 -0
- package/src/services/question-data-providers/prime-react-datatable-sql-data-provider.service.ts +78 -0
- package/src/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.ts +119 -0
- package/src/services/question-data-providers/test.sql +1 -0
- package/src/services/queues/publisher-factory.service.ts +1 -1
- package/src/services/scheduled-jobs/scheduler.service.ts +32 -64
- package/src/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.ts +41 -0
- package/src/services/selection-providers/list-of-dashboard-variable-providers-selection-provider.service.ts +41 -0
- package/src/services/solid-introspect.service.ts +42 -0
- package/src/services/sql-expression-resolver.service.ts +125 -0
- package/src/solid-core.module.ts +77 -2
- package/src/subscribers/dashboard-question-sql-dataset-config.subscriber.ts +61 -0
- package/src/subscribers/dashboard-question.subscriber.ts +62 -0
- package/src/subscribers/dashboard-variable.subscriber.ts +63 -0
- package/src/subscribers/dashboard.subscriber.ts +43 -0
|
@@ -496,7 +496,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
|
|
|
496
496
|
};
|
|
497
497
|
}
|
|
498
498
|
|
|
499
|
-
|
|
499
|
+
async createErrorLogEntry(importTransaction: ImportTransaction, record: Record<string, any>, error: any) {
|
|
500
500
|
const importTransactionRepo = this.entityManager.getRepository(ImportTransactionErrorLog);
|
|
501
501
|
// Create a new ImportTransactionErrorLog entry
|
|
502
502
|
const rowNumber = uuidv4(); // Generate a unique row number or use page.rowNumber if available
|
|
@@ -574,11 +574,39 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
|
|
|
574
574
|
return this.populateDtoForNumber(dtoRecord, fieldMetadata, record, key);
|
|
575
575
|
case SolidFieldType.boolean:
|
|
576
576
|
return this.populateDtoForBoolean(dtoRecord, fieldMetadata, record, key);
|
|
577
|
+
case SolidFieldType.selectionStatic:
|
|
578
|
+
case SolidFieldType.selectionDynamic:
|
|
579
|
+
return this.populateDtoForSelectionValues(dtoRecord, fieldMetadata, record, key);
|
|
577
580
|
default:
|
|
578
581
|
dtoRecord[fieldMetadata.name] = record[key];
|
|
579
582
|
return dtoRecord;
|
|
580
583
|
}
|
|
581
584
|
}
|
|
585
|
+
|
|
586
|
+
private populateDtoForSelectionValues(dtoRecord: Record<string, any>, fieldMetadata: FieldMetadata, record: Record<string, any>, key: string) {
|
|
587
|
+
const rawValue = record[key];
|
|
588
|
+
|
|
589
|
+
if (rawValue == null) {
|
|
590
|
+
dtoRecord[fieldMetadata.name] = null;
|
|
591
|
+
return dtoRecord;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
const isMultipleSelection = fieldMetadata.isMultiSelect;
|
|
595
|
+
|
|
596
|
+
if (isMultipleSelection) {
|
|
597
|
+
const selectionValues = String(rawValue)
|
|
598
|
+
.split(',')
|
|
599
|
+
.map(value => value.trim())
|
|
600
|
+
.filter(value => value !== '');
|
|
601
|
+
|
|
602
|
+
dtoRecord[fieldMetadata.name] = JSON.stringify(selectionValues);
|
|
603
|
+
} else {
|
|
604
|
+
dtoRecord[fieldMetadata.name] = rawValue; // Single select: assign directly
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return dtoRecord;
|
|
608
|
+
}
|
|
609
|
+
|
|
582
610
|
|
|
583
611
|
private populateDtoForBoolean(dtoRecord: Record<string, any>, fieldMetadata: FieldMetadata, record: Record<string, any>, key: string) {
|
|
584
612
|
const booleanValue = Boolean(record[key]);
|
|
@@ -39,6 +39,11 @@ export class ListOfValuesService extends CRUDService<ListOfValues> {
|
|
|
39
39
|
},
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
async findAll(): Promise<ListOfValues[]> {
|
|
44
|
+
return await this.repo.find();
|
|
45
|
+
}
|
|
46
|
+
|
|
42
47
|
async upsert(updateListOfValuesDto: any) {
|
|
43
48
|
// First check if module already exists using name
|
|
44
49
|
const existingListOfValue = await this.repo.findOne({
|
|
@@ -169,7 +169,8 @@ export class MenuItemMetadataService extends CRUDService<MenuItemMetadata> {
|
|
|
169
169
|
// TODO: Here we are assuming that we will always take the user to collection view of a model.
|
|
170
170
|
// We can make provision to take them other views also in the future.
|
|
171
171
|
// path = `/admin/core/${rootItem.module.name}/${rootItem.action.model.singularName}/${rootItem.action.view.name}`;
|
|
172
|
-
path = `/admin/core/${rootItem.module.name}/${dasherize(rootItem.action
|
|
172
|
+
path = `/admin/core/${rootItem.module.name}/${dasherize(rootItem.action?.model?.singularName ?? 'unknown')}/${rootItem.action?.view?.type ?? 'list'}`;
|
|
173
|
+
|
|
173
174
|
}
|
|
174
175
|
}
|
|
175
176
|
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { Injectable, Logger } from "@nestjs/common";
|
|
2
|
+
import { DashboardQuestionDataProvider } from "src/decorators/dashboard-question-data-provider.decorator";
|
|
3
|
+
import { DashboardQuestion } from "src/entities/dashboard-question.entity";
|
|
4
|
+
import { IDashboardQuestionDataProvider } from "src/interfaces";
|
|
5
|
+
import { EntityManager } from "typeorm";
|
|
6
|
+
import { SqlExpressionResolverService } from "../sql-expression-resolver.service";
|
|
7
|
+
import { getKpi, getLabels } from "./helpers";
|
|
8
|
+
|
|
9
|
+
export interface QuestionSqlDataProviderContext {
|
|
10
|
+
// questionSqlDatasetConfig: QuestionSqlDatasetConfig;
|
|
11
|
+
// questionId: number;
|
|
12
|
+
// question: Question;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export enum SqlExpressionOperator {
|
|
16
|
+
EQUALS = '$equals',
|
|
17
|
+
NOT_EQUALS = '$notEquals',
|
|
18
|
+
CONTAINS = '$contains',
|
|
19
|
+
NOT_CONTAINS = '$notContains',
|
|
20
|
+
STARTS_WITH = '$startsWith',
|
|
21
|
+
ENDS_WITH = '$endsWith',
|
|
22
|
+
IN = '$in',
|
|
23
|
+
NOT_IN = '$notIn',
|
|
24
|
+
BETWEEN = '$between',
|
|
25
|
+
LT = '$lt',
|
|
26
|
+
LTE = '$lte',
|
|
27
|
+
GT = '$gt',
|
|
28
|
+
GTE = '$gte'
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface SqlExpression {
|
|
32
|
+
variableName: string; // The name of the variable in the SQL query
|
|
33
|
+
operator: SqlExpressionOperator; // The operator to use for the replacement (e.g., '=', '>', '<', etc.)
|
|
34
|
+
value: string[]; // The value to replace the variable with
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@DashboardQuestionDataProvider()
|
|
38
|
+
@Injectable()
|
|
39
|
+
export class ChartJsSqlDataProvider implements IDashboardQuestionDataProvider<QuestionSqlDataProviderContext, any> {
|
|
40
|
+
private readonly logger = new Logger(ChartJsSqlDataProvider.name);
|
|
41
|
+
|
|
42
|
+
constructor(private readonly entityManager: EntityManager, private readonly sqlExpressionResolver: SqlExpressionResolverService) { }
|
|
43
|
+
|
|
44
|
+
help(): string {
|
|
45
|
+
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.";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
name(): string {
|
|
49
|
+
return "ChartJsSqlDataProvider";
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async getData(question: DashboardQuestion, expressions?: SqlExpression[], context?: QuestionSqlDataProviderContext): Promise<any> {
|
|
53
|
+
// TODO: put some validation to check if the results of each SQL in each dataset returns the same number of rows
|
|
54
|
+
|
|
55
|
+
// This is what we have to return.
|
|
56
|
+
// const data = {
|
|
57
|
+
// labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
|
|
58
|
+
// datasets: [
|
|
59
|
+
// {
|
|
60
|
+
// label: 'Dataset 1',
|
|
61
|
+
// data: labels.map(() => faker.number.int({ min: 0, max: 1000 })),
|
|
62
|
+
// backgroundColor: 'rgba(255, 99, 132, 0.5)',
|
|
63
|
+
// },
|
|
64
|
+
// {
|
|
65
|
+
// label: 'Dataset 2',
|
|
66
|
+
// data: labels.map(() => faker.number.int({ min: 0, max: 1000 })),
|
|
67
|
+
// backgroundColor: 'rgba(53, 162, 235, 0.5)',
|
|
68
|
+
// },
|
|
69
|
+
// {
|
|
70
|
+
// label: 'Dataset 3',
|
|
71
|
+
// data: labels.map(() => faker.number.int({ min: 0, max: 1000 })),
|
|
72
|
+
// backgroundColor: 'rgba(53, 235, 162, 0.5)',
|
|
73
|
+
// },
|
|
74
|
+
// ],
|
|
75
|
+
// };
|
|
76
|
+
|
|
77
|
+
// TODO: Load the set of labels by using a separate field on the question entity.
|
|
78
|
+
|
|
79
|
+
let datasetIdx = 0;
|
|
80
|
+
const datasets = [];
|
|
81
|
+
|
|
82
|
+
const labels: string[] = await getLabels(question, expressions, this.entityManager, this.sqlExpressionResolver);
|
|
83
|
+
const kpi: string = await getKpi(question, expressions, this.entityManager, this.sqlExpressionResolver);
|
|
84
|
+
|
|
85
|
+
// const question = context.question;
|
|
86
|
+
for (const questionSqlDatasetConfig of question.questionSqlDatasetConfigs) {
|
|
87
|
+
|
|
88
|
+
const sql = questionSqlDatasetConfig.sql;
|
|
89
|
+
if (!sql) {
|
|
90
|
+
throw new Error(`SQL dataset ${questionSqlDatasetConfig.datasetName} configuration does not contain a valid SQL query.`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const sqlReplacementResult = this.sqlExpressionResolver.resolveSqlWithExpressions(sql, expressions || []);
|
|
94
|
+
this.logger.debug(`Final Sql query for dataset [${questionSqlDatasetConfig.datasetName}] is query=[${sqlReplacementResult.rawSql}]`);
|
|
95
|
+
this.logger.debug(`Final Sql query for dataset [${questionSqlDatasetConfig.datasetName}] is parameters=[${JSON.stringify(sqlReplacementResult.parameters)}]`);
|
|
96
|
+
const results = await this.entityManager.query(sqlReplacementResult.rawSql, sqlReplacementResult.parameters);
|
|
97
|
+
|
|
98
|
+
// Also for each data set we create the dataset object as is expected by ChartJs.
|
|
99
|
+
const data = [];
|
|
100
|
+
for (let i = 0; i < results.length; i++) {
|
|
101
|
+
const result = results[i];
|
|
102
|
+
data.push(result[questionSqlDatasetConfig.valueColumnName]);
|
|
103
|
+
}
|
|
104
|
+
datasets.push({
|
|
105
|
+
label: questionSqlDatasetConfig.datasetDisplayName,
|
|
106
|
+
data: data,
|
|
107
|
+
...JSON.parse(questionSqlDatasetConfig.options || '{}'),
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
datasetIdx++;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
kpi,
|
|
115
|
+
visualizedAs: question.visualisedAs,
|
|
116
|
+
visualizationData: {
|
|
117
|
+
labels,
|
|
118
|
+
datasets
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { DashboardQuestion } from "src/entities/dashboard-question.entity";
|
|
2
|
+
import { EntityManager } from "typeorm";
|
|
3
|
+
import { SqlExpression } from "./chartjs-sql-data-provider.service";
|
|
4
|
+
import { SqlExpressionResolverService } from "../sql-expression-resolver.service";
|
|
5
|
+
|
|
6
|
+
export async function getLabels(question: DashboardQuestion, expressions: SqlExpression[], entityManager: EntityManager, sqlExpressionResolver: SqlExpressionResolverService): Promise<string[]> {
|
|
7
|
+
const sql = question.labelSql;
|
|
8
|
+
if (!sql) {
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
const sqlReplacementResult = sqlExpressionResolver.resolveSqlWithExpressions(sql, expressions || []);
|
|
12
|
+
|
|
13
|
+
const labelResults = await entityManager.query(sqlReplacementResult.rawSql, sqlReplacementResult.parameters);
|
|
14
|
+
|
|
15
|
+
// Assuming labelResults has a single row with a 'label' field
|
|
16
|
+
// Map the label results to the labels array
|
|
17
|
+
const labels: string[] = labelResults.map((result: { [x: string]: string; }) => result['label']);
|
|
18
|
+
return labels;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function getKpi(question: DashboardQuestion, expressions: SqlExpression[], entityManager: EntityManager, sqlExpressionResolver: SqlExpressionResolverService): Promise<string> {
|
|
22
|
+
const sql = question.kpiSql;
|
|
23
|
+
if (!sql) {
|
|
24
|
+
return "";
|
|
25
|
+
}
|
|
26
|
+
const sqlReplacementResult = sqlExpressionResolver.resolveSqlWithExpressions(sql, expressions || []);
|
|
27
|
+
const result = await entityManager.query(sqlReplacementResult.rawSql, sqlReplacementResult.parameters);
|
|
28
|
+
const kpiResult = result.pop();
|
|
29
|
+
return kpiResult?.kpi || "";
|
|
30
|
+
}
|
package/src/services/question-data-providers/prime-react-datatable-sql-data-provider.service.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Injectable } from "@nestjs/common";
|
|
2
|
+
import { DashboardQuestionDataProvider } from "src/decorators/dashboard-question-data-provider.decorator";
|
|
3
|
+
import { DashboardQuestion } from "src/entities/dashboard-question.entity";
|
|
4
|
+
import { IDashboardQuestionDataProvider } from "src/interfaces";
|
|
5
|
+
import { EntityManager } from "typeorm";
|
|
6
|
+
import { SqlExpressionResolverService } from "../sql-expression-resolver.service";
|
|
7
|
+
import { Logger } from '@nestjs/common';
|
|
8
|
+
import { SqlExpression } from "./chartjs-sql-data-provider.service";
|
|
9
|
+
import { getKpi } from "./helpers";
|
|
10
|
+
|
|
11
|
+
export interface QuestionSqlDataProviderContext {
|
|
12
|
+
// questionSqlDatasetConfig: QuestionSqlDatasetConfig;
|
|
13
|
+
// questionId: number;
|
|
14
|
+
// question: Question;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@DashboardQuestionDataProvider()
|
|
18
|
+
@Injectable()
|
|
19
|
+
export class PrimeReactDatatableSqlDataProvider implements IDashboardQuestionDataProvider<QuestionSqlDataProviderContext, any> {
|
|
20
|
+
private readonly logger = new Logger(PrimeReactDatatableSqlDataProvider.name);
|
|
21
|
+
|
|
22
|
+
constructor(private readonly entityManager: EntityManager, private readonly sqlExpressionResolver: SqlExpressionResolverService) { }
|
|
23
|
+
|
|
24
|
+
help(): string {
|
|
25
|
+
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.";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
name(): string {
|
|
29
|
+
return "PrimeReactDatatableSqlDataProvider";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async getData(question: DashboardQuestion, expressions?: SqlExpression[], context?: QuestionSqlDataProviderContext): Promise<any> {
|
|
33
|
+
// TODO: put some validation to check if the results of each SQL in each dataset returns the same number of rows
|
|
34
|
+
|
|
35
|
+
// Check the expected response for prime react data tables to understand what is going on here...
|
|
36
|
+
|
|
37
|
+
const kpi: string = await getKpi(question, expressions, this.entityManager, this.sqlExpressionResolver);
|
|
38
|
+
// TODO: Load the set of labels by using a separate field on the question entity.
|
|
39
|
+
const labelSql = question.labelSql;
|
|
40
|
+
const labelResults = await this.entityManager.query(labelSql);
|
|
41
|
+
const columns = [];
|
|
42
|
+
for (let i = 0; i < labelResults.length; i++) {
|
|
43
|
+
const labelResult = labelResults[i];
|
|
44
|
+
columns.push({
|
|
45
|
+
field: labelResult['field'],
|
|
46
|
+
header: labelResult['header'],
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Load the chart options as a JSON
|
|
51
|
+
// const chartOptions = JSON.parse(question.barChartLabelOptions || '{}');
|
|
52
|
+
|
|
53
|
+
const values = []
|
|
54
|
+
|
|
55
|
+
// For meter group we can assume that we only have one sql dataset config.
|
|
56
|
+
const questionSqlDatasetConfig = question.questionSqlDatasetConfigs[0];
|
|
57
|
+
|
|
58
|
+
const sql = questionSqlDatasetConfig.sql;
|
|
59
|
+
if (!sql) {
|
|
60
|
+
throw new Error(`SQL dataset ${questionSqlDatasetConfig.datasetName} configuration does not contain a valid SQL query.`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const sqlReplacementResult = this.sqlExpressionResolver.resolveSqlWithExpressions(sql, expressions || []);
|
|
64
|
+
this.logger.debug(`Final Sql query for dataset [${questionSqlDatasetConfig.datasetName}] is query=[${sqlReplacementResult.rawSql}]`);
|
|
65
|
+
this.logger.debug(`Final Sql query for dataset [${questionSqlDatasetConfig.datasetName}] is parameters=[${JSON.stringify(sqlReplacementResult.parameters)}]`);
|
|
66
|
+
const results = await this.entityManager.query(sqlReplacementResult.rawSql, sqlReplacementResult.parameters);
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
kpi,
|
|
70
|
+
visualisedAs: question.visualisedAs,
|
|
71
|
+
visualizationData: {
|
|
72
|
+
columns,
|
|
73
|
+
rows: results,
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
}
|
package/src/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.ts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Injectable } from "@nestjs/common";
|
|
2
|
+
import { DashboardQuestionDataProvider } from "src/decorators/dashboard-question-data-provider.decorator";
|
|
3
|
+
import { DashboardQuestion } from "src/entities/dashboard-question.entity";
|
|
4
|
+
import { IDashboardQuestionDataProvider } from "src/interfaces";
|
|
5
|
+
import { EntityManager } from "typeorm";
|
|
6
|
+
import { SqlExpressionResolverService } from "../sql-expression-resolver.service";
|
|
7
|
+
import { Logger } from '@nestjs/common';
|
|
8
|
+
import { SqlExpression } from "./chartjs-sql-data-provider.service";
|
|
9
|
+
import { getKpi } from "./helpers";
|
|
10
|
+
|
|
11
|
+
export interface QuestionSqlDataProviderContext {
|
|
12
|
+
// questionSqlDatasetConfig: QuestionSqlDatasetConfig;
|
|
13
|
+
// questionId: number;
|
|
14
|
+
// question: Question;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@DashboardQuestionDataProvider()
|
|
18
|
+
@Injectable()
|
|
19
|
+
export class PrimeReactMeterGroupSqlDataProvider implements IDashboardQuestionDataProvider<QuestionSqlDataProviderContext, any> {
|
|
20
|
+
private readonly logger = new Logger(PrimeReactMeterGroupSqlDataProvider.name);
|
|
21
|
+
|
|
22
|
+
constructor(private readonly entityManager: EntityManager, private readonly sqlExpressionResolver: SqlExpressionResolverService) { }
|
|
23
|
+
|
|
24
|
+
help(): string {
|
|
25
|
+
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.";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
name(): string {
|
|
29
|
+
return "PrimeReactMeterGroupSqlDataProvider";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
hslToHex(h: number, s: number, l: number): string {
|
|
33
|
+
l /= 100;
|
|
34
|
+
s /= 100;
|
|
35
|
+
|
|
36
|
+
const k = (n: number) => (n + h / 30) % 12;
|
|
37
|
+
const a = s * Math.min(l, 1 - l);
|
|
38
|
+
const f = (n: number) =>
|
|
39
|
+
Math.round(255 * (l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)))));
|
|
40
|
+
|
|
41
|
+
return `#${f(0).toString(16).padStart(2, '0')}${f(8).toString(16).padStart(2, '0')}${f(4)
|
|
42
|
+
.toString(16)
|
|
43
|
+
.padStart(2, '0')}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
generateDistinctColors(count: number): string[] {
|
|
47
|
+
const colors: string[] = [];
|
|
48
|
+
|
|
49
|
+
const hueStep = 360 / count;
|
|
50
|
+
const saturation = 65; // keep it vibrant
|
|
51
|
+
const lightness = 55; // balanced for both light/dark themes
|
|
52
|
+
|
|
53
|
+
for (let i = 0; i < count; i++) {
|
|
54
|
+
const hue = Math.round(i * hueStep);
|
|
55
|
+
colors.push(this.hslToHex(hue, saturation, lightness));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return colors;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async getData(question: DashboardQuestion, expressions?: SqlExpression[], context?: QuestionSqlDataProviderContext): Promise<any> {
|
|
62
|
+
// TODO: put some validation to check if the results of each SQL in each dataset returns the same number of rows
|
|
63
|
+
|
|
64
|
+
// This is what we have to return.
|
|
65
|
+
// const values = [
|
|
66
|
+
// { label: 'Apps', color: '#34d399', value: 16 },
|
|
67
|
+
// { label: 'Messages', color: '#fbbf24', value: 8 },
|
|
68
|
+
// { label: 'Media', color: '#60a5fa', value: 24 },
|
|
69
|
+
// { label: 'System', color: '#c084fc', value: 10 }
|
|
70
|
+
// ];
|
|
71
|
+
|
|
72
|
+
// TODO: Load the set of labels by using a separate field on the question entity.
|
|
73
|
+
|
|
74
|
+
const kpi: string = await getKpi(question, expressions, this.entityManager, this.sqlExpressionResolver);
|
|
75
|
+
|
|
76
|
+
// Load the chart options as a JSON
|
|
77
|
+
const chartOptions = JSON.parse(question.chartOptions || '{}');
|
|
78
|
+
|
|
79
|
+
const values = []
|
|
80
|
+
|
|
81
|
+
// For meter group we can assume that we only have one sql dataset config.
|
|
82
|
+
const questionSqlDatasetConfig = question.questionSqlDatasetConfigs[0];
|
|
83
|
+
|
|
84
|
+
const sql = questionSqlDatasetConfig.sql;
|
|
85
|
+
if (!sql) {
|
|
86
|
+
throw new Error(`SQL dataset ${questionSqlDatasetConfig.datasetName} configuration does not contain a valid SQL query.`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const sqlReplacementResult = this.sqlExpressionResolver.resolveSqlWithExpressions(sql, expressions || []);
|
|
90
|
+
this.logger.debug(`Final Sql query for dataset [${questionSqlDatasetConfig.datasetName}] is query=[${sqlReplacementResult.rawSql}]`);
|
|
91
|
+
this.logger.debug(`Final Sql query for dataset [${questionSqlDatasetConfig.datasetName}] is parameters=[${JSON.stringify(sqlReplacementResult.parameters)}]`);
|
|
92
|
+
const results = await this.entityManager.query(sqlReplacementResult.rawSql, sqlReplacementResult.parameters);
|
|
93
|
+
|
|
94
|
+
const colors = this.generateDistinctColors(results.length);
|
|
95
|
+
|
|
96
|
+
// Also for each data set we create the dataset object as is expected by ChartJs.
|
|
97
|
+
for (let i = 0; i < results.length; i++) {
|
|
98
|
+
const result = results[i];
|
|
99
|
+
|
|
100
|
+
const colorFromChartOptions = chartOptions?.colors?.[result[questionSqlDatasetConfig.labelColumnName]];
|
|
101
|
+
const color = typeof colorFromChartOptions === 'string' ? colorFromChartOptions : colors[i];
|
|
102
|
+
|
|
103
|
+
values.push({
|
|
104
|
+
label: result[questionSqlDatasetConfig.labelColumnName],
|
|
105
|
+
color: color,
|
|
106
|
+
value: result[questionSqlDatasetConfig.valueColumnName]
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
kpi,
|
|
112
|
+
visualizedAs: question.visualisedAs,
|
|
113
|
+
visualizationData: {
|
|
114
|
+
dataset: values
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
SELECT TO_CHAR(DATE_TRUNC('month', created_at), 'Mon-YYYY') AS label,FROM public.sapphire_clientwhere created_at >= $1 GROUP BY DATE_TRUNC('month', created_at) ORDER BY DATE_TRUNC('month', created_at)
|
|
@@ -16,7 +16,7 @@ export class PublisherFactory<T> {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
async publish(message: QueueMessage<T>, publisherName: string, brokerToUse?: string): Promise<string> {
|
|
19
|
-
let defaultBrokerToUse = brokerToUse || process.env.QUEUES_DEFAULT_BROKER;
|
|
19
|
+
let defaultBrokerToUse = brokerToUse || process.env.QUEUES_DEFAULT_BROKER || "database";
|
|
20
20
|
let resolvedPublisherName = `${publisherName}${classify(defaultBrokerToUse)}`;
|
|
21
21
|
|
|
22
22
|
// Register all ISolidDatabaseModules implementations
|
|
@@ -18,88 +18,54 @@ export class SchedulerServiceImpl implements ISchedulerService {
|
|
|
18
18
|
private readonly solidRegistry: SolidRegistry,
|
|
19
19
|
) { }
|
|
20
20
|
|
|
21
|
-
// @Cron(CronExpression.EVERY_MINUTE)
|
|
22
|
-
// async runScheduledJobs(): Promise<void> {
|
|
23
|
-
// const now = new Date();
|
|
24
|
-
|
|
25
|
-
// const dueScheduledJobs = await this.scheduledJobRepo.find({
|
|
26
|
-
// where: {
|
|
27
|
-
// isActive: true,
|
|
28
|
-
// nextRunAt: LessThanOrEqual(now),
|
|
29
|
-
// },
|
|
30
|
-
// });
|
|
31
|
-
|
|
32
|
-
// for (const dueScheduledJob of dueScheduledJobs) {
|
|
33
|
-
// try {
|
|
34
|
-
// const jobName = dueScheduledJob.job;
|
|
35
|
-
// // @ts-ignore
|
|
36
|
-
// // const jobHandler = this.jobMap[jobName];
|
|
37
|
-
// // const jobHandler = '';
|
|
38
|
-
// const jobHandler: IScheduledJob | undefined = this.solidRegistry.getScheduledJobProviderInstance(jobName)
|
|
39
|
-
|
|
40
|
-
// if (!jobHandler) {
|
|
41
|
-
// this.logger.warn(`No job service found for: ${jobName}`);
|
|
42
|
-
// continue;
|
|
43
|
-
// }
|
|
44
|
-
|
|
45
|
-
// await jobHandler.executeReminder(dueScheduledJob);
|
|
46
|
-
|
|
47
|
-
// // Update nextRunAt and lastRunAt based on frequency
|
|
48
|
-
// dueScheduledJob.lastRunAt = now;
|
|
49
|
-
// dueScheduledJob.nextRunAt = this.computeNextRunAt(dueScheduledJob);
|
|
50
|
-
// await this.scheduledJobRepo.save(dueScheduledJob);
|
|
51
|
-
|
|
52
|
-
// this.logger.log(`Successfully ran job: ${jobName}`);
|
|
53
|
-
// } catch (err) {
|
|
54
|
-
// this.logger.error(`Failed to run job for reminder ${dueScheduledJob.id}`, err.stack);
|
|
55
|
-
// }
|
|
56
|
-
// }
|
|
57
|
-
// }
|
|
58
|
-
|
|
59
|
-
// private computeNextRunAt(reminder: ScheduledJob): Date {
|
|
60
|
-
// const now = new Date();
|
|
61
|
-
// switch (reminder.frequency) {
|
|
62
|
-
// case 'daily':
|
|
63
|
-
// return new Date(now.getTime() + 24 * 60 * 60 * 1000);
|
|
64
|
-
// case 'weekly':
|
|
65
|
-
// return new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
|
|
66
|
-
// case 'monthly':
|
|
67
|
-
// return new Date(now.setMonth(now.getMonth() + 1));
|
|
68
|
-
// default:
|
|
69
|
-
// return new Date(now.getTime() + 24 * 60 * 60 * 1000); // default fallback
|
|
70
|
-
// }
|
|
71
|
-
// }
|
|
72
|
-
|
|
73
21
|
@Cron(CronExpression.EVERY_MINUTE)
|
|
74
22
|
async runScheduledJobs(): Promise<void> {
|
|
75
23
|
const now = new Date();
|
|
24
|
+
|
|
25
|
+
this.logger.log(`[${now.getTime()}]: scheduler service started run...`);
|
|
76
26
|
const dueJobs = await this.scheduledJobRepo.find({
|
|
77
|
-
where:
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
27
|
+
where: [
|
|
28
|
+
{
|
|
29
|
+
isActive: true,
|
|
30
|
+
nextRunAt: LessThanOrEqual(now),
|
|
31
|
+
},
|
|
32
|
+
// Newly created jobs are also picked for examination
|
|
33
|
+
{
|
|
34
|
+
isActive: true,
|
|
35
|
+
nextRunAt: null,
|
|
36
|
+
},
|
|
37
|
+
],
|
|
81
38
|
});
|
|
82
39
|
|
|
40
|
+
this.logger.log(`[${now.getTime()}]: scheduler service identified ${dueJobs.length} jobs to run...`);
|
|
41
|
+
|
|
83
42
|
for (const job of dueJobs) {
|
|
43
|
+
this.logger.log(`[${now.getTime()}]: scheduler service attempting to run job ${job.job}`);
|
|
84
44
|
try {
|
|
85
45
|
if (!this.shouldRunNow(job, now)) {
|
|
46
|
+
this.logger.log(`[${now.getTime()}]: scheduler service skipping job ${job.job}`);
|
|
86
47
|
continue;
|
|
87
48
|
}
|
|
88
49
|
|
|
89
50
|
const handler = this.solidRegistry.getScheduledJobProviderInstance(job.job);
|
|
90
51
|
if (!handler) {
|
|
91
|
-
this.logger.warn(`
|
|
52
|
+
this.logger.warn(`[${now.getTime()}]: scheduler service skipping because job handler not found: ${job.job}`);
|
|
92
53
|
continue;
|
|
93
54
|
}
|
|
94
55
|
|
|
56
|
+
this.logger.log(`[${now.getTime()}]: scheduler service about to run job ${job.job}`);
|
|
95
57
|
await handler.executeReminder(job);
|
|
58
|
+
this.logger.log(`[${now.getTime()}]: scheduler service finished running job ${job.job}`);
|
|
59
|
+
|
|
96
60
|
job.isActive = true;
|
|
97
61
|
job.lastRunAt = now;
|
|
98
62
|
job.nextRunAt = this.computeNextRunAt(job, now);
|
|
63
|
+
this.logger.log(`[${now.getTime()}]: scheduler service coomputed next run for ${job.job} as ${job.nextRunAt}`);
|
|
64
|
+
|
|
99
65
|
await this.scheduledJobRepo.save(job);
|
|
100
|
-
this.logger.log(`
|
|
66
|
+
this.logger.log(`[${now.getTime()}]: scheduler service finished running job: ${job.job}`);
|
|
101
67
|
} catch (err) {
|
|
102
|
-
this.logger.error(`
|
|
68
|
+
this.logger.error(`[${now.getTime()}]: scheduler service failed to run job ${job.job}`, err.stack);
|
|
103
69
|
}
|
|
104
70
|
}
|
|
105
71
|
}
|
|
@@ -143,8 +109,10 @@ export class SchedulerServiceImpl implements ISchedulerService {
|
|
|
143
109
|
const base = new Date(from);
|
|
144
110
|
|
|
145
111
|
switch (job.frequency.toLowerCase()) {
|
|
146
|
-
case 'once':
|
|
147
|
-
|
|
112
|
+
// case 'once':
|
|
113
|
+
// return null; // don't reschedule
|
|
114
|
+
case 'every minute':
|
|
115
|
+
return new Date(base.getTime() + 1 * 60 * 1000);
|
|
148
116
|
case 'hourly':
|
|
149
117
|
return new Date(base.getTime() + 60 * 60 * 1000);
|
|
150
118
|
case 'daily':
|
|
@@ -155,9 +123,9 @@ export class SchedulerServiceImpl implements ISchedulerService {
|
|
|
155
123
|
const next = new Date(base);
|
|
156
124
|
next.setMonth(base.getMonth() + 1);
|
|
157
125
|
return next;
|
|
158
|
-
case 'custom':
|
|
159
|
-
|
|
160
|
-
|
|
126
|
+
// case 'custom':
|
|
127
|
+
// // Optional: let job handler decide via metadata or registry
|
|
128
|
+
// return new Date(base.getTime() + 24 * 60 * 60 * 1000);
|
|
161
129
|
default:
|
|
162
130
|
return new Date(base.getTime() + 24 * 60 * 60 * 1000);
|
|
163
131
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Injectable } from "@nestjs/common";
|
|
2
|
+
import { SelectionProvider } from "src/decorators/selection-provider.decorator";
|
|
3
|
+
import { SolidRegistry } from "src/helpers/solid-registry";
|
|
4
|
+
import { IDashboardQuestionDataProvider, IDashboardVariableSelectionProvider, ISelectionProvider, ISelectionProviderContext, ISelectionProviderValues } from "../../interfaces";
|
|
5
|
+
import { SQL_DYNAMIC_PROVIDER_NAME } from "../dashboard.service";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@SelectionProvider()
|
|
9
|
+
@Injectable()
|
|
10
|
+
export class ListOfDashboardQuestionProvidersSelectionProvider implements ISelectionProvider<ISelectionProviderContext> {
|
|
11
|
+
|
|
12
|
+
constructor(
|
|
13
|
+
private readonly solidRegistry: SolidRegistry,
|
|
14
|
+
) {
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
help(): string {
|
|
18
|
+
return "# Allows one to dynamically fetch all the dashboard providers that are registered in the system. ";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
name(): string {
|
|
22
|
+
return 'ListOfDashboardQuestionProvidersSelectionProvider';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async value(optionValue: string, ctxt: ISelectionProviderContext): Promise<ISelectionProviderValues | any> {
|
|
26
|
+
const dashboardSelectionProvider: IDashboardQuestionDataProvider<any, any> | undefined = this.solidRegistry.getDashboardQuestionDataProviderInstance(optionValue);
|
|
27
|
+
if (!dashboardSelectionProvider) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return { label: dashboardSelectionProvider.name(), value: dashboardSelectionProvider.name() };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async values(query: string, ctxt: ISelectionProviderContext): Promise<readonly ISelectionProviderValues[]> {
|
|
35
|
+
const dashboardSelectionProviders = this.solidRegistry.getDashboardQuestionDataProviders()
|
|
36
|
+
//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)
|
|
37
|
+
return dashboardSelectionProviders.map(i => {
|
|
38
|
+
return { label: i.name, value: i.name };
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Injectable } from "@nestjs/common";
|
|
2
|
+
import { SelectionProvider } from "src/decorators/selection-provider.decorator";
|
|
3
|
+
import { SolidRegistry } from "src/helpers/solid-registry";
|
|
4
|
+
import { IDashboardVariableSelectionProvider, ISelectionProvider, ISelectionProviderContext, ISelectionProviderValues } from "../../interfaces";
|
|
5
|
+
import { SQL_DYNAMIC_PROVIDER_NAME } from "../dashboard.service";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@SelectionProvider()
|
|
9
|
+
@Injectable()
|
|
10
|
+
export class ListOfDashboardVariableProvidersSelectionProvider implements ISelectionProvider<ISelectionProviderContext> {
|
|
11
|
+
|
|
12
|
+
constructor(
|
|
13
|
+
private readonly solidRegistry: SolidRegistry,
|
|
14
|
+
) {
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
help(): string {
|
|
18
|
+
return "# Allows one to dynamically fetch all the dashboard providers that are registered in the system. ";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
name(): string {
|
|
22
|
+
return 'ListOfDashboardVariableProvidersSelectionProvider';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async value(optionValue: string, ctxt: ISelectionProviderContext): Promise<ISelectionProviderValues | any> {
|
|
26
|
+
const dashboardSelectionProvider: IDashboardVariableSelectionProvider<ISelectionProviderContext> | undefined = this.solidRegistry.getDashboardVariableSelectionProviderInstance(optionValue);
|
|
27
|
+
if (!dashboardSelectionProvider) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return { label: dashboardSelectionProvider.name(), value: dashboardSelectionProvider.name() };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async values(query: string, ctxt: ISelectionProviderContext): Promise<readonly ISelectionProviderValues[]> {
|
|
35
|
+
const dashboardSelectionProviders = this.solidRegistry.getDashboardVariableSelectionProviders()
|
|
36
|
+
//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)
|
|
37
|
+
return dashboardSelectionProviders.filter(i => (i.name !== SQL_DYNAMIC_PROVIDER_NAME)).map(i => {
|
|
38
|
+
return { label: i.name, value: i.name };
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|