Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ jobs:
run: |
./scripts/test-context-agent.sh
./scripts/test-user-migration.sh
docker compose exec -T --user www-data nextcloud php /var/www/html/custom_apps/proofing_gallery/tests/smoke/CollaborationSelectionSync.php
- name: Verify protected public routes
if: matrix.suite == 'api'
env:
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,14 @@ __pycache__/
/.env
/.env.local
/.env.studio
/.env.*
!/.env.example
/.local/
/.tmp/
/tmp/
/.idea/
/.vscode/
*.log

# graft's local graph cache — regenerable, not committed (run `graft build`).
/graft/
5 changes: 5 additions & 0 deletions .ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# graft's cards are gitignored but should stay greppable: ripgrep reads
# .ignore before .gitignore, so this re-admits the tree to search only.
!graft/
graft/.cache/
graft/.graph/
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@

## Unreleased

- separate general feedback from expandable annotation conversations, keep
panels beside the image detail without dimming artwork, and display review
state names with their configured colors
- retain image-relative annotation positions through transform-only zoom and
right-button panning, and refresh thread placement when opened from Pins
- deliver owner selection updates and deletions to the correct private account
without changing event attribution or guest visibility
- accept empty settings objects during additive user migration and report
migration smoke-test failures with a failing exit status
- make signed-in Nextcloud accounts and public guests first-class collaboration
actors across comments, selections, private ratings, picks, and review rounds
- preserve account UIDs in storage while displaying current Nextcloud names,
enforce actor-specific uniqueness, and purge account-authored collaboration
data when its Nextcloud account is deleted
- retain the existing guest session, export, rating, and review behavior for
backward compatibility

## 0.9.2 — 2026-09-07

- make the mobile gallery and lightbox easier to use with more reliable overlays,
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ Automation, Privacy, and History workspaces.
and server-rendered preview watermarks
- likes, color states, comments, image annotations, named selections, and
CSV/plain-text exports
- separate general comments and expandable pin conversations, with panels beside
the selected detail, color-labelled review states, and account-aware authorship
- individual downloads, selected ZIP files, and printable contact sheets
- resumable guest uploads to a hidden moderation inbox
- user/group gallery managers, activity filters, and opt-in event digests for
Expand Down
48 changes: 48 additions & 0 deletions docs/DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,47 @@ PHP routes, templates, or controller constructors, run
`docker compose restart nextcloud` to clear PHP OPcache before validating the
change.

## Persistent remote test tenant

A Docker-capable Linux VM can be used as a persistent manual-QA tenant when
Docker is not installed on the editing workstation. Keep source and build
dependencies in a staging directory outside the live Nextcloud Compose tree.
Build and test in disposable containers, then copy only a successful runtime
tree into the tenant's `custom_apps/proofing_gallery` directory.

Before deployment, record `occ status`, the enabled-app list, migration state,
and container health. Keep the previous app directory only during the immediate
HTTP, `occ`, log, and browser checks. Restore it only if that deployment fails;
delete it as soon as the replacement passes so the development tenant retains
only the latest verified app build. Never reset the tenant's Compose volumes as
part of an app deployment.

Keep rollback copies outside `custom_apps`; Nextcloud scans every directory in
that path and a backup containing the same app ID can cause duplicate-app
discovery. App Store packages intentionally omit development-only `scripts/`,
so run migration diagnostics from the source staging tree rather than assuming
they are installed with the runtime package.

The persistent tenant is for manual integration and browser QA only. Do not
run this repository's Playwright global setup against it: the current E2E
fixtures assume the disposable `admin` / `admin` tenant, rewrite that user's
preferences, and remove prior `E2E` fixtures. Use `npm run test:e2e` only with
the repository's isolated loopback Compose stack, or refactor the harness for
a dedicated test identity before targeting another tenant.

For frontend-only UI work, a persistent pinned Node container may run
`npm run watch` against the staging checkout. Run the affected Vitest files
during each small iteration and copy only generated `build`, `css`, and `js`
assets into the installed development app. Stable entry assets must be served
without long-lived caching on that development host so a refresh discovers
new content-hashed chunks. Run the complete lint, unit, build, package, PHP,
and compatibility gates at milestones and before publication. Never use the
frontend-only path for PHP, routes, migrations, or dependency changes.

Machine-specific addresses, SSH key locations, credentials, and deployment
commands belong in an ignored local runbook under `.local/`, never in tracked
documentation.

## Documentation sources and builds

The English and German user and administrator guides under `docs/en/` and
Expand Down Expand Up @@ -123,6 +164,13 @@ verify desktop and 390 px mobile layouts, scroll reachability, horizontal
overflow, media hit testing, rows below the hero, and side and bottom filmstrip
placement inside the viewport.

