user()->currentWorkspace; $automations = Inertia::scroll(fn () => AutomationResource::collection( $list($workspace) )); return Inertia::render('automations/Index', [ 'automations' => $automations, ]); } public function store(StoreAutomationRequest $request, CreateAutomation $create): RedirectResponse { $automation = $create( $request->user()->currentWorkspace, $request->user(), ); return redirect()->route('app.automations.workflow', $automation->id); } public function show(Automation $automation): RedirectResponse { return redirect()->route('app.automations.workflow', $automation->id); } public function workflow(Automation $automation, GetAutomationEditorData $editorData): Response { $this->authorize('update', $automation); ['socialAccounts' => $socialAccounts, 'pinterestBoards' => $pinterestBoards, 'tiktokCreatorInfos' => $tiktokCreatorInfos] = $editorData($automation); $platformConfigs = $socialAccounts->mapWithKeys(fn ($account) => [ $account->id => new PlatformConfigResource($account), ]); return Inertia::render('automations/Form', [ 'automation' => AutomationResource::make($automation), 'socialAccounts' => SocialAccountResource::collection($socialAccounts), 'platformConfigs' => $platformConfigs, 'pinterestBoards' => $pinterestBoards, 'tiktokCreatorInfos' => $tiktokCreatorInfos, ]); } public function invocations(Automation $automation, GetAutomationInvocations $invocations): Response { $this->authorize('view', $automation); $status = request()->string('status')->toString() ?: null; $search = request()->string('search')->toString() ?: null; return Inertia::render('automations/Invocations', [ 'automation' => AutomationResource::make($automation), 'invocations' => Inertia::scroll(fn () => AutomationInvocationResource::collection( $invocations($automation, $status, $search) )), 'filters' => [ 'status' => $status, 'search' => $search, ], ]); } public function settings(Automation $automation): Response { $this->authorize('view', $automation); return Inertia::render('automations/Settings', [ 'automation' => AutomationResource::make($automation), ]); } public function metrics(Automation $automation, GetAutomationMetrics $metrics): Response { $this->authorize('view', $automation); $end = (request()->date('end') ?? now())->startOfDay(); $start = (request()->date('start') ?? now()->subDays(6))->startOfDay(); if ($start->greaterThan($end)) { [$start, $end] = [$end, $start]; } // Cap the window so a hand-edited URL can't request a multi-year, daily // bucketed series. if ($start->diffInDays($end) > 366) { $start = $end->copy()->subDays(366); } return Inertia::render('automations/Metrics', [ 'automation' => AutomationResource::make($automation), 'metrics' => $metrics($automation, $start, $end), 'filters' => [ 'start' => $start->toDateString(), 'end' => $end->toDateString(), ], ]); } public function update(UpdateAutomationRequest $request, Automation $automation, UpdateAutomation $update): RedirectResponse { $this->authorize('update', $automation); $update($automation, $request->validated()); return back(); } public function destroy(Automation $automation, DeleteAutomation $delete): RedirectResponse { $this->authorize('delete', $automation); $delete($automation); session()->flash('flash.banner', __('automations.flash.deleted')); session()->flash('flash.bannerStyle', 'success'); return redirect()->route('app.automations.index'); } public function activate(ActivateAutomationRequest $request, Automation $automation, ActivateAutomation $activate): RedirectResponse { $this->authorize('activate', $automation); $activate($automation); return back(); } public function pause(PauseAutomationRequest $request, Automation $automation, PauseAutomation $pause): RedirectResponse { $this->authorize('pause', $automation); $pause($automation); return back(); } public function retryRun( RetryRunRequest $request, RetryRunFromNode $retry, Automation $automation, AutomationRun $run, ): \Illuminate\Http\Response { $this->authorize('update', $automation); abort_unless($run->automation_id === $automation->id, 404); $nodeId = $request->validated('node_id') ?? $run->current_node_id; $retry($run, $nodeId); return response()->noContent(); } public function test(TestAutomationRequest $request, Automation $automation, TestAutomation $test): JsonResponse { $this->authorize('update', $automation); $run = $test($automation, (bool) $request->validated('with_real_data', false)); return response()->json(['run_id' => $run->id]); } public function showRun(Automation $automation, AutomationRun $run): JsonResponse { $this->authorize('view', $automation); abort_unless($run->automation_id === $automation->id, 404); // Aggregate the node runs of every branch forked by a fan-out so the test // panel shows the whole execution, not just the branch the root walked. $rootId = $run->rootId(); $nodeRuns = AutomationNodeRun::query() ->whereHas('run', fn ($query) => $query ->where('id', $rootId) ->orWhere('root_run_id', $rootId)) ->orderBy('started_at') ->orderBy('id') ->get(); return response()->json([ 'run' => AutomationRunResource::make($run)->resolve(), 'node_runs' => AutomationNodeRunResource::collection($nodeRuns)->resolve(), ]); } }