Ver código fonte

Merge branch 'project-dynamic' into dev

moell 1 ano atrás
pai
commit
217525802c

+ 10 - 0
app/Http/Controllers/API/ProjectController.php

@@ -322,4 +322,14 @@ class ProjectController extends Controller
         });
         return $this->noContent();
     }
+
+
+    public function dynamic(Request $request, string $id)
+    {
+        $project = Project::findOrFail($id);
+
+        return $this->success([
+            'data' => ActionRepository::dynamic($project, $request->all())
+        ]);
+    }
 }

+ 38 - 0
app/ModelFilters/ActionFilter.php

@@ -0,0 +1,38 @@
+<?php
+
+namespace App\ModelFilters;
+
+use Carbon\Carbon;
+use EloquentFilter\ModelFilter;
+
+class ActionFilter extends ModelFilter
+{
+    /**
+    * Related Models that have ModelFilters as well as the method on the ModelFilter
+    * As [relationMethod => [input_key1, input_key2]].
+    *
+    * @var array
+    */
+    public $relations = [];
+
+    public function user($id)
+    {
+        return $this->where("created_by", $id);
+    }
+
+    public function time($time)
+    {
+        return match ($time) {
+            "today" => $this->where("created_at", ">=", Carbon::now()->startOfDay()),
+            "yesterday" => $this->where("created_at", ">=", Carbon::now()->subDay()->startOfDay())
+                ->where("created_at", "<", Carbon::now()->startOfDay()),
+            "this_week" => $this->where("created_at", ">=", Carbon::now()->startOfWeek()),
+            "last_week" => $this->where("created_at", ">=", Carbon::now()->subWeek()->startOfWeek())
+                ->where("created_at", "<", Carbon::now()->startOfWeek()),
+            "this_month" => $this->where("created_at", ">=", Carbon::now()->startOfMonth()),
+            "last_month" => $this->where("created_at", ">=", Carbon::now()->subMonth()->startOfMonth())
+                ->where("created_at", "<", Carbon::now()->startOfMonth()),
+            default => $this,
+        };
+    }
+}

+ 7 - 1
app/Models/Action.php

@@ -2,16 +2,22 @@
 
 namespace App\Models;
 
+use EloquentFilter\Filterable;
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 
 class Action extends Model
 {
-    use HasFactory;
+    use HasFactory, Filterable;
 
     protected $guarded = ['id'];
 
     protected $casts = [
         'extra_fields' => 'array',
     ];
+
+    public function createdBy(): \Illuminate\Database\Eloquent\Relations\BelongsTo
+    {
+        return $this->belongsTo(User::class, "created_by");
+    }
 }

+ 25 - 0
app/Models/Enums/ActionObjectType.php

@@ -2,6 +2,11 @@
 
 namespace App\Models\Enums;
 
+use App\Models\Asset;
+use App\Models\Plan;
+use App\Models\Project;
+use App\Models\Task;
+
 enum ActionObjectType: string
 {
     case ASSET = "asset";
@@ -9,4 +14,24 @@ enum ActionObjectType: string
     case PROJECT = "project";
 
     case TASK = "task";
+
+    case PLAN = "plan";
+
+    public function modelBuilder(): \Illuminate\Database\Eloquent\Builder
+    {
+        return match ($this) {
+            self::ASSET => Asset::query(),
+            self::PROJECT => Project::query(),
+            self::TASK => Task::query(),
+            self::PLAN => Plan::query(),
+        };
+    }
+
+    public function nameField(): string
+    {
+        return match ($this) {
+            self::ASSET, self::PROJECT, self::TASK  => "name",
+            self::PLAN => "title",
+        };
+    }
 }

+ 28 - 0
app/Models/Enums/ObjectAction.php

@@ -47,4 +47,32 @@ enum ObjectAction: string
     case CANCELED = "canceled";
 
     case ASSIGNED = "assigned";
+
+    case DELETED_FILE = "deletedFile";
+
+    case EDITED_FILE = "editedFile";
+
+    case HIDDEN = "hidden";
+
+    case COMMENTED = "commented";
+
+    case ACTIVATED = "activated";
+
+    case BLOCKED = "blocked";
+
+    case LINKED_TO_PLAN = "linkedToPlan";
+
+    case CHANGED_STATUS = "change status";
+
+    case VERIFIED = "verified";
+
+    case SUSPENDED = "suspended";
+
+    case LINK_CHILDREN_TASK = "linkChildrenTask";
+
+    case UNLINK_CHILDREN_TASK = "unlinkChildrenTask";
+
+    case BATCH_CREATE_TASK = "batchCreateTask";
+
+    case DELETE_CHILDREN_TASK = "deleteChildrenTask";
 }

+ 73 - 0
app/Repositories/ActionRepository.php

@@ -6,6 +6,8 @@ use App\Models\Action;
 use App\Models\Enums\ActionObjectType;
 use App\Models\Enums\ObjectAction;
 use App\Models\Project;
+use Carbon\Carbon;
+use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Auth;
 
 class ActionRepository
@@ -46,4 +48,75 @@ class ActionRepository
             $extraFields
         );
     }
