Refactored ErrorNotification/ErrorPage

Added i18n for error codes
This commit is contained in:
Philipp Czora
2019-02-27 10:45:10 +01:00
parent 6b55df464c
commit 510c295e00
9 changed files with 77 additions and 91 deletions

View File

@@ -18,13 +18,9 @@ class BackendErrorNotification extends React.Component<Props, State> {
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 (
<div className="content">
<p>
<p className="subtitle">
<span
onClick={() => {
this.setState({ collapsed: !this.state.collapsed });
@@ -50,12 +46,12 @@ class BackendErrorNotification extends React.Component<Props, State> {
};
renderUncollapsed = () => {
const { error } = this.props;
const { error, t } = this.props;
if (!this.state.collapsed) {
return (
<>
<p>
<strong>Context:</strong>
<strong>{t("errors.context")}</strong>
</p>
<ul>
{error.context.map((context, index) => {
@@ -68,8 +64,8 @@ class BackendErrorNotification extends React.Component<Props, State> {
</ul>
{this.renderMoreInformationLink(error)}
<div className="level is-size-7">
<div className="left">ErrorCode: {error.errorCode}</div>
<div className="right">TransactionId: {error.transactionId}</div>
<div className="left">{t("errors.errorCode")} {error.errorCode}</div>
<div className="right">{t("errors.transactionId")} {error.transactionId}</div>
</div>
</>
);
@@ -78,11 +74,11 @@ class BackendErrorNotification extends React.Component<Props, State> {
};
renderMoreInformationLink = (error: BackendError) => {
const { t } = this.props;
if (error.url) {
// TODO i18n
return (
<p>
For more information, see{" "}
{t("errors.moreInfo")}{" "}
<a href={error.url} target="_blank">
{error.errorCode}
</a>

View File

@@ -1,44 +0,0 @@
//@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<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
collapsed: true
};
}
render() {
const { title, error, t } = this.props;
return (
<section className="section">
<div className="box column is-4 is-offset-4 container has-background-danger">
<span onClick={() => {this.setState({collapsed: !this.state.collapsed})}}>
<h1 className="title"> {title} </h1>
</span>
<ErrorNotification error={error} />
</div>
</section>
);
}
}
export default translate("plugins")(CollapsibleErrorPage);

View File

@@ -1,6 +1,7 @@
//@flow
import React from "react";
import ErrorNotification from "./ErrorNotification";
import { BackendError } from "./errors";
type Props = {
error: Error,
@@ -10,18 +11,26 @@ type Props = {
class ErrorPage extends React.Component<Props> {
render() {
const { title, subtitle, error } = this.props;
const { title, error } = this.props;
return (
<section className="section">
<div className="box column is-4 is-offset-4 container">
<h1 className="title">{title}</h1>
<p className="subtitle">{subtitle}</p>
{this.renderSubtitle()}
<ErrorNotification error={error} />
</div>
</section>
);
}
renderSubtitle = () => {
const { error, subtitle } = this.props;
if (error instanceof BackendError) {
return null;
}
return <p className="subtitle">{subtitle}</p>
}
}
export default ErrorPage;

View File

@@ -9,7 +9,6 @@ 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";

View File

@@ -1,7 +1,11 @@
// @flow
import React from "react";
import { translate } from "react-i18next";
import { Title, ErrorPage, Loading } from "@scm-manager/ui-components";
import {
Title,
Loading,
ErrorNotification
} from "@scm-manager/ui-components";
import {
fetchConfig,
getFetchConfigFailure,
@@ -73,18 +77,8 @@ class GlobalConfig extends React.Component<Props, State> {
};
render() {
const { t, error, loading, config, configUpdatePermission } = this.props;
const { t, loading } = this.props;
if (error) {
return (
<ErrorPage
title={t("config.errorTitle")}
subtitle={t("config.errorSubtitle")}
error={error}
configUpdatePermission={configUpdatePermission}
/>
);
}
if (loading) {
return <Loading />;
}
@@ -92,6 +86,25 @@ class GlobalConfig extends React.Component<Props, State> {
return (
<div>
<Title title={t("config.title")} />
{this.renderError()}
{this.renderContent()}
</div>
);
}
renderError = () => {
const { error } = this.props;
if (error) {
return <ErrorNotification error={error} />;
}
return null;
};
renderContent = () => {
const { error, loading, config, configUpdatePermission } = this.props;
if (!error) {
return (
<>
{this.renderConfigChangedNotification()}
<ConfigForm
submitForm={config => this.modifyConfig(config)}
@@ -99,9 +112,11 @@ class GlobalConfig extends React.Component<Props, State> {
loading={loading}
configUpdatePermission={configUpdatePermission}
/>
</div>
</>
);
}
return null;
};
}
const mapDispatchToProps = dispatch => {

View File

@@ -18,7 +18,7 @@ import {
SubNavigation,
NavLink,
Page,
Section
Section, ErrorPage
} from "@scm-manager/ui-components";
import { translate } from "react-i18next";
import RepositoryDetails from "../components/RepositoryDetails";
@@ -81,17 +81,12 @@ class RepositoryRoot extends React.Component<Props> {
render() {
const { loading, error, indexLinks, repository, t } = this.props;
// if (error) {
// return <ErrorPage
// title={t("repositoryRoot.errorTitle")}
// subtitle={t("repositoryRoot.errorSubtitle")}
// error={error}
// />
// }
if (error) {
return (
<CollapsibleErrorPage title={t("repositoryRoot.errorTitle")} error={error} />
);
return <ErrorPage
title={t("repositoryRoot.errorTitle")}
subtitle={t("repositoryRoot.errorSubtitle")}
error={error}
/>
}
if (!repository || loading) {

View File

@@ -89,6 +89,14 @@
}
},
"errors": {
"AGR7UzkhA1": "Nicht gefunden"
"context": "Kontext",
"errorCode": "Fehlercode",
"transactionId": "Transaktions-ID",
"moreInfo": "Für mehr Informationen, siehe",
"AGR7UzkhA1": "Nicht gefunden",
"FtR7UznKU1": "Existiert bereits",
"9BR7qpDAe1": "Passwortänderung nicht erlaubt",
"2wR7UzpPG1": "Konkurrierende Änderungen",
"9SR8G0kmU1": "Feature nicht unterstützt"
}
}

View File

@@ -89,6 +89,14 @@
}
},
"errors": {
"AGR7UzkhA1": "Not found"
"context": "context",
"errorCode": "Error Code",
"transactionId": "Transaction ID",
"moreInfo": "For more information, see",
"AGR7UzkhA1": "Not found",
"FtR7UznKU1": "Already exists",
"9BR7qpDAe1": "Password change not allowed",
"2wR7UzpPG1": "Concurrent modifications",
"9SR8G0kmU1": "Feature not supported"
}
}