Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display not found page after getting null from API #3463

Merged
merged 10 commits into from
Dec 18, 2018
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ All notable, unreleased changes to this project will be documented in this file.
- Update Pipfile.lock - #3480 by @maarcingebala
- Add Stripe payment gateway - #3408 by @jxltom
- Remove Elasticsearch from `docker-compose.yml` - #3482 by @maarcingebala
- Add error page if object was not found - #3463 by @dominik-zeglen
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export const CategoryDetails: React.StatelessComponent<
<TypedCategoryDetailsQuery
displayLoader
variables={{ ...paginationState, id }}
require={["category"]}
>
{({ data, loading }) => (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export const CollectionDetails: React.StatelessComponent<
<TypedCollectionDetailsQuery
displayLoader
variables={{ id, ...paginationState }}
require={["collection"]}
>
{({ data, loading }) => {
const handleCollectionUpdate = (data: CollectionUpdate) => {
Expand Down
100 changes: 100 additions & 0 deletions saleor/static/dashboard-next/components/ErrorPage/ErrorPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import Button from "@material-ui/core/Button";
import {
createStyles,
Theme,
withStyles,
WithStyles
} from "@material-ui/core/styles";
import Typography from "@material-ui/core/Typography";
import * as React from "react";
import SVG from "react-inlinesvg";

import * as notFoundImage from "../../../images/what.svg";
import i18n from "../../i18n";

export interface ErrorPageProps extends WithStyles<typeof styles> {
onBack: () => void;
}

const styles = (theme: Theme) =>
createStyles({
bottomHeader: {
fontWeight: 600 as 600,
textTransform: "uppercase"
},
button: {
marginTop: theme.spacing.unit * 2,
padding: 20
},
container: {
[theme.breakpoints.down("sm")]: {
gridTemplateColumns: "1fr",
padding: theme.spacing.unit * 3,
width: "100%"
},
display: "grid",
gridTemplateColumns: "1fr 487px",
margin: "0 auto",
width: 830
},
innerContainer: {
[theme.breakpoints.down("sm")]: {
order: 1,
textAlign: "center"
},
display: "flex",
flexDirection: "column",
justifyContent: "center"
},
notFoundImage: {
"& svg": {
width: "100%"
}
},
root: {
alignItems: "center",
display: "flex",
height: "calc(100vh - 88px)"
},
upperHeader: {
fontWeight: 600 as 600
}
});

const ErrorPage = withStyles(styles, { name: "NotFoundPage" })(
({ classes, onBack }: ErrorPageProps) => (
<div className={classes.root}>
<div className={classes.container}>
<div className={classes.innerContainer}>
<div>
<Typography className={classes.upperHeader} variant="display1">
{i18n.t("Ooops!...")}
</Typography>
<Typography className={classes.bottomHeader} variant="display2">
{i18n.t("Error")}
</Typography>
<Typography>{i18n.t("We've encountered a problem...")}</Typography>
<Typography>
{i18n.t("Don't worry, everything is gonna be fine")}
</Typography>
</div>
<div>
<Button
className={classes.button}
color="secondary"
variant="contained"
onClick={onBack}
>
{i18n.t("Back to home", { context: "button" })}
</Button>
</div>
</div>
<div>
<SVG className={classes.notFoundImage} src={notFoundImage} />
</div>
</div>
</div>
)
);
ErrorPage.displayName = "ErrorPage";
export default ErrorPage;
2 changes: 2 additions & 0 deletions saleor/static/dashboard-next/components/ErrorPage/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from "./ErrorPage";
export * from "./ErrorPage";
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,11 @@ export const CustomerDetailsView: React.StatelessComponent<
onCompleted={handleCustomerUpdateSuccess}
>
{(updateCustomer, updateCustomerOpts) => (
<TypedCustomerDetailsQuery displayLoader variables={{ id }}>
<TypedCustomerDetailsQuery
displayLoader
variables={{ id }}
require={["user"]}
>
{customerDetails => {
const formTransitionState = getMutationState(
updateCustomerOpts.called,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ export const OrderDetails: React.StatelessComponent<OrderDetailsProps> = ({
}) => (
<Navigator>
{navigate => (
<TypedOrderDetailsQuery displayLoader variables={{ id }}>
<TypedOrderDetailsQuery
displayLoader
variables={{ id }}
require={["order"]}
>
{({ data, error, loading }) => {
if (error) {
return <ErrorMessageCard message="Something went wrong" />;
Expand Down
6 changes: 5 additions & 1 deletion saleor/static/dashboard-next/pages/views/PageDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ export class PageUpdateForm extends React.Component<
render() {
const { id } = this.props;
return (
<TypedPageDetailsQuery displayLoader variables={{ id }}>
<TypedPageDetailsQuery
displayLoader
variables={{ id }}
require={["page"]}
>
{({ data, loading }) => (
<TypedPageDeleteMutation>
{(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ export const ProductTypeUpdate: React.StatelessComponent<
{navigate => (
<ProductTypeUpdateErrors>
{({ errors, set: setErrors }) => (
<TypedProductTypeDetailsQuery displayLoader variables={{ id }}>
<TypedProductTypeDetailsQuery
displayLoader
variables={{ id }}
require={["productType"]}
>
{({ data, loading: dataLoading }) => {
const closeModal = () => {
navigate(productTypeUrl(id), true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const ProductImage: React.StatelessComponent<ProductImageProps> = ({
imageId,
productId
}}
require={["product"]}
>
{({ data, loading }) => {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export const ProductUpdate: React.StatelessComponent<ProductUpdateProps> = ({
}) => (
<TypedProductDetailsQuery
displayLoader
require={["product"]}
variables={{ id }}
>
{({ data, loading }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ export const ProductVariant: React.StatelessComponent<ProductUpdateProps> = ({
{navigate => (
<Messages>
{pushMessage => (
<TypedProductVariantQuery displayLoader variables={{ id: variantId }}>
<TypedProductVariantQuery
displayLoader
variables={{ id: variantId }}
require={["productVariant"]}
>
{({ data, loading, error }) => {
if (error) {
return <ErrorMessageCard message="Something went wrong" />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const ProductVariant: React.StatelessComponent<ProductUpdateProps> = ({
<TypedProductVariantCreateQuery
displayLoader
variables={{ id: productId }}
require={["product"]}
>
{({ data, loading: productLoading }) => {
const handleCreateSuccess = (data: VariantCreate) => {
Expand Down
90 changes: 58 additions & 32 deletions saleor/static/dashboard-next/queries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ import * as React from "react";
import { Query, QueryResult } from "react-apollo";

import AppProgress from "./components/AppProgress";
import ErrorPage from "./components/ErrorPage/ErrorPage";
import Messages from "./components/messages";
import Navigator from "./components/Navigator";
import i18n from "./i18n";

interface TypedQueryInnerProps<TData, TVariables> {
children: (result: QueryResult<TData, TVariables>) => React.ReactNode;
displayLoader?: boolean;
skip?: boolean;
variables?: TVariables;
require?: Array<keyof TData>;
}

interface QueryProgressProps {
Expand Down Expand Up @@ -49,44 +52,67 @@ export function TypedQuery<TData, TVariables>(query: DocumentNode) {
children,
displayLoader,
skip,
variables
variables,
require
}: TypedQueryInnerProps<TData, TVariables>) => (
<AppProgress>
{({ funcs: changeProgressState }) => (
<Messages>
{pushMessage => (
<StrictTypedQuery
context={{ useBatching: true }}
fetchPolicy="cache-and-network"
query={query}
variables={variables}
skip={skip}
>
{queryData => {
if (queryData.error) {
const msg = i18n.t("Something went wrong: {{ message }}", {
message: queryData.error.message
});
pushMessage({ text: msg });
}
<Navigator>
{navigate => (
<Messages>
{pushMessage => (
<StrictTypedQuery
fetchPolicy="cache-and-network"
query={query}
variables={variables}
skip={skip}
context={{ useBatching: true }}
>
{queryData => {
if (queryData.error) {
const msg = i18n.t(
"Something went wrong: {{ message }}",
{
message: queryData.error.message
}
);
pushMessage({ text: msg });
}

if (displayLoader) {
return (
<QueryProgress
loading={queryData.loading}
onCompleted={changeProgressState.disable}
onLoading={changeProgressState.enable}
>
{children(queryData)}
</QueryProgress>
);
}
let childrenOrNotFound = children(queryData);
if (
!queryData.loading &&
require &&
queryData.data &&
!require.reduce(
(acc, key) => acc && queryData.data[key] !== null,
true
)
) {
childrenOrNotFound = (
<ErrorPage onBack={() => navigate("/")} />
);
}

return children(queryData);
}}
</StrictTypedQuery>
if (displayLoader) {
return (
<QueryProgress
loading={queryData.loading}
onCompleted={changeProgressState.disable}
onLoading={changeProgressState.enable}
>
{childrenOrNotFound}
</QueryProgress>
);
}

return childrenOrNotFound;
}}
</StrictTypedQuery>
)}
</Messages>
)}
</Messages>
</Navigator>
)}
</AppProgress>
);
Expand Down
6 changes: 5 additions & 1 deletion saleor/static/dashboard-next/staff/views/StaffDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ export const StaffDetails: React.StatelessComponent<OrderListProps> = ({
{navigate => (
<Messages>
{pushMessage => (
<TypedStaffMemberDetailsQuery displayLoader variables={{ id }}>
<TypedStaffMemberDetailsQuery
displayLoader
variables={{ id }}
require={["user"]}
>
{({ data, loading }) => {
const handleStaffMemberUpdate = (data: StaffMemberUpdate) => {
if (!maybe(() => data.staffUpdate.errors.length !== 0)) {
Expand Down