saleor-dashboard/src/hooks/makeQuery.ts

130 lines
3.5 KiB
TypeScript
Raw Normal View History

2020-07-24 09:17:25 +00:00
import { handleQueryAuthError } from "@saleor/auth";
import { RequireAtLeastOne } from "@saleor/misc";
import { ApolloQueryResult } from "apollo-client";
2019-11-14 14:37:32 +00:00
import { DocumentNode } from "graphql";
import { useEffect } from "react";
import { QueryResult, useQuery as useBaseQuery } from "react-apollo";
import { useIntl } from "react-intl";
import { User_userPermissions } from "../fragments/types/User";
import { PrefixedPermissions } from "../types/extendedTypes";
import { PermissionEnum } from "../types/globalTypes";
2019-11-14 14:37:32 +00:00
import useAppState from "./useAppState";
import useNotifier from "./useNotifier";
2020-05-07 11:04:15 +00:00
import useUser from "./useUser";
2019-11-14 14:37:32 +00:00
const getPermissionKey = (permission: string) =>
`PERMISSION_${permission}` as PrefixedPermissions;
const allPermissions = Object.keys(PermissionEnum).reduce(
(prev, code) => ({
...prev,
[getPermissionKey(code)]: false
}),
{} as Record<PrefixedPermissions, boolean>
);
const getUserPermissions = (userPermissions: User_userPermissions[]) =>
userPermissions.reduce(
(prev, permission) => ({
...prev,
[getPermissionKey(permission.code)]: true
}),
{} as Record<PrefixedPermissions, boolean>
);
2019-11-14 14:37:32 +00:00
export interface LoadMore<TData, TVariables> {
loadMore: (
mergeFunc: (prev: TData, next: TData) => TData,
extraVariables: Partial<TVariables>
) => Promise<ApolloQueryResult<TData>>;
}
2019-11-19 11:31:32 +00:00
export type UseQueryResult<TData, TVariables> = QueryResult<TData, TVariables> &
2019-11-14 14:37:32 +00:00
LoadMore<TData, TVariables>;
2020-02-20 14:18:22 +00:00
type UseQueryOpts<TVariables> = Partial<{
2019-11-14 14:37:32 +00:00
displayLoader: boolean;
skip: boolean;
variables: TVariables;
}>;
type UseQueryHook<TData, TVariables> = (
opts: UseQueryOpts<Omit<TVariables, PrefixedPermissions>>
2019-11-19 11:31:32 +00:00
) => UseQueryResult<TData, TVariables>;
2019-11-14 14:37:32 +00:00
function makeQuery<TData, TVariables>(
query: DocumentNode
): UseQueryHook<TData, TVariables> {
2019-11-19 15:01:54 +00:00
function useQuery({
2019-11-14 14:37:32 +00:00
displayLoader,
skip,
variables
2020-02-20 14:18:22 +00:00
}: UseQueryOpts<TVariables>): UseQueryResult<TData, TVariables> {
2019-11-14 14:37:32 +00:00
const notify = useNotifier();
const intl = useIntl();
const [, dispatchAppState] = useAppState();
2020-05-07 11:04:15 +00:00
const user = useUser();
const userPermissions = getUserPermissions(
user.user?.userPermissions || []
);
const variablesWithPermissions = {
...variables,
...allPermissions,
...userPermissions
};
2020-05-07 11:04:15 +00:00
2019-11-14 14:37:32 +00:00
const queryData = useBaseQuery(query, {
context: {
useBatching: true
},
errorPolicy: "all",
fetchPolicy: "cache-and-network",
2020-07-24 09:17:25 +00:00
onError: error =>
handleQueryAuthError(
error,
notify,
user.tokenRefresh,
user.logout,
intl
),
2019-11-14 14:37:32 +00:00
skip,
variables: variablesWithPermissions
2019-11-14 14:37:32 +00:00
});
useEffect(() => {
if (displayLoader) {
dispatchAppState({
payload: {
value: queryData.loading
},
type: "displayLoader"
});
}
}, [queryData.loading]);
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: { ...variablesWithPermissions, ...extraVariables }
2019-11-14 14:37:32 +00:00
});
return {
...queryData,
loadMore
};
}
return useQuery;
}
export default makeQuery;