refactor: tags view

This commit is contained in:
Andras Bacsai 2024-07-12 12:51:13 +02:00
parent 39a7332343
commit 21612cccf7
2 changed files with 67 additions and 70 deletions

View File

@ -3,32 +3,63 @@
namespace App\Livewire\Project\Shared; namespace App\Livewire\Project\Shared;
use App\Models\Tag; use App\Models\Tag;
use Livewire\Attributes\Validate;
use Livewire\Component; use Livewire\Component;
// Refactored ✅
class Tags extends Component class Tags extends Component
{ {
public $resource = null; public $resource = null;
public ?string $new_tag = null; #[Validate('required|string|min:2')]
public string $newTags;
public $tags = []; public $tags = [];
protected $listeners = [ public $filteredTags = [];
'refresh' => '$refresh',
];
protected $rules = [
'resource.tags.*.name' => 'required|string|min:2',
'new_tag' => 'required|string|min:2',
];
protected $validationAttributes = [
'new_tag' => 'tag',
];
public function mount() public function mount()
{
$this->loadTags();
}
public function loadTags()
{ {
$this->tags = Tag::ownedByCurrentTeam()->get(); $this->tags = Tag::ownedByCurrentTeam()->get();
$this->filteredTags = $this->tags->filter(function ($tag) {
return ! $this->resource->tags->contains($tag);
});
}
public function submit()
{
try {
$this->validate();
$tags = str($this->newTags)->trim()->explode(' ');
foreach ($tags as $tag) {
if (strlen($tag) < 2) {
$this->dispatch('error', 'Invalid tag.', "Tag <span class='dark:text-warning'>$tag</span> is invalid. Min length is 2.");
continue;
}
if ($this->resource->tags()->where('name', $tag)->exists()) {
$this->dispatch('error', 'Duplicate tags.', "Tag <span class='dark:text-warning'>$tag</span> already added.");
continue;
}
$found = Tag::ownedByCurrentTeam()->where(['name' => $tag])->exists();
if (! $found) {
$found = Tag::create([
'name' => $tag,
'team_id' => currentTeam()->id,
]);
}
$this->resource->tags()->attach($found->id);
}
$this->refresh();
} catch (\Exception $e) {
return handleError($e, $this);
}
} }
public function addTag(string $id, string $name) public function addTag(string $id, string $name)
@ -39,8 +70,9 @@ public function addTag(string $id, string $name)
return; return;
} }
$this->resource->tags()->syncWithoutDetaching($id); $this->resource->tags()->attach($id);
$this->refresh(); $this->refresh();
$this->dispatch('success', 'Tag added.');
} catch (\Exception $e) { } catch (\Exception $e) {
return handleError($e, $this); return handleError($e, $this);
} }
@ -51,11 +83,12 @@ public function deleteTag(string $id)
try { try {
$this->resource->tags()->detach($id); $this->resource->tags()->detach($id);
$found_more_tags = Tag::where(['id' => $id, 'team_id' => currentTeam()->id])->first(); $found_more_tags = Tag::ownedByCurrentTeam()->find($id);
if ($found_more_tags->applications()->count() == 0 && $found_more_tags->services()->count() == 0) { if ($found_more_tags->applications()->count() == 0 && $found_more_tags->services()->count() == 0) {
$found_more_tags->delete(); $found_more_tags->delete();
} }
$this->refresh(); $this->refresh();
$this->dispatch('success', 'Tag deleted.');
} catch (\Exception $e) { } catch (\Exception $e) {
return handleError($e, $this); return handleError($e, $this);
} }
@ -63,41 +96,7 @@ public function deleteTag(string $id)
public function refresh() public function refresh()
{ {
$this->resource->load(['tags']); $this->loadTags();
$this->tags = Tag::ownedByCurrentTeam()->get(); $this->reset('newTags');
$this->new_tag = null;
}
public function submit()
{
try {
$this->validate([
'new_tag' => 'required|string|min:2',
]);
$tags = str($this->new_tag)->trim()->explode(' ');
foreach ($tags as $tag) {
if ($this->resource->tags()->where('name', $tag)->exists()) {
$this->dispatch('error', 'Duplicate tags.', "Tag <span class='dark:text-warning'>$tag</span> already added.");
continue;
}
$found = Tag::where(['name' => $tag, 'team_id' => currentTeam()->id])->first();
if (! $found) {
$found = Tag::create([
'name' => $tag,
'team_id' => currentTeam()->id,
]);
}
$this->resource->tags()->syncWithoutDetaching($found->id);
}
$this->refresh();
} catch (\Exception $e) {
return handleError($e, $this);
}
}
public function render()
{
return view('livewire.project.shared.tags');
} }
} }

View File

@ -1,10 +1,18 @@
<div> <div>
<h2>Tags</h2> <h2>Tags</h2>
<div class="flex flex-wrap gap-2 pt-4"> <form wire:submit='submit' class="flex items-end gap-2">
@if (data_get($this->resource, 'tags')) <div class="w-64">
@forelse (data_get($this->resource,'tags') as $tagId => $tag) <x-forms.input label="Create new or assign existing tags"
<div helper="You add more at once with space separated list: web api something<br><br>If the tag does not exists, it will be created."
class="px-2 py-1 text-center rounded select-none dark:text-white w-fit bg-neutral-200 hover:bg-neutral-300 dark:bg-coolgray-100 dark:hover:bg-coolgray-200"> wire:model="newTags" placeholder="example: prod app1 user" />
</div>
<x-forms.button type="submit">Add</x-forms.button>
</form>
@if (data_get($this->resource, 'tags') && count(data_get($this->resource, 'tags')) > 0)
<h3 class="pt-4">Assigned Tags</h3>
<div class="flex flex-wrap gap-2 pt-4">
@foreach (data_get($this->resource, 'tags') as $tagId => $tag)
<div class="button">
{{ $tag->name }} {{ $tag->name }}
<svg wire:click="deleteTag('{{ $tag->id }}')" xmlns="http://www.w3.org/2000/svg" fill="none" <svg wire:click="deleteTag('{{ $tag->id }}')" xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@ -13,24 +21,14 @@ class="inline-block w-3 h-3 rounded cursor-pointer stroke-current hover:bg-red-5
</path> </path>
</svg> </svg>
</div> </div>
@empty @endforeach
<div class="py-1">No tags yet</div>
@endforelse
@endif
</div>
<form wire:submit='submit' class="flex items-end gap-2 pt-4">
<div class="w-64">
<x-forms.input label="Create new or assign existing tags"
helper="You add more at once with space separated list: web api something<br><br>If the tag does not exists, it will be created."
wire:model="new_tag" />
</div> </div>
<x-forms.button type="submit">Add</x-forms.button> @endif
</form> @if (count($filteredTags) > 0)
@if (count($tags) > 0)
<h3 class="pt-4">Exisiting Tags</h3> <h3 class="pt-4">Exisiting Tags</h3>
<div>Click to add quickly</div> <div>Click to add quickly</div>
<div class="flex flex-wrap gap-2 pt-4"> <div class="flex flex-wrap gap-2 pt-4">
@foreach ($tags as $tag) @foreach ($filteredTags as $tag)
<x-forms.button wire:click="addTag('{{ $tag->id }}','{{ $tag->name }}')"> <x-forms.button wire:click="addTag('{{ $tag->id }}','{{ $tag->name }}')">
{{ $tag->name }}</x-forms.button> {{ $tag->name }}</x-forms.button>
@endforeach @endforeach