diff --git a/app/Entities/Users/Activity.php b/app/Entities/Users/Activity.php
index 2f63cbe..9d50807 100644
--- a/app/Entities/Users/Activity.php
+++ b/app/Entities/Users/Activity.php
@@ -2,6 +2,7 @@
namespace App\Entities\Users;
+use App\Entities\Users\User;
use Illuminate\Database\Eloquent\Model;
class Activity extends Model
@@ -11,4 +12,14 @@ class Activity extends Model
protected $fillable = ['type', 'parent_id', 'user_id', 'object_id', 'object_type', 'data'];
protected $casts = ['data' => 'array'];
+
+ public function user()
+ {
+ return $this->belongsTo(User::class)->withDefault(['name' => 'n/a']);
+ }
+
+ public function object()
+ {
+ return $this->morphTo();
+ }
}
diff --git a/app/Http/Controllers/Projects/ActivityController.php b/app/Http/Controllers/Projects/ActivityController.php
new file mode 100644
index 0000000..b39416e
--- /dev/null
+++ b/app/Http/Controllers/Projects/ActivityController.php
@@ -0,0 +1,24 @@
+where(function ($query) use ($project) {
+ $query->where('object_id', $project->id);
+ $query->where('object_type', 'projects');
+ });
+
+ $activities = $activityQuery->latest()->paginate();
+
+ return view('projects.activities.index', compact('project', 'activities'));
+ }
+}
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index e62e20c..5fe772b 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -25,6 +25,7 @@ class AppServiceProvider extends ServiceProvider
'projects' => 'App\Entities\Projects\Project',
'issues' => 'App\Entities\Projects\Issue',
'jobs' => 'App\Entities\Projects\Job',
+ 'tasks' => 'App\Entities\Projects\Task',
]);
Paginator::useBootstrap();
}
diff --git a/resources/lang/de/activity.php b/resources/lang/de/activity.php
new file mode 100644
index 0000000..a483ba5
--- /dev/null
+++ b/resources/lang/de/activity.php
@@ -0,0 +1,9 @@
+ [
+ 'project_created' => 'Project created: :name new :user.',
+ 'project_updated' => 'Project data :name updated by :user.',
+ 'job_deleted' => 'Job deleted by :user.',
+ ],
+];
diff --git a/resources/lang/de/project.php b/resources/lang/de/project.php
index 07898c5..28ab2d7 100644
--- a/resources/lang/de/project.php
+++ b/resources/lang/de/project.php
@@ -59,6 +59,7 @@ return [
'proposal_date' => 'Datum des Angebotes',
'project_value' => 'Projektwert',
'proposal_value' => 'Angebotswert',
+ 'updated_at' => 'Last Update',
// Relations
'files' => 'Dokumentenliste',
@@ -72,6 +73,7 @@ return [
'status' => 'Projektstatus',
'payments' => 'Zahlungen',
'issues' => 'Issues',
+ 'activities' => 'Activities',
// Statuses
'planned' => 'geplant',
diff --git a/resources/lang/en/activity.php b/resources/lang/en/activity.php
new file mode 100644
index 0000000..a483ba5
--- /dev/null
+++ b/resources/lang/en/activity.php
@@ -0,0 +1,9 @@
+ [
+ 'project_created' => 'Project created: :name new :user.',
+ 'project_updated' => 'Project data :name updated by :user.',
+ 'job_deleted' => 'Job deleted by :user.',
+ ],
+];
diff --git a/resources/lang/en/project.php b/resources/lang/en/project.php
index c3a5c40..8b104f6 100644
--- a/resources/lang/en/project.php
+++ b/resources/lang/en/project.php
@@ -59,6 +59,7 @@ return [
'proposal_date' => 'Proposal Date',
'project_value' => 'Project Value',
'proposal_value' => 'Proposal Value',
+ 'updated_at' => 'Last Update',
// Relations
'files' => 'Document List',
@@ -72,6 +73,7 @@ return [
'status' => 'Project Status',
'payments' => 'Payments',
'issues' => 'Issues',
+ 'activities' => 'Activities',
// Statuses
'planned' => 'Planned',
diff --git a/resources/lang/id/activity.php b/resources/lang/id/activity.php
new file mode 100644
index 0000000..19cb1ea
--- /dev/null
+++ b/resources/lang/id/activity.php
@@ -0,0 +1,9 @@
+ [
+ 'project_created' => 'Input project baru: :name oleh :user.',
+ 'project_updated' => 'Data project :name diubah oleh :user.',
+ 'job_deleted' => 'Job dihapus oleh :user.',
+ ],
+];
diff --git a/resources/lang/id/project.php b/resources/lang/id/project.php
index 2ea3b04..fcea474 100644
--- a/resources/lang/id/project.php
+++ b/resources/lang/id/project.php
@@ -59,6 +59,7 @@ return [
'proposal_date' => 'Tanggal Proposal',
'project_value' => 'Nilai Project',
'proposal_value' => 'Nilai Proposal',
+ 'updated_at' => 'Waktu Update',
// Relations
'files' => 'List Dokumen',
@@ -72,6 +73,7 @@ return [
'status' => 'Status Project',
'payments' => 'Pembayaran',
'issues' => 'Issue',
+ 'activities' => 'Aktifitas',
// Statuses
'planned' => 'Rencana',
diff --git a/resources/views/projects/activities/index.blade.php b/resources/views/projects/activities/index.blade.php
new file mode 100755
index 0000000..ade6096
--- /dev/null
+++ b/resources/views/projects/activities/index.blade.php
@@ -0,0 +1,22 @@
+@extends('layouts.project')
+
+@section('subtitle', __('project.activities'))
+
+@section('content-project')
+
+
+
+ {{ $activities->links() }}
+
+ @foreach($activities as $activity)
+ @includeWhen(
+ view()->exists('users.activities.'.$activity->object_type.'.'.$activity->type),
+ 'users.activities.'.$activity->object_type.'.'.$activity->type
+ )
+ @endforeach
+
+ {{ $activities->links() }}
+
+
+
+@endsection
diff --git a/resources/views/projects/partials/nav-tabs.blade.php b/resources/views/projects/partials/nav-tabs.blade.php
index ed2ee19..47df5b1 100644
--- a/resources/views/projects/partials/nav-tabs.blade.php
+++ b/resources/views/projects/partials/nav-tabs.blade.php
@@ -3,6 +3,9 @@
{!! link_to_route('projects.show', __('project.detail'), $project) !!}
+
+ {!! link_to_route('projects.activities.index', __('project.activities'), $project) !!}
+
@can('view-jobs', $project)
{!! link_to_route('projects.jobs.index', __('project.jobs').' ('.$project->jobs->count().')', $project) !!}
diff --git a/resources/views/users/activities/activity_list_item.blade.php b/resources/views/users/activities/activity_list_item.blade.php
new file mode 100644
index 0000000..ad295f8
--- /dev/null
+++ b/resources/views/users/activities/activity_list_item.blade.php
@@ -0,0 +1,4 @@
+
+ {{ $time }}
+ {{ $body }}
+
diff --git a/resources/views/users/activities/projects/job_deleted.blade.php b/resources/views/users/activities/projects/job_deleted.blade.php
new file mode 100644
index 0000000..57a1fa9
--- /dev/null
+++ b/resources/views/users/activities/projects/job_deleted.blade.php
@@ -0,0 +1,15 @@
+@component('users.activities.activity_list_item')
+@slot('time')
+ {{ $activity->created_at }}
+@endslot
+@slot('body')
+
+ {!! __('activity.'.$activity->object_type.'.'.$activity->type, [
+ 'user' => $activity->user->name,
+ ]) !!}
+
+ {{ __('job.name') }}: {{ $activity->data['name'] }}
+ {{ __('job.description') }}: {{ $activity->data['description'] }}
+ {{ __('job.price') }}: {{ format_money($activity->data['price']) }}
+@endslot
+@endcomponent
diff --git a/resources/views/users/activities/projects/project_created.blade.php b/resources/views/users/activities/projects/project_created.blade.php
new file mode 100644
index 0000000..421f0c6
--- /dev/null
+++ b/resources/views/users/activities/projects/project_created.blade.php
@@ -0,0 +1,11 @@
+@component('users.activities.activity_list_item')
+@slot('time')
+ {{ $activity->created_at }}
+@endslot
+@slot('body')
+ {!! __('activity.'.$activity->object_type.'.'.$activity->type, [
+ 'user' => $activity->user->name,
+ 'name' => $activity->object->name,
+ ]) !!}
+@endslot
+@endcomponent
diff --git a/resources/views/users/activities/projects/project_updated.blade.php b/resources/views/users/activities/projects/project_updated.blade.php
new file mode 100644
index 0000000..0a2d36b
--- /dev/null
+++ b/resources/views/users/activities/projects/project_updated.blade.php
@@ -0,0 +1,22 @@
+@component('users.activities.activity_list_item')
+@slot('time')
+ {{ $activity->created_at }}
+@endslot
+@slot('body')
+
+ {!! __('activity.'.$activity->object_type.'.'.$activity->type, [
+ 'user' => $activity->user->name,
+ 'name' => $activity->object->name,
+ ]) !!}
+
+ @php
+ $data = $activity->data;
+ @endphp
+ @foreach ($data['before'] as $key => $value)
+ @php
+ $afterValue = $data['after'][$key] ?? null;
+ @endphp
+ {{ __('project.'.$key) }}: {{ $value }} => {{ $afterValue }}
+ @endforeach
+@endslot
+@endcomponent
diff --git a/routes/web/projects.php b/routes/web/projects.php
index 45aefba..bc92298 100644
--- a/routes/web/projects.php
+++ b/routes/web/projects.php
@@ -26,6 +26,11 @@ Route::group(['middleware' => ['auth'], 'namespace' => 'Projects'], function ()
Route::get('projects/{project}/invoices', ['as' => 'projects.invoices', 'uses' => 'InvoicesController@index']);
/*
+ * Project Activities Routes
+ */
+ Route::get('projects/{project}/activities', ['as' => 'projects.activities.index', 'uses' => 'ActivityController@index']);
+
+ /*
* Project Jobs Routes
*/
Route::get('projects/{project}/jobs-export/{type?}', ['as' => 'projects.jobs-export', 'uses' => 'JobsController@jobsExport']);
diff --git a/tests/Unit/Models/ActivityTest.php b/tests/Unit/Models/ActivityTest.php
index 96bd2c8..5187594 100644
--- a/tests/Unit/Models/ActivityTest.php
+++ b/tests/Unit/Models/ActivityTest.php
@@ -5,6 +5,8 @@ namespace Tests\Unit\Models;
use App\Entities\Projects\Job;
use App\Entities\Projects\Project;
use App\Entities\Projects\Task;
+use App\Entities\Users\Activity;
+use App\Entities\Users\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
@@ -213,4 +215,36 @@ class ActivityTest extends TestCase
]),
]);
}
+
+ /** @test */
+ public function an_activity_has_belongs_to_user_relation()
+ {
+ $project = factory(Project::class)->create();
+ $activity = Activity::where('object_type', 'projects')
+ ->where('object_id', $project->id)
+ ->first();
+
+ $this->assertInstanceOf(User::class, $activity->user);
+ $this->assertEquals($activity->user_id, $activity->user->id);
+ }
+
+ /** @test */
+ public function an_activity_has_belongs_to_object_relation()
+ {
+ $project = factory(Project::class)->create();
+ $job = factory(Job::class)->create(['project_id' => $project->id]);
+ $task = factory(Task::class)->create(['job_id' => $job->id]);
+
+ $projectActivity = Activity::where('object_type', 'projects')->first();
+ $this->assertInstanceOf(Project::class, $projectActivity->object);
+ $this->assertEquals($projectActivity->object_id, $projectActivity->object->id);
+
+ $jobActivity = Activity::where('object_type', 'jobs')->first();
+ $this->assertInstanceOf(Job::class, $jobActivity->object);
+ $this->assertEquals($jobActivity->object_id, $jobActivity->object->id);
+
+ $taskActivity = Activity::where('object_type', 'tasks')->first();
+ $this->assertInstanceOf(Task::class, $taskActivity->object);
+ $this->assertEquals($taskActivity->object_id, $taskActivity->object->id);
+ }
}