+
+    public static function dynamic(Project $project, array $filter = [])
+    {
+        $actions = Action::query()->filter($filter)
+            ->where("project_id", $project->id)
+            ->with(['createdBy'])
+            ->selectRaw("*, date_format(created_at, '%Y-%m-%d') as created_date")
+            ->orderBy("created_at")
+            ->get();
+
+        $objectNames = self::objectNamesGroupByType($actions);
+
+        $items = $actions->groupBy("created_date")->toArray();
+        krsort($items);
+
+        $data = [];
+        foreach ($items as $day => $actionItems) {
+            $dayItems = [
+                'date' => $day,
+                'items' => []
+            ];
+
+            foreach ($actionItems as $actionItem) {
+                $labelKey = sprintf("action-labels.label.%s", $actionItem['action']);
+                $objectLabelKey = sprintf("action-labels.object_type.%s", $actionItem['object_type']);
+
+                $dayItems['items'][] = [
+                    'time' => Carbon::parse($actionItem['created_at'])->toTimeString(),
+                    'created_by' => [
+                        'id' => $actionItem['created_by']['id'],
+                        'name' => $actionItem['created_by']['name'],
+                        'username' => $actionItem['created_by']['username'],
+                    ],
+                    'action_label' => app('translator')->has($labelKey) ? __($labelKey) : $actionItem['action'],
+                    'object_label' => app('translator')->has($objectLabelKey) ? __($objectLabelKey) : $actionItem['object_type'],
+                    'object_id' => $actionItem['object_id'],
+                    'object_type' => $actionItem['object_type'],
+                    'object_name' => data_get($objectNames, sprintf("%s.%d", $actionItem['object_type'], $actionItem['object_id'])),
+                ];
+            }
+
+            $data[] = $dayItems;
+        }
+
+        return $data;
+    }
+
+    /**
+     * @param Collection $actions
+     * @return array
+     */
+    protected static function objectNamesGroupByType(Collection $actions): array
+    {
+        $groupActions = $actions->groupBy("object_type");
+
+        $objectNames = [];
+        foreach ($groupActions as $group => $items) {
+            $objectType = ActionObjectType::tryFrom($group);
+
+            $actionObjectBuilder= $objectType?->modelBuilder();
+            if (! $actionObjectBuilder) {
+                continue;
+            }
+
+            $objectNames[$group] = $actionObjectBuilder
+                ->whereIn("id", $items->pluck("object_id")->unique()->toArray())
+                ->pluck($objectType->nameField(), "id");
+        }
+
+        return $objectNames;
+    }
 }

+ 44 - 0
lang/en/action-labels.php

@@ -0,0 +1,44 @@
+<?php
+use \App\Models\Enums\ObjectAction;
+use \App\Models\Enums\ActionObjectType;
+
+return[
+    'object_type'=>[
+        ActionObjectType::PROJECT->value => "Project",
+        ActionObjectType::PLAN->value => "Plan",
+        ActionObjectType::TASK->value =>"Task",
+        ActionObjectType::ASSET->value =>"Asset",
+    ],
+    'label'=>[
+        ObjectAction::CREATED->value => "created",
+        ObjectAction::OPENED->value => "opened",
+        ObjectAction::CHANGED->value => "changed",
+        ObjectAction::EDITED->value => "edited",
+        ObjectAction::ASSIGNED->value => "assigned",
+        ObjectAction::CLOSED->value => "closed",
+        ObjectAction::DELETED->value => "deleted",
+        ObjectAction::DELETED_FILE->value => "deleted",
+        ObjectAction::EDITED_FILE->value => "edited",
+        ObjectAction::UNDELETED->value => "restored",
+        ObjectAction::HIDDEN->value => "restored",
+        ObjectAction::COMMENTED->value => "commented",
+        ObjectAction::ACTIVATED->value => "activated",
+        ObjectAction::BLOCKED->value => "blocked",
+        ObjectAction::REVIEWED->value => "reviewed",
+        ObjectAction::MOVED->value => "moved",
+        ObjectAction::LINKED_TO_PLAN->value => "linked to Plan",
+        ObjectAction::LINKED_TO_PLAN->value => "unlinked from",
+        ObjectAction::STARTED->value => "started",
+        ObjectAction::RESTARTED->value => "restarted",
+        ObjectAction::CHANGED_STATUS->value => "change status",
+        ObjectAction::CANCELED->value => "canceled",
+        ObjectAction::PAUSED->value => "paused",
+        ObjectAction::VERIFIED->value => "verified",
+        ObjectAction::DELAY->value => "delayed",
+        ObjectAction::SUSPENDED->value => "suspended",
+        ObjectAction::LINK_CHILDREN_TASK->value => "linked a child task",
+        ObjectAction::UNLINK_CHILDREN_TASK->value => "unlinked a child task",
+        ObjectAction::BATCH_CREATE_TASK->value => "batch created tasks",
+        ObjectAction::DELETE_CHILDREN_TASK->value => "delete children task",
+    ]
+];

+ 1 - 0
routes/api.php

@@ -44,6 +44,7 @@ Route::middleware(['auth:sanctum'])->group(function () {
         Route::patch("requirement/{plan_id}/plan", [API\RequirementController::class, "linkPlan"])->name("requirement.linkPlan");
         Route::patch("requirement/plan/unlink", [API\RequirementController::class, "unlinkPlan"])->name("requirement.unlinkPlan");
 
+        Route::get("project/{project}/dynamic", [API\ProjectController::class, "dynamic"])->name("project.dynamic");
         Route::patch("project/{project}/closed", [API\ProjectController::class, "closed"])->name("project.closed");
         Route::patch("project/{project}/start", [API\ProjectController::class, "start"])->name("project.start");
         Route::patch("project/{project}/pause", [API\ProjectController::class, "pause"])->name("project.pause");