From d767003c85440880d30ed421031af4dd27f9022b Mon Sep 17 00:00:00 2001 From: German Martinez Date: Fri, 8 Nov 2024 08:49:07 -0500 Subject: [PATCH 01/12] =?UTF-8?q?=E2=99=BB=EF=B8=8Frefactor:=20extracting?= =?UTF-8?q?=20toc=20repositories=20to=20a=20folder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../delete-recover-data.module.ts | 14 +++++++------- .../delete-recover-data.service.ts | 14 +++++++------- .../results-package-toc-result.module.ts | 14 +++++++------- .../results-package-toc-result.service.ts | 2 +- .../result-toc-action-area.repository.ts | 6 +++--- .../result-toc-impact-area-repository.ts | 6 +++--- ...esult-toc-result-target-indicator.repository.ts | 6 +++--- .../result-toc-sdg-target-repository.ts | 6 +++--- .../results-sdg-targets.respository.ts | 6 +++--- .../results-toc-results-indicators.repository.ts | 6 +++--- .../results-toc-results.repository.ts | 12 ++++++------ .../results-toc-results.module.ts | 14 +++++++------- .../results-toc-results.service.ts | 2 +- .../share-result-request.module.ts | 14 +++++++------- .../share-result-request.service.ts | 2 +- .../src/api/versioning/versioning.module.ts | 14 +++++++------- .../src/api/versioning/versioning.service.spec.ts | 14 +++++++------- .../src/toc/toc-results/toc-results.module.ts | 14 +++++++------- 18 files changed, 83 insertions(+), 83 deletions(-) rename onecgiar-pr-server/src/api/results/results-toc-results/{ => repositories}/result-toc-action-area.repository.ts (86%) rename onecgiar-pr-server/src/api/results/results-toc-results/{ => repositories}/result-toc-impact-area-repository.ts (86%) rename onecgiar-pr-server/src/api/results/results-toc-results/{ => repositories}/result-toc-result-target-indicator.repository.ts (87%) rename onecgiar-pr-server/src/api/results/results-toc-results/{ => repositories}/result-toc-sdg-target-repository.ts (86%) rename onecgiar-pr-server/src/api/results/results-toc-results/{ => repositories}/results-sdg-targets.respository.ts (84%) rename onecgiar-pr-server/src/api/results/results-toc-results/{ => repositories}/results-toc-results-indicators.repository.ts (86%) rename onecgiar-pr-server/src/api/results/results-toc-results/{ => repositories}/results-toc-results.repository.ts (99%) diff --git a/onecgiar-pr-server/src/api/delete-recover-data/delete-recover-data.module.ts b/onecgiar-pr-server/src/api/delete-recover-data/delete-recover-data.module.ts index 7664bdad5..8431c760b 100644 --- a/onecgiar-pr-server/src/api/delete-recover-data/delete-recover-data.module.ts +++ b/onecgiar-pr-server/src/api/delete-recover-data/delete-recover-data.module.ts @@ -38,13 +38,13 @@ import { ResultsKnowledgeProductAuthorRepository } from '../results/results-know import { ResultsKnowledgeProductKeywordRepository } from '../results/results-knowledge-products/repositories/results-knowledge-product-keywords.repository'; import { ResultsKnowledgeProductMetadataRepository } from '../results/results-knowledge-products/repositories/results-knowledge-product-metadata.repository'; import { ResultsKnowledgeProductsRepository } from '../results/results-knowledge-products/repositories/results-knowledge-products.repository'; -import { ResultsActionAreaOutcomeRepository } from '../results/results-toc-results/result-toc-action-area.repository'; -import { ResultsTocImpactAreaTargetRepository } from '../results/results-toc-results/result-toc-impact-area-repository'; -import { ResultsTocTargetIndicatorRepository } from '../results/results-toc-results/result-toc-result-target-indicator.repository'; -import { ResultsTocSdgTargetRepository } from '../results/results-toc-results/result-toc-sdg-target-repository'; -import { ResultsSdgTargetRepository } from '../results/results-toc-results/results-sdg-targets.respository'; -import { ResultsTocResultIndicatorsRepository } from '../results/results-toc-results/results-toc-results-indicators.repository'; -import { ResultsTocResultRepository } from '../results/results-toc-results/results-toc-results.repository'; +import { ResultsActionAreaOutcomeRepository } from '../results/results-toc-results/repositories/result-toc-action-area.repository'; +import { ResultsTocImpactAreaTargetRepository } from '../results/results-toc-results/repositories/result-toc-impact-area-repository'; +import { ResultsTocTargetIndicatorRepository } from '../results/results-toc-results/repositories/result-toc-result-target-indicator.repository'; +import { ResultsTocSdgTargetRepository } from '../results/results-toc-results/repositories/result-toc-sdg-target-repository'; +import { ResultsSdgTargetRepository } from '../results/results-toc-results/repositories/results-sdg-targets.respository'; +import { ResultsTocResultIndicatorsRepository } from '../results/results-toc-results/repositories/results-toc-results-indicators.repository'; +import { ResultsTocResultRepository } from '../results/results-toc-results/repositories/results-toc-results.repository'; import { resultValidationRepository } from '../results/results-validation-module/results-validation-module.repository'; import { ResultByEvidencesRepository } from '../results/results_by_evidences/result_by_evidences.repository'; import { ResultByInitiativesRepository } from '../results/results_by_inititiatives/resultByInitiatives.repository'; diff --git a/onecgiar-pr-server/src/api/delete-recover-data/delete-recover-data.service.ts b/onecgiar-pr-server/src/api/delete-recover-data/delete-recover-data.service.ts index 44fa99ab9..636e8b09c 100644 --- a/onecgiar-pr-server/src/api/delete-recover-data/delete-recover-data.service.ts +++ b/onecgiar-pr-server/src/api/delete-recover-data/delete-recover-data.service.ts @@ -37,13 +37,13 @@ import { ResultsKnowledgeProductAuthorRepository } from '../results/results-know import { ResultsKnowledgeProductKeywordRepository } from '../results/results-knowledge-products/repositories/results-knowledge-product-keywords.repository'; import { ResultsKnowledgeProductMetadataRepository } from '../results/results-knowledge-products/repositories/results-knowledge-product-metadata.repository'; import { ResultsKnowledgeProductsRepository } from '../results/results-knowledge-products/repositories/results-knowledge-products.repository'; -import { ResultsActionAreaOutcomeRepository } from '../results/results-toc-results/result-toc-action-area.repository'; -import { ResultsTocImpactAreaTargetRepository } from '../results/results-toc-results/result-toc-impact-area-repository'; -import { ResultsTocTargetIndicatorRepository } from '../results/results-toc-results/result-toc-result-target-indicator.repository'; -import { ResultsTocSdgTargetRepository } from '../results/results-toc-results/result-toc-sdg-target-repository'; -import { ResultsSdgTargetRepository } from '../results/results-toc-results/results-sdg-targets.respository'; -import { ResultsTocResultIndicatorsRepository } from '../results/results-toc-results/results-toc-results-indicators.repository'; -import { ResultsTocResultRepository } from '../results/results-toc-results/results-toc-results.repository'; +import { ResultsActionAreaOutcomeRepository } from '../results/results-toc-results/repositories/result-toc-action-area.repository'; +import { ResultsTocImpactAreaTargetRepository } from '../results/results-toc-results/repositories/result-toc-impact-area-repository'; +import { ResultsTocTargetIndicatorRepository } from '../results/results-toc-results/repositories/result-toc-result-target-indicator.repository'; +import { ResultsTocSdgTargetRepository } from '../results/results-toc-results/repositories/result-toc-sdg-target-repository'; +import { ResultsSdgTargetRepository } from '../results/results-toc-results/repositories/results-sdg-targets.respository'; +import { ResultsTocResultIndicatorsRepository } from '../results/results-toc-results/repositories/results-toc-results-indicators.repository'; +import { ResultsTocResultRepository } from '../results/results-toc-results/repositories/results-toc-results.repository'; import { resultValidationRepository } from '../results/results-validation-module/results-validation-module.repository'; import { ResultByEvidencesRepository } from '../results/results_by_evidences/result_by_evidences.repository'; import { ResultByInitiativesRepository } from '../results/results_by_inititiatives/resultByInitiatives.repository'; diff --git a/onecgiar-pr-server/src/api/ipsr/results-package-toc-result/results-package-toc-result.module.ts b/onecgiar-pr-server/src/api/ipsr/results-package-toc-result/results-package-toc-result.module.ts index b066deb47..80b972489 100644 --- a/onecgiar-pr-server/src/api/ipsr/results-package-toc-result/results-package-toc-result.module.ts +++ b/onecgiar-pr-server/src/api/ipsr/results-package-toc-result/results-package-toc-result.module.ts @@ -11,7 +11,7 @@ import { VersionRepository } from '../../versioning/versioning.repository'; import { IpsrRepository } from '../repository/ipsr.repository'; import { ResultsCenterRepository } from '../../results/results-centers/results-centers.repository'; import { ResultByInitiativesRepository } from '../../results/results_by_inititiatives/resultByInitiatives.repository'; -import { ResultsTocResultRepository } from '../../results/results-toc-results/results-toc-results.repository'; +import { ResultsTocResultRepository } from '../../results/results-toc-results/repositories/results-toc-results.repository'; import { ShareResultRequestService } from '../../results/share-result-request/share-result-request.service'; import { ShareResultRequestRepository } from '../../results/share-result-request/share-result-request.repository'; import { NonPooledProjectRepository } from '../../results/non-pooled-projects/non-pooled-projects.repository'; @@ -20,12 +20,12 @@ import { ResultByInstitutionsByDeliveriesTypeRepository } from '../../results/re import { ResultInitiativeBudgetRepository } from '../../results/result_budget/repositories/result_initiative_budget.repository'; import { ResultIpEoiOutcomeRepository } from '../innovation-pathway/repository/result-ip-eoi-outcomes.repository'; import { VersioningModule } from '../../versioning/versioning.module'; -import { ResultsTocResultIndicatorsRepository } from 'src/api/results/results-toc-results/results-toc-results-indicators.repository'; -import { ResultsTocSdgTargetRepository } from 'src/api/results/results-toc-results/result-toc-sdg-target-repository'; -import { ResultsTocImpactAreaTargetRepository } from 'src/api/results/results-toc-results/result-toc-impact-area-repository'; -import { ResultsSdgTargetRepository } from 'src/api/results/results-toc-results/results-sdg-targets.respository'; -import { ResultsActionAreaOutcomeRepository } from 'src/api/results/results-toc-results/result-toc-action-area.repository'; -import { ResultsTocTargetIndicatorRepository } from 'src/api/results/results-toc-results/result-toc-result-target-indicator.repository'; +import { ResultsTocResultIndicatorsRepository } from 'src/api/results/results-toc-results/repositories/results-toc-results-indicators.repository'; +import { ResultsTocSdgTargetRepository } from 'src/api/results/results-toc-results/repositories/result-toc-sdg-target-repository'; +import { ResultsTocImpactAreaTargetRepository } from 'src/api/results/results-toc-results/repositories/result-toc-impact-area-repository'; +import { ResultsSdgTargetRepository } from 'src/api/results/results-toc-results/repositories/results-sdg-targets.respository'; +import { ResultsActionAreaOutcomeRepository } from 'src/api/results/results-toc-results/repositories/result-toc-action-area.repository'; +import { ResultsTocTargetIndicatorRepository } from 'src/api/results/results-toc-results/repositories/result-toc-result-target-indicator.repository'; import { ResultsTocResultsModule } from '../../results/results-toc-results/results-toc-results.module'; import { ClarisaInitiativesRepository } from '../../../clarisa/clarisa-initiatives/ClarisaInitiatives.repository'; import { TemplateRepository } from '../../platform-report/repositories/template.repository'; diff --git a/onecgiar-pr-server/src/api/ipsr/results-package-toc-result/results-package-toc-result.service.ts b/onecgiar-pr-server/src/api/ipsr/results-package-toc-result/results-package-toc-result.service.ts index 12dd00b96..46760a82f 100644 --- a/onecgiar-pr-server/src/api/ipsr/results-package-toc-result/results-package-toc-result.service.ts +++ b/onecgiar-pr-server/src/api/ipsr/results-package-toc-result/results-package-toc-result.service.ts @@ -12,7 +12,7 @@ import { IpsrRepository } from '../repository/ipsr.repository'; import { NonPooledProjectRepository } from '../../results/non-pooled-projects/non-pooled-projects.repository'; import { ResultsCenterRepository } from '../../results/results-centers/results-centers.repository'; import { ResultByInitiativesRepository } from '../../results/results_by_inititiatives/resultByInitiatives.repository'; -import { ResultsTocResultRepository } from '../../results/results-toc-results/results-toc-results.repository'; +import { ResultsTocResultRepository } from '../../results/results-toc-results/repositories/results-toc-results.repository'; import { ResultByIntitutionsRepository } from '../../results/results_by_institutions/result_by_intitutions.repository'; import { ResultByInstitutionsByDeliveriesTypeRepository } from '../../results/result-by-institutions-by-deliveries-type/result-by-institutions-by-deliveries-type.repository'; import { ResultsByInstitution } from '../../results/results_by_institutions/entities/results_by_institution.entity'; diff --git a/onecgiar-pr-server/src/api/results/results-toc-results/result-toc-action-area.repository.ts b/onecgiar-pr-server/src/api/results/results-toc-results/repositories/result-toc-action-area.repository.ts similarity index 86% rename from onecgiar-pr-server/src/api/results/results-toc-results/result-toc-action-area.repository.ts rename to onecgiar-pr-server/src/api/results/results-toc-results/repositories/result-toc-action-area.repository.ts index fdb3d47ba..15eed3cc4 100644 --- a/onecgiar-pr-server/src/api/results/results-toc-results/result-toc-action-area.repository.ts +++ b/onecgiar-pr-server/src/api/results/results-toc-results/repositories/result-toc-action-area.repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { DataSource, Repository } from 'typeorm'; -import { HandlersError } from '../../../shared/handlers/error.utils'; -import { ResultTocActionArea } from './entities/result-toc-action-area.entity'; -import { LogicalDelete } from '../../../shared/globalInterfaces/delete.interface'; +import { HandlersError } from '../../../../shared/handlers/error.utils'; +import { ResultTocActionArea } from '../entities/result-toc-action-area.entity'; +import { LogicalDelete } from '../../../../shared/globalInterfaces/delete.interface'; @Injectable() export class ResultsActionAreaOutcomeRepository diff --git a/onecgiar-pr-server/src/api/results/results-toc-results/result-toc-impact-area-repository.ts b/onecgiar-pr-server/src/api/results/results-toc-results/repositories/result-toc-impact-area-repository.ts similarity index 86% rename from onecgiar-pr-server/src/api/results/results-toc-results/result-toc-impact-area-repository.ts rename to onecgiar-pr-server/src/api/results/results-toc-results/repositories/result-toc-impact-area-repository.ts index 53bc45dc6..20234b6be 100644 --- a/onecgiar-pr-server/src/api/results/results-toc-results/result-toc-impact-area-repository.ts +++ b/onecgiar-pr-server/src/api/results/results-toc-results/repositories/result-toc-impact-area-repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { DataSource, Repository } from 'typeorm'; -import { HandlersError } from '../../../shared/handlers/error.utils'; -import { ResultTocImpactArea } from './entities/result-toc-impact-area-target.entity'; -import { LogicalDelete } from '../../../shared/globalInterfaces/delete.interface'; +import { HandlersError } from '../../../../shared/handlers/error.utils'; +import { ResultTocImpactArea } from '../entities/result-toc-impact-area-target.entity'; +import { LogicalDelete } from '../../../../shared/globalInterfaces/delete.interface'; @Injectable() export class ResultsTocImpactAreaTargetRepository diff --git a/onecgiar-pr-server/src/api/results/results-toc-results/result-toc-result-target-indicator.repository.ts b/onecgiar-pr-server/src/api/results/results-toc-results/repositories/result-toc-result-target-indicator.repository.ts similarity index 87% rename from onecgiar-pr-server/src/api/results/results-toc-results/result-toc-result-target-indicator.repository.ts rename to onecgiar-pr-server/src/api/results/results-toc-results/repositories/result-toc-result-target-indicator.repository.ts index 36cf01c14..73aa189ac 100644 --- a/onecgiar-pr-server/src/api/results/results-toc-results/result-toc-result-target-indicator.repository.ts +++ b/onecgiar-pr-server/src/api/results/results-toc-results/repositories/result-toc-result-target-indicator.repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { DataSource, Repository } from 'typeorm'; -import { HandlersError } from '../../../shared/handlers/error.utils'; -import { ResultIndicatorTarget } from './entities/result-toc-result-target-indicators.entity'; -import { LogicalDelete } from '../../../shared/globalInterfaces/delete.interface'; +import { HandlersError } from '../../../../shared/handlers/error.utils'; +import { ResultIndicatorTarget } from '../entities/result-toc-result-target-indicators.entity'; +import { LogicalDelete } from '../../../../shared/globalInterfaces/delete.interface'; @Injectable() export class ResultsTocTargetIndicatorRepository diff --git a/onecgiar-pr-server/src/api/results/results-toc-results/result-toc-sdg-target-repository.ts b/onecgiar-pr-server/src/api/results/results-toc-results/repositories/result-toc-sdg-target-repository.ts similarity index 86% rename from onecgiar-pr-server/src/api/results/results-toc-results/result-toc-sdg-target-repository.ts rename to onecgiar-pr-server/src/api/results/results-toc-results/repositories/result-toc-sdg-target-repository.ts index dc11f5e5e..f45d3375b 100644 --- a/onecgiar-pr-server/src/api/results/results-toc-results/result-toc-sdg-target-repository.ts +++ b/onecgiar-pr-server/src/api/results/results-toc-results/repositories/result-toc-sdg-target-repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { DataSource, Repository } from 'typeorm'; -import { HandlersError } from '../../../shared/handlers/error.utils'; -import { ResultTocSdgTargets } from './entities/result-toc-sdg-target.entity'; -import { LogicalDelete } from '../../../shared/globalInterfaces/delete.interface'; +import { HandlersError } from '../../../../shared/handlers/error.utils'; +import { ResultTocSdgTargets } from '../entities/result-toc-sdg-target.entity'; +import { LogicalDelete } from '../../../../shared/globalInterfaces/delete.interface'; @Injectable() export class ResultsTocSdgTargetRepository diff --git a/onecgiar-pr-server/src/api/results/results-toc-results/results-sdg-targets.respository.ts b/onecgiar-pr-server/src/api/results/results-toc-results/repositories/results-sdg-targets.respository.ts similarity index 84% rename from onecgiar-pr-server/src/api/results/results-toc-results/results-sdg-targets.respository.ts rename to onecgiar-pr-server/src/api/results/results-toc-results/repositories/results-sdg-targets.respository.ts index 728392d97..322c0957e 100644 --- a/onecgiar-pr-server/src/api/results/results-toc-results/results-sdg-targets.respository.ts +++ b/onecgiar-pr-server/src/api/results/results-toc-results/repositories/results-sdg-targets.respository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { DataSource, Repository } from 'typeorm'; -import { HandlersError } from '../../../shared/handlers/error.utils'; -import { ResultSdgTargets } from './entities/results-sdg-targets.entity'; -import { LogicalDelete } from '../../../shared/globalInterfaces/delete.interface'; +import { HandlersError } from '../../../../shared/handlers/error.utils'; +import { ResultSdgTargets } from '../entities/results-sdg-targets.entity'; +import { LogicalDelete } from '../../../../shared/globalInterfaces/delete.interface'; @Injectable() export class ResultsSdgTargetRepository diff --git a/onecgiar-pr-server/src/api/results/results-toc-results/results-toc-results-indicators.repository.ts b/onecgiar-pr-server/src/api/results/results-toc-results/repositories/results-toc-results-indicators.repository.ts similarity index 86% rename from onecgiar-pr-server/src/api/results/results-toc-results/results-toc-results-indicators.repository.ts rename to onecgiar-pr-server/src/api/results/results-toc-results/repositories/results-toc-results-indicators.repository.ts index 227f2b574..0b4e01081 100644 --- a/onecgiar-pr-server/src/api/results/results-toc-results/results-toc-results-indicators.repository.ts +++ b/onecgiar-pr-server/src/api/results/results-toc-results/repositories/results-toc-results-indicators.repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { DataSource, Repository } from 'typeorm'; -import { HandlersError } from '../../../shared/handlers/error.utils'; -import { ResultsTocResultIndicators } from './entities/results-toc-results-indicators.entity'; -import { LogicalDelete } from '../../../shared/globalInterfaces/delete.interface'; +import { HandlersError } from '../../../../shared/handlers/error.utils'; +import { ResultsTocResultIndicators } from '../entities/results-toc-results-indicators.entity'; +import { LogicalDelete } from '../../../../shared/globalInterfaces/delete.interface'; @Injectable() export class ResultsTocResultIndicatorsRepository diff --git a/onecgiar-pr-server/src/api/results/results-toc-results/results-toc-results.repository.ts b/onecgiar-pr-server/src/api/results/results-toc-results/repositories/results-toc-results.repository.ts similarity index 99% rename from onecgiar-pr-server/src/api/results/results-toc-results/results-toc-results.repository.ts rename to onecgiar-pr-server/src/api/results/results-toc-results/repositories/results-toc-results.repository.ts index 1f111167b..ac204921b 100644 --- a/onecgiar-pr-server/src/api/results/results-toc-results/results-toc-results.repository.ts +++ b/onecgiar-pr-server/src/api/results/results-toc-results/repositories/results-toc-results.repository.ts @@ -1,21 +1,21 @@ import { Injectable, Logger } from '@nestjs/common'; import { env } from 'process'; import { DataSource, Repository } from 'typeorm'; -import { HandlersError } from '../../../shared/handlers/error.utils'; -import { ResultsTocResult } from './entities/results-toc-result.entity'; +import { HandlersError } from '../../../../shared/handlers/error.utils'; +import { ResultsTocResult } from '../entities/results-toc-result.entity'; import { ReplicableConfigInterface, ReplicableInterface, -} from '../../../shared/globalInterfaces/replicable.interface'; +} from '../../../../shared/globalInterfaces/replicable.interface'; import { ResultsTocResultIndicatorsRepository } from './results-toc-results-indicators.repository'; import { ResultsTocImpactAreaTargetRepository } from './result-toc-impact-area-repository'; import { ResultsTocSdgTargetRepository } from './result-toc-sdg-target-repository'; import { ResultsSdgTargetRepository } from './results-sdg-targets.respository'; import { ResultsActionAreaOutcomeRepository } from './result-toc-action-area.repository'; import { ResultsTocTargetIndicatorRepository } from './result-toc-result-target-indicator.repository'; -import { LogicalDelete } from '../../../shared/globalInterfaces/delete.interface'; -import { CreateResultsTocResultDto } from './dto/create-results-toc-result.dto'; -import { predeterminedDateValidation } from '../../../shared/utils/versioning.utils'; +import { LogicalDelete } from '../../../../shared/globalInterfaces/delete.interface'; +import { CreateResultsTocResultDto } from '../dto/create-results-toc-result.dto'; +import { predeterminedDateValidation } from '../../../../shared/utils/versioning.utils'; @Injectable() export class ResultsTocResultRepository diff --git a/onecgiar-pr-server/src/api/results/results-toc-results/results-toc-results.module.ts b/onecgiar-pr-server/src/api/results/results-toc-results/results-toc-results.module.ts index 6ebb4f4d9..9f10f8d8e 100644 --- a/onecgiar-pr-server/src/api/results/results-toc-results/results-toc-results.module.ts +++ b/onecgiar-pr-server/src/api/results/results-toc-results/results-toc-results.module.ts @@ -5,7 +5,7 @@ import { HandlersError, ReturnResponse, } from '../../../shared/handlers/error.utils'; -import { ResultsTocResultRepository } from './results-toc-results.repository'; +import { ResultsTocResultRepository } from './repositories/results-toc-results.repository'; import { NonPooledProjectRepository } from '../non-pooled-projects/non-pooled-projects.repository'; import { ResultsCenterRepository } from '../results-centers/results-centers.repository'; import { ResultByInitiativesRepository } from '../results_by_inititiatives/resultByInitiatives.repository'; @@ -18,14 +18,14 @@ import { ClarisaImpactAreaRepository } from '../../../clarisa/clarisa-impact-are import { ShareResultRequestService } from '../share-result-request/share-result-request.service'; import { ShareResultRequestRepository } from '../share-result-request/share-result-request.repository'; import { ResultInitiativeBudgetRepository } from '../result_budget/repositories/result_initiative_budget.repository'; -import { ResultsTocResultIndicatorsRepository } from './results-toc-results-indicators.repository'; -import { ResultsTocSdgTargetRepository } from './result-toc-sdg-target-repository'; -import { ResultsTocImpactAreaTargetRepository } from './result-toc-impact-area-repository'; -import { ResultsSdgTargetRepository } from './results-sdg-targets.respository'; +import { ResultsTocResultIndicatorsRepository } from './repositories/results-toc-results-indicators.repository'; +import { ResultsTocSdgTargetRepository } from './repositories/result-toc-sdg-target-repository'; +import { ResultsTocImpactAreaTargetRepository } from './repositories/result-toc-impact-area-repository'; +import { ResultsSdgTargetRepository } from './repositories/results-sdg-targets.respository'; import { NonPooledProjectBudgetRepository } from '../result_budget/repositories/non_pooled_proyect_budget.repository'; import { RoleByUserRepository } from '../../../auth/modules/role-by-user/RoleByUser.repository'; -import { ResultsActionAreaOutcomeRepository } from './result-toc-action-area.repository'; -import { ResultsTocTargetIndicatorRepository } from './result-toc-result-target-indicator.repository'; +import { ResultsActionAreaOutcomeRepository } from './repositories/result-toc-action-area.repository'; +import { ResultsTocTargetIndicatorRepository } from './repositories/result-toc-result-target-indicator.repository'; import { ClarisaInitiativesRepository } from '../../../clarisa/clarisa-initiatives/ClarisaInitiatives.repository'; import { TemplateRepository } from '../../platform-report/repositories/template.repository'; import { GlobalParameterRepository } from '../../global-parameter/repositories/global-parameter.repository'; diff --git a/onecgiar-pr-server/src/api/results/results-toc-results/results-toc-results.service.ts b/onecgiar-pr-server/src/api/results/results-toc-results/results-toc-results.service.ts index b8d2a323e..48de9c93e 100644 --- a/onecgiar-pr-server/src/api/results/results-toc-results/results-toc-results.service.ts +++ b/onecgiar-pr-server/src/api/results/results-toc-results/results-toc-results.service.ts @@ -3,7 +3,7 @@ import { ContributorResultTocResult, CreateResultsTocResultDto, } from './dto/create-results-toc-result.dto'; -import { ResultsTocResultRepository } from './results-toc-results.repository'; +import { ResultsTocResultRepository } from './repositories/results-toc-results.repository'; import { HandlersError } from '../../../shared/handlers/error.utils'; import { ResultsTocResult } from './entities/results-toc-result.entity'; import { TokenDto } from '../../../shared/globalInterfaces/token.dto'; diff --git a/onecgiar-pr-server/src/api/results/share-result-request/share-result-request.module.ts b/onecgiar-pr-server/src/api/results/share-result-request/share-result-request.module.ts index 3eb659be0..f35fb4ddc 100644 --- a/onecgiar-pr-server/src/api/results/share-result-request/share-result-request.module.ts +++ b/onecgiar-pr-server/src/api/results/share-result-request/share-result-request.module.ts @@ -10,15 +10,15 @@ import { ResultRepository } from '../result.repository'; import { ResultByInitiativesRepository } from '../results_by_inititiatives/resultByInitiatives.repository'; import { VersionsService } from '../versions/versions.service'; import { VersionRepository } from '../../versioning/versioning.repository'; -import { ResultsTocResultRepository } from '../results-toc-results/results-toc-results.repository'; +import { ResultsTocResultRepository } from '../results-toc-results/repositories/results-toc-results.repository'; import { ResultInitiativeBudgetRepository } from '../result_budget/repositories/result_initiative_budget.repository'; -import { ResultsTocResultIndicatorsRepository } from '../results-toc-results/results-toc-results-indicators.repository'; -import { ResultsTocSdgTargetRepository } from '../results-toc-results/result-toc-sdg-target-repository'; -import { ResultsTocImpactAreaTargetRepository } from '../results-toc-results/result-toc-impact-area-repository'; -import { ResultsSdgTargetRepository } from '../results-toc-results/results-sdg-targets.respository'; +import { ResultsTocResultIndicatorsRepository } from '../results-toc-results/repositories/results-toc-results-indicators.repository'; +import { ResultsTocSdgTargetRepository } from '../results-toc-results/repositories/result-toc-sdg-target-repository'; +import { ResultsTocImpactAreaTargetRepository } from '../results-toc-results/repositories/result-toc-impact-area-repository'; +import { ResultsSdgTargetRepository } from '../results-toc-results/repositories/results-sdg-targets.respository'; import { RoleByUserRepository } from '../../../auth/modules/role-by-user/RoleByUser.repository'; -import { ResultsActionAreaOutcomeRepository } from '../results-toc-results/result-toc-action-area.repository'; -import { ResultsTocTargetIndicatorRepository } from '../results-toc-results/result-toc-result-target-indicator.repository'; +import { ResultsActionAreaOutcomeRepository } from '../results-toc-results/repositories/result-toc-action-area.repository'; +import { ResultsTocTargetIndicatorRepository } from '../results-toc-results/repositories/result-toc-result-target-indicator.repository'; import { TemplateRepository } from '../../platform-report/repositories/template.repository'; import { ClarisaInitiativesRepository } from '../../../clarisa/clarisa-initiatives/ClarisaInitiatives.repository'; import { ResultsTocResultsModule } from '../results-toc-results/results-toc-results.module'; diff --git a/onecgiar-pr-server/src/api/results/share-result-request/share-result-request.service.ts b/onecgiar-pr-server/src/api/results/share-result-request/share-result-request.service.ts index f9b0efe08..0d23ed722 100644 --- a/onecgiar-pr-server/src/api/results/share-result-request/share-result-request.service.ts +++ b/onecgiar-pr-server/src/api/results/share-result-request/share-result-request.service.ts @@ -13,7 +13,7 @@ import { ShareResultRequest } from './entities/share-result-request.entity'; import { ResultRepository } from '../result.repository'; import { ResultsByInititiative } from '../results_by_inititiatives/entities/results_by_inititiative.entity'; import { ResultByInitiativesRepository } from '../results_by_inititiatives/resultByInitiatives.repository'; -import { ResultsTocResultRepository } from '../results-toc-results/results-toc-results.repository'; +import { ResultsTocResultRepository } from '../results-toc-results/repositories/results-toc-results.repository'; import { ResultInitiativeBudgetRepository } from '../result_budget/repositories/result_initiative_budget.repository'; import { RoleByUserRepository } from '../../../auth/modules/role-by-user/RoleByUser.repository'; import { CreateShareResultRequestDto } from './dto/create-share-result-request.dto'; diff --git a/onecgiar-pr-server/src/api/versioning/versioning.module.ts b/onecgiar-pr-server/src/api/versioning/versioning.module.ts index 13d9a9e12..1de4922e1 100644 --- a/onecgiar-pr-server/src/api/versioning/versioning.module.ts +++ b/onecgiar-pr-server/src/api/versioning/versioning.module.ts @@ -11,7 +11,7 @@ import { ApplicationModulesRepository } from './repositories/application-modules import { ResultRepository } from '../results/result.repository'; import { NonPooledProjectRepository } from '../results/non-pooled-projects/non-pooled-projects.repository'; import { ResultsCenterRepository } from '../results/results-centers/results-centers.repository'; -import { ResultsTocResultRepository } from '../results/results-toc-results/results-toc-results.repository'; +import { ResultsTocResultRepository } from '../results/results-toc-results/repositories/results-toc-results.repository'; import { ResultByInitiativesRepository } from '../results/results_by_inititiatives/resultByInitiatives.repository'; import { ResultByIntitutionsRepository } from '../results/results_by_institutions/result_by_intitutions.repository'; import { ResultByInstitutionsByDeliveriesTypeRepository } from '../results/result-by-institutions-by-deliveries-type/result-by-institutions-by-deliveries-type.repository'; @@ -33,13 +33,13 @@ import { ResultsKnowledgeProductKeywordRepository } from '../results/results-kno import { ResultsKnowledgeProductMetadataRepository } from '../results/results-knowledge-products/repositories/results-knowledge-product-metadata.repository'; import { ResultsKnowledgeProductInstitutionRepository } from '../results/results-knowledge-products/repositories/results-knowledge-product-institution.repository'; import { RoleByUserRepository } from '../../auth/modules/role-by-user/RoleByUser.repository'; -import { ResultsTocResultIndicatorsRepository } from '../results/results-toc-results/results-toc-results-indicators.repository'; -import { ResultsTocImpactAreaTargetRepository } from '../results/results-toc-results/result-toc-impact-area-repository'; -import { ResultsTocSdgTargetRepository } from '../results/results-toc-results/result-toc-sdg-target-repository'; -import { ResultsSdgTargetRepository } from '../results/results-toc-results/results-sdg-targets.respository'; +import { ResultsTocResultIndicatorsRepository } from '../results/results-toc-results/repositories/results-toc-results-indicators.repository'; +import { ResultsTocImpactAreaTargetRepository } from '../results/results-toc-results/repositories/result-toc-impact-area-repository'; +import { ResultsTocSdgTargetRepository } from '../results/results-toc-results/repositories/result-toc-sdg-target-repository'; +import { ResultsSdgTargetRepository } from '../results/results-toc-results/repositories/results-sdg-targets.respository'; import { ResultStatusRepository } from '../results/result-status/result-status.repository'; -import { ResultsActionAreaOutcomeRepository } from '../results/results-toc-results/result-toc-action-area.repository'; -import { ResultsTocTargetIndicatorRepository } from '../results/results-toc-results/result-toc-result-target-indicator.repository'; +import { ResultsActionAreaOutcomeRepository } from '../results/results-toc-results/repositories/result-toc-action-area.repository'; +import { ResultsTocTargetIndicatorRepository } from '../results/results-toc-results/repositories/result-toc-result-target-indicator.repository'; import { ResultInitiativeBudgetRepository } from '../results/result_budget/repositories/result_initiative_budget.repository'; import { EvidenceSharepointRepository } from '../results/evidences/repositories/evidence-sharepoint.repository'; import { EvidencesService } from '../results/evidences/evidences.service'; diff --git a/onecgiar-pr-server/src/api/versioning/versioning.service.spec.ts b/onecgiar-pr-server/src/api/versioning/versioning.service.spec.ts index ae16dd098..5b8eb1938 100644 --- a/onecgiar-pr-server/src/api/versioning/versioning.service.spec.ts +++ b/onecgiar-pr-server/src/api/versioning/versioning.service.spec.ts @@ -14,7 +14,7 @@ import { ApplicationModulesRepository } from './repositories/application-modules import { ResultRepository } from '../results/result.repository'; import { NonPooledProjectRepository } from '../results/non-pooled-projects/non-pooled-projects.repository'; import { ResultsCenterRepository } from '../results/results-centers/results-centers.repository'; -import { ResultsTocResultRepository } from '../results/results-toc-results/results-toc-results.repository'; +import { ResultsTocResultRepository } from '../results/results-toc-results/repositories/results-toc-results.repository'; import { ResultByInitiativesRepository } from '../results/results_by_inititiatives/resultByInitiatives.repository'; import { ResultByIntitutionsRepository } from '../results/results_by_institutions/result_by_intitutions.repository'; import { ResultByInstitutionsByDeliveriesTypeRepository } from '../results/result-by-institutions-by-deliveries-type/result-by-institutions-by-deliveries-type.repository'; @@ -35,13 +35,13 @@ import { ResultsKnowledgeProductKeywordRepository } from '../results/results-kno import { ResultsKnowledgeProductMetadataRepository } from '../results/results-knowledge-products/repositories/results-knowledge-product-metadata.repository'; import { ResultsKnowledgeProductInstitutionRepository } from '../results/results-knowledge-products/repositories/results-knowledge-product-institution.repository'; import { RoleByUserRepository } from '../../auth/modules/role-by-user/RoleByUser.repository'; -import { ResultsTocResultIndicatorsRepository } from '../results/results-toc-results/results-toc-results-indicators.repository'; -import { ResultsTocSdgTargetRepository } from '../results/results-toc-results/result-toc-sdg-target-repository'; -import { ResultsTocImpactAreaTargetRepository } from '../results/results-toc-results/result-toc-impact-area-repository'; -import { ResultsSdgTargetRepository } from '../results/results-toc-results/results-sdg-targets.respository'; +import { ResultsTocResultIndicatorsRepository } from '../results/results-toc-results/repositories/results-toc-results-indicators.repository'; +import { ResultsTocSdgTargetRepository } from '../results/results-toc-results/repositories/result-toc-sdg-target-repository'; +import { ResultsTocImpactAreaTargetRepository } from '../results/results-toc-results/repositories/result-toc-impact-area-repository'; +import { ResultsSdgTargetRepository } from '../results/results-toc-results/repositories/results-sdg-targets.respository'; import { ResultStatusRepository } from '../results/result-status/result-status.repository'; -import { ResultsActionAreaOutcomeRepository } from '../results/results-toc-results/result-toc-action-area.repository'; -import { ResultsTocTargetIndicatorRepository } from '../results/results-toc-results/result-toc-result-target-indicator.repository'; +import { ResultsActionAreaOutcomeRepository } from '../results/results-toc-results/repositories/result-toc-action-area.repository'; +import { ResultsTocTargetIndicatorRepository } from '../results/results-toc-results/repositories/result-toc-result-target-indicator.repository'; import { ResultInitiativeBudgetRepository } from '../results/result_budget/repositories/result_initiative_budget.repository'; import { EvidenceSharepointRepository } from '../results/evidences/repositories/evidence-sharepoint.repository'; import { EvidencesService } from '../results/evidences/evidences.service'; diff --git a/onecgiar-pr-server/src/toc/toc-results/toc-results.module.ts b/onecgiar-pr-server/src/toc/toc-results/toc-results.module.ts index ee523ab86..b84a44fd4 100644 --- a/onecgiar-pr-server/src/toc/toc-results/toc-results.module.ts +++ b/onecgiar-pr-server/src/toc/toc-results/toc-results.module.ts @@ -8,7 +8,7 @@ import { ResultRepository } from '../../api/results/result.repository'; import { ApplicationModulesRepository } from '../../api/versioning/repositories/application-modules.repository'; import { NonPooledProjectRepository } from '../../api/results/non-pooled-projects/non-pooled-projects.repository'; import { ResultsCenterRepository } from '../../api/results/results-centers/results-centers.repository'; -import { ResultsTocResultRepository } from '../../api/results/results-toc-results/results-toc-results.repository'; +import { ResultsTocResultRepository } from '../../api/results/results-toc-results/repositories/results-toc-results.repository'; import { ResultByInitiativesRepository } from '../../api/results/results_by_inititiatives/resultByInitiatives.repository'; import { ResultsKnowledgeProductInstitutionRepository } from '../../api/results/results-knowledge-products/repositories/results-knowledge-product-institution.repository'; import { ResponseInterceptor } from '../../shared/Interceptors/Return-data.interceptor'; @@ -31,16 +31,16 @@ import { ResultsKnowledgeProductAuthorRepository } from '../../api/results/resul import { ResultsKnowledgeProductKeywordRepository } from '../../api/results/results-knowledge-products/repositories/results-knowledge-product-keywords.repository'; import { ResultsKnowledgeProductMetadataRepository } from '../../api/results/results-knowledge-products/repositories/results-knowledge-product-metadata.repository'; import { RoleByUserRepository } from '../../auth/modules/role-by-user/RoleByUser.repository'; -import { ResultsTocResultIndicatorsRepository } from '../../api/results/results-toc-results/results-toc-results-indicators.repository'; +import { ResultsTocResultIndicatorsRepository } from '../../api/results/results-toc-results/repositories/results-toc-results-indicators.repository'; import { HandlersError, ReturnResponse, } from '../../shared/handlers/error.utils'; -import { ResultsTocImpactAreaTargetRepository } from 'src/api/results/results-toc-results/result-toc-impact-area-repository'; -import { ResultsTocSdgTargetRepository } from 'src/api/results/results-toc-results/result-toc-sdg-target-repository'; -import { ResultsSdgTargetRepository } from 'src/api/results/results-toc-results/results-sdg-targets.respository'; -import { ResultsActionAreaOutcomeRepository } from 'src/api/results/results-toc-results/result-toc-action-area.repository'; -import { ResultsTocTargetIndicatorRepository } from 'src/api/results/results-toc-results/result-toc-result-target-indicator.repository'; +import { ResultsTocImpactAreaTargetRepository } from 'src/api/results/results-toc-results/repositories/result-toc-impact-area-repository'; +import { ResultsTocSdgTargetRepository } from 'src/api/results/results-toc-results/repositories/result-toc-sdg-target-repository'; +import { ResultsSdgTargetRepository } from 'src/api/results/results-toc-results/repositories/results-sdg-targets.respository'; +import { ResultsActionAreaOutcomeRepository } from 'src/api/results/results-toc-results/repositories/result-toc-action-area.repository'; +import { ResultsTocTargetIndicatorRepository } from 'src/api/results/results-toc-results/repositories/result-toc-result-target-indicator.repository'; import { ResultInitiativeBudgetRepository } from '../../api/results/result_budget/repositories/result_initiative_budget.repository'; import { EvidenceSharepointRepository } from '../../api/results/evidences/repositories/evidence-sharepoint.repository'; import { EvidencesService } from '../../api/results/evidences/evidences.service'; From cba1792a7b8f48456409ec9101988584210d8519 Mon Sep 17 00:00:00 2001 From: German Martinez Date: Fri, 8 Nov 2024 08:56:04 -0500 Subject: [PATCH 02/12] =?UTF-8?q?=E2=9C=A8feat(Contribution=20to=20Indicat?= =?UTF-8?q?or):=20adding=20new=20module=20for=20CoI=20#1=20(WIP):=20-=20cr?= =?UTF-8?q?eated=20migration=20-=20created=20entities=20-=20added=20dtos?= =?UTF-8?q?=20-=20added=20relations=20-=20implemented=20loading=20of=20out?= =?UTF-8?q?comes=20-=20implemented=20save/update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...tribution-to-indicators.controller.spec.ts | 20 ++ .../contribution-to-indicators.controller.ts | 41 ++++ .../contribution-to-indicators.module.ts | 19 ++ .../contribution-to-indicators.routes.ts | 9 + ...contribution-to-indicators.service.spec.ts | 18 ++ .../contribution-to-indicators.service.ts | 211 ++++++++++++++++++ .../contribution-to-indicator-results.dto.ts | 13 ++ .../dto/contribution-to-indicators.dto.ts | 9 + .../create-contribution-to-indicator.dto.ts | 1 + .../update-contribution-to-indicator.dto.ts | 4 + ...contribution-to-indicator-result.entity.ts | 40 ++++ .../contribution-to-indicator.entity.ts | 38 ++++ ...ribution-to-indicator-result.repository.ts | 74 ++++++ .../contribution-to-indicators.repository.ts | 18 ++ .../src/api/results/entities/result.entity.ts | 4 + onecgiar-pr-server/src/app.module.ts | 2 + onecgiar-pr-server/src/main.routes.ts | 5 + ...629367-addContributionToIndicatorTables.ts | 21 ++ 18 files changed, 547 insertions(+) create mode 100644 onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.spec.ts create mode 100644 onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts create mode 100644 onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.module.ts create mode 100644 onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.routes.ts create mode 100644 onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.spec.ts create mode 100644 onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.ts create mode 100644 onecgiar-pr-server/src/api/contribution-to-indicators/dto/contribution-to-indicator-results.dto.ts create mode 100644 onecgiar-pr-server/src/api/contribution-to-indicators/dto/contribution-to-indicators.dto.ts create mode 100644 onecgiar-pr-server/src/api/contribution-to-indicators/dto/create-contribution-to-indicator.dto.ts create mode 100644 onecgiar-pr-server/src/api/contribution-to-indicators/dto/update-contribution-to-indicator.dto.ts create mode 100644 onecgiar-pr-server/src/api/contribution-to-indicators/entities/contribution-to-indicator-result.entity.ts create mode 100644 onecgiar-pr-server/src/api/contribution-to-indicators/entities/contribution-to-indicator.entity.ts create mode 100644 onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicator-result.repository.ts create mode 100644 onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicators.repository.ts create mode 100644 onecgiar-pr-server/src/migrations/1730929629367-addContributionToIndicatorTables.ts diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.spec.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.spec.ts new file mode 100644 index 000000000..bc2e4b6a1 --- /dev/null +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.spec.ts @@ -0,0 +1,20 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { ContributionToIndicatorsController } from './contribution-to-indicators.controller'; +import { ContributionToIndicatorsService } from './contribution-to-indicators.service'; + +describe('ContributionToIndicatorsController', () => { + let controller: ContributionToIndicatorsController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [ContributionToIndicatorsController], + providers: [ContributionToIndicatorsService], + }).compile(); + + controller = module.get(ContributionToIndicatorsController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts new file mode 100644 index 000000000..47ed06c5d --- /dev/null +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts @@ -0,0 +1,41 @@ +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Query, +} from '@nestjs/common'; +import { ContributionToIndicatorsService } from './contribution-to-indicators.service'; +import { UserToken } from '../../shared/decorators/user-token.decorator'; +import { TokenDto } from '../../shared/globalInterfaces/token.dto'; +import { ContributionToIndicatorsDto } from './dto/contribution-to-indicators.dto'; + +@Controller() +export class ContributionToIndicatorsController { + constructor( + private readonly contributionToIndicatorsService: ContributionToIndicatorsService, + ) {} + + @Post() + create(@Query() tocId: string, @UserToken() user: TokenDto) { + return this.contributionToIndicatorsService.create(tocId, user); + } + + @Get('get/:id') + findOne(@Param('tocId') tocId: string) { + return this.contributionToIndicatorsService.findOne(tocId); + } + + @Patch() + update( + @Body() updateContributionToIndicatorDto: ContributionToIndicatorsDto, + @UserToken() user: TokenDto, + ) { + return this.contributionToIndicatorsService.update( + updateContributionToIndicatorDto, + user, + ); + } +} diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.module.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.module.ts new file mode 100644 index 000000000..7c9d6a49d --- /dev/null +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.module.ts @@ -0,0 +1,19 @@ +import { Module } from '@nestjs/common'; +import { ContributionToIndicatorsService } from './contribution-to-indicators.service'; +import { ContributionToIndicatorsController } from './contribution-to-indicators.controller'; +import { ContributionToIndicatorsRepository } from './repositories/contribution-to-indicators.repository'; +import { ContributionToIndicatorResultsRepository } from './repositories/contribution-to-indicator-result.repository'; +import { HandlersError } from '../../shared/handlers/error.utils'; +import { UserRepository } from '../../auth/modules/user/repositories/user.repository'; + +@Module({ + controllers: [ContributionToIndicatorsController], + providers: [ + ContributionToIndicatorsService, + ContributionToIndicatorsRepository, + ContributionToIndicatorResultsRepository, + HandlersError, + UserRepository, + ], +}) +export class ContributionToIndicatorsModule {} diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.routes.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.routes.ts new file mode 100644 index 000000000..457aa4c79 --- /dev/null +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.routes.ts @@ -0,0 +1,9 @@ +import { Routes } from '@nestjs/core'; +import { ContributionToIndicatorsModule } from './contribution-to-indicators.module'; + +export const ContributionToIndicatorRoutes: Routes = [ + { + path: '', + module: ContributionToIndicatorsModule, + }, +]; diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.spec.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.spec.ts new file mode 100644 index 000000000..0f540ff14 --- /dev/null +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { ContributionToIndicatorsService } from './contribution-to-indicators.service'; + +describe('ContributionToIndicatorsService', () => { + let service: ContributionToIndicatorsService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ContributionToIndicatorsService], + }).compile(); + + service = module.get(ContributionToIndicatorsService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.ts new file mode 100644 index 000000000..44c75a094 --- /dev/null +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.ts @@ -0,0 +1,211 @@ +import { HttpStatus, Injectable, Logger } from '@nestjs/common'; +import { ContributionToIndicatorsRepository } from './repositories/contribution-to-indicators.repository'; +import { ContributionToIndicatorResultsRepository } from './repositories/contribution-to-indicator-result.repository'; +import { HandlersError } from '../../shared/handlers/error.utils'; +import { TokenDto } from '../../shared/globalInterfaces/token.dto'; +import { ContributionToIndicatorsDto } from './dto/contribution-to-indicators.dto'; +import { ContributionToIndicatorResult } from './entities/contribution-to-indicator-result.entity'; +import { ContributionToIndicator } from './entities/contribution-to-indicator.entity'; +import { ContributionToIndicatorResultsDto } from './dto/contribution-to-indicator-results.dto'; + +@Injectable() +export class ContributionToIndicatorsService { + private readonly _logger: Logger = new Logger( + ContributionToIndicatorsService.name, + ); + constructor( + private readonly _contributionToIndicatorsRepository: ContributionToIndicatorsRepository, + private readonly _contributionToIndicatorResultsRepository: ContributionToIndicatorResultsRepository, + private readonly _handlersError: HandlersError, + ) {} + + async create(tocId: string, user: TokenDto) { + try { + if (!tocId?.length) { + throw { + response: {}, + message: 'missing data: tocId', + status: HttpStatus.BAD_REQUEST, + }; + } + + let contribution: ContributionToIndicator = + await this._contributionToIndicatorsRepository.findOneBy({ + toc_result_id: tocId, + }); + + if (contribution) { + if (contribution.is_active) { + throw { + response: {}, + message: `Contribution to indicator with tocId "${tocId}" already exists`, + status: HttpStatus.CONFLICT, + }; + } + contribution.is_active = true; + } else { + contribution = await this._contributionToIndicatorsRepository.save({ + created_by: user.id, + toc_result_id: tocId, + }); + } + + return this.update(contribution, user); + } catch (error) { + return this._handlersError.returnErrorRes({ error }); + } + } + + async findOne(tocId: string) { + try { + if (!tocId?.length) { + throw { + response: {}, + message: 'missing data: tocId', + status: HttpStatus.BAD_REQUEST, + }; + } + + const contributionToIndicator = + await (this._contributionToIndicatorsRepository.findOneBy({ + toc_result_id: tocId, + is_active: true, + }) as Promise); + + if (!contributionToIndicator) { + throw { + response: {}, + message: `Contribution to indicator with tocId "${tocId}" not found`, + status: HttpStatus.NOT_FOUND, + }; + } + + contributionToIndicator.contributing_results = + await this._contributionToIndicatorResultsRepository.findResultContributionsByTocId( + contributionToIndicator.toc_result_id, + ); + + return { + contributionToIndicator, + message: 'The Contributor to Indicator has been found.', + status: HttpStatus.OK, + }; + } catch (error) { + return this._handlersError.returnErrorRes({ error }); + } + } + + async update( + contributionToIndicatorDto: ContributionToIndicatorsDto, + userDto: TokenDto, + ) { + try { + if (!contributionToIndicatorDto.id) { + throw { + response: {}, + message: 'missing data: id', + status: HttpStatus.BAD_REQUEST, + }; + } + + const contributionToIndicator = + await this._contributionToIndicatorsRepository.findOne({ + where: { id: contributionToIndicatorDto.id, is_active: true }, + relations: { contribution_to_indicator_result_array: true }, + }); + + if (!contributionToIndicator) { + throw { + response: {}, + message: `Contribution to indicator with id "${contributionToIndicatorDto.id}" not found`, + status: HttpStatus.NOT_FOUND, + }; + } + + await this._contributionToIndicatorsRepository.update( + contributionToIndicatorDto.id, + { + last_updated_by: userDto.id, + achieved_in_2024: contributionToIndicatorDto.achieved_in_2024, + narrative_achieved_in_2024: + contributionToIndicatorDto.narrative_achieved_in_2024, + }, + ); + + await this.handleContributingResults( + contributionToIndicatorDto, + userDto, + contributionToIndicator, + ); + + return { + contributionToIndicator, + message: 'The Contributor to Indicator has been updated.', + status: HttpStatus.OK, + }; + } catch (error) { + return this._handlersError.returnErrorRes({ error }); + } + } + + private async handleContributingResults( + contributionToIndicatorDto: ContributionToIndicatorsDto, + userDto: TokenDto, + contributionToIndicator: ContributionToIndicator, + ) { + function recursive( + contributingResults: ContributionToIndicatorResultsDto[], + processedContributingResults: ContributionToIndicatorResult[] = [], + ): ContributionToIndicatorResult[] { + for (const result of contributingResults) { + let contributingResult: ContributionToIndicatorResult = null; + if (!result.contribution_id) { + contributingResult = + this._contributionToIndicatorResultsRepository.create({ + created_by: userDto.id, + contribution_to_indicator_id: contributionToIndicatorDto.id, + result_id: result.result_id, + }); + } else { + contributingResult = + contributionToIndicator.contribution_to_indicator_result_array.find( + (ctir) => ctir.id === result.contribution_id, + ); + } + + if (!contributingResult) { + throw { + response: {}, + message: `Contribution to indicator result with id "${result.contribution_id}" not found`, + status: HttpStatus.NOT_FOUND, + }; + } + + contributingResult.is_active = true; + contributingResult.last_updated_by = userDto.id; + + processedContributingResults.push(contributingResult); + + if (result.linked_results) { + processedContributingResults.push( + ...recursive(result.linked_results, processedContributingResults), + ); + } + + return processedContributingResults; + } + } + + const contributingResultArray: ContributionToIndicatorResult[] = recursive( + contributionToIndicatorDto.contributing_results, + ); + + await this._contributionToIndicatorResultsRepository.save( + contributingResultArray, + ); + } + + remove(id: number) { + return `This action removes a #${id} contributionToIndicator`; + } +} diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/dto/contribution-to-indicator-results.dto.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/dto/contribution-to-indicator-results.dto.ts new file mode 100644 index 000000000..2946563b6 --- /dev/null +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/dto/contribution-to-indicator-results.dto.ts @@ -0,0 +1,13 @@ +export class ContributionToIndicatorResultsDto { + contribution_id: number; + result_id: number; + result_title: string; + result_code: number; + phase_name: string; + result_type: string; + result_submitter: string; + result_status: string; + result_creation_date: string; + result_link: string; + linked_results?: ContributionToIndicatorResultsDto[]; +} diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/dto/contribution-to-indicators.dto.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/dto/contribution-to-indicators.dto.ts new file mode 100644 index 000000000..7f43d0921 --- /dev/null +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/dto/contribution-to-indicators.dto.ts @@ -0,0 +1,9 @@ +import { ContributionToIndicatorResultsDto } from './contribution-to-indicator-results.dto'; + +export class ContributionToIndicatorsDto { + id: number; + toc_result_id: string; + achieved_in_2024: number; + narrative_achieved_in_2024: string; + contributing_results?: ContributionToIndicatorResultsDto[]; +} diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/dto/create-contribution-to-indicator.dto.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/dto/create-contribution-to-indicator.dto.ts new file mode 100644 index 000000000..60ba21130 --- /dev/null +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/dto/create-contribution-to-indicator.dto.ts @@ -0,0 +1 @@ +export class CreateContributionToIndicatorDto {} diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/dto/update-contribution-to-indicator.dto.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/dto/update-contribution-to-indicator.dto.ts new file mode 100644 index 000000000..43b8bf7d1 --- /dev/null +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/dto/update-contribution-to-indicator.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/swagger'; +import { CreateContributionToIndicatorDto } from './create-contribution-to-indicator.dto'; + +export class UpdateContributionToIndicatorDto extends PartialType(CreateContributionToIndicatorDto) {} diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/entities/contribution-to-indicator-result.entity.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/entities/contribution-to-indicator-result.entity.ts new file mode 100644 index 000000000..af502db73 --- /dev/null +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/entities/contribution-to-indicator-result.entity.ts @@ -0,0 +1,40 @@ +import { + Column, + Entity, + JoinColumn, + ManyToOne, + PrimaryGeneratedColumn, +} from 'typeorm'; +import { BaseEntity } from '../../../shared/entities/base-entity'; +import { ContributionToIndicator } from './contribution-to-indicator.entity'; +import { Result } from '../../results/entities/result.entity'; + +@Entity('contribution_to_indicator_results') +export class ContributionToIndicatorResult extends BaseEntity { + @PrimaryGeneratedColumn() + id: number; + + @Column({ + type: 'bigint', + name: 'contribution_to_indicator_id', + }) + contribution_to_indicator_id: number; + + @Column({ + type: 'bigint', + name: 'result_id', + }) + result_id: number; + + //object relations + @ManyToOne( + () => ContributionToIndicator, + (cti) => cti.contribution_to_indicator_result_array, + ) + @JoinColumn({ name: 'contribution_to_indicator_id' }) + contribution_to_indicator_object: ContributionToIndicator; + + @ManyToOne(() => Result, (r) => r.contribution_to_indicator_result_array) + @JoinColumn({ name: 'result_id' }) + result_object: Result; +} diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/entities/contribution-to-indicator.entity.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/entities/contribution-to-indicator.entity.ts new file mode 100644 index 000000000..e650fc173 --- /dev/null +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/entities/contribution-to-indicator.entity.ts @@ -0,0 +1,38 @@ +import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; +import { BaseEntity } from '../../../shared/entities/base-entity'; +import { ContributionToIndicatorResult } from './contribution-to-indicator-result.entity'; + +@Entity('contribution_to_indicators') +export class ContributionToIndicator extends BaseEntity { + @PrimaryGeneratedColumn() + id: number; + + @Column({ + type: 'varchar', + length: 255, + name: 'toc_result_id', + unique: true, + }) + toc_result_id: string; + + @Column({ + type: 'bigint', + name: 'achieved_in_2024', + nullable: true, + }) + achieved_in_2024: number; + + @Column({ + type: 'text', + name: 'narrative_achieved_in_2024', + nullable: true, + }) + narrative_achieved_in_2024: string; + + //object relations + @OneToMany( + () => ContributionToIndicatorResult, + (ctir) => ctir.contribution_to_indicator_object, + ) + contribution_to_indicator_result_array: ContributionToIndicatorResult[]; +} diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicator-result.repository.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicator-result.repository.ts new file mode 100644 index 000000000..e642dce21 --- /dev/null +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicator-result.repository.ts @@ -0,0 +1,74 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { ContributionToIndicatorResult } from '../entities/contribution-to-indicator-result.entity'; +import { DataSource, Repository } from 'typeorm'; +import { HandlersError } from '../../../shared/handlers/error.utils'; +import { ContributionToIndicatorResultsDto } from '../dto/contribution-to-indicator-results.dto'; + +@Injectable() +export class ContributionToIndicatorResultsRepository extends Repository { + private readonly _logger: Logger = new Logger( + ContributionToIndicatorResultsRepository.name, + ); + + constructor( + private dataSource: DataSource, + private readonly _handlersError: HandlersError, + ) { + super(ContributionToIndicatorResult, dataSource.createEntityManager()); + } + + async findResultContributionsByTocId( + tocId: string, + ): Promise { + const dataQuery = ` + select main_ctir.id as contribution_id, main_r.id as result_id, main_r.result_code, main_r.title as result_title, + main_v.phase_name, main_rt.name as result_type, main_ci.official_code as result_submitter, + main_rs.status_name as result_status, date_format(main_r.created_date, '%Y-%m-%d') as result_creation_date, + ( + select json_arrayagg(json_object( + "contribution_id", linked_ctir.id, + "result_id", linked_r.id, + "result_code", linked_r.result_code, + "result_title", linked_r.title, + "phase_name", linked_v.phase_name, + "result_type", linked_rt.name, + "result_submitter", linked_ci.official_code, + "result_status", linked_rs.status_name, + "result_creation_date", date_format(linked_r.created_date, '%Y-%m-%d') + )) + from prdb.linked_result lr + left join prdb.result linked_r on linked_r.id = lr.linked_results_id and linked_r.is_active + left join prdb.contribution_to_indicator_results linked_ctir on linked_ctir.result_id = linked_r.id + and linked_ctir.is_active + left join prdb.\`version\` linked_v on linked_r.version_id = linked_v.id + left join prdb.result_type linked_rt on linked_r.result_type_id = linked_rt.id + left join prdb.results_by_inititiative linked_rbi on linked_rbi.result_id = linked_r.id and linked_rbi.initiative_role_id = 1 + left join prdb.clarisa_initiatives linked_ci on linked_ci.id = linked_rbi.inititiative_id + left join prdb.result_status linked_rs on linked_rs.result_status_id = linked_r.status_id + where lr.origin_result_id = main_r.id and lr.is_active + group by main_r.id + ) as linked_results + from Integration_information.toc_results outcomes + right join prdb.results_toc_result rtr on rtr.toc_result_id = outcomes.id and rtr.is_active + left join prdb.result main_r on main_r.id = rtr.results_id and main_r.is_active + left join prdb.contribution_to_indicator_results main_ctir on main_ctir.result_id = main_r.id and main_ctir.is_active + left join prdb.\`version\` main_v on main_r.version_id = main_v.id + left join prdb.result_type main_rt on main_r.result_type_id = main_rt.id + left join prdb.results_by_inititiative main_rbi on main_rbi.result_id = main_r.id and main_rbi.initiative_role_id = 1 + left join prdb.clarisa_initiatives main_ci on main_ci.id = main_rbi.inititiative_id + left join prdb.result_status main_rs on main_rs.result_status_id = main_r.status_id + where outcomes.toc_result_id = ? and outcomes.is_active + `; + + return this.dataSource + .query(dataQuery, [tocId]) + .then((result) => result) + .catch((err) => + this._handlersError.returnErrorRepository({ + error: err, + className: ContributionToIndicatorResultsRepository.name, + debug: true, + }), + ); + } +} diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicators.repository.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicators.repository.ts new file mode 100644 index 000000000..02f40cbda --- /dev/null +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicators.repository.ts @@ -0,0 +1,18 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { ContributionToIndicator } from '../entities/contribution-to-indicator.entity'; +import { DataSource, Repository } from 'typeorm'; +import { HandlersError } from '../../../shared/handlers/error.utils'; + +@Injectable() +export class ContributionToIndicatorsRepository extends Repository { + private readonly _logger: Logger = new Logger( + ContributionToIndicatorsRepository.name, + ); + + constructor( + private dataSource: DataSource, + private readonly _handlersError: HandlersError, + ) { + super(ContributionToIndicator, dataSource.createEntityManager()); + } +} diff --git a/onecgiar-pr-server/src/api/results/entities/result.entity.ts b/onecgiar-pr-server/src/api/results/entities/result.entity.ts index 7c70131f1..088481648 100644 --- a/onecgiar-pr-server/src/api/results/entities/result.entity.ts +++ b/onecgiar-pr-server/src/api/results/entities/result.entity.ts @@ -29,6 +29,7 @@ import { ResultsByInstitution } from '../results_by_institutions/entities/result import { ShareResultRequest } from '../share-result-request/entities/share-result-request.entity'; import { ResultsTocResult } from '../results-toc-results/entities/results-toc-result.entity'; import { Notification } from '../../notification/entities/notification.entity'; +import { ContributionToIndicatorResult } from '../../contribution-to-indicators/entities/contribution-to-indicator-result.entity'; @Entity() export class Result { @@ -392,4 +393,7 @@ export class Result { @OneToMany(() => Notification, (ra) => ra.obj_result) obj_result_notification: Notification[]; + + @OneToMany(() => ContributionToIndicatorResult, (r) => r.result_object) + contribution_to_indicator_result_array: ContributionToIndicatorResult[]; } diff --git a/onecgiar-pr-server/src/app.module.ts b/onecgiar-pr-server/src/app.module.ts index 77483f66e..be27776b1 100644 --- a/onecgiar-pr-server/src/app.module.ts +++ b/onecgiar-pr-server/src/app.module.ts @@ -41,6 +41,7 @@ import { SharePointModule } from './shared/services/share-point/share-point.modu import { NotificationModule } from './api/notification/notification.module'; import { UserNotificationSettingsModule } from './api/user-notification-settings/user-notification-settings.module'; import { EmailNotificationManagementModule } from './shared/microservices/email-notification-management/email-notification-management.module'; +import { ContributionToIndicatorsModule } from './api/contribution-to-indicators/contribution-to-indicators.module'; @Module({ imports: [ @@ -78,6 +79,7 @@ import { EmailNotificationManagementModule } from './shared/microservices/email- UserNotificationSettingsModule, EmailNotificationManagementModule, NotificationModule, + ContributionToIndicatorsModule, ], controllers: [AppController], providers: [ diff --git a/onecgiar-pr-server/src/main.routes.ts b/onecgiar-pr-server/src/main.routes.ts index 311d5bfae..e30f6c224 100644 --- a/onecgiar-pr-server/src/main.routes.ts +++ b/onecgiar-pr-server/src/main.routes.ts @@ -6,6 +6,7 @@ import { ModulesRoutes } from './api/modules.routes'; import { TocRoutes } from './toc/toc.routes'; import { ResultDashboardBIRoutes } from './result-dashboard-bi/result-dashboard-bi.routes'; import { dynamoRoutes } from './connection/dynamoRoutes.routes'; +import { ContributionToIndicatorRoutes } from './api/contribution-to-indicators/contribution-to-indicators.routes'; export const MainRoutes: Routes = [ { @@ -33,4 +34,8 @@ export const MainRoutes: Routes = [ path: 'logs', children: dynamoRoutes, }, + { + path: 'contribution-to-indicators', + children: ContributionToIndicatorRoutes, + }, ]; diff --git a/onecgiar-pr-server/src/migrations/1730929629367-addContributionToIndicatorTables.ts b/onecgiar-pr-server/src/migrations/1730929629367-addContributionToIndicatorTables.ts new file mode 100644 index 000000000..2b32c266f --- /dev/null +++ b/onecgiar-pr-server/src/migrations/1730929629367-addContributionToIndicatorTables.ts @@ -0,0 +1,21 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddContributionToIndicatorTables1730929629367 implements MigrationInterface { + name = 'AddContributionToIndicatorTables1730929629367' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE \`contribution_to_indicators\` (\`is_active\` tinyint NOT NULL DEFAULT 1, \`created_date\` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`last_updated_date\` timestamp(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`created_by\` bigint NULL, \`last_updated_by\` bigint NULL, \`id\` int NOT NULL AUTO_INCREMENT, \`toc_result_id\` varchar(255) NOT NULL, \`achieved_in_2024\` bigint NULL, \`narrative_achieved_in_2024\` text NULL, UNIQUE INDEX \`IDX_5ac195983e11c09df28f9efba4\` (\`toc_result_id\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`contribution_to_indicator_results\` (\`is_active\` tinyint NOT NULL DEFAULT 1, \`created_date\` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`last_updated_date\` timestamp(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`created_by\` bigint NULL, \`last_updated_by\` bigint NULL, \`id\` int NOT NULL AUTO_INCREMENT, \`contribution_to_indicator_id\` int NOT NULL, \`result_id\` bigint NOT NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`ALTER TABLE \`contribution_to_indicator_results\` ADD CONSTRAINT \`FK_e9031d6f6f045909feb83658875\` FOREIGN KEY (\`contribution_to_indicator_id\`) REFERENCES \`contribution_to_indicators\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE \`contribution_to_indicator_results\` ADD CONSTRAINT \`FK_261565558607cad5454848c3f1d\` FOREIGN KEY (\`result_id\`) REFERENCES \`result\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`contribution_to_indicator_results\` DROP FOREIGN KEY \`FK_261565558607cad5454848c3f1d\``); + await queryRunner.query(`ALTER TABLE \`contribution_to_indicator_results\` DROP FOREIGN KEY \`FK_e9031d6f6f045909feb83658875\``); + await queryRunner.query(`DROP TABLE \`contribution_to_indicator_results\``); + await queryRunner.query(`DROP INDEX \`IDX_5ac195983e11c09df28f9efba4\` ON \`contribution_to_indicators\``); + await queryRunner.query(`DROP TABLE \`contribution_to_indicators\``); + } + +} From 7e76883166ae061802a1c6f3b063f4a4a3c6a258 Mon Sep 17 00:00:00 2001 From: xKeCo Date: Fri, 8 Nov 2024 14:44:28 -0500 Subject: [PATCH 03/12] =?UTF-8?q?=E2=9C=A8feat(OutcomeIndicator)=20P2-903:?= =?UTF-8?q?=20implement=20initiative=20filter=20and=20phase=20display=20in?= =?UTF-8?q?=20outcome=20indicator=20module=20layout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outcome-indicator.component.html | 23 +++++++++++ .../outcome-indicator.component.scss | 39 +++++++++++++++++++ .../outcome-indicator.component.ts | 25 +++++++++++- .../outcome-indicator.module.ts | 3 +- .../outcome-indicator-home.component.html | 23 ----------- .../outcome-indicator-home.component.scss | 36 ----------------- 6 files changed, 88 insertions(+), 61 deletions(-) diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.html b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.html index e071df7f8..2abd741ee 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.html +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.html @@ -1,3 +1,26 @@
+
+ + + +
+

Phase:

+

+ {{ this.api.dataControlSE.reportingCurrentPhase.phaseName }} +

+
+
+ +
+
diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.scss b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.scss index 4d3f05ba1..1b02efad0 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.scss +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.scss @@ -4,3 +4,42 @@ padding-top: 15px !important; padding-bottom: 50px; } + +p { + margin: 0; +} + +.filters { + display: grid; + grid-template-columns: 1fr 300px; + gap: 2rem; + padding: 0; + + .filters_phase { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + + .filters_phase_title { + margin-top: 20px; + margin-bottom: 7px; + text-align: left; + font-size: 1.1em; + font-weight: 500; + color: #5569dd; + } + + .filters_phase_text { + padding: 6px 0; + font-size: 15px; + } + } +} + +.separator_line { + margin-top: 20px; + margin-bottom: 20px; + border-top: 2px solid #5569dd; + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2); +} diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.ts index 7b51742ef..6dfd1c072 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.ts @@ -1,8 +1,31 @@ import { Component } from '@angular/core'; +import { ApiService } from '../../shared/services/api/api.service'; @Component({ selector: 'app-outcome-indicator-module', templateUrl: './outcome-indicator.component.html', styleUrl: './outcome-indicator.component.scss' }) -export class OutcomeIndicatorComponent {} +export class OutcomeIndicatorComponent { + initiativeIdFilter = null; + allInitiatives = []; + + constructor(public api: ApiService) {} + + ngOnInit() { + this.GET_AllInitiatives(); + this.api.dataControlSE.getCurrentPhases(); + + if (!this.api.rolesSE.isAdmin) { + this.initiativeIdFilter = this.api.dataControlSE.myInitiativesList[0]?.initiative_id; + } + } + + GET_AllInitiatives() { + if (!this.api.rolesSE.isAdmin) return; + this.api.resultsSE.GET_AllInitiatives().subscribe(({ response }) => { + this.allInitiatives = response; + this.initiativeIdFilter = this.allInitiatives[0]?.initiative_id; + }); + } +} diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.module.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.module.ts index bded44caa..052f8a8d5 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.module.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.module.ts @@ -3,9 +3,10 @@ import { CommonModule } from '@angular/common'; import { OutcomeIndicatorComponent } from './outcome-indicator.component'; import { OutcomeIndicatorRoutingModule } from './outcome-indicator-routing.module'; +import { CustomFieldsModule } from '../../custom-fields/custom-fields.module'; @NgModule({ declarations: [OutcomeIndicatorComponent], - imports: [CommonModule, OutcomeIndicatorRoutingModule] + imports: [CommonModule, OutcomeIndicatorRoutingModule, CustomFieldsModule] }) export class OutcomeIndicatorModule {} diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.html b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.html index 646cad442..e3abf907a 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.html +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.html @@ -1,26 +1,3 @@ -
- - - -
-

Phase:

-

- {{ this.api.dataControlSE.reportingCurrentPhase.phaseName }} -

-
-
- -
-
assessment diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.scss b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.scss index 3608a12cd..e86fcb03b 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.scss +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.scss @@ -2,42 +2,6 @@ p { margin: 0; } -.filters { - display: grid; - grid-template-columns: 1fr 300px; - gap: 2rem; - padding: 0; - - .filters_phase { - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: flex-start; - - .filters_phase_title { - margin-top: 20px; - margin-bottom: 7px; - text-align: left; - font-size: 1.1em; - font-weight: 500; - color: #5569dd; - } - - .filters_phase_text { - padding: 6px 0; - font-size: 15px; - } - } -} - -.separator_line { - margin-top: 20px; - margin-bottom: 20px; - border-top: 2px solid #5569dd; - // Bottom shadow - box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2); -} - .outcomes { display: flex; flex-direction: column; From 116751d7cdb58bb4970ea62873f630b32a7bbdc4 Mon Sep 17 00:00:00 2001 From: Kevin Collazos Date: Fri, 8 Nov 2024 15:36:32 -0500 Subject: [PATCH 04/12] =?UTF-8?q?=E2=9C=A8feat(OutcomeIndicator)=20P2-903:?= =?UTF-8?q?=20refactor=20routing=20and=20add=20new=20components=20for=20En?= =?UTF-8?q?d-of-Initiative=20and=20Work=20Packages=20outcomes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pages/eioi-home/eoio-home.component.html | 2 ++ .../pages/eioi-home/eoio-home.component.scss | 0 .../eioi-home/eoio-home.component.spec.ts | 23 ++++++++++++++++++ .../pages/eioi-home/eoio-home.component.ts | 12 ++++++++++ .../outcome-indicator-home-routing.module.ts | 11 --------- .../outcome-indicator-home.component.html | 10 ++++++-- .../outcome-indicator-home.component.ts | 6 ++++- .../outcome-indicator-home.module.ts | 12 ---------- .../pages/wp-home/wp-home.component.html | 2 ++ .../pages/wp-home/wp-home.component.scss | 0 .../pages/wp-home/wp-home.component.spec.ts | 23 ++++++++++++++++++ .../pages/wp-home/wp-home.component.ts | 13 ++++++++++ .../src/app/shared/routing/routing-data.ts | 24 ++++++++++++------- 13 files changed, 103 insertions(+), 35 deletions(-) create mode 100644 onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html create mode 100644 onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.scss create mode 100644 onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.spec.ts create mode 100644 onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.ts delete mode 100644 onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home-routing.module.ts delete mode 100644 onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.module.ts create mode 100644 onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.html create mode 100644 onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.scss create mode 100644 onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.spec.ts create mode 100644 onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.ts diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html new file mode 100644 index 000000000..530bd18af --- /dev/null +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html @@ -0,0 +1,2 @@ +

eioi-home works!

+, diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.scss b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.spec.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.spec.ts new file mode 100644 index 000000000..54ec5c6b2 --- /dev/null +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { EoioHomeComponent } from './eoio-home.component'; +import { CommonModule } from '@angular/common'; + +describe('EoioHomeComponent', () => { + let component: EoioHomeComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [CommonModule, EoioHomeComponent], + declarations: [] + }).compileComponents(); + + fixture = TestBed.createComponent(EoioHomeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.ts new file mode 100644 index 000000000..ad10089f7 --- /dev/null +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.ts @@ -0,0 +1,12 @@ +import { CommonModule } from '@angular/common'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'app-eioi-home', + standalone: true, + imports: [CommonModule], + templateUrl: './eoio-home.component.html', + styleUrl: './eoio-home.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class EoioHomeComponent {} diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home-routing.module.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home-routing.module.ts deleted file mode 100644 index 72dd82cb2..000000000 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home-routing.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; -import { OutcomeIndicatorHomeComponent } from './outcome-indicator-home.component'; - -const routes: Routes = [{ path: '', component: OutcomeIndicatorHomeComponent }]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class OutcomeIndicatorHomeRoutingModule {} diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.html b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.html index e3abf907a..60adc6053 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.html +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.html @@ -7,12 +7,18 @@

Outcome Indicator Module

Welcome to the Outcome indicators reporting module. Please select an action you would like to do.

-
+

Report progress on End-Of-Initiative Outcomes

-
+

Report progress on Work Packages Outcomes

diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.ts index 4a67fb5ec..9842802ba 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.ts @@ -1,10 +1,14 @@ import { Component, OnInit } from '@angular/core'; import { ApiService } from '../../../../shared/services/api/api.service'; +import { CommonModule, NgClass } from '@angular/common'; +import { RouterLink } from '@angular/router'; @Component({ selector: 'app-outcome-indicator-home', templateUrl: './outcome-indicator-home.component.html', - styleUrl: './outcome-indicator-home.component.scss' + styleUrl: './outcome-indicator-home.component.scss', + standalone: true, + imports: [NgClass, RouterLink] }) export class OutcomeIndicatorHomeComponent implements OnInit { initiativeIdFilter = null; diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.module.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.module.ts deleted file mode 100644 index 2ca2c752d..000000000 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -import { OutcomeIndicatorHomeComponent } from './outcome-indicator-home.component'; -import { OutcomeIndicatorHomeRoutingModule } from './outcome-indicator-home-routing.module'; -import { CustomFieldsModule } from '../../../../custom-fields/custom-fields.module'; - -@NgModule({ - declarations: [OutcomeIndicatorHomeComponent], - imports: [CommonModule, OutcomeIndicatorHomeRoutingModule, CustomFieldsModule] -}) -export class OutcomeIndicatorHomeModule {} diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.html b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.html new file mode 100644 index 000000000..3982dc0ae --- /dev/null +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.html @@ -0,0 +1,2 @@ +

wp-home works!

+, diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.scss b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.spec.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.spec.ts new file mode 100644 index 000000000..baea435c1 --- /dev/null +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { WpHomeComponent } from './wp-home.component'; +import { CommonModule } from '@angular/common'; + +describe('WpHomeComponent', () => { + let component: WpHomeComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [CommonModule, WpHomeComponent], + declarations: [] + }).compileComponents(); + + fixture = TestBed.createComponent(WpHomeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.ts new file mode 100644 index 000000000..293ad881b --- /dev/null +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.ts @@ -0,0 +1,13 @@ +import { CommonModule } from '@angular/common'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +@Component({ + selector: 'app-wp-home', + standalone: true, + imports: [CommonModule, RouterModule], + templateUrl: './wp-home.component.html', + styleUrl: './wp-home.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class WpHomeComponent {} diff --git a/onecgiar-pr-client/src/app/shared/routing/routing-data.ts b/onecgiar-pr-client/src/app/shared/routing/routing-data.ts index 6101b7ebe..16a5006b9 100644 --- a/onecgiar-pr-client/src/app/shared/routing/routing-data.ts +++ b/onecgiar-pr-client/src/app/shared/routing/routing-data.ts @@ -369,15 +369,21 @@ export const OutcomeIndicatorRouting: PrRoute[] = [ prName: 'Outcome indicators home', underConstruction: false, path: 'home', - loadChildren: () => - import('../../pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.module').then(m => m.OutcomeIndicatorHomeModule) - }, - // { - // prName: 'Report progress on End-of-initiative outcome', - // underConstruction: false, - // path: 'report-progress-eoi-outcome', - // loadChildren: () => import('../../pages/type-one-report/pages/tor-fact-sheet/tor-fact-sheet.module').then(m => m.TorFactSheetModule) - // } + loadComponent: () => + import('../../pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component').then(m => m.OutcomeIndicatorHomeComponent) + }, + { + prName: 'Report progress on End-of-initiative outcome', + underConstruction: false, + path: 'eoi-outcome-home', + loadComponent: () => import('../../pages/outcome-indicator/pages/eioi-home/eoio-home.component').then(m => m.EoioHomeComponent) + }, + { + prName: 'Report progress on Work Packages outcome', + underConstruction: false, + path: 'work-package-outcome-home', + loadComponent: () => import('../../pages/outcome-indicator/pages/wp-home/wp-home.component').then(m => m.WpHomeComponent) + }, { prName: '', path: '**', pathMatch: 'full', redirectTo: 'home' } ]; From a2b8b9e1596723399d91b3aca5a08aefd7a22c35 Mon Sep 17 00:00:00 2001 From: German Martinez Date: Fri, 8 Nov 2024 16:36:47 -0500 Subject: [PATCH 05/12] =?UTF-8?q?=E2=9C=A8feat(Contribution=20to=20Indicat?= =?UTF-8?q?or):=20adding=20new=20module=20for=20CoI=20#2=20(WIP):=20-=20im?= =?UTF-8?q?plemented=20loading=20of=20outcomes=20and=20eois=20by=20initiat?= =?UTF-8?q?ive=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../contribution-to-indicators.controller.ts | 18 ++++++ .../contribution-to-indicators.routes.ts | 2 +- .../contribution-to-indicators.service.ts | 30 ++++++++++ .../contribution-to-indicators.repository.ts | 57 +++++++++++++++++++ 4 files changed, 106 insertions(+), 1 deletion(-) diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts index 47ed06c5d..acc269252 100644 --- a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts @@ -23,6 +23,24 @@ export class ContributionToIndicatorsController { return this.contributionToIndicatorsService.create(tocId, user); } + @Get('outcomes/:initiativeCode') + findAllOutcomesByInitiativeCode( + @Param('initiativeCode') initiativeCode: string, + ) { + return this.contributionToIndicatorsService.findAllToCResultsByInitiativeCode( + initiativeCode, + true, + ); + } + + @Get('eois/:initiativeCode') + findAllEoIsByInitiativeCode(@Param('initiativeCode') initiativeCode: string) { + return this.contributionToIndicatorsService.findAllToCResultsByInitiativeCode( + initiativeCode, + false, + ); + } + @Get('get/:id') findOne(@Param('tocId') tocId: string) { return this.contributionToIndicatorsService.findOne(tocId); diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.routes.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.routes.ts index 457aa4c79..4d46dc256 100644 --- a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.routes.ts +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.routes.ts @@ -3,7 +3,7 @@ import { ContributionToIndicatorsModule } from './contribution-to-indicators.mod export const ContributionToIndicatorRoutes: Routes = [ { - path: '', + path: '/', module: ContributionToIndicatorsModule, }, ]; diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.ts index 44c75a094..1396498d7 100644 --- a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.ts +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.ts @@ -19,6 +19,36 @@ export class ContributionToIndicatorsService { private readonly _handlersError: HandlersError, ) {} + async findAllToCResultsByInitiativeCode( + initiativeCode: string, + isOutcome: boolean, + ) { + try { + if (!initiativeCode?.length) { + throw { + response: {}, + message: 'missing data: initiativeCode', + status: HttpStatus.BAD_REQUEST, + }; + } + + const data = + await this._contributionToIndicatorsRepository.findAllToCResultsByInitiativeCode( + initiativeCode, + isOutcome, + ); + + return { + data, + message: + 'The Contributor to Indicators list has been fetched successfully.', + status: HttpStatus.OK, + }; + } catch (error) { + return this._handlersError.returnErrorRes({ error }); + } + } + async create(tocId: string, user: TokenDto) { try { if (!tocId?.length) { diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicators.repository.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicators.repository.ts index 02f40cbda..ead6e5df6 100644 --- a/onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicators.repository.ts +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicators.repository.ts @@ -2,6 +2,7 @@ import { Injectable, Logger } from '@nestjs/common'; import { ContributionToIndicator } from '../entities/contribution-to-indicator.entity'; import { DataSource, Repository } from 'typeorm'; import { HandlersError } from '../../../shared/handlers/error.utils'; +import { env } from 'process'; @Injectable() export class ContributionToIndicatorsRepository extends Repository { @@ -15,4 +16,60 @@ export class ContributionToIndicatorsRepository extends Repository data.map((item) => item.workpackage)) + .catch((err) => { + throw this._handlersError.returnErrorRepository({ + error: err, + className: ContributionToIndicatorsRepository.name, + debug: true, + }); + }); + } } From 0413aea2b9821b946bc5523ea08154599ddf0588 Mon Sep 17 00:00:00 2001 From: German Martinez Date: Wed, 13 Nov 2024 08:08:08 -0500 Subject: [PATCH 06/12] =?UTF-8?q?=F0=9F=90=9Bfix(CoI):=20changing=20param?= =?UTF-8?q?=20name=20on=20url?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../contribution-to-indicators.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts index acc269252..0e1526fee 100644 --- a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts @@ -41,7 +41,7 @@ export class ContributionToIndicatorsController { ); } - @Get('get/:id') + @Get('get/:tocId') findOne(@Param('tocId') tocId: string) { return this.contributionToIndicatorsService.findOne(tocId); } From 794ab491074c7a8c632101061bebda7174ab0e21 Mon Sep 17 00:00:00 2001 From: xKeCo Date: Wed, 13 Nov 2024 08:52:00 -0500 Subject: [PATCH 07/12] =?UTF-8?q?=E2=9C=A8feat(OutcomeIndicator)=20P2-903:?= =?UTF-8?q?=20implement=20EOI=20outcome=20indicators=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outcome-indicator.component.html | 5 +- .../outcome-indicator.component.scss | 1 + .../outcome-indicator.component.spec.ts | 98 ++++++++++++++++++- .../outcome-indicator.component.ts | 77 ++++++++++++--- .../pages/eioi-home/eoio-home.component.html | 86 +++++++++++++++- .../pages/eioi-home/eoio-home.component.scss | 39 ++++++++ .../eioi-home/eoio-home.component.spec.ts | 41 +++++++- .../pages/eioi-home/eoio-home.component.ts | 24 ++++- .../outcome-indicator-home.component.html | 8 +- .../outcome-indicator-home.component.spec.ts | 58 +---------- .../outcome-indicator-home.component.ts | 28 ++---- .../outcome-indicator.service.test.ts | 48 +++++++++ .../services/outcome-indicator.service.ts | 28 ++++++ .../custom-spinner.component.html | 2 +- .../custom-spinner.component.ts | 1 + .../services/api/results-api.service.spec.ts | 15 +++ .../services/api/results-api.service.ts | 4 + 17 files changed, 455 insertions(+), 108 deletions(-) create mode 100644 onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.test.ts create mode 100644 onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.ts diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.html b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.html index 2abd741ee..fc95e2add 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.html +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.html @@ -6,10 +6,11 @@ [required]="false" [isStatic]="true" optionLabel="full_name" - optionValue="initiative_id" + optionValue="official_code" placeholder="Select Initiative" labelDescInlineStyles="color: #5569dd" - [(ngModel)]="this.initiativeIdFilter"> + [(ngModel)]="this.outcomeIService.initiativeIdFilter" + (ngModelChange)="this.outcomeIService.getEOIsData(); updateQueryParams()">
diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.scss b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.scss index 1b02efad0..90b73cfdb 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.scss +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.scss @@ -1,5 +1,6 @@ .local_container { margin-top: 20px !important; + margin-bottom: 20px !important; padding: 0px 40px; padding-top: 15px !important; padding-bottom: 50px; diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.spec.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.spec.ts index 115934c37..ce6343a4a 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.spec.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.spec.ts @@ -1,6 +1,9 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { OutcomeIndicatorComponent } from './outcome-indicator.component'; import { RouterTestingModule } from '@angular/router/testing'; +import { CustomFieldsModule } from '../../custom-fields/custom-fields.module'; +import { of, throwError } from 'rxjs'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; describe('OutcomeIndicatorComponent', () => { let component: OutcomeIndicatorComponent; @@ -9,7 +12,7 @@ describe('OutcomeIndicatorComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [OutcomeIndicatorComponent], - imports: [RouterTestingModule] + imports: [RouterTestingModule, CustomFieldsModule, HttpClientTestingModule] }).compileComponents(); }); @@ -22,4 +25,97 @@ describe('OutcomeIndicatorComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should initialize component for admin user', async () => { + component.api.rolesSE.isAdmin = true; + jest.spyOn(component, 'loadAllInitiatives'); + jest.spyOn(component.api.dataControlSE, 'getCurrentPhases'); + + await component.initializeComponent(); + + expect(component.api.dataControlSE.getCurrentPhases).toHaveBeenCalled(); + expect(component.loadAllInitiatives).toHaveBeenCalled(); + }); + + it('should initialize component for non-admin user', async () => { + component.api.rolesSE.isAdmin = false; + jest.spyOn(component.api, 'updateUserData'); + jest.spyOn(component.api.dataControlSE, 'getCurrentPhases'); + + await component.initializeComponent(); + + expect(component.api.dataControlSE.getCurrentPhases).toHaveBeenCalled(); + expect(component.api.updateUserData).toHaveBeenCalled(); + }); + + it('should set default initiative for non-admin user', () => { + const mockInitiative = { official_code: 'TEST1' }; + component.api.dataControlSE.myInitiativesList = [mockInitiative]; + jest.spyOn(component, 'updateQueryParams'); + jest.spyOn(component.outcomeIService, 'getEOIsData'); + + component.setDefaultInitiativeForNonAdmin(); + + expect(component.outcomeIService.initiativeIdFilter).toBe('TEST1'); + expect(component.updateQueryParams).toHaveBeenCalled(); + expect(component.outcomeIService.getEOIsData).toHaveBeenCalled(); + }); + + it('should set default initiative for non-admin user when query param exists', () => { + component.api.rolesSE.isAdmin = false; + component.api.dataControlSE.myInitiativesList = [{ official_code: 'TEST1' }, { official_code: 'TEST2' }]; + component.activatedRoute.snapshot.queryParams = { init: 'TEST2' }; + jest.spyOn(component, 'updateQueryParams'); + jest.spyOn(component.outcomeIService, 'getEOIsData'); + + component.setDefaultInitiativeForNonAdmin(); + + expect(component.outcomeIService.initiativeIdFilter).toBe('TEST2'); + expect(component.updateQueryParams).toHaveBeenCalled(); + expect(component.outcomeIService.getEOIsData).toHaveBeenCalled(); + }); + + it('should load all initiatives', async () => { + const mockResponse = { response: [{ official_code: 'TEST1' }] }; + jest.spyOn(component.api.resultsSE, 'GET_AllInitiatives').mockReturnValue(of(mockResponse)); + jest.spyOn(component, 'handleInitiativeQueryParam'); + + await component.loadAllInitiatives(); + + expect(component.allInitiatives).toEqual(mockResponse.response); + expect(component.handleInitiativeQueryParam).toHaveBeenCalled(); + }); + + it('should handle error when loading initiatives', () => { + jest.spyOn(console, 'error'); + jest.spyOn(component.api.resultsSE, 'GET_AllInitiatives').mockReturnValue(throwError(() => 'Test error')); + + component.loadAllInitiatives(); + + expect(console.error).toHaveBeenCalledWith('Error loading initiatives:', 'Test error'); + }); + + it('should handle initiative query param when param exists', () => { + const mockQueryParams = { init: 'test1' }; + component.activatedRoute.snapshot.queryParams = mockQueryParams; + jest.spyOn(component.outcomeIService, 'getEOIsData'); + + component.handleInitiativeQueryParam(); + + expect(component.outcomeIService.initiativeIdFilter).toBe('TEST1'); + expect(component.outcomeIService.getEOIsData).toHaveBeenCalled(); + }); + + it('should update query params', () => { + component.outcomeIService.initiativeIdFilter = 'TEST1'; + jest.spyOn(component.router, 'navigate'); + + component.updateQueryParams(); + + expect(component.router.navigate).toHaveBeenCalledWith([], { + relativeTo: component.activatedRoute, + queryParams: { init: 'TEST1' }, + queryParamsHandling: 'merge' + }); + }); }); diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.ts index 6dfd1c072..3de5e71ae 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.ts @@ -1,31 +1,78 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { ApiService } from '../../shared/services/api/api.service'; +import { OutcomeIndicatorService } from './services/outcome-indicator.service'; +import { ActivatedRoute, Router } from '@angular/router'; +import { take } from 'rxjs/operators'; @Component({ selector: 'app-outcome-indicator-module', templateUrl: './outcome-indicator.component.html', - styleUrl: './outcome-indicator.component.scss' + styleUrls: ['./outcome-indicator.component.scss'] }) -export class OutcomeIndicatorComponent { - initiativeIdFilter = null; - allInitiatives = []; +export class OutcomeIndicatorComponent implements OnInit { + readonly QUERY_PARAM_INITIATIVE = 'init'; + allInitiatives: any[] = []; - constructor(public api: ApiService) {} + constructor( + public api: ApiService, + public outcomeIService: OutcomeIndicatorService, + public activatedRoute: ActivatedRoute, + public router: Router + ) {} - ngOnInit() { - this.GET_AllInitiatives(); + ngOnInit(): void { + this.initializeComponent(); + } + + async initializeComponent(): Promise { this.api.dataControlSE.getCurrentPhases(); - if (!this.api.rolesSE.isAdmin) { - this.initiativeIdFilter = this.api.dataControlSE.myInitiativesList[0]?.initiative_id; + if (this.api.rolesSE.isAdmin) { + await this.loadAllInitiatives(); + } else { + this.api.updateUserData(() => this.setDefaultInitiativeForNonAdmin()); + } + } + + setDefaultInitiativeForNonAdmin(): void { + const defaultInitiative = this.api.dataControlSE.myInitiativesList[0]?.official_code; + const initParam = this.activatedRoute.snapshot.queryParams[this.QUERY_PARAM_INITIATIVE]; + + this.outcomeIService.initiativeIdFilter = this.api.dataControlSE.myInitiativesList.some(init => init.official_code === initParam?.toUpperCase()) + ? initParam + : defaultInitiative; + + this.updateQueryParams(); + this.outcomeIService.getEOIsData(); + } + + async loadAllInitiatives(): Promise { + this.api.resultsSE.GET_AllInitiatives().subscribe({ + next: ({ response }) => { + this.allInitiatives = response; + this.handleInitiativeQueryParam(); + }, + error: error => console.error('Error loading initiatives:', error) + }); + } + + handleInitiativeQueryParam(): void { + const initParam = this.activatedRoute.snapshot.queryParams[this.QUERY_PARAM_INITIATIVE]; + + if (initParam) { + this.outcomeIService.initiativeIdFilter = initParam.toUpperCase(); + } else if (this.allInitiatives.length > 0) { + this.outcomeIService.initiativeIdFilter = this.allInitiatives[0].official_code; + this.updateQueryParams(); } + this.outcomeIService.getEOIsData(); } - GET_AllInitiatives() { - if (!this.api.rolesSE.isAdmin) return; - this.api.resultsSE.GET_AllInitiatives().subscribe(({ response }) => { - this.allInitiatives = response; - this.initiativeIdFilter = this.allInitiatives[0]?.initiative_id; + updateQueryParams(): void { + this.router.navigate([], { + relativeTo: this.activatedRoute, + queryParams: { [this.QUERY_PARAM_INITIATIVE]: this.outcomeIService.initiativeIdFilter }, + queryParamsHandling: 'merge' }); } } diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html index 530bd18af..8da62e4d0 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html @@ -1,2 +1,84 @@ -

eioi-home works!

-, +
+
+ arrow_back +
+

Indicator list

+
+ +
+ search + +
+ + + + + Outcome + + Indicator + + + + Indicator Type + + + Expected Target + Actual target achieved + Achieved status + Reporting status + + + + + @let indicator = item.indicators?.[0]; + + {{ item?.toc_result_title }} + {{ indicator?.indicator_description }} + + + {{ !indicator?.indicator_name ? '' : indicator?.is_indicator_custom ? 'Custom - ' : 'Standard - ' }} + + {{ indicator?.indicator_name }} + + {{ indicator?.indicator_target_value ?? 'Not defined' }} + {{ indicator?.indicator_achieved_value ?? 'Not defined' }} + + {{ achievedStatus(indicator?.indicator_target_value, indicator?.indicator_achieved_value) ? 'Achieved' : 'Not Achieved' }} + + +
+
+
+ + +
+ + + + + + + + +
diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.scss b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.scss index e69de29bb..2980d6fcd 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.scss +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.scss @@ -0,0 +1,39 @@ +.circle { + background-color: #b9b9b9; + width: 20px; + height: 20px; + border-radius: 50%; + border: 1px solid #000; +} + +.circle-success { + background-color: #4caf50; +} + +#resultListTable th { + text-align: center; +} + +.eoio_header { + display: flex; + justify-content: flex-start; + align-items: center; + margin-bottom: 2rem; + gap: 1rem; + + .eoio_header_arrow { + display: flex; + justify-content: center; + align-items: center; + background-color: var(--pr-color-primary); + border-radius: 3px; + padding: 3px; + cursor: pointer; + } + + .eoio_header_title { + font-size: 24px; + font-weight: 600; + margin: 0; + } +} diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.spec.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.spec.ts index 54ec5c6b2..5b7ad5742 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.spec.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.spec.ts @@ -1,6 +1,9 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { EoioHomeComponent } from './eoio-home.component'; import { CommonModule } from '@angular/common'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ActivatedRoute } from '@angular/router'; +import { RouterTestingModule } from '@angular/router/testing'; describe('EoioHomeComponent', () => { let component: EoioHomeComponent; @@ -8,7 +11,7 @@ describe('EoioHomeComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [CommonModule, EoioHomeComponent], + imports: [CommonModule, EoioHomeComponent, HttpClientTestingModule, RouterTestingModule], declarations: [] }).compileComponents(); @@ -17,7 +20,39 @@ describe('EoioHomeComponent', () => { fixture.detectChanges(); }); - it('should create', () => { - expect(component).toBeTruthy(); + describe('EoioHomeComponent', () => { + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should return true when achievedTarget is greater than or equal to expectedTarget', () => { + const expectedTarget = 10; + const achievedTarget = 15; + expect(component.achievedStatus(expectedTarget, achievedTarget)).toBe(true); + }); + + it('should return false when achievedTarget is less than expectedTarget', () => { + const expectedTarget = 10; + const achievedTarget = 5; + expect(component.achievedStatus(expectedTarget, achievedTarget)).toBe(false); + }); + + it('should return false when expectedTarget is null', () => { + const expectedTarget = null; + const achievedTarget = 10; + expect(component.achievedStatus(expectedTarget, achievedTarget)).toBe(false); + }); + + it('should return false when achievedTarget is null', () => { + const expectedTarget = 10; + const achievedTarget = null; + expect(component.achievedStatus(expectedTarget, achievedTarget)).toBe(false); + }); + + it('should return false when both expectedTarget and achievedTarget are null', () => { + const expectedTarget = null; + const achievedTarget = null; + expect(component.achievedStatus(expectedTarget, achievedTarget)).toBe(false); + }); }); }); diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.ts index ad10089f7..451e25470 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.ts @@ -1,12 +1,30 @@ import { CommonModule } from '@angular/common'; -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject, OnInit, signal } from '@angular/core'; +import { TableModule } from 'primeng/table'; +import { ApiService } from '../../../../shared/services/api/api.service'; +import { ButtonModule } from 'primeng/button'; +import { TagModule } from 'primeng/tag'; +import { CustomSpinnerModule } from '../../../../shared/components/custom-spinner/custom-spinner.module'; +import { OutcomeIndicatorService } from '../../services/outcome-indicator.service'; +import { ActivatedRoute, RouterLink } from '@angular/router'; @Component({ selector: 'app-eioi-home', standalone: true, - imports: [CommonModule], + imports: [CommonModule, TableModule, ButtonModule, TagModule, CustomSpinnerModule, RouterLink], templateUrl: './eoio-home.component.html', styleUrl: './eoio-home.component.scss', changeDetection: ChangeDetectionStrategy.OnPush }) -export class EoioHomeComponent {} +export class EoioHomeComponent { + api = inject(ApiService); + outcomeIService = inject(OutcomeIndicatorService); + activatedRoute = inject(ActivatedRoute); + + achievedStatus(expectedTarget: number | null, achievedTarget: number | null): boolean { + if (expectedTarget === null || achievedTarget === null) { + return false; + } + return achievedTarget >= expectedTarget; + } +} diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.html b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.html index 60adc6053..db7edccb7 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.html +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.html @@ -10,7 +10,8 @@

Outcome Indicator Module

+ [ngClass]="{ disabled: !this.outcomeIService.initiativeIdFilter || !this.api.dataControlSE.reportingCurrentPhase.phaseName }" + [queryParams]="{ init: this.outcomeIService.initiativeIdFilter }">

Report progress on End-Of-Initiative Outcomes

@@ -18,14 +19,15 @@

Outcome Indicator Module

+ [ngClass]="{ disabled: !this.outcomeIService.initiativeIdFilter || !this.api.dataControlSE.reportingCurrentPhase.phaseName }" + [queryParams]="{ init: this.outcomeIService.initiativeIdFilter }">

Report progress on Work Packages Outcomes

Export all the progress reported by indicators

diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.spec.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.spec.ts index 03f34e5c8..55a0bc028 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.spec.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.spec.ts @@ -2,8 +2,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { OutcomeIndicatorHomeComponent } from './outcome-indicator-home.component'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { CustomFieldsModule } from '../../../../custom-fields/custom-fields.module'; -import { ApiService } from '../../../../shared/services/api/api.service'; -import { of } from 'rxjs'; +import { RouterTestingModule } from '@angular/router/testing'; describe('OutcomeIndicatorHomeComponent', () => { let component: OutcomeIndicatorHomeComponent; @@ -11,8 +10,7 @@ describe('OutcomeIndicatorHomeComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [OutcomeIndicatorHomeComponent], - imports: [HttpClientTestingModule, CustomFieldsModule] + imports: [HttpClientTestingModule, CustomFieldsModule, OutcomeIndicatorHomeComponent, RouterTestingModule] }).compileComponents(); fixture = TestBed.createComponent(OutcomeIndicatorHomeComponent); @@ -23,58 +21,6 @@ describe('OutcomeIndicatorHomeComponent', () => { expect(component).toBeTruthy(); }); - describe('ngOnInit', () => { - it('should call GET_AllInitiatives and getCurrentPhases', () => { - jest.spyOn(component, 'GET_AllInitiatives'); - jest.spyOn(component.api.dataControlSE, 'getCurrentPhases'); - - component.ngOnInit(); - - expect(component.GET_AllInitiatives).toHaveBeenCalled(); - expect(component.api.dataControlSE.getCurrentPhases).toHaveBeenCalled(); - }); - - it('should set initiativeIdFilter if user is not admin', () => { - component.api.rolesSE.isAdmin = false; - component.api.dataControlSE.myInitiativesList = [{ initiative_id: 123 }]; - - component.ngOnInit(); - - expect(component.initiativeIdFilter).toBe(123); - }); - - it('should not set initiativeIdFilter if user is admin', () => { - component.api.rolesSE.isAdmin = true; - - component.ngOnInit(); - - expect(component.initiativeIdFilter).toBeNull(); - }); - }); - - describe('GET_AllInitiatives', () => { - it('should not call GET_AllInitiatives if user is not admin', () => { - component.api.rolesSE.isAdmin = false; - jest.spyOn(component.api.resultsSE, 'GET_AllInitiatives'); - - component.GET_AllInitiatives(); - - expect(component.api.resultsSE.GET_AllInitiatives).not.toHaveBeenCalled(); - }); - - it('should call GET_AllInitiatives and set allInitiatives if user is admin', () => { - component.api.rolesSE.isAdmin = true; - const mockResponse = { response: [{ initiative_id: 456 }] }; - jest.spyOn(component.api.resultsSE, 'GET_AllInitiatives').mockReturnValue(of(mockResponse)); - - component.GET_AllInitiatives(); - - expect(component.api.resultsSE.GET_AllInitiatives).toHaveBeenCalled(); - expect(component.allInitiatives).toEqual(mockResponse.response); - expect(component.initiativeIdFilter).toBe(456); - }); - }); - describe('exportToExcel', () => { it('should log "Export to Excel"', () => { console.error = jest.fn(); diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.ts index 9842802ba..5f1c13d74 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/outcome-indicator-home/outcome-indicator-home.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { ApiService } from '../../../../shared/services/api/api.service'; import { CommonModule, NgClass } from '@angular/common'; import { RouterLink } from '@angular/router'; +import { OutcomeIndicatorService } from '../../services/outcome-indicator.service'; @Component({ selector: 'app-outcome-indicator-home', @@ -10,28 +11,11 @@ import { RouterLink } from '@angular/router'; standalone: true, imports: [NgClass, RouterLink] }) -export class OutcomeIndicatorHomeComponent implements OnInit { - initiativeIdFilter = null; - allInitiatives = []; - - constructor(public api: ApiService) {} - - ngOnInit() { - this.GET_AllInitiatives(); - this.api.dataControlSE.getCurrentPhases(); - - if (!this.api.rolesSE.isAdmin) { - this.initiativeIdFilter = this.api.dataControlSE.myInitiativesList[0]?.initiative_id; - } - } - - GET_AllInitiatives() { - if (!this.api.rolesSE.isAdmin) return; - this.api.resultsSE.GET_AllInitiatives().subscribe(({ response }) => { - this.allInitiatives = response; - this.initiativeIdFilter = this.allInitiatives[0]?.initiative_id; - }); - } +export class OutcomeIndicatorHomeComponent { + constructor( + public api: ApiService, + public outcomeIService: OutcomeIndicatorService + ) {} exportToExcel() { console.error('Export to Excel'); diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.test.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.test.ts new file mode 100644 index 000000000..241ef0e0a --- /dev/null +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.test.ts @@ -0,0 +1,48 @@ +import { OutcomeIndicatorService } from './outcome-indicator.service'; + +describe('OutcomeIndicatorService', () => { + let service: OutcomeIndicatorService; + let apiServiceMock: any; + + beforeEach(() => { + apiServiceMock = { + resultsSE: { + GET_contributionsToIndicatorsEOIS: jest.fn() + } + }; + + service = new OutcomeIndicatorService(apiServiceMock); + }); + + it('should set loading to true and call GET_contributionsToIndicatorsEOIS', () => { + const subscribeMock = jest.fn(); + apiServiceMock.resultsSE.GET_contributionsToIndicatorsEOIS.mockReturnValue({ subscribe: subscribeMock }); + + service.getEOIsData(); + + expect(service.loading()).toBe(true); + expect(apiServiceMock.resultsSE.GET_contributionsToIndicatorsEOIS).toHaveBeenCalledWith(service.initiativeIdFilter); + expect(subscribeMock).toHaveBeenCalled(); + }); + + it('should set eoisData and loading to false on successful response', () => { + const response = { data: [{ toc_results: ['result1', 'result2'] }] }; + const subscribeMock = jest.fn(({ next }) => next(response)); + apiServiceMock.resultsSE.GET_contributionsToIndicatorsEOIS.mockReturnValue({ subscribe: subscribeMock }); + + service.getEOIsData(); + + expect(service.eoisData).toEqual(['result1', 'result2']); + expect(service.loading()).toBe(false); + }); + + it('should set loading to false on error response', () => { + const error = new Error('Test error'); + const subscribeMock = jest.fn(({ error }) => error(error)); + apiServiceMock.resultsSE.GET_contributionsToIndicatorsEOIS.mockReturnValue({ subscribe: subscribeMock }); + + service.getEOIsData(); + + expect(service.loading()).toBe(false); + }); +}); diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.ts new file mode 100644 index 000000000..ca16b5ebd --- /dev/null +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.ts @@ -0,0 +1,28 @@ +import { Injectable, signal } from '@angular/core'; +import { ApiService } from '../../../shared/services/api/api.service'; + +@Injectable({ + providedIn: 'root' +}) +export class OutcomeIndicatorService { + eoisData: any = []; + initiativeIdFilter = ''; + loading = signal(false); + searchText = signal(''); + + constructor(public api: ApiService) {} + + getEOIsData() { + this.loading.set(true); + this.api.resultsSE.GET_contributionsToIndicatorsEOIS(this.initiativeIdFilter).subscribe({ + next: res => { + this.eoisData = res?.data?.[0]?.toc_results; + this.loading.set(false); + }, + error: error => { + console.error(error); + this.loading.set(false); + } + }); + } +} diff --git a/onecgiar-pr-client/src/app/shared/components/custom-spinner/custom-spinner.component.html b/onecgiar-pr-client/src/app/shared/components/custom-spinner/custom-spinner.component.html index 332acafec..c46d4e225 100644 --- a/onecgiar-pr-client/src/app/shared/components/custom-spinner/custom-spinner.component.html +++ b/onecgiar-pr-client/src/app/shared/components/custom-spinner/custom-spinner.component.html @@ -1,4 +1,4 @@ -
+
{{text||'Please wait'}}...
diff --git a/onecgiar-pr-client/src/app/shared/components/custom-spinner/custom-spinner.component.ts b/onecgiar-pr-client/src/app/shared/components/custom-spinner/custom-spinner.component.ts index 7e1da77ea..ce2141a8c 100644 --- a/onecgiar-pr-client/src/app/shared/components/custom-spinner/custom-spinner.component.ts +++ b/onecgiar-pr-client/src/app/shared/components/custom-spinner/custom-spinner.component.ts @@ -8,6 +8,7 @@ import { ResultsListService } from '../../../pages/results/pages/results-outlet/ }) export class CustomSpinnerComponent { @Input() text: string; + @Input() showSpinner: boolean = false; constructor(public resultsListService: ResultsListService) {} } diff --git a/onecgiar-pr-client/src/app/shared/services/api/results-api.service.spec.ts b/onecgiar-pr-client/src/app/shared/services/api/results-api.service.spec.ts index eb69f89e1..416391505 100644 --- a/onecgiar-pr-client/src/app/shared/services/api/results-api.service.spec.ts +++ b/onecgiar-pr-client/src/app/shared/services/api/results-api.service.spec.ts @@ -3468,4 +3468,19 @@ describe('ResultsApiService', () => { expect(req.request.method).toBe('GET'); }); }); + + describe('GET_contributionsToIndicatorsEOIS', () => { + it('should call GET_contributionsToIndicatorsEOIS and return expected data', done => { + const initiativeCode = 'INIT_CODE'; + service.GET_contributionsToIndicatorsEOIS(initiativeCode).subscribe(response => { + expect(response).toEqual(mockResponse); + done(); + }); + + const req = httpMock.expectOne(`${environment.apiBaseUrl}contribution-to-indicators/eois/${initiativeCode}`); + expect(req.request.method).toBe('GET'); + + req.flush(mockResponse); + }); + }); }); diff --git a/onecgiar-pr-client/src/app/shared/services/api/results-api.service.ts b/onecgiar-pr-client/src/app/shared/services/api/results-api.service.ts index cd0969a69..6d40cf751 100644 --- a/onecgiar-pr-client/src/app/shared/services/api/results-api.service.ts +++ b/onecgiar-pr-client/src/app/shared/services/api/results-api.service.ts @@ -1060,4 +1060,8 @@ export class ResultsApiService { GET_cgiarEntityTypes() { return this.http.get(`${environment.apiBaseUrl}clarisa/cgiar-entity-types`); } + + GET_contributionsToIndicatorsEOIS(initiativeCode: string) { + return this.http.get(`${environment.apiBaseUrl}contribution-to-indicators/eois/${initiativeCode}`); + } } From cc6f71788d3c220d7248225cb33b571cb5d8878c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20D=2E=20Guzm=C3=A1n?= Date: Wed, 13 Nov 2024 10:52:37 -0500 Subject: [PATCH 08/12] =?UTF-8?q?=F0=9F=90=9B=20fix(Result=20entity):=20Up?= =?UTF-8?q?date=20obj=5Fresult=5Fqaed=20property=20type=20to=20ResultQaedL?= =?UTF-8?q?og[]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- onecgiar-pr-server/src/api/results/entities/result.entity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onecgiar-pr-server/src/api/results/entities/result.entity.ts b/onecgiar-pr-server/src/api/results/entities/result.entity.ts index 4956c905d..67e426a2c 100644 --- a/onecgiar-pr-server/src/api/results/entities/result.entity.ts +++ b/onecgiar-pr-server/src/api/results/entities/result.entity.ts @@ -395,5 +395,5 @@ export class Result { obj_result_notification: Notification[]; @OneToMany(() => ResultQaedLog, (ra) => ra.obj_result_id_qaed) - obj_result_qaed: Notification[]; + obj_result_qaed: ResultQaedLog[]; } From 624733ae622562a3aec08e77e0d24d9bf6f21ea7 Mon Sep 17 00:00:00 2001 From: xKeCo Date: Wed, 13 Nov 2024 15:42:51 -0500 Subject: [PATCH 09/12] =?UTF-8?q?=E2=9C=A8=20feat(EIOI=20Home)=20P2-903:?= =?UTF-8?q?=20Implement=20search=20filtering=20for=20outcome=20indicators?= =?UTF-8?q?=20and=20update=20table=20sorting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pages/eioi-home/eoio-home.component.html | 14 ++-- .../pages/eioi-home/eoio-home.component.ts | 4 +- .../filter-indicator-by-search.pipe.spec.ts | 71 +++++++++++++++++++ .../pipes/filter-indicator-by-search.pipe.ts | 27 +++++++ 4 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.spec.ts create mode 100644 onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.ts diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html index 8da62e4d0..5d7039590 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html @@ -7,14 +7,14 @@

Indicator list

search - +
Indicator list [loading]="this.outcomeIService.loading()" [showLoader]="false" [first]="this.outcomeIService.searchText && 0" - [paginator]="this.outcomeIService.eoisData?.length > 0" + [paginator]="(this.outcomeIService.eoisData | appFilterIndicatorBySearch: this.outcomeIService.searchText())?.length > 0" [tableStyle]="{ 'min-width': '80rem' }"> - Outcome + Outcome Indicator @@ -46,7 +46,7 @@

Indicator list

@let indicator = item.indicators?.[0]; - {{ item?.toc_result_title }} + {{ item?.toc_result_description }} {{ indicator?.indicator_description }} @@ -74,7 +74,7 @@

Indicator list

diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.ts index 451e25470..e6a4bf49e 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.ts @@ -7,11 +7,13 @@ import { TagModule } from 'primeng/tag'; import { CustomSpinnerModule } from '../../../../shared/components/custom-spinner/custom-spinner.module'; import { OutcomeIndicatorService } from '../../services/outcome-indicator.service'; import { ActivatedRoute, RouterLink } from '@angular/router'; +import { FilterIndicatorBySearchPipe } from '../../pipes/filter-indicator-by-search.pipe'; +import { FormsModule } from '@angular/forms'; @Component({ selector: 'app-eioi-home', standalone: true, - imports: [CommonModule, TableModule, ButtonModule, TagModule, CustomSpinnerModule, RouterLink], + imports: [CommonModule, TableModule, ButtonModule, TagModule, CustomSpinnerModule, RouterLink, FilterIndicatorBySearchPipe, FormsModule], templateUrl: './eoio-home.component.html', styleUrl: './eoio-home.component.scss', changeDetection: ChangeDetectionStrategy.OnPush diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.spec.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.spec.ts new file mode 100644 index 000000000..60de7c0bc --- /dev/null +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.spec.ts @@ -0,0 +1,71 @@ +import { FilterIndicatorBySearchPipe } from './filter-indicator-by-search.pipe'; + +describe('FilterIndicatorBySearchPipe', () => { + let pipe: FilterIndicatorBySearchPipe; + + beforeEach(() => { + pipe = new FilterIndicatorBySearchPipe(); + }); + + it('should create an instance', () => { + expect(pipe).toBeTruthy(); + }); + + it('should return the original list if searchFilter is empty', () => { + const list = [{ toc_result_description: 'Test' }]; + const result = pipe.transform(list, ''); + expect(result).toEqual(list); + }); + + it('should filter the list based on searchFilter', () => { + const list = [ + { toc_result_description: 'Test1', indicators: [{ indicator_description: 'Desc1', indicator_name: 'Name1', is_indicator_custom: false }] }, + { toc_result_description: 'Test2', indicators: [{ indicator_description: 'Desc2', indicator_name: 'Name2', is_indicator_custom: true }] } + ]; + const result = pipe.transform(list, 'Desc1'); + expect(result.length).toBe(1); + expect(result[0].toc_result_description).toBe('Test1'); + }); + + it('should create joinAll string for each item', () => { + const list = [ + { + toc_result_description: 'Test1', + indicators: [{ indicator_description: 'Desc1', indicator_name: 'Name1', is_indicator_custom: false }], + joinAll: '' + } + ]; + pipe.transform(list, 'Desc1'); + expect(list[0].joinAll).toBe('Test1 Desc1 Standard - Name1'); + }); + + it('should handle items with missing toc_result_description ', () => { + const list = [ + { + toc_result_description: null, + indicators: [{ indicator_description: 'Desc1', indicator_name: 'Name1', is_indicator_custom: false }], + joinAll: '' + } + ]; + pipe.transform(list, 'Desc1'); + expect(list[0].joinAll).toBe('Desc1 Standard - Name1'); + }); + + it('should handle items with missing indicator_name', () => { + const list = [ + { + toc_result_description: 'Test1', + indicators: [{ indicator_description: 'Desc1', indicator_name: null, is_indicator_custom: false }], + joinAll: '' + } + ]; + pipe.transform(list, 'Desc1'); + expect(list[0].joinAll).toBe('Test1 Desc1'); + }); + + it('should handle items with missing indicators array', () => { + const list = [{ toc_result_description: 'Test1', indicators: [], joinAll: '' }]; + pipe.transform(list, 'Test1'); + expect(list[0].joinAll).toBe('Test1'); + }); +}); diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.ts new file mode 100644 index 000000000..3c48b6234 --- /dev/null +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.ts @@ -0,0 +1,27 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'appFilterIndicatorBySearch', + standalone: true +}) +export class FilterIndicatorBySearchPipe implements PipeTransform { + transform(list, searchFilter: string): any[] { + if (!searchFilter) { + return list; + } + + list.forEach(item => { + item.joinAll = this.createJoinAllString(item).trim(); + }); + + return list.filter(item => item.joinAll.toUpperCase().includes(searchFilter.toUpperCase())); + } + + private createJoinAllString(item): string { + return this.createDefaultString(item); + } + + private createDefaultString(item): string { + return `${item?.toc_result_description ?? ''} ${item?.indicators?.[0]?.indicator_description ?? ''} ${!item?.indicators?.[0]?.indicator_name ? '' : item?.indicators?.[0]?.is_indicator_custom ? 'Custom -' : 'Standard -'} ${item?.indicators?.[0]?.indicator_name ?? ''}`; + } +} From 8d33c373500eeca63deb8a640a1a56d79945fe87 Mon Sep 17 00:00:00 2001 From: German Martinez Date: Thu, 14 Nov 2024 08:59:53 -0500 Subject: [PATCH 10/12] =?UTF-8?q?=F0=9F=90=9Bfix(CoI):=20adding=20query=20?= =?UTF-8?q?param=20name=20on=20url.=20Adding=20missing=20condition=20on=20?= =?UTF-8?q?query?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../contribution-to-indicators.controller.ts | 2 +- .../contribution-to-indicators.service.ts | 6 ++++++ .../repositories/contribution-to-indicators.repository.ts | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts index 0e1526fee..ad665c061 100644 --- a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.controller.ts @@ -19,7 +19,7 @@ export class ContributionToIndicatorsController { ) {} @Post() - create(@Query() tocId: string, @UserToken() user: TokenDto) { + create(@Query('tocId') tocId: string, @UserToken() user: TokenDto) { return this.contributionToIndicatorsService.create(tocId, user); } diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.ts index 1396498d7..58e945283 100644 --- a/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.ts +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/contribution-to-indicators.service.ts @@ -73,6 +73,12 @@ export class ContributionToIndicatorsService { }; } contribution.is_active = true; + await this._contributionToIndicatorsRepository.update( + { + id: contribution.id, + }, + contribution, + ); } else { contribution = await this._contributionToIndicatorsRepository.save({ created_by: user.id, diff --git a/onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicators.repository.ts b/onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicators.repository.ts index ead6e5df6..f6e635328 100644 --- a/onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicators.repository.ts +++ b/onecgiar-pr-server/src/api/contribution-to-indicators/repositories/contribution-to-indicators.repository.ts @@ -54,7 +54,8 @@ export class ContributionToIndicatorsRepository extends Repository Date: Thu, 14 Nov 2024 10:11:36 -0500 Subject: [PATCH 11/12] =?UTF-8?q?=E2=9C=A8=20feat=20(Outcome=20Indicator)?= =?UTF-8?q?=20P2-903:=20Enhance=20outcome=20indicator=20functionality=20wi?= =?UTF-8?q?th=20new=20WPS=20data=20retrieval=20and=20UI=20updates?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outcome-indicator.component.html | 2 +- .../outcome-indicator.component.spec.ts | 20 +++ .../outcome-indicator.component.ts | 10 +- .../pages/eioi-home/eoio-home.component.html | 28 ++-- .../pages/eioi-home/eoio-home.component.scss | 8 ++ .../eioi-home/eoio-home.component.spec.ts | 41 +----- .../pages/eioi-home/eoio-home.component.ts | 14 +- .../pages/wp-home/wp-home.component.html | 123 +++++++++++++++++- .../pages/wp-home/wp-home.component.scss | 47 +++++++ .../pages/wp-home/wp-home.component.spec.ts | 10 +- .../pages/wp-home/wp-home.component.ts | 23 +++- .../filter-indicator-by-search.pipe.spec.ts | 60 +++++++++ .../pipes/filter-indicator-by-search.pipe.ts | 14 +- .../outcome-indicator.service.test.ts | 83 +++++++++++- .../services/outcome-indicator.service.ts | 32 +++++ .../services/api/results-api.service.spec.ts | 15 +++ .../services/api/results-api.service.ts | 4 + 17 files changed, 462 insertions(+), 72 deletions(-) diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.html b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.html index fc95e2add..456ac337c 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.html +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.html @@ -10,7 +10,7 @@ placeholder="Select Initiative" labelDescInlineStyles="color: #5569dd" [(ngModel)]="this.outcomeIService.initiativeIdFilter" - (ngModelChange)="this.outcomeIService.getEOIsData(); updateQueryParams()"> + (ngModelChange)="handleInitiativeChange()">
diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.spec.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.spec.ts index ce6343a4a..03ce604cd 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.spec.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.spec.ts @@ -53,12 +53,14 @@ describe('OutcomeIndicatorComponent', () => { component.api.dataControlSE.myInitiativesList = [mockInitiative]; jest.spyOn(component, 'updateQueryParams'); jest.spyOn(component.outcomeIService, 'getEOIsData'); + jest.spyOn(component.outcomeIService, 'getWorkPackagesData'); component.setDefaultInitiativeForNonAdmin(); expect(component.outcomeIService.initiativeIdFilter).toBe('TEST1'); expect(component.updateQueryParams).toHaveBeenCalled(); expect(component.outcomeIService.getEOIsData).toHaveBeenCalled(); + expect(component.outcomeIService.getWorkPackagesData).toHaveBeenCalled(); }); it('should set default initiative for non-admin user when query param exists', () => { @@ -67,12 +69,14 @@ describe('OutcomeIndicatorComponent', () => { component.activatedRoute.snapshot.queryParams = { init: 'TEST2' }; jest.spyOn(component, 'updateQueryParams'); jest.spyOn(component.outcomeIService, 'getEOIsData'); + jest.spyOn(component.outcomeIService, 'getWorkPackagesData'); component.setDefaultInitiativeForNonAdmin(); expect(component.outcomeIService.initiativeIdFilter).toBe('TEST2'); expect(component.updateQueryParams).toHaveBeenCalled(); expect(component.outcomeIService.getEOIsData).toHaveBeenCalled(); + expect(component.outcomeIService.getWorkPackagesData).toHaveBeenCalled(); }); it('should load all initiatives', async () => { @@ -99,11 +103,13 @@ describe('OutcomeIndicatorComponent', () => { const mockQueryParams = { init: 'test1' }; component.activatedRoute.snapshot.queryParams = mockQueryParams; jest.spyOn(component.outcomeIService, 'getEOIsData'); + jest.spyOn(component.outcomeIService, 'getWorkPackagesData'); component.handleInitiativeQueryParam(); expect(component.outcomeIService.initiativeIdFilter).toBe('TEST1'); expect(component.outcomeIService.getEOIsData).toHaveBeenCalled(); + expect(component.outcomeIService.getWorkPackagesData).toHaveBeenCalled(); }); it('should update query params', () => { @@ -118,4 +124,18 @@ describe('OutcomeIndicatorComponent', () => { queryParamsHandling: 'merge' }); }); + + it('should handle initiative change', () => { + jest.spyOn(component, 'updateQueryParams'); + jest.spyOn(component.outcomeIService, 'getEOIsData'); + jest.spyOn(component.outcomeIService, 'getWorkPackagesData'); + jest.spyOn(component.outcomeIService.searchText, 'set'); + + component.handleInitiativeChange(); + + expect(component.updateQueryParams).toHaveBeenCalled(); + expect(component.outcomeIService.getEOIsData).toHaveBeenCalled(); + expect(component.outcomeIService.getWorkPackagesData).toHaveBeenCalled(); + expect(component.outcomeIService.searchText.set).toHaveBeenCalledWith(''); + }); }); diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.ts index 3de5e71ae..c5fed14e4 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/outcome-indicator.component.ts @@ -2,7 +2,6 @@ import { Component, OnInit } from '@angular/core'; import { ApiService } from '../../shared/services/api/api.service'; import { OutcomeIndicatorService } from './services/outcome-indicator.service'; import { ActivatedRoute, Router } from '@angular/router'; -import { take } from 'rxjs/operators'; @Component({ selector: 'app-outcome-indicator-module', @@ -34,6 +33,13 @@ export class OutcomeIndicatorComponent implements OnInit { } } + handleInitiativeChange() { + this.updateQueryParams(); + this.outcomeIService.getEOIsData(); + this.outcomeIService.getWorkPackagesData(); + this.outcomeIService.searchText.set(''); + } + setDefaultInitiativeForNonAdmin(): void { const defaultInitiative = this.api.dataControlSE.myInitiativesList[0]?.official_code; const initParam = this.activatedRoute.snapshot.queryParams[this.QUERY_PARAM_INITIATIVE]; @@ -44,6 +50,7 @@ export class OutcomeIndicatorComponent implements OnInit { this.updateQueryParams(); this.outcomeIService.getEOIsData(); + this.outcomeIService.getWorkPackagesData(); } async loadAllInitiatives(): Promise { @@ -66,6 +73,7 @@ export class OutcomeIndicatorComponent implements OnInit { this.updateQueryParams(); } this.outcomeIService.getEOIsData(); + this.outcomeIService.getWorkPackagesData(); } updateQueryParams(): void { diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html index 5d7039590..8bbdb19ae 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html @@ -28,14 +28,8 @@

Indicator list

Outcome - - Indicator - - - - Indicator Type - - + Indicator + Indicator Type Expected Target Actual target achieved Achieved status @@ -46,31 +40,39 @@

Indicator list

@let indicator = item.indicators?.[0]; - {{ item?.toc_result_description }} - {{ indicator?.indicator_description }} + {{ item?.toc_result_description ?? 'No data found.' }} + {{ indicator?.indicator_description ?? 'No data found.' }} {{ !indicator?.indicator_name ? '' : indicator?.is_indicator_custom ? 'Custom - ' : 'Standard - ' }} - {{ indicator?.indicator_name }} + {{ indicator?.indicator_name ?? 'No data found.' }} {{ indicator?.indicator_target_value ?? 'Not defined' }} {{ indicator?.indicator_achieved_value ?? 'Not defined' }} - {{ achievedStatus(indicator?.indicator_target_value, indicator?.indicator_achieved_value) ? 'Achieved' : 'Not Achieved' }} + {{ + this.outcomeIService.achievedStatus(indicator?.indicator_target_value, indicator?.indicator_achieved_value) ? 'Achieved' : 'Not Achieved' + }}
+ + + There are no results for the selected filters. + + + +
+ arrow_back +
+

Indicator list

+ + +
+ search + +
+ + + + + Outcome + Indicator + Indicator Type + Expected Target + Actual target achieved + Achieved status + Reporting status + + + + + + +
+ + + {{ item.workpackage_name }} +
+ + +
+ + + @for (result of item.toc_results; track $index) { + @if (!result.indicators) { + + {{ result?.toc_result_description }} + No indicator data found + + } @else { + @for (indicator of result.indicators; track $index) { + + @if ($index === 0) { + {{ result?.toc_result_description }} + } + {{ indicator?.indicator_description }} + + + {{ !indicator?.indicator_name ? '' : indicator?.is_indicator_custom ? 'Custom - ' : 'Standard - ' }} + + {{ indicator?.indicator_name }} + + {{ indicator?.indicator_target_value ?? 'Not defined' }} + {{ indicator?.indicator_achieved_value ?? 'Not defined' }} + + {{ + this.outcomeIService.achievedStatus(indicator?.indicator_target_value, indicator?.indicator_achieved_value) + ? 'Achieved' + : 'Not Achieved' + }} + + +
+
+
+ + + } + } + } +
+ + + + There are no results for the selected filters. + + + + + + + + + + +
diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.scss b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.scss index e69de29bb..6454a534c 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.scss +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.scss @@ -0,0 +1,47 @@ +.circle { + background-color: #b9b9b9; + width: 20px; + height: 20px; + border-radius: 50%; + border: 1px solid #000; +} + +.circle-success { + background-color: #4caf50; +} + +#resultListTable th { + text-align: center; +} + +.wp_header { + display: flex; + justify-content: flex-start; + align-items: center; + margin-bottom: 2rem; + gap: 1rem; + + .wp_header_arrow { + display: flex; + justify-content: center; + align-items: center; + background-color: var(--pr-color-primary); + border-radius: 3px; + padding: 3px; + cursor: pointer; + } + + .wp_header_title { + font-size: 24px; + font-weight: 600; + margin: 0; + } +} + +.noDataText { + text-align: center; + padding: 50px 0px; + font-size: 1.3em; + font-weight: 500; + color: var(--pr-color-primary); +} diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.spec.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.spec.ts index baea435c1..11a01bde3 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.spec.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.spec.ts @@ -1,6 +1,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { WpHomeComponent } from './wp-home.component'; import { CommonModule } from '@angular/common'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { RouterTestingModule } from '@angular/router/testing'; describe('WpHomeComponent', () => { let component: WpHomeComponent; @@ -8,7 +10,7 @@ describe('WpHomeComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [CommonModule, WpHomeComponent], + imports: [CommonModule, WpHomeComponent, HttpClientTestingModule, RouterTestingModule], declarations: [] }).compileComponents(); @@ -20,4 +22,10 @@ describe('WpHomeComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should call outcomeIService.searchText.set with an empty string on ngOnDestroy', () => { + const spy = jest.spyOn(component.outcomeIService.searchText, 'set'); + component.ngOnDestroy(); + expect(spy).toHaveBeenCalledWith(''); + }); }); diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.ts index 293ad881b..6153826e5 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/wp-home/wp-home.component.ts @@ -1,13 +1,28 @@ import { CommonModule } from '@angular/common'; -import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { RouterModule } from '@angular/router'; +import { ChangeDetectionStrategy, Component, inject, OnDestroy } from '@angular/core'; +import { ActivatedRoute, RouterLink, RouterModule } from '@angular/router'; +import { ApiService } from '../../../../shared/services/api/api.service'; +import { OutcomeIndicatorService } from '../../services/outcome-indicator.service'; +import { FormsModule } from '@angular/forms'; +import { FilterIndicatorBySearchPipe } from '../../pipes/filter-indicator-by-search.pipe'; +import { CustomSpinnerModule } from '../../../../shared/components/custom-spinner/custom-spinner.module'; +import { ButtonModule } from 'primeng/button'; +import { TableModule } from 'primeng/table'; @Component({ selector: 'app-wp-home', standalone: true, - imports: [CommonModule, RouterModule], + imports: [CommonModule, TableModule, ButtonModule, CustomSpinnerModule, RouterLink, FilterIndicatorBySearchPipe, FormsModule], templateUrl: './wp-home.component.html', styleUrl: './wp-home.component.scss', changeDetection: ChangeDetectionStrategy.OnPush }) -export class WpHomeComponent {} +export class WpHomeComponent implements OnDestroy { + api = inject(ApiService); + outcomeIService = inject(OutcomeIndicatorService); + activatedRoute = inject(ActivatedRoute); + + ngOnDestroy(): void { + this.outcomeIService.searchText.set(''); + } +} diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.spec.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.spec.ts index 60de7c0bc..e3af5d1f9 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.spec.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.spec.ts @@ -68,4 +68,64 @@ describe('FilterIndicatorBySearchPipe', () => { pipe.transform(list, 'Test1'); expect(list[0].joinAll).toBe('Test1'); }); + + it('should filter the list based on searchFilter in a case-insensitive manner', () => { + const list = [ + { toc_result_description: 'Test1', indicators: [{ indicator_description: 'Desc1', indicator_name: 'Name1', is_indicator_custom: false }] }, + { toc_result_description: 'Test2', indicators: [{ indicator_description: 'Desc2', indicator_name: 'Name2', is_indicator_custom: true }] } + ]; + const result = pipe.transform(list, 'desc1'); + expect(result.length).toBe(1); + expect(result[0].toc_result_description).toBe('Test1'); + }); + + it('should return the original list if searchFilter is null', () => { + const list = [{ toc_result_description: 'Test' }]; + const result = pipe.transform(list, null); + expect(result).toEqual(list); + }); + + it('should handle items with missing workpackage_name when isWPsTable is true', () => { + const list = [ + { + workpackage_name: null, + toc_result_description: 'Test1', + indicators: [{ indicator_description: 'Desc1', indicator_name: 'Name1', is_indicator_custom: false }], + joinAll: '' + } + ]; + pipe.transform(list, 'Test1', true); + expect(list[0].joinAll).toBe(''); + }); + + it('should create joinAll string using workpackage_name when isWPsTable is true', () => { + const list = [ + { + workpackage_name: 'WP1', + toc_result_description: 'Test1', + indicators: [{ indicator_description: 'Desc1', indicator_name: 'Name1', is_indicator_custom: false }], + joinAll: '' + } + ]; + pipe.transform(list, 'WP1', true); + expect(list[0].joinAll).toBe('WP1'); + }); + + it('should filter the list based on workpackage_name when isWPsTable is true', () => { + const list = [ + { + workpackage_name: 'WP1', + toc_result_description: 'Test1', + indicators: [{ indicator_description: 'Desc1', indicator_name: 'Name1', is_indicator_custom: false }] + }, + { + workpackage_name: 'WP2', + toc_result_description: 'Test2', + indicators: [{ indicator_description: 'Desc2', indicator_name: 'Name2', is_indicator_custom: true }] + } + ]; + const result = pipe.transform(list, 'WP1', true); + expect(result.length).toBe(1); + expect(result[0].workpackage_name).toBe('WP1'); + }); }); diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.ts index 3c48b6234..088a94689 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pipes/filter-indicator-by-search.pipe.ts @@ -5,23 +5,27 @@ import { Pipe, PipeTransform } from '@angular/core'; standalone: true }) export class FilterIndicatorBySearchPipe implements PipeTransform { - transform(list, searchFilter: string): any[] { + transform(list, searchFilter: string, isWPsTable: boolean = false): any[] { if (!searchFilter) { return list; } list.forEach(item => { - item.joinAll = this.createJoinAllString(item).trim(); + item.joinAll = this.createJoinAllString(item, isWPsTable).trim(); }); return list.filter(item => item.joinAll.toUpperCase().includes(searchFilter.toUpperCase())); } - private createJoinAllString(item): string { - return this.createDefaultString(item); + private createJoinAllString(item, isWPsTable): string { + return this.createDefaultString(item, isWPsTable); } - private createDefaultString(item): string { + private createDefaultString(item, isWPsTable): string { + if (isWPsTable) { + return `${item?.workpackage_name ?? ''}`; + } + return `${item?.toc_result_description ?? ''} ${item?.indicators?.[0]?.indicator_description ?? ''} ${!item?.indicators?.[0]?.indicator_name ? '' : item?.indicators?.[0]?.is_indicator_custom ? 'Custom -' : 'Standard -'} ${item?.indicators?.[0]?.indicator_name ?? ''}`; } } diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.test.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.test.ts index 241ef0e0a..123e5a544 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.test.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.test.ts @@ -7,7 +7,8 @@ describe('OutcomeIndicatorService', () => { beforeEach(() => { apiServiceMock = { resultsSE: { - GET_contributionsToIndicatorsEOIS: jest.fn() + GET_contributionsToIndicatorsEOIS: jest.fn(), + GET_contributionsToIndicatorsWPS: jest.fn() } }; @@ -37,7 +38,6 @@ describe('OutcomeIndicatorService', () => { }); it('should set loading to false on error response', () => { - const error = new Error('Test error'); const subscribeMock = jest.fn(({ error }) => error(error)); apiServiceMock.resultsSE.GET_contributionsToIndicatorsEOIS.mockReturnValue({ subscribe: subscribeMock }); @@ -45,4 +45,83 @@ describe('OutcomeIndicatorService', () => { expect(service.loading()).toBe(false); }); + + it('should set loadingWPs to true and call GET_contributionsToIndicatorsWPS', () => { + const subscribeMock = jest.fn(); + apiServiceMock.resultsSE.GET_contributionsToIndicatorsWPS.mockReturnValue({ subscribe: subscribeMock }); + + service.getWorkPackagesData(); + + expect(service.loadingWPs()).toBe(true); + expect(apiServiceMock.resultsSE.GET_contributionsToIndicatorsWPS).toHaveBeenCalledWith(service.initiativeIdFilter); + expect(subscribeMock).toHaveBeenCalled(); + }); + + it('should set wpsData and loadingWPs to false on successful response', () => { + const response = { data: [{ toc_results: ['result1', 'result2'] }] }; + const subscribeMock = jest.fn(({ next }) => next(response)); + apiServiceMock.resultsSE.GET_contributionsToIndicatorsWPS.mockReturnValue({ subscribe: subscribeMock }); + + service.getWorkPackagesData(); + + expect(service.wpsData).toEqual([{ toc_results: ['result1', 'result2'] }]); + expect(service.loadingWPs()).toBe(false); + }); + + it('should set loadingWPs to false on error response', () => { + const subscribeMock = jest.fn(({ error }) => error(error)); + apiServiceMock.resultsSE.GET_contributionsToIndicatorsWPS.mockReturnValue({ subscribe: subscribeMock }); + + service.getWorkPackagesData(); + + expect(service.loadingWPs()).toBe(false); + }); + + it('should return true when achievedTarget is greater than or equal to expectedTarget', () => { + const expectedTarget = 10; + const achievedTarget = 15; + expect(service.achievedStatus(expectedTarget, achievedTarget)).toBe(true); + }); + + it('should return false when achievedTarget is less than expectedTarget', () => { + const expectedTarget = 10; + const achievedTarget = 5; + expect(service.achievedStatus(expectedTarget, achievedTarget)).toBe(false); + }); + + it('should return false when expectedTarget is null', () => { + const expectedTarget = null; + const achievedTarget = 10; + expect(service.achievedStatus(expectedTarget, achievedTarget)).toBe(false); + }); + + it('should return false when achievedTarget is null', () => { + const expectedTarget = 10; + const achievedTarget = null; + expect(service.achievedStatus(expectedTarget, achievedTarget)).toBe(false); + }); + + it('should return false when both expectedTarget and achievedTarget are null', () => { + const expectedTarget = null; + const achievedTarget = null; + expect(service.achievedStatus(expectedTarget, achievedTarget)).toBe(false); + }); + + it('should return false when achievedTarget is NaN', () => { + const expectedTarget = 10; + const achievedTarget = NaN; + expect(service.achievedStatus(expectedTarget, achievedTarget)).toBe(false); + }); + + it('should return false when expectedTarget is NaN', () => { + const expectedTarget = NaN; + const achievedTarget = 10; + expect(service.achievedStatus(expectedTarget, achievedTarget)).toBe(false); + }); + + it('should return false when both expectedTarget and achievedTarget are NaN', () => { + const expectedTarget = NaN; + const achievedTarget = NaN; + expect(service.achievedStatus(expectedTarget, achievedTarget)).toBe(false); + }); }); diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.ts b/onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.ts index ca16b5ebd..c82387d7c 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.ts +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/services/outcome-indicator.service.ts @@ -6,12 +6,30 @@ import { ApiService } from '../../../shared/services/api/api.service'; }) export class OutcomeIndicatorService { eoisData: any = []; + wpsData: any = []; initiativeIdFilter = ''; loading = signal(false); + loadingWPs = signal(false); + searchText = signal(''); constructor(public api: ApiService) {} + achievedStatus(expectedTarget: number | null, achievedTarget: number | null): boolean { + if (expectedTarget === null || achievedTarget === null) { + return false; + } + + const achievedTargetValue = Number(achievedTarget); + const expectedTargetValue = Number(expectedTarget); + + if (isNaN(achievedTargetValue) || isNaN(expectedTargetValue)) { + return false; + } + + return achievedTarget >= expectedTarget; + } + getEOIsData() { this.loading.set(true); this.api.resultsSE.GET_contributionsToIndicatorsEOIS(this.initiativeIdFilter).subscribe({ @@ -25,4 +43,18 @@ export class OutcomeIndicatorService { } }); } + + getWorkPackagesData() { + this.loadingWPs.set(true); + this.api.resultsSE.GET_contributionsToIndicatorsWPS(this.initiativeIdFilter).subscribe({ + next: res => { + this.wpsData = res.data; + this.loadingWPs.set(false); + }, + error: error => { + console.error(error); + this.loadingWPs.set(false); + } + }); + } } diff --git a/onecgiar-pr-client/src/app/shared/services/api/results-api.service.spec.ts b/onecgiar-pr-client/src/app/shared/services/api/results-api.service.spec.ts index 416391505..958861caa 100644 --- a/onecgiar-pr-client/src/app/shared/services/api/results-api.service.spec.ts +++ b/onecgiar-pr-client/src/app/shared/services/api/results-api.service.spec.ts @@ -3483,4 +3483,19 @@ describe('ResultsApiService', () => { req.flush(mockResponse); }); }); + + describe('GET_contributionsToIndicatorsWPS', () => { + it('should call GET_contributionsToIndicatorsWPS and return expected data', done => { + const initiativeCode = 'INIT_CODE'; + service.GET_contributionsToIndicatorsWPS(initiativeCode).subscribe(response => { + expect(response).toEqual(mockResponse); + done(); + }); + + const req = httpMock.expectOne(`${environment.apiBaseUrl}contribution-to-indicators/outcomes/${initiativeCode}`); + expect(req.request.method).toBe('GET'); + + req.flush(mockResponse); + }); + }); }); diff --git a/onecgiar-pr-client/src/app/shared/services/api/results-api.service.ts b/onecgiar-pr-client/src/app/shared/services/api/results-api.service.ts index a607ee6c2..1a3508550 100644 --- a/onecgiar-pr-client/src/app/shared/services/api/results-api.service.ts +++ b/onecgiar-pr-client/src/app/shared/services/api/results-api.service.ts @@ -1068,4 +1068,8 @@ export class ResultsApiService { GET_contributionsToIndicatorsEOIS(initiativeCode: string) { return this.http.get(`${environment.apiBaseUrl}contribution-to-indicators/eois/${initiativeCode}`); } + + GET_contributionsToIndicatorsWPS(initiativeCode: string) { + return this.http.get(`${environment.apiBaseUrl}contribution-to-indicators/outcomes/${initiativeCode}`); + } } From c3b998ac306e0994f82ce56e619c38f89f3c2d64 Mon Sep 17 00:00:00 2001 From: xKeCo Date: Thu, 14 Nov 2024 10:57:01 -0500 Subject: [PATCH 12/12] =?UTF-8?q?=E2=9C=A8=20feat(Tooltip)=20P2-903:=20Add?= =?UTF-8?q?=20tooltip=20functionality=20to=20outcome=20indicators=20in=20E?= =?UTF-8?q?IOI=20and=20WP=20home=20components?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pages/eioi-home/eoio-home.component.html | 8 +++++++- .../pages/eioi-home/eoio-home.component.ts | 3 ++- .../pages/wp-home/wp-home.component.html | 10 +++++++++- .../pages/wp-home/wp-home.component.ts | 3 ++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html index 8bbdb19ae..8a01c12aa 100644 --- a/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html +++ b/onecgiar-pr-client/src/app/pages/outcome-indicator/pages/eioi-home/eoio-home.component.html @@ -56,7 +56,13 @@

Indicator list

}} -
+
Indicator list }} -
+