Skip to content

Commit 7dfdd09

Browse files
committed
fixed editor path
1 parent 0dd7a1d commit 7dfdd09

3 files changed

Lines changed: 93 additions & 4 deletions

File tree

pages/workspace/[id]/projects/[projectId].vue renamed to pages/workspace/[id]/projects/[projectId]/index.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,9 +458,9 @@ function buildTabRoute(tab: WorkspaceProjectDetailTab) {
458458
};
459459
}
460460
461-
function buildTaskEditorRoute(taskNumber: number) {
461+
function buildTaskEditorRoute(taskId: string) {
462462
return {
463-
path: `/workspaces/${workspaceId}/${projectId}/${taskNumber}/editor`,
463+
path: `/workspace/${workspaceId}/projects/${projectId}/tasks/${taskId}/editor`,
464464
};
465465
}
466466
@@ -560,7 +560,7 @@ async function handleSelectedTaskAction() {
560560
}
561561
}
562562
563-
await navigateTo(buildTaskEditorRoute(taskToOpen.taskNumber));
563+
await navigateTo(buildTaskEditorRoute(taskToOpen.id));
564564
}
565565
566566
async function handleActivateProject() {

pages/workspaces/[workspaceId]/[projectId]/[taskId]/editor.vue renamed to pages/workspace/[id]/projects/[projectId]/tasks/[taskId]/editor.vue

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,10 @@ import type {
145145
WorkspaceProjectTaskFeedbackReasonCategory,
146146
WorkspaceProjectTaskSubmitFeedback,
147147
} from '~/types/projects';
148+
import { shapeToCenter } from '~/util/geojson';
148149
149150
const route = useRoute();
150-
const workspaceId = Number(route.params.workspaceId);
151+
const workspaceId = Number(route.params.id);
151152
const projectId = String(route.params.projectId);
152153
const taskId = String(route.params.taskId);
153154
const editorContainer = ref<HTMLDivElement | null>(null);
@@ -232,6 +233,7 @@ onMounted(() => {
232233
}
233234
234235
editorContainer.value.appendChild(manager.containerNode);
236+
syncTaskHash();
235237
void manager.switchWorkspace(workspaceId);
236238
});
237239
@@ -261,13 +263,47 @@ async function loadTaskDetail(): Promise<WorkspaceProjectTaskDetail> {
261263
);
262264
}
263265
catch (error) {
266+
const fallbackTaskDetail = await loadTaskDetailByTaskNumber(taskId, error);
267+
268+
if (fallbackTaskDetail) {
269+
return fallbackTaskDetail;
270+
}
271+
264272
throw createError({
265273
statusCode: 500,
266274
statusMessage: 'Failed to load task details',
267275
data: error,
268276
});
269277
}
270278
}
279+
280+
async function loadTaskDetailByTaskNumber(
281+
taskIdentifier: string,
282+
error: unknown,
283+
): Promise<WorkspaceProjectTaskDetail | null> {
284+
if (!(error instanceof WorkspaceProjectsClientError) || error.response.status !== 404) {
285+
return null;
286+
}
287+
288+
const taskNumber = Number(taskIdentifier);
289+
290+
if (!Number.isInteger(taskNumber) || taskNumber < 1) {
291+
return null;
292+
}
293+
294+
const tasks = await workspaceProjectsClient.getWorkspaceProjectTasks(workspaceId, projectId);
295+
const matchedTask = tasks.find(candidate => candidate.taskNumber === taskNumber);
296+
297+
if (!matchedTask) {
298+
return null;
299+
}
300+
301+
return await workspaceProjectsClient.getWorkspaceProjectTaskDetail(
302+
workspaceId,
303+
projectId,
304+
matchedTask.id,
305+
);
306+
}
271307
function handleTaskAction(actionId: 'complete' | 'skip') {
272308
if (hasActiveEdits.value) {
273309
return;
@@ -327,6 +363,23 @@ function buildFeedbackPayload(): WorkspaceProjectTaskSubmitFeedback | undefined
327363
reasonCategory: feedbackReasonCategory.value || undefined,
328364
};
329365
}
366+
function generateInitialHash() {
367+
const center = shapeToCenter(task.geometry);
368+
const lat = center[0];
369+
const lon = center[1];
370+
const zoom = 17;
371+
return `#map=${zoom}/${lat}/${lon}`;
372+
}
373+
374+
function syncTaskHash() {
375+
if (!task.geometry) {
376+
return;
377+
}
378+
379+
const initialHash = generateInitialHash();
380+
const nextUrl = `${window.location.pathname}${window.location.search}${initialHash}`;
381+
window.history.replaceState(window.history.state, '', nextUrl);
382+
}
330383
331384
async function submitCompletedMapping() {
332385
submitErrorMessage.value = '';
@@ -399,6 +452,7 @@ function mountEditor() {
399452
}
400453
401454
editorContainer.value.appendChild(manager.containerNode);
455+
syncTaskHash();
402456
void manager.init(workspaceId);
403457
}
404458

util/geojson.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,38 @@ export function bboxToPolygon(
2525
}
2626
}
2727
}
28+
export function polygonToBbox(polygonGeometry: any) {
29+
if (
30+
polygonGeometry.type !== 'Polygon' ||
31+
!Array.isArray(polygonGeometry.coordinates) ||
32+
polygonGeometry.coordinates.length === 0
33+
) {
34+
throw new Error('Invalid GeoJSON Polygon feature')
35+
}
36+
37+
const coordinates = polygonGeometry.coordinates[0]
38+
let minLat = Infinity
39+
let minLon = Infinity
40+
let maxLat = -Infinity
41+
let maxLon = -Infinity
42+
43+
for (const [lon, lat] of coordinates) {
44+
if (lat < minLat) minLat = lat
45+
if (lat > maxLat) maxLat = lat
46+
if (lon < minLon) minLon = lon
47+
if (lon > maxLon) maxLon = lon
48+
}
49+
50+
return [minLat, minLon, maxLat, maxLon]
51+
}
52+
53+
export function shapeToCenter(shape: any) {
54+
if (shape.type === 'Polygon') {
55+
const bbox = polygonToBbox(shape)
56+
const centerLat = (bbox[0] + bbox[2]) / 2
57+
const centerLon = (bbox[1] + bbox[3]) / 2
58+
return [centerLat, centerLon]
59+
} else {
60+
throw new Error('Invalid GeoJSON Polygon feature')
61+
}
62+
}

0 commit comments

Comments
 (0)