import { ApolloError, MutationUpdaterFn } from "apollo-client"; import { DocumentNode } from "graphql"; import React from "react"; import { Mutation, MutationFunction, MutationResult } from "react-apollo"; import { useIntl } from "react-intl"; import useNotifier from "./hooks/useNotifier"; import { commonMessages } from "./intl"; import { maybe, getMutationStatus } from "./misc"; import { MutationResultAdditionalProps } from "./types"; import { isJwtError } from "./auth/errors"; import useUser from "./hooks/useUser"; export interface TypedMutationInnerProps { children: ( mutateFn: MutationFunction, result: MutationResult & MutationResultAdditionalProps ) => React.ReactNode; onCompleted?: (data: TData) => void; onError?: (error: ApolloError) => void; variables?: TVariables; } // For some reason Mutation returns () => Element instead of () => ReactNode export function TypedMutation( mutation: DocumentNode, update?: MutationUpdaterFn ) { return (props: TypedMutationInnerProps) => { const notify = useNotifier(); const intl = useIntl(); const user = useUser(); const { children, onCompleted, onError, variables } = props; return ( { if ( maybe( () => err.graphQLErrors[0].extensions.exception.code === "ReadOnlyException" ) ) { notify({ text: intl.formatMessage(commonMessages.readOnly) }); } else if (err.graphQLErrors.every(isJwtError)) { user.logout(); notify({ text: intl.formatMessage(commonMessages.sessionExpired) }); } else { notify({ text: intl.formatMessage(commonMessages.somethingWentWrong) }); } if (onError) { onError(err); } }} variables={variables} update={update} > {(mutateFn, result) => ( <> {children(mutateFn, { ...result, status: getMutationStatus(result) })} )} ); }; }