Skip to content

Commit

Permalink
add page that allows to fix broken trees
Browse files Browse the repository at this point in the history
  • Loading branch information
ildyria committed Nov 29, 2024
1 parent 3ec13bf commit ab4a977
Show file tree
Hide file tree
Showing 16 changed files with 662 additions and 18 deletions.
47 changes: 47 additions & 0 deletions app/Http/Controllers/Admin/Maintenance/FullTree.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace App\Http\Controllers\Admin\Maintenance;

use App\Http\Controllers\Admin\Maintenance\Model\Album;
use App\Http\Requests\Maintenance\FullTreeUpdateRequest;
use App\Http\Requests\Maintenance\MaintenanceRequest;
use App\Http\Resources\Diagnostics\AlbumTree;
use Illuminate\Routing\Controller;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

/**
* Maybe the album tree is broken.
* We fix it here.
*/
class FullTree extends Controller
{
/**
* Clean the path from all files excluding $this->skip.
*
* @return void
*/
public function do(FullTreeUpdateRequest $request): void
{
DB::beginTransaction();

$keyName = 'id';
$albumInstance = new Album();
batch()->updateMultipleCondition($albumInstance, $request->albums(), $keyName);

DB::commit();
}

/**
* Check whether there are files to be removed.
* If not, we will not display the module to reduce complexity.
*
* @return Collection<int,AlbumTree>
*/
public function check(MaintenanceRequest $request): Collection
{
$albums = Album::query()->join('base_albums', 'base_albums.id', '=', 'albums.id')->select(['albums.id', 'title', 'parent_id', '_lft', '_rgt'])->orderBy('_lft', 'asc')->toBase()->get();

return AlbumTree::collect($albums);
}
}
51 changes: 51 additions & 0 deletions app/Http/Requests/Maintenance/FullTreeUpdateRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace App\Http\Requests\Maintenance;

use App\Http\Requests\BaseApiRequest;
use App\Models\Configs;
use App\Policies\SettingsPolicy;
use App\Rules\AlbumIDRule;
use Illuminate\Support\Facades\Gate;

class FullTreeUpdateRequest extends BaseApiRequest
{
/**
* @var array<int,array{id:string,_lft:int,_rgt:int}>
*/
private array $albums;

/**
* {@inheritDoc}
*/
public function authorize(): bool
{
return Gate::check(SettingsPolicy::CAN_EDIT, Configs::class);
}

public function rules(): array
{
return [
'albums' => 'required|array|min:1',
'albums.*' => 'required|array',
'albums.*.id' => ['required', new AlbumIDRule(false)],
'albums.*._lft' => 'required|integer|min:1',
'albums.*._rgt' => 'required|integer|min:1',
];
}

protected function processValidatedValues(
array $values,
array $files,
): void {
$this->albums = $values['albums'];
}

/**
* @return array<int,array{id:string,_lft:int,_rgt:int}>
*/
public function albums(): array
{
return $this->albums;
}
}
31 changes: 31 additions & 0 deletions app/Http/Resources/Diagnostics/AlbumTree.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace App\Http\Resources\Diagnostics;

use App\Models\Album;
use Spatie\LaravelData\Data;
use Spatie\TypeScriptTransformer\Attributes\TypeScript;

#[TypeScript()]
class AlbumTree extends Data
{
public function __construct(
public string $id,
public string $title,
public ?string $parent_id,
public int $_lft,
public int $_rgt,
) {
}

public static function FromModel(Album $album): AlbumTree
{
return new self(
$album->id,
$album->title,
$album->parent_id,
$album->_lft,
$album->_rgt
);
}
}
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"lychee-org/nestedset": "^9.0",
"lychee-org/php-exif": "^1.0.4",
"maennchen/zipstream-php": "^3.1",
"mavinoo/laravel-batch": "^2.4",
"opcodesio/log-viewer": "dev-lycheeOrg",
"php-ffmpeg/php-ffmpeg": "^1.0",
"php-http/guzzle7-adapter": "^1.0",
Expand Down
58 changes: 57 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ function renv(string $cst, ?string $default = null): string

\SocialiteProviders\Manager\ServiceProvider::class,
// Barryvdh\Debugbar\ServiceProvider::class,
Mavinoo\Batch\BatchServiceProvider::class,

