saleor-dashboard/src/queries.tsx

166 lines
4.7 KiB
TypeScript
Raw Normal View History

2019-08-12 11:48:09 +00:00
import { ApolloQueryResult } from "apollo-client";
2019-06-19 14:40:52 +00:00
import { DocumentNode } from "graphql";
import gql from "graphql-tag";
2019-08-09 10:26:22 +00:00
import React from "react";
2019-06-19 14:40:52 +00:00
import { Query, QueryResult } from "react-apollo";
2019-08-29 10:55:56 +00:00
import { useIntl } from "react-intl";
2019-06-19 14:40:52 +00:00
import AppProgress from "./components/AppProgress";
2019-11-13 16:52:46 +00:00
import NotFoundPage from "./components/NotFoundPage";
2019-06-19 14:40:52 +00:00
import useNavigator from "./hooks/useNavigator";
import useNotifier from "./hooks/useNotifier";
2019-09-04 10:28:04 +00:00
import { commonMessages } from "./intl";
2019-10-08 13:31:33 +00:00
import { maybe, RequireAtLeastOne } from "./misc";
2019-06-19 14:40:52 +00:00
export interface LoadMore<TData, TVariables> {
loadMore: (
mergeFunc: (prev: TData, next: TData) => TData,
2019-10-15 12:17:35 +00:00
extraVariables: Partial<TVariables>
2019-06-19 14:40:52 +00:00
) => Promise<ApolloQueryResult<TData>>;
}
export type TypedQueryResult<TData, TVariables> = QueryResult<
TData,
TVariables
> &
LoadMore<TData, TVariables>;
export interface TypedQueryInnerProps<TData, TVariables> {
children: (result: TypedQueryResult<TData, TVariables>) => React.ReactNode;
displayLoader?: boolean;
skip?: boolean;
variables?: TVariables;
require?: Array<keyof TData>;
}
interface QueryProgressProps {
loading: boolean;
onLoading: () => void;
onCompleted: () => void;
}
class QueryProgress extends React.Component<QueryProgressProps, {}> {
componentDidMount() {
const { loading, onLoading } = this.props;
if (loading) {
onLoading();
}
}
componentDidUpdate(prevProps) {
const { loading, onLoading, onCompleted } = this.props;
if (prevProps.loading !== loading) {
if (loading) {
onLoading();
} else {
onCompleted();
}
}
}
render() {
return this.props.children;
}
}
2019-08-12 11:48:09 +00:00
// For some reason Query returns () => Element instead of () => ReactNode
2019-06-19 14:40:52 +00:00
export function TypedQuery<TData, TVariables>(
query: DocumentNode
): React.FC<TypedQueryInnerProps<TData, TVariables>> {
2019-08-12 11:48:09 +00:00
return ({ children, displayLoader, skip, variables, require }) => {
2019-06-19 14:40:52 +00:00
const navigate = useNavigator();
const pushMessage = useNotifier();
2019-08-29 10:55:56 +00:00
const intl = useIntl();
2019-06-19 14:40:52 +00:00
return (
<AppProgress>
2019-08-12 11:48:09 +00:00
{({ setProgressState }) => (
<Query
fetchPolicy="cache-and-network"
query={query}
variables={variables}
skip={skip}
context={{ useBatching: true }}
2019-10-08 13:31:33 +00:00
errorPolicy="all"
2019-08-12 11:48:09 +00:00
>
2019-10-24 12:10:00 +00:00
{(queryData: QueryResult<TData, TVariables>) => {
2019-08-12 11:48:09 +00:00
if (queryData.error) {
2019-10-08 13:31:33 +00:00
if (
!queryData.error.graphQLErrors.every(
err =>
maybe(() => err.extensions.exception.code) ===
"PermissionDenied"
)
) {
pushMessage({
text: intl.formatMessage(commonMessages.somethingWentWrong)
});
}
2019-08-12 11:48:09 +00:00
}
2019-06-19 14:40:52 +00:00
2019-08-12 11:48:09 +00:00
const loadMore = (
mergeFunc: (
previousResults: TData,
fetchMoreResult: TData
) => TData,
extraVariables: RequireAtLeastOne<TVariables>
) =>
queryData.fetchMore({
query,
updateQuery: (previousResults, { fetchMoreResult }) => {
if (!fetchMoreResult) {
return previousResults;
}
return mergeFunc(previousResults, fetchMoreResult);
},
variables: { ...variables, ...extraVariables }
2019-06-19 14:40:52 +00:00
});
2019-08-12 11:48:09 +00:00
let childrenOrNotFound = children({
...queryData,
loadMore
});
if (
!queryData.loading &&
require &&
queryData.data &&
!require.reduce(
(acc, key) => acc && queryData.data[key] !== null,
true
)
) {
2019-11-13 16:52:46 +00:00
childrenOrNotFound = (
<NotFoundPage onBack={() => navigate("/")} />
);
2019-08-12 11:48:09 +00:00
}
if (displayLoader) {
return (
<QueryProgress
loading={queryData.loading}
onCompleted={() => setProgressState(false)}
onLoading={() => setProgressState(true)}
>
{childrenOrNotFound}
</QueryProgress>
);
}
2019-06-19 14:40:52 +00:00
2019-08-12 11:48:09 +00:00
return <>{childrenOrNotFound}</>;
}}
</Query>
)}
2019-06-19 14:40:52 +00:00
</AppProgress>
);
};
}
export const pageInfoFragment = gql`
fragment PageInfoFragment on PageInfo {
endCursor
hasNextPage
hasPreviousPage
startCursor
}
`;