@apollo/client#ApolloError TypeScript Examples
The following examples show how to use
@apollo/client#ApolloError.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: entityRestore.ts From jmix-frontend with Apache License 2.0 | 6 votes |
export function useEntityRestore(restoreEntitesVariables: RestoreEntitiesVariables, onCompleteCallback?: () => Promise<any>) {
const intl = useIntl();
const {className, ids} = restoreEntitesVariables;
const [restoreEntities] = useMutation<RestoreData, RestoreEntitiesVariables>(
gqlRestoreEntity,
{
fetchPolicy: "no-cache"
}
);
const restore = () => {
restoreEntities({
variables: {
className,
ids
}
}).then(({data}) => {
if(data != null) {
restoreEntitesHandler(data, intl, onCompleteCallback);
}
}).catch(({message}: ApolloError) => {
restoreEntitesErrorHandler(message, intl);
})
};
return restore;
}
Example #2
Source File: PaymentsPageContent.tsx From condo with MIT License | 6 votes |
function renderError (error: ApolloError | string) {
if (isString(error)) {
return (
<BasicEmptyListView>
<Typography.Title level={3}>
{error}
</Typography.Title>
</BasicEmptyListView>
)
}
return (
<BasicEmptyListView>
<Typography.Title level={3}>
{error.name}
</Typography.Title>
<Typography.Text>
{error.message}
</Typography.Text>
</BasicEmptyListView>
)
}
Example #3
Source File: extractBeanValidationErrors.ts From jmix-frontend with Apache License 2.0 | 6 votes |
export function extractBeanValidationErrors(apolloError?: ApolloError): JmixServerValidationErrors | undefined {
if (apolloError == null) {
return undefined;
}
const constraintViolations = apolloError
?.graphQLErrors
?.[0]
?.extensions
?.constraintViolations;
if (constraintViolations == null) {
return undefined;
}
const fieldErrors = new Map<string, string[]>();
const globalErrors: string[] = [];
constraintViolations.forEach((violation: JmixConstraintViolation) => {
// Global error, e.g. cross-validation
if (violation.path === '') {
globalErrors.push(violation.message);
return;
}
// Field error
const messages = fieldErrors.get(violation.path) ?? [];
messages.push(violation.message);
fieldErrors.set(violation.path, messages);
});
return {
fieldErrors,
globalErrors
};
}
Example #4
Source File: useQuery.ts From lexicon with MIT License | 6 votes |
export function useQuery<TData, TVariables = OperationVariables>(
query: DocumentNode,
options?: QueryHookOptions<TData, TVariables>,
errorAlert: ErrorAlertOptionType = 'SHOW_ALERT',
): QueryResult<TData, TVariables> {
const onErrorDefault = (error: ApolloError) => {
errorHandlerAlert(error);
};
const { fetchPolicy = 'cache-and-network', ...others } = options ?? {};
const {
onError = errorAlert === 'SHOW_ALERT' ? onErrorDefault : undefined,
nextFetchPolicy = fetchPolicy === 'cache-and-network'
? 'cache-first'
: undefined,
notifyOnNetworkStatusChange = fetchPolicy === 'network-only',
...otherOptions
} = others;
let queryResult = useQueryBase<TData, TVariables>(query, {
fetchPolicy,
nextFetchPolicy,
notifyOnNetworkStatusChange,
onError,
...otherOptions,
});
return queryResult;
}
Example #5
Source File: useMutation.ts From lexicon with MIT License | 6 votes |
export function useMutation<TData, TVariables = OperationVariables>(
query: DocumentNode,
options?: MutationHookOptions<TData, TVariables>,
errorAlert: ErrorAlertOptionType = 'SHOW_ALERT',
): MutationTuple<TData, TVariables> {
const { navigate } = useNavigation<TabNavProp<'Home'>>();
const onErrorDefault = (error: ApolloError) => {
errorHandlerAlert(error, navigate);
};
const { ...others } = options ?? {};
const {
onError = errorAlert === 'SHOW_ALERT' ? onErrorDefault : undefined,
...otherOptions
} = others;
let [mutationFunction, mutationResult] = useMutationBase<TData, TVariables>(
query,
{
onError,
...otherOptions,
},
);
return [mutationFunction, mutationResult];
}
Example #6
Source File: useLazyQuery.ts From lexicon with MIT License | 6 votes |
export function useLazyQuery<TData, TVariables = OperationVariables>(
query: DocumentNode,
options?: LazyQueryHookOptions<TData, TVariables>,
errorAlert: ErrorAlertOptionType = 'SHOW_ALERT',
): QueryTuple<TData, TVariables> {
const onErrorDefault = (error: ApolloError) => {
errorHandlerAlert(error);
};
const { fetchPolicy = 'cache-and-network', ...others } = options ?? {};
const {
onError = errorAlert === 'SHOW_ALERT' ? onErrorDefault : undefined,
nextFetchPolicy = fetchPolicy === 'cache-and-network'
? 'cache-first'
: undefined,
notifyOnNetworkStatusChange = fetchPolicy === 'network-only',
...otherOptions
} = others;
let [queryFunction, queryResult] = useLazyQueryBase<TData, TVariables>(
query,
{
fetchPolicy,
nextFetchPolicy,
notifyOnNetworkStatusChange,
onError,
...otherOptions,
},
);
return [queryFunction, queryResult];
}
Example #7
Source File: errorHandler.ts From lexicon with MIT License | 6 votes |
export function errorHandler(
error: ApolloError,
isFiltered = false,
isTranslated = true,
): string {
let errorMsg: string;
if (error.networkError) {
errorMsg = 'Please connect to a network';
} else if (error.message === 'Not found or private.') {
errorMsg = 'Not found or private';
} else {
errorMsg = isFiltered
? 'Something unexpected happened. Please try again'
: error.message;
}
return isTranslated ? t('{errorMsg}', { errorMsg }) : errorMsg;
}
Example #8
Source File: error.ts From amplication with Apache License 2.0 | 6 votes |
export function formatError(error: Error | undefined): string | undefined {
if (error === undefined) {
return undefined;
}
if ((error as ApolloError).graphQLErrors) {
// show the first error
/**@todo: return multiple errors */
const [gqlError] = (error as ApolloError).graphQLErrors;
if (gqlError && gqlError.message) {
return gqlError.message;
}
}
return String(error);
}
Example #9
Source File: base-user-apollo.service.ts From svvs with MIT License | 6 votes |
// eslint-disable-next-line @typescript-eslint/no-unused-vars
loadUser(queryParams: Record<string, unknown> = {}): TApolloResponse<IUser> {
return this.apollo
.query<{ user: IUser}>( {query: UserQieries.usersRequest.query} )
.pipe(
map(result => extractApolloResponse(result, UserQieries.usersRequest.keys)),
catchError((error: ApolloError) => throwError(error))
)
}
Example #10
Source File: persistEntity.ts From jmix-frontend with Apache License 2.0 | 5 votes |
export function persistEntity<
TEntity = unknown,
TData extends Record<string, any> = Record<string, any>,
TVariables = unknown
>(
upsertItem: GraphQLMutationFn<TData, TVariables>,
upsertInputName: string,
updatedEntity: TEntity,
updateResultName: string,
listQueryName: string,
entityName: string,
isNewEntity: boolean,
goToParentScreen: () => void,
metadata: Metadata,
persistEntityCallbacks?: PersistEntityCallbacks
) {
upsertItem({
variables: {
[upsertInputName]: jmixFront_to_jmixGraphQL(updatedEntity, entityName, metadata)
} as any,
update(cache: ApolloCache<TData>, result: FetchResult<TData>) {
const updateResult = result.data?.[updateResultName];
// Reflect the update in Apollo cache
cache.modify({
fields: {
[listQueryName](existingRefs = []) {
const updatedItemRef = cache.writeFragment({
id: `${entityName}:${updateResult.id}`,
data: updatedEntity,
fragment: gql(`
fragment New_${dollarsToUnderscores(entityName)} on ${dollarsToUnderscores(entityName)} {
id
type
}
`)
});
return [...existingRefs, updatedItemRef];
}
}
});
}
}).then(action(({errors}: FetchResult<TData, Record<string, any>, Record<string, any>>) => {
if (errors == null || errors.length === 0) {
isNewEntity ? persistEntityCallbacks?.onCreate?.() : persistEntityCallbacks?.onEdit?.()
goToParentScreen();
} else {
console.error(errors);
persistEntityCallbacks?.onError?.();
}
}))
.catch((e: Error | ApolloError) => {
const constraintViolations = (e as ApolloError)
?.graphQLErrors
?.[0]
?.extensions
?.constraintViolations;
if (constraintViolations != null) {
return; // Bean validation error
}
console.error(e);
persistEntityCallbacks?.onError?.();
});
}
Example #11
Source File: errorHandler.ts From lexicon with MIT License | 5 votes |
export function errorHandlerAlert(
error: ApolloError | string,
navigate?: Function,
isFiltered = false,
) {
let errorMsg;
if (typeof error === 'string') {
errorMsg = error;
} else {
errorMsg = errorHandler(error, isFiltered, false);
}
let errorMsgi8n = t('{errorMsg}', { errorMsg });
switch (errorMsg) {
case LoginError:
Alert.alert(t('Please Log In'), errorMsgi8n, [
{ text: t('Close') },
{
text: t('Log In'),
onPress: () => (navigate ? navigate('Login') : undefined),
},
]);
break;
case UsedTitleError:
Alert.alert(
t('Title Already Exists'),
t(
'A Post with this title has already been created. Please use a different title.',
),
[{ text: t('Got it') }],
);
break;
case EditPostError:
Alert.alert(t('Unable to Edit'), errorMsgi8n, [{ text: t('Got it') }]);
break;
case ChangeUsernameError:
Alert.alert(t('Username Unavailable'), errorMsgi8n, [
{ text: t('Got it') },
]);
break;
default:
Alert.alert(t('Error'), errorMsgi8n, [{ text: t('Got it') }]);
}
}
Example #12
Source File: ErrorText.tsx From graphql-ts-client with MIT License | 5 votes |
ErrorText: FC<{
error: ApolloError
}> = memo(({error}) => {
const serverErrors = (error.networkError as any).result?.errors as {readonly message: string}[] | undefined;
return (
<div className={ERROR_CSS}>
<div className={FORM_CSS}>
{
serverErrors &&
<ul>
{
serverErrors.map((serverError, index) =>
<li key={index}>{serverError.message}</li>
)
}
</ul>
}
{
serverErrors === undefined && error.networkError &&
<div>
<div>Network error</div>
<div>{error.networkError.message}</div>
</div>
}
{
error.clientErrors.length !== 0 &&
<div>
<div>Client errors</div>
<div>
<ul>
{
error.clientErrors.map(ce =>
<li>{ce.message}</li>
)
}
</ul>
</div>
</div>
}
{
error.graphQLErrors.length !== 0 &&
<div>
<div>GraphQL errors</div>
<div>
<ul>
{
error.graphQLErrors.map(ce =>
<li>{ce.message}</li>
)
}
</ul>
</div>
</div>
}
</div>
</div>
);
})
Example #13
Source File: users-facade.interface.ts From svvs with MIT License | 5 votes |
/**
* User load error observer
*/
userLoadFailure$: Observable<ApolloError>
Example #14
Source File: users.actions.ts From svvs with MIT License | 5 votes |
loadUserFailure = createAction('[Users] Load User Failure', payload<ApolloError>())
Example #15
Source File: base-auth-apollo.service.ts From svvs with MIT License | 5 votes |
signOut(queryParams?: Record<string, unknown>): TApolloResponse<void> {
return this.apollo
.query<{logout: boolean}>({query: AuthQueries.logoutRequest.query})
.pipe(
map(result => null),
catchError((error: ApolloError) => throwError(error))
)
}
Example #16
Source File: base-auth-apollo.service.ts From svvs with MIT License | 5 votes |
signIn(payload: ISignAuthPayload, queryParams: Record<string, unknown> = {}): TApolloResponse<ISignAuthResponse> {
return this.apollo
.query<{user: IUser}>({query: AuthQueries.loginRequest.query, variables: payload})
.pipe(
map(result => extractApolloResponse(result, AuthQueries.loginRequest.keys)),
catchError((error: ApolloError) => throwError(error))
)
}
Example #17
Source File: auth-facade.interface.ts From svvs with MIT License | 5 votes |
/**
* SignOut error observer
*/
signOutError$: Observable<ApolloError>
Example #18
Source File: auth-facade.interface.ts From svvs with MIT License | 5 votes |
/**
* SignInError observer
*/
signInError$: Observable<ApolloError>
Example #19
Source File: auth.actions.ts From svvs with MIT License | 5 votes |
signOutFailure = createAction('[Auth] SignOut error', payload<ApolloError>())
Example #20
Source File: auth.actions.ts From svvs with MIT License | 5 votes |
signInFailure = createAction('[Auth] SignIn error', payload<ApolloError>())
Example #21
Source File: extractBeanValidationErrors.ts From jmix-frontend with Apache License 2.0 | 5 votes |
export function useExtractBeanValidationErrors(apolloError?: ApolloError): JmixServerValidationErrors | undefined {
return useMemo(() => extractBeanValidationErrors(apolloError), [apolloError]);
}
Example #22
Source File: FormLayout.tsx From glific-frontend with GNU Affero General Public License v3.0 | 4 votes |
FormLayout: React.SFC<FormLayoutProps> = ({
match,
deleteItemQuery,
states,
setStates,
validationSchema,
listItemName,
dialogMessage,
formFields,
redirectionLink,
listItem,
getItemQuery,
createItemQuery,
updateItemQuery,
additionalQuery = null,
defaultAttribute = null,
additionalAction,
icon,
idType = 'id',
additionalState,
title,
linkParameter = null,
cancelLink = null,
languageSupport = true,
setPayload,
advanceSearch,
cancelAction,
button = 'Save',
type,
afterSave,
afterDelete,
refetchQueries,
redirect = true,
getLanguageId,
backLinkButton,
isAttachment = false,
getMediaId,
customStyles = null,
customHandler,
copyNotification = '',
showPreviewButton = false,
onPreviewClick = () => {},
getQueryFetchPolicy = 'cache-first',
saveOnPageChange = true,
}: FormLayoutProps) => {
const [showDialog, setShowDialog] = useState(false);
const [formSubmitted, setFormSubmitted] = useState(false);
const [languageId, setLanguageId] = useState('');
const [formCancelled, setFormCancelled] = useState(false);
const [action, setAction] = useState(false);
const [link, setLink] = useState(undefined);
const [deleted, setDeleted] = useState(false);
const [saveClick, onSaveClick] = useState(false);
const [isLoadedData, setIsLoadedData] = useState(false);
const [customError, setCustomError] = useState<any>(null);
const { t } = useTranslation();
const capitalListItemName = listItemName[0].toUpperCase() + listItemName.slice(1);
let item: any = null;
const itemId = match.params.id ? match.params.id : false;
let variables: any = itemId ? { [idType]: itemId } : false;
const [deleteItem] = useMutation(deleteItemQuery, {
onCompleted: () => {
setNotification(`${capitalListItemName} deleted successfully`);
setDeleted(true);
},
awaitRefetchQueries: true,
refetchQueries: [
{
query: SEARCH_QUERY,
variables: SEARCH_QUERY_VARIABLES,
},
],
});
// get the organization for current user and have languages option set to that.
const organization = useQuery(USER_LANGUAGES, {
onCompleted: (data: any) => {
if (!itemId) {
setLanguageId(data.currentUser.user.organization.defaultLanguage.id);
}
},
});
if (listItem === 'credential') {
variables = match.params.shortcode ? { shortcode: match.params.shortcode } : false;
}
const { loading, error } = useQuery(getItemQuery, {
variables,
skip: !itemId,
fetchPolicy: getQueryFetchPolicy,
onCompleted: (data) => {
if (data) {
item = data[listItem] ? data[listItem][listItem] : data[Object.keys(data)[0]][listItem];
if (item) {
setIsLoadedData(true);
setLink(data[listItem] ? data[listItem][listItem][linkParameter] : item.linkParameter);
setStates(item);
setLanguageId(languageSupport ? item.language.id : null);
}
}
},
});
const camelCaseItem = listItem[0].toUpperCase() + listItem.slice(1);
const [updateItem] = useMutation(updateItemQuery, {
onCompleted: (data) => {
let itemUpdatedObject: any = Object.keys(data)[0];
itemUpdatedObject = data[itemUpdatedObject];
const updatedItem = itemUpdatedObject[listItem];
const { errors } = itemUpdatedObject;
if (errors) {
if (customHandler) {
customHandler(errors);
} else {
setErrorMessage(errors[0]);
}
} else if (updatedItem && typeof updatedItem.isValid === 'boolean' && !updatedItem.isValid) {
if (customError) {
// this is a custom error for extensions. We need to move this out of this component
const codeErrors = { code: 'Failed to compile code. Please check again' };
customError.setErrors(codeErrors);
}
} else {
if (type === 'copy') setLink(updatedItem[linkParameter]);
if (additionalQuery) {
additionalQuery(itemId);
}
if (saveOnPageChange || saveClick) {
setFormSubmitted(true);
// display successful message after update
let message = `${capitalListItemName} edited successfully!`;
if (type === 'copy') {
message = copyNotification;
}
setNotification(message);
} else {
setNotification('Your changes have been autosaved');
}
// emit data after save
if (afterSave) {
afterSave(data, saveClick);
}
}
onSaveClick(false);
},
onError: (e: ApolloError) => {
onSaveClick(false);
setErrorMessage(e);
return null;
},
refetchQueries: () => {
if (refetchQueries)
return refetchQueries.map((refetchQuery: any) => ({
query: refetchQuery.query,
variables: refetchQuery.variables,
}));
return [];
},
});
const [createItem] = useMutation(createItemQuery, {
onCompleted: (data) => {
let itemCreatedObject: any = `create${camelCaseItem}`;
itemCreatedObject = data[itemCreatedObject];
const itemCreated = itemCreatedObject[listItem];
const { errors } = itemCreatedObject;
if (errors) {
if (customHandler) {
customHandler(errors);
} else {
setErrorMessage(errors[0]);
}
} else if (itemCreated && typeof itemCreated.isValid === 'boolean' && !itemCreated.isValid) {
if (customError) {
const codeErrors = { code: 'Failed to compile code. Please check again' };
customError.setErrors(codeErrors);
}
} else {
if (additionalQuery) {
additionalQuery(itemCreated.id);
}
if (!itemId) setLink(itemCreated[linkParameter]);
if (saveOnPageChange || saveClick) {
setFormSubmitted(true);
// display successful message after create
setNotification(`${capitalListItemName} created successfully!`);
} else {
setNotification('Your changes have been autosaved');
}
// emit data after save
if (afterSave) {
afterSave(data, saveClick);
}
}
setIsLoadedData(true);
onSaveClick(false);
},
refetchQueries: () => {
if (refetchQueries)
return refetchQueries.map((refetchQuery: any) => ({
query: refetchQuery.query,
variables: refetchQuery.variables,
}));
return [];
},
onError: (e: ApolloError) => {
onSaveClick(false);
setErrorMessage(e);
return null;
},
});
if (loading) return <Loading />;
if (error) {
setErrorMessage(error);
return null;
}
const performTask = (payload: any) => {
if (itemId) {
if (isLoadedData) {
let idKey = idType;
let idVal = itemId;
/**
* When idType is organizationId
* We are updating billing for given organization
* since match.params.id is orgId we want billing
* id to update billing details
*/
const payloadBody = { ...payload };
if (idType === 'organizationId') {
idKey = 'id';
idVal = payloadBody.billingId;
// Clearning unnecessary fields
delete payloadBody.billingId;
}
updateItem({
variables: {
[idKey]: idVal,
input: payloadBody,
},
});
} else {
createItem({
variables: {
input: payload,
},
});
}
} else {
createItem({
variables: {
input: payload,
},
});
}
};
const saveHandler = ({ languageId: languageIdValue, ...itemData }: any) => {
let payload = {
...itemData,
...defaultAttribute,
};
payload = languageSupport
? { ...payload, languageId: Number(languageIdValue) }
: { ...payload };
// create custom payload for searches
if (setPayload) {
payload = setPayload(payload);
if (advanceSearch) {
const data = advanceSearch(payload);
if (data && data.heading && type === 'search') return;
}
}
// remove fields from the payload that marked as skipPayload = true
formFields.forEach((field: any) => {
if (field.additionalState) {
additionalState(payload[field.additionalState]);
}
if (field.convertToWhatsApp && payload[field.name]) {
payload[field.name] = getPlainTextFromEditor(payload[field.name]);
}
if (field.skipPayload) {
delete payload[field.name];
}
});
// for template create media for attachment
if (isAttachment && payload.type !== 'TEXT' && payload.type) {
getMediaId(payload)
.then((data: any) => {
if (data) {
const payloadCopy = payload;
delete payloadCopy.attachmentURL;
payloadCopy.messageMediaId = parseInt(data.data.createMessageMedia.messageMedia.id, 10);
performTask(payloadCopy);
}
})
.catch((e: any) => {
setErrorMessage(e);
});
} else {
performTask(payload);
}
};
const cancelHandler = () => {
// for chat screen searches
if (type === 'search' || type === 'saveSearch') {
advanceSearch('cancel');
return;
}
if (cancelAction) {
cancelAction();
}
setFormCancelled(true);
};
if (formSubmitted && redirect) {
return <Redirect to={action ? `${additionalAction.link}/${link}` : `/${redirectionLink}`} />;
}
if (deleted) {
if (afterDelete) {
return <Redirect to={afterDelete.link} />;
}
return <Redirect to={`/${redirectionLink}`} />;
}
if (formCancelled) {
return <Redirect to={cancelLink ? `/${cancelLink}` : `/${redirectionLink}`} />;
}
const validateLanguage = (value: any) => {
if (value && getLanguageId) {
getLanguageId(value);
}
};
const languageOptions = organization.data
? organization.data.currentUser.user.organization.activeLanguages.slice()
: [];
// sort languages by their name
languageOptions.sort((first: any, second: any) => (first.label > second.label ? 1 : -1));
const language = languageSupport
? {
component: Dropdown,
name: 'languageId',
placeholder: t('Language'),
options: languageOptions,
validate: validateLanguage,
helperText: t('For more languages check settings or connect with your admin'),
}
: null;
const formFieldItems = languageSupport ? [...formFields, language] : formFields;
const deleteButton =
itemId && !type ? (
<Button
variant="contained"
color="secondary"
className={styles.DeleteButton}
onClick={() => setShowDialog(true)}
>
<DeleteIcon className={styles.DeleteIcon} />
Remove
</Button>
) : null;
const onSaveButtonClick = (errors: any) => {
if (Object.keys(errors).length > 0) {
return;
}
onSaveClick(true);
};
const form = (
<Formik
enableReinitialize
validateOnMount
initialValues={{
...states,
languageId,
}}
validationSchema={validationSchema}
onSubmit={(itemData, { setErrors }) => {
// when you want to show custom error on form field and error message is not coming from api
setCustomError({ setErrors });
saveHandler(itemData);
}}
>
{({ errors, submitForm }) => (
<Form className={[styles.Form, customStyles].join(' ')} data-testid="formLayout">
{formFieldItems.map((field, index) => {
const key = index;
if (field.skip) {
return null;
}
return (
<React.Fragment key={key}>
{field.label && (
<Typography variant="h5" className={styles.FieldLabel}>
{field.label}
</Typography>
)}
<Field key={key} {...field} onSubmit={submitForm} />
</React.Fragment>
);
})}
<div className={styles.Buttons}>
<Button
variant="contained"
color="primary"
onClick={() => {
onSaveButtonClick(errors);
submitForm();
}}
className={styles.Button}
data-testid="submitActionButton"
loading={saveClick}
>
{button}
</Button>
{additionalAction ? (
<Button
variant="outlined"
color="primary"
onClick={() => {
submitForm();
setAction(true);
}}
data-testid="additionalActionButton"
>
{additionalAction.label}
</Button>
) : null}
<Button
variant="contained"
color="default"
onClick={cancelHandler}
data-testid="cancelActionButton"
>
{t('Cancel')}
</Button>
{showPreviewButton && (
<Button
variant="contained"
color="primary"
onClick={onPreviewClick}
className={styles.Button}
data-testid="previewButton"
>
Preview
</Button>
)}
{deleteButton}
</div>
</Form>
)}
</Formik>
);
const handleDeleteItem = () => {
deleteItem({ variables: { id: itemId } });
};
let dialogBox;
if (showDialog) {
dialogBox = (
<DialogBox
title={`Are you sure you want to delete the ${listItemName}?`}
handleOk={handleDeleteItem}
handleCancel={() => setShowDialog(false)}
colorOk="secondary"
alignButtons="center"
contentAlign="center"
>
{dialogMessage}
</DialogBox>
);
}
let formTitle = '';
// set title if there is a title
if (title) {
formTitle = title;
} else if (type === 'copy') {
formTitle = `Copy ${listItemName}`; // case when copying an item
} else if (itemId) {
formTitle = `Edit ${listItemName}`; // case when editing a item
} else {
formTitle = `Add a new ${listItemName}`; // case when adding a new item
}
let heading = (
<Typography variant="h5" className={styles.Title}>
<IconButton disabled className={styles.Icon}>
{icon}
</IconButton>
{formTitle}
</Typography>
);
if (advanceSearch) {
const data = advanceSearch({});
if (data && data.heading) heading = data.heading;
}
const backLink = backLinkButton ? (
<div className={styles.BackLink}>
<Link to={backLinkButton.link}>
<BackIcon />
{backLinkButton.text}
</Link>
</div>
) : null;
return (
<div className={styles.ItemAdd}>
{dialogBox}
{heading}
{backLink}
{form}
</div>
);
}
Example #23
Source File: extractBeanValidationErrors.test.ts From jmix-frontend with Apache License 2.0 | 4 votes |
describe('extractBeanValidationErrors()', () => {
it('returns fieldErrors when there are field-related constraint violations', () => {
const apolloError: ApolloError = {
...apolloErrorPartial,
graphQLErrors: [
{
...graphQLErrorPartial,
extensions: {
constraintViolations: [
{
path: 'regNumber',
message: 'error message',
},
{
path: 'manufacturer',
message: 'another message',
}
]
}
}
],
clientErrors: []
};
const errors = extractBeanValidationErrors(apolloError);
expect(errors?.fieldErrors?.size).toEqual(2);
expect(errors?.fieldErrors?.get('regNumber')).toEqual(['error message']);
expect(errors?.fieldErrors?.get('manufacturer')).toEqual(['another message']);
});
it('returns globalErrors when there are non-field-related constraint violations', () => {
const apolloError: ApolloError = {
...apolloErrorPartial,
graphQLErrors: [
{
...graphQLErrorPartial,
extensions: {
constraintViolations: [
{
path: '',
message: 'global error'
}
]
}
}
],
clientErrors: []
};
const errors = extractBeanValidationErrors(apolloError);
expect(errors?.globalErrors).toEqual(['global error']);
});
it('returns both fieldErrors and globalErrors when there are both types of constraint violations', () => {
const apolloError: ApolloError = {
...apolloErrorPartial,
graphQLErrors: [
{
...graphQLErrorPartial,
extensions: {
constraintViolations: [
{
path: 'regNumber',
message: 'error message',
},
{
path: 'manufacturer',
message: 'another message',
},
{
path: '',
message: 'global error'
}
]
}
}
],
clientErrors: []
};
const errors = extractBeanValidationErrors(apolloError);
expect(errors?.globalErrors).toEqual(['global error']);
expect(errors?.fieldErrors?.size).toEqual(2);
expect(errors?.fieldErrors?.get('regNumber')).toEqual(['error message']);
expect(errors?.fieldErrors?.get('manufacturer')).toEqual(['another message']);
});
it('multiple errors on same field', () => {
const apolloError: ApolloError = {
...apolloErrorPartial,
graphQLErrors: [
{
...graphQLErrorPartial,
extensions: {
constraintViolations: [
{
path: 'regNumber',
message: 'error1',
},
{
path: 'regNumber',
message: 'error2',
},
{
path: 'regNumber',
message: 'error3'
}
]
}
}
],
clientErrors: []
};
const errors = extractBeanValidationErrors(apolloError);
expect(errors?.fieldErrors?.size).toEqual(1);
expect(errors?.fieldErrors?.get('regNumber')).toEqual(['error1', 'error2', 'error3']);
});
it('returns undefined when there are no constraint violations', () => {
const apolloError: ApolloError = {
...apolloErrorPartial,
graphQLErrors: [
{
...graphQLErrorPartial,
extensions: {}
}
],
clientErrors: []
};
expect(extractBeanValidationErrors(apolloError)).toBeUndefined();
expect(extractBeanValidationErrors(undefined)).toBeUndefined();
});
});
Example #24
Source File: generate.hooks.ts From condo with MIT License | 4 votes |
export function generateReactHooks<GQL, GQLInput, UIForm, UI, Q> (gql, { convertToGQLInput, convertToUIState }: IHookConverters<GQL, GQLInput, UI, UIForm>): IHookResult<UI, UIForm, Q> {
function useObject (variables: Q, options?: QueryHookOptions<{ objs?: GQL[], meta?: { count?: number } }, Q>) {
const { loading, refetch, fetchMore, objs, count, error } = useObjects(variables, options)
if (count && count > 1) throw new Error('Wrong query condition! return more then one result')
const obj = (objs.length) ? objs[0] : null
return { loading, refetch, fetchMore, obj, error }
}
function useObjects (variables: Q, options?: QueryHookOptions<{ objs?: GQL[], meta?: { count?: number } }, Q>) {
const intl = useIntl()
const ServerErrorPleaseTryAgainLaterMsg = intl.formatMessage({ id: 'ServerErrorPleaseTryAgainLater' })
const AccessErrorMsg = intl.formatMessage({ id: 'AccessError' })
const result = useQuery<{ objs?: GQL[], meta?: { count?: number } }, Q>(gql.GET_ALL_OBJS_WITH_COUNT_QUERY, {
variables,
notifyOnNetworkStatusChange: true,
...options,
})
let error: ApolloError | string
if (error && String(error).includes('not have access')) {
error = AccessErrorMsg
} else if (error) {
error = ServerErrorPleaseTryAgainLaterMsg
}
const objs: UI[] = getObjects(result.data, convertToUIState)
const count = (result.data && result.data.meta) ? result.data.meta.count : null
return {
loading: result.loading,
refetch: result.refetch,
fetchMore: result.fetchMore,
objs,
count,
error,
}
}
/**
* Client hook that uses create-mutation of current schema
* @param attrs - values, that will be passed to update input unchanged by form
*/
function useCreate (attrs: UIForm | Record<string, unknown> = {}, onComplete) {
if (typeof attrs !== 'object' || !attrs) throw new Error('useCreate(): invalid attrs argument')
const [rowAction] = useMutation(gql.CREATE_OBJ_MUTATION)
async function _action (state: UIForm) {
const { data, errors } = await rowAction({
variables: { data: convertToGQLInput({ ...state, ...attrs }) },
})
if (data && data.obj) {
const result = convertToUIState(data.obj)
if (onComplete) onComplete(result)
return result
}
if (errors) {
console.warn(errors)
throw errors
}
throw new Error('unknown action result')
}
return useMemo(() => _action, [rowAction])
}
function useUpdate (attrs = {}, onComplete) {
if (typeof attrs !== 'object' || !attrs) throw new Error('useUpdate(): invalid attrs argument')
const [rowAction] = useMutation(gql.UPDATE_OBJ_MUTATION)
async function _action (state, obj) {
if (!obj || !obj.id) throw new Error('No obj.id argument')
const { data, errors } = await rowAction({
variables: {
id: obj.id,
data: convertToGQLInput({ ...state, ...attrs }, obj),
},
})
if (data && data.obj) {
const result = convertToUIState(data.obj)
if (onComplete) onComplete(result)
return result
}
if (errors) {
console.warn(errors)
throw errors
}
throw new Error('unknown action result')
}
return useMemo(() => _action, [rowAction])
}
function useDelete (attrs = {}, onComplete) {
if (typeof attrs !== 'object' || !attrs) throw new Error('useDelete(): invalid attrs argument')
const [rowAction] = useMutation(gql.DELETE_OBJ_MUTATION)
async function _action (obj) {
if (!obj || !obj.id) throw new Error('No obj.id argument')
const { data, errors } = await rowAction({
variables: {
id: obj.id,
},
})
if (data && data.obj) {
const result = convertToUIState(data.obj)
if (onComplete) onComplete(result)
return result
}
if (errors) {
console.warn(errors)
throw errors
}
throw new Error('unknown action result')
}
return useMemo(() => _action, [rowAction])
}
function useSoftDelete (attrs = {}, onComplete) {
if (typeof attrs !== 'object' || !attrs) throw new Error('useSoftDelete(): invalid attrs argument')
const [rowAction] = useMutation(gql.UPDATE_OBJ_MUTATION)
async function _action (state, obj) {
if (!obj.id) throw new Error('No obj.id argument')
const { data, errors } = await rowAction({
variables: {
id: obj.id,
data: convertToGQLInput({ ...state, deletedAt: 'true' }, obj),
},
})
if (data && data.obj) {
const result = convertToUIState(data.obj)
if (onComplete) onComplete(result)
return result
}
if (errors) {
console.warn(errors)
throw errors
}
throw new Error('unknown action result')
}
return useMemo(() => _action, [rowAction])
}
return {
gql,
useObject,
useObjects,
useCreate,
useUpdate,
useDelete,
useSoftDelete,
}
}
Example #25
Source File: generate.hooks.ts From condo with MIT License | 4 votes |
export function generateReactHooks<GQL, GQLInput, UIForm, UI, Q> (gql, { convertToGQLInput, convertToUIState }: IHookConverters<GQL, GQLInput, UI, UIForm>): IHookResult<UI, UIForm, Q> {
function useObject (variables: Q, memoize = true) {
const { loading, refetch, objs, count, error } = useObjects(variables, memoize)
if (count && count > 1) throw new Error('Wrong query condition! return more then one result')
const obj = (objs.length) ? objs[0] : null
return { loading, refetch, obj, error }
}
function useObjects (variables: Q, memoize = true) {
const intl = useIntl()
const ServerErrorPleaseTryAgainLaterMsg = intl.formatMessage({ id: 'ServerErrorPleaseTryAgainLater' })
const AccessErrorMsg = intl.formatMessage({ id: 'AccessError' })
// eslint-disable-next-line prefer-const
const result = useQuery<{ objs?: GQL[], meta?: { count?: number } }, Q>(gql.GET_ALL_OBJS_WITH_COUNT_QUERY, {
variables,
})
let error: ApolloError | string
if (error && String(error).includes('not have access')) {
error = AccessErrorMsg
} else if (error) {
error = ServerErrorPleaseTryAgainLaterMsg
}
/*
* There is bug here with nested objs memoization.
*
* We should use this tricky solution for manually control default memoization flow.
* React and eslint recommend to avoid using reactHooks in conditional statements,
* as result, we should do some tricks with initial objs value calculation.
* TODO: debug and remove useMemo later
*/
let objs: UI[] = useMemo(() => {
return getObjects(result.data, convertToUIState)
}, [result.data])
if (!memoize) {
objs = getObjects(result.data, convertToUIState)
}
const count = (result.data && result.data.meta) ? result.data.meta.count : null
return {
loading: result.loading,
refetch: result.refetch,
fetchMore: result.fetchMore,
objs,
count,
error,
}
}
function useCreate (attrs: UIForm | Record<string, unknown> = {}, onComplete) {
if (typeof attrs !== 'object' || !attrs) throw new Error('useCreate(): invalid attrs argument')
const [rowAction] = useMutation(gql.CREATE_OBJ_MUTATION)
async function _action (state: UIForm) {
const { data, errors } = await rowAction({
variables: { data: convertToGQLInput({ ...state, ...attrs }) },
})
if (data && data.obj) {
const result = convertToUIState(data.obj)
if (onComplete) onComplete(result)
return result
}
if (errors) {
console.warn(errors)
throw errors
}
throw new Error('unknown action result')
}
return useMemo(() => _action, [rowAction])
}
function useUpdate (attrs = {}, onComplete) {
if (typeof attrs !== 'object' || !attrs) throw new Error('useUpdate(): invalid attrs argument')
const [rowAction] = useMutation(gql.UPDATE_OBJ_MUTATION)
async function _action (state, obj) {
if (!obj || !obj.id) throw new Error('No obj.id argument')
const { data, errors } = await rowAction({
variables: {
id: obj.id,
data: convertToGQLInput({ ...state, ...attrs }, obj),
},
})
if (data && data.obj) {
const result = convertToUIState(data.obj)
if (onComplete) onComplete(result)
return result
}
if (errors) {
console.warn(errors)
throw errors
}
throw new Error('unknown action result')
}
return useMemo(() => _action, [rowAction])
}
function useDelete (attrs = {}, onComplete) {
if (typeof attrs !== 'object' || !attrs) throw new Error('useDelete(): invalid attrs argument')
const [rowAction] = useMutation(gql.DELETE_OBJ_MUTATION)
async function _action (obj) {
if (!obj || !obj.id) throw new Error('No obj.id argument')
const { data, errors } = await rowAction({
variables: {
id: obj.id,
},
})
if (data && data.obj) {
const result = convertToUIState(data.obj)
if (onComplete) onComplete(result)
return result
}
if (errors) {
console.warn(errors)
throw errors
}
throw new Error('unknown action result')
}
return useMemo(() => _action, [rowAction])
}
return {
gql,
useObject,
useObjects,
useCreate,
useUpdate,
useDelete,
}
}