Skip to content

Commit

Permalink
#2: activity log UI
Browse files Browse the repository at this point in the history
  • Loading branch information
iqbaleff214 committed Feb 20, 2025
1 parent 22bafb5 commit 040f34b
Show file tree
Hide file tree
Showing 16 changed files with 298 additions and 6 deletions.
58 changes: 58 additions & 0 deletions app/Http/Controllers/ActivityLogController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace App\Http\Controllers;

use App\Models\ActivityLog;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;

class ActivityLogController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request): View
{
return view('pages.log.index', [
'items' => ActivityLog::query()
->causedBy($request->user())
->search($request->query('q'))
->render($request->query('size')),
]);
}

/**
* Remove the specified resource from storage.
*/
public function destroy(ActivityLog $log): RedirectResponse
{
try {
$log->delete();

return back()
->with('notification', $this->successNotification('notification.success_delete', 'menu.activity_log'));
} catch (\Throwable $throwable) {
Log::error($throwable->getMessage());

return back()
->with('notification', $this->failNotification('notification.fail_delete', 'menu.activity_log'));
}
}

public function destroyBulk(Request $request): RedirectResponse
{
try {
ActivityLog::query()->delete();

return back()
->with('notification', $this->successNotification('notification.success_delete', 'menu.activity_log'));
} catch (\Throwable $throwable) {
Log::error($throwable->getMessage());

return back()
->with('notification', $this->failNotification('notification.fail_delete', 'menu.activity_log'));
}
}
}
6 changes: 6 additions & 0 deletions app/Http/Controllers/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ public function __construct()
'active' => Route::is('account.password.edit'),
'available' => true,
],
[
'url' => route('account.log.index'),
'name' => __('menu.activity_log'),
'active' => Route::is('account.log.index'),
'available' => true,
],
],
],
]);
Expand Down
39 changes: 39 additions & 0 deletions app/Models/ActivityLog.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Spatie\Activitylog\Models\Activity;

class ActivityLog extends Activity
{
protected $appends = [
'module'
];

public function module(): Attribute
{
return new Attribute(
get: function () {
$module = strtolower($this->log_name);
$module = basename(str_replace("\\", "/", $module));
return __('menu.' . $module);
}
);
}

public function scopeSearch(Builder $query, ?string $search)
{
return $query->when($search, function (Builder $query, string $search) {
return $query
->where('log_name', 'LIKE', $search.'%')
->orWhere('subject', $search);
});
}

public function scopeRender(Builder $query, ?int $page): \Illuminate\Contracts\Pagination\LengthAwarePaginator
{
return $query->latest()->paginate($page ?? 50)->withQueryString();
}
}
31 changes: 31 additions & 0 deletions app/Models/Role.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;

