Add app state
This commit is contained in:
parent
0d51418f72
commit
b12f3c35fa
12 changed files with 551 additions and 442 deletions
|
@ -1,10 +1,6 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ErrorBoundary from "react-error-boundary";
|
|
||||||
import { Route, RouteProps } from "react-router-dom";
|
import { Route, RouteProps } from "react-router-dom";
|
||||||
|
|
||||||
import AppLayout from "@saleor/components/AppLayout";
|
|
||||||
import ErrorPage from "@saleor/components/ErrorPage";
|
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
|
||||||
import useUser from "@saleor/hooks/useUser";
|
import useUser from "@saleor/hooks/useUser";
|
||||||
import NotFound from "../../NotFound";
|
import NotFound from "../../NotFound";
|
||||||
import { PermissionEnum } from "../../types/globalTypes";
|
import { PermissionEnum } from "../../types/globalTypes";
|
||||||
|
@ -18,7 +14,6 @@ export const SectionRoute: React.FC<SectionRouteProps> = ({
|
||||||
permissions,
|
permissions,
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigator();
|
|
||||||
const { user } = useUser();
|
const { user } = useUser();
|
||||||
|
|
||||||
const hasPermissions =
|
const hasPermissions =
|
||||||
|
@ -26,18 +21,7 @@ export const SectionRoute: React.FC<SectionRouteProps> = ({
|
||||||
permissions
|
permissions
|
||||||
.map(permission => hasPermission(permission, user))
|
.map(permission => hasPermission(permission, user))
|
||||||
.reduce((prev, curr) => prev && curr);
|
.reduce((prev, curr) => prev && curr);
|
||||||
return hasPermissions ? (
|
return hasPermissions ? <Route {...props} /> : <NotFound />;
|
||||||
<AppLayout>
|
|
||||||
<ErrorBoundary
|
|
||||||
FallbackComponent={() => <ErrorPage onBack={() => navigate("/")} />}
|
|
||||||
key={permissions ? permissions.join(":") : "home"}
|
|
||||||
>
|
|
||||||
<Route {...props} />
|
|
||||||
</ErrorBoundary>
|
|
||||||
</AppLayout>
|
|
||||||
) : (
|
|
||||||
<NotFound />
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
SectionRoute.displayName = "Route";
|
SectionRoute.displayName = "Route";
|
||||||
export default SectionRoute;
|
export default SectionRoute;
|
||||||
|
|
|
@ -13,13 +13,13 @@ import classNames from "classnames";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import SVG from "react-inlinesvg";
|
import SVG from "react-inlinesvg";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import { RouteComponentProps, withRouter } from "react-router";
|
import useRouter from "use-react-router";
|
||||||
|
|
||||||
import saleorDarkLogoSmall from "@assets/images/logo-dark-small.svg";
|
import saleorDarkLogoSmall from "@assets/images/logo-dark-small.svg";
|
||||||
import saleorDarkLogo from "@assets/images/logo-dark.svg";
|
import saleorDarkLogo from "@assets/images/logo-dark.svg";
|
||||||
import menuArrowIcon from "@assets/images/menu-arrow-icon.svg";
|
import menuArrowIcon from "@assets/images/menu-arrow-icon.svg";
|
||||||
import AppProgressProvider from "@saleor/components/AppProgress";
|
|
||||||
import { createConfigurationMenu } from "@saleor/configuration";
|
import { createConfigurationMenu } from "@saleor/configuration";
|
||||||
|
import useAppState from "@saleor/hooks/useAppState";
|
||||||
import useLocalStorage from "@saleor/hooks/useLocalStorage";
|
import useLocalStorage from "@saleor/hooks/useLocalStorage";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useTheme from "@saleor/hooks/useTheme";
|
import useTheme from "@saleor/hooks/useTheme";
|
||||||
|
@ -28,6 +28,8 @@ import ArrowDropdown from "@saleor/icons/ArrowDropdown";
|
||||||
import { maybe } from "@saleor/misc";
|
import { maybe } from "@saleor/misc";
|
||||||
import { staffMemberDetailsUrl } from "@saleor/staff/urls";
|
import { staffMemberDetailsUrl } from "@saleor/staff/urls";
|
||||||
import Container from "../Container";
|
import Container from "../Container";
|
||||||
|
import ErrorPage from "../ErrorPage";
|
||||||
|
import NotFoundPage from "../NotFoundPage";
|
||||||
import AppActionContext from "./AppActionContext";
|
import AppActionContext from "./AppActionContext";
|
||||||
import AppHeaderContext from "./AppHeaderContext";
|
import AppHeaderContext from "./AppHeaderContext";
|
||||||
import { appLoaderHeight, drawerWidth, drawerWidthExpanded } from "./consts";
|
import { appLoaderHeight, drawerWidth, drawerWidthExpanded } from "./consts";
|
||||||
|
@ -273,8 +275,7 @@ interface AppLayoutProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppLayout = withRouter<AppLayoutProps & RouteComponentProps<any>, any>(
|
const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
|
||||||
({ children, location }: AppLayoutProps & RouteComponentProps<any>) => {
|
|
||||||
const classes = useStyles({});
|
const classes = useStyles({});
|
||||||
const { isDark, toggleTheme } = useTheme();
|
const { isDark, toggleTheme } = useTheme();
|
||||||
const [isMenuSmall, setMenuSmall] = useLocalStorage("isMenuSmall", false);
|
const [isMenuSmall, setMenuSmall] = useLocalStorage("isMenuSmall", false);
|
||||||
|
@ -286,6 +287,8 @@ const AppLayout = withRouter<AppLayoutProps & RouteComponentProps<any>, any>(
|
||||||
const { logout, user } = useUser();
|
const { logout, user } = useUser();
|
||||||
const navigate = useNavigator();
|
const navigate = useNavigator();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const [appState, dispatchAppState] = useAppState();
|
||||||
|
const { location } = useRouter();
|
||||||
|
|
||||||
const menuStructure = createMenuStructure(intl);
|
const menuStructure = createMenuStructure(intl);
|
||||||
const configurationMenu = createConfigurationMenu(intl);
|
const configurationMenu = createConfigurationMenu(intl);
|
||||||
|
@ -321,9 +324,17 @@ const AppLayout = withRouter<AppLayoutProps & RouteComponentProps<any>, any>(
|
||||||
setMenuSmall(!isMenuSmall);
|
setMenuSmall(!isMenuSmall);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleErrorBack = () => {
|
||||||
|
navigate("/");
|
||||||
|
dispatchAppState({
|
||||||
|
payload: {
|
||||||
|
error: null
|
||||||
|
},
|
||||||
|
type: "displayError"
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppProgressProvider>
|
|
||||||
{({ isProgress }) => (
|
|
||||||
<AppHeaderContext.Provider value={appHeaderAnchor}>
|
<AppHeaderContext.Provider value={appHeaderAnchor}>
|
||||||
<AppActionContext.Provider value={appActionAnchor}>
|
<AppActionContext.Provider value={appActionAnchor}>
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
|
@ -339,9 +350,7 @@ const AppLayout = withRouter<AppLayoutProps & RouteComponentProps<any>, any>(
|
||||||
[classes.logoDark]: isDark
|
[classes.logoDark]: isDark
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<SVG
|
<SVG src={isMenuSmall ? saleorDarkLogoSmall : saleorDarkLogo} />
|
||||||
src={isMenuSmall ? saleorDarkLogoSmall : saleorDarkLogo}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<Hidden smDown>
|
<Hidden smDown>
|
||||||
<div
|
<div
|
||||||
|
@ -370,11 +379,8 @@ const AppLayout = withRouter<AppLayoutProps & RouteComponentProps<any>, any>(
|
||||||
[classes.contentToggle]: isMenuSmall
|
[classes.contentToggle]: isMenuSmall
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{isProgress ? (
|
{appState.loading ? (
|
||||||
<LinearProgress
|
<LinearProgress className={classes.appLoader} color="primary" />
|
||||||
className={classes.appLoader}
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<div className={classes.appLoaderPlaceholder} />
|
<div className={classes.appLoaderPlaceholder} />
|
||||||
)}
|
)}
|
||||||
|
@ -402,10 +408,7 @@ const AppLayout = withRouter<AppLayoutProps & RouteComponentProps<any>, any>(
|
||||||
checked={isDark}
|
checked={isDark}
|
||||||
onClick={toggleTheme}
|
onClick={toggleTheme}
|
||||||
/>
|
/>
|
||||||
<div
|
<div className={classes.userMenuContainer} ref={anchor}>
|
||||||
className={classes.userMenuContainer}
|
|
||||||
ref={anchor}
|
|
||||||
>
|
|
||||||
<Chip
|
<Chip
|
||||||
avatar={
|
avatar={
|
||||||
user.avatar && (
|
user.avatar && (
|
||||||
|
@ -478,17 +481,24 @@ const AppLayout = withRouter<AppLayoutProps & RouteComponentProps<any>, any>(
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
<main className={classes.view}>{children}</main>
|
<main className={classes.view}>
|
||||||
|
{appState.error ? (
|
||||||
|
appState.error === "not-found" ? (
|
||||||
|
<NotFoundPage onBack={handleErrorBack} />
|
||||||
|
) : (
|
||||||
|
<ErrorPage onBack={handleErrorBack} />
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
children
|
||||||
|
)}
|
||||||
|
</main>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.appAction} ref={appActionAnchor} />
|
<div className={classes.appAction} ref={appActionAnchor} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</AppActionContext.Provider>
|
</AppActionContext.Provider>
|
||||||
</AppHeaderContext.Provider>
|
</AppHeaderContext.Provider>
|
||||||
)}
|
|
||||||
</AppProgressProvider>
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
);
|
|
||||||
|
|
||||||
export default AppLayout;
|
export default AppLayout;
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
interface IAppProgressContext {
|
|
||||||
isProgress: boolean;
|
|
||||||
setProgressState: (isOpened: boolean) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AppProgressContext = React.createContext<IAppProgressContext>(
|
|
||||||
undefined
|
|
||||||
);
|
|
||||||
|
|
||||||
export const AppProgressProvider: React.FC<{}> = ({ children }) => {
|
|
||||||
const [isProgress, setProgressState] = React.useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AppProgressContext.Provider
|
|
||||||
value={{
|
|
||||||
isProgress,
|
|
||||||
setProgressState
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</AppProgressContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AppProgress = AppProgressContext.Consumer;
|
|
||||||
export default AppProgress;
|
|
|
@ -48,7 +48,7 @@ const useStyles = makeStyles(theme => ({
|
||||||
root: {
|
root: {
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
height: "calc(100vh - 88px)"
|
height: "calc(100vh - 180px)"
|
||||||
},
|
},
|
||||||
upperHeader: {
|
upperHeader: {
|
||||||
fontWeight: 600 as 600
|
fontWeight: 600 as 600
|
||||||
|
|
|
@ -43,8 +43,7 @@ const useStyles = makeStyles(theme => ({
|
||||||
root: {
|
root: {
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
height: "100vh",
|
height: "calc(100vh - 180px)"
|
||||||
width: "100vw"
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
40
src/containers/AppState/AppState.tsx
Normal file
40
src/containers/AppState/AppState.tsx
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import React from "react";
|
||||||
|
import useRouter from "use-react-router";
|
||||||
|
|
||||||
|
import appStateReducer, { AppStateReducerAction } from "./reducer";
|
||||||
|
import IAppState, { initialAppState } from "./state";
|
||||||
|
|
||||||
|
export type AppStateContextType = [
|
||||||
|
IAppState,
|
||||||
|
React.Dispatch<AppStateReducerAction>
|
||||||
|
];
|
||||||
|
export const AppStateContext = React.createContext<AppStateContextType>([
|
||||||
|
initialAppState,
|
||||||
|
() => undefined
|
||||||
|
]);
|
||||||
|
const AppStateProvider: React.FC = ({ children }) => {
|
||||||
|
const { location } = useRouter();
|
||||||
|
const stateAndDispatch = React.useReducer(appStateReducer, initialAppState);
|
||||||
|
const [state, dispatch] = stateAndDispatch;
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!!state.error) {
|
||||||
|
dispatch({
|
||||||
|
payload: {
|
||||||
|
error: null
|
||||||
|
},
|
||||||
|
type: "displayError"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [location]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppStateContext.Provider value={stateAndDispatch}>
|
||||||
|
{children}
|
||||||
|
</AppStateContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const { Consumer } = AppStateContext;
|
||||||
|
|
||||||
|
export default AppStateProvider;
|
2
src/containers/AppState/index.ts
Normal file
2
src/containers/AppState/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export { default } from "./AppState";
|
||||||
|
export * from "./AppState";
|
42
src/containers/AppState/reducer.ts
Normal file
42
src/containers/AppState/reducer.ts
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import IAppState, { AppError } from "./state";
|
||||||
|
|
||||||
|
export type AppStateReducerActionType = "displayError" | "displayLoader";
|
||||||
|
|
||||||
|
export interface AppStateReducerAction {
|
||||||
|
payload: Partial<{
|
||||||
|
error: AppError;
|
||||||
|
value: boolean;
|
||||||
|
}>;
|
||||||
|
type: AppStateReducerActionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayError(prevState: IAppState, error: AppError): IAppState {
|
||||||
|
return {
|
||||||
|
...prevState,
|
||||||
|
error,
|
||||||
|
loading: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayLoader(prevState: IAppState, value: boolean): IAppState {
|
||||||
|
return {
|
||||||
|
...prevState,
|
||||||
|
loading: value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function reduceAppState(
|
||||||
|
prevState: IAppState,
|
||||||
|
action: AppStateReducerAction
|
||||||
|
): IAppState {
|
||||||
|
switch (action.type) {
|
||||||
|
case "displayError":
|
||||||
|
return displayError(prevState, action.payload.error);
|
||||||
|
case "displayLoader":
|
||||||
|
return displayLoader(prevState, action.payload.value);
|
||||||
|
default:
|
||||||
|
return prevState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default reduceAppState;
|
13
src/containers/AppState/state.ts
Normal file
13
src/containers/AppState/state.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
export type AppError = "unhandled" | "not-found";
|
||||||
|
|
||||||
|
interface IAppState {
|
||||||
|
error: AppError | null;
|
||||||
|
loading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const initialAppState: IAppState = {
|
||||||
|
error: null,
|
||||||
|
loading: false
|
||||||
|
};
|
||||||
|
|
||||||
|
export default IAppState;
|
11
src/hooks/useAppState.ts
Normal file
11
src/hooks/useAppState.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { AppStateContext } from "../containers/AppState";
|
||||||
|
|
||||||
|
function useAppState() {
|
||||||
|
const stateAndDispatch = React.useContext(AppStateContext);
|
||||||
|
|
||||||
|
return stateAndDispatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useAppState;
|
|
@ -8,9 +8,11 @@ import { createUploadLink } from "apollo-upload-client";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { ApolloProvider } from "react-apollo";
|
import { ApolloProvider } from "react-apollo";
|
||||||
import { render } from "react-dom";
|
import { render } from "react-dom";
|
||||||
|
import ErrorBoundary from "react-error-boundary";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
import { BrowserRouter, Route, Switch } from "react-router-dom";
|
import { BrowserRouter, Route, Switch } from "react-router-dom";
|
||||||
|
|
||||||
|
import useAppState from "@saleor/hooks/useAppState";
|
||||||
import AttributeSection from "./attributes";
|
import AttributeSection from "./attributes";
|
||||||
import { attributeSection } from "./attributes/urls";
|
import { attributeSection } from "./attributes/urls";
|
||||||
import Auth, { getAuthToken, removeAuthToken } from "./auth";
|
import Auth, { getAuthToken, removeAuthToken } from "./auth";
|
||||||
|
@ -20,7 +22,7 @@ import SectionRoute from "./auth/components/SectionRoute";
|
||||||
import { hasPermission } from "./auth/misc";
|
import { hasPermission } from "./auth/misc";
|
||||||
import CategorySection from "./categories";
|
import CategorySection from "./categories";
|
||||||
import CollectionSection from "./collections";
|
import CollectionSection from "./collections";
|
||||||
import { AppProgressProvider } from "./components/AppProgress";
|
import AppLayout from "./components/AppLayout";
|
||||||
import { DateProvider } from "./components/Date";
|
import { DateProvider } from "./components/Date";
|
||||||
import { LocaleProvider } from "./components/Locale";
|
import { LocaleProvider } from "./components/Locale";
|
||||||
import { MessageManager } from "./components/messages";
|
import { MessageManager } from "./components/messages";
|
||||||
|
@ -29,6 +31,7 @@ import ThemeProvider from "./components/Theme";
|
||||||
import { WindowTitle } from "./components/WindowTitle";
|
import { WindowTitle } from "./components/WindowTitle";
|
||||||
import { API_URI, APP_MOUNT_URI } from "./config";
|
import { API_URI, APP_MOUNT_URI } from "./config";
|
||||||
import ConfigurationSection, { createConfigurationMenu } from "./configuration";
|
import ConfigurationSection, { createConfigurationMenu } from "./configuration";
|
||||||
|
import AppStateProvider from "./containers/AppState";
|
||||||
import { CustomerSection } from "./customers";
|
import { CustomerSection } from "./customers";
|
||||||
import DiscountSection from "./discounts";
|
import DiscountSection from "./discounts";
|
||||||
import HomePage from "./home";
|
import HomePage from "./home";
|
||||||
|
@ -119,11 +122,11 @@ const App: React.FC = () => {
|
||||||
<DateProvider>
|
<DateProvider>
|
||||||
<LocaleProvider>
|
<LocaleProvider>
|
||||||
<MessageManager>
|
<MessageManager>
|
||||||
<AppProgressProvider>
|
<AppStateProvider>
|
||||||
<ShopProvider>
|
<ShopProvider>
|
||||||
<Routes />
|
<Routes />
|
||||||
</ShopProvider>
|
</ShopProvider>
|
||||||
</AppProgressProvider>
|
</AppStateProvider>
|
||||||
</MessageManager>
|
</MessageManager>
|
||||||
</LocaleProvider>
|
</LocaleProvider>
|
||||||
</DateProvider>
|
</DateProvider>
|
||||||
|
@ -135,6 +138,7 @@ const App: React.FC = () => {
|
||||||
|
|
||||||
const Routes: React.FC = () => {
|
const Routes: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const [, dispatchAppState] = useAppState();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -148,6 +152,17 @@ const Routes: React.FC = () => {
|
||||||
user
|
user
|
||||||
}) =>
|
}) =>
|
||||||
isAuthenticated && !tokenAuthLoading && !tokenVerifyLoading ? (
|
isAuthenticated && !tokenAuthLoading && !tokenVerifyLoading ? (
|
||||||
|
<AppLayout>
|
||||||
|
<ErrorBoundary
|
||||||
|
onError={() =>
|
||||||
|
dispatchAppState({
|
||||||
|
payload: {
|
||||||
|
error: "unhandled"
|
||||||
|
},
|
||||||
|
type: "displayError"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
<Switch>
|
<Switch>
|
||||||
<SectionRoute exact path="/" component={HomePage} />
|
<SectionRoute exact path="/" component={HomePage} />
|
||||||
<SectionRoute
|
<SectionRoute
|
||||||
|
@ -241,7 +256,9 @@ const Routes: React.FC = () => {
|
||||||
component={ServiceSection}
|
component={ServiceSection}
|
||||||
/>
|
/>
|
||||||
{createConfigurationMenu(intl).filter(menu =>
|
{createConfigurationMenu(intl).filter(menu =>
|
||||||
menu.menuItems.map(item => hasPermission(item.permission, user))
|
menu.menuItems.map(item =>
|
||||||
|
hasPermission(item.permission, user)
|
||||||
|
)
|
||||||
).length > 0 && (
|
).length > 0 && (
|
||||||
<SectionRoute
|
<SectionRoute
|
||||||
exact
|
exact
|
||||||
|
@ -251,6 +268,8 @@ const Routes: React.FC = () => {
|
||||||
)}
|
)}
|
||||||
<Route component={NotFound} />
|
<Route component={NotFound} />
|
||||||
</Switch>
|
</Switch>
|
||||||
|
</ErrorBoundary>
|
||||||
|
</AppLayout>
|
||||||
) : hasToken && tokenVerifyLoading ? (
|
) : hasToken && tokenVerifyLoading ? (
|
||||||
<LoginLoading />
|
<LoginLoading />
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -5,9 +5,7 @@ import React from "react";
|
||||||
import { Query, QueryResult } from "react-apollo";
|
import { Query, QueryResult } from "react-apollo";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import AppProgress from "./components/AppProgress";
|
import useAppState from "./hooks/useAppState";
|
||||||
import NotFoundPage from "./components/NotFoundPage";
|
|
||||||
import useNavigator from "./hooks/useNavigator";
|
|
||||||
import useNotifier from "./hooks/useNotifier";
|
import useNotifier from "./hooks/useNotifier";
|
||||||
import { commonMessages } from "./intl";
|
import { commonMessages } from "./intl";
|
||||||
import { maybe, RequireAtLeastOne } from "./misc";
|
import { maybe, RequireAtLeastOne } from "./misc";
|
||||||
|
@ -68,13 +66,11 @@ export function TypedQuery<TData, TVariables>(
|
||||||
query: DocumentNode
|
query: DocumentNode
|
||||||
): React.FC<TypedQueryInnerProps<TData, TVariables>> {
|
): React.FC<TypedQueryInnerProps<TData, TVariables>> {
|
||||||
return ({ children, displayLoader, skip, variables, require }) => {
|
return ({ children, displayLoader, skip, variables, require }) => {
|
||||||
const navigate = useNavigator();
|
|
||||||
const pushMessage = useNotifier();
|
const pushMessage = useNotifier();
|
||||||
|
const [, dispatchAppState] = useAppState();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppProgress>
|
|
||||||
{({ setProgressState }) => (
|
|
||||||
<Query
|
<Query
|
||||||
fetchPolicy="cache-and-network"
|
fetchPolicy="cache-and-network"
|
||||||
query={query}
|
query={query}
|
||||||
|
@ -116,10 +112,6 @@ export function TypedQuery<TData, TVariables>(
|
||||||
variables: { ...variables, ...extraVariables }
|
variables: { ...variables, ...extraVariables }
|
||||||
});
|
});
|
||||||
|
|
||||||
let childrenOrNotFound = children({
|
|
||||||
...queryData,
|
|
||||||
loadMore
|
|
||||||
});
|
|
||||||
if (
|
if (
|
||||||
!queryData.loading &&
|
!queryData.loading &&
|
||||||
require &&
|
require &&
|
||||||
|
@ -129,28 +121,53 @@ export function TypedQuery<TData, TVariables>(
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
childrenOrNotFound = (
|
dispatchAppState({
|
||||||
<NotFoundPage onBack={() => navigate("/")} />
|
payload: {
|
||||||
);
|
error: "not-found"
|
||||||
|
},
|
||||||
|
type: "displayError"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (displayLoader) {
|
if (displayLoader) {
|
||||||
return (
|
return (
|
||||||
<QueryProgress
|
<QueryProgress
|
||||||
loading={queryData.loading}
|
loading={queryData.loading}
|
||||||
onCompleted={() => setProgressState(false)}
|
onCompleted={() =>
|
||||||
onLoading={() => setProgressState(true)}
|
dispatchAppState({
|
||||||
|
payload: {
|
||||||
|
value: false
|
||||||
|
},
|
||||||
|
type: "displayLoader"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onLoading={() =>
|
||||||
|
dispatchAppState({
|
||||||
|
payload: {
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
type: "displayLoader"
|
||||||
|
})
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{childrenOrNotFound}
|
{children({
|
||||||
|
...queryData,
|
||||||
|
loadMore
|
||||||
|
})}
|
||||||
</QueryProgress>
|
</QueryProgress>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <>{childrenOrNotFound}</>;
|
return (
|
||||||
|
<>
|
||||||
|
{children({
|
||||||
|
...queryData,
|
||||||
|
loadMore
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
</Query>
|
</Query>
|
||||||
)}
|
|
||||||
</AppProgress>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue