diff --git a/Classes/Domain/Model/AbstractChange.php b/Classes/Domain/Model/AbstractChange.php index af92a52c74..b118c1168c 100644 --- a/Classes/Domain/Model/AbstractChange.php +++ b/Classes/Domain/Model/AbstractChange.php @@ -27,7 +27,7 @@ abstract class AbstractChange implements ChangeInterface { use NodeTypeWithFallbackProvider; - protected ?Node $subject; + protected ?Node $subject = null; #[Flow\Inject] protected ContentRepositoryRegistry $contentRepositoryRegistry; diff --git a/Classes/Domain/Model/Changes/AbstractCreate.php b/Classes/Domain/Model/Changes/AbstractCreate.php index 6ebae28193..c2278f8d3b 100644 --- a/Classes/Domain/Model/Changes/AbstractCreate.php +++ b/Classes/Domain/Model/Changes/AbstractCreate.php @@ -29,7 +29,7 @@ abstract class AbstractCreate extends AbstractStructuralChange /** * The type of the node that will be created */ - protected ?NodeTypeName $nodeTypeName; + protected ?NodeTypeName $nodeTypeName = null; /** * Incoming data from creationDialog diff --git a/Classes/Domain/Model/Changes/CopyInto.php b/Classes/Domain/Model/Changes/CopyInto.php index 56c4e55d5d..b0a37574d5 100644 --- a/Classes/Domain/Model/Changes/CopyInto.php +++ b/Classes/Domain/Model/Changes/CopyInto.php @@ -21,7 +21,7 @@ class CopyInto extends AbstractStructuralChange { protected ?string $parentContextPath; - protected ?Node $cachedParentNode; + protected ?Node $cachedParentNode = null; public function setParentContextPath(string $parentContextPath): void { diff --git a/Classes/Domain/Model/Feedback/Operations/ReloadContentOutOfBand.php b/Classes/Domain/Model/Feedback/Operations/ReloadContentOutOfBand.php index fc511798de..8b8b5b900b 100644 --- a/Classes/Domain/Model/Feedback/Operations/ReloadContentOutOfBand.php +++ b/Classes/Domain/Model/Feedback/Operations/ReloadContentOutOfBand.php @@ -23,12 +23,12 @@ use Neos\Neos\Ui\Domain\Model\AbstractFeedback; use Neos\Neos\Ui\Domain\Model\FeedbackInterface; use Neos\Neos\Ui\Domain\Model\RenderedNodeDomAddress; -use Neos\Neos\View\FusionView; +use Neos\Neos\Ui\View\OutOfBandRenderingViewFactory; use Psr\Http\Message\ResponseInterface; class ReloadContentOutOfBand extends AbstractFeedback { - protected ?Node $node; + protected ?Node $node = null; protected ?RenderedNodeDomAddress $nodeDomAddress; @@ -53,6 +53,9 @@ class ReloadContentOutOfBand extends AbstractFeedback #[Flow\Inject] protected RenderingModeService $renderingModeService; + #[Flow\Inject] + protected OutOfBandRenderingViewFactory $outOfBandRenderingViewFactory; + public function setNode(Node $node): void { $this->node = $node; @@ -137,14 +140,14 @@ protected function renderContent(ControllerContext $controllerContext): string|R if ($this->nodeDomAddress) { $renderingMode = $this->renderingModeService->findByCurrentUser(); - $fusionView = new FusionView(); - $fusionView->setControllerContext($controllerContext); - $fusionView->setOption('renderingModeName', $renderingMode->name); + $view = $this->outOfBandRenderingViewFactory->resolveView(); + $view->setControllerContext($controllerContext); + $view->setOption('renderingModeName', $renderingMode->name); - $fusionView->assign('value', $this->node); - $fusionView->setFusionPath($this->nodeDomAddress->getFusionPathForContentRendering()); + $view->assign('value', $this->node); + $view->setRenderingEntryPoint($this->nodeDomAddress->getFusionPathForContentRendering()); - return $fusionView->render(); + return $view->render(); } } diff --git a/Classes/Domain/Model/Feedback/Operations/ReloadDocument.php b/Classes/Domain/Model/Feedback/Operations/ReloadDocument.php index ee9651ee6b..3b8ee6a13b 100644 --- a/Classes/Domain/Model/Feedback/Operations/ReloadDocument.php +++ b/Classes/Domain/Model/Feedback/Operations/ReloadDocument.php @@ -23,7 +23,7 @@ class ReloadDocument extends AbstractFeedback { - protected ?Node $node; + protected ?Node $node = null; #[Flow\Inject] protected ContentRepositoryRegistry $contentRepositoryRegistry; diff --git a/Classes/Domain/Model/Feedback/Operations/RenderContentOutOfBand.php b/Classes/Domain/Model/Feedback/Operations/RenderContentOutOfBand.php index 409ad394e7..d5714f8641 100644 --- a/Classes/Domain/Model/Feedback/Operations/RenderContentOutOfBand.php +++ b/Classes/Domain/Model/Feedback/Operations/RenderContentOutOfBand.php @@ -1,5 +1,4 @@ node = $node; @@ -183,14 +189,14 @@ protected function renderContent(ControllerContext $controllerContext): string|R if ($parentDomAddress) { $renderingMode = $this->renderingModeService->findByCurrentUser(); - $fusionView = new FusionView(); - $fusionView->setControllerContext($controllerContext); - $fusionView->setOption('renderingModeName', $renderingMode->name); + $view = $this->outOfBandRenderingViewFactory->resolveView(); + $view->setControllerContext($controllerContext); + $view->setOption('renderingModeName', $renderingMode->name); - $fusionView->assign('value', $parentNode); - $fusionView->setFusionPath($parentDomAddress->getFusionPath()); + $view->assign('value', $parentNode); + $view->setRenderingEntryPoint($parentDomAddress->getFusionPath()); - return $fusionView->render(); + return $view->render(); } } diff --git a/Classes/Domain/Model/Feedback/Operations/UpdateNodeInfo.php b/Classes/Domain/Model/Feedback/Operations/UpdateNodeInfo.php index a5093bac59..27d363dec6 100644 --- a/Classes/Domain/Model/Feedback/Operations/UpdateNodeInfo.php +++ b/Classes/Domain/Model/Feedback/Operations/UpdateNodeInfo.php @@ -23,7 +23,7 @@ class UpdateNodeInfo extends AbstractFeedback { - protected ?Node $node; + protected ?Node $node = null; /** * @Flow\Inject @@ -113,7 +113,7 @@ public function serializePayload(ControllerContext $controllerContext): array * * @return array> */ - public function serializeNodeRecursively(Node $node, ControllerContext $controllerContext): array + private function serializeNodeRecursively(Node $node, ControllerContext $controllerContext): array { $contentRepository = $this->contentRepositoryRegistry->get($node->subgraphIdentity->contentRepositoryId); $nodeAddressFactory = NodeAddressFactory::create($contentRepository); diff --git a/Classes/Domain/Model/Feedback/Operations/UpdateWorkspaceInfo.php b/Classes/Domain/Model/Feedback/Operations/UpdateWorkspaceInfo.php index 86c190cc9e..2cdce7bb69 100644 --- a/Classes/Domain/Model/Feedback/Operations/UpdateWorkspaceInfo.php +++ b/Classes/Domain/Model/Feedback/Operations/UpdateWorkspaceInfo.php @@ -23,7 +23,7 @@ class UpdateWorkspaceInfo extends AbstractFeedback { - protected ?WorkspaceName $workspaceName; + protected ?WorkspaceName $workspaceName = null; /** * @Flow\Inject diff --git a/Classes/Domain/Model/FeedbackCollection.php b/Classes/Domain/Model/FeedbackCollection.php index 0857f1adbe..5f5a9dd9f7 100644 --- a/Classes/Domain/Model/FeedbackCollection.php +++ b/Classes/Domain/Model/FeedbackCollection.php @@ -48,8 +48,9 @@ public function setControllerContext(ControllerContext $controllerContext) */ public function add(FeedbackInterface $feedback) { - foreach ($this->feedbacks as $value) { - if ($value->isSimilarTo($feedback)) { + foreach ($this->feedbacks as $i => $value) { + if ($feedback->isSimilarTo($value)) { + $this->feedbacks[$i] = $feedback; return; } } diff --git a/Classes/View/OutOfBandRenderingCapable.php b/Classes/View/OutOfBandRenderingCapable.php new file mode 100644 index 0000000000..31cb7a5809 --- /dev/null +++ b/Classes/View/OutOfBandRenderingCapable.php @@ -0,0 +1,30 @@ +setFusionPath($renderingEntryPoint); + } +} diff --git a/Classes/View/OutOfBandRenderingViewFactory.php b/Classes/View/OutOfBandRenderingViewFactory.php new file mode 100644 index 0000000000..23f0620dc4 --- /dev/null +++ b/Classes/View/OutOfBandRenderingViewFactory.php @@ -0,0 +1,54 @@ +viewObjectName)) { + throw new \DomainException( + 'Declared view for out of band rendering (' . $this->viewObjectName . ') does not exist', + 1697821296 + ); + } + $view = new $this->viewObjectName(); + if (!$view instanceof AbstractView) { + throw new \DomainException( + 'Declared view (' . $this->viewObjectName . ') does not implement ' . AbstractView::class + . ' required for out-of-band rendering', + 1697821429 + ); + } + if (!$view instanceof OutOfBandRenderingCapable) { + throw new \DomainException( + 'Declared view (' . $this->viewObjectName . ') does not implement ' . OutOfBandRenderingCapable::class + . ' required for out-of-band rendering', + 1697821364 + ); + } + + return $view; + } +} diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index 92de6e127f..a5aa25d1cf 100644 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -176,7 +176,6 @@ Neos: preferences: interfaceLanguage: '${q(user).property(''preferences.interfaceLanguage'') || Configuration.setting(''Neos.Neos.userInterface.defaultLanguage'')}' settings: - isAutoPublishingEnabled: false targetWorkspace: 'live' changes: types: @@ -191,6 +190,8 @@ Neos: 'Neos.Neos.Ui:MoveBefore': Neos\Neos\Ui\Domain\Model\Changes\MoveBefore 'Neos.Neos.Ui:MoveAfter': Neos\Neos\Ui\Domain\Model\Changes\MoveAfter 'Neos.Neos.Ui:MoveInto': Neos\Neos\Ui\Domain\Model\Changes\MoveInto + outOfBandRendering: + viewObjectName: 'Neos\Neos\Ui\View\OutOfBandRenderingFusionView' Flow: security: authentication: diff --git a/Resources/Private/Fusion/Prototypes/Shortcut.fusion b/Resources/Private/Fusion/Prototypes/Shortcut.fusion deleted file mode 100644 index 23d36fe282..0000000000 --- a/Resources/Private/Fusion/Prototypes/Shortcut.fusion +++ /dev/null @@ -1,17 +0,0 @@ -prototype(Neos.Neos:Page) { - head { - shortcutCSS = Neos.Fusion:Tag { - @position = 'after guestFrameApplication' - - tagName = 'style' - content = Neos.Fusion:Value { - value = '#neos-shortcut {position: fixed;top: 0;left: 0;width: 100%;height: 100%;background-color: #323232;z-index: 9999;font-family: "Noto Sans", sans-serif;-webkit-font-smoothing: antialiased;}#neos-shortcut p {position: relative;margin: 0 auto;width: 500px;height: 60px;top: 50%;margin-top: -30px;color: #fff;font-size: 22px;line-height: 1.4;text-align: center;}#neos-shortcut p a {color: #00b5ff;text-decoration: none;}#neos-shortcut p a:hover {color: #39c6ff;}' - } - - @if { - inBackend = ${renderingMode.isEdit || renderingMode.isPreview} - isShortcut = ${q(node).is('[instanceof Neos.Neos:Shortcut]')} - } - } - } -} diff --git a/packages/neos-ui-redux-store/src/User/Settings/index.spec.js b/packages/neos-ui-redux-store/src/User/Settings/index.spec.js deleted file mode 100644 index a942bbc090..0000000000 --- a/packages/neos-ui-redux-store/src/User/Settings/index.spec.js +++ /dev/null @@ -1,53 +0,0 @@ -import {actionTypes, actions, reducer, defaultState} from './index'; -import {actionTypes as system} from '../../System/index'; - -test(`should export actionTypes`, () => { - expect(actionTypes).not.toBe(undefined); - expect(typeof (actionTypes.TOGGLE_AUTO_PUBLISHING)).toBe('string'); -}); - -test(`should export action creators`, () => { - expect(actions).not.toBe(undefined); - expect(typeof (actions.toggleAutoPublishing)).toBe('function'); -}); - -test(`should export a reducer`, () => { - expect(reducer).not.toBe(undefined); - expect(typeof (reducer)).toBe('function'); -}); - -test(`The reducer should return the default state when called with undefined.`, () => { - const nextState = reducer(undefined, { - type: 'unknown' - }); - - expect(nextState).toBe(defaultState); -}); - -test(`The reducer should correctly rehydrate data on INIT.`, () => { - const initValues = { - isAutoPublishingEnabled: true - }; - const nextState = reducer(undefined, { - type: system.INIT, - payload: { - user: { - settings: initValues - } - } - }); - expect(nextState).toEqual(initValues); -}); - -test(` - The "toggle" action should be able to reverse the value of the - "isAutoPublishingEnabled" key.`, () => { - const state = { - isAutoPublishingEnabled: false - }; - const nextState1 = reducer(state, actions.toggleAutoPublishing()); - const nextState2 = reducer(nextState1, actions.toggleAutoPublishing()); - - expect(nextState1.isAutoPublishingEnabled).toBe(true); - expect(nextState2.isAutoPublishingEnabled).toBe(false); -}); diff --git a/packages/neos-ui-redux-store/src/User/Settings/index.ts b/packages/neos-ui-redux-store/src/User/Settings/index.ts deleted file mode 100644 index 29cb79f778..0000000000 --- a/packages/neos-ui-redux-store/src/User/Settings/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -import produce from 'immer'; -import {action as createAction, ActionType} from 'typesafe-actions'; - -import {actionTypes as system, InitAction} from '../../System'; - -// -// Export the subreducer state shape interface -// -export interface State extends Readonly<{ - isAutoPublishingEnabled: boolean; -}> {} - -export const defaultState: State = { - isAutoPublishingEnabled: false -}; - -// -// Export the action types -// -export enum actionTypes { - TOGGLE_AUTO_PUBLISHING = '@neos/neos-ui/User/Settings/TOGGLE_AUTO_PUBLISHING' -} - -// -// Export the actions -// -export const actions = { - /** - * Toggles the auto publishing mode for the current logged in user. - */ - toggleAutoPublishing: () => createAction(actionTypes.TOGGLE_AUTO_PUBLISHING) -}; - -// -// Export the union type of all actions -// -export type Action = ActionType; - -// -// Export the reducer -// -export const reducer = (state: State = defaultState, action: Action | InitAction) => produce(state, draft => { - switch (action.type) { - case system.INIT: - draft.isAutoPublishingEnabled = action.payload.user.settings.isAutoPublishingEnabled; - break; - case actionTypes.TOGGLE_AUTO_PUBLISHING: - draft.isAutoPublishingEnabled = !state.isAutoPublishingEnabled; - break; - } -}); - -// -// Export the selectors -// -export const selectors = {}; diff --git a/packages/neos-ui-redux-store/src/User/index.ts b/packages/neos-ui-redux-store/src/User/index.ts index 46b794a61f..fbe1d17a3c 100644 --- a/packages/neos-ui-redux-store/src/User/index.ts +++ b/packages/neos-ui-redux-store/src/User/index.ts @@ -1,17 +1,15 @@ import {combineReducers} from '../combineReducers'; -import * as Settings from './Settings'; import * as Preferences from './Preferences'; import * as Name from './Name'; import * as Impersonate from './Impersonate'; -const all = {Settings, Preferences, Name, Impersonate}; +const all = {Preferences, Name, Impersonate}; // // Export the subreducer state shape interface // export interface State { - settings: Settings.State; preferences: Preferences.State; name: Name.State; impersonate: Impersonate.State; @@ -35,7 +33,6 @@ export const actions = typedKeys(all).reduce((acc, cur) => ({...acc, [cur]: all[ // Export the reducer // export const reducer = combineReducers({ - settings: Settings.reducer, preferences: Preferences.reducer, name: Name.reducer, impersonate: Impersonate.reducer diff --git a/packages/neos-ui-sagas/src/Changes/index.js b/packages/neos-ui-sagas/src/Changes/index.js index 5bff7889d8..f0df377dfa 100644 --- a/packages/neos-ui-sagas/src/Changes/index.js +++ b/packages/neos-ui-sagas/src/Changes/index.js @@ -1,11 +1,9 @@ import {takeEvery, put, call, select} from 'redux-saga/effects'; import {$get} from 'plow-js'; -import {actionTypes, actions, selectors} from '@neos-project/neos-ui-redux-store'; +import {actionTypes, actions} from '@neos-project/neos-ui-redux-store'; import backend from '@neos-project/neos-ui-backend-connector'; -const {publishableNodesInDocumentSelector, baseWorkspaceSelector} = selectors.CR.Workspaces; - function * persistChanges(changes) { const {change} = backend.get().endpoints; @@ -14,15 +12,6 @@ function * persistChanges(changes) { try { const feedback = yield call(change, changes); yield put(actions.ServerFeedback.handleServerFeedback(feedback)); - - const state = yield select(); - const isAutoPublishingEnabled = $get('user.settings.isAutoPublishingEnabled', state); - - if (isAutoPublishingEnabled) { - const baseWorkspace = baseWorkspaceSelector(state); - const publishableNodesInDocument = publishableNodesInDocumentSelector(state); - yield put(actions.CR.Workspaces.publish(publishableNodesInDocument.map($get('contextPath')), baseWorkspace)); - } } catch (error) { console.error('Failed to persist changes', error); } finally { diff --git a/packages/neos-ui-sagas/src/Publish/index.js b/packages/neos-ui-sagas/src/Publish/index.js index 6822c2d301..e8a650d86e 100644 --- a/packages/neos-ui-sagas/src/Publish/index.js +++ b/packages/neos-ui-sagas/src/Publish/index.js @@ -5,8 +5,6 @@ import {actionTypes, actions, selectors} from '@neos-project/neos-ui-redux-store import backend from '@neos-project/neos-ui-backend-connector'; import {getGuestFrameDocument} from '@neos-project/neos-ui-guest-frame/src/dom'; -const {publishableNodesInDocumentSelector} = selectors.CR.Workspaces; - export function * watchPublish() { const {publish} = backend.get().endpoints; @@ -27,18 +25,6 @@ export function * watchPublish() { }); } -export function * watchToggleAutoPublish() { - yield takeEvery(actionTypes.User.Settings.TOGGLE_AUTO_PUBLISHING, function * publishInitially() { - const state = yield select(); - const isAutoPublishingEnabled = $get('user.settings.isAutoPublishingEnabled', state); - - if (isAutoPublishingEnabled) { - const publishableNodesInDocument = publishableNodesInDocumentSelector(state); - yield put(actions.CR.Workspaces.publish(publishableNodesInDocument.map($get('contextPath')), 'live')); - } - }); -} - export function * watchChangeBaseWorkspace() { const {changeBaseWorkspace} = backend.get().endpoints; yield takeEvery(actionTypes.CR.Workspaces.CHANGE_BASE_WORKSPACE, function * change(action) { diff --git a/packages/neos-ui-sagas/src/manifest.js b/packages/neos-ui-sagas/src/manifest.js index 6c88de7dfc..55cdfa564c 100644 --- a/packages/neos-ui-sagas/src/manifest.js +++ b/packages/neos-ui-sagas/src/manifest.js @@ -51,7 +51,6 @@ manifest('main.sagas', {}, globalRegistry => { sagasRegistry.set('neos-ui/Publish/watchChangeBaseWorkspace', {saga: publish.watchChangeBaseWorkspace}); sagasRegistry.set('neos-ui/Publish/discardIfConfirmed', {saga: publish.discardIfConfirmed}); sagasRegistry.set('neos-ui/Publish/watchPublish', {saga: publish.watchPublish}); - sagasRegistry.set('neos-ui/Publish/watchToggleAutoPublish', {saga: publish.watchToggleAutoPublish}); sagasRegistry.set('neos-ui/ServerFeedback/watchServerFeedback', {saga: serverFeedback.watchServerFeedback}); diff --git a/packages/neos-ui/src/Containers/PrimaryToolbar/PublishDropDown/index.js b/packages/neos-ui/src/Containers/PrimaryToolbar/PublishDropDown/index.js index aa39151dcc..c37151c371 100644 --- a/packages/neos-ui/src/Containers/PrimaryToolbar/PublishDropDown/index.js +++ b/packages/neos-ui/src/Containers/PrimaryToolbar/PublishDropDown/index.js @@ -7,8 +7,6 @@ import {$transform, $get} from 'plow-js'; import Badge from '@neos-project/react-ui-components/src/Badge/'; import Icon from '@neos-project/react-ui-components/src/Icon/'; -import CheckBox from '@neos-project/react-ui-components/src/CheckBox/'; -import Label from '@neos-project/react-ui-components/src/Label/'; import DropDown from '@neos-project/react-ui-components/src/DropDown/'; import I18n from '@neos-project/neos-ui-i18n'; @@ -29,10 +27,8 @@ import style from './style.module.css'; publishableNodesInDocument: publishableNodesInDocumentSelector, personalWorkspaceName: personalWorkspaceNameSelector, baseWorkspace: baseWorkspaceSelector, - isWorkspaceReadOnly: isWorkspaceReadOnlySelector, - isAutoPublishingEnabled: $get('user.settings.isAutoPublishingEnabled') + isWorkspaceReadOnly: isWorkspaceReadOnlySelector }), { - toggleAutoPublishing: actions.User.Settings.toggleAutoPublishing, changeBaseWorkspaceAction: actions.CR.Workspaces.changeBaseWorkspace, publishAction: actions.CR.Workspaces.publish, discardAction: actions.CR.Workspaces.commenceDiscard @@ -52,8 +48,6 @@ export default class PublishDropDown extends PureComponent { personalWorkspaceName: PropTypes.string.isRequired, baseWorkspace: PropTypes.string.isRequired, neos: PropTypes.object.isRequired, - isAutoPublishingEnabled: PropTypes.bool, - toggleAutoPublishing: PropTypes.func.isRequired, publishAction: PropTypes.func.isRequired, discardAction: PropTypes.func.isRequired, changeBaseWorkspaceAction: PropTypes.func.isRequired, @@ -92,9 +86,7 @@ export default class PublishDropDown extends PureComponent { isSaving, isPublishing, isDiscarding, - isAutoPublishingEnabled, isWorkspaceReadOnly, - toggleAutoPublishing, baseWorkspace, changeBaseWorkspaceAction, i18nRegistry, @@ -107,10 +99,6 @@ export default class PublishDropDown extends PureComponent { const canPublishLocally = !isSaving && !isPublishing && !isDiscarding && publishableNodesInDocument && (publishableNodesInDocument.length > 0); const canPublishGlobally = !isSaving && !isPublishing && !isDiscarding && publishableNodes && (publishableNodes.length > 0); const changingWorkspaceAllowed = !canPublishGlobally; - const autoPublishWrapperClassNames = mergeClassNames({ - [style.dropDown__item]: true, - [style['dropDown__item--noHover']]: true - }); const mainButton = this.getTranslatedMainButton(baseWorkspaceTitle); const dropDownBtnClassName = mergeClassNames({ [style.dropDown__btn]: true, @@ -213,27 +201,6 @@ export default class PublishDropDown extends PureComponent { )} -
  • - { - /** - PLEASE NOTE: this additional styleClass is a fix, because react checkboxes inside a react select component are buggy, - for further information see https://github.com/neos/neos-ui/pull/3211 - */ - } - -
  • @@ -253,8 +220,7 @@ export default class PublishDropDown extends PureComponent { publishableNodesInDocument, isSaving, isPublishing, - isDiscarding, - isAutoPublishingEnabled + isDiscarding } = this.props; const canPublishLocally = publishableNodesInDocument && (publishableNodesInDocument.length > 0); @@ -270,13 +236,6 @@ export default class PublishDropDown extends PureComponent { return 'Discarding...'; } - if (isAutoPublishingEnabled) { - if (baseWorkspaceTitle) { - return ; - } - return ; - } - if (canPublishLocally) { return ; }