diff --git a/Neos.Workspace.Ui/Classes/Controller/WorkspaceController.php b/Neos.Workspace.Ui/Classes/Controller/WorkspaceController.php index e9fe075ddb0..67edb6cf91a 100644 --- a/Neos.Workspace.Ui/Classes/Controller/WorkspaceController.php +++ b/Neos.Workspace.Ui/Classes/Controller/WorkspaceController.php @@ -46,7 +46,6 @@ use Neos\Flow\I18n\Exception\InvalidFormatPlaceholderException; use Neos\Flow\Mvc\ActionRequest; use Neos\Flow\Mvc\Exception\StopActionException; -use Neos\Flow\Mvc\View\ViewInterface; use Neos\Flow\Package\PackageManager; use Neos\Flow\Property\PropertyMapper; use Neos\Flow\Security\Account; @@ -107,18 +106,6 @@ class WorkspaceController extends AbstractModuleController #[Flow\Inject] protected WorkspaceProvider $workspaceProvider; - protected function initializeView(ViewInterface $view): void - { - parent::initializeView($view); - // If we're in a HTMX-request... - if ($this->request->getHttpRequest()->hasHeader('HX-Request')) { - // We append an "/htmx" segment to the fusion path, changing it from "//" to "///htmx" - $htmxFusionPath = str_replace(['\\Controller\\', '\\'], ['\\', '/'], $this->request->getControllerObjectName()); - $htmxFusionPath .= '/' . $this->request->getControllerActionName() . '/htmx'; - $view->setOption('fusionPath', $htmxFusionPath); - } - } - /** * Display a list of unpublished content */ @@ -383,11 +370,11 @@ public function deleteAction(WorkspaceName $workspaceName): void '', Message::SEVERITY_ERROR ); - $this->redirect('index'); + $this->throwStatus(404, 'Workspace does not exist'); } if ($workspace->isPersonalWorkspace()) { - $this->redirect('index'); + $this->throwStatus(403, 'Personal workspaces cannot be deleted'); } $dependentWorkspaces = $contentRepository->getWorkspaceFinder() @@ -408,7 +395,7 @@ public function deleteAction(WorkspaceName $workspaceName): void 'Neos.Workspace.Ui' ) ?: 'workspaces.workspaceCannotBeDeletedBecauseOfDependencies'; $this->addFlashMessage($message, '', Message::SEVERITY_WARNING); - $this->redirect('index'); + $this->throwStatus(403, 'Workspace has dependencies'); } $nodesCount = 0; @@ -428,7 +415,7 @@ public function deleteAction(WorkspaceName $workspaceName): void 'Neos.Workspace.Ui' ) ?: 'workspaces.notDeletedErrorWhileFetchingUnpublishedNodes'; $this->addFlashMessage($message, '', Message::SEVERITY_WARNING); - $this->redirect('index'); + $this->throwStatus(500, 'Error while fetching unpublished nodes'); } if ($nodesCount > 0) { $message = $this->translator->translateById( @@ -440,7 +427,7 @@ public function deleteAction(WorkspaceName $workspaceName): void 'Neos.Workspace.Ui' ) ?: 'workspaces.workspaceCannotBeDeletedBecauseOfUnpublishedNodes'; $this->addFlashMessage($message, '', Message::SEVERITY_WARNING); - $this->redirect('index'); + $this->throwStatus(403, 'Workspace has unpublished nodes'); } $contentRepository->handle( @@ -457,7 +444,6 @@ public function deleteAction(WorkspaceName $workspaceName): void 'Main', 'Neos.Workspace.Ui' ) ?: 'workspaces.workspaceHasBeenRemoved'); - $this->redirect('index'); } /** diff --git a/Neos.Workspace.Ui/Classes/Mvc/HtmxRequestPattern.php b/Neos.Workspace.Ui/Classes/Mvc/HtmxRequestPattern.php new file mode 100644 index 00000000000..04b190f90e6 --- /dev/null +++ b/Neos.Workspace.Ui/Classes/Mvc/HtmxRequestPattern.php @@ -0,0 +1,26 @@ +getFormat() === 'htmx'; + } +} diff --git a/Neos.Workspace.Ui/Classes/Mvc/HttpHeaderFlashMessageStorage.php b/Neos.Workspace.Ui/Classes/Mvc/HttpHeaderFlashMessageStorage.php new file mode 100644 index 00000000000..715dfe1d738 --- /dev/null +++ b/Neos.Workspace.Ui/Classes/Mvc/HttpHeaderFlashMessageStorage.php @@ -0,0 +1,48 @@ +flashMessageContainer === null) { + $this->flashMessageContainer = new FlashMessageContainer(); + } + return $this->flashMessageContainer; + } + + public function persist(HttpResponseInterface $response): HttpResponseInterface + { + $messages = array_map(static fn(Message $message) => [ + 'title' => $message->getTitle(), + 'message' => $message->render(), + 'severity' => $message->getSeverity(), + 'code' => $message->getCode(), + ], $this->flashMessageContainer?->getMessagesAndFlush() ?? []); + if ($messages === []) { + return $response; + } + return $response->withAddedHeader('X-Flow-FlashMessages', json_encode($messages, JSON_THROW_ON_ERROR)); + } +} diff --git a/Neos.Workspace.Ui/Configuration/Settings.Flow.yaml b/Neos.Workspace.Ui/Configuration/Settings.Flow.yaml new file mode 100644 index 00000000000..91a652d7d24 --- /dev/null +++ b/Neos.Workspace.Ui/Configuration/Settings.Flow.yaml @@ -0,0 +1,10 @@ +Neos: + Flow: + mvc: + flashMessages: + containers: + 'httpHeaderFlashMessages': + storage: 'Neos\Workspace\Ui\Mvc\HttpHeaderFlashMessageStorage' + requestPatterns: + 'htmx': + pattern: 'Neos\Workspace\Ui\Mvc\HtmxRequestPattern' diff --git a/Neos.Workspace.Ui/Resources/Private/Fusion/Components/Modals/Delete.fusion b/Neos.Workspace.Ui/Resources/Private/Fusion/Components/Modals/Delete.fusion index ec24966b130..da5fe1abebb 100644 --- a/Neos.Workspace.Ui/Resources/Private/Fusion/Components/Modals/Delete.fusion +++ b/Neos.Workspace.Ui/Resources/Private/Fusion/Components/Modals/Delete.fusion @@ -36,7 +36,7 @@ prototype(Neos.Workspace.Ui:Component.Modal.Delete) < prototype(Neos.Fusion:Comp form.target.action="delete" form.target.format="htmx" form.target.arguments.workspaceName={props.workspaceName} - class="neos-inline" + attributes.class="neos-inline" attributes.hx-post={form.getTarget()} attributes.hx-target="closest tr" attributes.hx-swap="delete" diff --git a/Neos.Workspace.Ui/Resources/Private/Fusion/Views/Delete.fusion b/Neos.Workspace.Ui/Resources/Private/Fusion/Views/Delete.fusion new file mode 100644 index 00000000000..b7fbf345050 --- /dev/null +++ b/Neos.Workspace.Ui/Resources/Private/Fusion/Views/Delete.fusion @@ -0,0 +1,4 @@ +## +# Empty template for the delete response as the payload is contained in the HTTP headers +# +Neos.Workspace.Ui.WorkspaceController.delete.htmx = '' diff --git a/Neos.Workspace.Ui/Resources/Private/Fusion/Views/Index.htmx.fusion b/Neos.Workspace.Ui/Resources/Private/Fusion/Views/Index.htmx.fusion deleted file mode 100644 index c8734844947..00000000000 --- a/Neos.Workspace.Ui/Resources/Private/Fusion/Views/Index.htmx.fusion +++ /dev/null @@ -1,7 +0,0 @@ -Neos.Workspace.Ui.WorkspaceController.index.htmx = Neos.Fusion:Component { - flashMessages = ${flashMessages} - - renderer = afx` - - ` -}