All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
hooks.submit.tsx Maven / Gradle / Ivy
import { NavigateFunction, useNavigate } from 'react-router';
import { FormikContextType } from 'formik';
import { FetchResult, useMutation } from '@apollo/client';
import { focusOnField } from 'components/form/utils/field-utils';
import { FormInfo } from 'contexts/FormInfoContext';
import Report from 'helpers/report';
import { TraitHelper } from 'helpers/traits';
import { useMountedRef } from 'hooks/mounted';
import { Notifier, useNotifier } from 'hooks/notification';
import { openTasksForm, StartProcessFunction } from 'hooks/process';
import { useSubmitting } from 'hooks/submitting';
import { useTranslator } from 'hooks/translator';
import { START_PROCESS_WITH_FORM } from 'queries/form';
import { SUBMIT_TASK } from 'queries/task';
import { ProcessDefinition, ProcessInstance, Task } from 'types/graphql';
import { SubmitValues } from 'types/types';
import { bannerQueries } from 'utils/banner-utils';
import { extractFiles, isEmptyValue } from 'utils/utils';
import { useFormInfo } from './form';
type LocalSubmitProps = {
id: string
isStartForm: boolean
}
export type FormikType = FormikContextType //FormikSharedConfig<{}> //FormikProps
export interface FormikFormInfo extends FormInfo {
formik: FormikType
}
export type SubmitHandler = (values: any, formInfo: FormikFormInfo, local?: LocalSubmitProps) => void
export type SubmitReturn = { handleSubmit : SubmitHandler}
export type ProcessStarterKit = {
startProcess: StartProcessFunction
processDefinition: ProcessDefinition
}
export type TaskEndFunction = (tasks?: Task[] | Task) => void
export const useSubmitHandler = (id?: string, isStartForm?: boolean): SubmitReturn => {
const navigate = useNavigate()
const notifier = useNotifier()
const {isMounted} = useMountedRef()
const {setSubmitting} = useSubmitting()
const taskEndHandler = useTaskEndHandler()
const { translator } = useTranslator()
const [doSubmitStartForm] = useMutation(START_PROCESS_WITH_FORM, { refetchQueries: bannerQueries })
const [doSubmitTaskForm] = useMutation(SUBMIT_TASK, { refetchQueries: bannerQueries })
function handleSubmit(values: any, formInfo: FormikFormInfo, local?: LocalSubmitProps) {
setSubmitting(true)
const [rValues, files] = extractFiles(values)
const isLocalStartForm = local != undefined ? local.isStartForm : isStartForm
const localId = local != undefined ? local.id : id
const extractSubmitData = (result: FetchResult) => isLocalStartForm ? result?.data?.startProcess : result?.data?.submitTask
const doSubmit = isLocalStartForm ? doSubmitStartForm : doSubmitTaskForm
if (isLocalStartForm == undefined || localId == undefined)
notifier.error("The submit handler does not have enough process information to start the process")
console.debug("Submit values: %o, files: %o", rValues, files)
doSubmit({ variables: { id: localId, values: rValues, files } })
.then(
result => {
const data = extractSubmitData(result)
return handleSubmitResult(data, formInfo, taskEndHandler)
},
error => {
const report = Report.from(error, translator, { category: Report.backend }, formInfo.processDefinition.key)
report.addToNotifier(notifier)
const specErrors = Report.toSpecErrors(error)
if (specErrors.length > 0) {
for (let i = 0; i < specErrors.length; i++) {
// @ts-ignore
const location = specErrors[i].extensions.location || ""
const sp = location.split(/\r?\n/).map((v: string, i: number) => i > 0 ? " " + v : v).join("\r\n")
console.error("Specification error\nMessage : %s\nLocation: %s", specErrors[i].message, sp)
}
} else {
console.error("Submit error: %s", report.verboseMessage)
}
}
)
.finally(() => { if (isMounted()) setSubmitting(false) })
}
function handleSubmitResult(data: FetchResult & {__typename: string}, formInfo: FormikFormInfo, taskEndHandler: TaskEndFunction) {
console.log("handleSubmitResult: data=%o, formInfo=%o", data, formInfo)
switch (data.__typename) {
case "ProcessInstanceEnded": taskEndHandler(); break
case "ProcessInstance": handleProcessInstance(data as unknown as ProcessInstance, taskEndHandler); break
case "SubmitInProgress": handleSubmitInProgress(formInfo, navigate); break
case "InputErrors": handleInputErrors(data, formInfo, notifier); break
default: alert("Submit result return an unexpected return type: " + data.__typename)
}
}
function handleProcessInstance(instance: ProcessInstance, taskEndHandler: TaskEndFunction) {
const tasks = instance?.assignedTasks
taskEndHandler(tasks)
}
function handleSubmitInProgress(formInfo: FormInfo, navigate: NavigateFunction) {
if (!formInfo?.statusUrl)
notifier.error("Runtime issue: no status url available")
else {
const url = formInfo.statusUrl
if (url) navigate(url)
}
}
function handleInputErrors(data: any, formInfo: FormInfo & {formik: any}, notifier: Notifier) {
const errors = Object.fromEntries(data.errors.map((error: any) => [error.path, error]))
console.error("Input errors: %o", errors)
if (!formInfo?.formik) {
notifier.error("Input errors: " + JSON.stringify(errors))
} else {
formInfo.formik.setStatus(errors)
data.errors.forEach((error: any) => formInfo.formik.setFieldError(error.path, error))
Report.error(Report.input, Report.code.input.Error).addToNotifier(notifier)
const first = data.errors[0]
if (first && first.path) {
focusOnField(first.path)
}
}
}
return { handleSubmit }
}
// go to the next task. eighter the only task that is given of the first task if the process has autostart.
export const useTaskEndHandler = (): TaskEndFunction => {
const navigate = useNavigate()
const notifier = useNotifier()
const formInfo = useFormInfo()
const { translator } = useTranslator()
const processDefinition = formInfo.processDefinition
return (tasks) => {
const tsks: Task[] = Array.isArray(tasks) ? tasks : isEmptyValue(tasks) ? [] : [tasks!]
if (tsks.length > 0)
openTasksForm({ navigate, translator, notifier }, tsks)
else if (TraitHelper.containsTrait(processDefinition?.traits, "autostart"))
navigate(`/gears/process/${processDefinition.key}`)
else
openTasksForm({ navigate, translator, notifier }, [])
}
}