class Role extends \Spatie\Permission\Models\Role
{
use LogsActivity;

public function scopeSearch(Builder $query, ?string $search)
{
return $query->when($search, function (Builder $query, string $search) {
Expand All @@ -17,4 +21,31 @@ public function scopeRender(Builder $query, ?int $page): \Illuminate\Contracts\P
{
return $query->paginate($page ?? 50)->withQueryString();
}

public function getActivitylogOptions(): LogOptions
{
return LogOptions::defaults()
->useLogName(self::class)
->logOnly([
'name',
])
->logOnlyDirty()
->dontSubmitEmptyLogs()
->setDescriptionForEvent(fn(string $eventName) => match ($eventName) {
'created' => __('activity.created', [
'menu' => __('menu.role'),
'identifier' => $this->name,
'link' => route('role.show', $this->id),
]),
'updated' => __('activity.updated', [
'menu' => __('menu.role'),
'identifier' => $this->name,
'link' => route('role.show', $this->id),
]),
'deleted' => __('activity.deleted', [
'menu' => __('menu.role'),
'identifier' => $this->name,
]),
});
}
}
52 changes: 52 additions & 0 deletions config/activitylog.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

return [

/*
* If set to false, no activities will be saved to the database.
*/
'enabled' => env('ACTIVITY_LOGGER_ENABLED', true),

/*
* When the clean-command is executed, all recording activities older than
* the number of days specified here will be deleted.
*/
'delete_records_older_than_days' => 365,

/*
* If no log name is passed to the activity() helper
* we use this default log name.
*/
'default_log_name' => 'default',

/*
* You can specify an auth driver here that gets user models.
* If this is null we'll use the current Laravel auth driver.
*/
'default_auth_driver' => null,

/*
* If set to true, the subject returns soft deleted models.
*/
'subject_returns_soft_deleted_models' => false,

/*
* This model will be used to log activity.
* It should implement the Spatie\ActivityLog\Contracts\Activity interface
* and extend Illuminate\Database\Eloquent\Model.
*/
'activity_model' => \App\Models\ActivityLog::class,

/*
* This is the name of the table that will be created by the migration and
* used by the Activity model shipped with this package.
*/
'table_name' => env('ACTIVITY_LOGGER_TABLE_NAME', 'activity_log'),

/*
* This is the database connection that will be used by the migration and
* the Activity model shipped with this package. In case it's not set
* Laravel is database.default will be used instead.
*/
'database_connection' => env('ACTIVITY_LOGGER_DB_CONNECTION'),
];
11 changes: 11 additions & 0 deletions lang/en/activity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

return [
'created' => 'Created new :menu <a class="link" target="_blank" href=":link">:identifier</a>.',
'updated' => 'Updated :menu <a class="link" target="_blank" href=":link">:identifier</a>.',
'deleted' => 'Deleted :menu :identifier.',
'status-updated' => 'Updated :menu <a class="link" target="_blank" href=":link">:identifier</a>\'s status as <strong>:status</strong>.',
'uploaded' => 'Uploaded new <strong>:file</strong> for :menu <a class="link" target="_blank" href=":link">:identifier</a>.',
'delete-uploaded' => 'Deleted an uploaded <strong>:file</strong> for :menu <a class="link" target="_blank" href=":link">:identifier</a>.',
'notary-office-accessed' => 'Notary Office <a class="link" target="_blank" href=":link">:identifier</a> accessed by administrator.',
];
1 change: 1 addition & 0 deletions lang/en/button.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
'import_feature' => 'Import :Feature',
'delete' => 'Delete',
'edit' => 'Edit',
'delete_all' => 'Delete All',

];
6 changes: 6 additions & 0 deletions lang/en/field.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,10 @@
'current_password' => 'Current Password',
'role' => 'Role',
'permission' => 'Permission',
'module' => 'Module',
'description' => 'Description',
'created_at' => 'Created At',
'updated_at' => 'Updated At',
'deleted_at' => 'Deleted At',
'timestamp' => 'Timestamp',
];
1 change: 1 addition & 0 deletions lang/en/menu.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
'user' => 'User',
'role' => 'Role & Permission',
'my_setting' => 'My Settings',
'activity_log' => 'Activity Log',
];
11 changes: 11 additions & 0 deletions lang/id/activity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