For feedback panels, test the overflow model rather than requiring every item
to fit at once. A history of 20 or more comments must scroll inside the panel;
headers, comment text, identity labels, edit controls, and the composer must not
be clipped, overlapped, or made unreachable at short viewport heights. Selecting
an image annotation may keep its marker visible for context, but the comment
workflow must remain usable without relying on the marker staying on screen.

Playwright global setup creates and later supersedes its own E2E gallery.
Snapshots are intentionally versioned. Update them only after reviewing the
rendered images, preferably through the isolation-preserving wrapper:
Expand Down
7 changes: 6 additions & 1 deletion docs/PRIVACY.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,15 @@ and workflow labels even if those values exist in Files or an XMP sidecar.

## Visibility and retention

Private proofing exposes a guest's feedback only to that guest and gallery
Private proofing exposes an author's feedback only to that guest or account and gallery
managers. Collaborative proofing deliberately shares feedback with other
reviewers. The chosen policy should be communicated before inviting guests.

Signed-in feedback records the existing Nextcloud UID. Historical guest
authorship is not transferred on sign-in. Owner-originated selection events
retain the owner's UID and a separate private account recipient where needed;
neither identity field is added to the public event response.

Guest identities expire after 30 days unless renewed by product behavior.
Scheduled cleanup removes expired identities, abandoned chunks, stale derived
previews, and old internal activity in bounded batches. Owners can revoke the
Expand Down
15 changes: 15 additions & 0 deletions docs/USER-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,21 @@ pick, reject, label, comment, annotate, and save named selections. Guests do
not need Nextcloud accounts. Their identity and mutation token are stored in a
private browser session; clearing site data ends access to private feedback.

If you are signed in to Nextcloud, new feedback uses your account identity.
Earlier guest comments remain linked to their original guest identity; signing
in does not claim them. Account identity does not bypass gallery or link rules.

**Feedback** opens **General comments**, newest first beneath the input.
The **Pins** tab groups point conversations into expandable rows. Expand a row
to read its replies, or use its separate open button to show the conversation
beside the pin. These panels do not dim the image. **Review state** shows both
the configured state name and its color indicator.

Zoom with the viewer controls, mouse wheel, or a touch pinch. On desktop, hold
the right mouse button and drag the zoomed image to pan. A right-click without
dragging keeps the browser context menu. Pins retain their image-relative
positions while zooming and panning.

Click or tap an image to place a numbered point and open its comment editor.
For keyboard placement, choose **Add point comment**, move the point with the
arrow keys, press Enter to write, or Escape to cancel. Unpinned comments remain
Expand Down
14 changes: 14 additions & 0 deletions docs/de/administrationshandbuch.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ Aufbewahrung. Die Regeln werden serverseitig erzwungen und sperren kritische
Funktionen bei Unsicherheit. Native Nextcloud-Regeln für Freigaben, Passwörter,
Ablauf und Uploads bleiben maßgeblich und werden niemals gelockert.

Öffentliche Prüfer können Gastidentitäten oder angemeldete Nextcloud-Konten
verwenden. Konto-UIDs bestimmen die Urheberschaft, nicht zusätzliche Rechte.
Frühere Gastbeiträge werden nicht anhand von Namen oder E-Mail-Adressen
übertragen. Privates Feedback bleibt auf den Autor und berechtigte
Galerieverwalter beschränkt. Eigentümeränderungen an einer Kontoauswahl werden
nur an den zulässigen Empfängerkreis übermittelt. Gast-Uploads bleiben ein
separater, Gästen vorbehaltener Ablauf.

Die Migration der Kontozuordnung behält bei doppelten Konto-Feedbackzeilen die
höchste ID, bevor sie Eindeutigkeitsregeln anlegt; Gastkommentare und Punkte
werden nicht neu zugeordnet. Eine folgende Migration ergänzt eine optionale
Empfänger-UID für Ereignisse, getrennt vom auslösenden Eigentümer. Schließe das
normale Datenbank-Upgrade ab, bevor der neue Anwendungscode bereitgestellt wird.

Prüfe Freigabe-, Mail- und Gruppenrichtlinien vor der Einführung. Aktiviere
Gast-Downloads und -Uploads nur bei Bedarf. Richte Grenzen nach PHP, Proxy,
Speicher und Worker-Kapazität aus, nicht nach Browservalidierung.
Expand Down
15 changes: 15 additions & 0 deletions docs/de/benutzerhandbuch.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,21 @@ Auswahlen speichern. Ein Nextcloud-Konto ist nicht nötig. Identität und
Änderungstoken liegen in einer privaten Browsersitzung; gelöschte Website-Daten
beenden den Zugriff auf privates Feedback.

