fix: 🩹 update activity logs functionnality
This commit is contained in:
parent
c3bad6a098
commit
98856ed81f
8 changed files with 98 additions and 35 deletions
|
|
@ -4,13 +4,11 @@ namespace App\Http\Controllers\Bo;
|
|||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\ActivityLog;
|
||||
use App\Traits\Controllers\ChangesModelOrder;
|
||||
use App\Traits\Controllers\UpdateModelPublished;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ActivityLogController extends Controller
|
||||
{
|
||||
use ChangesModelOrder;
|
||||
use UpdateModelPublished;
|
||||
|
||||
/**
|
||||
|
|
@ -25,6 +23,12 @@ class ActivityLogController extends Controller
|
|||
/** @var \Illuminate\Database\Eloquent\Builder $query */
|
||||
$query = ActivityLog::query()->with('user');
|
||||
|
||||
/** @var \App\Models\User|null $userModel */
|
||||
$userModel = $request->route()->parameter('user');
|
||||
if ($userModel) {
|
||||
$query->where('user_id', $userModel->getKey());
|
||||
}
|
||||
|
||||
/** @var string $search Search field */
|
||||
$search = $request->search;
|
||||
if ($search) {
|
||||
|
|
@ -45,7 +49,12 @@ class ActivityLogController extends Controller
|
|||
/** Custom pagination */
|
||||
$activitylogModels = $this->paginate($query);
|
||||
|
||||
return view('bo.pages.activity_logs.index', compact('activitylogModels', 'search', 'searchFields'));
|
||||
return view('bo.pages.activity_logs.index', compact(
|
||||
'activitylogModels',
|
||||
'search',
|
||||
'searchFields',
|
||||
'userModel'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use App\Enums\ActivityLogs\ActivityLogsEventEnum;
|
|||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @property string $model Target model.
|
||||
|
|
@ -98,22 +98,71 @@ class ActivityLog extends Model
|
|||
{
|
||||
$modelClassName = $activity->model_class;
|
||||
/** Get type of each fields of the target model */
|
||||
/** @var \Illuminate\Database\Eloquent\Model|null $targetModel */
|
||||
$targetModel = $activity->model_class::where(
|
||||
(new $modelClassName())->getRouteKeyName(),
|
||||
$activity->model_id
|
||||
)->first();
|
||||
if ($targetModel != null) {
|
||||
// phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
|
||||
$targetModelTypes = collect($targetModel->toArray())
|
||||
->map(function ($field, $fieldIndex) use ($targetModel) {
|
||||
return Schema::getColumnType($targetModel->getTable(), $fieldIndex);
|
||||
})->toArray();
|
||||
// phpcs:enable
|
||||
/** Return old, new and type of values changed */
|
||||
return ($eventEnum === ActivityLogsEventEnum::updated) ?
|
||||
array_intersect_key($targetModelTypes, $model->getChanges()) : [];
|
||||
|
||||
if (\is_null($targetModel)) {
|
||||
return [];
|
||||
}
|
||||
return [];
|
||||
$targetModelTypes = collect($targetModel->toArray())
|
||||
->map(fn($value) => self::getValueType($value))
|
||||
->toArray();
|
||||
/** Return old, new and type of values changed */
|
||||
return match ($eventEnum) {
|
||||
ActivityLogsEventEnum::created => array_intersect_key($targetModelTypes, $model->toArray()),
|
||||
ActivityLogsEventEnum::duplicated => array_intersect_key($targetModelTypes, $model->toArray()),
|
||||
ActivityLogsEventEnum::updated => array_intersect_key($targetModelTypes, $model->getChanges()),
|
||||
default => []
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a value type as a string
|
||||
* ! Use this for display purpose only
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
* @throws \RuntimeException If type is unhlanded.
|
||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.MaxExceeded
|
||||
*/
|
||||
private static function getValueType(mixed $value): string
|
||||
{
|
||||
// phpcs:enable
|
||||
$type = \gettype($value);
|
||||
switch ($type) {
|
||||
// phpcs:ignore PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
|
||||
case 'string':
|
||||
return match (true) {
|
||||
Str::length(\strip_tags($value)) !== Str::length($value) => 'html',
|
||||
Str::startsWith($value, 'storage/modelfiles') => 'file',
|
||||
Str::isUuid($value) => 'uuid',
|
||||
Str::isUlid($value) => 'ulid',
|
||||
Str::isUrl($value) => 'url',
|
||||
Str::isMatch('/^[0-9A-Za-z_-]{10}[048AEIMQUYcgkosw]$/', $value) => 'youtube_video_id',
|
||||
\is_numeric($value) => 'numeric',
|
||||
Str::isJson($value) and
|
||||
(Str::startsWith($value, '[') or Str::startsWith($value, '{')) => 'json',
|
||||
default => 'string'
|
||||
};
|
||||
case 'NULL':
|
||||
case 'object':
|
||||
case 'array':
|
||||
case 'integer':
|
||||
case 'boolean':
|
||||
return $type;
|
||||
case 'double':
|
||||
return is_float($value) ? 'float' : 'double';
|
||||
case 'resource (closed)':
|
||||
case 'resource':
|
||||
throw new \RuntimeException('Laravel model properties should not contain resources !');
|
||||
case 'unknown type':
|
||||
default:
|
||||
throw new \RuntimeException('Unhandled Type ' . \gettype($value));
|
||||
} //end switch
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@ use Illuminate\Notifications\Notifiable;
|
|||
* @property \Illuminate\Support\Carbon $published_at Publication status update date.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Created date.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
|
||||
*
|
||||
* @property-read \App\Models\ActivityLog $activityLogs Activities logs One-to-many relationship.
|
||||
*/
|
||||
class User extends Authenticatable
|
||||
{
|
||||
|
|
@ -91,16 +89,4 @@ class User extends Authenticatable
|
|||
);
|
||||
});
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* Activities logs One-to-many relationship.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function activityLogs(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(ActivityLog::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Traits\Models;
|
||||
|
||||
use App\Observers\ModelObserver;
|
||||
use App\Models\ActivityLog as ActivityLogModel;
|
||||
|
||||
/**
|
||||
* If there is a static function in a trait (named boot[TraitName]),
|
||||
|
|
@ -20,4 +21,16 @@ trait ActivityLog
|
|||
{
|
||||
static::observe(ModelObserver::class);
|
||||
}
|
||||
|
||||
// * RELATIONS
|
||||
|
||||
/**
|
||||
* Activities logs One-to-many relationship.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function activityLogs(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(ActivityLogModel::class, 'model_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class UserFactory extends Factory
|
|||
public function unverified(): static
|
||||
{
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
return $this->state(fn (array $attributes) => [
|
||||
return $this->state(fn() => [
|
||||
'email_verified_at' => null,
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ return new class extends Migration
|
|||
{
|
||||
Schema::create('activity_logs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('user_id')->nullable()->constrained('users')->nullOnDelete();
|
||||
$table->foreignId('user_id')->nullable()->constrained('users')->nullOnDelete()
|
||||
->comment('Id of the user associated, or nullable for a deleted user.');
|
||||
$table->boolean('is_anonymous')->comment('If there is no user connected when action was realised.');
|
||||
$table->boolean('is_console')->comment('If the action was realised in console.');
|
||||
$table->string('model_class')->comment('Target model.');
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
@extends('bo.layout')
|
||||
@extends('bo.layout', ['brParam' => $userModel])
|
||||
|
||||
@section('title', Str::ucfirst(trans_choice('models.classes.activity_log', '*')))
|
||||
@section('description', __('Liste de tous les :model', ['model' => trans_choice('models.classes.activity_log', '*')]))
|
||||
@section('breadcrumb', request()->route()->getName())
|
||||
|
||||
@section('content')
|
||||
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap">
|
||||
@include('modules.breadcrumbs.breadcrumb-body')
|
||||
@include('modules.breadcrumbs.breadcrumb-body', ['brParam' => $userModel])
|
||||
</div>
|
||||
@include('bo.modules.search-bar')
|
||||
<div class="table-responsive mb-3">
|
||||
|
|
|
|||
|
|
@ -41,15 +41,19 @@ Route::prefix('bo')
|
|||
// * USERS.
|
||||
Route::resource('users', UserController::class)->except('show');
|
||||
Route::patch('/users/{user}/change-published', [
|
||||
UserController::class, 'changePublished'
|
||||
UserController::class,
|
||||
'changePublished'
|
||||
])->name('users.change-published');
|
||||
Route::get('/users/{user}/duplicate', [
|
||||
UserController::class, 'duplicate'
|
||||
UserController::class,
|
||||
'duplicate'
|
||||
])->name('users.duplicate');
|
||||
|
||||
Route::middleware('can:isConceptor')->group(function () {
|
||||
// * ACTIVITY LOGS.
|
||||
Route::resource('activity_logs', ActivityLogController::class)->only(['index', 'show']);
|
||||
Route::get('/activity_logs/user/{user:id}', [ActivityLogController::class, 'index'])
|
||||
->name('activity_logs.user');
|
||||
});
|
||||
});
|
||||
// * Others routes
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue