-
Notifications
You must be signed in to change notification settings - Fork 3
zoom to all fiscal polygons, not only current year, add helper methods to handle activity boundaries #584
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
zoom to all fiscal polygons, not only current year, add helper methods to handle activity boundaries #584
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
.map-container{ | ||
margin-top: 12px; | ||
} | ||
} | ||
|
||
#fiscalMap { | ||
height: 100%; | ||
width: 100%; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,8 +27,8 @@ export class FiscalMapComponent implements AfterViewInit, OnDestroy, OnInit { | |
}; | ||
|
||
constructor( | ||
private projectService: ProjectService, | ||
private route: ActivatedRoute, | ||
readonly projectService: ProjectService, | ||
readonly route: ActivatedRoute, | ||
protected router: Router, | ||
) {} | ||
|
||
|
@@ -66,18 +66,18 @@ export class FiscalMapComponent implements AfterViewInit, OnDestroy, OnInit { | |
const lat = parseFloat(this.projectLatitude); | ||
const lng = parseFloat(this.projectLongitude); | ||
|
||
const marker = L.marker([lat, lng]).addTo(this.map); | ||
L.marker([lat, lng]).addTo(this.map); | ||
|
||
this.map.setView([lat, lng], 14); | ||
} | ||
} | ||
}) | ||
} | ||
getProjectBoundary() { | ||
this.projectGuid = this.route.snapshot?.queryParamMap?.get('projectGuid') || ''; | ||
this.projectGuid = this.route.snapshot?.queryParamMap?.get('projectGuid') ?? ''; | ||
if (this.projectGuid) { | ||
this.projectService.getProjectBoundaries(this.projectGuid).subscribe((data) => { | ||
const boundary = data?._embedded?.projectBoundary || []; | ||
const boundary = data?._embedded?.projectBoundary ?? []; | ||
this.projectBoundary = boundary; | ||
|
||
if (this.map && boundary.length > 0) { | ||
|
@@ -86,71 +86,85 @@ export class FiscalMapComponent implements AfterViewInit, OnDestroy, OnInit { | |
}); | ||
} | ||
} | ||
getAllActivitiesBoundaries() { | ||
this.projectGuid = this.route.snapshot?.queryParamMap?.get('projectGuid') || ''; | ||
|
||
if (this.projectGuid) { | ||
this.projectService.getProjectFiscalsByProjectGuid(this.projectGuid).subscribe((data) => { | ||
this.projectFiscals = (data._embedded?.projectFiscals || []).sort( | ||
(a: { fiscalYear: number }, b: { fiscalYear: number }) => a.fiscalYear - b.fiscalYear | ||
); | ||
|
||
const activityRequests = this.projectFiscals.map(fiscal => | ||
this.projectService.getFiscalActivities(this.projectGuid, fiscal.projectPlanFiscalGuid).pipe( | ||
map((response: any) => { | ||
const activities = response?._embedded?.activities || []; | ||
return activities.map((activity: any) => ({ | ||
...activity, | ||
fiscalYear: fiscal.fiscalYear, | ||
projectPlanFiscalGuid: fiscal.projectPlanFiscalGuid | ||
})); | ||
}) | ||
) | ||
); | ||
|
||
forkJoin(activityRequests).subscribe((allActivityArrays) => { | ||
const allActivities = allActivityArrays.flat(); | ||
|
||
if (allActivities.length === 0) { | ||
// no activites at all. | ||
this.getProjectCoordinates(); | ||
return; | ||
} | ||
const boundaryRequests = allActivities.map(activity => | ||
this.projectService | ||
.getActivityBoundaries(this.projectGuid, activity.projectPlanFiscalGuid, activity.activityGuid) | ||
.pipe( | ||
map(boundary => boundary ? ({ | ||
activityGuid: activity.activityGuid, | ||
fiscalYear: activity.fiscalYear, | ||
boundary: boundary?._embedded?.activityBoundary | ||
}) : null), | ||
) | ||
); | ||
|
||
forkJoin(boundaryRequests).subscribe((allResults) => { | ||
this.allActivityBoundaries = allResults.filter(r => | ||
r !== null && r.boundary && Object.keys(r.boundary).length > 0 | ||
); | ||
const hasActivityPolygons = this.allActivityBoundaries.length > 0; | ||
const hasProjectPolygons = this.projectBoundary?.length > 0; | ||
|
||
if (hasActivityPolygons && this.map) { | ||
this.plotBoundariesOnMap(this.allActivityBoundaries); | ||
} | ||
|
||
// Only show pin if NO polygons exist at all | ||
if (!hasActivityPolygons && !hasProjectPolygons) { | ||
this.getProjectCoordinates(); | ||
} | ||
}); | ||
}); | ||
}); | ||
getAllActivitiesBoundaries(): void { | ||
this.projectGuid = this.route.snapshot?.queryParamMap?.get('projectGuid') ?? ''; | ||
if (!this.projectGuid) return; | ||
|
||
this.projectService.getProjectFiscalsByProjectGuid(this.projectGuid).subscribe(data => | ||
this.handleFiscalsResponse(data) | ||
); | ||
} | ||
|
||
private handleFiscalsResponse(data: any): void { | ||
this.projectFiscals = (data._embedded?.projectFiscals ?? []).sort( | ||
(a: { fiscalYear: number }, b: { fiscalYear: number }) => a.fiscalYear - b.fiscalYear | ||
); | ||
|
||
const activityRequests = this.projectFiscals.map(fiscal => | ||
this.projectService.getFiscalActivities(this.projectGuid, fiscal.projectPlanFiscalGuid).pipe( | ||
map(response => this.mapFiscalActivities(response, fiscal)) | ||
) | ||
); | ||
|
||
forkJoin(activityRequests).subscribe(allActivityArrays => | ||
this.handleActivitiesResponse(allActivityArrays.flat()) | ||
); | ||
} | ||
|
||
private mapFiscalActivities(response: any, fiscal: any): any[] { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
const activities = response?._embedded?.activities ?? []; | ||
return activities.map((activity: any) => ({ | ||
...activity, | ||
fiscalYear: fiscal.fiscalYear, | ||
projectPlanFiscalGuid: fiscal.projectPlanFiscalGuid | ||
})); | ||
} | ||
|
||
private handleActivitiesResponse(allActivities: any[]): void { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if (allActivities.length === 0) { | ||
this.getProjectCoordinates(); | ||
return; | ||
} | ||
|
||
const boundaryRequests = allActivities.map(activity => | ||
this.projectService | ||
.getActivityBoundaries(this.projectGuid, activity.projectPlanFiscalGuid, activity.activityGuid) | ||
.pipe( | ||
map(boundary => this.mapActivityBoundary(boundary, activity)) | ||
) | ||
); | ||
|
||
forkJoin(boundaryRequests).subscribe(allResults => | ||
this.handleBoundariesResponse(allResults) | ||
); | ||
} | ||
|
||
private mapActivityBoundary(boundary: any, activity: any): any { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You have a could to types here defined. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good, I will create some objects in model.ts to store them. Will go through the application to use defined type with updated method signature. I will create a separate to address them |
||
return boundary ? { | ||
activityGuid: activity.activityGuid, | ||
fiscalYear: activity.fiscalYear, | ||
boundary: boundary?._embedded?.activityBoundary | ||
} : null; | ||
} | ||
|
||
private handleBoundariesResponse(results: any[]): void { | ||
this.allActivityBoundaries = results.filter(r => r?.boundary && Object.keys(r.boundary).length > 0); | ||
|
||
const hasActivityPolygons = this.allActivityBoundaries.length > 0; | ||
const hasProjectPolygons = this.projectBoundary?.length > 0; | ||
|
||
if (hasActivityPolygons && this.map) { | ||
this.plotBoundariesOnMap(this.allActivityBoundaries); | ||
} | ||
|
||
if (!hasActivityPolygons && !hasProjectPolygons) { | ||
this.getProjectCoordinates(); | ||
} | ||
} | ||
|
||
plotBoundariesOnMap(boundaries: any[]): void { | ||
const currentFiscalPolygons: L.Layer[] = []; | ||
const allFiscalPolygons: L.Layer[] = []; | ||
|
||
boundaries.forEach(boundaryEntry => { | ||
const fiscalYear = boundaryEntry.fiscalYear; | ||
|
@@ -167,20 +181,18 @@ export class FiscalMapComponent implements AfterViewInit, OnDestroy, OnInit { | |
for (const item of boundaryEntry.boundary) { | ||
const geometry = item.geometry; | ||
if (!geometry) continue; | ||
|
||
const geoJsonOptions: L.GeoJSONOptions = { | ||
style: { | ||
color, | ||
weight: fiscalYear === this.currentFiscalYear ? 4 : 2, | ||
fillOpacity: 0.1 | ||
} | ||
}; | ||
|
||
const addToMap = (geom: any) => { | ||
const layer = L.geoJSON(geom, geoJsonOptions).addTo(this.map!); | ||
if (fiscalYear === this.currentFiscalYear) { | ||
currentFiscalPolygons.push(layer); | ||
} | ||
allFiscalPolygons.push(layer); // Track all layers | ||
}; | ||
|
||
if (geometry.type === 'GeometryCollection') { | ||
|
@@ -191,12 +203,11 @@ export class FiscalMapComponent implements AfterViewInit, OnDestroy, OnInit { | |
addToMap(geometry); | ||
} | ||
} | ||
|
||
}); | ||
|
||
// Zoom to current fiscal year polygons | ||
if (currentFiscalPolygons.length > 0) { | ||
const group = L.featureGroup(currentFiscalPolygons); | ||
// Zoom to ALL fiscal year polygons | ||
if (allFiscalPolygons.length > 0) { | ||
const group = L.featureGroup(allFiscalPolygons); | ||
this.map!.fitBounds(group.getBounds(), { padding: [20, 20] }); | ||
} | ||
} | ||
|
@@ -247,17 +258,17 @@ export class FiscalMapComponent implements AfterViewInit, OnDestroy, OnInit { | |
zoomControl: true, | ||
}); | ||
|
||
(this.map.zoomControl as L.Control.Zoom).setPosition('topright'); | ||
(this.map.zoomControl).setPosition('topright'); | ||
|
||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be good to parameterize this. It isn't likely to change much or at all, but just in case. Should we be sticking with openstreetmap or using DataBC BC basemaps? |
||
attribution: '© OpenStreetMap contributors' | ||
}).addTo(this.map); | ||
|
||
const legendHelper = new LeafletLegendService(); | ||
legendHelper.addLegend(this.map!, this.fiscalColorMap); | ||
legendHelper.addLegend(this.map, this.fiscalColorMap); | ||
const bcBounds = L.latLngBounds([48.3, -139.1], [60.0, -114.0]); | ||
this.map.fitBounds(bcBounds, { padding: [20, 20] }); | ||
createFullPageControl(() => this.openFullMap()).addTo(this.map!); | ||
createFullPageControl(() => this.openFullMap()).addTo(this.map); | ||
} | ||
|
||
openFullMap(): void { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try to avoid using "any". You can always define a type and use that instead so it's explicit and we're not just letting anything through. This can also help with error checking