Skip to content
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

Use Mapbox Layer for Cases and User Markers in Microplanning Map #35535

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
59e9f3a
create marker source and layers
zandre-eng Dec 18, 2024
a367470
helper functions to manage source
zandre-eng Dec 18, 2024
1f523a3
refactor mapitem model to work with layer
zandre-eng Dec 18, 2024
b8579ac
create popup when clicking on marker
zandre-eng Dec 18, 2024
a2d34d1
refactor helper functions to select map items
zandre-eng Dec 18, 2024
3ab3869
refactor loading cases to source
zandre-eng Dec 18, 2024
cc90053
refactor loading users to source
zandre-eng Dec 18, 2024
7c8482b
remove redundant helper functions
zandre-eng Dec 18, 2024
4499c7b
refactor assignment class to work with new map item model
zandre-eng Dec 18, 2024
f4a642a
remove cases that are not assigned from case group index
zandre-eng Dec 18, 2024
202dcb9
create entry for each user in case group index
zandre-eng Dec 18, 2024
665fcf1
correctly retrieve coordinates from map item
zandre-eng Dec 18, 2024
a56340a
ensure active poly layer does not clash with streets layers
zandre-eng Dec 18, 2024
b695cc1
update which markers are still selected after clearing the active sav…
zandre-eng Dec 18, 2024
5cdcb2d
make open and close even funcs optional
zandre-eng Dec 18, 2024
dd24468
refactor template to correctly reference link property
zandre-eng Dec 18, 2024
6bda152
ran prettify-changed.sh to fix existing code style issues
zandre-eng Dec 18, 2024
a588115
reference element directly and not through a var
zandre-eng Dec 18, 2024
89ff75c
add coordinates field for use in some helper functions
zandre-eng Dec 18, 2024
1d8fc89
remove unused var
zandre-eng Dec 18, 2024
8499f2a
only wait for map load if polygon filters not loaded yet
zandre-eng Dec 19, 2024
d868d9c
increase pagination size + enforce single page size
zandre-eng Dec 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions corehq/apps/geospatial/reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ class CaseManagementMap(BaseCaseMapReport):

base_template = "geospatial/case_management_base.html"
report_template_path = "geospatial/case_management.html"
max_rows = 7_000
default_rows = 7_000
force_page_size = True

