From 6b55df464cf37aa48563d261f864e6f3bdd1c2ac Mon Sep 17 00:00:00 2001 From: Philipp Czora Date: Tue, 26 Feb 2019 17:08:33 +0100 Subject: [PATCH] WIP: Reworking ErrorPage/ErrorNotification --- .../src/BackendErrorNotification.js | 95 +++++++++++++++++++ .../ui-components/src/CollapsibleErrorPage.js | 44 +++++++++ .../ui-components/src/ErrorNotification.js | 56 +---------- .../packages/ui-components/src/index.js | 1 + scm-ui/src/repos/containers/RepositoryRoot.js | 15 +-- .../main/resources/locales/de/plugins.json | 3 + .../main/resources/locales/en/plugins.json | 3 + 7 files changed, 159 insertions(+), 58 deletions(-) create mode 100644 scm-ui-components/packages/ui-components/src/BackendErrorNotification.js create mode 100644 scm-ui-components/packages/ui-components/src/CollapsibleErrorPage.js diff --git a/scm-ui-components/packages/ui-components/src/BackendErrorNotification.js b/scm-ui-components/packages/ui-components/src/BackendErrorNotification.js new file mode 100644 index 0000000000..cf4d0def0d --- /dev/null +++ b/scm-ui-components/packages/ui-components/src/BackendErrorNotification.js @@ -0,0 +1,95 @@ +// @flow +import React from "react"; +import { BackendError } from "./errors"; +import classNames from "classnames"; + +import { translate } from "react-i18next"; + +type Props = { error: BackendError, t: string => string }; +type State = { collapsed: boolean }; + +class BackendErrorNotification extends React.Component { + constructor(props: Props) { + super(props); + this.state = { collapsed: true }; + } + + render() { + const { collapsed } = this.state; + const icon = collapsed ? "fa-angle-right" : "fa-angle-down"; + + // TODO error page + // we have currently the ErrorNotification, which is often wrapped by the ErrorPage + // the ErrorPage has often a SubTitle like "Unkwown xzy error", which is no longer always the case + // if the error is a BackendError its not fully unknown + return ( +
+

+ { + this.setState({ collapsed: !this.state.collapsed }); + }} + > + + + {this.renderErrorMessage()} + +

+ {this.renderUncollapsed()} +
+ ); + } + + renderErrorMessage = () => { + const { error, t } = this.props; + const translation = t("errors." + error.errorCode); + if (translation === error.errorCode) { + return error.message; + } + return translation; + }; + + renderUncollapsed = () => { + const { error } = this.props; + if (!this.state.collapsed) { + return ( + <> +

+ Context: +

+
    + {error.context.map((context, index) => { + return ( +
  • + {context.type}: {context.id} +
  • + ); + })} +
+ {this.renderMoreInformationLink(error)} +
+
ErrorCode: {error.errorCode}
+
TransactionId: {error.transactionId}
+
+ + ); + } + return null; + }; + + renderMoreInformationLink = (error: BackendError) => { + if (error.url) { + // TODO i18n + return ( +

+ For more information, see{" "} + + {error.errorCode} + +

+ ); + } + }; +} + +export default translate("plugins")(BackendErrorNotification); diff --git a/scm-ui-components/packages/ui-components/src/CollapsibleErrorPage.js b/scm-ui-components/packages/ui-components/src/CollapsibleErrorPage.js new file mode 100644 index 0000000000..c7c328fe6d --- /dev/null +++ b/scm-ui-components/packages/ui-components/src/CollapsibleErrorPage.js @@ -0,0 +1,44 @@ +//@flow +import React from "react"; +import ErrorNotification from "./ErrorNotification"; +import { translate } from "react-i18next"; + +type Props = { + error: Error, + title: string, + subtitle?: string, + t: string => string +}; + +type State = { + collapsed: boolean +}; + +class CollapsibleErrorPage extends React.Component { + constructor(props: Props) { + super(props); + this.state = { + collapsed: true + }; + } + + + + render() { + const { title, error, t } = this.props; + + return ( +
+
+ {this.setState({collapsed: !this.state.collapsed})}}> +

{title}

