Skip to content

Commit

Permalink
Delete tags in bulk (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
GeniJaho authored Dec 28, 2024
1 parent 00ac2db commit 47c09fa
Show file tree
Hide file tree
Showing 9 changed files with 640 additions and 17 deletions.
51 changes: 51 additions & 0 deletions app/DTO/BulkDeletePhotoItems.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace App\DTO;

use App\Rules\PhotosBelongToUser;
use Spatie\LaravelData\Data;

class BulkDeletePhotoItems extends Data
{
/**
* @param int[] $photo_ids
* @param int[] $item_ids
* @param int[] $tag_ids
*/
public function __construct(
public array $photo_ids,
public array $item_ids = [],
public array $tag_ids = [],
) {}

/**
* @return array<string, mixed>
*/
public static function rules(): array
{
return [
'photo_ids' => [
'required',
'array',
new PhotosBelongToUser,
],
'photo_ids.*' => ['required', 'exists:photos,id'],
'item_ids' => ['array'],
'item_ids.*' => ['required', 'exists:items,id'],
'tag_ids' => ['array'],
'tag_ids.*' => ['required', 'exists:tags,id'],
];
}

/**
* @return string[]
*/
public static function messages(): array
{
return [
'photo_ids.required' => 'You must select at least one photo.',
'photo_ids.*.required' => 'You must select at least one photo.',
'photo_ids.*.exists' => 'The selected photo #:position does not exist.',
];
}
}
18 changes: 2 additions & 16 deletions app/DTO/BulkPhotoItems.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

namespace App\DTO;

use App\Models\Photo;
use Closure;
use App\Rules\PhotosBelongToUser;
use Spatie\LaravelData\Data;

class BulkPhotoItems extends Data
Expand All @@ -26,20 +25,7 @@ public static function rules(): array
'photo_ids' => [
'required',
'array',
function (string $attribute, mixed $value, Closure $fail): void {
if (! is_array($value)) {
return;
}

$photosBelongsToOthers = Photo::query()
->whereIn('id', $value)
->where('user_id', '!=', auth()->id())
->exists();

if ($photosBelongsToOthers) {
$fail('You are not the owner of the photos.');
}
},
new PhotosBelongToUser,
],
'photo_ids.*' => ['required', 'exists:photos,id'],
];
Expand Down
21 changes: 21 additions & 0 deletions app/Http/Controllers/Photos/BulkPhotoItemsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

namespace App\Http\Controllers\Photos;

use App\DTO\BulkDeletePhotoItems;
use App\DTO\BulkPhotoItems;
use App\Http\Controllers\Controller;
use App\Models\Item;
use App\Models\PhotoItem;
use App\Models\PhotoItemTag;
use Illuminate\Support\Facades\DB;

class BulkPhotoItemsController extends Controller
Expand Down Expand Up @@ -35,4 +37,23 @@ public function store(BulkPhotoItems $bulkPhotoItems): void
}
});
}

public function destroy(BulkDeletePhotoItems $bulkDeletePhotoItems): void
{
DB::transaction(function () use ($bulkDeletePhotoItems): void {
PhotoItem::query()
->whereIn('photo_id', $bulkDeletePhotoItems->photo_ids)
->whereIn('item_id', $bulkDeletePhotoItems->item_ids)
->delete();

$photoItems = PhotoItem::query()
->whereIn('photo_id', $bulkDeletePhotoItems->photo_ids)
->pluck('id');

PhotoItemTag::query()
->whereIn('photo_item_id', $photoItems)
->whereIn('tag_id', $bulkDeletePhotoItems->tag_ids)
->delete();
});
}
}
32 changes: 32 additions & 0 deletions app/Rules/PhotosBelongToUser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace App\Rules;

use App\Models\Photo;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Translation\PotentiallyTranslatedString;

class PhotosBelongToUser implements ValidationRule
{
/**
* Run the validation rule.
*
* @param Closure(string, ?string=): PotentiallyTranslatedString $fail
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (! is_array($value)) {
return;
}

$photosBelongsToOthers = Photo::query()
->whereIn('id', $value)
->where('user_id', '!=', auth()->id())
->exists();

if ($photosBelongsToOthers) {
$fail('You are not the owner of the photos.');
}
}
}
9 changes: 9 additions & 0 deletions resources/js/Pages/Photos/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Dropdown from "@/Components/Dropdown.vue";
import ToggleInput from "@/Components/ToggleInput.vue";
import InputLabel from "@/Components/InputLabel.vue";
import DropdownLink from "@/Components/DropdownLink.vue";
import BulkRemoveItemsAndTags from "@/Pages/Photos/Partials/BulkRemoveItemsAndTags.vue";
const props = defineProps({
photos: Object,
Expand Down Expand Up @@ -222,6 +223,14 @@ const exportData = (format) => {
:tagShortcutsEnabled="tagShortcutsEnabled"
@closeModalWithSuccess="clearSelection"
></BulkTag>

<BulkRemoveItemsAndTags
v-if="isSelecting && selectedPhotos.length"
:photoIds="selectedPhotos"
:tags="tags"
:items="items"
@closeModalWithSuccess="clearSelection"
></BulkRemoveItemsAndTags>
</div>

<div>
Expand Down
Loading

0 comments on commit 47c09fa

Please sign in to comment.