projectPermissionService->userCanManageProjectAccess($request->user(), $project), 403, ); return Inertia::render('projects/settings/Board', [ 'boardColumns' => $project->boardColumns()->get(), 'project' => $project, 'status' => session('status'), ]); } public function store( StoreBoardColumnRequest $request, Project $project, ): RedirectResponse { abort_unless( $this->projectPermissionService->userCanManageProjectAccess($request->user(), $project), 403, ); $desiredPosition = $request->position() ?? $project->boardColumns()->count() + 1; $boardColumn = DB::transaction(function () use ($project, $request, $desiredPosition): BoardColumn { $boardColumn = $project->boardColumns()->create([ 'name' => $request->validated('name'), 'position' => $project->boardColumns()->count() + 1, ]); $this->reorderColumns($project, $boardColumn, $desiredPosition); return $boardColumn; }); return to_route('projects.settings.board', $project) ->with('status', "{$boardColumn->name} was added to the board workflow."); } public function update( UpdateBoardColumnRequest $request, Project $project, BoardColumn $boardColumn, ): RedirectResponse { abort_unless( $this->projectPermissionService->userCanManageProjectAccess($request->user(), $project), 403, ); DB::transaction(function () use ($boardColumn, $project, $request): void { $boardColumn->update([ 'name' => $request->validated('name'), ]); $this->reorderColumns($project, $boardColumn, $request->position()); }); return to_route('projects.settings.board', $project) ->with('status', "{$boardColumn->fresh()->name} was updated."); } public function destroy( Request $request, Project $project, BoardColumn $boardColumn, ): RedirectResponse { abort_unless( $this->projectPermissionService->userCanManageProjectAccess($request->user(), $project), 403, ); $deletedName = $boardColumn->name; DB::transaction(function () use ($boardColumn, $project): void { $boardColumn->delete(); $this->normalizeColumnPositions($project); }); return to_route('projects.settings.board', $project) ->with('status', "{$deletedName} was removed from the board workflow."); } private function normalizeColumnPositions(Project $project): void { $this->persistOrderedColumns( $project->boardColumns() ->get() ->values(), ); } private function reorderColumns(Project $project, BoardColumn $movingColumn, int $desiredPosition): void { /** @var Collection $columns */ $columns = $project->boardColumns() ->whereKeyNot($movingColumn->id) ->get() ->values(); $insertAt = max(0, min($desiredPosition - 1, $columns->count())); $columns->splice($insertAt, 0, [$movingColumn]); $this->persistOrderedColumns($columns->values()); } /** * @param Collection $columns */ private function persistOrderedColumns(Collection $columns): void { $temporaryOffset = ((int) $columns->max('position')) + $columns->count() + 1; $columns->each(function (BoardColumn $column, int $index) use ($temporaryOffset): void { $column->forceFill([ 'position' => $temporaryOffset + $index, ])->saveQuietly(); }); $columns->each(function (BoardColumn $column, int $index): void { $column->forceFill([ 'position' => $index + 1, ])->saveQuietly(); }); } }