/*
* Application Service Providers...
Expand Down
3 changes: 3 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,6 @@ parameters:

-
message: '#Dynamic call to static method Illuminate\\Session\\Store::(has|get|now|forget)\(\).#'

-
message: '#Dynamic call to static method Kalnoy\\Nestedset\\QueryBuilder<.*>::(join|select|orderBy)\(\)#'
129 changes: 129 additions & 0 deletions resources/js/components/maintenance/FixTreeLine.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<template>
<div class="flex justify-between hover:bg-primary-emphasis/5 gap-8 items-center">
<div class="w-1/2" @mouseenter="setHoverId">
<span v-if="props.album.prefix.length > 4" class="font-mono" v-html="props.album.prefix.slice(0, -2)" />
<span
:class="{
'font-bold text-primary-emphasis': isHoverParent || isHoverId,
}"
v-if="props.album.prefix.length > 0"
>
</span>
<span
:class="{
'font-bold text-primary-emphasis': isHoverParent || isHoverId,
}"
>{{ props.album.title }}</span
>
</div>
<div class="flex w-1/4">
<div class="flex">
<InputNumber
class="border-0 w-full px-2"
pt:pcInputText:root:class="w-full border-0 px-3 py-1.5 w-full border-b hover:border-b-primary-400 focus:border-b-primary-400"
v-model="lft"
:invalid="lft === null || lft === undefined || lft === 0 || props.album.isDuplicate_lft"
mode="decimal"
:step="1"
placeholder="_lft"
@update:modelValue="console.log($event)"
/>
<Button text severity="secondary" icon="pi pi-angle-up" class="py-0.5" @click="incrementLft" />
<Button text severity="secondary" icon="pi pi-angle-down" class="py-0.5" @click="decrementLft" />
</div>
<div class="flex">
<InputNumber
class="border-0 w-full px-2"
pt:pcInputText:root:class="w-full border-0 px-3 py-1.5 w-full border-b hover:border-b-primary-400 focus:border-b-primary-400"
v-model="rgt"
:invalid="rgt === null || rgt === undefined || rgt === 0 || props.album.isDuplicate_rgt"
mode="decimal"
:step="1"
placeholder="_rgt"
/>
<Button text severity="secondary" icon="pi pi-angle-up" class="py-0.5" @click="incrementRgt" />
<Button text severity="secondary" icon="pi pi-angle-down" class="py-0.5" @click="decrementRgt" />
</div>
</div>
<div class="flex w-1/4 justify-between">
<div
@mouseenter="setHoverId"
:class="{
'font-bold text-primary-emphasis': isHoverId,
}"
>
{{ props.album.trimmedId }}
<span v-if="props.album.isDuplicate_lft" class="ml-2 text-warning-600 pi pi-chevron-circle-left" />
<span v-if="props.album.isDuplicate_rgt" class="ml-2 text-warning-600 pi pi-chevron-circle-right" />
</div>
<span
@mouseenter="setHoverParent"
:class="{
' text-muted-color-emphasis': props.album.trimmedParentId === 'root',
'!text-danger-600 font-bold': !props.album.isExpectedParentId,
'font-bold text-primary-emphasis': isHoverParent,
}"
>{{ props.album.trimmedParentId }}</span
>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, type Ref, watch } from "vue";
import { AugmentedAlbum } from "@/composables/album/treeOperations";
import InputNumber from "primevue/inputnumber";
import Button from "primevue/button";
const props = defineProps<{
album: AugmentedAlbum;
isHoverId: boolean;
isHoverParent: boolean;
}>();
const lft = defineModel("lft") as Ref<number>;
const rgt = defineModel("rgt") as Ref<number>;
const isHoverId = ref<boolean>(props.isHoverId);
const isHoverParent = ref<boolean>(props.isHoverParent);
const emits = defineEmits<{
hoverId: [id: string];
incrementLft: [];
decrementLft: [];
incrementRgt: [];
decrementRgt: [];
}>();
function setHoverId() {
emits("hoverId", props.album.trimmedId);
}
function setHoverParent() {
emits("hoverId", props.album.trimmedParentId);
}
function incrementLft() {
emits("incrementLft");
}
function decrementLft() {
emits("decrementLft");
}
function incrementRgt() {
emits("incrementRgt");
}
function decrementRgt() {
emits("decrementRgt");
}
watch(
() => [props.isHoverId, props.isHoverParent],
([newIsHoverId, newIsHoverParent]) => {
isHoverId.value = newIsHoverId;
isHoverParent.value = newIsHoverParent;
},
);
</script>
Loading

0 comments on commit ab4a977

Please sign in to comment.