Feature pat filemanager#1592
Conversation
d1f8425 to
a3eabff
Compare
|
This is close to being ready. Only missig feature is the reordering function from pat-structure, which will be added by @petschki. Then we can release this with the next plone.staticresources release, so people can start using it in Plone 6 project, by overriding the folder_contents.pt: |
Add a new pat-filemanager pattern built with Svelte 5 runes, covering content browsing, breadcrumbs, pagination, filtering, upload, clipboard operations, workflow/rename/tags/properties modals, and configurable columns, backed by plone.restapi. Extend the build chain with TypeScript support: babel preset-typescript, svelte-preprocess in webpack and svelte.config, dedicated webpack rules for .ts and .svelte.(js|ts), tsconfig.json, and custom Jest transformers for Svelte components and runes-in-module files.
Store the listing batch size and visible-column config in a cookie (matching legacy pat-structure) instead of the patternslib localStorage store, so the view survives reloads the same way the old structure view did.
Apply Svelte's animate:flip to the listing rows and the column-config list so drag reordering slides items into place. To satisfy flip's "immediate child of a keyed each" rule, lift the row <tr> (with its drag handlers) from ContentRow into ContentTable and drop the now-redundant ContentRow component. moveTo now reorders the items array optimistically so the rows flip right away, then PATCHes the server and reconciles via a silent reload that does not toggle `loading` — previously the loading placeholder tore down the keyed rows, so flip never ran.
Update the spec for the post-P6 follow-ups: switch the batch-size and column persistence notes from localStorage to the cookie-backed storage util, record that ContentRow was merged into ContentTable so animate:flip can run on the row element, and add §19 covering the optimistic-reorder / silent-reload animation fix.
Move the spec into the pattern dir and ignore stamp-yarn.
Render the upload list inside the filemanager-status element with a derived summary header, a corner close button and ESC-to-close, instead of a separate panel and a duplicate status message. Drops the redundant reportUpload() summary.
Add a user-switchable listing view: the existing table plus a new photo-organizing grid. ViewStore (cookie-persisted, seeded from a new default-view config arg) drives a ViewSwitcher in the toolbar and the table/grid swap in App. Shared selection and drag/drop logic is extracted from ContentTable into a ListInteractions store reused by both views (unit-tested). ContentGrid renders cards with larger previews via a thumbnailUrl scale-fallback chain.
Upgrade the hand-rolled role="dialog" overlay to the native <dialog> element driven by showModal()/close() from an $effect on modal.isOpen. The browser provides the focus move/trap/restore, ::backdrop, page inertness and Escape handling, so the manual focus trap and window keydown handler are gone. ModalStore gains toggle(); the toolbar's State/Tags/Properties/Rename buttons toggle the dialog and reflect it with aria-pressed.
Move ColumnsConfig out of the toolbar into the table's actions-column header: the toggle is now a 3-dots icon button labelled "Column settings" (aria-haspopup/expanded/title), and its popover opens toward the table (right: 0) so it doesn't run off the edge. Living in the table header makes it table-only by construction, so the grid-mode guard in App is no longer needed.
Add a native Svelte QueryBuilder mirroring pat-structure's QueryString
widget: rows of index/operation/value that serialise to
plone.app.querystring {i,o,v} criteria, sourced from @querystring.
Supported widgets: String, Date, DateRange, RelativeDate,
MultipleSelection, Reference/RelativePath (as text).
Wire extraCriteria through ContentsStore (buildQuery, applyFilters,
clearFilters, hasActiveFilters, navigateTo reset) and host the builder
in a FilterBar popover alongside the existing search and type filters.
…-all - sort and drag reorder reconcile via a silent reload so the keyed rows stay mounted and flip into place instead of snapping - live drag preview shows an insertion bar in the gap between siblings and keeps the dragged item visible - contiguous multi-row selections drag and drop as one block, committed as a sequence of single restapi ordering moves against a working order - grid view gains a select-all / deselect-all header to reset the selection
…yout - toolbar actions reordered like pat-structure and rendered as an icon button group (Plone @@iconresolver icons); the Delete icon is tinted red - the selection count is replaced by a reusable select-all/deselect control (SelectAll), dropping the separate Clear selection button - move-into-folder now asks for confirmation through a native <dialog> (ConfirmStore/ConfirmDialog), defaulting to and highlighting "Move" - drop the type filter; move search and the advanced filter to the right of the action row, opening the filter popover right-aligned
…avigation to the portal root Render the breadcrumbs beneath the toolbar instead of above it and right-align the toolbar controls. Resolve a portalUrl from the folder_contents urlStructure.base (get_top_site_from_url) so "go up" / breadcrumb navigation can climb out of a navigation root such as a plone.app.multilingual language folder back to the portal root.
Add a five-stage (xs–xl) size slider, shown in the filter bar while the grid view is active, that scales the card min-width via .grid-size-* classes. The chosen scale is remembered as a cookie preference (medium by default), kept on the ViewStore alongside the view mode.
… selection, checkbox) Grid card drag-and-drop and selection refinements: - Reorder via three-band drag zones (before/into/after) shared with the table, and a live insertion marker that tracks the drop gap. At a row boundary the marker no longer jumps to an adjacent row: a forward drop past a row's last image shows on that card's trailing edge, while a backward drop before a row's first image stays on its leading edge. - Clicking a card toggles its selection (a second click deselects it, like Space and the checkbox); the table keeps click-to-replace. - Replace the custom checkbox with check-circle / check-circle-fill icons, inset from the card corner, and drop the review-state marker.
…grid Replace the custom native-HTML5 reorder (live movePreview/animate:flip preview, per-row drag handlers, three-band folder-zone geometry, grid wrap-marker) with sortablejs, wrapped in a small Svelte use: action (utils/sortable.ts). The reorder/move-into-folder/move-into-parent decisions stay in the shared ListInteractions controller via dragStart/ dragMove/dragEnd; the action reverts sortablejs's DOM move so Svelte's keyed each stays the source of truth. Folders are solid drop targets: dragMove never lets sortablejs swap the dragged item with a folder, so it stays put under the pointer and the whole row/card is a reliable move-into target (fixes drag-into-folder in the vertical table, where row swaps made folders slide away). Reordering past a folder still works via the next non-folder item. External file-drop (upload into subfolder/parent) stays on native DOM events, file-only while a sortablejs drag is active. Verified end-to-end in a live Plone Classic listing: drag-into-folder (table + grid) and drag-into-parent (grid). Also fix the progress dialog showing as an empty bordered box over the listing: scope its display:flex to [open] so a closed dialog keeps the UA display:none.
… other actions Match the toolbar action buttons (1px border, 6px radius, white bg, same padding) so select-all reads as one of the actions instead of a bare checkbox + label.
Replace the prev/next text buttons with chevron icons and the per-page select with a segmented button group (matching ViewSwitcher and pat-structure), and scroll the app back to the top after paging or resizing the batch.
…ayout shift Render greyed-out skeleton rows (table) and cards (grid) during loading instead of collapsing the listing to a one-line message, so the loaded content drops into the same space without a jump. A new placeholderCount getter sizes the skeleton from the previous page's item count (exact when paging/sorting within a folder), falling back to a modest screenful on a fresh load. Images already use loading=lazy in both views.
Icons resolved asynchronously and rendered nothing until ready, so action buttons and rows reflowed as each icon popped in. Always render the sized icon container so it reserves its final footprint from first paint; the SVG fills that box once resolveIcon settles.
Add an arrows-move button to each grid card (manual-order only) that puts the card into move-mode, after which Arrow keys step it one slot backward (Up/Left) or forward (Down/Right) through the listing. Esc/Enter leaves the mode; steps past either end are ignored and the card keeps focus across repeated presses. Reuses the existing optimistic reorder path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Each arrow step committed via moveTo, which awaited a server PATCH and a reload per keystroke. A second press before the round-trip finished sent a subset_ids from the not-yet-committed order; the server rejected it and the error path's full (non-silent) reload swapped in the loading skeleton, destroying the focused card so the keys stopped landing. Mirror the drag flow instead: each step is a local-only movePreview (instant, focus kept), and the accumulated reorder is committed once via commitReorder on leaving move-mode (Escape/Enter, the button, switching cards, or blurring away). No per-keystroke requests, no skeleton swap, no races. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The keyboard move-mode (arrows-move button + Arrow-key repositioning) did not work well in practice, so back it out. Removes the move button, the is-moving styling, and the ListInteractions move-mode logic and tests, returning the grid to drag-and-drop reordering only. Keeps the unrelated unselected-card icon change (check-circle -> circle). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fix(pat filemanager): item hover background.
5dfe754 to
7e79f09
Compare
Add §25 covering the link-integrity warning on delete (checkLinkIntegrity API, ModalStore data payload, Toolbar delete flow, LinkIntegrityForm). Update §16 to drop the link-integrity item from planned features and §24 to reflect the trimmed Title/ID rearrange sort options. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ntents Dropping an OS folder (onto the listing, a subfolder row, or the "up to parent" card) now recreates the folder tree in Plone and uploads every nested file, after a calculated preview + approval step. Plain file drops are unchanged (immediate upload, no preview). dataTransfer.files is a flat FileList that silently omits directories, so dragging a folder previously uploaded nothing. Read directories via the webkitGetAsEntry() entries API instead. - utils/dropentries.ts: capture top-level entries synchronously during the drop, walk them into a DropManifest (files+relative paths, dirs parents-first, counts/size); drains the paginated readEntries(); degrades to the flat path when the API is absent. - api/upload.js createFolder() + UploadStore.uploadTree(): create folders parents-first (mapping each path to the real @id), upload files into them reusing the existing per-file progress panel; folder-create failures orphan descendants without aborting the batch. - FolderDropStore + FolderDropPreview.svelte: approval gate modelled on ConfirmStore/ConfirmDialog; shows summary + indented folder tree. - ListInteractions.handleExternalDrop(): single orchestrator that all external drops (UploadZone, subfolder row, parent card) route through. - Configurable folderType option (parser arg folder-type, default "Folder"). - Tests for dropentries, uploadTree, createFolder, FolderDropStore; CSS; README + spec updates. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
feature implementation: Folder drop → recreate structure & upload contentsDropping an OS folder (onto the list, a subfolder row, or the "up one level" card) now recreates the folder tree in Plone and uploads all nested files — after a preview + approval step. Plain file drops are unchanged. Why: Changes
Tests/build: new tests for dropentries / uploadTree / createFolder / FolderDropStore; full suite green; dev build compiles. Note: folder reading works on drag&drop only, not the upload button ( |


If your pull request closes an open issue, include the exact text below, immediately followed by the issue number. When your pull request gets merged, then that issue will close automatically.
Closes #