Skip to content

Commit

Permalink
feat: aggregates view (#770)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kyrch authored Jan 4, 2025
1 parent 33f62da commit e10bcfc
Show file tree
Hide file tree
Showing 52 changed files with 657 additions and 265 deletions.
4 changes: 3 additions & 1 deletion app/Actions/Models/BackfillWikiAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use App\Actions\Models\Wiki\ApiAction;
use App\Concerns\Models\CanCreateExternalResource;
use App\Concerns\Models\CanCreateImage;
use App\Contracts\Models\HasImages;
use App\Contracts\Models\HasResources;
use App\Enums\Models\Wiki\ImageFacet;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\BaseModel;
Expand Down Expand Up @@ -128,7 +130,7 @@ protected function backfilled(mixed $enum, string $scope): void
/**
* Get the model for the action.
*
* @return BaseModel
* @return BaseModel&HasResources&HasImages
*/
abstract protected function getModel(): BaseModel;

Expand Down
47 changes: 47 additions & 0 deletions app/Actions/Models/Service/SyncViewAggregatesAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

namespace App\Actions\Models\Service;

use App\Actions\ActionResult;
use App\Enums\Actions\ActionStatus;
use Exception;
use Illuminate\Support\Facades\DB;

/**
* Class SyncViewAggregatesAction.
*/
class SyncViewAggregatesAction
{
/**
* Handles the action.
*
* @return ActionResult
*
* @throws Exception
*/
public function handle(): ActionResult
{
try {
DB::statement("
INSERT INTO view_aggregates (viewable_id, viewable_type, value)
SELECT viewable_id, viewable_type, COUNT(*) as value
FROM views
GROUP BY viewable_type, viewable_id
ON DUPLICATE KEY UPDATE value = VALUES(value);
");

} catch (Exception $e) {
return new ActionResult(
ActionStatus::FAILED,
$e->getMessage()
);
}

return new ActionResult(
ActionStatus::PASSED,
'View aggregates synced successfully',
);
}
}
21 changes: 7 additions & 14 deletions app/Actions/Models/Wiki/AttachImageAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\Actions\Models\Wiki;

use App\Concerns\Models\CanCreateImage;
use App\Contracts\Models\HasImages;
use App\Enums\Models\Wiki\ImageFacet;
use App\Models\BaseModel;
use Illuminate\Support\Arr;
Expand All @@ -17,29 +18,21 @@ class AttachImageAction
use CanCreateImage;

/**
* Create a new action instance.
* Perform the action on the given models.
*
* @param BaseModel $model
* @param BaseModel&HasImages $model
* @param array $fields
* @param ImageFacet[] $facets
*/
public function __construct(protected BaseModel $model, protected array $fields, protected array $facets)
{
}

/**
* Perform the action on the given models.
*
* @return void
*/
public function handle(): void
public function handle(BaseModel&HasImages $model, array $fields, array $facets): void
{
foreach ($this->facets as $facet) {
$image = Arr::get($this->fields, $facet->name);
foreach ($facets as $facet) {
$image = Arr::get($fields, $facet->name);

if (empty($image)) continue;

$this->createImageFromFile($image, $facet, $this->model);
$this->createImageFromFile($image, $facet, $model);
}
}
}
21 changes: 7 additions & 14 deletions app/Actions/Models/Wiki/AttachResourceAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\Actions\Models\Wiki;

use App\Concerns\Models\CanCreateExternalResource;
use App\Contracts\Models\HasResources;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\BaseModel;
use Illuminate\Support\Arr;
Expand All @@ -17,29 +18,21 @@ class AttachResourceAction
use CanCreateExternalResource;

/**
* Create a new action instance.
* Handle the action.
*
* @param BaseModel $model
* @param BaseModel&HasResources $model
* @param array $fields
* @param ResourceSite[] $sites
*/
public function __construct(protected BaseModel $model, protected array $fields, protected array $sites)
{
}

/**
* Handle the action.
*
* @return void
*/
public function handle(): void
public function handle(BaseModel&HasResources $model,array $fields, array $sites): void
{
foreach ($this->sites as $resourceSite) {
$link = Arr::get($this->fields, $resourceSite->name);
foreach ($sites as $resourceSite) {
$link = Arr::get($fields, $resourceSite->name);

if (empty($link)) continue;

$this->createResource($link, $resourceSite, $this->model);
$this->createResource($link, $resourceSite, $model);
}
}
}
2 changes: 1 addition & 1 deletion app/Actions/Models/Wiki/BackfillAnimeAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ protected function forSynonyms(ApiAction $api): void
if (!$this->toBackfill[self::SYNONYMS]) return;

foreach ($api->getSynonyms() as $type => $text) {
$this->createAnimeSynonym($text, $type, $this->getModel());
$this->createAnimeSynonym($text, $type, $this->getModel());
}

if ($this->getModel()->animesynonyms()->exists()) {
Expand Down
4 changes: 2 additions & 2 deletions app/Actions/Models/Wiki/BackfillSongAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ public function handle(): ActionResult
DB::beginTransaction();

// Attach other resources
$attachResourceAction = new AttachResourceAction($this->getModel(), $this->fields, $this->sites);
$attachResourceAction = new AttachResourceAction();

$attachResourceAction->handle();
$attachResourceAction->handle($this->getModel(), $this->fields, $this->sites);

// Request to lnk.to site
$response = Http::get($this->lnkto);
Expand Down
1 change: 1 addition & 0 deletions app/Concerns/Filament/ActionLogs/HasActionLogs.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public function createActionLog(mixed $action, ?Model $record = null, ?bool $sho
}

// $record must be specified if in context of bulk action
/** @phpstan-ignore-next-line */
$this->recordLog = $record ?? $this->getRecord();

$actionLog = ActionLog::modelActioned(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@

namespace App\Concerns\Filament\Actions\Models\Wiki\Anime;

use App\Actions\Models\Wiki\AttachResourceAction as AttachResourceActionAction;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Wiki\Anime;
use App\Rules\Wiki\Resource\AnimeResourceLinkFormatRule;
use Illuminate\Contracts\Validation\ValidationRule;

/**
* Trait AttachAnimeResourceActionTrait.
Expand Down Expand Up @@ -37,18 +33,5 @@ protected function setUp(): void
ResourceSite::YOUTUBE,
ResourceSite::WIKI,
]);

$this->action(fn (Anime $record, array $data) => new AttachResourceActionAction($record, $data, $this->sites)->handle());
}

/**
* Get the format validation rule.
*
* @param ResourceSite $site
* @return ValidationRule
*/
protected function getFormatRule(ResourceSite $site): ValidationRule
{
return new AnimeResourceLinkFormatRule($site);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,73 +110,80 @@ public function getForm(Form $form): ?Form
{
$anime = $this->getRecord();

if (!($anime instanceof Anime)) return $form;

$anime = $anime->load([Anime::RELATION_RESOURCES, Anime::RELATION_IMAGES, Anime::RELATION_STUDIOS, Anime::RELATION_SYNONYMS]);

$resources = $anime->resources->pluck(ExternalResource::ATTRIBUTE_SITE)->keyBy(fn (ResourceSite $site) => $site->value)->keys();
$images = $anime->images->pluck(Image::ATTRIBUTE_FACET)->keyBy(fn (ImageFacet $facet) => $facet->value)->keys();

return $form
->schema([
Section::make(__('filament.actions.anime.backfill.fields.resources.name'))
->schema([
Checkbox::make(self::BACKFILL_KITSU_RESOURCE)
->label(__('filament.actions.anime.backfill.fields.resources.kitsu.name'))
->helperText(__('filament.actions.anime.backfill.fields.resources.kitsu.help'))
->default(fn () => $anime instanceof Anime && $anime->resources()->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::KITSU->value)->doesntExist()),
->default(fn () => $resources->doesntContain(ResourceSite::KITSU->value)),

Checkbox::make(self::BACKFILL_ANILIST_RESOURCE)
->label(__('filament.actions.anime.backfill.fields.resources.anilist.name'))
->helperText(__('filament.actions.anime.backfill.fields.resources.anilist.help'))
->default(fn () => $anime instanceof Anime && $anime->resources()->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::ANILIST->value)->doesntExist()),
->default(fn () => $resources->doesntContain(ResourceSite::ANILIST->value)),

Checkbox::make(self::BACKFILL_MAL_RESOURCE)
->label(__('filament.actions.anime.backfill.fields.resources.mal.name'))
->helperText(__('filament.actions.anime.backfill.fields.resources.mal.help'))
->default(fn () => $anime instanceof Anime && $anime->resources()->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::MAL->value)->doesntExist()),
->default(fn () => $resources->doesntContain(ResourceSite::MAL->value)),

Checkbox::make(self::BACKFILL_ANIDB_RESOURCE)
->label(__('filament.actions.anime.backfill.fields.resources.anidb.name'))
->helperText(__('filament.actions.anime.backfill.fields.resources.anidb.help'))
->default(fn () => $anime instanceof Anime && $anime->resources()->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::ANIDB->value)->doesntExist()),
->default(fn () => $resources->doesntContain(ResourceSite::ANIDB->value)),

Checkbox::make(self::BACKFILL_ANN_RESOURCE)
->label(__('filament.actions.anime.backfill.fields.resources.ann.name'))
->helperText(__('filament.actions.anime.backfill.fields.resources.ann.help'))
->default(fn () => $anime instanceof Anime && $anime->resources()->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::ANN->value)->doesntExist()),
->default(fn () => $resources->doesntContain(ResourceSite::ANN->value)),

Checkbox::make(self::BACKFILL_ANIME_PLANET_RESOURCE)
->label(__('filament.actions.anime.backfill.fields.resources.anime_planet.name'))
->helperText(__('filament.actions.anime.backfill.fields.resources.anime_planet.help'))
->default(fn () => $anime instanceof Anime && $anime->resources()->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::ANIME_PLANET->value)->doesntExist()),
->default(fn () => $resources->doesntContain(ResourceSite::ANIME_PLANET->value)),

Checkbox::make(self::BACKFILL_OTHER_RESOURCES)
->label(__('filament.actions.anime.backfill.fields.resources.external_links.name'))
->helperText(__('filament.actions.anime.backfill.fields.resources.external_links.help'))
->default(fn () => $anime instanceof Anime),
->default(true),
]),

Section::make(__('filament.actions.anime.backfill.fields.images.name'))
->schema([
Checkbox::make(self::BACKFILL_LARGE_COVER)
->label(__('filament.actions.anime.backfill.fields.images.large_cover.name'))
->helperText(__('filament.actions.anime.backfill.fields.images.large_cover.help'))
->default(fn () => $anime instanceof Anime && $anime->images()->where(Image::ATTRIBUTE_FACET, ImageFacet::COVER_LARGE->value)->doesntExist()),
->default(fn () => $images->doesntContain(ImageFacet::COVER_LARGE->value)),

Checkbox::make(self::BACKFILL_SMALL_COVER)
->label(__('filament.actions.anime.backfill.fields.images.small_cover.name'))
->helperText(__('filament.actions.anime.backfill.fields.images.small_cover.help'))
->default(fn () => $anime instanceof Anime && $anime->images()->where(Image::ATTRIBUTE_FACET, ImageFacet::COVER_SMALL->value)->doesntExist()),
->default(fn () => $images->doesntContain(ImageFacet::COVER_SMALL->value)),
]),

Section::make(__('filament.actions.anime.backfill.fields.studios.name'))
->schema([
Checkbox::make(self::BACKFILL_STUDIOS)
->label(__('filament.actions.anime.backfill.fields.studios.anime.name'))
->helperText(__('filament.actions.anime.backfill.fields.studios.anime.help'))
->default(fn () => $anime instanceof Anime && $anime->studios()->doesntExist()),
->default(fn () => $anime->studios->isEmpty()),
]),

Section::make(__('filament.actions.anime.backfill.fields.synonyms.name'))
->schema([
Checkbox::make(self::BACKFILL_SYNONYMS)
->label(__('filament.actions.anime.backfill.fields.synonyms.name'))
->helperText(__('filament.actions.anime.backfill.fields.synonyms.help'))
->default(fn () => $anime instanceof Anime && $anime->animesynonyms()->count() === 0),
->default(fn () => $anime->animesynonyms->isEmpty()),
]),
]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@

namespace App\Concerns\Filament\Actions\Models\Wiki\Artist;

use App\Actions\Models\Wiki\AttachResourceAction as AttachResourceActionAction;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Wiki\Artist;
use App\Rules\Wiki\Resource\ArtistResourceLinkFormatRule;
use Illuminate\Contracts\Validation\ValidationRule;

/**
* Trait AttachArtistResourceActionTrait.
Expand Down Expand Up @@ -37,18 +33,5 @@ protected function setUp(): void
ResourceSite::YOUTUBE_MUSIC,
ResourceSite::WIKI,
]);

$this->action(fn (Artist $record, array $data) => new AttachResourceActionAction($record, $data, $this->sites)->handle());
}

/**
* Get the format validation rule.
*
* @param ResourceSite $site
* @return ValidationRule
*/
protected function getFormatRule(ResourceSite $site): ValidationRule
{
return new ArtistResourceLinkFormatRule($site);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
namespace App\Concerns\Filament\Actions\Models\Wiki;

use App\Actions\Models\Wiki\AttachImageAction as AttachImageActionAction;
use App\Contracts\Models\HasImages;
use App\Enums\Models\Wiki\ImageFacet;
use App\Models\BaseModel;
use App\Models\Wiki\Anime;
use App\Models\Wiki\Artist;
use App\Models\Wiki\Image;
use App\Models\Wiki\Studio;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Form;

Expand Down Expand Up @@ -38,7 +36,7 @@ protected function setUp(): void

$this->authorize('create', Image::class);

$this->action(fn (BaseModel $record, array $data) => new AttachImageActionAction($record, $data, $this->facets)->handle());
$this->action(fn (BaseModel&HasImages $record, array $data, AttachImageActionAction $attachImage) => $attachImage->handle($record, $data, $this->facets));
}

/**
Expand All @@ -52,20 +50,25 @@ public function getForm(Form $form): Form
$fields = [];
$model = $form->getRecord();

if ($model instanceof Anime || $model instanceof Artist || $model instanceof Studio) {
foreach ($this->facets as $facet) {
$images = $model->images();
if ($images->where(Image::ATTRIBUTE_FACET, $facet->value)->exists()) continue;

$fields[] = FileUpload::make($facet->name)
->label($facet->localize())
->helperText(__('filament.actions.models.wiki.attach_image.help'))
->imageCropAspectRatio('2:3')
->image()
->imageEditor()
->imageEditorAspectRatios([null, '2:3'])
->storeFiles(false);
}
if (!($model instanceof HasImages)) return $form;

$images = $model->images()
->get([Image::ATTRIBUTE_FACET])
->pluck(Image::ATTRIBUTE_FACET)
->keyBy(fn (ImageFacet $facet) => $facet->value)
->keys();

foreach ($this->facets as $facet) {
if ($images->contains($facet->value)) continue;

$fields[] = FileUpload::make($facet->name)
->label($facet->localize())
->helperText(__('filament.actions.models.wiki.attach_image.help'))
->imageCropAspectRatio('2:3')
->image()
->imageEditor()
->imageEditorAspectRatios([null, '2:3'])
->storeFiles(false);
}

return $form
Expand Down
Loading

0 comments on commit e10bcfc

Please sign in to comment.