def default_report_url(self):
return reverse('geospatial_default', args=[self.request.project.name])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ hqDefine("geospatial/js/case_grouping_map",[
};

_.each(caseList, function (caseWithGPS) {
const coordinates = caseWithGPS.itemData.coordinates;
const coordinates = caseWithGPS.coordinates;
if (coordinates && coordinates.lat && coordinates.lng) {
caseLocationsGeoJson["features"].push(
{
Expand Down
144 changes: 82 additions & 62 deletions corehq/apps/geospatial/static/geospatial/js/case_management.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'use strict';

Check warning on line 1 in corehq/apps/geospatial/static/geospatial/js/case_management.js

View workflow job for this annotation

GitHub Actions / Lint Javascript

'use strict' is unnecessary inside of modules

hqDefine("geospatial/js/case_management", [
"jquery",
Expand All @@ -16,15 +16,6 @@
utils,
alertUser
) {
const caseMarkerColors = {
'default': "#808080", // Gray
'selected': "#00FF00", // Green
};
const userMarkerColors = {
'default': "#0e00ff", // Blue
'selected': "#0b940d", // Dark Green
};

const MAP_CONTAINER_ID = 'geospatial-map';
const SHOW_USERS_QUERY_PARAM = 'show_users';
const USER_LOCATION_ID_QUERY_PARAM = 'user_location_id';
Expand Down Expand Up @@ -69,21 +60,23 @@

let groupId = 0;
mapModel.caseGroupsIndex = {};
Object.keys(result).forEach((userId) => {
const user = mapModel.userMapItems().find((userModel) => {return userModel.itemId === userId;});
mapModel.caseGroupsIndex[userId] = {groupId: groupId, item: user};

for (const userItem of mapModel.userMapItems()) {
mapModel.caseGroupsIndex[userItem.itemId] = {groupId: groupId, item: userItem};
if (!result[userItem.itemId]) {
groupId++;
continue;
}
mapModel.caseMapItems().forEach((caseModel) => {
if (result[userId].includes(caseModel.itemId)) {
if (result[userItem.itemId].includes(caseModel.itemId)) {
mapModel.caseGroupsIndex[caseModel.itemId] = {
groupId: groupId,
item: caseModel,
assignedUserId: userId,
assignedUserId: userItem.itemId,
};
}
});
groupId += 1;
});
}
self.connectUserWithCasesOnMap();
self.setBusy(false);
};
Expand All @@ -96,8 +89,8 @@
if (!hasSelectedCases || c.isSelected()) {
caseData.push({
id: c.itemId,
lon: c.itemData.coordinates.lng,
lat: c.itemData.coordinates.lat,
lon: c.coordinates.lng,
lat: c.coordinates.lat,
});
}
});
Expand Down Expand Up @@ -138,8 +131,8 @@
if (!hasSelectedUsers || userMapItem.isSelected()) {
userData.push({
id: userMapItem.itemId,
lon: userMapItem.itemData.coordinates.lng,
lat: userMapItem.itemData.coordinates.lat,
lon: userMapItem.coordinates.lng,
lat: userMapItem.coordinates.lat,
});
}
});
Expand Down Expand Up @@ -186,8 +179,8 @@
if ('assignedUserId' in element) {
let user = mapModel.caseGroupsIndex[element.assignedUserId].item;
const lineCoordinates = [
[user.itemData.coordinates.lng, user.itemData.coordinates.lat],
[element.item.itemData.coordinates.lng, element.item.itemData.coordinates.lat],
[user.coordinates.lng, user.coordinates.lat],
[element.item.coordinates.lng, element.item.coordinates.lat],
];
disbursementLinesSource.features.push(
{
Expand Down Expand Up @@ -233,14 +226,17 @@
});
}

function selectMapItemsInPolygons() {
function getMapPolygons() {
let features = mapModel.drawControls.getAll().features;
if (polygonFilterModel.activeSavedPolygon()) {
features = features.concat(polygonFilterModel.activeSavedPolygon().geoJson.features);
}
if (features.length) {
mapModel.selectAllMapItems(features);
}
return features;
}

function selectMapItemsInPolygons() {
const polygons = getMapPolygons();
mapModel.selectAllMapItems(polygons);
}

function initPolygonFilters() {
Expand All @@ -253,8 +249,7 @@
$mapControlDiv.koApplyBindings(polygonFilterModel);
}

var $runDisbursement = $("#btnRunDisbursement");
$runDisbursement.click(function () {
$("#btnRunDisbursement").click(function () {
$('#disbursement-clear-message').hide();
if (mapModel && mapModel.mapInstance && !polygonFilterModel.btnRunDisbursementDisabled()) {
let selectedCases = mapModel.caseMapItems();
Expand Down Expand Up @@ -313,7 +308,7 @@
};

self.loadUsers = function () {
mapModel.removeMarkersFromMap(mapModel.userMapItems());
mapModel.removeItemTypeFromSource('user');
mapModel.userMapItems([]);
self.hasErrors(false);
if (!self.shouldShowUsers()) {
Expand All @@ -327,30 +322,39 @@
url: initialPageData.reverse('get_users_with_gps'),
success: function (data) {
self.hasFiltersChanged(false);
const userData = _.object(_.map(data.user_data, function (userData) {
let features = [];
let userMapItems = [];
const polygonFeatures = getMapPolygons();
for (const userData of data.user_data) {
const gpsData = (userData.gps_point) ? userData.gps_point.split(' ') : [];
const lat = parseFloat(gpsData[0]);
const lng = parseFloat(gpsData[1]);

if (!gpsData.length) {
continue;
}
const coordinates = {
'lat': gpsData[0],
'lng': gpsData[1],
};
const editUrl = initialPageData.reverse('edit_commcare_user', userData.id);
const link = `<a class="ajax_dialog" href="${editUrl}" target="_blank">${userData.username}</a>`;

const userInfo = {
'coordinates': {
'lat': lat,
'lng': lng,
const isInPolygon = mapModel.isMapItemInPolygons(polygonFeatures, coordinates);
const parsedData = {
id: userData.id,
coordinates: coordinates,
link: link,
name: userData.username,
itemType: 'user',
isSelected: isInPolygon,
customData: {
primary_loc_name: userData.primary_loc_name,
},
'link': link,
'type': 'user',
'name': userData.username,
'primary_loc_name': userData.primary_loc_name,
};
return [userData.id, userInfo];
}));

const userMapItems = mapModel.addMarkersToMap(userData, userMarkerColors);
const userMapItem = new models.MapItem(parsedData, mapModel);
userMapItems.push(userMapItem);
features.push(userMapItem.getGeoJson());
}
mapModel.addDataToSource(features);
mapModel.userMapItems(userMapItems);
selectMapItemsInPolygons();
},
error: function () {
self.hasErrors(true);
Expand Down Expand Up @@ -436,20 +440,36 @@
}
}

function beforeLoadCases(caseData) {
loadCases(caseData);
if (mapModel.hasDisbursementLayer()) {
mapModel.removeDisbursementLayer();
}
}

function loadCases(caseData) {
mapModel.removeMarkersFromMap(mapModel.caseMapItems());
mapModel.removeItemTypeFromSource('case');
mapModel.caseMapItems([]);
var casesWithGPS = caseData.filter(function (item) {
return item[1] !== null;
});
// Index by case_id
var casesById = _.object(_.map(casesWithGPS, function (item) {
if (item[1]) {
return [item[0], {'coordinates': item[1], 'link': item[2], 'type': 'case', 'name': item[3]}];
}
}));
const caseMapItems = mapModel.addMarkersToMap(casesById, caseMarkerColors);
let features = [];
let caseMapItems = [];
const polygonFeatures = getMapPolygons();
for (const caseItem of caseData) {
const isInPolygon = mapModel.isMapItemInPolygons(polygonFeatures, caseItem[1]);
const parsedData = {
id: caseItem[0],
coordinates: caseItem[1],
link: caseItem[2],
name: caseItem[3],
itemType: 'case',
isSelected: isInPolygon,
customData: {},
};
const caseMapItem = new models.MapItem(parsedData, mapModel);
caseMapItems.push(caseMapItem);
features.push(caseMapItem.getGeoJson());
}
mapModel.caseMapItems(caseMapItems);
mapModel.addDataToSource(features);
mapModel.fitMapBounds(caseMapItems);
}

Expand Down Expand Up @@ -503,12 +523,12 @@
);
}
} else if (xhr.responseJSON.aaData.length && mapModel.mapInstance) {
loadCases(xhr.responseJSON.aaData);
if (polygonFilterModel) {
selectMapItemsInPolygons();
}
if (mapModel.hasDisbursementLayer()) {
mapModel.removeDisbursementLayer();
beforeLoadCases(xhr.responseJSON.aaData);
} else {
mapModel.mapInstance.on('load', () => {
beforeLoadCases(xhr.responseJSON.aaData);
});
}
}
});
Expand Down
Loading
Loading