feat(admin): allow existing resources to be attached in lenses (#421)

* feat(admin): allow existing resources to be attached to anime in lenses

* style: fix StyleCI findings

* fix(admin): change confirm button text
This commit is contained in:
paranarimasu
2022-07-15 17:09:46 -05:00
committed by GitHub
parent 95f8229b50
commit 06ee91f968
11 changed files with 206 additions and 282 deletions
@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace App\Nova\Actions\Wiki\Anime;
use App\Models\Wiki\ExternalResource;
use App\Nova\Actions\Wiki\AttachResourceAction;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
/**
* Class AttachAnimeResourceAction.
*/
class AttachAnimeResourceAction extends AttachResourceAction
{
/**
* Get the relation to the action models.
*
* @param ExternalResource $resource
* @return BelongsToMany
*/
protected function relation(ExternalResource $resource): BelongsToMany
{
return $resource->anime();
}
}
@@ -1,89 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Nova\Actions\Wiki\Anime;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Wiki\ExternalResource;
use App\Rules\Wiki\ResourceLinkMatchesSiteRule;
use Illuminate\Support\Collection;
use Illuminate\Validation\Rule;
use Laravel\Nova\Actions\Action;
use Laravel\Nova\Fields\ActionFields;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Http\Requests\NovaRequest;
/**
* Class CreateExternalResourceSiteForAnimeAction.
*/
class CreateExternalResourceSiteForAnimeAction extends Action
{
/**
* @param int $site
*/
public function __construct(protected readonly int $site)
{
}
/**
* Get the displayable name of the action.
*
* @return string
*
* @noinspection PhpMissingParentCallCommonInspection
*/
public function name(): string
{
return __('nova.anime_create_resource_action', ['site' => ResourceSite::getDescription($this->site)]);
}
/**
* Perform the action on the given models.
*
* @param ActionFields $fields
* @param Collection $models
* @return array
*/
public function handle(ActionFields $fields, Collection $models): array
{
$link = $fields->get('link');
// Create Resource Model with link and provided site
/** @var ExternalResource $resource */
$resource = ExternalResource::query()->create([
ExternalResource::ATTRIBUTE_EXTERNAL_ID => ResourceSite::parseIdFromLink($link),
ExternalResource::ATTRIBUTE_LINK => $link,
ExternalResource::ATTRIBUTE_SITE => $this->site,
]);
// Attach Resource to Anime and provide success message
$resource->anime()->attach($models);
return Action::message(__('nova.anime_create_resource_action_success'));
}
/**
* Get the fields available on the action.
*
* @param NovaRequest $request
* @return array
*/
public function fields(NovaRequest $request): array
{
return array_merge(
parent::fields($request),
[
Text::make(__('nova.link'), 'link')
->rules([
'required',
'max:192',
'url',
Rule::unique(ExternalResource::TABLE),
new ResourceLinkMatchesSiteRule($this->site),
])
->help(__('nova.resource_link_help')),
]
);
}
}
@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace App\Nova\Actions\Wiki\Artist;
use App\Models\Wiki\ExternalResource;
use App\Nova\Actions\Wiki\AttachResourceAction;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
/**
* Class AttachArtistResourceAction.
*/
class AttachArtistResourceAction extends AttachResourceAction
{
/**
* Get the relation to the action models.
*
* @param ExternalResource $resource
* @return BelongsToMany
*/
protected function relation(ExternalResource $resource): BelongsToMany
{
return $resource->artists();
}
}
@@ -1,89 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Nova\Actions\Wiki\Artist;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Wiki\ExternalResource;
use App\Rules\Wiki\ResourceLinkMatchesSiteRule;
use Illuminate\Support\Collection;
use Illuminate\Validation\Rule;
use Laravel\Nova\Actions\Action;
use Laravel\Nova\Fields\ActionFields;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Http\Requests\NovaRequest;
/**
* Class CreateExternalResourceSiteForArtistAction.
*/
class CreateExternalResourceSiteForArtistAction extends Action
{
/**
* @param int $site
*/
public function __construct(protected readonly int $site)
{
}
/**
* Get the displayable name of the action.
*
* @return string
*
* @noinspection PhpMissingParentCallCommonInspection
*/
public function name(): string
{
return __('nova.artist_create_resource_action', ['site' => ResourceSite::getDescription($this->site)]);
}
/**
* Perform the action on the given models.
*
* @param ActionFields $fields
* @param Collection $models
* @return array
*/
public function handle(ActionFields $fields, Collection $models): array
{
$link = $fields->get('link');
// Create Resource Model with link and provided site
/** @var ExternalResource $resource */
$resource = ExternalResource::query()->create([
ExternalResource::ATTRIBUTE_EXTERNAL_ID => ResourceSite::parseIdFromLink($link),
ExternalResource::ATTRIBUTE_LINK => $link,
ExternalResource::ATTRIBUTE_SITE => $this->site,
]);
// Attach Resource to Anime and provide success message
$resource->artists()->attach($models);
return Action::message(__('nova.artist_create_resource_action_success'));
}
/**
* Get the fields available on the action.
*
* @param NovaRequest $request
* @return array
*/
public function fields(NovaRequest $request): array
{
return array_merge(
parent::fields($request),
[
Text::make(__('nova.link'), 'link')
->rules([
'required',
'max:192',
'url',
Rule::unique(ExternalResource::TABLE),
new ResourceLinkMatchesSiteRule($this->site),
])
->help(__('nova.resource_link_help')),
]
);
}
}
@@ -0,0 +1,117 @@
<?php
declare(strict_types=1);
namespace App\Nova\Actions\Wiki;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Wiki\ExternalResource;
use App\Rules\Wiki\ResourceLinkMatchesSiteRule;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Collection;
use Laravel\Nova\Actions\Action;
use Laravel\Nova\Fields\ActionFields;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Http\Requests\NovaRequest;
/**
* Class AttachResourceAction.
*/
abstract class AttachResourceAction extends Action
{
/**
* Create a new action instance.
*
* @param ResourceSite $site
*/
public function __construct(protected ResourceSite $site)
{
}
/**
* Get the displayable name of the action.
*
* @return string
*
* @noinspection PhpMissingParentCallCommonInspection
*/
public function name(): string
{
return __('nova.attach_resource_action', ['site' => $this->site->description]);
}
/**
* Perform the action on the given models.
*
* @param ActionFields $fields
* @param Collection $models
* @return Collection
*/
public function handle(ActionFields $fields, Collection $models): Collection
{
$resource = $this->getOrCreateResource($fields);
$relation = $this->relation($resource);
$relation->attach($models);
return $models;
}
/**
* Get or Create Resource from link field.
*
* @param ActionFields $fields
* @return ExternalResource
*/
protected function getOrCreateResource(ActionFields $fields): ExternalResource
{
$link = $fields->get('link');
$resource = ExternalResource::query()
->where(ExternalResource::ATTRIBUTE_LINK, $link)
->first();
if ($resource === null) {
$resource = ExternalResource::query()->create([
ExternalResource::ATTRIBUTE_EXTERNAL_ID => ResourceSite::parseIdFromLink($link),
ExternalResource::ATTRIBUTE_LINK => $link,
ExternalResource::ATTRIBUTE_SITE => $this->site->value,
]);
}
return $resource;
}
/**
* Get the relation to the action models.
*
* @param ExternalResource $resource
* @return BelongsToMany
*/
abstract protected function relation(ExternalResource $resource): BelongsToMany;
/**
* Get the fields available on the action.
*
* @param NovaRequest $request
* @return array
*/
public function fields(NovaRequest $request): array
{
return array_merge(
parent::fields($request),
[
Text::make(__('nova.link'), 'link')
->required()
->rules([
'required',
'max:192',
'url',
new ResourceLinkMatchesSiteRule($this->site->value),
])
->help(__('nova.resource_link_help')),
]
);
}
}
@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace App\Nova\Actions\Wiki\Studio;
use App\Models\Wiki\ExternalResource;
use App\Nova\Actions\Wiki\AttachResourceAction;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
/**
* Class AttachStudioResourceAction.
*/
class AttachStudioResourceAction extends AttachResourceAction
{
/**
* Get the relation to the action models.
*
* @param ExternalResource $resource
* @return BelongsToMany
*/
protected function relation(ExternalResource $resource): BelongsToMany
{
return $resource->studios();
}
}
@@ -1,89 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Nova\Actions\Wiki\Studio;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Wiki\ExternalResource;
use App\Rules\Wiki\ResourceLinkMatchesSiteRule;
use Illuminate\Support\Collection;
use Illuminate\Validation\Rule;
use Laravel\Nova\Actions\Action;
use Laravel\Nova\Fields\ActionFields;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Http\Requests\NovaRequest;
/**
* Class CreateExternalResourceSiteForStudioAction.
*/
class CreateExternalResourceSiteForStudioAction extends Action
{
/**
* @param int $site
*/
public function __construct(protected readonly int $site)
{
}
/**
* Get the displayable name of the action.
*
* @return string
*
* @noinspection PhpMissingParentCallCommonInspection
*/
public function name(): string
{
return __('nova.studio_create_resource_action', ['site' => ResourceSite::getDescription($this->site)]);
}
/**
* Perform the action on the given models.
*
* @param ActionFields $fields
* @param Collection $models
* @return array
*/
public function handle(ActionFields $fields, Collection $models): array
{
$link = $fields->get('link');
// Create Resource Model with link and provided site
/** @var ExternalResource $resource */
$resource = ExternalResource::query()->create([
ExternalResource::ATTRIBUTE_EXTERNAL_ID => ResourceSite::parseIdFromLink($link),
ExternalResource::ATTRIBUTE_LINK => $link,
ExternalResource::ATTRIBUTE_SITE => $this->site,
]);
// Attach Resource to Studio and provide success message
$resource->studios()->attach($models);
return Action::message(__('nova.studio_create_resource_action_success'));
}
/**
* Get the fields available on the action.
*
* @param NovaRequest $request
* @return array
*/
public function fields(NovaRequest $request): array
{
return array_merge(
parent::fields($request),
[
Text::make(__('nova.link'), 'link')
->rules([
'required',
'max:192',
'url',
Rule::unique(ExternalResource::TABLE),
new ResourceLinkMatchesSiteRule($this->site),
])
->help(__('nova.resource_link_help')),
]
);
}
}
+3 -3
View File
@@ -8,7 +8,7 @@ use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Auth\User;
use App\Models\Wiki\Anime;
use App\Models\Wiki\ExternalResource;
use App\Nova\Actions\Wiki\Anime\CreateExternalResourceSiteForAnimeAction;
use App\Nova\Actions\Wiki\Anime\AttachAnimeResourceAction;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Laravel\Nova\Http\Requests\NovaRequest;
@@ -61,8 +61,8 @@ abstract class AnimeResourceLens extends AnimeLens
public function actions(NovaRequest $request): array
{
return [
(new CreateExternalResourceSiteForAnimeAction(static::site()->value))
->confirmButtonText(__('nova.create'))
(new AttachAnimeResourceAction(static::site()))
->confirmButtonText(__('nova.attach'))
->cancelButtonText(__('nova.cancel'))
->showInline()
->canSee(function (Request $request) {
@@ -8,7 +8,7 @@ use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Auth\User;
use App\Models\Wiki\Artist;
use App\Models\Wiki\ExternalResource;
use App\Nova\Actions\Wiki\Artist\CreateExternalResourceSiteForArtistAction;
use App\Nova\Actions\Wiki\Artist\AttachArtistResourceAction;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Laravel\Nova\Http\Requests\NovaRequest;
@@ -61,8 +61,8 @@ abstract class ArtistResourceLens extends ArtistLens
public function actions(NovaRequest $request): array
{
return [
(new CreateExternalResourceSiteForArtistAction(static::site()->value))
->confirmButtonText(__('nova.create'))
(new AttachArtistResourceAction(static::site()))
->confirmButtonText(__('nova.attach'))
->cancelButtonText(__('nova.cancel'))
->showInline()
->canSee(function (Request $request) {
@@ -8,7 +8,7 @@ use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Auth\User;
use App\Models\Wiki\ExternalResource;
use App\Models\Wiki\Studio;
use App\Nova\Actions\Wiki\Studio\CreateExternalResourceSiteForStudioAction;
use App\Nova\Actions\Wiki\Studio\AttachStudioResourceAction;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
@@ -60,8 +60,8 @@ abstract class StudioResourceLens extends StudioLens
public function actions(Request $request): array
{
return [
(new CreateExternalResourceSiteForStudioAction(static::site()->value))
->confirmButtonText(__('nova.create'))
(new AttachStudioResourceAction(static::site()))
->confirmButtonText(__('nova.attach'))
->cancelButtonText(__('nova.cancel'))
->showInline()
->canSee(function (Request $request) {
+2 -6
View File
@@ -5,8 +5,6 @@ declare(strict_types=1);
return [
'admin' => 'Admin',
'amount' => 'Amount',
'anime_create_resource_action_success' => 'The Resource has been created and attached to the Anime',
'anime_create_resource_action' => 'Create :site Resource for Anime',
'anime_image_lens' => 'Anime Without :facet Image',
'anime_name_help' => 'The display title of the Anime. By default, we will use the same title as MAL. Ex: "Bakemonogatari", "Code Geass: Hangyaku no Lelouch", "Dungeon ni Deai wo Motomeru no wa Machigatteiru Darou ka".',
'anime_resource_lens' => 'Anime Without :site Resource',
@@ -35,8 +33,6 @@ return [
'anime' => 'Anime',
'announcement' => 'Announcement',
'announcements' => 'Announcements',
'artist_create_resource_action_success' => 'The Resource has been created and attached to the Artist',
'artist_create_resource_action' => 'Create :site Resource for Artist',
'artist_image_lens' => 'Artist Without :facet Image',
'artist_name_help' => 'The display title of the Artist. By default, we will use the same title as MAL, but we will prefer "[Given Name] [Family name]". Ex: "Aimer", "Yui Horie", "Fear, and Loathing in Las Vegas".',
'artist_resource_lens' => 'Artist Without :site Resource',
@@ -46,6 +42,8 @@ return [
'artists' => 'Artists',
'as_help' => 'Used in place of the Artist name if the performance is made as a character or group/unit member.',
'as' => 'As',
'attach_resource_action' => 'Attach :site Resource',
'attach' => 'Attach',
'auth' => 'Auth',
'backfill' => 'Backfill',
'backfill_anidb_resource_help' => 'Use the Manami Project Anime Offline Database hosted by yuna.moe to find an AniDB mapping from a MAL, Anilist or Kitsu Resource',
@@ -181,8 +179,6 @@ return [
'source' => 'Source',
'spoiler' => 'Spoiler',
'status' => 'Status',
'studio_create_resource_action_success' => 'The Resource has been created and attached to the Studio',
'studio_create_resource_action' => 'Create :site Resource for Studio',
'studio_image_lens' => 'Studio Without :facet Image',
'studio_name_help' => 'The display title of the Studio',
'studio_resource_lens' => 'Studio Without :site Resource',