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

Fly to nearby MapRoulette challenge #1618

Merged
merged 7 commits into from
Dec 3, 2024
2 changes: 2 additions & 0 deletions data/core.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,8 @@ en:
comment: Please confirm
cancel: Cancel
submit: Submit
nearbyTask:
title: Jump to nearby task
keepRight:
tooltip: Data issues detected by keepright.at
title: KeepRight Issues
Expand Down
5 changes: 4 additions & 1 deletion data/l10n/core.en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,10 @@
"inputPlaceholder": "Change comment (optional)",
"comment": "Please confirm",
"cancel": "Cancel",
"submit": "Submit"
"submit": "Submit",
"nearbyTask": {
"title": "Jump to nearby task"
}
},
"keepRight": {
"tooltip": "Data issues detected by keepright.at",
Expand Down
90 changes: 90 additions & 0 deletions modules/services/MapRouletteService.js
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,96 @@ export class MapRouletteService extends AbstractSystem {
}


/**
* flyToNearbyTask
* Initiates the process to find and fly to a nearby task based on the current task's challenge ID and task ID.
* @param {Object} task - The current task object containing task details.
*/
flyToNearbyTask(task) {
if (!this.nearbyTaskEnabled) return;
const challengeID = task.parentId;
const taskID = task.id;
if (!challengeID || !taskID) return;
this.filterNearbyTasks(challengeID, taskID);
}


/**
* getChallengeDetails
* Retrieves challenge details from cache or API.
* @param {string} challengeID - The ID of the challenge.
* @returns {Promise} Promise resolving with challenge data.
*/
getChallengeDetails(challengeID) {
const cachedChallenge = this._cache.challenges.get(challengeID);
if (cachedChallenge) {
return Promise.resolve(cachedChallenge);
} else {
const challengeUrl = `${MAPROULETTE_API}/challenge/${challengeID}`;
return fetch(challengeUrl)
.then(utilFetchResponse);
}
}


/**
* filterNearbyTasks
* Fetches nearby tasks for a given challenge and task ID, and flies to the nearest task.
* @param {string} challengeID - The ID of the challenge.
* @param {string} taskID - The ID of the current task.
* @param {number} [zoom] - Optional zoom level for the map.
*/
filterNearbyTasks(challengeID, taskID, zoom) {
const nearbyTasksUrl = `${MAPROULETTE_API}/challenge/${challengeID}/tasksNearby/${taskID}?excludeSelfLocked=true&limit=1`;
if (!taskID) return;
fetch(nearbyTasksUrl)
.then(utilFetchResponse)
.then(nearbyTasks => {
if (nearbyTasks.length > 0) {
const nearestTaskData = nearbyTasks[0];
nearestTaskData.parentId = nearestTaskData.parent.toString();
return this.getChallengeDetails(challengeID)
.then(challengeData => {
// Set the title and parentName using the challenge name
nearestTaskData.title = challengeData.name;
nearestTaskData.parentName = challengeData.name;

// Create a new QAItem with the updated title and parentName
const nearestTask = new QAItem(this, null, nearestTaskData.id.toString(), nearestTaskData);
const [lng, lat] = nearestTask.location.coordinates;

const map = this.context.systems.map;
if (map) {
map.centerZoomEase([lng, lat], zoom);
this.selectAndDisplayTask(nearestTask);
}
});
}
})
.catch(err => {
console.error('Error fetching nearby tasks for challenge:', challengeID, err);
});
}


/**
* selectAndDisplayTask
* Selects a task and updates the sidebar reflect the selection
* @param {QAItem} task - The task to be selected
*/
selectAndDisplayTask(task) {
const maproulette = this.context.services.maproulette;
if (maproulette) {
if (!(task instanceof QAItem)) return;

maproulette.currentTask = task;
const selection = new Map();
selection.set(task.id, task);
this.context.enter('select', { selection });
}
}


/**
* itemURL
* Returns the url to link to task about a challenge
Expand Down
30 changes: 28 additions & 2 deletions modules/ui/maproulette_editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,18 @@ export function uiMapRouletteEditor(context) {
notAnIssue(d3_event, d, selection);
});

const checkboxSection = buttonEnter.append('div')
.attr('class', 'checkbox-section');
checkboxSection
.append('input')
.attr('type', 'checkbox')
.attr('id', 'nearbyTaskCheckbox')
.property('checked', maproulette.nearbyTaskEnabled)
.on('change', nearbyTaskChanged);
checkboxSection
.append('label')
.attr('for', 'nearbyTaskCheckbox')
.text(l10n.t('map_data.layers.maproulette.nearbyTask.title'));

function isSaveDisabled(d) {
return (hasAuth && d.service === 'maproulette') ? null : true;
Expand All @@ -382,6 +394,16 @@ export function uiMapRouletteEditor(context) {
}


function nearbyTaskChanged(d3_event) {
const isChecked = d3_event.target.checked;
const mapRouletteService = context.services.maproulette;
if (mapRouletteService) {
mapRouletteService.nearbyTaskEnabled = isChecked;
// console.log('Nearby Task feature is now', isChecked ? 'enabled' : 'disabled');
}
}


function setSaveButtonVisibility(isVisible) {
if (isVisible) {
d3_select('.note-save').style('display', 'block'); // Show the commentSaveSection
Expand Down Expand Up @@ -443,7 +465,7 @@ export function uiMapRouletteEditor(context) {
buttonSection.select('.submit-button')
.text(l10n.t('map_data.layers.maproulette.submit'))
.on('click.submit', function(d3_event, d) {
clickSumbit(d3_event, d, selection);
clickSubmit(d3_event, d, selection);
});
}

Expand Down Expand Up @@ -489,7 +511,7 @@ export function uiMapRouletteEditor(context) {
selection.call(commentSaveSection);
}

function clickSumbit(d3_event, d) {
function clickSubmit(d3_event, d) {
this.blur(); // avoid keeping focus on the button - iD#4641
const osm = context.services.osm;
const userID = osm._userDetails.id;
Expand All @@ -505,6 +527,10 @@ export function uiMapRouletteEditor(context) {
return;
}
dispatch.call('change', item);
// Fly to a nearby task if the feature is enabled, after the update
if (maproulette.nearbyTaskEnabled) {
maproulette.flyToNearbyTask(d);
}
});
}
}
Expand Down
Loading