@apollo/client#useMutation TypeScript Examples
The following examples show how to use
@apollo/client#useMutation.
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: useUpdateThreadPoint.ts From Full-Stack-React-TypeScript-and-Node with MIT License | 6 votes |
useUpdateThreadPoint = (
refreshThread?: () => void,
threadId?: string
) => {
const [execUpdateThreadPoint] = useMutation(UpdateThreadPoint);
const onClickIncThreadPoint = async (
e: React.MouseEvent<SVGSVGElement, MouseEvent>
) => {
e.preventDefault();
await execUpdateThreadPoint({
variables: {
threadId,
increment: true,
},
});
refreshThread && refreshThread();
};
const onClickDecThreadPoint = async (
e: React.MouseEvent<SVGSVGElement, MouseEvent>
) => {
e.preventDefault();
await execUpdateThreadPoint({
variables: {
threadId,
increment: false,
},
});
refreshThread && refreshThread();
};
return {
onClickIncThreadPoint,
onClickDecThreadPoint,
};
}
Example #3
Source File: AuthAppWithGitCallback.tsx From amplication with Apache License 2.0 | 6 votes |
AuthAppWithGitCallback = () => {
const { trackEvent } = useTracking();
const [completeAuthWithGit] = useMutation<Boolean>(CREATE_GIT_ORGANIZATION, {
onCompleted: (data) => {
window.opener.postMessage({ completed: true });
// close the popup
window.close();
},
});
useEffect(() => {
// get the URL parameters with the code and state values
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const installationId = urlParams.get("installation_id");
if (window.opener) {
trackEvent({
eventName: "completeAuthAppWithGitHub",
});
completeAuthWithGit({
variables: {
installationId,
gitProvider: "Github",
},
}).catch(console.error);
}
}, [completeAuthWithGit, trackEvent]);
/**@todo: show formatted layout and optional error message */
return <p>Please wait...</p>;
}
Example #4
Source File: Apollo.ts From graphql-ts-client with MIT License | 6 votes |
export function useTypedMutation<
TData extends object,
TVariables extends object,
TContext = DefaultContext,
TCache extends ApolloCache<any> = ApolloCache<any>
>(
fetcher: Fetcher<"Mutation", TData, TVariables>,
options?: MutationHookOptions<TData, TVariables, TContext> & {
readonly operationName?: string
}
): MutationTuple<
TData,
TVariables,
TContext,
TCache
> {
const body = requestBody(fetcher);
const request = useMemo<DocumentNode>(() => {
const operationName = options?.operationName ?? `mutation_${util.toMd5(body)}`;
return gql`mutation ${operationName}${body}`;
}, [body, options?.operationName]);
const response = useMutation<
TData,
TVariables,
TContext,
TCache
>(request, options);
const responseData = response[1].data;
const newResponseData = useMemo(() => util.exceptNullValues(responseData), [responseData]);
return newResponseData === responseData ? response : [
response[0],
{ ...response[1], data: newResponseData }
];
}
Example #5
Source File: TerminateFlow.tsx From glific-frontend with GNU Affero General Public License v3.0 | 6 votes |
TerminateFlow: React.FC<TerminateFlowProps> = ({
contactId,
setDialog,
}: TerminateFlowProps) => {
const [terminateFlow] = useMutation(TERMINATE_FLOW, {
onCompleted: ({ terminateContactFlows }) => {
if (terminateContactFlows.success) {
setNotification('Flow terminated successfully');
} else if (terminateContactFlows.errors) {
setNotification(terminateContactFlows.errors[0].message, 'warning');
}
},
});
const handleTerminateFlow = () => {
terminateFlow({ variables: { contactId } });
setDialog(false);
};
return (
<DialogBox
title="Terminate flows!"
alignButtons="center"
buttonOk="YES, TERMINATE"
buttonCancel="NO, CANCEL"
additionalTitleStyles={styles.Title}
colorOk="secondary"
handleOk={handleTerminateFlow}
handleCancel={() => {
setDialog(false);
}}
>
<div className={styles.Dialog}>
All active flows for the contact will be stopped. They can initiate a flow via keyword or
you will need to do it manually.
</div>
</DialogBox>
);
}
Example #6
Source File: MainRoomComponent.tsx From dh-web with GNU General Public License v3.0 | 6 votes |
RoomComponent: FC = () => {
const router = useRouter();
const [joinRoom, { error, loading }] = useMutation<RoomJoinQuery>(ROOM_JOIN_QUERY, { errorPolicy: "all" });
useEffect(() => {
if (router.query["roomId"]) {
joinRoom({ variables: { room_id: router.query["roomId"] || "" } });
}
}, [joinRoom, router.query]);
if (error) return (<p>{error.message}</p>);
if (loading) return (<p>...Loading</p>);
return (
<MainRoomComponent room_id={router.query["roomId"].toString() || ""} />
);
}
Example #7
Source File: form.create.mutation.ts From ui with GNU Affero General Public License v3.0 | 6 votes |
useFormCreateMutation = (
options: MutationHookOptions<Data, Variables> = {}
): MutationTuple<Data, Variables> => {
const oldUpdate = options.update
options.update = (cache, result, options) => {
cache.evict({
fieldName: 'listForms',
})
cache.gc()
if (oldUpdate) {
oldUpdate(cache, result, options)
}
}
return useMutation<Data, Variables>(MUTATION, options)
}
Example #8
Source File: useSignup.ts From magento_react_native_graphql with MIT License | 6 votes |
useSignup = (): Result<SignupForm> => {
const [createCustomer, { loading, data, error }] = useMutation<
CreateCustomerDataType,
CreateCustomerVars
>(CREATE_CUSTOMER);
const { values, handleChange, handleSubmit } = useForm<SignupForm>({
initialValues: {
firstName: '',
lastName: '',
email: '',
password: '',
secureTextEntry: true,
},
onSubmit: async _values => {
try {
await createCustomer({
variables: {
firstName: _values.firstName,
lastName: _values.lastName,
email: _values.email,
password: _values.password,
},
});
} catch {}
},
});
return {
values,
data,
error,
loading,
handleChange,
handleSubmit,
};
}
Example #9
Source File: Logout.tsx From Full-Stack-React-TypeScript-and-Node with MIT License | 5 votes |
Logout: FC<ModalProps> = ({ isOpen, onClickToggle }) => {
const user = useSelector((state: AppState) => state.user);
const [execLogout] = useMutation(LogoutMutation, {
refetchQueries: [
{
query: Me,
},
],
});
const { deleteMe } = useRefreshReduxMe();
const onClickLogin = async (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
e.preventDefault();
onClickToggle(e);
await execLogout({
variables: {
userName: user?.userName ?? "",
},
});
deleteMe();
};
const onClickCancel = (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
onClickToggle(e);
};
return (
<ReactModal
className="modal-menu"
isOpen={isOpen}
onRequestClose={onClickToggle}
shouldCloseOnOverlayClick={true}
>
<form>
<div className="logout-inputs">Are you sure you want to logout?</div>
<div className="form-buttons form-buttons-sm">
<div className="form-btn-left">
<button
style={{ marginLeft: ".5em" }}
className="action-btn"
onClick={onClickLogin}
>
Login
</button>
<button
style={{ marginLeft: ".5em" }}
className="cancel-btn"
onClick={onClickCancel}
>
Close
</button>
</div>
</div>
</form>
</ReactModal>
);
}
Example #10
Source File: GithubSyncDetails.tsx From amplication with Apache License 2.0 | 5 votes |
function GithubSyncDetails({ gitRepositoryWithOrganization }: Props) {
const gitRepositoryFullName = `${gitRepositoryWithOrganization.gitOrganization.name}/${gitRepositoryWithOrganization.name}`;
const [deleteGitRepository, { error: errorUpdate }] = useMutation(
DELETE_GIT_REPOSITORY,
{
variables: { gitRepositoryId: gitRepositoryWithOrganization.id },
}
);
const handleDeleteGitRepository = useCallback(() => {
deleteGitRepository({
variables: { gitRepositoryId: gitRepositoryWithOrganization.id },
}).catch(console.error);
}, [deleteGitRepository, gitRepositoryWithOrganization.id]);
const errorMessage = formatError(errorUpdate);
const repoUrl = `https://github.com/${gitRepositoryFullName}`;
return (
<div className={CLASS_NAME}>
<div className={`${CLASS_NAME}__body`}>
<div className={`${CLASS_NAME}__details`}>
<div className={`${CLASS_NAME}__name`}>{gitRepositoryFullName}</div>
<div>
<a href={repoUrl} target="github_repo">
{repoUrl}
</a>
</div>
</div>
<div className={`${CLASS_NAME}__action`}>
<Button
buttonStyle={EnumButtonStyle.Primary}
eventData={{
eventName: "changeGithubRepo",
}}
onClick={handleDeleteGitRepository}
>
Change Repository
</Button>
</div>
</div>
<Snackbar open={Boolean(errorUpdate)} message={errorMessage} />
</div>
);
}
Example #11
Source File: add-new-feed-form.tsx From nextjs-strapi-boilerplate with MIT License | 5 votes |
AddNewFeedForm = () => {
const { colorMode } = useColorMode();
const bgColor = { light: "white", dark: "gray.800" };
const color = { light: "gray.800", dark: "gray.100" };
const [body, setBody] = useState("");
const { data:session, status } = useSession();
if (!session) {
return (
<AccessDeniedIndicator message="You need to be signed in to add a new feed!" />
);
}
const [
insertFeed,
{ loading: insertFeedFetching, error: insertFeedError },
] = useMutation(insertFeedMutation);
const handleSubmit = async () => {
await insertFeed({ variables: { userId: session.id, body } });
setBody("");
};
const errorNode = () => {
if (!insertFeedError) {
return false;
}
return (
<Alert status="error">
<AlertIcon />
<AlertTitle>{insertFeedError.message}</AlertTitle>
<CloseButton position="absolute" right="8px" top="8px" />
</Alert>
);
};
return (
<Stack spacing={4}>
{errorNode()}
<Box
p={4}
bg={bgColor[colorMode]}
color={color[colorMode]}
shadow="lg"
rounded="lg"
>
<Stack spacing={4}>
<FormControl isRequired>
<FormLabel htmlFor="body">What's on your mind?</FormLabel>
<Textarea
id="body"
value={body}
onChange={(e: FormEvent<HTMLInputElement>) =>
setBody(e.currentTarget.value)
}
isDisabled={insertFeedFetching}
/>
</FormControl>
<FormControl>
<Button
loadingText="Posting..."
onClick={handleSubmit}
isLoading={insertFeedFetching}
isDisabled={!body.trim()}
>
Post
</Button>
</FormControl>
</Stack>
</Box>
</Stack>
);
}
Example #12
Source File: Login.tsx From HoldemSolver with MIT License | 5 votes |
function Login(props: Props): React.ReactElement {
const { login: setCredentials } = props;
let history = useHistory();
const [error, setError] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [
login,
{ loading }
] = useMutation(LOGIN, {
onCompleted(res) {
const { jwt, csrf } = res.auth.login;
// set auth keys
setCredentials(jwt, csrf);
// push to home
history.push('/home');
},
onError({ message }) {
setError(message);
}
});
function onEmailChange(e: ChangeEvent<HTMLInputElement>) {
const value = (e.target as HTMLInputElement).value;
setEmail(value);
}
function onPasswordChange(e: ChangeEvent<HTMLInputElement>) {
e.preventDefault();
const value = (e.target as HTMLInputElement).value;
setPassword(value);
}
function onSubmit(e: MouseEvent<HTMLButtonElement>) {
e.preventDefault();
setError('');
if (email && password)
login({ variables: { email, password }});
}
return (
<LoginStyle>
<form className="login-container">
<h1>Login</h1>
<p className="login-error">{error}</p>
<Input className="login-field" label="Email" name="email" onChange={onEmailChange} value={email}/>
<Input className="login-field" type="password" label="Password" name="password" onChange={onPasswordChange} value={password}/>
<Button size="lg" isLoading={loading} onClick={onSubmit} type="submit" className="login-btn" block variant="primary">Login</Button>
<p>Don't have an account? <Link to="/register">Sign up</Link></p>
</form>
</LoginStyle>
);
}
Example #13
Source File: middleware.tsx From liferay-grow with MIT License | 5 votes |
AuthMiddleware: React.FC = () => {
const router = useRouter();
const i18n = useLang();
const docs = {
'not-a-liferay-member': {
link:
'https://github.com/liferay-labs-br/liferay-grow/blob/master/docs/not-a-liferay-member.md',
message: i18n.sub('read-more-about-x', 'not-a-liferay-member'),
},
};
const [onAuthGithub, { loading }] = useMutation(authGithub);
const { dispatch } = useContext(AppContext);
const [error, setError] = useState<string>();
const getUserToken = async () => {
const urlParams = new URLSearchParams(location.search);
const code = urlParams.get('code');
if (code) {
try {
const {
data: { authGithub: bearer },
} = await onAuthGithub({ variables: { code } });
dispatch({ payload: { token: bearer }, type: Types.SET_LOGGED_USER });
const decodedToken = parseJwt(bearer);
toast.info(i18n.sub('welcome-x', decodedToken?.name));
router.replace(
decodedToken?.user?.growMap ? ROUTES.HOME : ROUTES.WELCOME,
);
} catch (err) {
toast.error(i18n.get(err.message));
setError(err.message);
}
} else {
router.replace(ROUTES.AUTH);
}
};
useEffect(() => {
getUserToken();
}, []);
return (
<AuthTemplate>
<SEO title={i18n.sub('app-title-x', 'Auth Middleware')} />
{error ? (
<div>
{docs[error] ? (
<p>
<a target="_blank" href={docs[error].link} rel="noreferrer">
{docs[error].message}
</a>
</p>
) : (
<p>{i18n.get(error)}</p>
)}
<ClayButton className="mt-4" onClick={() => router.replace('/auth')}>
{i18n.get('try-again')}
</ClayButton>
</div>
) : loading ? (
<LoadingWrapper />
) : (
<div>{`${i18n.get('redirecting')}...`}</div>
)}
</AuthTemplate>
);
}
Example #14
Source File: MainRoomComponent.tsx From dh-web with GNU General Public License v3.0 | 5 votes |
MainRoomComponent: FC<MainRoomComponentProperties> = ({ room_id }: MainRoomComponentProperties) => {
const { data, error, loading } = useQuery<RoomDataQuery>(ROOM_DATA, { variables: { room_id } });
const [leaveRoom] = useMutation(LEAVE_ROOM);
const router = useRouter();
// const theme = useTheme();
// const one = useMediaQuery(`(min-width:${theme.breakpoints.one + 1}px)`);
// const two = useMediaQuery(`(min-width:${theme.breakpoints.two + 1}px)`);
// const three = useMediaQuery(`(min-width:${theme.breakpoints.three + 1}px)`);
if (loading || error) {
return <></>;
}
return (
<RoomCard>
<RoomHeader>
<Title>{data.room.name}</Title>
{/*<SubTitle> // TODO: Impelement as soon as API Endpoints are available
with
<span>{"owner"}</span>
</SubTitle> */}
<Description>{data.room.description}</Description>
</RoomHeader>
<RoomMembers>
{
data.room.members.map((member) => (
<div key={member.user.id}>{member.user.username}</div>
))
}
</RoomMembers>
<RoomActions>
<Button variant="PRIMARY"><img src="/microphone.svg" alt="Microphone Button" /></Button>
<Button variant="PRIMARY"><img src="/headphone.svg" alt="Headphone Button" /></Button>
<Button variant="PRIMARY"><img src="/settings.svg" alt="Settings Button" /></Button>
<Button variant="PRIMARY"><img src="/users-plus.svg" alt="Invite Button" /></Button>
<Button variant="PRIMARY" onClick={async () => {
await leaveRoom();
router.push("/dash");
}}>Leave</Button>
</RoomActions>
</RoomCard>
);
}
Example #15
Source File: index.tsx From tinyhouse with MIT License | 5 votes |
function App() {
const [viewer, setViewer] = useState<Viewer>(initialViewer);
const [logIn, { error }] = useMutation<LogInData, LogInVariables>(LOG_IN, {
onCompleted: (data) => {
if (data && data.logIn) {
setViewer(data.logIn);
if (data.logIn.token) {
sessionStorage.setItem("token", data.logIn.token);
}
} else {
sessionStorage.removeItem("token");
}
},
});
const logInRef = useRef(logIn);
useEffect(() => {
logInRef.current();
}, []);
if (!viewer.didRequest && !error) {
return (
<Layout className="app-skeleton">
<AppHeaderSkeleton />
<div className="app-skeleton__spin-section">
<Spin size="large" tip="Launching TinyHouse" />
</div>
</Layout>
);
}
const logInErrorBannerElement = error ? (
<ErrorBanner description="We weren't able to verify if you were logged in. Please try again later!" />
) : null;
return (
<BrowserRouter>
<Layout id="app">
{logInErrorBannerElement}
<Affix offsetTop={0} className="app__affix-header">
<AppHeader viewer={viewer} setViewer={setViewer} />
</Affix>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/host" element={<Host />} />
<Route path="/listing/:listingId" element={<Listing />} />
<Route
path="/listings"
element={<Listings title="TinyHouse Listings" />}
>
<Route
path="/listings/:location"
element={<Listings title="TinyHouse Listings" />}
/>
</Route>
<Route
path="/login"
element={<Login setViewer={setViewer} />}
/>
<Route
path="/user/:userId"
element={<User viewer={viewer} />}
/>
<Route path="*" element={<NotFound />} />
</Routes>
</Layout>
</BrowserRouter>
);
}
Example #16
Source File: LikeSet.tsx From keycapsets.com with GNU General Public License v3.0 | 5 votes |
function LikeSet(props: LikeSetProps) { const { keycapset, size = 16 } = props; const router: NextRouter = useRouter(); const [addWantToUser] = useMutation(WANT_SET); const isLoggedIn = useStore((state) => state.isLoggedIn); const userWants = useStore((state) => state.userWants); const setUserWants = useStore((state) => state.setUserWants); function removeUserWants(id: string): Keycapset[] { const wantsClone = [...userWants]; const indexOfSetInWants = userWants.map((s: Keycapset) => s._id).indexOf(id); wantsClone.splice(indexOfSetInWants, 1); return wantsClone; } function adduserWants(keycapset: Keycapset): Keycapset[] { return [...userWants, keycapset]; } async function userWantSet(evt: React.MouseEvent<HTMLSpanElement>) { evt.preventDefault(); evt.stopPropagation(); if (isLoggedIn) { try { const { data: response } = await addWantToUser({ variables: { setId: keycapset._id, }, }); const isLiking: boolean = response.wantSet.message === 'liked'; setUserWants(isLiking ? adduserWants(keycapset) : removeUserWants(keycapset._id)); } catch (err) { console.error('want set err', { err }); } } else { router.push('/sign-up'); } } return ( <span data-tip="Sign up to create collections" onClick={userWantSet} className="heart-icon"> <HeartIcon filled={userWants.map((s: Keycapset) => s._id).includes(keycapset._id)} isDisabled={!isLoggedIn} width={size} height={size - 2} /> {!isLoggedIn && <ReactTooltip delayHide={500} className="tooltip" effect="solid" />} </span> ); }
Example #17
Source File: use.submission.ts From ui with GNU Affero General Public License v3.0 | 5 votes |
useSubmission = (formId: string): Submission => {
const [submission, setSubmission] = useState<{ id: string; token: string }>()
const [start] = useMutation<SubmissionStartMutationData, SubmissionStartMutationVariables>(
SUBMISSION_START_MUTATION
)
const [save] = useMutation<SubmissionSetFieldMutationData, SubmissionSetFieldMutationVariables>(
SUBMISSION_SET_FIELD_MUTATION
)
const [submit] = useMutation<SubmissionFinishMutationData, SubmissionFinishMutationVariables>(
SUBMISSION_FINISH_MUTATION
)
useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const token = [...Array(40)].map(() => Math.random().toString(36)[2]).join('')
start({
variables: {
form: formId,
submission: {
token,
device: {
name: /Mobi/i.test(window.navigator.userAgent) ? 'mobile' : 'desktop',
type: window.navigator.userAgent,
},
},
},
})
.then(({ data }) => {
logger('submission id = %O', data.submission.id)
setSubmission({
id: data.submission.id,
token,
})
})
.catch((e: Error) => logger('failed to start submission %J', e))
}, [formId])
const setField = useCallback(
async (fieldId: string, data: unknown) => {
if (data === undefined || data === null) {
logger('skip save field id=%O %O', fieldId, data)
return
}
logger('save field id=%O %O', fieldId, data)
await save({
variables: {
submission: submission.id,
field: {
token: submission.token,
field: fieldId,
data: JSON.stringify(data),
},
},
})
},
[submission]
)
const finish = useCallback(async () => {
logger('finish submission!!', formId)
await submit({
variables: {
submission: submission.id,
},
})
}, [submission])
return {
setField,
finish,
}
}
Example #18
Source File: useLogin.ts From magento_react_native_graphql with MIT License | 5 votes |
useLogin = (): Result<LoginForm> => {
const [createCustomerToken, { loading, data, error }] = useMutation<
CreateCustomerTokenDataType,
CreateCustomerTokenVars
>(CREATE_CUSTOMER_TOKEN, {
async update(cache, { data: _data }) {
if (_data?.generateCustomerToken?.token) {
await saveCustomerToken(_data.generateCustomerToken.token);
cache.writeQuery({
query: IS_LOGGED_IN,
data: {
isLoggedIn: true,
},
});
}
},
});
const { values, handleChange, handleSubmit } = useForm<LoginForm>({
initialValues: {
email: '',
password: '',
secureTextEntry: true,
},
onSubmit: async _values => {
try {
await createCustomerToken({
variables: {
email: _values.email,
password: _values.password,
},
});
} catch {}
},
});
return {
values,
data,
error,
loading,
handleChange,
handleSubmit,
};
}
Example #19
Source File: use-push-token-to-remote.ts From beancount-mobile with MIT License | 5 votes |
useAddPushTokenToRemote = () => {
const [mutate, { error, data }] = useMutation<
addPushToken,
addPushTokenVariables
>(addPushTokenToRemote);
return { error, mutate, data };
}
Example #20
Source File: useEntityEditor.ts From jmix-frontend with Apache License 2.0 | 4 votes |
export function useEntityEditor<
TEntity = unknown,
TData extends Record<string, any> = Record<string, any>,
TQueryVars extends HasId = HasId,
TMutationVars = unknown
>(
options: EntityEditorHookOptions<TEntity, TData, TQueryVars, TMutationVars>
): EntityEditorHookResult<TEntity, TData, TQueryVars, TMutationVars> {
const multiScreen = useMultiScreen();
const {
loadQuery,
loadQueryOptions,
upsertMutation,
upsertMutationOptions,
entityId = multiScreen?.params?.entityId,
entityName,
routingPath,
onCommit,
entityInstance,
useEntityEditorForm = useNoop,
useEntityEditorFormValidation = useNoop,
uiKit_to_jmixFront,
persistEntityCallbacks,
shouldNotGoToParentScreen
} = options;
const intl = useIntl();
const updateResultName = `upsert_${dollarsToUnderscores(entityName)}`;
const listQueryName = `${dollarsToUnderscores(entityName)}List`;
const entityEditorState: EntityEditorState = useEntityEditorStore();
const {
item,
relationOptions,
executeLoadQuery,
loadQueryResult
} = useEntityEditorData({
loadQuery,
loadQueryOptions,
entityInstance,
entityId,
entityName,
cloneEntity: multiScreen?.params?.cloneEntity
});
useEntityEditorForm(item, entityName);
const [executeUpsertMutation, upsertMutationResult] = useMutation<TData, TMutationVars>(upsertMutation, upsertMutationOptions);
const serverValidationErrors = useExtractBeanValidationErrors(upsertMutationResult.error);
const [executeClientValidation, clientValidationErrors] = useClientValidation();
useEntityEditorFormValidation(clientValidationErrors || serverValidationErrors);
const goToParentScreen = useParentScreen(routingPath, shouldNotGoToParentScreen);
const handleCancelBtnClick = goToParentScreen;
const handleSubmit = useSubmitCallback({
executeUpsertMutation,
updateResultName,
listQueryName,
entityName,
goToParentScreen,
entityId: multiScreen?.params?.cloneEntity
? undefined
: entityId,
entityInstance,
onCommit,
uiKit_to_jmixFront,
persistEntityCallbacks,
executeClientValidation
});
return {
item,
serverValidationErrors,
relationOptions,
executeLoadQuery,
loadQueryResult,
executeUpsertMutation,
upsertMutationResult,
entityEditorState,
intl,
handleSubmit,
handleCancelBtnClick,
};
}
Example #21
Source File: Login.tsx From Full-Stack-React-TypeScript-and-Node with MIT License | 4 votes |
Login: FC<ModalProps> = ({ isOpen, onClickToggle }) => {
const [execLogin] = useMutation(LoginMutation, {
refetchQueries: [
{
query: Me,
},
],
});
const [
{ userName, password, resultMsg, isSubmitDisabled },
dispatch,
] = useReducer(userReducer, {
userName: "test1",
password: "Test123$%^",
resultMsg: "",
isSubmitDisabled: false,
});
const { execMe, updateMe } = useRefreshReduxMe();
const onChangeUserName = (e: React.ChangeEvent<HTMLInputElement>) => {
dispatch({ type: "userName", payload: e.target.value });
if (!e.target.value)
allowSubmit(dispatch, "Username cannot be empty", true);
else allowSubmit(dispatch, "", false);
};
const onChangePassword = (e: React.ChangeEvent<HTMLInputElement>) => {
dispatch({ type: "password", payload: e.target.value });
if (!e.target.value)
allowSubmit(dispatch, "Password cannot be empty", true);
else allowSubmit(dispatch, "", false);
};
const onClickLogin = async (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
e.preventDefault();
onClickToggle(e);
const result = await execLogin({
variables: {
userName,
password,
},
});
console.log("login", result);
execMe();
updateMe();
};
const onClickCancel = (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
onClickToggle(e);
};
return (
<ReactModal
className="modal-menu"
isOpen={isOpen}
onRequestClose={onClickToggle}
shouldCloseOnOverlayClick={true}
>
<form>
<div className="reg-inputs">
<div>
<label>username</label>
<input type="text" value={userName} onChange={onChangeUserName} />
</div>
<div>
<label>password</label>
<input
type="password"
placeholder="Password"
value={password}
onChange={onChangePassword}
/>
</div>
</div>
<div className="form-buttons form-buttons-sm">
<div className="form-btn-left">
<button
style={{ marginLeft: ".5em" }}
className="action-btn"
disabled={isSubmitDisabled}
onClick={onClickLogin}
>
Login
</button>
<button
style={{ marginLeft: ".5em" }}
className="cancel-btn"
onClick={onClickCancel}
>
Close
</button>
</div>
<span className="form-btn-left">
<strong>{resultMsg}</strong>
</span>
</div>
</form>
</ReactModal>
);
}
Example #22
Source File: ApplicationAuthSettingForm.tsx From amplication with Apache License 2.0 | 4 votes |
function ApplicationAuthSettingForm({ match }: Props) {
const applicationId = match.params.application;
const { data, error } = useQuery<{
appSettings: models.AppSettings;
}>(GET_APP_SETTINGS, {
variables: {
id: applicationId,
},
});
const pendingChangesContext = useContext(PendingChangesContext);
const { trackEvent } = useTracking();
const [updateAppSettings, { error: updateError }] = useMutation<TData>(
UPDATE_APP_SETTINGS,
{
onCompleted: (data) => {
pendingChangesContext.addBlock(data.updateAppSettings.id);
},
}
);
const handleSubmit = useCallback(
(data: models.AppSettings) => {
const { dbHost, dbName, dbPassword, dbPort, dbUser, authProvider } = data;
trackEvent({
eventName: "updateAppSettings",
});
updateAppSettings({
variables: {
data: {
dbHost,
dbName,
dbPassword,
dbPort,
dbUser,
authProvider,
},
appId: applicationId,
},
}).catch(console.error);
},
[updateAppSettings, applicationId, trackEvent]
);
const errorMessage = formatError(error || updateError);
return (
<div className={CLASS_NAME}>
{data?.appSettings && (
<Formik
initialValues={data.appSettings}
validate={(values: models.AppSettings) =>
validate(values, FORM_SCHEMA)
}
enableReinitialize
onSubmit={handleSubmit}
>
{(formik) => {
return (
<Form>
<FormikAutoSave debounceMS={2000} />
<h3>Authentication Providers</h3>
<p>
Select the authentication method to be used in the generated
app.
</p>
<div className={`${CLASS_NAME}__space`}>
<SelectField
label="Authentication provider"
name="authProvider"
options={Object.keys(models.EnumAuthProviderType).map(
(authProvider) => ({
label: authProvider,
value: authProvider,
})
)}
/>
</div>
</Form>
);
}}
</Formik>
)}
<Snackbar open={Boolean(error)} message={errorMessage} />
</div>
);
}
Example #23
Source File: index.tsx From nextjs-strapi-boilerplate with MIT License | 4 votes |
MyAccountPageComponent = () => {
const { colorMode } = useColorMode();
const bgColor = { light: "white", dark: "gray.800" };
const color = { light: "gray.800", dark: "gray.100" };
const [username, setUsername] = useState("");
const { data:session, status } = useSession();
const {
loading: fetchUserFetching,
error: fetchUserError,
data: fetchUserData,
} = useQuery(usersQuery, {
variables: { userId: session.id },
});
useEffect(() => {
if (fetchUserData) {
const { username } = fetchUserData.user;
setUsername(username || "");
}
}, [fetchUserData]);
const [
updateUser,
{ loading: updateUserFetching, error: updateUserError },
] = useMutation(updateUserMutation);
if (fetchUserFetching) {
return <Loader />;
}
if (fetchUserError) {
return <p>Error: {fetchUserError.message}</p>;
}
const handleSubmit = () => {
updateUser({ variables: { userId: session.id, username } });
};
const errorNode = () => {
if (!updateUserError) {
return false;
}
return (
<Alert status="error">
<AlertIcon />
<AlertTitle>{updateUserError}</AlertTitle>
<CloseButton position="absolute" right="8px" top="8px" />
</Alert>
);
};
return (
<Stack spacing={4}>
<Heading color={color[colorMode]}>My Account</Heading>
{errorNode()}
<Grid templateColumns="repeat(1, 1fr)" gap={4}>
<Box
p={4}
bg={bgColor[colorMode]}
color={color[colorMode]}
shadow="sm"
rounded="lg"
>
<Stack spacing={4}>
<FormControl isRequired>
<FormLabel htmlFor="username">Username</FormLabel>
<Input
type="text"
id="username"
value={username}
onChange={(e: FormEvent<HTMLInputElement>) =>
setUsername(e.currentTarget.value)
}
isDisabled={updateUserFetching}
/>
</FormControl>
<FormControl>
<Button
loadingText="Saving..."
onClick={handleSubmit}
isLoading={updateUserFetching}
>
Save
</Button>
</FormControl>
</Stack>
</Box>
</Grid>
</Stack>
);
}
Example #24
Source File: FlowEditor.tsx From glific-frontend with GNU Affero General Public License v3.0 | 4 votes |
FlowEditor = (props: FlowEditorProps) => {
const { match } = props;
const history = useHistory();
const { uuid } = match.params;
const [publishDialog, setPublishDialog] = useState(false);
const [simulatorId, setSimulatorId] = useState(0);
const [loading, setLoading] = useState(true);
const config = setConfig(uuid);
const [published, setPublished] = useState(false);
const [stayOnPublish, setStayOnPublish] = useState(false);
const [modalVisible, setModalVisible] = useState(false);
const [showResetFlowModal, setShowResetFlowModal] = useState(false);
const [lastLocation, setLastLocation] = useState<Location | null>(null);
const [confirmedNavigation, setConfirmedNavigation] = useState(false);
const [flowValidation, setFlowValidation] = useState<any>();
const [IsError, setIsError] = useState(false);
const [flowKeyword, setFlowKeyword] = useState('');
const [currentEditDialogBox, setCurrentEditDialogBox] = useState(false);
const [dialogMessage, setDialogMessage] = useState('');
const { drawerOpen } = useContext(SideDrawerContext);
let modal = null;
let dialog = null;
let flowTitle: any;
const [getOrganizationServices] = useLazyQuery(GET_ORGANIZATION_SERVICES, {
fetchPolicy: 'network-only',
onCompleted: (services) => {
const { dialogflow, googleCloudStorage, flowUuidDisplay } = services.organizationServices;
if (googleCloudStorage) {
config.attachmentsEnabled = true;
}
if (!dialogflow) {
config.excludeTypes.push('split_by_intent');
}
if (flowUuidDisplay) {
config.showNodeLabel = true;
}
showFlowEditor(document.getElementById('flow'), config);
setLoading(false);
},
});
const [getFreeFlow] = useLazyQuery(GET_FREE_FLOW, {
fetchPolicy: 'network-only',
onCompleted: ({ flowGet }) => {
if (flowGet.flow) {
getOrganizationServices();
} else if (flowGet.errors && flowGet.errors.length) {
setDialogMessage(flowGet.errors[0].message);
setCurrentEditDialogBox(true);
}
},
});
const [exportFlowMutation] = useLazyQuery(EXPORT_FLOW, {
fetchPolicy: 'network-only',
onCompleted: async ({ exportFlow }) => {
const { exportData } = exportFlow;
exportFlowMethod(exportData, flowTitle);
},
});
const [resetFlowCountMethod] = useMutation(RESET_FLOW_COUNT, {
onCompleted: ({ resetFlowCount }) => {
const { success } = resetFlowCount;
if (success) {
setNotification('Flow counts have been reset', 'success');
setShowResetFlowModal(false);
window.location.reload();
}
},
});
const [publishFlow] = useMutation(PUBLISH_FLOW, {
onCompleted: (data) => {
if (data.publishFlow.errors && data.publishFlow.errors.length > 0) {
setFlowValidation(data.publishFlow.errors);
setIsError(true);
} else if (data.publishFlow.success) {
setPublished(true);
}
},
});
const { data: flowName } = useQuery(GET_FLOW_DETAILS, {
fetchPolicy: 'network-only',
variables: {
filter: {
uuid,
},
opts: {},
},
});
let flowId: any;
// flowname can return an empty array if the uuid present is not correct
if (flowName && flowName.flows.length > 0) {
flowTitle = flowName.flows[0].name;
flowId = flowName.flows[0].id;
}
const closeModal = () => {
setModalVisible(false);
};
const handleBlockedNavigation = (nextLocation: any): boolean => {
if (!confirmedNavigation) {
setModalVisible(true);
setLastLocation(nextLocation);
return false;
}
return true;
};
const handleConfirmNavigationClick = () => {
setModalVisible(false);
setConfirmedNavigation(true);
};
useEffect(() => {
if (confirmedNavigation && lastLocation) {
history.push(lastLocation);
}
}, [confirmedNavigation, lastLocation, history]);
if (modalVisible) {
modal = (
<DialogBox
title="Unsaved changes!"
handleOk={handleConfirmNavigationClick}
handleCancel={closeModal}
colorOk="secondary"
buttonOk="Ignore & leave"
buttonCancel="Stay & recheck"
alignButtons="center"
contentAlign="center"
additionalTitleStyles={styles.DialogTitle}
>
<div className={styles.DialogContent}>
Your changes will not be saved if you navigate away. Please save as draft or publish.
</div>
</DialogBox>
);
}
const handleResetFlowCount = () => {
resetFlowCountMethod({ variables: { flowId } });
};
if (showResetFlowModal) {
modal = (
<DialogBox
title="Warning!"
handleOk={handleResetFlowCount}
handleCancel={() => setShowResetFlowModal(false)}
colorOk="secondary"
buttonOk="Accept & reset"
buttonCancel="DON'T RESET YET"
alignButtons="center"
contentAlign="center"
additionalTitleStyles={styles.DialogTitle}
>
<div className={styles.DialogContent}>
Please be careful, this cannot be undone. Once you reset the flow counts you will lose
tracking of how many times a node was triggered for users.
</div>
</DialogBox>
);
}
useEffect(() => {
if (flowName) {
document.title = flowTitle;
}
return () => {
document.title = APP_NAME;
};
}, [flowName]);
useEffect(() => {
if (flowId) {
const { fetch, xmlSend, xmlOpen } = setAuthHeaders();
const files = loadfiles(() => {
getFreeFlow({ variables: { id: flowId } });
});
// when switching tabs we need to check if the flow is still active for the user
window.onfocus = () => {
getFreeFlow({ variables: { id: flowId } });
};
return () => {
Object.keys(files).forEach((node: any) => {
if (files[node]) {
document.body.removeChild(files[node]);
}
});
// clearing all timeouts when component unmounts
const highestTimeoutId: any = setTimeout(() => {});
for (let timeoutId = 0; timeoutId < highestTimeoutId; timeoutId += 1) {
clearTimeout(timeoutId);
}
XMLHttpRequest.prototype.send = xmlSend;
XMLHttpRequest.prototype.open = xmlOpen;
window.fetch = fetch;
};
}
return () => {};
}, [flowId]);
const handlePublishFlow = () => {
publishFlow({ variables: { uuid: match.params.uuid } });
};
const handleCancelFlow = () => {
setPublishDialog(false);
setIsError(false);
setFlowValidation('');
};
const errorMsg = () => (
<div className={styles.DialogError}>
Errors were detected in the flow. Would you like to continue modifying?
<div>
{flowValidation.map((message: any) => (
<div key={message.message}>
<WarningIcon className={styles.ErrorMsgIcon} />
{message.message}
</div>
))}
</div>
</div>
);
if (currentEditDialogBox) {
dialog = (
<DialogBox
title={dialogMessage}
alignButtons="center"
skipCancel
buttonOk="Okay"
handleOk={() => {
setConfirmedNavigation(true);
history.push('/flow');
}}
>
<p className={styles.DialogDescription}>Please try again later or contact the user.</p>
</DialogBox>
);
}
if (publishDialog) {
dialog = (
<DialogBox
title="Ready to publish?"
buttonOk="Publish & Stay"
titleAlign="center"
buttonMiddle="Publish & go back"
handleOk={() => {
setStayOnPublish(true);
handlePublishFlow();
}}
handleCancel={() => handleCancelFlow()}
handleMiddle={() => {
setStayOnPublish(false);
handlePublishFlow();
}}
alignButtons="center"
buttonCancel="Cancel"
additionalTitleStyles={styles.PublishDialogTitle}
>
<p className={styles.DialogDescription}>New changes will be activated for the users</p>
</DialogBox>
);
}
if (IsError) {
dialog = (
<DialogBox
title=""
buttonOk="Publish"
handleOk={() => {
setPublishDialog(false);
setIsError(false);
setPublished(true);
}}
handleCancel={() => handleCancelFlow()}
alignButtons="center"
buttonCancel="Modify"
>
{errorMsg()}
</DialogBox>
);
}
if (published && !IsError) {
setNotification('The flow has been published');
if (!stayOnPublish) {
return <Redirect to="/flow" />;
}
setPublishDialog(false);
setPublished(false);
}
const resetMessage = () => {
setFlowKeyword('');
};
const getFlowKeyword = () => {
const flows = flowName ? flowName.flows : null;
if (flows && flows.length > 0) {
const { isActive, keywords } = flows[0];
if (isActive && keywords.length > 0) {
setFlowKeyword(`draft:${keywords[0]}`);
} else if (keywords.length === 0) {
setFlowKeyword('No keyword found');
} else {
setFlowKeyword('Sorry, the flow is not active');
}
}
};
return (
<>
{dialog}
<div className={styles.ButtonContainer}>
<a
href={FLOWS_HELP_LINK}
className={styles.Link}
target="_blank"
rel="noopener noreferrer"
data-testid="helpButton"
>
<HelpIcon className={styles.HelpIcon} />
</a>
<Button
variant="contained"
color="default"
className={styles.ContainedButton}
onClick={() => {
history.push('/flow');
}}
>
Back
</Button>
<div
className={styles.ExportIcon}
onClick={() => exportFlowMutation({ variables: { id: flowId } })}
aria-hidden="true"
>
<ExportIcon />
</div>
<Button
variant="outlined"
color="primary"
data-testid="saveDraftButton"
className={simulatorId === 0 ? styles.Draft : styles.SimulatorDraft}
onClick={() => {
setNotification('The flow has been saved as draft');
}}
>
Save as draft
</Button>
<Button
variant="contained"
color="primary"
data-testid="button"
className={styles.ContainedButton}
onClick={() => setPublishDialog(true)}
>
Publish
</Button>
</div>
<Simulator
showSimulator={simulatorId > 0}
setSimulatorId={setSimulatorId}
hasResetButton
flowSimulator
message={flowKeyword}
resetMessage={resetMessage}
getFlowKeyword={getFlowKeyword}
/>
{modal}
<Prompt when message={handleBlockedNavigation} />
<div className={styles.FlowContainer}>
<div
className={drawerOpen ? styles.FlowName : styles.FlowNameClosed}
data-testid="flowName"
>
{flowName && (
<>
<IconButton disabled className={styles.Icon}>
<FlowIcon />
</IconButton>
{flowTitle}
</>
)}
</div>
<Button
variant="outlined"
color="primary"
className={drawerOpen ? styles.ResetFlow : styles.ResetClosedDrawer}
data-testid="resetFlow"
onClick={() => setShowResetFlowModal(true)}
aria-hidden="true"
>
<ResetFlowIcon /> Reset flow counts
</Button>
<div id="flow" />
{loading && <Loading />}
</div>
</>
);
}