Wenn du bei Nextcloud angemeldet bist, gehört neues Feedback zu deinem Konto.
Frühere Gastkommentare bleiben ihrer ursprünglichen Gastidentität zugeordnet;
die Anmeldung übernimmt sie nicht. Galerie- und Linkregeln gelten weiterhin.

**Feedback** öffnet **Allgemeine Kommentare**, mit den neuesten Beiträgen direkt
unter dem Eingabefeld. **Markierungen** gruppiert Punktgespräche in aufklappbaren
Zeilen. Klappe eine Zeile zum Lesen auf oder öffne das Gespräch über dessen
separate Schaltfläche neben dem Punkt. Diese Fenster verdunkeln das Bild nicht.
**Prüfstatus** zeigt den konfigurierten Statusnamen zusammen mit seiner Farbe.

Zoome über die Bedienelemente, das Mausrad oder eine Zwei-Finger-Geste. Am Desktop
kannst du das vergrößerte Bild mit gedrückter rechter Maustaste verschieben.
Ein Rechtsklick ohne Ziehen öffnet weiterhin das Browser-Kontextmenü. Punkte
bleiben beim Zoomen und Verschieben an derselben bildrelativen Position.

Klicke oder tippe direkt auf ein Bild, um einen nummerierten Punkt zu setzen
und den zugehörigen Kommentar zu schreiben. Wähle für die Tastaturplatzierung
**Punktkommentar hinzufügen**, verschiebe den Punkt mit den Pfeiltasten, drücke
Expand Down
13 changes: 13 additions & 0 deletions docs/en/admin-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,19 @@ the server, including existing galleries where a capability must fail closed.
Native Nextcloud sharing, password, expiration, and upload restrictions remain
authoritative; this app never weakens them.

Public reviewers may use guest identities or existing signed-in Nextcloud
accounts. Account UIDs establish authorship, not additional permissions. Earlier
guest contributions are not reassigned by matching names or email addresses.
Private feedback stays private to its author and authorized gallery managers;
owner changes to an account's selection are delivered only to the permitted
review audience. Guest uploads remain a separate guest-only workflow.

The account-attribution migration retains the highest-ID duplicate account
feedback row before adding uniqueness constraints; guest comments and pins are
not reassigned. A subsequent migration adds a nullable event recipient UID so
owner attribution remains distinct from private account delivery. Complete the
normal database upgrade before serving the new application code.

Review public-link, mail, and group policy before onboarding users. Keep guest
downloads and uploads disabled unless required. Set limits according to PHP,
proxy, storage, and worker capacity rather than relying on browser validation.
Expand Down
15 changes: 15 additions & 0 deletions docs/en/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,21 @@ pick, reject, label, comment, annotate, and save named selections. Guests do
not need Nextcloud accounts. Their identity and mutation token are stored in a
private browser session; clearing site data ends access to private feedback.

If you are signed in to Nextcloud, new feedback uses your account identity.
Earlier guest comments remain linked to their original guest identity; signing
in does not claim them. Account identity does not bypass gallery or link rules.

**Feedback** opens **General comments**, newest first beneath the input.
The **Pins** tab groups point conversations into expandable rows. Expand a row
to read its replies, or use its separate open button to show the conversation
beside the pin. These panels do not dim the image. **Review state** shows both
the configured state name and its color indicator.

Zoom with the viewer controls, mouse wheel, or a touch pinch. On desktop, hold
the right mouse button and drag the zoomed image to pan. A right-click without
dragging keeps the browser context menu. Pins retain their image-relative
positions while zooming and panning.

Click or tap an image to place a numbered point and open its comment editor.
For keyboard placement, choose **Add point comment**, move the point with the
arrow keys, press Enter to write, or Escape to cancel. Unpinned comments remain
Expand Down
5 changes: 5 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export default [
'vue/custom-event-name-casing': ['error', 'kebab-case'],
'vue/define-macros-order': 'off',
'vue/first-attribute-linebreak': 'off',
'vue/no-bare-strings-in-template': ['error', {
// Numbers, icons, punctuation, units and protocol tokens are not prose.
// Everything containing translatable words must use the l10n helpers.
allowlist: ['/^[^\\p{L}]+$/u', '/^[A-Z]$/u', 'Ø', 'TXT', 'px'],
}],
'vue/v-on-event-hyphenation': ['error', 'always'],
},
},
Expand Down
Loading