chore(react/collections/geomap): bring back context menu

This commit is contained in:
Elian Doran 2025-09-04 21:26:09 +03:00
parent dd654fcd8d
commit 189b7e20db
No known key found for this signature in database
7 changed files with 34 additions and 36 deletions

View File

@ -60,7 +60,7 @@ async function confirmDeleteNoteBoxWithNote(title: string) {
return new Promise<ConfirmDialogResult | undefined>((res) => appContext.triggerCommand("showConfirmDeleteNoteBoxWithNoteDialog", { title, callback: res })); return new Promise<ConfirmDialogResult | undefined>((res) => appContext.triggerCommand("showConfirmDeleteNoteBoxWithNoteDialog", { title, callback: res }));
} }
async function prompt(props: PromptDialogOptions) { export async function prompt(props: PromptDialogOptions) {
return new Promise<string | null>((res) => appContext.triggerCommand("showPromptDialog", { ...props, callback: res })); return new Promise<string | null>((res) => appContext.triggerCommand("showPromptDialog", { ...props, callback: res }));
} }

View File

@ -1,8 +1,28 @@
import { LatLng } from "leaflet"; import { LatLng } from "leaflet";
import { LOCATION_ATTRIBUTE } from "."; import { LOCATION_ATTRIBUTE } from ".";
import attributes from "../../../services/attributes"; import attributes from "../../../services/attributes";
import { prompt } from "../../../services/dialog";
import server from "../../../services/server";
import { t } from "../../../services/i18n";
import { CreateChildrenResponse } from "@triliumnext/commons";
const CHILD_NOTE_ICON = "bx bx-pin";
export async function moveMarker(noteId: string, latLng: LatLng | null) { export async function moveMarker(noteId: string, latLng: LatLng | null) {
const value = latLng ? [latLng.lat, latLng.lng].join(",") : ""; const value = latLng ? [latLng.lat, latLng.lng].join(",") : "";
await attributes.setLabel(noteId, LOCATION_ATTRIBUTE, value); await attributes.setLabel(noteId, LOCATION_ATTRIBUTE, value);
} }
export async function createNewNote(noteId: string, e: LeafletMouseEvent) {
const title = await prompt({ message: t("relation_map.enter_title_of_new_note"), defaultValue: t("relation_map.default_new_note_title") });
if (title?.trim()) {
const { note } = await server.post<CreateChildrenResponse>(`notes/${noteId}/children?target=into`, {
title,
content: "",
type: "text"
});
attributes.setLabel(note.noteId, "iconClass", CHILD_NOTE_ICON);
moveMarker(note.noteId, e.latlng);
}
}

View File

@ -3,7 +3,7 @@ import appContext, { type CommandMappings } from "../../../components/app_contex
import contextMenu, { type MenuItem } from "../../../menus/context_menu.js"; import contextMenu, { type MenuItem } from "../../../menus/context_menu.js";
import linkContextMenu from "../../../menus/link_context_menu.js"; import linkContextMenu from "../../../menus/link_context_menu.js";
import { t } from "../../../services/i18n.js"; import { t } from "../../../services/i18n.js";
import { createNewNote } from "./editing.js"; import { createNewNote } from "./api.js";
import { copyTextWithToast } from "../../../services/clipboard_ext.js"; import { copyTextWithToast } from "../../../services/clipboard_ext.js";
import link from "../../../services/link.js"; import link from "../../../services/link.js";

View File

@ -3,7 +3,7 @@ import "./index.css";
import { ViewModeProps } from "../interface"; import { ViewModeProps } from "../interface";
import { useNoteLabel, useNoteLabelBoolean, useNoteProperty, useSpacedUpdate } from "../../react/hooks"; import { useNoteLabel, useNoteLabelBoolean, useNoteProperty, useSpacedUpdate } from "../../react/hooks";
import { DEFAULT_MAP_LAYER_NAME } from "./map_layer"; import { DEFAULT_MAP_LAYER_NAME } from "./map_layer";
import { divIcon, LatLng } from "leaflet"; import { divIcon, LatLng, LeafletMouseEvent } from "leaflet";
import { useCallback, useEffect, useMemo, useState } from "preact/hooks"; import { useCallback, useEffect, useMemo, useState } from "preact/hooks";
import Marker from "./marker"; import Marker from "./marker";
import froca from "../../../services/froca"; import froca from "../../../services/froca";
@ -12,6 +12,7 @@ import markerIcon from "leaflet/dist/images/marker-icon.png";
import markerIconShadow from "leaflet/dist/images/marker-shadow.png"; import markerIconShadow from "leaflet/dist/images/marker-shadow.png";
import appContext from "../../../components/app_context"; import appContext from "../../../components/app_context";
import { moveMarker } from "./api"; import { moveMarker } from "./api";
import openContextMenu from "./context_menu";
const DEFAULT_COORDINATES: [number, number] = [3.878638227135724, 446.6630455551659]; const DEFAULT_COORDINATES: [number, number] = [3.878638227135724, 446.6630455551659];
const DEFAULT_ZOOM = 2; const DEFAULT_ZOOM = 2;
@ -84,6 +85,8 @@ function NoteMarker({ note, editable }: { note: FNote, editable: boolean }) {
moveMarker(note.noteId, newCoordinates); moveMarker(note.noteId, newCoordinates);
}, [ note.noteId ]); }, [ note.noteId ]);
const onContextMenu = useCallback((e: LeafletMouseEvent) => openContextMenu(note.noteId, e, editable), [ note.noteId, editable ]);
return latLng && <Marker return latLng && <Marker
coordinates={latLng} coordinates={latLng}
icon={icon} icon={icon}
@ -91,6 +94,7 @@ function NoteMarker({ note, editable }: { note: FNote, editable: boolean }) {
onMouseDown={onMouseDown} onMouseDown={onMouseDown}
onDragged={editable ? onDragged : undefined} onDragged={editable ? onDragged : undefined}
onClick={!editable ? onClick : undefined} onClick={!editable ? onClick : undefined}
onContextMenu={onContextMenu}
/> />
} }

