saleor-dashboard/src/queries.tsx

165 lines
4.2 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
2019-11-14 14:10:52 +00:00
import useAppState from "./hooks/useAppState";
2019-06-19 14:40:52 +00:00
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;
}
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>> {
2020-02-20 14:18:22 +00:00
return ({ children, displayLoader, skip, variables }) => {
2019-06-19 14:40:52 +00:00
const pushMessage = useNotifier();
2019-11-14 14:10:52 +00:00
const [, dispatchAppState] = useAppState();
2019-08-29 10:55:56 +00:00
const intl = useIntl();
2019-06-19 14:40:52 +00:00
return (
2019-11-14 14:10:52 +00:00
<Query
fetchPolicy="cache-and-network"
query={query}
variables={variables}
skip={skip}
context={{ useBatching: true }}
errorPolicy="all"
>
{(queryData: QueryResult<TData, TVariables>) => {
if (queryData.error) {
if (
!queryData.error.graphQLErrors.every(
err =>
maybe(() => err.extensions.exception.code) ===
"PermissionDenied"
)
) {
pushMessage({
text: intl.formatMessage(commonMessages.somethingWentWrong)
});
}
}
const loadMore = (
mergeFunc: (
previousResults: TData,
fetchMoreResult: TData
) => TData,
extraVariables: RequireAtLeastOne<TVariables>
) =>
queryData.fetchMore({
query,
updateQuery: (previousResults, { fetchMoreResult }) => {
if (!fetchMoreResult) {
return previousResults;
2019-10-08 13:31:33 +00:00
}
2019-11-14 14:10:52 +00:00
return mergeFunc(previousResults, fetchMoreResult);
},
variables: { ...variables, ...extraVariables }
});
2019-06-19 14:40:52 +00:00
2019-11-14 14:10:52 +00:00
if (displayLoader) {
return (
<QueryProgress
loading={queryData.loading}
onCompleted={() =>
dispatchAppState({
payload: {
value: false
},
type: "displayLoader"
})
}
onLoading={() =>
dispatchAppState({
payload: {
value: true
},
type: "displayLoader"
})
}
>
{children({
...queryData,
loadMore
})}
</QueryProgress>
);
}
2019-06-19 14:40:52 +00:00
2019-11-14 14:10:52 +00:00
return (
<>
{children({
2019-08-12 11:48:09 +00:00
...queryData,
loadMore
2019-11-14 14:10:52 +00:00
})}
</>
);
}}
</Query>
2019-06-19 14:40:52 +00:00
);
};
}
export const pageInfoFragment = gql`
fragment PageInfoFragment on PageInfo {
endCursor
hasNextPage
hasPreviousPage
startCursor
}
`;