Skip to content

Commit

Permalink
Merge branch 'feature/non-concession-activity' into staging
Browse files Browse the repository at this point in the history
  • Loading branch information
tsubik committed Oct 10, 2024
2 parents 2737455 + 5f492be commit ce97d7e
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ jobs:
uses: actions/checkout@v4
with:
repository: wri/fti_api
ref: feature/new-password-requirements
ref: feature/obs-non-concession-activity
path: otp_api

- name: Save OTP API Commit SHA
Expand Down
23 changes: 23 additions & 0 deletions e2e/cypress/e2e/observations.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,29 @@ describe('Observations', () => {
).should('be.visible');
})

it('allow to select all country FMUs if checking non concession activity checkbox - only for DRC', () => {
cy.get('a').contains('New observation', { timeout: 10000 }).click();
cy.get('select#observation_type').select('Producer');
cy.get('select#country_id').select('Cameroon');
cy.get('input#non_concession_activity').should('not.exist');
cy.get('select#country_id').select('Democratic Republic of the Congo');
cy.get('input#non_concession_activity').should('be.visible');
cy.selectOption('operator_id', 'CFT');

// we are going to select FMU that belongs to country but not this operator
cy.get('select#fmu_field').find('option').should('not.contain.text', '046/11');
cy.get('input#non_concession_activity').check();
cy.get('select#fmu_field').find('option').should('contain.text', '046/11');
cy.get('select#fmu_field').select('046/11');
cy.get('button').contains('Create').click();

// let's verify if everyting was correctly saved
cy.get('otp-table tbody tr:first').find('button[aria-label=Edit]').click();
cy.location('pathname').should('include', '/observations/edit');
cy.get('input#non_concession_activity').should('be.checked');
cy.get('select[name=fmu_field]').find('option').contains('046/11').should('be.selected');
})