return [
'created' => 'Membuat :menu <a class="link" target="_blank" href=":link">:identifier</a>.',
'updated' => 'Memperbarui :menu <a class="link" target="_blank" href=":link">:identifier</a>.',
'deleted' => 'Menghapus :menu :identifier.',
'status-updated' => 'Mengubah status :menu <a class="link" target="_blank" href=":link">:identifier</a> menjadi <strong>:status</strong>.',
'uploaded' => 'Mengunggah <strong>:file</strong> baru pada :menu <a class="link" target="_blank" href=":link">:identifier</a>.',
'delete-uploaded' => 'Menghapus <strong>:file</strong> pada :menu <a class="link" target="_blank" href=":link">:identifier</a>.',
'notary-office-accessed' => 'Kantor Notaris <a class="link" target="_blank" href=":link">:identifier</a> diakses oleh pengelola.',
];
1 change: 1 addition & 0 deletions lang/id/button.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
'import_feature' => 'Impor :Feature',
'delete' => 'Hapus',
'edit' => 'Edit',
'delete_all' => 'Hapus Semua',

];
6 changes: 6 additions & 0 deletions lang/id/field.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,10 @@
'current_password' => 'Password Sekarang',
'role' => 'Peran',
'permission' => 'Hak Akses',
'module' => 'Modul',
'description' => 'Deskripsi',
'created_at' => 'Waktu Dibuat',
'updated_at' => 'Waktu Diubah',
'deleted_at' => 'Waktu Hapus',
'timestamp' => 'Waktu',
];
1 change: 1 addition & 0 deletions lang/id/menu.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@
'user' => 'Pengguna',
'role' => 'Peran dan Hak Akses',
'my_setting' => 'Pengaturan Saya',
'activity_log' => 'Riwayat Aktivitas',
];
6 changes: 6 additions & 0 deletions resources/views/components/navbar.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ class="github-button"
<span class="align-middle">{{ __('menu.account') }}</span>
</a>
</li>
<li>
<a class="dropdown-item" href="{{ route('account.log.index') }}">
<i class="bx bx-history me-2"></i>
<span class="align-middle">{{ __('menu.activity_log') }}</span>
</a>
</li>
<li>
<div class="dropdown-divider"></div>
</li>
Expand Down
58 changes: 58 additions & 0 deletions resources/views/pages/log/index.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
@extends('layouts.dashboard')

@section('content')
<div class="card">
<div class="card-header d-flex justify-content-between">
<h5>{{ __('menu.activity_log') }}</h5>
<div>
<form action="{{ route('account.log.destroy.bulk') }}" method="post" class="delete-form">
@csrf
@method('DELETE')
<button class="btn btn-danger">
{{ __('button.delete_all') }}
</button>
</form>
</div>
</div>
<div class="table-responsive text-nowrap">
<table class="table">
<thead>
<tr>
<th>{{ __('field.timestamp') }}</th>
<th>{{ __('field.module') }}</th>
<th>{{ __('field.description') }}</th>
<th style="width: 50px"></th>
</tr>
</thead>
<tbody class="table-border-bottom-0">
@foreach($items as $item)
<tr>
<td>{{ $item->created_at }}</td>
<td>{{ $item->module }}</td>
<td>{!! $item->description !!}</td>
<td>
<div class="dropdown">
<button type="button" class="btn p-0 dropdown-toggle hide-arrow" data-bs-toggle="dropdown"><i class="bx bx-dots-vertical-rounded"></i></button>
<div class="dropdown-menu">
<form action="{{ route('account.log.destroy', $item->id) }}" method="post" class="delete-form">
@csrf
@method('DELETE')
<button class="dropdown-item" type="submit">
<i class="bx bx-trash me-1"></i>
{{ __('button.delete') }}
</button>
</form>
</div>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>

<div class="card-body">
{!! $items->links() !!}
</div>
</div>
@endsection
16 changes: 10 additions & 6 deletions routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@
Route::patch('/role/{role}', [\App\Http\Controllers\RoleController::class, 'update'])->name('role.update')->can('edit_role');
Route::delete('/role/{role}', [\App\Http\Controllers\RoleController::class, 'destroy'])->name('role.destroy')->can('delete_role');

Route::as('account.')->group(function () {
Route::get('/account/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/account/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/account/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
Route::get('/account/change-password', [PasswordController::class, 'edit'])->name('password.edit');
Route::get('/account/change-language', [PageController::class, 'locale'])->name('locale');
Route::as('account.')->prefix('account')->group(function () {
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
Route::get('/change-password', [PasswordController::class, 'edit'])->name('password.edit');
Route::get('/change-language', [PageController::class, 'locale'])->name('locale');

Route::get('/activity-log', [\App\Http\Controllers\ActivityLogController::class, 'index'])->name('log.index');
Route::delete('/activity-log', [\App\Http\Controllers\ActivityLogController::class, 'destroyBulk'])->name('log.destroy.bulk');
Route::delete('/activity-log/{log}', [\App\Http\Controllers\ActivityLogController::class, 'destroy'])->name('log.destroy');
});
});

Expand Down

0 comments on commit 040f34b

Please sign in to comment.