diff --git a/packages/neos-ui-error/package.json b/packages/neos-ui-error/package.json index 38151c7642..20ce5842d7 100644 --- a/packages/neos-ui-error/package.json +++ b/packages/neos-ui-error/package.json @@ -5,12 +5,12 @@ "private": true, "main": "./src/index.ts", "dependencies": { + "@neos-project/framework-observable": "workspace:*", + "@neos-project/framework-observable-react": "workspace:*", "@neos-project/neos-ui-i18n": "workspace:*", - "@neos-project/neos-ui-redux-store": "workspace:*", "@neos-project/react-ui-components": "workspace:*", "classnames": "^2.2.3", - "react": "^16.12.0", - "react-redux": "^7.1.3" + "react": "^16.12.0" }, "license": "GNU GPLv3", "stableVersion": "8.3.4" diff --git a/packages/neos-ui-error/src/container/FlashMessages/FlashMessage.tsx b/packages/neos-ui-error/src/container/FlashMessages/FlashMessage.tsx index 1bdb2e0a10..cfaa8ce7f4 100644 --- a/packages/neos-ui-error/src/container/FlashMessages/FlashMessage.tsx +++ b/packages/neos-ui-error/src/container/FlashMessages/FlashMessage.tsx @@ -12,12 +12,14 @@ import mergeClassNames from 'classnames'; import {IconButton, Icon} from '@neos-project/react-ui-components'; +import {Severity} from '../../types'; + import style from './style.module.css'; export const FlashMessage: React.FC<{ id: string; message: string; - severity: 'success' | 'error' | 'info'; + severity: Severity; timeout?: number; onClose: (id: string) => void; diff --git a/packages/neos-ui-error/src/container/FlashMessages/FlashMessages.tsx b/packages/neos-ui-error/src/container/FlashMessages/FlashMessages.tsx index d2ea544737..85fdd3a9b2 100644 --- a/packages/neos-ui-error/src/container/FlashMessages/FlashMessages.tsx +++ b/packages/neos-ui-error/src/container/FlashMessages/FlashMessages.tsx @@ -8,32 +8,55 @@ * source code. */ import React from 'react'; -// @ts-ignore -import {connect} from 'react-redux'; -import {actions} from '@neos-project/neos-ui-redux-store'; -import {GlobalState} from '@neos-project/neos-ui-redux-store/src/System'; +import {createState} from '@neos-project/framework-observable'; +import {useLatestState} from '@neos-project/framework-observable-react'; import {FlashMessage} from './FlashMessage'; +import {Severity} from '../../types'; + import style from './style.module.css'; -const withReduxState = connect((state: GlobalState) => ({ - flashMessages: state?.ui?.flashMessages -}), { - removeMessage: actions.UI.FlashMessages.remove -}); - -const StatelessFlashMessages: React.FC<{ - flashMessages: Record; - removeMessage: (id: string) => void; -}> = (props) => { - const {flashMessages, removeMessage} = props; +const flashMessages$ = createState>({}); + +export function showFlashMessage(flashMessage: { + id: string; + message: string; + severity?: Severity; + timeout?: number; +}) { + const flashMessageWithDefaults = { + id: flashMessage.id, + message: flashMessage.message, + severity: flashMessage.severity ?? 'info', + timeout: flashMessage.timeout + }; + + flashMessages$.update((flashMessages) => ({ + ...flashMessages, + [flashMessageWithDefaults.id]: flashMessageWithDefaults + })); +} + +function removeFlashMessage(id: string) { + flashMessages$.update((flashMessages) => { + const { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + [id]: _, + ...remainingFlashMessages + } = flashMessages; + return remainingFlashMessages; + }); +} + +export const FlashMessages: React.FC = () => { + const flashMessages = useLatestState(flashMessages$); return (
@@ -48,12 +71,10 @@ const StatelessFlashMessages: React.FC<{ message={message} severity={severity} timeout={timeout} - onClose={removeMessage} + onClose={removeFlashMessage} /> ); })}
); } - -export const FlashMessages = withReduxState(StatelessFlashMessages); diff --git a/packages/neos-ui-error/src/container/FlashMessages/index.ts b/packages/neos-ui-error/src/container/FlashMessages/index.ts index 097ed78742..f2279f27a1 100644 --- a/packages/neos-ui-error/src/container/FlashMessages/index.ts +++ b/packages/neos-ui-error/src/container/FlashMessages/index.ts @@ -7,4 +7,4 @@ * information, please view the LICENSE file which was distributed with this * source code. */ -export {FlashMessages} from './FlashMessages'; +export {FlashMessages, showFlashMessage} from './FlashMessages'; diff --git a/packages/neos-ui-error/src/container/index.ts b/packages/neos-ui-error/src/container/index.ts index e4b02df376..507ef19d3c 100644 --- a/packages/neos-ui-error/src/container/index.ts +++ b/packages/neos-ui-error/src/container/index.ts @@ -9,4 +9,4 @@ */ export {ErrorBoundary, terminateDueToFatalInitializationError} from './ErrorBoundary'; export {ErrorView} from './ErrorView'; -export {FlashMessages} from './FlashMessages'; +export {FlashMessages, showFlashMessage} from './FlashMessages'; diff --git a/packages/neos-ui-error/src/index.ts b/packages/neos-ui-error/src/index.ts index 08c63eaeb3..82fa0fedab 100644 --- a/packages/neos-ui-error/src/index.ts +++ b/packages/neos-ui-error/src/index.ts @@ -11,12 +11,14 @@ export type { ECMAScriptError as ClientSideError, ServerSideError, StringError, - AnyError + AnyError, + Severity } from './types'; export { ErrorBoundary, ErrorView, FlashMessages, + showFlashMessage, terminateDueToFatalInitializationError } from './container'; diff --git a/packages/neos-ui-error/src/types.ts b/packages/neos-ui-error/src/types.ts index dc529db4d5..6228781e68 100644 --- a/packages/neos-ui-error/src/types.ts +++ b/packages/neos-ui-error/src/types.ts @@ -17,6 +17,7 @@ export type ServerSideError = { }; export type StringError = string; export type AnyError = ECMAScriptError | ServerSideError | StringError; +export type Severity = 'success' | 'error' | 'info'; export function isECMAScriptError(candidate: unknown): candidate is ECMAScriptError { return candidate instanceof Error; diff --git a/packages/neos-ui-sagas/package.json b/packages/neos-ui-sagas/package.json index ae10867255..99edf11223 100644 --- a/packages/neos-ui-sagas/package.json +++ b/packages/neos-ui-sagas/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@neos-project/neos-ui-backend-connector": "workspace:*", + "@neos-project/neos-ui-error": "workspace:*", "@neos-project/neos-ui-extensibility": "workspace:*", "@neos-project/neos-ui-guest-frame": "workspace:*", "@neos-project/neos-ui-redux-store": "workspace:*", diff --git a/packages/neos-ui-sagas/src/UI/FlashMessages/index.ts b/packages/neos-ui-sagas/src/UI/FlashMessages/index.ts new file mode 100644 index 0000000000..a40562f094 --- /dev/null +++ b/packages/neos-ui-sagas/src/UI/FlashMessages/index.ts @@ -0,0 +1,29 @@ +/* + * This file is part of the Neos.Neos.Ui package. + * + * (c) Contributors of the Neos Project - www.neos.io + * + * This package is Open Source Software. For the full copyright and license + * information, please view the LICENSE file which was distributed with this + * source code. + */ +import {takeEvery} from 'redux-saga/effects'; + +import {actionTypes, actions} from '@neos-project/neos-ui-redux-store'; +import {Severity, showFlashMessage} from '@neos-project/neos-ui-error'; + +export function * legacy__redirectReduxFlashMessagesToHighLevelApiCall() { + yield takeEvery( + actionTypes.UI.FlashMessages.ADD, + function restore( + action: ReturnType + ) { + showFlashMessage({ + id: action.payload.id, + message: action.payload.message, + severity: action.payload.severity.toLowerCase() as Severity, + timeout: action.payload.timeout + }); + } + ); +} diff --git a/packages/neos-ui-sagas/src/index.js b/packages/neos-ui-sagas/src/index.js index c0a6392b6b..7a78469b3a 100644 --- a/packages/neos-ui-sagas/src/index.js +++ b/packages/neos-ui-sagas/src/index.js @@ -12,4 +12,5 @@ export * as uiInspector from './UI/Inspector/index'; export * as uiPageTree from './UI/PageTree/index'; export * as uiHotkeys from './UI/Hotkeys/index'; export * as impersonate from './UI/Impersonate/index'; +export * as flashMessages from './UI/FlashMessages/index'; export * as sync from './Sync/index'; diff --git a/packages/neos-ui-sagas/src/manifest.js b/packages/neos-ui-sagas/src/manifest.js index ac9db2832d..4e226a187d 100644 --- a/packages/neos-ui-sagas/src/manifest.js +++ b/packages/neos-ui-sagas/src/manifest.js @@ -16,7 +16,8 @@ import { uiInspector, uiPageTree, uiHotkeys, - impersonate + impersonate, + flashMessages } from './index'; manifest('main.sagas', {}, globalRegistry => { @@ -81,4 +82,6 @@ manifest('main.sagas', {}, globalRegistry => { sagasRegistry.set('neos-ui/UI/Hotkeys/handleHotkeys', {saga: uiHotkeys.handleHotkeys}); sagasRegistry.set('neos-ui/UI/Impersonate/impersonateRestore', {saga: impersonate.impersonateRestore}); + + sagasRegistry.set('neos-ui/UI/FlashMessages/legacy__redirectReduxFlashMessagesToHighLevelApiCall', {saga: flashMessages.legacy__redirectReduxFlashMessagesToHighLevelApiCall}); }); diff --git a/yarn.lock b/yarn.lock index 99561c9516..046245605f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2277,7 +2277,7 @@ __metadata: languageName: node linkType: hard -"@neos-project/framework-observable-react@workspace:packages/framework-observable-react": +"@neos-project/framework-observable-react@workspace:*, @neos-project/framework-observable-react@workspace:packages/framework-observable-react": version: 0.0.0-use.local resolution: "@neos-project/framework-observable-react@workspace:packages/framework-observable-react" dependencies: @@ -2456,12 +2456,12 @@ __metadata: version: 0.0.0-use.local resolution: "@neos-project/neos-ui-error@workspace:packages/neos-ui-error" dependencies: + "@neos-project/framework-observable": "workspace:*" + "@neos-project/framework-observable-react": "workspace:*" "@neos-project/neos-ui-i18n": "workspace:*" - "@neos-project/neos-ui-redux-store": "workspace:*" "@neos-project/react-ui-components": "workspace:*" classnames: ^2.2.3 react: ^16.12.0 - react-redux: ^7.1.3 languageName: unknown linkType: soft @@ -2569,6 +2569,7 @@ __metadata: dependencies: "@neos-project/jest-preset-neos-ui": "workspace:*" "@neos-project/neos-ui-backend-connector": "workspace:*" + "@neos-project/neos-ui-error": "workspace:*" "@neos-project/neos-ui-extensibility": "workspace:*" "@neos-project/neos-ui-guest-frame": "workspace:*" "@neos-project/neos-ui-redux-store": "workspace:*"