From 256fc746764163e20411e941b351fd318b50945a Mon Sep 17 00:00:00 2001 From: Keith Grant Date: Mon, 5 Aug 2019 16:11:30 -0700 Subject: [PATCH 1/6] add NotFound screen/route handling --- .../components/ContentError/ContentError.jsx | 8 ++++- .../components/ContentError/NotFoundError.jsx | 34 +++++++++++++++++++ .../src/components/ContentError/index.js | 1 + awx/ui_next/src/index.jsx | 17 +++++++--- awx/ui_next/src/screens/NotFound.jsx | 15 ++++++++ 5 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 awx/ui_next/src/components/ContentError/NotFoundError.jsx create mode 100644 awx/ui_next/src/screens/NotFound.jsx diff --git a/awx/ui_next/src/components/ContentError/ContentError.jsx b/awx/ui_next/src/components/ContentError/ContentError.jsx index e3723dc48d..6aa43a68e0 100644 --- a/awx/ui_next/src/components/ContentError/ContentError.jsx +++ b/awx/ui_next/src/components/ContentError/ContentError.jsx @@ -9,8 +9,8 @@ import { EmptyStateBody, } from '@patternfly/react-core'; import { ExclamationTriangleIcon } from '@patternfly/react-icons'; - import ErrorDetail from '@components/ErrorDetail'; +import NotFoundError from './NotFoundError'; const EmptyState = styled(PFEmptyState)` width: var(--pf-c-empty-state--m-lg--MaxWidth); @@ -19,6 +19,12 @@ const EmptyState = styled(PFEmptyState)` class ContentError extends React.Component { render() { const { error, i18n } = this.props; + if (error && error.response && error.response.status === 401) { + // TODO: check for session timeout & redirect to /login + } + if (error && error.response && error.response.status === 404) { + return ; + } return ( diff --git a/awx/ui_next/src/components/ContentError/NotFoundError.jsx b/awx/ui_next/src/components/ContentError/NotFoundError.jsx new file mode 100644 index 0000000000..022cf8e927 --- /dev/null +++ b/awx/ui_next/src/components/ContentError/NotFoundError.jsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { t } from '@lingui/macro'; +import styled from 'styled-components'; +import { withI18n } from '@lingui/react'; +import { + Title, + EmptyState as PFEmptyState, + EmptyStateIcon, + EmptyStateBody, +} from '@patternfly/react-core'; +import { ExclamationTriangleIcon } from '@patternfly/react-icons'; +import ErrorDetail from '@components/ErrorDetail'; + +const EmptyState = styled(PFEmptyState)` + width: var(--pf-c-empty-state--m-lg--MaxWidth); +`; + +function NotFoundError ({ i18n, error }) { + return ( + + + + {i18n._(t`Not Found`)} + + + {i18n._(`The page you requested could not be found.`)} + + {error && } + + ); +} + +export { NotFoundError as _NotFoundError }; +export default withI18n()(NotFoundError); diff --git a/awx/ui_next/src/components/ContentError/index.js b/awx/ui_next/src/components/ContentError/index.js index 14587f410d..8f0d6fcf9c 100644 --- a/awx/ui_next/src/components/ContentError/index.js +++ b/awx/ui_next/src/components/ContentError/index.js @@ -1 +1,2 @@ export { default } from './ContentError'; +export { default as NotFoundError } from './NotFoundError'; diff --git a/awx/ui_next/src/index.jsx b/awx/ui_next/src/index.jsx index dfec0c4c49..9fd10daf47 100644 --- a/awx/ui_next/src/index.jsx +++ b/awx/ui_next/src/index.jsx @@ -32,6 +32,7 @@ import License from '@screens/License'; import Teams from '@screens/Team'; import Templates from '@screens/Template'; import Users from '@screens/User'; +import NotFound from '@screens/NotFound'; import App from './App'; import RootProvider from './RootProvider'; @@ -224,8 +225,8 @@ export function main(render) { ], }, ]} - render={({ routeGroups }) => - routeGroups + render={({ routeGroups }) => { + const routeList = routeGroups .reduce( (allRoutes, { routes }) => allRoutes.concat(routes), [] @@ -238,8 +239,16 @@ export function main(render) { )} /> - )) - } + )); + routeList.push( + + ); + return {routeList}; + }} /> )} /> diff --git a/awx/ui_next/src/screens/NotFound.jsx b/awx/ui_next/src/screens/NotFound.jsx new file mode 100644 index 0000000000..a50ed2e05e --- /dev/null +++ b/awx/ui_next/src/screens/NotFound.jsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { PageSection, Card } from '@patternfly/react-core'; +import { NotFoundError } from '@components/ContentError'; + +function NotFound() { + return ( + + + + + + ); +} + +export default NotFound; From fe8df2781126971add06f8898e466e3e1f03d761 Mon Sep 17 00:00:00 2001 From: Keith Grant Date: Wed, 7 Aug 2019 16:04:39 -0700 Subject: [PATCH 2/6] add more meaningful 404 error screens --- .../components/ContentError/ContentError.jsx | 23 +++++++--- .../components/ContentError/NotFoundError.jsx | 8 ++-- awx/ui_next/src/screens/Job/Job.jsx | 27 ++++++++++-- .../src/screens/Job/JobTypeRedirect.jsx | 43 +++++++++++++++---- .../src/screens/Organization/Organization.jsx | 30 +++++++++++-- awx/ui_next/src/screens/Template/Template.jsx | 41 ++++++++++++++---- .../src/screens/Template/Templates.jsx | 4 +- 7 files changed, 139 insertions(+), 37 deletions(-) diff --git a/awx/ui_next/src/components/ContentError/ContentError.jsx b/awx/ui_next/src/components/ContentError/ContentError.jsx index 6aa43a68e0..e5f8fbbbb1 100644 --- a/awx/ui_next/src/components/ContentError/ContentError.jsx +++ b/awx/ui_next/src/components/ContentError/ContentError.jsx @@ -9,6 +9,7 @@ import { EmptyStateBody, } from '@patternfly/react-core'; import { ExclamationTriangleIcon } from '@patternfly/react-icons'; +import { RootAPI } from '@api'; import ErrorDetail from '@components/ErrorDetail'; import NotFoundError from './NotFoundError'; @@ -16,23 +17,33 @@ const EmptyState = styled(PFEmptyState)` width: var(--pf-c-empty-state--m-lg--MaxWidth); `; +async function logout() { + await RootAPI.logout(); + window.location.replace('/#/login'); +} + class ContentError extends React.Component { + render() { - const { error, i18n } = this.props; + const { error, children, i18n } = this.props; if (error && error.response && error.response.status === 401) { - // TODO: check for session timeout & redirect to /login + if (!error.response.headers['session-timeout']) { + logout(); + return null; + } } if (error && error.response && error.response.status === 404) { - return ; + return {children}; } return ( {i18n._(t`Something went wrong...`)} - {i18n._( - t`There was an error loading this content. Please reload the page.` - )} + {children || + i18n._( + t`There was an error loading this content. Please reload the page.` + )} {error && } diff --git a/awx/ui_next/src/components/ContentError/NotFoundError.jsx b/awx/ui_next/src/components/ContentError/NotFoundError.jsx index 022cf8e927..a8ae056ec6 100644 --- a/awx/ui_next/src/components/ContentError/NotFoundError.jsx +++ b/awx/ui_next/src/components/ContentError/NotFoundError.jsx @@ -15,15 +15,13 @@ const EmptyState = styled(PFEmptyState)` width: var(--pf-c-empty-state--m-lg--MaxWidth); `; -function NotFoundError ({ i18n, error }) { +function NotFoundError({ i18n, error, children }) { return ( - - {i18n._(t`Not Found`)} - + {i18n._(t`Not Found`)} - {i18n._(`The page you requested could not be found.`)} + {children || i18n._(`The page you requested could not be found.`)} {error && } diff --git a/awx/ui_next/src/screens/Job/Job.jsx b/awx/ui_next/src/screens/Job/Job.jsx index 313f051cad..95e084c409 100644 --- a/awx/ui_next/src/screens/Job/Job.jsx +++ b/awx/ui_next/src/screens/Job/Job.jsx @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import { Route, withRouter, Switch, Redirect } from 'react-router-dom'; +import { Route, withRouter, Switch, Redirect, Link } from 'react-router-dom'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import styled from 'styled-components'; @@ -9,7 +9,7 @@ import { PageSection, } from '@patternfly/react-core'; import { JobsAPI } from '@api'; -import ContentError from '@components/ContentError'; +import ContentError, { NotFoundError } from '@components/ContentError'; import CardCloseButton from '@components/CardCloseButton'; import RoutedTabs from '@components/RoutedTabs'; @@ -99,7 +99,14 @@ class Job extends Component { return ( - + + {contentError.response.status === 404 && ( + + {i18n._(`The page you requested could not be found.`)}{' '} + {i18n._(`View all Jobs.`)} + + )} + ); @@ -139,6 +146,20 @@ class Job extends Component { path="/jobs/:type/:id/output" render={() => } />, + ( + + {i18n._(`The page you requested could not be found.`)}{' '} + + {i18n._(`View Job Details`)} + + + )} + />, ]} diff --git a/awx/ui_next/src/screens/Job/JobTypeRedirect.jsx b/awx/ui_next/src/screens/Job/JobTypeRedirect.jsx index 20ba8b1bc0..0a1e3266f0 100644 --- a/awx/ui_next/src/screens/Job/JobTypeRedirect.jsx +++ b/awx/ui_next/src/screens/Job/JobTypeRedirect.jsx @@ -1,8 +1,12 @@ import React, { Component } from 'react'; -import { Redirect } from 'react-router-dom'; +import { Redirect, Link } from 'react-router-dom'; +import { PageSection, Card } from '@patternfly/react-core'; import { UnifiedJobsAPI } from '@api'; +import ContentError, { NotFoundError } from '@components/ContentError'; import { JOB_TYPE_URL_SEGMENTS } from '../../constants'; +const NOT_FOUND = 'not found'; + class JobTypeRedirect extends Component { static defaultProps = { view: 'details', @@ -12,8 +16,9 @@ class JobTypeRedirect extends Component { super(props); this.state = { - hasError: false, + error: null, job: null, + isLoading: true, }; this.loadJob = this.loadJob.bind(this); } @@ -24,24 +29,44 @@ class JobTypeRedirect extends Component { async loadJob() { const { id } = this.props; + this.setState({ isLoading: true }); try { const { data } = await UnifiedJobsAPI.read({ id }); + const job = data.results[0]; this.setState({ - job: data.results[0], + job, + isLoading: false, + error: job ? null : NOT_FOUND, + }); + } catch (error) { + this.setState({ + error, + isLoading: false, }); - } catch (err) { - this.setState({ hasError: true }); } } render() { const { path, view } = this.props; - const { hasError, job } = this.state; + const { error, job, isLoading } = this.state; - if (hasError) { - return
Error
; + if (error) { + return ( + + + {error === NOT_FOUND ? ( + + The requested job could not be found. View all Jobs. + + ) : ( + + )} + + + ); } - if (!job) { + if (isLoading) { + // TODO show loading state return
Loading...
; } const type = JOB_TYPE_URL_SEGMENTS[job.type]; diff --git a/awx/ui_next/src/screens/Organization/Organization.jsx b/awx/ui_next/src/screens/Organization/Organization.jsx index 9727bdc411..47086b79d1 100644 --- a/awx/ui_next/src/screens/Organization/Organization.jsx +++ b/awx/ui_next/src/screens/Organization/Organization.jsx @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; -import { Switch, Route, withRouter, Redirect } from 'react-router-dom'; +import { Switch, Route, withRouter, Redirect, Link } from 'react-router-dom'; import { Card, CardHeader as PFCardHeader, @@ -10,7 +10,7 @@ import { import styled from 'styled-components'; import CardCloseButton from '@components/CardCloseButton'; import RoutedTabs from '@components/RoutedTabs'; -import ContentError from '@components/ContentError'; +import ContentError, { NotFoundError } from '@components/ContentError'; import { OrganizationAccess } from './OrganizationAccess'; import OrganizationDetail from './OrganizationDetail'; import OrganizationEdit from './OrganizationEdit'; @@ -168,7 +168,16 @@ class Organization extends Component { return ( - + + {contentError.response.status === 404 && ( + + {i18n._(`Organization not found.`)}{' '} + + {i18n._(`View all Organizations.`)} + + + )} + ); @@ -226,6 +235,21 @@ class Organization extends Component { )} /> )} + ( + + {i18n._(`The page you requested could not be found.`)}{' '} + {match.params.id && ( + + {i18n._(`View Organization Details`)} + + )} + + )} + /> + , diff --git a/awx/ui_next/src/screens/Template/Template.jsx b/awx/ui_next/src/screens/Template/Template.jsx index adead1c6c0..67848f2bde 100644 --- a/awx/ui_next/src/screens/Template/Template.jsx +++ b/awx/ui_next/src/screens/Template/Template.jsx @@ -2,9 +2,9 @@ import React, { Component } from 'react'; import { t } from '@lingui/macro'; import { withI18n } from '@lingui/react'; import { Card, CardHeader, PageSection } from '@patternfly/react-core'; -import { Switch, Route, Redirect, withRouter } from 'react-router-dom'; +import { Switch, Route, Redirect, withRouter, Link } from 'react-router-dom'; import CardCloseButton from '@components/CardCloseButton'; -import ContentError from '@components/ContentError'; +import ContentError, { NotFoundError } from '@components/ContentError'; import RoutedTabs from '@components/RoutedTabs'; import JobTemplateDetail from './JobTemplateDetail'; import { JobTemplatesAPI } from '@api'; @@ -77,7 +77,14 @@ class Template extends Component { return ( - + + {contentError.response.status === 404 && ( + + {i18n._(`Template not found.`)}{' '} + {i18n._(`View all Templates.`)} + + )} + ); @@ -92,8 +99,9 @@ class Template extends Component { to="/templates/:templateType/:id/details" exact /> - {template && ( + {template && [ ( )} - /> - )} - {template && ( + />, } - /> - )} + />, + ( + + {i18n._(`The page you requested could not be found.`)}{' '} + {match.params.id && ( + + {i18n._(`View Template Details`)} + + )} + + )} + />, + ]} diff --git a/awx/ui_next/src/screens/Template/Templates.jsx b/awx/ui_next/src/screens/Template/Templates.jsx index 55643616cd..d9460d0ac3 100644 --- a/awx/ui_next/src/screens/Template/Templates.jsx +++ b/awx/ui_next/src/screens/Template/Templates.jsx @@ -1,11 +1,11 @@ import React, { Component, Fragment } from 'react'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; -import { Route, withRouter, Switch } from 'react-router-dom'; +import { Route, withRouter, Switch, Link } from 'react-router-dom'; import { Config } from '@contexts/Config'; import Breadcrumbs from '@components/Breadcrumbs/Breadcrumbs'; - +import { NotFoundError } from '@components/ContentError'; import { TemplateList } from './TemplateList'; import Template from './Template'; import JobTemplateAdd from './JobTemplateAdd'; From 47357aea28bec0e7fddfad1b112acf10597ccb50 Mon Sep 17 00:00:00 2001 From: Keith Grant Date: Thu, 8 Aug 2019 08:45:05 -0700 Subject: [PATCH 3/6] fix lint errors --- awx/ui_next/src/components/ContentError/ContentError.jsx | 1 - awx/ui_next/src/screens/Job/JobTypeRedirect.jsx | 3 ++- awx/ui_next/src/screens/Template/Templates.jsx | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/awx/ui_next/src/components/ContentError/ContentError.jsx b/awx/ui_next/src/components/ContentError/ContentError.jsx index e5f8fbbbb1..0b6572ff6d 100644 --- a/awx/ui_next/src/components/ContentError/ContentError.jsx +++ b/awx/ui_next/src/components/ContentError/ContentError.jsx @@ -23,7 +23,6 @@ async function logout() { } class ContentError extends React.Component { - render() { const { error, children, i18n } = this.props; if (error && error.response && error.response.status === 401) { diff --git a/awx/ui_next/src/screens/Job/JobTypeRedirect.jsx b/awx/ui_next/src/screens/Job/JobTypeRedirect.jsx index 0a1e3266f0..48d89385d2 100644 --- a/awx/ui_next/src/screens/Job/JobTypeRedirect.jsx +++ b/awx/ui_next/src/screens/Job/JobTypeRedirect.jsx @@ -56,7 +56,8 @@ class JobTypeRedirect extends Component { {error === NOT_FOUND ? ( - The requested job could not be found. View all Jobs. + The requested job could not be found.{' '} + View all Jobs. ) : ( diff --git a/awx/ui_next/src/screens/Template/Templates.jsx b/awx/ui_next/src/screens/Template/Templates.jsx index d9460d0ac3..0b54b5952a 100644 --- a/awx/ui_next/src/screens/Template/Templates.jsx +++ b/awx/ui_next/src/screens/Template/Templates.jsx @@ -1,11 +1,10 @@ import React, { Component, Fragment } from 'react'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; -import { Route, withRouter, Switch, Link } from 'react-router-dom'; +import { Route, withRouter, Switch } from 'react-router-dom'; import { Config } from '@contexts/Config'; import Breadcrumbs from '@components/Breadcrumbs/Breadcrumbs'; -import { NotFoundError } from '@components/ContentError'; import { TemplateList } from './TemplateList'; import Template from './Template'; import JobTemplateAdd from './JobTemplateAdd'; From db1dddb95e4a234be7cb2b989c2d565d15af5095 Mon Sep 17 00:00:00 2001 From: Keith Grant Date: Thu, 8 Aug 2019 11:26:38 -0700 Subject: [PATCH 4/6] fix redirect to login with expired session on org list & template list --- .../screens/Organization/OrganizationList/OrganizationList.jsx | 2 +- awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx index 147bd9eec2..4f943126f5 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx @@ -149,7 +149,7 @@ class OrganizationsList extends Component { Date: Fri, 9 Aug 2019 15:19:47 -0700 Subject: [PATCH 5/6] remove NotFoundError and use ContentError instead --- .../components/ContentError/ContentError.jsx | 58 +++++++++++-------- .../components/ContentError/NotFoundError.jsx | 32 ---------- .../src/components/ContentError/index.js | 1 - awx/ui_next/src/screens/Job/Job.jsx | 7 +-- .../src/screens/Job/JobTypeRedirect.jsx | 14 ++--- awx/ui_next/src/screens/NotFound.jsx | 4 +- .../src/screens/Organization/Organization.jsx | 7 +-- awx/ui_next/src/screens/Template/Template.jsx | 7 +-- 8 files changed, 51 insertions(+), 79 deletions(-) delete mode 100644 awx/ui_next/src/components/ContentError/NotFoundError.jsx diff --git a/awx/ui_next/src/components/ContentError/ContentError.jsx b/awx/ui_next/src/components/ContentError/ContentError.jsx index 0b6572ff6d..7b0e6c8f75 100644 --- a/awx/ui_next/src/components/ContentError/ContentError.jsx +++ b/awx/ui_next/src/components/ContentError/ContentError.jsx @@ -1,6 +1,7 @@ import React from 'react'; -import { t } from '@lingui/macro'; import styled from 'styled-components'; +import { bool, instanceOf } from 'prop-types'; +import { t } from '@lingui/macro'; import { withI18n } from '@lingui/react'; import { Title, @@ -11,7 +12,6 @@ import { import { ExclamationTriangleIcon } from '@patternfly/react-icons'; import { RootAPI } from '@api'; import ErrorDetail from '@components/ErrorDetail'; -import NotFoundError from './NotFoundError'; const EmptyState = styled(PFEmptyState)` width: var(--pf-c-empty-state--m-lg--MaxWidth); @@ -22,33 +22,41 @@ async function logout() { window.location.replace('/#/login'); } -class ContentError extends React.Component { - render() { - const { error, children, i18n } = this.props; - if (error && error.response && error.response.status === 401) { - if (!error.response.headers['session-timeout']) { - logout(); - return null; - } +function ContentError({ error, children, isNotFound, i18n }) { + if (error && error.response && error.response.status === 401) { + if (!error.response.headers['session-timeout']) { + logout(); + return null; } - if (error && error.response && error.response.status === 404) { - return {children}; - } - return ( - - - {i18n._(t`Something went wrong...`)} - - {children || - i18n._( + } + const is404 = + isNotFound || (error && error.response && error.response.status === 404); + return ( + + + + {is404 ? i18n._(t`Not Found`) : i18n._(t`Something went wrong...`)} + + + {is404 + ? i18n._(t`The page you requested could not be found.`) + : i18n._( t`There was an error loading this content. Please reload the page.` )} - - {error && } - - ); - } + {children} + + {error && } + + ); } +ContentError.propTypes = { + error: instanceOf(Error), + isNotFound: bool, +}; +ContentError.defaultProps = { + error: null, + isNotFound: false, +}; export { ContentError as _ContentError }; export default withI18n()(ContentError); diff --git a/awx/ui_next/src/components/ContentError/NotFoundError.jsx b/awx/ui_next/src/components/ContentError/NotFoundError.jsx deleted file mode 100644 index a8ae056ec6..0000000000 --- a/awx/ui_next/src/components/ContentError/NotFoundError.jsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import { t } from '@lingui/macro'; -import styled from 'styled-components'; -import { withI18n } from '@lingui/react'; -import { - Title, - EmptyState as PFEmptyState, - EmptyStateIcon, - EmptyStateBody, -} from '@patternfly/react-core'; -import { ExclamationTriangleIcon } from '@patternfly/react-icons'; -import ErrorDetail from '@components/ErrorDetail'; - -const EmptyState = styled(PFEmptyState)` - width: var(--pf-c-empty-state--m-lg--MaxWidth); -`; - -function NotFoundError({ i18n, error, children }) { - return ( - - - {i18n._(t`Not Found`)} - - {children || i18n._(`The page you requested could not be found.`)} - - {error && } - - ); -} - -export { NotFoundError as _NotFoundError }; -export default withI18n()(NotFoundError); diff --git a/awx/ui_next/src/components/ContentError/index.js b/awx/ui_next/src/components/ContentError/index.js index 8f0d6fcf9c..14587f410d 100644 --- a/awx/ui_next/src/components/ContentError/index.js +++ b/awx/ui_next/src/components/ContentError/index.js @@ -1,2 +1 @@ export { default } from './ContentError'; -export { default as NotFoundError } from './NotFoundError'; diff --git a/awx/ui_next/src/screens/Job/Job.jsx b/awx/ui_next/src/screens/Job/Job.jsx index 95e084c409..c3150ab15a 100644 --- a/awx/ui_next/src/screens/Job/Job.jsx +++ b/awx/ui_next/src/screens/Job/Job.jsx @@ -9,7 +9,7 @@ import { PageSection, } from '@patternfly/react-core'; import { JobsAPI } from '@api'; -import ContentError, { NotFoundError } from '@components/ContentError'; +import ContentError from '@components/ContentError'; import CardCloseButton from '@components/CardCloseButton'; import RoutedTabs from '@components/RoutedTabs'; @@ -150,14 +150,13 @@ class Job extends Component { key="not-found" path="*" render={() => ( - - {i18n._(`The page you requested could not be found.`)}{' '} + {i18n._(`View Job Details`)} - + )} />, ]} diff --git a/awx/ui_next/src/screens/Job/JobTypeRedirect.jsx b/awx/ui_next/src/screens/Job/JobTypeRedirect.jsx index 48d89385d2..e2eeb57725 100644 --- a/awx/ui_next/src/screens/Job/JobTypeRedirect.jsx +++ b/awx/ui_next/src/screens/Job/JobTypeRedirect.jsx @@ -1,8 +1,9 @@ import React, { Component } from 'react'; import { Redirect, Link } from 'react-router-dom'; import { PageSection, Card } from '@patternfly/react-core'; +import { withI18n } from '@lingui/react'; import { UnifiedJobsAPI } from '@api'; -import ContentError, { NotFoundError } from '@components/ContentError'; +import ContentError from '@components/ContentError'; import { JOB_TYPE_URL_SEGMENTS } from '../../constants'; const NOT_FOUND = 'not found'; @@ -47,7 +48,7 @@ class JobTypeRedirect extends Component { } render() { - const { path, view } = this.props; + const { path, view, i18n } = this.props; const { error, job, isLoading } = this.state; if (error) { @@ -55,10 +56,9 @@ class JobTypeRedirect extends Component { {error === NOT_FOUND ? ( - - The requested job could not be found.{' '} - View all Jobs. - + + {i18n._(`View all Jobs`)} + ) : ( )} @@ -75,4 +75,4 @@ class JobTypeRedirect extends Component { } } -export default JobTypeRedirect; +export default withI18n()(JobTypeRedirect); diff --git a/awx/ui_next/src/screens/NotFound.jsx b/awx/ui_next/src/screens/NotFound.jsx index a50ed2e05e..f09a8fdba9 100644 --- a/awx/ui_next/src/screens/NotFound.jsx +++ b/awx/ui_next/src/screens/NotFound.jsx @@ -1,12 +1,12 @@ import React from 'react'; import { PageSection, Card } from '@patternfly/react-core'; -import { NotFoundError } from '@components/ContentError'; +import ContentError from '@components/ContentError'; function NotFound() { return ( - + ); diff --git a/awx/ui_next/src/screens/Organization/Organization.jsx b/awx/ui_next/src/screens/Organization/Organization.jsx index 47086b79d1..69e08354dd 100644 --- a/awx/ui_next/src/screens/Organization/Organization.jsx +++ b/awx/ui_next/src/screens/Organization/Organization.jsx @@ -10,7 +10,7 @@ import { import styled from 'styled-components'; import CardCloseButton from '@components/CardCloseButton'; import RoutedTabs from '@components/RoutedTabs'; -import ContentError, { NotFoundError } from '@components/ContentError'; +import ContentError from '@components/ContentError'; import { OrganizationAccess } from './OrganizationAccess'; import OrganizationDetail from './OrganizationDetail'; import OrganizationEdit from './OrganizationEdit'; @@ -239,14 +239,13 @@ class Organization extends Component { key="not-found" path="*" render={() => ( - - {i18n._(`The page you requested could not be found.`)}{' '} + {match.params.id && ( {i18n._(`View Organization Details`)} )} - + )} /> , diff --git a/awx/ui_next/src/screens/Template/Template.jsx b/awx/ui_next/src/screens/Template/Template.jsx index 67848f2bde..062ba9e0c3 100644 --- a/awx/ui_next/src/screens/Template/Template.jsx +++ b/awx/ui_next/src/screens/Template/Template.jsx @@ -4,7 +4,7 @@ import { withI18n } from '@lingui/react'; import { Card, CardHeader, PageSection } from '@patternfly/react-core'; import { Switch, Route, Redirect, withRouter, Link } from 'react-router-dom'; import CardCloseButton from '@components/CardCloseButton'; -import ContentError, { NotFoundError } from '@components/ContentError'; +import ContentError from '@components/ContentError'; import RoutedTabs from '@components/RoutedTabs'; import JobTemplateDetail from './JobTemplateDetail'; import { JobTemplatesAPI } from '@api'; @@ -120,8 +120,7 @@ class Template extends Component { key="not-found" path="*" render={() => ( - - {i18n._(`The page you requested could not be found.`)}{' '} + {match.params.id && ( )} - + )} />, ]} From e1636b3ad44babca52294ce264683644465d83b7 Mon Sep 17 00:00:00 2001 From: Keith Grant Date: Mon, 12 Aug 2019 12:18:35 -0700 Subject: [PATCH 6/6] add link back to dashboard from ContentError --- awx/ui_next/src/components/ContentError/ContentError.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/awx/ui_next/src/components/ContentError/ContentError.jsx b/awx/ui_next/src/components/ContentError/ContentError.jsx index 7b0e6c8f75..a94adc4ac9 100644 --- a/awx/ui_next/src/components/ContentError/ContentError.jsx +++ b/awx/ui_next/src/components/ContentError/ContentError.jsx @@ -1,5 +1,6 @@ import React from 'react'; import styled from 'styled-components'; +import { Link } from 'react-router-dom'; import { bool, instanceOf } from 'prop-types'; import { t } from '@lingui/macro'; import { withI18n } from '@lingui/react'; @@ -42,8 +43,8 @@ function ContentError({ error, children, isNotFound, i18n }) { ? i18n._(t`The page you requested could not be found.`) : i18n._( t`There was an error loading this content. Please reload the page.` - )} - {children} + )}{' '} + {children || {i18n._(t`Back to Dashboard.`)}} {error && }