it('can add a new producer directly from observation form', () => {
cy.get('a').contains('New observation', { timeout: 10000 }).click();
cy.get('select#observation_type').select('Producer');
Expand Down
1 change: 1 addition & 0 deletions src/app/models/draft_observation.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface DraftObservation {
evidenceAttachment?: string; // Base64
evidenceDocumentType?: string;

nonConcessionActivity?: boolean;
isPhysicalPlace?: boolean;
litigationStatus?: string;
locationAccuracy?: string;
Expand Down
1 change: 1 addition & 0 deletions src/app/models/observation.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class Observation extends JsonApiModel {
@Attribute() 'hidden': boolean; // Whether an observation is archived
@Attribute() 'user-type'?: string;
@Attribute() 'monitor-comment'?: string;
@Attribute() 'non-concession-activity': boolean; // if operator operates in another operator fmu
@Attribute() 'locale': string;

@BelongsTo() fmu?: Fmu;
Expand Down
8 changes: 8 additions & 0 deletions src/app/pages/observations/observation-detail.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,14 @@ <h3>{{'List of evidence' | translate}}</h3>
</ng-template>

<ng-template [ngIf]="physicalPlace">
<div class="form-group" *ngIf="nonConcessionActivityEnabled">
<input type="checkbox" name="non_concession_activity" id="non_concession_activity" [(ngModel)]="nonConcessionActivity" #non_concession_activity="ngModel" />
<label for="non_concession_activity">{{'Producer conducts activities in a concession that is attributed to another producer' | translate}}</label>
<p class="note">
{{'When checking this checkbox you will be able to select any FMU within selected country' | translate}}
</p>
</div>

<!-- 8.1. Forest management unit -->
<div [ngClass]="{ 'form-group': true, '-required': !!fmus.length && (latitude === null || longitude === null || latitude === undefined || longitude === undefined || latitude.length === 0 || longitude.length === 0) && (subcategory === null || subcategory === undefined || subcategory['location-required'] === true) }">
<label for="fmu_field">{{'Forest management unit' | translate}}</label>
Expand Down
86 changes: 71 additions & 15 deletions src/app/pages/observations/observation-detail.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { ObservationsService } from 'app/services/observations.service';
import { Severity } from 'app/models/severity.model';
import { Router, ActivatedRoute } from '@angular/router';
import { Operator } from 'app/models/operator.model';
import { FmusService } from 'app/services/fmus.service';
import { OperatorsService } from 'app/services/operators.service';
import { ObserversService } from 'app/services/observers.service';
import { Observer } from 'app/models/observer.model';
Expand Down Expand Up @@ -73,7 +74,9 @@ export class ObservationDetailComponent implements OnDestroy {
unknownOperator: Operator = null; // Special unknown operator
governments: Government[] = [];
observers: Observer[] = []; // Ordered by name
fmus: Fmu[] = [];
_fmus: Fmu[] = [];
operatorFmus: Fmu[] = [];
countryFmus: Fmu[] = [];
reports: ObservationReport[] = []; // Ordered by title
documents: ObservationDocument[] = []; // Sorted by name initially
reportDocuments: ObservationDocument[] = []; // Documents of the selected report
Expand Down Expand Up @@ -230,6 +233,7 @@ export class ObservationDetailComponent implements OnDestroy {
_latitude: number; // Only for type operator
_longitude: number; // Only for type operator
_fmu: Fmu = null; // Only for type operator
_nonConcessionActivity: boolean = false; // Only for type operator
_government: Government = null; // Only for type government
_law: Law = null; // Only for type operator
_actions: string;
Expand Down Expand Up @@ -348,6 +352,11 @@ export class ObservationDetailComponent implements OnDestroy {
}

if (country) {
this.fmusService.getAll({ sort: 'name', filter: { country: country.id } })
.then((fmus) => {
this.countryFmus = fmus;
});

this.operatorsService.getAll({ sort: 'name', filter: { country: country.id } })
.then((operators) => {
this.operators = operators;
Expand Down Expand Up @@ -397,32 +406,68 @@ export class ObservationDetailComponent implements OnDestroy {
if (operatorChoice) {
this.operatorsService.getById(operatorChoice.id, { include: 'fmus' })
.then((op) => {
this.fmus = op.fmus ? op.fmus : [];

// If we can restore the FMU of the observation, we do it,
// otherwise we just reset the fmu each time the user
// update the operator
if (this.draft && this.draft.operatorId === operatorChoice.id) {
this.fmu = this.fmus.find(fmu => fmu.id === this.draft.fmuId);
} else if (this.observation && this.observation.operator.id === operatorChoice.id && this.observation.fmu) {
this.fmu = this.fmus.find(fmu => fmu.id === this.observation.fmu.id);
} else {
this.fmu = null;
}
this.operatorFmus = op.fmus ? op.fmus : [];
this.resetFmus();
})
.catch(err => console.error(err)); // TODO: visual feedback

this.operatorsSelection = [operatorChoice.id];
} else {
this.fmus = [];
this.fmu = null;
this.operatorFmus = [];
this.resetFmus();
this.operatorsSelection = [];
}
}
get unknownOperatorSelected() {
return this.operatorChoice && this.unknownOperator && +this.operatorChoice.id === +this.unknownOperator.id;
}

get nonConcessionActivityEnabled() {
return this.country && this.country.iso === 'COD';
}

get nonConcessionActivity() { return this.observation ? this.observation['non-concession-activity'] : this._nonConcessionActivity; }
set nonConcessionActivity(nonConcessionActivity) {
if (this.nonConcessionActivityEnabled) {
this._nonConcessionActivity = nonConcessionActivity;
} else {
this._nonConcessionActivity = false;
}

if (this.observation) {
this.observation['non-concession-activity'] = this._nonConcessionActivity;
}

this.resetFmus();
this.fmu = null;
}

resetFmus() {
this.fmus = this.nonConcessionActivity ? this.countryFmus : this.operatorFmus;
}

resetFmu() {
let fmuId = null;
if (this.draft) {
fmuId = this.draft.fmuId;
} else if (this.observation && this.observation.fmu) {
fmuId = this.observation.fmu.id;
}

if (fmuId) {
if (this.nonConcessionActivity && this.countryFmus.length
|| (!this.nonConcessionActivity && this.operatorFmus.length)) {
this.fmu = this._fmus.find(fmu => fmu.id === fmuId);
}
}
}

get fmus() { return this._fmus; }
set fmus(collection) {
this._fmus = collection;
this.resetFmu();
}

get fmu() { return this.observation ? this.observation.fmu : this._fmu; }
set fmu(fmu) {
// We create the map layer for the FMU and store it
Expand All @@ -447,6 +492,11 @@ export class ObservationDetailComponent implements OnDestroy {
}

if (this.observation) {
if (this.observation.fmu && this.observation.fmu.id !== fmu.id) {
// reset latitude and longitude
this.latitude = null;
this.longitude = null;
}
this.observation.fmu = fmu;
} else {
this._fmu = fmu;
Expand Down Expand Up @@ -822,6 +872,7 @@ export class ObservationDetailComponent implements OnDestroy {
private governmentsService: GovernmentsService,
private subcategoriesService: SubcategoriesService,
private operatorsService: OperatorsService,
private fmusService: FmusService,
private lawsService: LawsService,
private datastoreService: DatastoreService,
private router: Router,
Expand Down Expand Up @@ -888,6 +939,7 @@ export class ObservationDetailComponent implements OnDestroy {
this.reportDate = new Date(this.draft.reportDate);

if (this.type === 'operator') {
this.nonConcessionActivity = this.draft.nonConcessionActivity;
this.physicalPlace = this.draft.isPhysicalPlace;
this.latitude = this.draft.lat;
this.longitude = this.draft.lng;
Expand Down Expand Up @@ -1077,6 +1129,7 @@ export class ObservationDetailComponent implements OnDestroy {
draftModel.operatorId = this.operatorChoice && this.operatorChoice.id;
}

draftModel.nonConcessionActivity = this.nonConcessionActivity;
draftModel.isPhysicalPlace = this.physicalPlace;
draftModel.lat = this.physicalPlace && decimalCoordinates ? decimalCoordinates[0] : null;
draftModel.lng = this.physicalPlace && decimalCoordinates ? decimalCoordinates[1] : null;
Expand Down Expand Up @@ -1870,6 +1923,7 @@ export class ObservationDetailComponent implements OnDestroy {
const decimalCoordinates = this.getDecimalCoordinates();

model.operator = this.operatorChoice;
model['non-concession-activity'] = this.nonConcessionActivityEnabled ? this.nonConcessionActivity : false;
model['is-physical-place'] = this.physicalPlace;
model.lat = this.physicalPlace && decimalCoordinates ? decimalCoordinates[0] : null;
model.lng = this.physicalPlace && decimalCoordinates ? decimalCoordinates[1] : null;
Expand All @@ -1888,6 +1942,8 @@ export class ObservationDetailComponent implements OnDestroy {
observation = this.datastoreService.createRecord(Observation, model);
}

observation['non-concession-activity'] = this.nonConcessionActivityEnabled ? this.nonConcessionActivity : false;

this.uploadReport()
.then(() => {
// If we created a report, we link it to the observation
Expand Down

0 comments on commit ce97d7e

Please sign in to comment.