entityType, $this->action); } public function broadcastWith(): array { // TODO: [ ] optimize loaded changes - payload too big $model = match (true) { $this->model instanceof Project && $this->entityType === 'gantt' => $this ->model ->setPermissionsUser(User::query()->find($this->userId)) ->load([ 'tasks' => fn(HasMany $queue) => $queue ->orderBy('start_date') ->select([ 'id', 'task_name', 'priority_id', 'status_id', 'estimate', 'start_date', 'due_date', 'project_phase_id', 'project_id' ])->with(['status', 'priority']) ->withSum(['workers as total_spent_time'], 'duration') ->withSum(['workers as total_offset'], 'offset') ->withCasts(['start_date' => 'string', 'due_date' => 'string']) ->whereNotNull('start_date')->whereNotNull('due_date'), 'phases' => fn(HasMany $queue) => $queue ->select(['id', 'name', 'project_id']) ->withMin([ 'tasks as start_date' => fn(AdjacencyListBuilder $q) => $q ->whereNotNull('start_date') ->whereNotNull('due_date') ], 'start_date') ->withMax([ 'tasks as due_date' => fn(AdjacencyListBuilder $q) => $q ->whereNotNull('start_date') ->whereNotNull('due_date') ], 'due_date'), ]) ->append('tasks_relations'), $this->model instanceof Task => $this->model->setPermissionsUser(User::query()->find($this->userId)) ->load([ 'priority', 'project', 'users', 'status', 'parents', 'children', 'phase:id,name', 'workers', 'workers.user:id,full_name', 'attachmentsRelation', 'attachmentsRelation.user:id,full_name', ]) ->append(['can']) ->loadSum('workers as total_spent_time', 'duration') ->loadSum('workers as total_offset', 'offset') ->makeVisible('can'), $this->model instanceof TaskComment => $this->model ->load( 'user', 'attachmentsRelation', 'attachmentsRelation.user:id,full_name' ), $this->model instanceof Project => $this->model->setPermissionsUser(User::query()->find($this->userId)) ->load([ 'users', 'defaultPriority', 'statuses', 'workers', 'workers.user:id,full_name', 'workers.task:id,task_name', 'phases' => fn($q) => $q->withCount('tasks'), 'group', ]) ->loadCount('tasks') ->append(['can']) ->loadSum('workers as total_spent_time', 'duration') ->loadSum('workers as total_offset', 'offset') ->makeVisible('can'), // Format a time interval as in the dashboard report $this->model instanceof TimeInterval => DashboardExport::init( [$this->model->user_id], [$this->model->task->project_id], Carbon::parse($this->model->start_at)->startOfDay(), Carbon::parse($this->model->end_at)->endOfDay(), Settings::scope('core')->get('timezone', 'UTC'), $this->model->user->timezone ?? Settings::scope('core')->get('timezone', 'UTC'), )->collection(['time_intervals.id' => $this->model->id])->first()->first()->toArray(), default => $this->model, }; return ['model' => $model]; } /** @return Channel[] */ public function broadcastOn(): array { return [new PrivateChannel(sprintf('%s.%s', $this->entityType, $this->userId))]; } /** * @param Task|Project|TimeInterval $model * @return int[] */ public static function getRelatedUserIds($model): array { $userRelation = match (true) { $model instanceof Task => 'tasks', $model instanceof Project => 'projects', $model instanceof TimeInterval => 'timeIntervals', default => null, }; $query = User::query()->where('role_id', Role::ADMIN->value)->orWhere('role_id', Role::MANAGER->value); if (isset($userRelation)) { $query = $query->orWhereHas($userRelation, fn(Builder $builder) => $builder->where('id', $model->id)); } return $query->pluck('id')->toArray(); } }