Skip to content

Mass edit license#4120

Merged
ildyria merged 4 commits intomasterfrom
mass-edit-license
Feb 26, 2026
Merged

Mass edit license#4120
ildyria merged 4 commits intomasterfrom
mass-edit-license

Conversation

@ildyria
Copy link
Member

@ildyria ildyria commented Feb 26, 2026

Summary by CodeRabbit

  • New Features

    • Bulk photo license editing: select one or many photos and set their license via a new dialog; updates apply in batches for large selections.
  • UI

    • New license option in photo menus, context menus, and gallery panels; integrated modal dialog with success feedback.
  • Localization

    • Added translations for license dialog and menu labels across multiple locales.
  • Documentation

    • Added feature spec, plan, and task checklist for bulk license edit.
  • Tests

    • Added feature tests for validation, authorization, and bulk update scenarios.

Add bulk license update functionality with API endpoint, request validation,
frontend dialog, and context menu integration across all gallery views.

Backend:
- SetPhotosLicenseRequest with authorization and validation
- PhotoController::license() with chunked batch processing (100 photos/batch)
- PATCH /Photo::license route
- 7 comprehensive tests (401/403/422/204 scenarios)

Frontend:
- PhotoLicenseDialog component with PrimeVue Select (31 license types)
- Integration in Album, Tag, Timeline, Search views
- Context menu items: 'License' (single) and 'License Selected' (bulk)
- galleryModals composable toggleLicense trigger
- ModalsState is_license_visible flag

Translations:
- English translations for dialog and menu labels
- Placeholders added to 21 other languages (ar, bg, cz, de, el, es, fa, fr,
  hu, it, ja, nl, no, pl, pt, ru, sk, sv, vi, zh_CN, zh_TW)

Spec impact: Marked tasks T-016-01 through T-016-14 complete in tasks.md.
Updated roadmap status. Feature ready for manual testing (T-016-15 to T-016-24).
@ildyria ildyria requested a review from a team as a code owner February 26, 2026 00:18
@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 2026

📝 Walkthrough

Walkthrough

Adds a bulk photo license feature: backend request/endpoint for batched transactional updates, frontend dialog and modal wiring across gallery panels, translations for many locales, tests, and documentation for the feature rollout.

Changes

