Skip to content

Commit

Permalink
Merge branch 'P2-903-Tracking-of-outcomes-achievements-against-target…
Browse files Browse the repository at this point in the history
…s' into dev
  • Loading branch information
German Martinez committed Nov 14, 2024
2 parents 8eb018a + c3b998a commit f32dfe8
Show file tree
Hide file tree
Showing 58 changed files with 1,811 additions and 204 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
<div class="local_container section_container">
<div class="filters">
<app-pr-select
[options]="this.api.rolesSE.isAdmin ? this.allInitiatives : this.api.dataControlSE.myInitiativesList"
label="Initiative"
[required]="false"
[isStatic]="true"
optionLabel="full_name"
optionValue="official_code"
placeholder="Select Initiative"
labelDescInlineStyles="color: #5569dd"
[(ngModel)]="this.outcomeIService.initiativeIdFilter"
(ngModelChange)="handleInitiativeChange()">
</app-pr-select>

<div class="filters_phase">
<p class="filters_phase_title">Phase:</p>
<p class="filters_phase_text">
{{ this.api.dataControlSE.reportingCurrentPhase.phaseName }}
</p>
</div>
</div>

<div class="separator_line"></div>

<router-outlet></router-outlet>
</div>
Original file line number Diff line number Diff line change
@@ -1,6 +1,46 @@
.local_container {
margin-top: 20px !important;
margin-bottom: 20px !important;
padding: 0px 40px;
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);
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -9,7 +12,7 @@ describe('OutcomeIndicatorComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [OutcomeIndicatorComponent],
imports: [RouterTestingModule]
imports: [RouterTestingModule, CustomFieldsModule, HttpClientTestingModule]
}).compileComponents();
});

Expand All @@ -22,4 +25,117 @@ 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');
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', () => {
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');
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 () => {
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');
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', () => {
component.outcomeIService.initiativeIdFilter = 'TEST1';
jest.spyOn(component.router, 'navigate');

component.updateQueryParams();

expect(component.router.navigate).toHaveBeenCalledWith([], {
relativeTo: component.activatedRoute,
queryParams: { init: 'TEST1' },
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('');
});
});
Original file line number Diff line number Diff line change
@@ -1,8 +1,86 @@
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';

@Component({
selector: 'app-outcome-indicator-module',
templateUrl: './outcome-indicator.component.html',
styleUrl: './outcome-indicator.component.scss'
styleUrls: ['./outcome-indicator.component.scss']
})
export class OutcomeIndicatorComponent {}
export class OutcomeIndicatorComponent implements OnInit {
readonly QUERY_PARAM_INITIATIVE = 'init';
allInitiatives: any[] = [];

constructor(
public api: ApiService,
public outcomeIService: OutcomeIndicatorService,
public activatedRoute: ActivatedRoute,
public router: Router
) {}

ngOnInit(): void {
this.initializeComponent();
}

async initializeComponent(): Promise<void> {
this.api.dataControlSE.getCurrentPhases();

if (this.api.rolesSE.isAdmin) {
await this.loadAllInitiatives();
} else {
this.api.updateUserData(() => this.setDefaultInitiativeForNonAdmin());
}
}

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];

this.outcomeIService.initiativeIdFilter = this.api.dataControlSE.myInitiativesList.some(init => init.official_code === initParam?.toUpperCase())
? initParam
: defaultInitiative;

this.updateQueryParams();
this.outcomeIService.getEOIsData();
this.outcomeIService.getWorkPackagesData();
}

async loadAllInitiatives(): Promise<void> {
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();
this.outcomeIService.getWorkPackagesData();
}

updateQueryParams(): void {
this.router.navigate([], {
relativeTo: this.activatedRoute,
queryParams: { [this.QUERY_PARAM_INITIATIVE]: this.outcomeIService.initiativeIdFilter },
queryParamsHandling: 'merge'
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Loading

0 comments on commit f32dfe8

Please sign in to comment.