View File

@ -1,6 +1,6 @@
import { useContext, useEffect } from "preact/hooks"; import { useContext, useEffect } from "preact/hooks";
import { ParentMap } from "./map"; import { ParentMap } from "./map";
import { DivIcon, Icon, LatLng, Marker as LeafletMarker, marker, MarkerOptions } from "leaflet"; import { DivIcon, Icon, LatLng, Marker as LeafletMarker, LeafletMouseEvent, marker, MarkerOptions } from "leaflet";
export interface MarkerProps { export interface MarkerProps {
coordinates: [ number, number ]; coordinates: [ number, number ];
@ -8,10 +8,11 @@ export interface MarkerProps {
onClick?: () => void; onClick?: () => void;
onMouseDown?: (e: MouseEvent) => void; onMouseDown?: (e: MouseEvent) => void;
onDragged?: ((newCoordinates: LatLng) => void); onDragged?: ((newCoordinates: LatLng) => void);
onContextMenu: (e: LeafletMouseEvent) => void;
draggable?: boolean; draggable?: boolean;
} }
export default function Marker({ coordinates, icon, draggable, onClick, onDragged, onMouseDown }: MarkerProps) { export default function Marker({ coordinates, icon, draggable, onClick, onDragged, onMouseDown, onContextMenu }: MarkerProps) {
const parentMap = useContext(ParentMap); const parentMap = useContext(ParentMap);
useEffect(() => { useEffect(() => {
@ -41,6 +42,10 @@ export default function Marker({ coordinates, icon, draggable, onClick, onDragge
}); });
} }
if (onContextMenu) {
newMarker.on("contextmenu", e => onContextMenu(e))
}
newMarker.addTo(parentMap); newMarker.addTo(parentMap);
return () => newMarker.removeFrom(parentMap); return () => newMarker.removeFrom(parentMap);

View File

@ -9,29 +9,6 @@ import type { DragData } from "../../note_tree.js";
import froca from "../../../services/froca.js"; import froca from "../../../services/froca.js";
import branches from "../../../services/branches.js"; import branches from "../../../services/branches.js";
const CHILD_NOTE_ICON = "bx bx-pin";
// TODO: Deduplicate
interface CreateChildResponse {
note: {
noteId: string;
};
}
export async function createNewNote(noteId: string, e: LeafletMouseEvent) {
const title = await dialog.prompt({ message: t("relation_map.enter_title_of_new_note"), defaultValue: t("relation_map.default_new_note_title") });
if (title?.trim()) {
const { note } = await server.post<CreateChildResponse>(`notes/${noteId}/children?target=into`, {
title,
content: "",
type: "text"
});
attributes.setLabel(note.noteId, "iconClass", CHILD_NOTE_ICON);
moveMarker(note.noteId, e.latlng);
}
}
export function setupDragging($container: JQuery<HTMLElement>, map: Map, mapNoteId: string) { export function setupDragging($container: JQuery<HTMLElement>, map: Map, mapNoteId: string) {
$container.on("dragover", (e) => { $container.on("dragover", (e) => {
// Allow drag. // Allow drag.

View File

@ -7,14 +7,6 @@ import L from "leaflet";
let gpxLoaded = false; let gpxLoaded = false;
export default function processNoteWithMarker(map: Map, note: FNote, location: string, isEditable: boolean) {
newMarker.on("contextmenu", (e) => {
openContextMenu(note.noteId, e, isEditable);
});
return newMarker;
}
export async function processNoteWithGpxTrack(map: Map, note: FNote) { export async function processNoteWithGpxTrack(map: Map, note: FNote) {
if (!gpxLoaded) { if (!gpxLoaded) {
const GPX = await import("leaflet-gpx"); const GPX = await import("leaflet-gpx");