Cohort / File(s) Summary
Backend: Controller & Request
app/Http/Controllers/Gallery/PhotoController.php, app/Http/Requests/Photo/SetPhotosLicenseRequest.php, app/Http/Requests/Traits/Authorize/AuthorizeCanEditPhotosByIdTrait.php, app/Http/Requests/Photo/WatermarkPhotoRequest.php
Adds PhotoController::license() PATCH endpoint handling chunked (100) transactional updates; new SetPhotosLicenseRequest validating photo_ids and license; introduces trait-based authorization for photo-id checks and applies it to watermark request (removed inline authorize()).
Routing
routes/api_v2.php
New route: PATCH /Photo::licenseGallery\PhotoController::license.
Frontend: Dialog & Service
resources/js/components/forms/photo/PhotoLicenseDialog.vue, resources/js/services/photo-service.ts
New PhotoLicenseDialog component for single/multiple photos and PhotoService.license() method issuing PATCH to the new endpoint.
Frontend: Modal State & Helpers
resources/js/composables/modalsTriggers/galleryModals.ts, resources/js/stores/ModalsState.ts, resources/js/utils/Helpers.ts
Adds is_license_visible state, toggleLicense() composable, and toggleLicense stub in EmptyPhotoCallbacks.
Frontend: Panel Integrations
resources/js/views/gallery-panels/Album.vue, resources/js/views/gallery-panels/Search.vue, resources/js/views/gallery-panels/Tag.vue, resources/js/views/gallery-panels/Timeline.vue
Integrates PhotoLicenseDialog in panel templates; wires is_license_visible and licensed event handlers (unselect + refresh).
Frontend: Context Menus & Panels
resources/js/composables/contextMenus/contextMenu.ts, resources/js/components/gallery/.../AlbumPanel.vue, resources/js/components/gallery/.../TagPanel.vue
Exposes toggleLicense in PhotoCallbacks; adds license menu items (single and multi) guarded by can_edit; exposes toggle in gallery panel controls.
Frontend: Views & State Usage
resources/js/views/gallery-panels/*.vue, resources/js/components/.../AlbumPanel.vue, resources/js/components/.../TagPanel.vue
Wires modal toggle and callbacks across gallery views/panels to enable the dialog from various UIs.
Translations
lang/{ar,bg,cz,de,el,en,es,fa,fr,hu,it,ja,nl,no,pl,pt,ru,sk,sv,vi,zh_CN,zh_TW}/dialogs.php, lang/{ar,bg,cz,de,el,en,es,fa,fr,hu,it,ja,nl,no,pl,pt,ru,sk,sv,vi,zh_CN,zh_TW}/gallery.php
Adds photo_license translation group (question, question_multiple, select_license, set_license, updated) and menus entries license/license_all across locales.
Documentation & Roadmap
docs/specs/4-architecture/features/016-bulk-license-edit/plan.md, .../spec.md, .../tasks.md, docs/specs/4-architecture/roadmap.md
New feature plan, spec, task checklist and roadmap entry for Bulk License Edit.
Tests
tests/Feature_v2/Photo/PhotoBulkLicenseTest.php
New feature tests covering auth, validation, single/multi updates, all license types, and mixed-ownership denial.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰
I hopped through routes and dialogs bright,
Patch by patch, set licenses right.
With chunks and traits, the updates race—
A licensed gallery, neat in place.
Hooray for batchy carrot-powered grace!

🚥 Pre-merge checks | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.55% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
resources/js/composables/contextMenus/contextMenu.ts (1)

145-150: Consider using a distinct icon for the license action.

The license menu items use pi pi-id-card, which is also used for setAsCover (Line 116). While functionally correct, using a different icon (e.g., pi pi-file-check or pi pi-verified) could improve visual distinction between these actions.

🔧 Optional icon differentiation
 {
     label: "gallery.menus.license",
-    icon: "pi pi-id-card",
+    icon: "pi pi-file-check",
     callback: photoCallbacks.toggleLicense,
     access: albumStore.rights?.can_edit ?? false,
 },

Apply the same change to the license_all entry at Line 227.

Also applies to: 226-231

resources/js/components/forms/photo/PhotoLicenseDialog.vue (1)

71-72: Guard condition will never trigger.

The check selectedLicense.value === undefined will never be true since selectedLicense is initialized to "none" on Line 63 and reset to "none" in close(). Consider removing this dead code or adjusting the guard to check for a meaningful invalid state if needed.


ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 596e56d and c5d44e6.

📒 Files selected for processing (64)
  • app/Http/Controllers/Gallery/PhotoController.php
  • app/Http/Requests/Photo/SetPhotosLicenseRequest.php
  • docs/specs/4-architecture/features/016-bulk-license-edit/plan.md
  • docs/specs/4-architecture/features/016-bulk-license-edit/spec.md
  • docs/specs/4-architecture/features/016-bulk-license-edit/tasks.md
  • docs/specs/4-architecture/roadmap.md
  • lang/ar/dialogs.php
  • lang/ar/gallery.php
  • lang/bg/dialogs.php
  • lang/bg/gallery.php
  • lang/cz/dialogs.php
  • lang/cz/gallery.php
  • lang/de/dialogs.php
  • lang/de/gallery.php
  • lang/el/dialogs.php
  • lang/el/gallery.php
  • lang/en/dialogs.php
  • lang/en/gallery.php
  • lang/es/dialogs.php
  • lang/es/gallery.php
  • lang/fa/dialogs.php
  • lang/fa/gallery.php
  • lang/fr/dialogs.php
  • lang/fr/gallery.php
  • lang/hu/dialogs.php
  • lang/hu/gallery.php
  • lang/it/dialogs.php
  • lang/it/gallery.php
  • lang/ja/dialogs.php
  • lang/ja/gallery.php
  • lang/nl/dialogs.php
  • lang/nl/gallery.php
  • lang/no/dialogs.php
  • lang/no/gallery.php
  • lang/pl/dialogs.php
  • lang/pl/gallery.php
  • lang/pt/dialogs.php
  • lang/pt/gallery.php
  • lang/ru/dialogs.php
  • lang/ru/gallery.php
  • lang/sk/dialogs.php
  • lang/sk/gallery.php
  • lang/sv/dialogs.php
  • lang/sv/gallery.php
  • lang/vi/dialogs.php
  • lang/vi/gallery.php
  • lang/zh_CN/dialogs.php
  • lang/zh_CN/gallery.php
  • lang/zh_TW/dialogs.php
  • lang/zh_TW/gallery.php
  • resources/js/components/forms/photo/PhotoLicenseDialog.vue
  • resources/js/components/gallery/albumModule/AlbumPanel.vue
  • resources/js/components/gallery/tagModule/TagPanel.vue
  • resources/js/composables/contextMenus/contextMenu.ts
  • resources/js/composables/modalsTriggers/galleryModals.ts
  • resources/js/services/photo-service.ts
  • resources/js/stores/ModalsState.ts
  • resources/js/utils/Helpers.ts
  • resources/js/views/gallery-panels/Album.vue
  • resources/js/views/gallery-panels/Search.vue
  • resources/js/views/gallery-panels/Tag.vue
  • resources/js/views/gallery-panels/Timeline.vue
  • routes/api_v2.php
  • tests/Feature_v2/Photo/PhotoBulkLicenseTest.php

@codecov
Copy link

codecov bot commented Feb 26, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.19%. Comparing base (08dbd1c) to head (5e0aefe).
⚠️ Report is 2 commits behind head on master.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
app/Http/Controllers/Gallery/PhotoController.php (1)

295-308: Variable naming: $photo_id should reflect that it's a chunk collection.

The variable $photo_id in the chunk callback receives a collection of IDs, not a single ID. This naming is misleading and could cause confusion.

♻️ Suggested rename for clarity
 	public function license(SetPhotosLicenseRequest $request): void
 	{
 		$license = $request->license();
 		$photo_ids = collect($request->photoIds());
 		DB::transaction(function () use ($photo_ids, $license): void {
 			// Process photos in chunks of 100 to avoid memory issues
-			$photo_ids->chunk(100)->each(function ($photo_id) use ($license): void {
-				Photo::query()->whereIn('id', $photo_id)->update(['license' => $license->value]);
+			$photo_ids->chunk(100)->each(function ($chunk) use ($license): void {
+				Photo::query()->whereIn('id', $chunk)->update(['license' => $license->value]);
 			});
 		});
 	}

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c5d44e6 and 5e0aefe.

📒 Files selected for processing (4)
  • app/Http/Controllers/Gallery/PhotoController.php
  • app/Http/Requests/Photo/SetPhotosLicenseRequest.php
  • app/Http/Requests/Photo/WatermarkPhotoRequest.php
  • app/Http/Requests/Traits/Authorize/AuthorizeCanEditPhotosByIdTrait.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/Http/Requests/Photo/SetPhotosLicenseRequest.php

@ildyria ildyria merged commit 75bd868 into master Feb 26, 2026
44 checks passed
@ildyria ildyria deleted the mass-edit-license branch February 26, 2026 11:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant