@solidxai/core 0.1.6-beta.2 → 0.1.6-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controllers/dashboard-layout.controller.d.ts +47 -0
- package/dist/controllers/dashboard-layout.controller.d.ts.map +1 -0
- package/dist/controllers/dashboard-layout.controller.js +204 -0
- package/dist/controllers/dashboard-layout.controller.js.map +1 -0
- package/dist/controllers/scheduled-job.controller.d.ts +1 -0
- package/dist/controllers/scheduled-job.controller.d.ts.map +1 -1
- package/dist/controllers/scheduled-job.controller.js +12 -0
- package/dist/controllers/scheduled-job.controller.js.map +1 -1
- package/dist/dtos/create-dashboard-layout.dto.d.ts +8 -0
- package/dist/dtos/create-dashboard-layout.dto.d.ts.map +1 -0
- package/dist/dtos/create-dashboard-layout.dto.js +53 -0
- package/dist/dtos/create-dashboard-layout.dto.js.map +1 -0
- package/dist/dtos/create-dashboard-variable.dto.d.ts +1 -0
- package/dist/dtos/create-dashboard-variable.dto.d.ts.map +1 -1
- package/dist/dtos/create-dashboard-variable.dto.js +7 -1
- package/dist/dtos/create-dashboard-variable.dto.js.map +1 -1
- package/dist/dtos/update-dashboard-layout.dto.d.ts +8 -0
- package/dist/dtos/update-dashboard-layout.dto.d.ts.map +1 -0
- package/dist/dtos/update-dashboard-layout.dto.js +53 -0
- package/dist/dtos/update-dashboard-layout.dto.js.map +1 -0
- package/dist/dtos/update-dashboard-variable.dto.d.ts +1 -0
- package/dist/dtos/update-dashboard-variable.dto.d.ts.map +1 -1
- package/dist/dtos/update-dashboard-variable.dto.js +7 -1
- package/dist/dtos/update-dashboard-variable.dto.js.map +1 -1
- package/dist/entities/action-metadata.entity.d.ts.map +1 -1
- package/dist/entities/action-metadata.entity.js.map +1 -1
- package/dist/entities/ai-interaction.entity.d.ts.map +1 -1
- package/dist/entities/ai-interaction.entity.js +5 -4
- package/dist/entities/ai-interaction.entity.js.map +1 -1
- package/dist/entities/chatter-message-details.entity.d.ts +1 -0
- package/dist/entities/chatter-message-details.entity.d.ts.map +1 -1
- package/dist/entities/chatter-message-details.entity.js +9 -4
- package/dist/entities/chatter-message-details.entity.js.map +1 -1
- package/dist/entities/chatter-message.entity.d.ts.map +1 -1
- package/dist/entities/chatter-message.entity.js +4 -3
- package/dist/entities/chatter-message.entity.js.map +1 -1
- package/dist/entities/common.entity.js +1 -1
- package/dist/entities/common.entity.js.map +1 -1
- package/dist/entities/dashboard-layout.entity.d.ts +9 -0
- package/dist/entities/dashboard-layout.entity.d.ts.map +1 -0
- package/dist/entities/dashboard-layout.entity.js +41 -0
- package/dist/entities/dashboard-layout.entity.js.map +1 -0
- package/dist/entities/dashboard-question-sql-dataset-config.entity.d.ts.map +1 -1
- package/dist/entities/dashboard-question-sql-dataset-config.entity.js +5 -4
- package/dist/entities/dashboard-question-sql-dataset-config.entity.js.map +1 -1
- package/dist/entities/dashboard-question.entity.d.ts.map +1 -1
- package/dist/entities/dashboard-question.entity.js +5 -4
- package/dist/entities/dashboard-question.entity.js.map +1 -1
- package/dist/entities/dashboard-variable.entity.d.ts +1 -0
- package/dist/entities/dashboard-variable.entity.d.ts.map +1 -1
- package/dist/entities/dashboard-variable.entity.js +10 -4
- package/dist/entities/dashboard-variable.entity.js.map +1 -1
- package/dist/entities/dashboard.entity.d.ts +2 -0
- package/dist/entities/dashboard.entity.d.ts.map +1 -1
- package/dist/entities/dashboard.entity.js +9 -3
- package/dist/entities/dashboard.entity.js.map +1 -1
- package/dist/entities/email-attachment.entity.d.ts.map +1 -1
- package/dist/entities/email-attachment.entity.js +2 -1
- package/dist/entities/email-attachment.entity.js.map +1 -1
- package/dist/entities/email-template.entity.js +1 -1
- package/dist/entities/email-template.entity.js.map +1 -1
- package/dist/entities/export-transaction.entity.d.ts.map +1 -1
- package/dist/entities/export-transaction.entity.js +2 -1
- package/dist/entities/export-transaction.entity.js.map +1 -1
- package/dist/entities/field-metadata.entity.js +2 -2
- package/dist/entities/field-metadata.entity.js.map +1 -1
- package/dist/entities/import-transaction-error-log.entity.d.ts.map +1 -1
- package/dist/entities/import-transaction-error-log.entity.js +3 -2
- package/dist/entities/import-transaction-error-log.entity.js.map +1 -1
- package/dist/entities/import-transaction.entity.d.ts.map +1 -1
- package/dist/entities/import-transaction.entity.js +2 -1
- package/dist/entities/import-transaction.entity.js.map +1 -1
- package/dist/entities/legacy-common.entity.d.ts.map +1 -1
- package/dist/entities/legacy-common.entity.js +1 -1
- package/dist/entities/legacy-common.entity.js.map +1 -1
- package/dist/entities/mq-message.entity.d.ts.map +1 -1
- package/dist/entities/mq-message.entity.js +5 -3
- package/dist/entities/mq-message.entity.js.map +1 -1
- package/dist/entities/saved-filters.entity.d.ts.map +1 -1
- package/dist/entities/saved-filters.entity.js +3 -2
- package/dist/entities/saved-filters.entity.js.map +1 -1
- package/dist/entities/security-rule.entity.d.ts.map +1 -1
- package/dist/entities/security-rule.entity.js +2 -1
- package/dist/entities/security-rule.entity.js.map +1 -1
- package/dist/entities/sms-template.entity.js +1 -1
- package/dist/entities/sms-template.entity.js.map +1 -1
- package/dist/entities/user-view-metadata.entity.d.ts.map +1 -1
- package/dist/entities/user-view-metadata.entity.js +2 -1
- package/dist/entities/user-view-metadata.entity.js.map +1 -1
- package/dist/entities/user.entity.d.ts.map +1 -1
- package/dist/entities/user.entity.js +2 -0
- package/dist/entities/user.entity.js.map +1 -1
- package/dist/entities/view-metadata.entity.d.ts.map +1 -1
- package/dist/entities/view-metadata.entity.js.map +1 -1
- package/dist/helpers/bootstrap.helper.d.ts +14 -0
- package/dist/helpers/bootstrap.helper.d.ts.map +1 -0
- package/dist/helpers/bootstrap.helper.js +132 -0
- package/dist/helpers/bootstrap.helper.js.map +1 -0
- package/dist/helpers/cache.helper.d.ts +2 -0
- package/dist/helpers/cache.helper.d.ts.map +1 -0
- package/dist/helpers/cache.helper.js +8 -0
- package/dist/helpers/cache.helper.js.map +1 -0
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts +1 -0
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js +8 -9
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js.map +1 -1
- package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.d.ts +2 -2
- package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.js +8 -5
- package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.js.map +1 -1
- package/dist/helpers/solid-registry.d.ts.map +1 -1
- package/dist/helpers/solid-registry.js.map +1 -1
- package/dist/helpers/typeorm-db-helper.d.ts.map +1 -1
- package/dist/helpers/typeorm-db-helper.js +21 -0
- package/dist/helpers/typeorm-db-helper.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +5 -1
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/jobs/computed-field-evaluation-queue-options.d.ts +1 -0
- package/dist/jobs/computed-field-evaluation-queue-options.d.ts.map +1 -1
- package/dist/jobs/computed-field-evaluation-queue-options.js +1 -0
- package/dist/jobs/computed-field-evaluation-queue-options.js.map +1 -1
- package/dist/repository/dashboard-layout.repository.d.ts +12 -0
- package/dist/repository/dashboard-layout.repository.d.ts.map +1 -0
- package/dist/repository/dashboard-layout.repository.js +34 -0
- package/dist/repository/dashboard-layout.repository.js.map +1 -0
- package/dist/seeders/module-metadata-seeder.service.js +4 -4
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +445 -35
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +44 -21
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/chatter-message.service.d.ts +0 -1
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +22 -19
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.d.ts +7 -3
- package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.d.ts.map +1 -1
- package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.js +61 -22
- package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.js.map +1 -1
- package/dist/services/crud.service.js +1 -1
- package/dist/services/crud.service.js.map +1 -1
- package/dist/services/dashboard-layout.service.d.ts +20 -0
- package/dist/services/dashboard-layout.service.d.ts.map +1 -0
- package/dist/services/dashboard-layout.service.js +120 -0
- package/dist/services/dashboard-layout.service.js.map +1 -0
- package/dist/services/dashboard-question.service.d.ts +4 -0
- package/dist/services/dashboard-question.service.d.ts.map +1 -1
- package/dist/services/dashboard-question.service.js +22 -8
- package/dist/services/dashboard-question.service.js.map +1 -1
- package/dist/services/dashboard.service.d.ts +2 -0
- package/dist/services/dashboard.service.d.ts.map +1 -1
- package/dist/services/dashboard.service.js +4 -0
- package/dist/services/dashboard.service.js.map +1 -1
- package/dist/services/model-metadata.service.d.ts +6 -1
- package/dist/services/model-metadata.service.d.ts.map +1 -1
- package/dist/services/model-metadata.service.js +151 -8
- package/dist/services/model-metadata.service.js.map +1 -1
- package/dist/services/permission-metadata.service.d.ts +5 -1
- package/dist/services/permission-metadata.service.d.ts.map +1 -1
- package/dist/services/permission-metadata.service.js +66 -20
- package/dist/services/permission-metadata.service.js.map +1 -1
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts +2 -4
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts.map +1 -1
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js +2 -1
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js.map +1 -1
- package/dist/services/question-data-providers/interfaces.d.ts +1 -0
- package/dist/services/question-data-providers/interfaces.d.ts.map +1 -0
- package/dist/services/question-data-providers/interfaces.js +1 -0
- package/dist/services/question-data-providers/interfaces.js.map +1 -0
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts +2 -5
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts.map +1 -1
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js +2 -1
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js.map +1 -1
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts +2 -5
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts.map +1 -1
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js +2 -1
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js.map +1 -1
- package/dist/services/queues/database-subscriber.service.d.ts +4 -2
- package/dist/services/queues/database-subscriber.service.d.ts.map +1 -1
- package/dist/services/queues/database-subscriber.service.js +15 -2
- package/dist/services/queues/database-subscriber.service.js.map +1 -1
- package/dist/services/queues/publisher-factory.service.d.ts.map +1 -1
- package/dist/services/queues/publisher-factory.service.js +4 -6
- package/dist/services/queues/publisher-factory.service.js.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.d.ts +8 -3
- package/dist/services/queues/rabbitmq-subscriber.service.d.ts.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.js +78 -6
- package/dist/services/queues/rabbitmq-subscriber.service.js.map +1 -1
- package/dist/services/scheduled-job.service.d.ts +6 -1
- package/dist/services/scheduled-job.service.d.ts.map +1 -1
- package/dist/services/scheduled-job.service.js +26 -2
- package/dist/services/scheduled-job.service.js.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.interface.d.ts +2 -0
- package/dist/services/scheduled-jobs/scheduler.interface.d.ts.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.interface.js.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.service.d.ts +6 -2
- package/dist/services/scheduled-jobs/scheduler.service.d.ts.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.service.js +75 -17
- 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.map +1 -1
- package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js +4 -1
- package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js.map +1 -1
- package/dist/services/solid-ts-morph.service.d.ts +9 -0
- package/dist/services/solid-ts-morph.service.d.ts.map +1 -1
- package/dist/services/solid-ts-morph.service.js +76 -0
- package/dist/services/solid-ts-morph.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +8 -0
- package/dist/solid-core.module.js.map +1 -1
- package/dist/subscribers/computed-entity-field.subscriber.js +3 -1
- package/dist/subscribers/computed-entity-field.subscriber.js.map +1 -1
- package/dist/transformers/typeorm/local-date-time-transformer.d.ts +4 -4
- package/dist/transformers/typeorm/local-date-time-transformer.d.ts.map +1 -1
- package/dist/transformers/typeorm/local-date-time-transformer.js +25 -28
- package/dist/transformers/typeorm/local-date-time-transformer.js.map +1 -1
- package/dist-tests/api/authenticate.spec.js +119 -0
- package/dist-tests/api/authenticate.spec.js.map +1 -0
- package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +97 -0
- package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +1 -0
- package/dist-tests/api/ping.spec.js +21 -0
- package/dist-tests/api/ping.spec.js.map +1 -0
- package/dist-tests/helpers/auth.js +41 -0
- package/dist-tests/helpers/auth.js.map +1 -0
- package/dist-tests/helpers/env.js +11 -0
- package/dist-tests/helpers/env.js.map +1 -0
- package/package.json +3 -1
- package/sql/default/mariadb/proc_CleanupModelMetadata.sql +153 -0
- package/sql/default/mariadb/proc_CleanupModuleMetadata.sql +56 -0
- package/sql/default/mysql/proc_CleanupModelMetadata.sql +153 -0
- package/sql/default/mysql/proc_CleanupModuleMetadata.sql +56 -0
- package/src/controllers/dashboard-layout.controller.ts +106 -0
- package/src/controllers/scheduled-job.controller.ts +6 -0
- package/src/dtos/create-dashboard-layout.dto.ts +31 -0
- package/src/dtos/create-dashboard-variable.dto.ts +4 -0
- package/src/dtos/update-dashboard-layout.dto.ts +30 -0
- package/src/dtos/update-dashboard-variable.dto.ts +5 -1
- package/src/entities/action-metadata.entity.ts +3 -2
- package/src/entities/ai-interaction.entity.ts +5 -4
- package/src/entities/chatter-message-details.entity.ts +7 -3
- package/src/entities/chatter-message.entity.ts +4 -3
- package/src/entities/common.entity.ts +2 -2
- package/src/entities/dashboard-layout.entity.ts +18 -0
- package/src/entities/dashboard-question-sql-dataset-config.entity.ts +5 -4
- package/src/entities/dashboard-question.entity.ts +5 -4
- package/src/entities/dashboard-variable.entity.ts +9 -4
- package/src/entities/dashboard.entity.ts +7 -2
- package/src/entities/email-attachment.entity.ts +2 -1
- package/src/entities/email-template.entity.ts +1 -1
- package/src/entities/export-transaction.entity.ts +2 -1
- package/src/entities/field-metadata.entity.ts +2 -2
- package/src/entities/import-transaction-error-log.entity.ts +3 -2
- package/src/entities/import-transaction.entity.ts +2 -1
- package/src/entities/legacy-common.entity.ts +3 -4
- package/src/entities/mq-message.entity.ts +5 -3
- package/src/entities/saved-filters.entity.ts +3 -2
- package/src/entities/security-rule.entity.ts +2 -1
- package/src/entities/sms-template.entity.ts +1 -1
- package/src/entities/user-view-metadata.entity.ts +2 -1
- package/src/entities/user.entity.ts +37 -2
- package/src/entities/view-metadata.entity.ts +3 -0
- package/src/helpers/bootstrap.helper.ts +222 -0
- package/src/helpers/cache.helper.ts +5 -0
- package/src/helpers/field-crud-managers/MediaFieldCrudManager.ts +9 -9
- package/src/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.ts +9 -6
- package/src/helpers/solid-registry.ts +1 -5
- package/src/helpers/typeorm-db-helper.ts +26 -0
- package/src/index.ts +3 -0
- package/src/interfaces.ts +9 -1
- package/src/jobs/computed-field-evaluation-queue-options.ts +1 -0
- package/src/repository/dashboard-layout.repository.ts +17 -0
- package/src/seeders/module-metadata-seeder.service.ts +5 -5
- package/src/seeders/seed-data/solid-core-metadata.json +446 -36
- package/src/services/authentication.service.ts +46 -24
- package/src/services/chatter-message.service.ts +21 -21
- package/src/services/computed-fields/entity/sequence-num-computed-field-provider.ts +79 -40
- package/src/services/crud.service.ts +1 -1
- package/src/services/dashboard-layout.service.ts +111 -0
- package/src/services/dashboard-question.service.ts +23 -4
- package/src/services/dashboard.service.ts +7 -0
- package/src/services/model-metadata.service.ts +173 -50
- package/src/services/permission-metadata.service.ts +73 -20
- package/src/services/question-data-providers/chartjs-sql-data-provider.service.ts +3 -7
- package/src/services/question-data-providers/interfaces.ts +0 -0
- package/src/services/question-data-providers/prime-react-datatable-sql-data-provider.service.ts +4 -8
- package/src/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.ts +4 -8
- package/src/services/queues/database-subscriber.service.ts +19 -2
- package/src/services/queues/publisher-factory.service.ts +8 -6
- package/src/services/queues/rabbitmq-subscriber.service.ts +123 -6
- package/src/services/scheduled-job.service.ts +31 -2
- package/src/services/scheduled-jobs/scheduler.interface.ts +4 -1
- package/src/services/scheduled-jobs/scheduler.service.ts +82 -20
- package/src/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.ts +4 -1
- package/src/services/solid-ts-morph.service.ts +98 -0
- package/src/solid-core.module.ts +13 -0
- package/src/subscribers/computed-entity-field.subscriber.ts +3 -3
- package/src/transformers/typeorm/local-date-time-transformer.ts +41 -33
- package/.claude/settings.local.json +0 -15
- package/src/services/1.js +0 -6
|
@@ -464,10 +464,6 @@ export class AuthenticationService {
|
|
|
464
464
|
|
|
465
465
|
private async notifyUserOnOtpInitiateRegistration(user: User, registrationValidationSource: string) {
|
|
466
466
|
const companyLogo = await this.getCompanyLogo();
|
|
467
|
-
const dummyOtp = this.getDummyOtpForUser(user);
|
|
468
|
-
|
|
469
|
-
if (dummyOtp)
|
|
470
|
-
return; // Do nothing if dummy otp is configured.
|
|
471
467
|
if (registrationValidationSource === PasswordlessLoginValidateWhatSources.EMAIL) {
|
|
472
468
|
const mailService = this.mailServiceFactory.getMailService();
|
|
473
469
|
mailService.sendEmailUsingTemplate(
|
|
@@ -594,13 +590,12 @@ export class AuthenticationService {
|
|
|
594
590
|
return true;
|
|
595
591
|
}
|
|
596
592
|
|
|
597
|
-
private async otp(
|
|
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:
|
|
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
|
-
|
|
696
|
-
|
|
690
|
+
const dummyOtp = this.getDummyOtpForUser(user);
|
|
691
|
+
if (!dummyOtp) {
|
|
692
|
+
await this.assignLoginOtp(user, type);
|
|
693
|
+
this.notifyUserOnOtpInititateLogin(user, type);
|
|
694
|
+
}
|
|
697
695
|
return this.buildLoginOtpResponse(user, type);
|
|
698
696
|
}
|
|
699
697
|
|
|
@@ -738,15 +736,22 @@ export class AuthenticationService {
|
|
|
738
736
|
}
|
|
739
737
|
|
|
740
738
|
private async assignLoginOtp(user: User, type: PasswordlessLoginValidateWhatSources): Promise<void> {
|
|
741
|
-
const { token, expiresAt } = await this.otp(
|
|
739
|
+
const { token, expiresAt } = await this.otp();
|
|
742
740
|
if (type === PasswordlessLoginValidateWhatSources.EMAIL) {
|
|
743
741
|
user.emailVerificationTokenOnLogin = token;
|
|
744
742
|
user.emailVerificationTokenOnLoginExpiresAt = expiresAt;
|
|
743
|
+
await this.userRepository.update(user.id, {
|
|
744
|
+
emailVerificationTokenOnLogin: token,
|
|
745
|
+
emailVerificationTokenOnLoginExpiresAt: expiresAt,
|
|
746
|
+
});
|
|
745
747
|
} else {
|
|
746
748
|
user.mobileVerificationTokenOnLogin = token;
|
|
747
749
|
user.mobileVerificationTokenOnLoginExpiresAt = expiresAt;
|
|
750
|
+
await this.userRepository.update(user.id, {
|
|
751
|
+
mobileVerificationTokenOnLogin: token,
|
|
752
|
+
mobileVerificationTokenOnLoginExpiresAt: expiresAt,
|
|
753
|
+
});
|
|
748
754
|
}
|
|
749
|
-
await this.userRepository.save(user);
|
|
750
755
|
}
|
|
751
756
|
|
|
752
757
|
private buildLoginOtpResponse(user: User, type: PasswordlessLoginValidateWhatSources) {
|
|
@@ -815,6 +820,15 @@ export class AuthenticationService {
|
|
|
815
820
|
|
|
816
821
|
const user = await this.findUserForLogin(type, identifier, { withRoles: true });
|
|
817
822
|
this.checkAccountBlocked(user);
|
|
823
|
+
const dummyOtp = this.getDummyOtpForUser(user);
|
|
824
|
+
|
|
825
|
+
if (dummyOtp) {
|
|
826
|
+
if (otp !== dummyOtp) {
|
|
827
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INVALID_OTP);
|
|
828
|
+
}
|
|
829
|
+
return this.buildLoginTokenResponse(user);
|
|
830
|
+
}
|
|
831
|
+
|
|
818
832
|
try {
|
|
819
833
|
this.validateLoginOtp(user, otp, type);
|
|
820
834
|
} catch (e) {
|
|
@@ -822,14 +836,9 @@ export class AuthenticationService {
|
|
|
822
836
|
throw e;
|
|
823
837
|
}
|
|
824
838
|
|
|
825
|
-
|
|
826
|
-
const dummyOtp = this.getDummyOtpForUser(user);
|
|
827
|
-
if (!dummyOtp)
|
|
828
|
-
this.clearLoginOtp(user, type);
|
|
829
|
-
|
|
830
|
-
user.failedLoginAttempts = 0;
|
|
839
|
+
await this.clearLoginOtp(user, type);
|
|
831
840
|
await this.userActivityHistoryService.logEvent('login', user);
|
|
832
|
-
await this.
|
|
841
|
+
await this.resetFailedAttempts(user);
|
|
833
842
|
return this.buildLoginTokenResponse(user);
|
|
834
843
|
}
|
|
835
844
|
|
|
@@ -846,15 +855,27 @@ export class AuthenticationService {
|
|
|
846
855
|
}
|
|
847
856
|
}
|
|
848
857
|
|
|
849
|
-
private clearLoginOtp(user: User, type: PasswordlessLoginValidateWhatSources): void {
|
|
858
|
+
private async clearLoginOtp(user: User, type: PasswordlessLoginValidateWhatSources): Promise<void> {
|
|
850
859
|
if (type === PasswordlessLoginValidateWhatSources.EMAIL) {
|
|
851
|
-
|
|
860
|
+
const verifiedAt = new Date();
|
|
861
|
+
user.emailVerifiedOnLoginAt = verifiedAt;
|
|
852
862
|
user.emailVerificationTokenOnLogin = null;
|
|
853
863
|
user.emailVerificationTokenOnLoginExpiresAt = null;
|
|
864
|
+
await this.userRepository.update(user.id, {
|
|
865
|
+
emailVerifiedOnLoginAt: verifiedAt,
|
|
866
|
+
emailVerificationTokenOnLogin: null,
|
|
867
|
+
emailVerificationTokenOnLoginExpiresAt: null,
|
|
868
|
+
});
|
|
854
869
|
} else {
|
|
855
|
-
|
|
870
|
+
const verifiedAt = new Date();
|
|
871
|
+
user.mobileVerifiedOnLoginAt = verifiedAt;
|
|
856
872
|
user.mobileVerificationTokenOnLogin = null;
|
|
857
873
|
user.mobileVerificationTokenOnLoginExpiresAt = null;
|
|
874
|
+
await this.userRepository.update(user.id, {
|
|
875
|
+
mobileVerifiedOnLoginAt: verifiedAt,
|
|
876
|
+
mobileVerificationTokenOnLogin: null,
|
|
877
|
+
mobileVerificationTokenOnLoginExpiresAt: null,
|
|
878
|
+
});
|
|
858
879
|
}
|
|
859
880
|
}
|
|
860
881
|
|
|
@@ -1297,14 +1318,15 @@ export class AuthenticationService {
|
|
|
1297
1318
|
}
|
|
1298
1319
|
|
|
1299
1320
|
private async incrementFailedAttempts(user: User): Promise<void> {
|
|
1300
|
-
user.failedLoginAttempts
|
|
1301
|
-
|
|
1321
|
+
const nextFailedAttempts = (user.failedLoginAttempts ?? 0) + 1;
|
|
1322
|
+
user.failedLoginAttempts = nextFailedAttempts;
|
|
1323
|
+
await this.userRepository.update(user.id, { failedLoginAttempts: nextFailedAttempts });
|
|
1302
1324
|
}
|
|
1303
1325
|
|
|
1304
1326
|
private async resetFailedAttempts(user: User): Promise<void> {
|
|
1305
1327
|
if (user.failedLoginAttempts === 0) return;
|
|
1306
1328
|
user.failedLoginAttempts = 0;
|
|
1307
|
-
await this.userRepository.
|
|
1329
|
+
await this.userRepository.update(user.id, { failedLoginAttempts: 0 });
|
|
1308
1330
|
}
|
|
1309
1331
|
|
|
1310
1332
|
//FIXME - Pending implementation
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
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
|
|
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
|
|
343
|
+
return null;
|
|
360
344
|
}
|
|
361
345
|
|
|
362
346
|
if (field.type === 'relation') {
|
|
@@ -644,6 +628,22 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
644
628
|
const [entities, count] = await qb.getManyAndCount();
|
|
645
629
|
this.logHeapUsed('getChatterMessages-entitiesLoaded');
|
|
646
630
|
|
|
631
|
+
// Convert date strings in message details to ISO format for consistent handling on the frontend
|
|
632
|
+
const DATE_FIELD_TYPES = ['date', 'datetime', 'time'];
|
|
633
|
+
for (const entity of entities) {
|
|
634
|
+
for (const detail of entity.chatterMessageDetails ?? []) {
|
|
635
|
+
if (!detail.fieldType || !DATE_FIELD_TYPES.includes(detail.fieldType)) continue;
|
|
636
|
+
if (detail.oldValue) {
|
|
637
|
+
const d = LocalDateTimeTransformer.from(detail.oldValue);
|
|
638
|
+
if (d) detail.oldValue = d.toISOString();
|
|
639
|
+
}
|
|
640
|
+
if (detail.newValue) {
|
|
641
|
+
const d = LocalDateTimeTransformer.from(detail.newValue);
|
|
642
|
+
if (d) detail.newValue = d.toISOString();
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
647
|
if (populateMedia && populateMedia.length > 0) {
|
|
648
648
|
const normalizedPopulateMedia = this.crudHelperService.normalize(populateMedia);
|
|
649
649
|
this.logHeapUsed('getChatterMessages-beforePopulateMedia');
|
|
@@ -1,20 +1,28 @@
|
|
|
1
|
+
import { classify } from "@angular-devkit/core/src/utils/strings";
|
|
1
2
|
import { Injectable } from "@nestjs/common";
|
|
2
3
|
import { InjectDataSource } from "@nestjs/typeorm";
|
|
4
|
+
import { ComputedFieldTriggerOperation } from "src/dtos/create-field-metadata.dto";
|
|
3
5
|
import { ComputedFieldProvider } from "src/decorators/computed-field-provider.decorator";
|
|
4
6
|
import { CommonEntity } from "src/entities/common.entity";
|
|
5
7
|
import { ModelSequence } from "src/entities/model-sequence.entity";
|
|
6
8
|
import { ComputedFieldMetadata } from "src/helpers/solid-registry";
|
|
7
|
-
import {
|
|
8
|
-
import { DataSource,
|
|
9
|
+
import { IEntityPostComputeFieldProvider } from "src/interfaces";
|
|
10
|
+
import { DataSource, EntityManager } from "typeorm";
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
export interface SequenceNumComputedFieldContext {
|
|
12
|
-
sequenceName: string;
|
|
14
|
+
sequenceName: string;
|
|
15
|
+
/**
|
|
16
|
+
* - `'counter'` (default): increments the sequence's `currentValue` and uses it as the number.
|
|
17
|
+
* - `'entityId'`: uses the entity's own `id` as the number; does not update the counter.
|
|
18
|
+
* Only valid on `afterInsert` events.
|
|
19
|
+
*/
|
|
20
|
+
mode?: 'counter' | 'entityId';
|
|
13
21
|
}
|
|
14
22
|
|
|
15
23
|
@ComputedFieldProvider()
|
|
16
24
|
@Injectable()
|
|
17
|
-
export class SequenceNumComputedFieldProvider<T extends CommonEntity> implements
|
|
25
|
+
export class SequenceNumComputedFieldProvider<T extends CommonEntity> implements IEntityPostComputeFieldProvider<T, SequenceNumComputedFieldContext> {
|
|
18
26
|
constructor(
|
|
19
27
|
@InjectDataSource()
|
|
20
28
|
private readonly dataSource: DataSource
|
|
@@ -25,23 +33,21 @@ export class SequenceNumComputedFieldProvider<T extends CommonEntity> implements
|
|
|
25
33
|
}
|
|
26
34
|
|
|
27
35
|
help(): string {
|
|
28
|
-
return "Computed field provider used to create fields whose value is based on some prefix, padding & sequence number."
|
|
36
|
+
return "Computed field provider used to create fields whose value is based on some prefix, padding & sequence number. " +
|
|
37
|
+
"Use mode='counter' (default) to auto-increment the sequence's currentValue. " +
|
|
38
|
+
"Use mode='entityId' to use the entity's own id as the number (afterInsert only, does not update the counter).";
|
|
29
39
|
}
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
41
|
+
private buildSequenceString(modelSequence: ModelSequence, numericValue: number): string {
|
|
42
|
+
const prefix = modelSequence.prefix ?? "";
|
|
43
|
+
const separator = modelSequence.separator ?? "";
|
|
44
|
+
const padded = String(numericValue).padStart(modelSequence.padding ?? 5, "0");
|
|
45
|
+
return `${prefix}${separator}${padded}`;
|
|
46
|
+
}
|
|
38
47
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
*/
|
|
43
|
-
// 1️⃣ Fetch sequence row
|
|
44
|
-
const modelSequenceRepo = manager.getRepository(ModelSequence)
|
|
48
|
+
private async generateCounterSequenceValue(sequenceName: string, manager?: EntityManager): Promise<{ sequenceString: string; currentValue: number; modelSingularName: string }> {
|
|
49
|
+
const run = async (mgr: EntityManager) => {
|
|
50
|
+
const modelSequenceRepo = mgr.getRepository(ModelSequence);
|
|
45
51
|
const modelSequence = await modelSequenceRepo.findOne({
|
|
46
52
|
where: { sequenceName },
|
|
47
53
|
lock: { mode: "pessimistic_write" }
|
|
@@ -51,36 +57,69 @@ export class SequenceNumComputedFieldProvider<T extends CommonEntity> implements
|
|
|
51
57
|
throw new Error(`ModelSequence not found for ${sequenceName}`);
|
|
52
58
|
}
|
|
53
59
|
|
|
54
|
-
// 2️⃣ Generate next sequence value
|
|
55
60
|
const nextValue = modelSequence.currentValue + 1;
|
|
61
|
+
const sequenceString = this.buildSequenceString(modelSequence, nextValue);
|
|
56
62
|
|
|
57
|
-
|
|
63
|
+
modelSequence.currentValue = nextValue;
|
|
64
|
+
await modelSequenceRepo.save(modelSequence);
|
|
58
65
|
|
|
59
|
-
|
|
60
|
-
const
|
|
66
|
+
// Load model relation in a separate query to avoid FOR UPDATE on joined relation.
|
|
67
|
+
const modelSequenceWithModel = await modelSequenceRepo.findOne({
|
|
68
|
+
where: { id: modelSequence.id },
|
|
69
|
+
relations: { model: true },
|
|
70
|
+
});
|
|
71
|
+
const modelSingularName = modelSequenceWithModel?.model?.singularName;
|
|
72
|
+
if (!modelSingularName) {
|
|
73
|
+
throw new Error(`Model singularName not found for sequence ${sequenceName}`);
|
|
74
|
+
}
|
|
61
75
|
|
|
62
|
-
|
|
76
|
+
return { sequenceString, currentValue: nextValue, modelSingularName };
|
|
77
|
+
};
|
|
63
78
|
|
|
64
|
-
|
|
65
|
-
|
|
79
|
+
return manager ? run(manager) : this.dataSource.transaction(run);
|
|
80
|
+
}
|
|
66
81
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
82
|
+
private async generateEntityIdSequenceValue(sequenceName: string, entityId: number): Promise<{ sequenceString: string; modelSingularName: string }> {
|
|
83
|
+
const modelSequenceRepo = this.dataSource.manager.getRepository(ModelSequence);
|
|
84
|
+
const modelSequence = await modelSequenceRepo.findOne({
|
|
85
|
+
where: { sequenceName },
|
|
86
|
+
relations: { model: true },
|
|
87
|
+
});
|
|
72
88
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
89
|
+
if (!modelSequence) {
|
|
90
|
+
throw new Error(`ModelSequence not found for ${sequenceName}`);
|
|
91
|
+
}
|
|
76
92
|
|
|
77
|
-
|
|
78
|
-
|
|
93
|
+
const modelSingularName = modelSequence.model?.singularName;
|
|
94
|
+
if (!modelSingularName) {
|
|
95
|
+
throw new Error(`Model singularName not found for sequence ${sequenceName}`);
|
|
96
|
+
}
|
|
79
97
|
|
|
80
|
-
|
|
81
|
-
modelSequence.currentValue = nextValue;
|
|
82
|
-
await modelSequenceRepo.save(modelSequence);
|
|
83
|
-
});
|
|
98
|
+
return { sequenceString: this.buildSequenceString(modelSequence, entityId), modelSingularName };
|
|
84
99
|
}
|
|
85
100
|
|
|
86
|
-
|
|
101
|
+
async postComputeAndSaveValue(triggerEntity: T, computedFieldMetadata: ComputedFieldMetadata<SequenceNumComputedFieldContext>): Promise<void> {
|
|
102
|
+
const { sequenceName, mode = 'counter' } = computedFieldMetadata.computedFieldValueProviderCtxt ?? {};
|
|
103
|
+
|
|
104
|
+
if (!sequenceName) {
|
|
105
|
+
throw new Error("sequenceName is required for sequence computation");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
let sequenceString: string;
|
|
109
|
+
let modelSingularName: string;
|
|
110
|
+
|
|
111
|
+
if (mode === 'entityId') {
|
|
112
|
+
const eventType = computedFieldMetadata.eventContext?.eventType;
|
|
113
|
+
if (eventType !== ComputedFieldTriggerOperation.afterInsert) {
|
|
114
|
+
throw new Error(`SequenceNumComputedFieldProvider with mode='entityId' only supports "${ComputedFieldTriggerOperation.afterInsert}" events, but received "${eventType}"`);
|
|
115
|
+
}
|
|
116
|
+
({ sequenceString, modelSingularName } = await this.generateEntityIdSequenceValue(sequenceName, triggerEntity.id));
|
|
117
|
+
} else {
|
|
118
|
+
({ sequenceString, modelSingularName } = await this.generateCounterSequenceValue(sequenceName));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const entityName = classify(modelSingularName);
|
|
122
|
+
const entityRepo = this.dataSource.manager.getRepository(entityName);
|
|
123
|
+
await entityRepo.update(triggerEntity.id, { [computedFieldMetadata.fieldName]: sequenceString });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -432,7 +432,7 @@ export class CRUDService<T extends CommonEntity> { // Add two generic value i.e
|
|
|
432
432
|
// dataSource: string; // The name of the selection provider
|
|
433
433
|
// filterSchema : json // This is a custom json object that every data source will handle accordingly. We could validate the query against the selection provider
|
|
434
434
|
// values : string[]; // The values returned by the selection provider
|
|
435
|
-
const options = { ...commonOptions, selectionDynamicProvider: fieldMetadata.selectionDynamicProvider, selectionDynamicProviderCtxt: fieldMetadata.selectionDynamicProviderCtxt, selectionValueType: fieldMetadata.selectionValueType as SelectionValueType, discoveryService: this.discoveryService, isMultiSelect: fieldMetadata.isMultiSelect };
|
|
435
|
+
const options = { ...commonOptions, selectionDynamicProvider: fieldMetadata.selectionDynamicProvider, selectionDynamicProviderCtxt: JSON.parse(fieldMetadata.selectionDynamicProviderCtxt), selectionValueType: fieldMetadata.selectionValueType as SelectionValueType, discoveryService: this.discoveryService, isMultiSelect: fieldMetadata.isMultiSelect };
|
|
436
436
|
return new SelectionDynamicFieldCrudManager(options);
|
|
437
437
|
}
|
|
438
438
|
case SolidFieldType.uuid: {
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { Injectable, Logger } from '@nestjs/common';
|
|
2
|
+
import { ModuleRef } from "@nestjs/core";
|
|
3
|
+
import { InjectEntityManager } from '@nestjs/typeorm';
|
|
4
|
+
import { EntityManager } from 'typeorm';
|
|
5
|
+
|
|
6
|
+
import { CRUDService } from 'src/services/crud.service';
|
|
7
|
+
import { DashboardLayout } from 'src/entities/dashboard-layout.entity';
|
|
8
|
+
import { DashboardLayoutRepository } from 'src/repository/dashboard-layout.repository';
|
|
9
|
+
import { CreateDashboardLayoutDto } from 'src/dtos/create-dashboard-layout.dto';
|
|
10
|
+
import { RequestContextService } from './request-context.service';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@Injectable()
|
|
14
|
+
export class DashboardLayoutService extends CRUDService<DashboardLayout> {
|
|
15
|
+
private readonly logger = new Logger(this.constructor.name);
|
|
16
|
+
constructor(
|
|
17
|
+
@InjectEntityManager()
|
|
18
|
+
readonly entityManager: EntityManager,
|
|
19
|
+
readonly repo: DashboardLayoutRepository,
|
|
20
|
+
readonly requestContextService: RequestContextService,
|
|
21
|
+
readonly moduleRef: ModuleRef,
|
|
22
|
+
) {
|
|
23
|
+
super(entityManager, repo, 'dashboardLayout', 'solid-core', moduleRef);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async upsertUserDashboardLayout(createDtos: CreateDashboardLayoutDto) {
|
|
27
|
+
const activeUser = this.requestContextService.getActiveUser();
|
|
28
|
+
|
|
29
|
+
if (!activeUser) {
|
|
30
|
+
throw new Error('User not found');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let userId = null;
|
|
34
|
+
if (activeUser.roles.includes('Admin')) {
|
|
35
|
+
userId = null;
|
|
36
|
+
} else {
|
|
37
|
+
userId = activeUser?.sub;
|
|
38
|
+
}
|
|
39
|
+
const existingLayout = await this.repo.findOne({
|
|
40
|
+
where: {
|
|
41
|
+
user: { id: userId },
|
|
42
|
+
dashboard: {
|
|
43
|
+
id: createDtos.dashboardId
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
relations: {
|
|
47
|
+
user: true,
|
|
48
|
+
dashboard: true,
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
if (existingLayout) {
|
|
53
|
+
return super.update(existingLayout.id, { layout: createDtos.layout }, [], true);
|
|
54
|
+
} else {
|
|
55
|
+
const createDto = {
|
|
56
|
+
layout: createDtos.layout,
|
|
57
|
+
dashboardId: createDtos.dashboardId,
|
|
58
|
+
uesrId: userId
|
|
59
|
+
}
|
|
60
|
+
return super.create(createDto, []);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async getUserDashboardLayoutByDashboardId(dashboardId: any) {
|
|
65
|
+
const activeUser = this.requestContextService.getActiveUser();
|
|
66
|
+
|
|
67
|
+
if (!activeUser) {
|
|
68
|
+
throw new Error('User not found');
|
|
69
|
+
}
|
|
70
|
+
const userId = activeUser?.sub;
|
|
71
|
+
const existingUserLayout = await this.repo.findOne({
|
|
72
|
+
where: {
|
|
73
|
+
user: { id: userId },
|
|
74
|
+
dashboard: {
|
|
75
|
+
id: dashboardId
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
relations: {
|
|
79
|
+
user: true,
|
|
80
|
+
dashboard: true,
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
if (existingUserLayout) {
|
|
84
|
+
// if dahsboard for userid exists
|
|
85
|
+
return existingUserLayout;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// if not then check for default dashboard
|
|
89
|
+
const defaultLayout = await this.repo.findOne({
|
|
90
|
+
where: {
|
|
91
|
+
user: { id: null },
|
|
92
|
+
dashboard: {
|
|
93
|
+
id: dashboardId
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
relations: {
|
|
97
|
+
user: true,
|
|
98
|
+
dashboard: true,
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
if (defaultLayout) {
|
|
102
|
+
// if default layout exists return it
|
|
103
|
+
return defaultLayout;
|
|
104
|
+
} else {
|
|
105
|
+
// if default layout does not exist return empty layout
|
|
106
|
+
return {
|
|
107
|
+
layout: null
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -11,15 +11,18 @@ import { SolidRegistry } from 'src/helpers/solid-registry';
|
|
|
11
11
|
import { DashboardQuestion } from '../entities/dashboard-question.entity';
|
|
12
12
|
import { SqlExpression, SqlExpressionOperator } from './question-data-providers/chartjs-sql-data-provider.service';
|
|
13
13
|
import { DashboardQuestionRepository } from 'src/repository/dashboard-question.repository';
|
|
14
|
+
import { QuestionSqlDataProviderContext } from 'src';
|
|
14
15
|
|
|
15
16
|
enum SOURCE_TYPE {
|
|
16
17
|
SQL = 'sql',
|
|
17
18
|
PROVIDER = 'provider',
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
const CHARTJS_SQL_DATA_PROVIDER_NAME = 'ChartJsSqlDataProvider';
|
|
21
|
-
const PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME = 'PrimeReactMeterGroupSqlDataProvider';
|
|
22
|
-
const PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME = 'PrimeReactDatatableSqlDataProvider';
|
|
21
|
+
export const CHARTJS_SQL_DATA_PROVIDER_NAME = 'ChartJsSqlDataProvider';
|
|
22
|
+
export const PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME = 'PrimeReactMeterGroupSqlDataProvider';
|
|
23
|
+
export const PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME = 'PrimeReactDatatableSqlDataProvider';
|
|
24
|
+
|
|
25
|
+
export const INBUILT_SQL_DATA_PROVIDERS = [CHARTJS_SQL_DATA_PROVIDER_NAME, PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME, PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME];
|
|
23
26
|
|
|
24
27
|
@Injectable()
|
|
25
28
|
export class DashboardQuestionService extends CRUDService<DashboardQuestion> {
|
|
@@ -50,22 +53,38 @@ export class DashboardQuestionService extends CRUDService<DashboardQuestion> {
|
|
|
50
53
|
|
|
51
54
|
// Try to resolve the dataProvider based on a combination of sourceType and visualisedAs
|
|
52
55
|
let dataProvider = null;
|
|
56
|
+
let context = {};
|
|
53
57
|
|
|
58
|
+
// Decide which data provider to use based on the question visualisation type if sourceType is SQL.
|
|
54
59
|
if (question.sourceType === SOURCE_TYPE.SQL && ['bar', 'pie', 'line', 'donut'].includes(question.visualisedAs)) {
|
|
55
60
|
dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(CHARTJS_SQL_DATA_PROVIDER_NAME);
|
|
61
|
+
context = {
|
|
62
|
+
expressions,
|
|
63
|
+
} as QuestionSqlDataProviderContext;
|
|
56
64
|
}
|
|
57
65
|
if (question.sourceType === SOURCE_TYPE.SQL && ['prime-meter-group'].includes(question.visualisedAs)) {
|
|
58
66
|
dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME);
|
|
67
|
+
context = {
|
|
68
|
+
expressions,
|
|
69
|
+
} as QuestionSqlDataProviderContext;
|
|
59
70
|
}
|
|
60
71
|
if (question.sourceType === SOURCE_TYPE.SQL && ['prime-datatable'].includes(question.visualisedAs)) {
|
|
61
72
|
dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME);
|
|
73
|
+
context = {
|
|
74
|
+
expressions,
|
|
75
|
+
} as QuestionSqlDataProviderContext;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// If a custom provider is specified, use that one instead
|
|
79
|
+
if (question.sourceType === SOURCE_TYPE.PROVIDER) {
|
|
80
|
+
dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(question.providerName);
|
|
62
81
|
}
|
|
63
82
|
|
|
64
83
|
if (!dataProvider) {
|
|
65
84
|
throw new NotImplementedException(`Invalid data source type ${question.sourceType}`);
|
|
66
85
|
}
|
|
67
86
|
|
|
68
|
-
return await dataProvider.getData(question,
|
|
87
|
+
return await dataProvider.getData(question, context);
|
|
69
88
|
|
|
70
89
|
}
|
|
71
90
|
|
|
@@ -15,6 +15,7 @@ import { SolidRegistry } from 'src/helpers/solid-registry';
|
|
|
15
15
|
import { DashboardMapper } from 'src/mappers/dashboard-mapper';
|
|
16
16
|
import { DashboardRepository } from 'src/repository/dashboard.repository';
|
|
17
17
|
import { Dashboard } from '../entities/dashboard.entity';
|
|
18
|
+
import { CreateDashboardDto } from 'src/dtos/create-dashboard.dto';
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
export const SQL_DYNAMIC_PROVIDER_NAME = 'DashboardVariableSQLDynamicProvider';
|
|
@@ -33,6 +34,12 @@ export class DashboardService extends CRUDService<Dashboard> {
|
|
|
33
34
|
super(entityManager, repo, 'dashboard', 'solid-core', moduleRef);
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
|
|
38
|
+
async create(createDto: CreateDashboardDto, files: Express.Multer.File[]) {
|
|
39
|
+
createDto.name = createDto.name.trim().replace(/\s+/g, '-').toLowerCase();
|
|
40
|
+
return super.create(createDto, files);
|
|
41
|
+
}
|
|
42
|
+
|
|
36
43
|
async getSelectionDynamicValues(query: DashboardVariableSelectionDynamicQueryDto) {
|
|
37
44
|
// Get the dashboard variable repo
|
|
38
45
|
const dashboardVariable = await this.loadDashboardVariable(query.variableId);
|