Skip to content

Commit

Permalink
Merge branch 'expander-component' of github.com:OurPlanscape/Planscap…
Browse files Browse the repository at this point in the history
…e into expander-component
  • Loading branch information
lastminutediorama committed Aug 28, 2024
2 parents 3c94170 + 87939a3 commit 0e34cb2
Show file tree
Hide file tree
Showing 18 changed files with 156 additions and 26 deletions.
1 change: 1 addition & 0 deletions src/interface/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ const routes: Routes = [
canActivate: [AuthGuard, createFeatureGuard('treatments')],
resolve: {
treatmentId: numberResolver('treatmentId', ''),
scenarioId: numberResolver('scenarioId', ''),
},
loadChildren: () =>
import('./treatments/treatments.module').then(
Expand Down
16 changes: 5 additions & 11 deletions src/interface/src/app/plan/plan-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import {
} from './project-areas/project-areas.component';
import { DEFAULT_AREA_COLOR, PROJECT_AREA_COLORS } from '@shared';

export const NOTE_SAVE_INTERVAL = 5000;

export const POLLING_INTERVAL = 3000;

// sizes in hectares
Expand All @@ -25,10 +23,10 @@ export const STAND_SIZES: Record<string, number> = {
export function parseResultsToProjectAreas(
results: ScenarioResult
): ProjectAreaReport[] {
return results.result.features.map((featureCollection, i) => {
return results.result.features.map((featureCollection) => {
const props = featureCollection.properties;
return {
id: i + 1,
rank: props.treatment_rank,
acres: props.area_acres,
percentTotal: props.pct_area,
estimatedCost: props.total_cost,
Expand All @@ -55,15 +53,11 @@ export function parseResultsToTotals(
);
}

/**
*
* @param position rank position (1 based index) of scenario projection
*/
export function getColorForProjectPosition(position: number) {
if (position < 1) {
export function getColorForProjectPosition(rank: number) {
if (rank < 1) {
return DEFAULT_AREA_COLOR;
}
return PROJECT_AREA_COLORS[(position - 1) % PROJECT_AREA_COLORS.length];
return PROJECT_AREA_COLORS[(rank - 1) % PROJECT_AREA_COLORS.length];
}

export function findQuestionOnTreatmentGoalsConfig(
Expand Down
6 changes: 3 additions & 3 deletions src/interface/src/app/plan/plan-map/plan-map.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ export class PlanMapComponent implements OnInit, AfterViewInit, OnDestroy {
this.projectAreasLayer = L.geoJSON(shapes, {
style: (shape) => ({
color: '#000',
fillColor: getColorForProjectPosition(shape?.properties.proj_id),
fillColor: getColorForProjectPosition(shape?.properties.treatment_rank),
fillOpacity: 0.4,
weight: 1.5,
}),
Expand All @@ -333,15 +333,15 @@ export class PlanMapComponent implements OnInit, AfterViewInit, OnDestroy {
if (feature.geometry.type === 'Polygon') {
center = polylabel(feature.geometry.coordinates, 0.0005);
addTooltipAtCenter(
feature.properties.proj_id.toString(),
feature.properties.treatment_rank.toString(),
center,
this.map
);
} else if (feature.geometry.type === 'MultiPolygon') {
feature.geometry.coordinates.forEach((positions) => {
center = polylabel(positions, 0.005);
addTooltipAtCenter(
feature.properties.proj_id.toString(),
feature.properties.treatment_rank.toString(),
center,
this.map
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ <h3 class="title">Project Areas</h3>
<tr *ngFor="let area of areas">
<td
class="area-id"
[style.border-left-color]="getColorByPosition(area.id)">
{{ area.id }}
[style.border-left-color]="getColorByPosition(area.rank)">
{{ area.rank }}
</td>
<td data-id="acres">{{ area.acres | number: '1.0-0' }}</td>
<td data-id="percentTotal">{{ area.percentTotal | percent: '1.0-2' }}</td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
import { PROJECT_AREA_COLORS } from '@shared';

export interface ProjectAreaReport {
id: number;
rank: number;
acres: number;
percentTotal: number;
estimatedCost: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
title="Learn more about planscape"
content="Visit our FAQs to learn more"
iconsrc="../../assets/svg/icons/info-circle-dark.svg"
outboundLink="https://www.planscape.org/faqs">
outboundLink="https://www.planscape.org/documentation/faq/">
</app-horizonal-card>
<app-horizonal-card
title="Planscape user guide"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<mgl-vector-source
id="scenarioProjectAreas"
[tiles]="[vectorLayerUrl]"></mgl-vector-source>

<mgl-layer
id="map-project-areas-line"
type="line"
source="scenarioProjectAreas"
[sourceLayer]="layerName"
[paint]="{
'line-color': '#333',
'line-width': 2
}"></mgl-layer>

<mgl-layer
id="map-project-areas-fill"
type="fill"
source="scenarioProjectAreas"
[sourceLayer]="layerName"
[paint]="paint"></mgl-layer>

<mgl-layer
id="map-project-areas-labels"
type="symbol"
source="scenarioProjectAreas"
[sourceLayer]="layerName"
[layout]="{
'text-field': ['get', 'rank'],
'text-size': 14,
'text-anchor': 'center',
'text-justify': 'center'
}"
[paint]="{
'text-color': '#000',
'text-halo-color': '#fff',
'text-halo-width': 2
}"></mgl-layer>
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { MapProjectAreasComponent } from './map-project-areas.component';
import { MockDeclarations } from 'ng-mocks';
import {
LayerComponent,
VectorSourceComponent,
} from '@maplibre/ngx-maplibre-gl';

describe('MapProjectAreasComponent', () => {
let component: MapProjectAreasComponent;
let fixture: ComponentFixture<MapProjectAreasComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MapProjectAreasComponent],
declarations: MockDeclarations(VectorSourceComponent, LayerComponent),
}).compileComponents();

fixture = TestBed.createComponent(MapProjectAreasComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Component, Input } from '@angular/core';
import {
FeatureComponent,
GeoJSONSourceComponent,
LayerComponent,
VectorSourceComponent,
} from '@maplibre/ngx-maplibre-gl';
import { getColorForProjectPosition } from '../../plan/plan-helpers';
import { LayerSpecification, Map as MapLibreMap } from 'maplibre-gl';
import { environment } from '../../../environments/environment';

@Component({
selector: 'app-map-project-areas',
standalone: true,
imports: [
FeatureComponent,
GeoJSONSourceComponent,
LayerComponent,
VectorSourceComponent,
],
templateUrl: './map-project-areas.component.html',
styleUrl: './map-project-areas.component.scss',
})
export class MapProjectAreasComponent {
@Input() scenarioId!: number;
@Input() mapLibreMap!: MapLibreMap;

readonly layerName = 'project_areas_by_scenario';
readonly tilesUrl =
environment.martin_server + 'project_areas_by_scenario/{z}/{x}/{y}';

constructor() {}

get vectorLayerUrl() {
return this.tilesUrl + `?scenario_id=${this.scenarioId}`;
}

paint: LayerSpecification['paint'] = {
'fill-outline-color': '#000',
'fill-color': this.getFillColors() as any,
'fill-opacity': 0.5,
};

getFillColors() {
const defaultColor = '#00000050';
const matchExpression: (number | string | string[])[] = [
'match',
['get', 'rank'],
];
for (let i = 1; i < 11; i++) {
matchExpression.push(i.toString(), getColorForProjectPosition(i));
}
matchExpression.push(defaultColor);
return matchExpression;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<mgl-geojson-source id="rectangle-source">
<mgl-geojson-source [id]="sourceName">
<mgl-feature [geometry]="rectangleGeometry"></mgl-feature>
</mgl-geojson-source>
<mgl-layer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
'line-color': 'black',
'line-width': 3
}"
sourceLayer="project_area_outline"></mgl-layer>
sourceLayer="project_area_aggregate"></mgl-layer>

<mgl-layer
[id]="layers.stands"
type="fill"
source="stands"
[paint]="paint"
(layerMouseDown)="clickOnLayer($event)"
sourceLayer="treatment_plan_prescriptions"></mgl-layer>
sourceLayer="stands_by_tx_plan"></mgl-layer>

<mgl-layer
[id]="layers.selectedStands"
Expand All @@ -26,7 +26,7 @@
'fill-color': '#007dff',
'fill-opacity': 0.2
}"
sourceLayer="treatment_plan_prescriptions"
sourceLayer="stands_by_tx_plan"
[filter]="[
'in',
['get', 'id'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ export class MapStandsComponent implements OnChanges {
selectedStands$ = this.mapStandsService.selectedStands$;
private initialSelectedStands: number[] = [];

// TODO project_area_aggregate only applies when looking at a specific project area
readonly tilesUrl =
environment.martin_server +
'project_area_outline,treatment_plan_prescriptions/{z}/{x}/{y}';
'project_area_aggregate,stands_by_tx_plan/{z}/{x}/{y}';

readonly layers = {
outline: 'outline-layer',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,9 @@
[mapLibreMap]="mapLibreMap"
[start]="start ? start.lngLat : null"
[end]="end ? end.lngLat : null"></app-map-rectangle>

<app-map-project-areas
*ngIf="scenarioId"
[mapLibreMap]="mapLibreMap"
[scenarioId]="scenarioId"></app-map-project-areas>
</mgl-map>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, Input } from '@angular/core';
import { JsonPipe, NgForOf } from '@angular/common';
import { JsonPipe, NgForOf, NgIf } from '@angular/common';
import {
DraggableDirective,
FeatureComponent,
Expand All @@ -15,6 +15,7 @@ import { MapRectangleComponent } from '../map-rectangle/map-rectangle.component'
import { SelectedStandsState } from './selected-stands.state';
import { MapControlsComponent } from '../map-controls/map-controls.component';
import { environment } from '../../../environments/environment';
import { MapProjectAreasComponent } from '../map-project-areas/map-project-areas.component';

@Component({
selector: 'app-treatment-map',
Expand All @@ -31,6 +32,8 @@ import { environment } from '../../../environments/environment';
MapStandsComponent,
MapRectangleComponent,
MapControlsComponent,
MapProjectAreasComponent,
NgIf,
],
providers: [SelectedStandsState],
templateUrl: './treatment-map.component.html',
Expand All @@ -43,6 +46,7 @@ export class TreatmentMapComponent {
// TODO: should we keep using prop drilling here? Consider using a provider service to hold these values
@Input() projectAreaId: number | null = null;
@Input() treatmentPlanId = 0;
@Input() scenarioId: number | null = null;

treatedStands: { id: number; assigment: string }[] = [];

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<app-treatment-summary
[treatmentPlanId]="treatmentPlanId"></app-treatment-summary>

<app-treatment-map [treatmentPlanId]="treatmentPlanId"></app-treatment-map>
<app-treatment-map
[treatmentPlanId]="treatmentPlanId"
[scenarioId]="scenarioId"></app-treatment-map>
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { TreatmentSummaryComponent } from '../treatment-summary/treatment-summar
export class TreatmentOverviewComponent implements OnInit {
treatmentPlanId: number = this.route.snapshot.data['treatmentId'];
treatmentPlan: TreatmentPlan | null = null;
scenarioId: number = this.route.snapshot.data['scenarioId'];

constructor(
private treatmentsService: TreatmentsService,
Expand Down
3 changes: 2 additions & 1 deletion src/interface/src/app/types/scenario.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ export interface ScenarioResult {
status: ScenarioResultStatus;
completed_at: string;
result: {
features: FeatureCollection[];
// this is the FeatureCollection[]
features: FeatureCollection[]; // TODO this is actually Features[]
type: string;
};
}
Expand Down

0 comments on commit 0e34cb2

Please sign in to comment.