Add GPX drag & drop, folder management, delete, and folder-first sort
Uploading is now drag & drop (or click to browse) instead of a form; folders can be created any time, not just during upload; files can be dragged onto a folder to move them, or dropped elsewhere in the tree to move back to the top level; files and folders can be deleted. Both drag sources (an OS file drag and dragging an existing tree entry) land on the same drop targets, told apart by a custom drag payload type versus the browser's own "Files" type. Also sort folders before files in the tree (previously interleaved alphabetically).
This commit is contained in:
1 parent
4e0d2abbd0
commit
d813dd0b20
6 files changed
+440
-66
No files matched your search
+26
-9
@@ -116,20 +116,37 @@ terms, the API is free for personal/non-commercial use.
|
||||
|
||||
== GPX tracks and waypoints
|
||||
|
||||
The "GPX" map control (`public/js/gpx.js`) opens a side panel to upload
|
||||
GPX files and toggle them on the map, individually.
|
||||
The "GPX" map control (`public/js/gpx.js`) opens a side panel to
|
||||
upload GPX files by dragging them in, organize them into folders (also
|
||||
by dragging), and toggle each one on the map individually.
|
||||
|
||||
Storage:: Uploaded files are stored as-is under `data/gpx/`, in
|
||||
whatever folder hierarchy the user types into the upload form (e.g.
|
||||
`Hiking/2026`) — `Maptool::GpxStore`
|
||||
(`lib/maptool/gpx_store.rb`) creates folders as needed. Every path
|
||||
coming from the client (upload folder, file path in a URL) is
|
||||
Storage:: Files are stored as-is under `data/gpx/`, in a
|
||||
folder hierarchy the user manages directly — `Maptool::GpxStore`
|
||||
(`lib/maptool/gpx_store.rb`) provides `save`, `create_folder`,
|
||||
`delete_file`, `delete_folder` and `move`. Every path coming from the
|
||||
client (a folder to create/upload/move into, a file path in a URL) is
|
||||
resolved with `File.expand_path` and checked against the store root
|
||||
before touching the filesystem, so `../..`-style path traversal can't
|
||||
escape `data/gpx/`.
|
||||
escape `data/gpx/`; `delete_folder` additionally refuses an empty path
|
||||
or one that resolves to the store root itself, so it can never `rm
|
||||
-rf` the whole store.
|
||||
`GET /api/gpx/tree` returns the resulting folder/file tree as JSON,
|
||||
which the panel renders recursively (folders as `<details>`, files as
|
||||
a checkbox).
|
||||
a checkbox, both with a delete button).
|
||||
|
||||
Drag & drop:: The dropzone at the top of the panel accepts one or more
|
||||
`.gpx` files (`POST /api/gpx`, multipart) into the top level, or click
|
||||
it to browse instead. An already-uploaded file (a
|
||||
`.gpx-tree__file` row, `draggable`) can be dragged onto a folder to
|
||||
move it there (`POST /api/gpx/move`), or dropped anywhere else in the
|
||||
tree to move it back to the top level; an OS file can also be dropped
|
||||
directly onto a folder to upload straight into it. Both drag sources
|
||||
land on the same drop targets and are told apart by a custom
|
||||
`application/x-gpx-path` drag payload type versus the browser's own
|
||||
`"Files"` type. If a file that's currently checked (visible on the
|
||||
map) gets moved, its map layers are re-added under the new path so it
|
||||
stays visible; if it (or its containing folder) gets deleted, its
|
||||
layers are removed instead.
|
||||
|
||||
Rendering:: Checking a file fetches `GET
|
||||
/api/gpx/file/<path>` — `Maptool::Gpx` (`lib/maptool/gpx.rb`) parses
|
||||
|
||||
Reference in new issue
Block a user