+
+ + +
+
+ ); + } +} + +export default translate("plugins")(CollapsibleErrorPage); diff --git a/scm-ui-components/packages/ui-components/src/ErrorNotification.js b/scm-ui-components/packages/ui-components/src/ErrorNotification.js index 747978297b..ab7d8ad882 100644 --- a/scm-ui-components/packages/ui-components/src/ErrorNotification.js +++ b/scm-ui-components/packages/ui-components/src/ErrorNotification.js @@ -1,70 +1,22 @@ //@flow import React from "react"; import { translate } from "react-i18next"; -import Notification from "./Notification"; import { BackendError, UnauthorizedError } from "./errors"; +import Notification from "./Notification"; +import BackendErrorNotification from "./BackendErrorNotification"; type Props = { t: string => string, error?: Error }; + class ErrorNotification extends React.Component { - renderMoreInformationLink(error: BackendError) { - if (error.url) { - // TODO i18n - return ( -

- For more information, see{" "} - - {error.errorCode} - -

- ); - } - } - - renderBackendError = (error: BackendError) => { - // TODO i18n - // how should we handle i18n for the message? - // we could add translation for known error codes to i18n and pass the context objects as parameters, - // but this will not work for errors from plugins, because the ErrorNotification will search for the translation - // in the wrong namespace (plugins could only add translations to the plugins namespace. - // should we add a special namespace for errors? which could be extend by plugins? - - // TODO error page - // we have currently the ErrorNotification, which is often wrapped by the ErrorPage - // the ErrorPage has often a SubTitle like "Unkwown xzy error", which is no longer always the case - // if the error is a BackendError its not fully unknown - return ( -
-

{error.message}

-

- Context: -

-
    - {error.context.map((context, index) => { - return ( -
  • - {context.type}: {context.id} -
  • - ); - })} -
- {this.renderMoreInformationLink(error)} -
-
ErrorCode: {error.errorCode}
-
TransactionId: {error.transactionId}
-
-
- ); - }; - render() { const { t, error } = this.props; if (error) { if (error instanceof BackendError) { - return this.renderBackendError(error); + return } else if (error instanceof UnauthorizedError) { return ( diff --git a/scm-ui-components/packages/ui-components/src/index.js b/scm-ui-components/packages/ui-components/src/index.js index b403ea78b7..4bf6c57338 100644 --- a/scm-ui-components/packages/ui-components/src/index.js +++ b/scm-ui-components/packages/ui-components/src/index.js @@ -9,6 +9,7 @@ export { validation, urls, repositories }; export { default as DateFromNow } from "./DateFromNow.js"; export { default as ErrorNotification } from "./ErrorNotification.js"; export { default as ErrorPage } from "./ErrorPage.js"; +export { default as CollapsibleErrorPage } from "./CollapsibleErrorPage.js"; export { default as Image } from "./Image.js"; export { default as Loading } from "./Loading.js"; export { default as Logo } from "./Logo.js"; diff --git a/scm-ui/src/repos/containers/RepositoryRoot.js b/scm-ui/src/repos/containers/RepositoryRoot.js index 8608b9c957..e8874675d5 100644 --- a/scm-ui/src/repos/containers/RepositoryRoot.js +++ b/scm-ui/src/repos/containers/RepositoryRoot.js @@ -12,7 +12,7 @@ import { Route, Switch } from "react-router-dom"; import type { Repository } from "@scm-manager/ui-types"; import { - ErrorPage, + CollapsibleErrorPage, Loading, Navigation, SubNavigation, @@ -81,13 +81,16 @@ class RepositoryRoot extends React.Component { render() { const { loading, error, indexLinks, repository, t } = this.props; + // if (error) { + // return + // } if (error) { return ( - + ); } diff --git a/scm-webapp/src/main/resources/locales/de/plugins.json b/scm-webapp/src/main/resources/locales/de/plugins.json index 8c2015a0e8..1f2dcc9a41 100644 --- a/scm-webapp/src/main/resources/locales/de/plugins.json +++ b/scm-webapp/src/main/resources/locales/de/plugins.json @@ -87,5 +87,8 @@ "description": "Darf im Repository Kontext alles ausführen. Dies beinhaltet alle Repository Berechtigungen." } } + }, + "errors": { + "AGR7UzkhA1": "Nicht gefunden" } } diff --git a/scm-webapp/src/main/resources/locales/en/plugins.json b/scm-webapp/src/main/resources/locales/en/plugins.json index 03eb06e597..6b1081f2d1 100644 --- a/scm-webapp/src/main/resources/locales/en/plugins.json +++ b/scm-webapp/src/main/resources/locales/en/plugins.json @@ -87,5 +87,8 @@ "description": "May change everything for the repository (includes all other permissions)" } } + }, + "errors": { + "AGR7UzkhA1": "Not found" } }