@oneblink/apps-react 4.0.0-beta.1 → 4.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -8
- package/dist/OneBlinkAutoSaveForm.d.ts +25 -5
- package/dist/OneBlinkAutoSaveForm.js +12 -0
- package/dist/OneBlinkAutoSaveForm.js.map +1 -1
- package/dist/OneBlinkForm.d.ts +558 -8
- package/dist/OneBlinkForm.js +546 -0
- package/dist/OneBlinkForm.js.map +1 -1
- package/dist/OneBlinkFormBase.d.ts +52 -7
- package/dist/OneBlinkFormBase.js +4 -1
- package/dist/OneBlinkFormBase.js.map +1 -1
- package/dist/OneBlinkReadOnlyForm.d.ts +83 -6
- package/dist/OneBlinkReadOnlyForm.js +80 -1
- package/dist/OneBlinkReadOnlyForm.js.map +1 -1
- package/dist/PaymentReceipt.d.ts +59 -0
- package/dist/PaymentReceipt.js +49 -0
- package/dist/PaymentReceipt.js.map +1 -1
- package/dist/components/formStore/FormStoreTableProvider.js +23 -1
- package/dist/components/formStore/FormStoreTableProvider.js.map +1 -1
- package/dist/components/formStore/OneBlinkFormStoreClearFiltersButton.d.ts +5 -0
- package/dist/components/formStore/OneBlinkFormStoreClearFiltersButton.js +5 -0
- package/dist/components/formStore/OneBlinkFormStoreClearFiltersButton.js.map +1 -1
- package/dist/components/formStore/OneBlinkFormStoreColumnsButton.d.ts +5 -0
- package/dist/components/formStore/OneBlinkFormStoreColumnsButton.js +5 -0
- package/dist/components/formStore/OneBlinkFormStoreColumnsButton.js.map +1 -1
- package/dist/components/formStore/OneBlinkFormStoreDownloadButton.d.ts +5 -0
- package/dist/components/formStore/OneBlinkFormStoreDownloadButton.js +5 -0
- package/dist/components/formStore/OneBlinkFormStoreDownloadButton.js.map +1 -1
- package/dist/components/formStore/OneBlinkFormStoreProvider.d.ts +5 -0
- package/dist/components/formStore/OneBlinkFormStoreProvider.js +5 -0
- package/dist/components/formStore/OneBlinkFormStoreProvider.js.map +1 -1
- package/dist/components/formStore/OneBlinkFormStoreRefreshButton.d.ts +5 -0
- package/dist/components/formStore/OneBlinkFormStoreRefreshButton.js +5 -0
- package/dist/components/formStore/OneBlinkFormStoreRefreshButton.js.map +1 -1
- package/dist/components/formStore/OneBlinkFormStoreTable.d.ts +4 -0
- package/dist/components/formStore/OneBlinkFormStoreTable.js +4 -0
- package/dist/components/formStore/OneBlinkFormStoreTable.js.map +1 -1
- package/dist/components/pickers/V4CompatibleDatePicker.d.ts +5 -0
- package/dist/components/pickers/V4CompatibleDatePicker.js +5 -0
- package/dist/components/pickers/V4CompatibleDatePicker.js.map +1 -1
- package/dist/components/pickers/V4CompatibleDateTimePicker.d.ts +5 -0
- package/dist/components/pickers/V4CompatibleDateTimePicker.js +5 -0
- package/dist/components/pickers/V4CompatibleDateTimePicker.js.map +1 -1
- package/dist/components/pickers/V4CompatibleTimePicker.d.ts +5 -0
- package/dist/components/pickers/V4CompatibleTimePicker.js +5 -0
- package/dist/components/pickers/V4CompatibleTimePicker.js.map +1 -1
- package/dist/components/renderer/LookupButton.js +2 -2
- package/dist/components/renderer/LookupButton.js.map +1 -1
- package/dist/components/renderer/LookupNotification.js +47 -25
- package/dist/components/renderer/LookupNotification.js.map +1 -1
- package/dist/components/renderer/OneBlinkFormElements.d.ts +3 -3
- package/dist/components/renderer/OneBlinkFormElements.js.map +1 -1
- package/dist/components/renderer/PageFormElements.d.ts +3 -3
- package/dist/components/renderer/PageFormElements.js.map +1 -1
- package/dist/components/renderer/ProgressBar.d.ts +7 -3
- package/dist/components/renderer/ProgressBar.js +5 -0
- package/dist/components/renderer/ProgressBar.js.map +1 -1
- package/dist/form-elements/FormElementBarcodeScanner.js +2 -2
- package/dist/form-elements/FormElementBarcodeScanner.js.map +1 -1
- package/dist/form-elements/FormElementCalculation.js.map +1 -1
- package/dist/form-elements/FormElementForm.d.ts +4 -4
- package/dist/form-elements/FormElementForm.js.map +1 -1
- package/dist/form-elements/FormElementRepeatableSet.d.ts +4 -4
- package/dist/form-elements/FormElementRepeatableSet.js.map +1 -1
- package/dist/form-elements/FormElementSummary.js.map +1 -1
- package/dist/hooks/useAuth.d.ts +81 -6
- package/dist/hooks/useAuth.js +54 -0
- package/dist/hooks/useAuth.js.map +1 -1
- package/dist/hooks/useBooleanState.d.ts +42 -5
- package/dist/hooks/useBooleanState.js +36 -0
- package/dist/hooks/useBooleanState.js.map +1 -1
- package/dist/hooks/useClickOutsideElement.d.ts +40 -0
- package/dist/hooks/useClickOutsideElement.js +40 -0
- package/dist/hooks/useClickOutsideElement.js.map +1 -1
- package/dist/hooks/useConditionalLogic.d.ts +2 -3
- package/dist/hooks/useConditionalLogic.js.map +1 -1
- package/dist/hooks/useDrafts.d.ts +82 -0
- package/dist/hooks/useDrafts.js +204 -0
- package/dist/hooks/useDrafts.js.map +1 -0
- package/dist/hooks/useFormSubmissionAutoSaveState.d.ts +18 -5
- package/dist/hooks/useFormSubmissionAutoSaveState.js +10 -0
- package/dist/hooks/useFormSubmissionAutoSaveState.js.map +1 -1
- package/dist/hooks/useFormSubmissionModelContext.d.ts +4 -4
- package/dist/hooks/useFormSubmissionModelContext.js.map +1 -1
- package/dist/hooks/useFormSubmissionState.d.ts +45 -5
- package/dist/hooks/useFormSubmissionState.js +37 -0
- package/dist/hooks/useFormSubmissionState.js.map +1 -1
- package/dist/hooks/useFormValidation.d.ts +3 -3
- package/dist/hooks/useFormValidation.js.map +1 -1
- package/dist/hooks/useInjectPages.d.ts +2 -3
- package/dist/hooks/useInjectPages.js.map +1 -1
- package/dist/hooks/useIsMounted.d.ts +20 -0
- package/dist/hooks/useIsMounted.js +19 -0
- package/dist/hooks/useIsMounted.js.map +1 -1
- package/dist/hooks/useIsOffline.d.ts +54 -0
- package/dist/hooks/useIsOffline.js +54 -0
- package/dist/hooks/useIsOffline.js.map +1 -1
- package/dist/hooks/useLoadDataState.d.ts +46 -3
- package/dist/hooks/useLoadDataState.js +41 -0
- package/dist/hooks/useLoadDataState.js.map +1 -1
- package/dist/hooks/useLogin.d.ts +400 -13
- package/dist/hooks/useLogin.js +300 -0
- package/dist/hooks/useLogin.js.map +1 -1
- package/dist/hooks/useLookupNotification.d.ts +6 -2
- package/dist/hooks/useLookupNotification.js +29 -3
- package/dist/hooks/useLookupNotification.js.map +1 -1
- package/dist/hooks/useLookups.d.ts +3 -3
- package/dist/hooks/useLookups.js.map +1 -1
- package/dist/hooks/useNullableState.d.ts +46 -1
- package/dist/hooks/useNullableState.js +42 -1
- package/dist/hooks/useNullableState.js.map +1 -1
- package/dist/hooks/usePendingSubmissions.d.ts +103 -0
- package/dist/hooks/usePendingSubmissions.js +195 -0
- package/dist/hooks/usePendingSubmissions.js.map +1 -0
- package/dist/hooks/useSignUp.d.ts +5 -0
- package/dist/hooks/useSignUp.js +5 -0
- package/dist/hooks/useSignUp.js.map +1 -1
- package/dist/index.d.ts +7 -4
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/services/checkBsbsAreInvalid.d.ts +2 -3
- package/dist/services/checkBsbsAreInvalid.js.map +1 -1
- package/dist/services/checkIfAttachmentsExist.d.ts +2 -3
- package/dist/services/checkIfAttachmentsExist.js.map +1 -1
- package/dist/services/checkIfBsbsAreValidating.d.ts +2 -3
- package/dist/services/checkIfBsbsAreValidating.js.map +1 -1
- package/dist/services/cleanFormSubmissionModel.d.ts +4 -4
- package/dist/services/cleanFormSubmissionModel.js +2 -1
- package/dist/services/cleanFormSubmissionModel.js.map +1 -1
- package/dist/services/form-validation.d.ts +3 -3
- package/dist/services/form-validation.js.map +1 -1
- package/dist/services/generate-default-data.d.ts +2 -3
- package/dist/services/generate-default-data.js +3 -1
- package/dist/services/generate-default-data.js.map +1 -1
- package/dist/services/generateFreshdeskDependentFieldElements.js.map +1 -1
- package/dist/services/getDateRangeConfiguration.d.ts +2 -3
- package/dist/services/getDateRangeConfiguration.js.map +1 -1
- package/dist/services/getRepeatableSetEntriesConfiguration.d.ts +2 -3
- package/dist/services/getRepeatableSetEntriesConfiguration.js.map +1 -1
- package/dist/styles/receipt.scss +1 -1
- package/dist/styles/repeatable-set.scss +2 -2
- package/dist/typedoc.d.ts +2 -0
- package/dist/typedoc.js +3 -0
- package/dist/typedoc.js.map +1 -0
- package/dist/types/form.d.ts +5 -6
- package/dist/types/form.js.map +1 -1
- package/package.json +10 -4
package/dist/OneBlinkForm.js
CHANGED
@@ -1,9 +1,555 @@
|
|
1
1
|
import * as React from 'react';
|
2
2
|
import OneBlinkFormBase from './OneBlinkFormBase';
|
3
3
|
import useFormSubmissionState from './hooks/useFormSubmissionState';
|
4
|
+
/**
|
5
|
+
* Similar to {@link OneBlinkForm}, however requires props to control the
|
6
|
+
* `definition` and `submission` values.
|
7
|
+
*
|
8
|
+
* #### Example
|
9
|
+
*
|
10
|
+
* ```tsx
|
11
|
+
* import React from 'react'
|
12
|
+
* import ReactDOM from 'react-dom'
|
13
|
+
* import { FormTypes } from '@oneblink/types'
|
14
|
+
* import {
|
15
|
+
* OneBlinkAppsError,
|
16
|
+
* draftService,
|
17
|
+
* submissionService,
|
18
|
+
* } from '@oneblink/apps'
|
19
|
+
* import {
|
20
|
+
* IsOfflineContextProvider,
|
21
|
+
* OneBlinkFormControlled,
|
22
|
+
* useIsMounted,
|
23
|
+
* useFormSubmissionState,
|
24
|
+
* } from '@oneblink/apps-react'
|
25
|
+
* import '@oneblink/apps-react/dist/styles.css'
|
26
|
+
*
|
27
|
+
* const captchaSiteKey = 'ENTER_YOUR_SITE_KEY_HERE'
|
28
|
+
* const googleMapsApiKey = 'ENTER_YOUR_MAPS_API_KEY_HERE'
|
29
|
+
* const formsAppId = 1
|
30
|
+
* const form: FormTypes.Form = {
|
31
|
+
* id: 1,
|
32
|
+
* name: 'Name of Form',
|
33
|
+
* description: '',
|
34
|
+
* organisationId: 'abc123',
|
35
|
+
* formsAppEnvironmentId: 1,
|
36
|
+
* formsAppIds: [],
|
37
|
+
* elements: [],
|
38
|
+
* isAuthenticated: false,
|
39
|
+
* isMultiPage: false,
|
40
|
+
* isInfoPage: false,
|
41
|
+
* publishStartDate: null,
|
42
|
+
* publishEndDate: null,
|
43
|
+
* postSubmissionAction: 'FORMS_LIBRARY',
|
44
|
+
* submissionEvents: [],
|
45
|
+
* tags: [],
|
46
|
+
* }
|
47
|
+
* const initialSubmission: Record<string, unknown> = {
|
48
|
+
* data: 1,
|
49
|
+
* }
|
50
|
+
*
|
51
|
+
* function FormContainer() {
|
52
|
+
* const isMounted = useIsMounted()
|
53
|
+
*
|
54
|
+
* const [{ definition, submission }, setFormSubmission] =
|
55
|
+
* useFormSubmissionState(form, initialSubmission)
|
56
|
+
*
|
57
|
+
* const [{ isSavingDraft, saveDraftError }, setSaveDraftState] =
|
58
|
+
* React.useState({
|
59
|
+
* isSavingDraft: false,
|
60
|
+
* saveDraftError: null,
|
61
|
+
* })
|
62
|
+
*
|
63
|
+
* const [
|
64
|
+
* { isSubmitting, submitError, formSubmissionResult },
|
65
|
+
* setSubmitState,
|
66
|
+
* ] = React.useState({
|
67
|
+
* formSubmissionResult: null,
|
68
|
+
* isSubmitting: false,
|
69
|
+
* submitError: null,
|
70
|
+
* })
|
71
|
+
*
|
72
|
+
* const handleSubmit = React.useCallback(
|
73
|
+
* async (newFormSubmission: FormTypes.NewFormSubmission) => {
|
74
|
+
* const formSubmission: FormSubmission = Object.assign(
|
75
|
+
* {},
|
76
|
+
* newFormSubmission,
|
77
|
+
* {
|
78
|
+
* formsAppId,
|
79
|
+
* jobId: null,
|
80
|
+
* externalId: null,
|
81
|
+
* draftId: null,
|
82
|
+
* preFillFormDataId: null,
|
83
|
+
* },
|
84
|
+
* )
|
85
|
+
*
|
86
|
+
* setSubmitState({
|
87
|
+
* formSubmissionResult: null,
|
88
|
+
* submitError: null,
|
89
|
+
* isSubmitting: true,
|
90
|
+
* })
|
91
|
+
*
|
92
|
+
* try {
|
93
|
+
* const newFormSubmissionResult = await submissionService.submit({
|
94
|
+
* formSubmission,
|
95
|
+
* })
|
96
|
+
* if (
|
97
|
+
* newFormSubmissionResult.isOffline &&
|
98
|
+
* !newFormSubmissionResult.isInPendingQueue
|
99
|
+
* ) {
|
100
|
+
* throw new OneBlinkAppsError(
|
101
|
+
* 'You cannot submit this form while offline, please try again when connectivity is restored.',
|
102
|
+
* {
|
103
|
+
* isOffline: true,
|
104
|
+
* },
|
105
|
+
* )
|
106
|
+
* }
|
107
|
+
*
|
108
|
+
* if (isMounted.current) {
|
109
|
+
* setSubmitState({
|
110
|
+
* formSubmissionResult: newFormSubmissionResult,
|
111
|
+
* isSubmitting: false,
|
112
|
+
* submitError: null,
|
113
|
+
* })
|
114
|
+
* }
|
115
|
+
* } catch (error) {
|
116
|
+
* if (isMounted.current) {
|
117
|
+
* setSubmitState({
|
118
|
+
* formSubmissionResult: null,
|
119
|
+
* isSubmitting: false,
|
120
|
+
* submitError: error,
|
121
|
+
* })
|
122
|
+
* }
|
123
|
+
* }
|
124
|
+
* },
|
125
|
+
* [isMounted],
|
126
|
+
* )
|
127
|
+
*
|
128
|
+
* const handleSaveDraft = React.useCallback(
|
129
|
+
* async (newDraftSubmission: FormTypes.NewDraftSubmission) => {
|
130
|
+
* const draftSubmission: FormTypes.DraftSubmission = {
|
131
|
+
* ...newDraftSubmission,
|
132
|
+
* formsAppId,
|
133
|
+
* }
|
134
|
+
* setSaveDraftState({
|
135
|
+
* saveDraftError: null,
|
136
|
+
* isSavingDraft: true,
|
137
|
+
* })
|
138
|
+
*
|
139
|
+
* try {
|
140
|
+
* await draftService.addDraft(
|
141
|
+
* {
|
142
|
+
* title: form.name,
|
143
|
+
* formId: form.id,
|
144
|
+
* externalId: null,
|
145
|
+
* jobId: null,
|
146
|
+
* },
|
147
|
+
* draftSubmission,
|
148
|
+
* )
|
149
|
+
*
|
150
|
+
* if (isMounted.current) {
|
151
|
+
* setSaveDraftState({
|
152
|
+
* saveDraftError: null,
|
153
|
+
* isSavingDraft: false,
|
154
|
+
* })
|
155
|
+
* }
|
156
|
+
* } catch (error) {
|
157
|
+
* if (isMounted.current) {
|
158
|
+
* setSaveDraftState({
|
159
|
+
* saveDraftError: error,
|
160
|
+
* isSavingDraft: false,
|
161
|
+
* })
|
162
|
+
* }
|
163
|
+
* }
|
164
|
+
* },
|
165
|
+
* [isMounted],
|
166
|
+
* )
|
167
|
+
*
|
168
|
+
* const handleCancel = React.useCallback(() => {
|
169
|
+
* // handle cancel here...
|
170
|
+
* }, [])
|
171
|
+
*
|
172
|
+
* if (isSubmitting) {
|
173
|
+
* // Render submitting animation/loading
|
174
|
+
* }
|
175
|
+
*
|
176
|
+
* if (submitError) {
|
177
|
+
* // Render error while submitting
|
178
|
+
* }
|
179
|
+
*
|
180
|
+
* if (isSavingDraft) {
|
181
|
+
* // Render saving draft animation/loading
|
182
|
+
* }
|
183
|
+
*
|
184
|
+
* if (saveDraftError) {
|
185
|
+
* // Render error while saving draft
|
186
|
+
* }
|
187
|
+
*
|
188
|
+
* if (formSubmissionResult) {
|
189
|
+
* // Render submission success
|
190
|
+
* }
|
191
|
+
*
|
192
|
+
* return (
|
193
|
+
* <OneBlinkFormControlled
|
194
|
+
* captchaSiteKey={captchaSiteKey}
|
195
|
+
* googleMapsApiKey={googleMapsApiKey}
|
196
|
+
* formsAppId={formsAppId}
|
197
|
+
* definition={definition}
|
198
|
+
* submission={submission}
|
199
|
+
* setFormSubmission={setFormSubmission}
|
200
|
+
* onCancel={handleCancel}
|
201
|
+
* onSubmit={handleSubmit}
|
202
|
+
* onSaveDraft={handleSaveDraft}
|
203
|
+
* />
|
204
|
+
* )
|
205
|
+
* }
|
206
|
+
*
|
207
|
+
* function App() {
|
208
|
+
* return (
|
209
|
+
* <IsOfflineContextProvider>
|
210
|
+
* <FormContainer />
|
211
|
+
* </IsOfflineContextProvider>
|
212
|
+
* )
|
213
|
+
* }
|
214
|
+
*
|
215
|
+
* const root = document.getElementById('root')
|
216
|
+
* if (root) {
|
217
|
+
* ReactDOM.render(<App />, root)
|
218
|
+
* }
|
219
|
+
* ```
|
220
|
+
*
|
221
|
+
* #### Implementing Controlled Auto Save
|
222
|
+
*
|
223
|
+
* The {@link OneBlinkAutoSaveForm} component does not offer props to allow for a
|
224
|
+
* controlled form (i.e. having access to `submission` and `definition` values).
|
225
|
+
* To implement a controlled version of the `<OneBlinkAutoSaveForm />`
|
226
|
+
* component, use the example component below.
|
227
|
+
*
|
228
|
+
* ```tsx
|
229
|
+
* import * as React from 'react'
|
230
|
+
* import {
|
231
|
+
* OneBlinkAutoSaveForm,
|
232
|
+
* OneBlinkFormControlled,
|
233
|
+
* useFormSubmissionAutoSaveState,
|
234
|
+
* } from '@oneblink/apps-react'
|
235
|
+
*
|
236
|
+
* function OneBlinkAutoSaveFormControlled({
|
237
|
+
* form,
|
238
|
+
* initialSubmission,
|
239
|
+
* autoSaveKey,
|
240
|
+
* onCancel,
|
241
|
+
* onSubmit,
|
242
|
+
* onSaveDraft,
|
243
|
+
* ...props
|
244
|
+
* }: React.ComponentProps<typeof OneBlinkAutoSaveForm>) {
|
245
|
+
* const {
|
246
|
+
* definition,
|
247
|
+
* submission,
|
248
|
+
* isLoadingAutoSaveSubmission,
|
249
|
+
* isAutoSaveSubmissionAvailable,
|
250
|
+
* startNewSubmission,
|
251
|
+
* continueAutoSaveSubmission,
|
252
|
+
* handleSubmit,
|
253
|
+
* handleCancel,
|
254
|
+
* handleSaveDraft,
|
255
|
+
* setFormSubmission,
|
256
|
+
* } = useFormSubmissionAutoSaveState({
|
257
|
+
* form,
|
258
|
+
* initialSubmission,
|
259
|
+
* autoSaveKey,
|
260
|
+
* onCancel,
|
261
|
+
* onSubmit,
|
262
|
+
* onSaveDraft,
|
263
|
+
* })
|
264
|
+
*
|
265
|
+
* // This is just an example of how you could intercept
|
266
|
+
* // the change event when a user enters/selects a value
|
267
|
+
* // on the form.
|
268
|
+
* const customSetFormSubmission = React.useCallback(
|
269
|
+
* (formSubmission) => {
|
270
|
+
* setFormSubmission((currentFormSubmission) => {
|
271
|
+
* const newFormSubmission =
|
272
|
+
* typeof formSubmission === 'function'
|
273
|
+
* ? formSubmission(currentFormSubmission)
|
274
|
+
* : formSubmission
|
275
|
+
*
|
276
|
+
* // This is where you can access the updated
|
277
|
+
* // submission data or form definition.
|
278
|
+
* // You could even change the form definition
|
279
|
+
* // programmatically based on user inputs.
|
280
|
+
* console.log(
|
281
|
+
* 'A change has occurred to the submission',
|
282
|
+
* newFormSubmission.submission,
|
283
|
+
* )
|
284
|
+
* newFormSubmission.definition.isInfoPage =
|
285
|
+
* !newFormSubmission.submission.doesTheUserNeedToSubmit
|
286
|
+
*
|
287
|
+
* return newFormSubmission
|
288
|
+
* })
|
289
|
+
* },
|
290
|
+
* [setFormSubmission],
|
291
|
+
* )
|
292
|
+
*
|
293
|
+
* if (isLoadingAutoSaveSubmission) {
|
294
|
+
* return <p>Checking for auto save data...</p>
|
295
|
+
* }
|
296
|
+
*
|
297
|
+
* if (isAutoSaveSubmissionAvailable) {
|
298
|
+
* return (
|
299
|
+
* <>
|
300
|
+
* <p>Do you want to use the auto save data?</p>
|
301
|
+
* <button onClick={startNewSubmission}>No, start again</button>
|
302
|
+
* <button onClick={continueAutoSaveSubmission}>
|
303
|
+
* Yes, continue
|
304
|
+
* </button>
|
305
|
+
* </>
|
306
|
+
* )
|
307
|
+
* }
|
308
|
+
*
|
309
|
+
* return (
|
310
|
+
* <OneBlinkFormControlled
|
311
|
+
* {...props}
|
312
|
+
* submission={submission}
|
313
|
+
* definition={definition}
|
314
|
+
* onCancel={handleCancel}
|
315
|
+
* onSubmit={handleSubmit}
|
316
|
+
* onSaveDraft={handleSaveDraft}
|
317
|
+
* setFormSubmission={customSetFormSubmission}
|
318
|
+
* />
|
319
|
+
* )
|
320
|
+
* }
|
321
|
+
*
|
322
|
+
* export default React.memo(OneBlinkAutoSaveFormControlled)
|
323
|
+
* ```
|
324
|
+
*
|
325
|
+
* @param props
|
326
|
+
* @returns
|
327
|
+
* @group Components
|
328
|
+
*/
|
4
329
|
const OneBlinkFormControlled = React.memo(function OneBlinkFormControlled(props) {
|
5
330
|
return React.createElement(OneBlinkFormBase, { ...props, isReadOnly: false });
|
6
331
|
});
|
332
|
+
/**
|
333
|
+
* Component for rendering a OneBlink Form. This component will render the
|
334
|
+
* submit, cancel and save draft buttons but it is up to the developer to
|
335
|
+
* implement what happens when those buttons are clicked.
|
336
|
+
*
|
337
|
+
* It is also recommended to import the `css` from this library as well.
|
338
|
+
*
|
339
|
+
* ```js
|
340
|
+
* import { OneBlinkForm } from '@oneblink/apps-react'
|
341
|
+
* import '@oneblink/apps-react/dist/styles.css'
|
342
|
+
* ```
|
343
|
+
*
|
344
|
+
* #### Example
|
345
|
+
*
|
346
|
+
* ```tsx
|
347
|
+
* import React from 'react'
|
348
|
+
* import ReactDOM from 'react-dom'
|
349
|
+
* import { FormTypes } from '@oneblink/types'
|
350
|
+
* import {
|
351
|
+
* OneBlinkAppsError,
|
352
|
+
* draftService,
|
353
|
+
* submissionService,
|
354
|
+
* } from '@oneblink/apps'
|
355
|
+
* import {
|
356
|
+
* IsOfflineContextProvider,
|
357
|
+
* OneBlinkForm,
|
358
|
+
* useIsMounted,
|
359
|
+
* } from '@oneblink/apps-react'
|
360
|
+
* import '@oneblink/apps-react/dist/styles.css'
|
361
|
+
*
|
362
|
+
* const captchaSiteKey = 'ENTER_YOUR_SITE_KEY_HERE'
|
363
|
+
* const googleMapsApiKey = 'ENTER_YOUR_MAPS_API_KEY_HERE'
|
364
|
+
* const formsAppId = 1
|
365
|
+
* const form: FormTypes.Form = {
|
366
|
+
* id: 1,
|
367
|
+
* name: 'Name of Form',
|
368
|
+
* description: '',
|
369
|
+
* organisationId: 'abc123',
|
370
|
+
* formsAppEnvironmentId: 1,
|
371
|
+
* formsAppIds: [],
|
372
|
+
* elements: [],
|
373
|
+
* isAuthenticated: false,
|
374
|
+
* isMultiPage: false,
|
375
|
+
* isInfoPage: false,
|
376
|
+
* publishStartDate: null,
|
377
|
+
* publishEndDate: null,
|
378
|
+
* postSubmissionAction: 'FORMS_LIBRARY',
|
379
|
+
* submissionEvents: [],
|
380
|
+
* tags: [],
|
381
|
+
* }
|
382
|
+
*
|
383
|
+
* function FormContainer() {
|
384
|
+
* const isMounted = useIsMounted()
|
385
|
+
*
|
386
|
+
* const [{ isSavingDraft, saveDraftError }, setSaveDraftState] =
|
387
|
+
* React.useState({
|
388
|
+
* isSavingDraft: false,
|
389
|
+
* saveDraftError: null,
|
390
|
+
* })
|
391
|
+
*
|
392
|
+
* const [
|
393
|
+
* { isSubmitting, submitError, formSubmissionResult },
|
394
|
+
* setSubmitState,
|
395
|
+
* ] = React.useState({
|
396
|
+
* formSubmissionResult: null,
|
397
|
+
* isSubmitting: false,
|
398
|
+
* submitError: null,
|
399
|
+
* })
|
400
|
+
*
|
401
|
+
* const handleSubmit = React.useCallback(
|
402
|
+
* async (newFormSubmission: FormTypes.NewFormSubmission) => {
|
403
|
+
* const formSubmission: FormSubmission = Object.assign(
|
404
|
+
* {},
|
405
|
+
* newFormSubmission,
|
406
|
+
* {
|
407
|
+
* formsAppId,
|
408
|
+
* jobId: null,
|
409
|
+
* externalId: null,
|
410
|
+
* draftId: null,
|
411
|
+
* preFillFormDataId: null,
|
412
|
+
* },
|
413
|
+
* )
|
414
|
+
*
|
415
|
+
* setSubmitState({
|
416
|
+
* formSubmissionResult: null,
|
417
|
+
* submitError: null,
|
418
|
+
* isSubmitting: true,
|
419
|
+
* })
|
420
|
+
*
|
421
|
+
* try {
|
422
|
+
* const newFormSubmissionResult = await submissionService.submit({
|
423
|
+
* formSubmission,
|
424
|
+
* })
|
425
|
+
* if (
|
426
|
+
* newFormSubmissionResult.isOffline &&
|
427
|
+
* !newFormSubmissionResult.isInPendingQueue
|
428
|
+
* ) {
|
429
|
+
* throw new OneBlinkAppsError(
|
430
|
+
* 'You cannot submit this form while offline, please try again when connectivity is restored.',
|
431
|
+
* {
|
432
|
+
* isOffline: true,
|
433
|
+
* },
|
434
|
+
* )
|
435
|
+
* }
|
436
|
+
*
|
437
|
+
* if (isMounted.current) {
|
438
|
+
* setSubmitState({
|
439
|
+
* formSubmissionResult: newFormSubmissionResult,
|
440
|
+
* isSubmitting: false,
|
441
|
+
* submitError: null,
|
442
|
+
* })
|
443
|
+
* }
|
444
|
+
* } catch (error) {
|
445
|
+
* if (isMounted.current) {
|
446
|
+
* setSubmitState({
|
447
|
+
* formSubmissionResult: null,
|
448
|
+
* isSubmitting: false,
|
449
|
+
* submitError: error,
|
450
|
+
* })
|
451
|
+
* }
|
452
|
+
* }
|
453
|
+
* },
|
454
|
+
* [isMounted],
|
455
|
+
* )
|
456
|
+
*
|
457
|
+
* const handleSaveDraft = React.useCallback(
|
458
|
+
* async (newDraftSubmission: FormTypes.NewDraftSubmission) => {
|
459
|
+
* const draftSubmission: FormTypes.DraftSubmission = {
|
460
|
+
* ...newDraftSubmission,
|
461
|
+
* formsAppId,
|
462
|
+
* }
|
463
|
+
* setSaveDraftState({
|
464
|
+
* saveDraftError: null,
|
465
|
+
* isSavingDraft: true,
|
466
|
+
* })
|
467
|
+
*
|
468
|
+
* try {
|
469
|
+
* await draftService.addDraft(
|
470
|
+
* {
|
471
|
+
* title: form.name,
|
472
|
+
* formId: form.id,
|
473
|
+
* externalId: null,
|
474
|
+
* jobId: null,
|
475
|
+
* },
|
476
|
+
* draftSubmission,
|
477
|
+
* )
|
478
|
+
*
|
479
|
+
* if (isMounted.current) {
|
480
|
+
* setSaveDraftState({
|
481
|
+
* saveDraftError: null,
|
482
|
+
* isSavingDraft: false,
|
483
|
+
* })
|
484
|
+
* }
|
485
|
+
* } catch (error) {
|
486
|
+
* if (isMounted.current) {
|
487
|
+
* setSaveDraftState({
|
488
|
+
* saveDraftError: error,
|
489
|
+
* isSavingDraft: false,
|
490
|
+
* })
|
491
|
+
* }
|
492
|
+
* }
|
493
|
+
* },
|
494
|
+
* [isMounted],
|
495
|
+
* )
|
496
|
+
*
|
497
|
+
* const handleCancel = React.useCallback(() => {
|
498
|
+
* // handle cancel here...
|
499
|
+
* }, [isMounted])
|
500
|
+
*
|
501
|
+
* if (isSubmitting) {
|
502
|
+
* // Render submitting animation/loading
|
503
|
+
* }
|
504
|
+
*
|
505
|
+
* if (submitError) {
|
506
|
+
* // Render error while submitting
|
507
|
+
* }
|
508
|
+
*
|
509
|
+
* if (isSavingDraft) {
|
510
|
+
* // Render saving draft animation/loading
|
511
|
+
* }
|
512
|
+
*
|
513
|
+
* if (saveDraftError) {
|
514
|
+
* // Render error while saving draft
|
515
|
+
* }
|
516
|
+
*
|
517
|
+
* if (formSubmissionResult) {
|
518
|
+
* // Render submission success
|
519
|
+
* }
|
520
|
+
*
|
521
|
+
* return (
|
522
|
+
* <OneBlinkForm
|
523
|
+
* captchaSiteKey={captchaSiteKey}
|
524
|
+
* googleMapsApiKey={googleMapsApiKey}
|
525
|
+
* formsAppId={formsAppId}
|
526
|
+
* form={form}
|
527
|
+
* onCancel={handleCancel}
|
528
|
+
* onSubmit={handleSubmit}
|
529
|
+
* onSaveDraft={handleSaveDraft}
|
530
|
+
* attachmentRetentionInDays={1}
|
531
|
+
* />
|
532
|
+
* )
|
533
|
+
* }
|
534
|
+
*
|
535
|
+
* function App() {
|
536
|
+
* return (
|
537
|
+
* <IsOfflineContextProvider>
|
538
|
+
* <FormContainer />
|
539
|
+
* </IsOfflineContextProvider>
|
540
|
+
* )
|
541
|
+
* }
|
542
|
+
*
|
543
|
+
* const root = document.getElementById('root')
|
544
|
+
* if (root) {
|
545
|
+
* ReactDOM.render(<App />, root)
|
546
|
+
* }
|
547
|
+
* ```
|
548
|
+
*
|
549
|
+
* @param props
|
550
|
+
* @returns
|
551
|
+
* @group Components
|
552
|
+
*/
|
7
553
|
const OneBlinkFormUncontrolled = React.memo(function OneBlinkFormUncontrolled({ form, initialSubmission, resumeAtElement, ...props }) {
|
8
554
|
const [{ definition, submission, lastElementUpdated }, setFormSubmission] = useFormSubmissionState(form, initialSubmission, resumeAtElement);
|
9
555
|
return (React.createElement(OneBlinkFormBase, { ...props, isReadOnly: false, definition: definition, submission: submission, setFormSubmission: setFormSubmission, lastElementUpdated: lastElementUpdated }));
|
package/dist/OneBlinkForm.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"OneBlinkForm.js","sourceRoot":"","sources":["../src/OneBlinkForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,gBAGN,MAAM,oBAAoB,CAAA;AAC3B,OAAO,sBAAsB,MAAM,gCAAgC,CAAA;AAGnE,MAAM,sBAAsB,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,sBAAsB,CACvE,KAAkC;IAElC,OAAO,oBAAC,gBAAgB,OAAK,KAAK,EAAE,UAAU,EAAE,KAAK,GAAI,CAAA;AAC3D,CAAC,CAAC,CAAA;AAQF,MAAM,wBAAwB,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,wBAAwB,CAAC,EAC5E,IAAI,EACJ,iBAAiB,EACjB,eAAe,EACf,GAAG,KAAK,EACsB;IAC9B,MAAM,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,kBAAkB,EAAE,EAAE,iBAAiB,CAAC,GACvE,sBAAsB,CAAC,IAAI,EAAE,iBAAiB,EAAE,eAAe,CAAC,CAAA;IAClE,OAAO,CACL,oBAAC,gBAAgB,OACX,KAAK,EACT,UAAU,EAAE,KAAK,EACjB,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,iBAAiB,EACpC,kBAAkB,EAAE,kBAAkB,GACtC,CACH,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,CAAA","sourcesContent":["import * as React from 'react'\nimport { FormTypes } from '@oneblink/types'\nimport OneBlinkFormBase, {\n BaseProps,\n ControlledProps,\n} from './OneBlinkFormBase'\nimport useFormSubmissionState from './hooks/useFormSubmissionState'\nimport { FormSubmissionModel } from './types/form'\n\nconst OneBlinkFormControlled = React.memo(function OneBlinkFormControlled(\n props: BaseProps & ControlledProps,\n) {\n return <OneBlinkFormBase {...props} isReadOnly={false} />\n})\n\ntype UncontrolledProps = {\n form: FormTypes.Form\n initialSubmission?: FormSubmissionModel\n resumeAtElement?: FormTypes.FormElement\n}\n\nconst OneBlinkFormUncontrolled = React.memo(function OneBlinkFormUncontrolled({\n form,\n initialSubmission,\n resumeAtElement,\n ...props\n}: BaseProps & UncontrolledProps) {\n const [{ definition, submission, lastElementUpdated }, setFormSubmission] =\n useFormSubmissionState(form, initialSubmission, resumeAtElement)\n return (\n <OneBlinkFormBase\n {...props}\n isReadOnly={false}\n definition={definition}\n submission={submission}\n setFormSubmission={setFormSubmission}\n lastElementUpdated={lastElementUpdated}\n />\n )\n})\n\nexport { OneBlinkFormControlled, OneBlinkFormUncontrolled }\n"]}
|
1
|
+
{"version":3,"file":"OneBlinkForm.js","sourceRoot":"","sources":["../src/OneBlinkForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,gBAGN,MAAM,oBAAoB,CAAA;AAC3B,OAAO,sBAAsB,MAAM,gCAAgC,CAAA;AAInE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoUG;AACH,MAAM,sBAAsB,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,sBAAsB,CACvE,KAA0D;IAE1D,OAAO,oBAAC,gBAAgB,OAAK,KAAK,EAAE,UAAU,EAAE,KAAK,GAAI,CAAA;AAC3D,CAAC,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4NG;AACH,MAAM,wBAAwB,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,wBAAwB,CAAC,EAC5E,IAAI,EACJ,iBAAiB,EACjB,eAAe,EACf,GAAG,KAAK,EAQT;IACC,MAAM,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,kBAAkB,EAAE,EAAE,iBAAiB,CAAC,GACvE,sBAAsB,CAAC,IAAI,EAAE,iBAAiB,EAAE,eAAe,CAAC,CAAA;IAClE,OAAO,CACL,oBAAC,gBAAgB,OACX,KAAK,EACT,UAAU,EAAE,KAAK,EACjB,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,iBAAiB,EACpC,kBAAkB,EAAE,kBAAkB,GACtC,CACH,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,CAAA","sourcesContent":["import * as React from 'react'\nimport { FormTypes, SubmissionTypes } from '@oneblink/types'\nimport OneBlinkFormBase, {\n OneBlinkFormBaseProps,\n OneBlinkFormControlledProps,\n} from './OneBlinkFormBase'\nimport useFormSubmissionState from './hooks/useFormSubmissionState'\n\nexport { OneBlinkFormBaseProps, OneBlinkFormControlledProps }\n\n/**\n * Similar to {@link OneBlinkForm}, however requires props to control the\n * `definition` and `submission` values.\n *\n * #### Example\n *\n * ```tsx\n * import React from 'react'\n * import ReactDOM from 'react-dom'\n * import { FormTypes } from '@oneblink/types'\n * import {\n * OneBlinkAppsError,\n * draftService,\n * submissionService,\n * } from '@oneblink/apps'\n * import {\n * IsOfflineContextProvider,\n * OneBlinkFormControlled,\n * useIsMounted,\n * useFormSubmissionState,\n * } from '@oneblink/apps-react'\n * import '@oneblink/apps-react/dist/styles.css'\n *\n * const captchaSiteKey = 'ENTER_YOUR_SITE_KEY_HERE'\n * const googleMapsApiKey = 'ENTER_YOUR_MAPS_API_KEY_HERE'\n * const formsAppId = 1\n * const form: FormTypes.Form = {\n * id: 1,\n * name: 'Name of Form',\n * description: '',\n * organisationId: 'abc123',\n * formsAppEnvironmentId: 1,\n * formsAppIds: [],\n * elements: [],\n * isAuthenticated: false,\n * isMultiPage: false,\n * isInfoPage: false,\n * publishStartDate: null,\n * publishEndDate: null,\n * postSubmissionAction: 'FORMS_LIBRARY',\n * submissionEvents: [],\n * tags: [],\n * }\n * const initialSubmission: Record<string, unknown> = {\n * data: 1,\n * }\n *\n * function FormContainer() {\n * const isMounted = useIsMounted()\n *\n * const [{ definition, submission }, setFormSubmission] =\n * useFormSubmissionState(form, initialSubmission)\n *\n * const [{ isSavingDraft, saveDraftError }, setSaveDraftState] =\n * React.useState({\n * isSavingDraft: false,\n * saveDraftError: null,\n * })\n *\n * const [\n * { isSubmitting, submitError, formSubmissionResult },\n * setSubmitState,\n * ] = React.useState({\n * formSubmissionResult: null,\n * isSubmitting: false,\n * submitError: null,\n * })\n *\n * const handleSubmit = React.useCallback(\n * async (newFormSubmission: FormTypes.NewFormSubmission) => {\n * const formSubmission: FormSubmission = Object.assign(\n * {},\n * newFormSubmission,\n * {\n * formsAppId,\n * jobId: null,\n * externalId: null,\n * draftId: null,\n * preFillFormDataId: null,\n * },\n * )\n *\n * setSubmitState({\n * formSubmissionResult: null,\n * submitError: null,\n * isSubmitting: true,\n * })\n *\n * try {\n * const newFormSubmissionResult = await submissionService.submit({\n * formSubmission,\n * })\n * if (\n * newFormSubmissionResult.isOffline &&\n * !newFormSubmissionResult.isInPendingQueue\n * ) {\n * throw new OneBlinkAppsError(\n * 'You cannot submit this form while offline, please try again when connectivity is restored.',\n * {\n * isOffline: true,\n * },\n * )\n * }\n *\n * if (isMounted.current) {\n * setSubmitState({\n * formSubmissionResult: newFormSubmissionResult,\n * isSubmitting: false,\n * submitError: null,\n * })\n * }\n * } catch (error) {\n * if (isMounted.current) {\n * setSubmitState({\n * formSubmissionResult: null,\n * isSubmitting: false,\n * submitError: error,\n * })\n * }\n * }\n * },\n * [isMounted],\n * )\n *\n * const handleSaveDraft = React.useCallback(\n * async (newDraftSubmission: FormTypes.NewDraftSubmission) => {\n * const draftSubmission: FormTypes.DraftSubmission = {\n * ...newDraftSubmission,\n * formsAppId,\n * }\n * setSaveDraftState({\n * saveDraftError: null,\n * isSavingDraft: true,\n * })\n *\n * try {\n * await draftService.addDraft(\n * {\n * title: form.name,\n * formId: form.id,\n * externalId: null,\n * jobId: null,\n * },\n * draftSubmission,\n * )\n *\n * if (isMounted.current) {\n * setSaveDraftState({\n * saveDraftError: null,\n * isSavingDraft: false,\n * })\n * }\n * } catch (error) {\n * if (isMounted.current) {\n * setSaveDraftState({\n * saveDraftError: error,\n * isSavingDraft: false,\n * })\n * }\n * }\n * },\n * [isMounted],\n * )\n *\n * const handleCancel = React.useCallback(() => {\n * // handle cancel here...\n * }, [])\n *\n * if (isSubmitting) {\n * // Render submitting animation/loading\n * }\n *\n * if (submitError) {\n * // Render error while submitting\n * }\n *\n * if (isSavingDraft) {\n * // Render saving draft animation/loading\n * }\n *\n * if (saveDraftError) {\n * // Render error while saving draft\n * }\n *\n * if (formSubmissionResult) {\n * // Render submission success\n * }\n *\n * return (\n * <OneBlinkFormControlled\n * captchaSiteKey={captchaSiteKey}\n * googleMapsApiKey={googleMapsApiKey}\n * formsAppId={formsAppId}\n * definition={definition}\n * submission={submission}\n * setFormSubmission={setFormSubmission}\n * onCancel={handleCancel}\n * onSubmit={handleSubmit}\n * onSaveDraft={handleSaveDraft}\n * />\n * )\n * }\n *\n * function App() {\n * return (\n * <IsOfflineContextProvider>\n * <FormContainer />\n * </IsOfflineContextProvider>\n * )\n * }\n *\n * const root = document.getElementById('root')\n * if (root) {\n * ReactDOM.render(<App />, root)\n * }\n * ```\n *\n * #### Implementing Controlled Auto Save\n *\n * The {@link OneBlinkAutoSaveForm} component does not offer props to allow for a\n * controlled form (i.e. having access to `submission` and `definition` values).\n * To implement a controlled version of the `<OneBlinkAutoSaveForm />`\n * component, use the example component below.\n *\n * ```tsx\n * import * as React from 'react'\n * import {\n * OneBlinkAutoSaveForm,\n * OneBlinkFormControlled,\n * useFormSubmissionAutoSaveState,\n * } from '@oneblink/apps-react'\n *\n * function OneBlinkAutoSaveFormControlled({\n * form,\n * initialSubmission,\n * autoSaveKey,\n * onCancel,\n * onSubmit,\n * onSaveDraft,\n * ...props\n * }: React.ComponentProps<typeof OneBlinkAutoSaveForm>) {\n * const {\n * definition,\n * submission,\n * isLoadingAutoSaveSubmission,\n * isAutoSaveSubmissionAvailable,\n * startNewSubmission,\n * continueAutoSaveSubmission,\n * handleSubmit,\n * handleCancel,\n * handleSaveDraft,\n * setFormSubmission,\n * } = useFormSubmissionAutoSaveState({\n * form,\n * initialSubmission,\n * autoSaveKey,\n * onCancel,\n * onSubmit,\n * onSaveDraft,\n * })\n *\n * // This is just an example of how you could intercept\n * // the change event when a user enters/selects a value\n * // on the form.\n * const customSetFormSubmission = React.useCallback(\n * (formSubmission) => {\n * setFormSubmission((currentFormSubmission) => {\n * const newFormSubmission =\n * typeof formSubmission === 'function'\n * ? formSubmission(currentFormSubmission)\n * : formSubmission\n *\n * // This is where you can access the updated\n * // submission data or form definition.\n * // You could even change the form definition\n * // programmatically based on user inputs.\n * console.log(\n * 'A change has occurred to the submission',\n * newFormSubmission.submission,\n * )\n * newFormSubmission.definition.isInfoPage =\n * !newFormSubmission.submission.doesTheUserNeedToSubmit\n *\n * return newFormSubmission\n * })\n * },\n * [setFormSubmission],\n * )\n *\n * if (isLoadingAutoSaveSubmission) {\n * return <p>Checking for auto save data...</p>\n * }\n *\n * if (isAutoSaveSubmissionAvailable) {\n * return (\n * <>\n * <p>Do you want to use the auto save data?</p>\n * <button onClick={startNewSubmission}>No, start again</button>\n * <button onClick={continueAutoSaveSubmission}>\n * Yes, continue\n * </button>\n * </>\n * )\n * }\n *\n * return (\n * <OneBlinkFormControlled\n * {...props}\n * submission={submission}\n * definition={definition}\n * onCancel={handleCancel}\n * onSubmit={handleSubmit}\n * onSaveDraft={handleSaveDraft}\n * setFormSubmission={customSetFormSubmission}\n * />\n * )\n * }\n *\n * export default React.memo(OneBlinkAutoSaveFormControlled)\n * ```\n *\n * @param props\n * @returns\n * @group Components\n */\nconst OneBlinkFormControlled = React.memo(function OneBlinkFormControlled(\n props: OneBlinkFormBaseProps & OneBlinkFormControlledProps,\n) {\n return <OneBlinkFormBase {...props} isReadOnly={false} />\n})\n\n/**\n * Component for rendering a OneBlink Form. This component will render the\n * submit, cancel and save draft buttons but it is up to the developer to\n * implement what happens when those buttons are clicked.\n *\n * It is also recommended to import the `css` from this library as well.\n *\n * ```js\n * import { OneBlinkForm } from '@oneblink/apps-react'\n * import '@oneblink/apps-react/dist/styles.css'\n * ```\n *\n * #### Example\n *\n * ```tsx\n * import React from 'react'\n * import ReactDOM from 'react-dom'\n * import { FormTypes } from '@oneblink/types'\n * import {\n * OneBlinkAppsError,\n * draftService,\n * submissionService,\n * } from '@oneblink/apps'\n * import {\n * IsOfflineContextProvider,\n * OneBlinkForm,\n * useIsMounted,\n * } from '@oneblink/apps-react'\n * import '@oneblink/apps-react/dist/styles.css'\n *\n * const captchaSiteKey = 'ENTER_YOUR_SITE_KEY_HERE'\n * const googleMapsApiKey = 'ENTER_YOUR_MAPS_API_KEY_HERE'\n * const formsAppId = 1\n * const form: FormTypes.Form = {\n * id: 1,\n * name: 'Name of Form',\n * description: '',\n * organisationId: 'abc123',\n * formsAppEnvironmentId: 1,\n * formsAppIds: [],\n * elements: [],\n * isAuthenticated: false,\n * isMultiPage: false,\n * isInfoPage: false,\n * publishStartDate: null,\n * publishEndDate: null,\n * postSubmissionAction: 'FORMS_LIBRARY',\n * submissionEvents: [],\n * tags: [],\n * }\n *\n * function FormContainer() {\n * const isMounted = useIsMounted()\n *\n * const [{ isSavingDraft, saveDraftError }, setSaveDraftState] =\n * React.useState({\n * isSavingDraft: false,\n * saveDraftError: null,\n * })\n *\n * const [\n * { isSubmitting, submitError, formSubmissionResult },\n * setSubmitState,\n * ] = React.useState({\n * formSubmissionResult: null,\n * isSubmitting: false,\n * submitError: null,\n * })\n *\n * const handleSubmit = React.useCallback(\n * async (newFormSubmission: FormTypes.NewFormSubmission) => {\n * const formSubmission: FormSubmission = Object.assign(\n * {},\n * newFormSubmission,\n * {\n * formsAppId,\n * jobId: null,\n * externalId: null,\n * draftId: null,\n * preFillFormDataId: null,\n * },\n * )\n *\n * setSubmitState({\n * formSubmissionResult: null,\n * submitError: null,\n * isSubmitting: true,\n * })\n *\n * try {\n * const newFormSubmissionResult = await submissionService.submit({\n * formSubmission,\n * })\n * if (\n * newFormSubmissionResult.isOffline &&\n * !newFormSubmissionResult.isInPendingQueue\n * ) {\n * throw new OneBlinkAppsError(\n * 'You cannot submit this form while offline, please try again when connectivity is restored.',\n * {\n * isOffline: true,\n * },\n * )\n * }\n *\n * if (isMounted.current) {\n * setSubmitState({\n * formSubmissionResult: newFormSubmissionResult,\n * isSubmitting: false,\n * submitError: null,\n * })\n * }\n * } catch (error) {\n * if (isMounted.current) {\n * setSubmitState({\n * formSubmissionResult: null,\n * isSubmitting: false,\n * submitError: error,\n * })\n * }\n * }\n * },\n * [isMounted],\n * )\n *\n * const handleSaveDraft = React.useCallback(\n * async (newDraftSubmission: FormTypes.NewDraftSubmission) => {\n * const draftSubmission: FormTypes.DraftSubmission = {\n * ...newDraftSubmission,\n * formsAppId,\n * }\n * setSaveDraftState({\n * saveDraftError: null,\n * isSavingDraft: true,\n * })\n *\n * try {\n * await draftService.addDraft(\n * {\n * title: form.name,\n * formId: form.id,\n * externalId: null,\n * jobId: null,\n * },\n * draftSubmission,\n * )\n *\n * if (isMounted.current) {\n * setSaveDraftState({\n * saveDraftError: null,\n * isSavingDraft: false,\n * })\n * }\n * } catch (error) {\n * if (isMounted.current) {\n * setSaveDraftState({\n * saveDraftError: error,\n * isSavingDraft: false,\n * })\n * }\n * }\n * },\n * [isMounted],\n * )\n *\n * const handleCancel = React.useCallback(() => {\n * // handle cancel here...\n * }, [isMounted])\n *\n * if (isSubmitting) {\n * // Render submitting animation/loading\n * }\n *\n * if (submitError) {\n * // Render error while submitting\n * }\n *\n * if (isSavingDraft) {\n * // Render saving draft animation/loading\n * }\n *\n * if (saveDraftError) {\n * // Render error while saving draft\n * }\n *\n * if (formSubmissionResult) {\n * // Render submission success\n * }\n *\n * return (\n * <OneBlinkForm\n * captchaSiteKey={captchaSiteKey}\n * googleMapsApiKey={googleMapsApiKey}\n * formsAppId={formsAppId}\n * form={form}\n * onCancel={handleCancel}\n * onSubmit={handleSubmit}\n * onSaveDraft={handleSaveDraft}\n * attachmentRetentionInDays={1}\n * />\n * )\n * }\n *\n * function App() {\n * return (\n * <IsOfflineContextProvider>\n * <FormContainer />\n * </IsOfflineContextProvider>\n * )\n * }\n *\n * const root = document.getElementById('root')\n * if (root) {\n * ReactDOM.render(<App />, root)\n * }\n * ```\n *\n * @param props\n * @returns\n * @group Components\n */\nconst OneBlinkFormUncontrolled = React.memo(function OneBlinkFormUncontrolled({\n form,\n initialSubmission,\n resumeAtElement,\n ...props\n}: OneBlinkFormBaseProps & {\n /** The OneBlink Form to render */\n form: FormTypes.Form\n /** The initial submission data */\n initialSubmission?: SubmissionTypes.S3SubmissionData['submission']\n /** The element to resume the form at. */\n resumeAtElement?: FormTypes.FormElement\n}) {\n const [{ definition, submission, lastElementUpdated }, setFormSubmission] =\n useFormSubmissionState(form, initialSubmission, resumeAtElement)\n return (\n <OneBlinkFormBase\n {...props}\n isReadOnly={false}\n definition={definition}\n submission={submission}\n setFormSubmission={setFormSubmission}\n lastElementUpdated={lastElementUpdated}\n />\n )\n})\n\nexport { OneBlinkFormControlled, OneBlinkFormUncontrolled }\n"]}
|
@@ -1,30 +1,75 @@
|
|
1
1
|
import * as React from 'react';
|
2
2
|
import { submissionService } from '@oneblink/apps';
|
3
|
-
import { FormTypes, FormsAppsTypes } from '@oneblink/types';
|
4
|
-
import {
|
5
|
-
export type
|
3
|
+
import { FormTypes, FormsAppsTypes, SubmissionTypes } from '@oneblink/types';
|
4
|
+
import { SetFormSubmission } from './types/form';
|
5
|
+
export type OneBlinkFormBaseProps = {
|
6
|
+
/** The function to call when the user cancels the form */
|
6
7
|
onCancel: () => unknown;
|
8
|
+
/**
|
9
|
+
* The function to call when the user submits the form with valid submission
|
10
|
+
* data. See
|
11
|
+
* [NewFormSubmission](https://oneblink.github.io/apps/modules/submissionService.html#NewFormSubmission)
|
12
|
+
* for the structure of the argument.
|
13
|
+
*/
|
7
14
|
onSubmit: (newFormSubmission: submissionService.NewFormSubmission) => unknown;
|
15
|
+
/** Whether the form is currently able to be submitted. False by default. */
|
8
16
|
disabled?: boolean;
|
9
17
|
isPreview?: boolean;
|
18
|
+
/**
|
19
|
+
* A [Google Maps API
|
20
|
+
* Key](https://developers.google.com/maps/documentation/javascript/get-api-key).
|
21
|
+
* Required if the form contains a `location` form element.
|
22
|
+
*/
|
10
23
|
googleMapsApiKey?: string;
|
24
|
+
/**
|
25
|
+
* An [ABN Lookup Authentication
|
26
|
+
* Guid](https://abr.business.gov.au/Tools/WebServices). Required if the form
|
27
|
+
* contains a `abn` form element.
|
28
|
+
*/
|
11
29
|
abnLookupAuthenticationGuid?: string;
|
30
|
+
/**
|
31
|
+
* A [reCAPTCHA Site Key](https://developers.google.com/recaptcha/intro).
|
32
|
+
* Required if the form contains a `captcha` form element.
|
33
|
+
*/
|
12
34
|
captchaSiteKey?: string;
|
35
|
+
/** Change properties for certain buttons on the form. */
|
13
36
|
buttons?: FormsAppsTypes.FormsListStyles['buttons'];
|
37
|
+
/** Hex colour value for certain inputs (defaults to `#4c8da7`). */
|
14
38
|
primaryColour?: string;
|
39
|
+
/** Number of days attachments are retained for. */
|
15
40
|
attachmentRetentionInDays?: number;
|
16
|
-
|
41
|
+
/**
|
42
|
+
* If set to `false`, submission will be prevented while offline. If set to
|
43
|
+
* `true`, the user will be prompted to allow them to continue with
|
44
|
+
* attachments uploading in the background later.
|
45
|
+
*/
|
46
|
+
isPendingQueueEnabled: boolean;
|
47
|
+
/**
|
48
|
+
* The function to call when the user wishes to save there submission data as
|
49
|
+
* a draft submission. If not specified, drafts cannot be saved. See
|
50
|
+
* [NewDraftSubmission](https://oneblink.github.io/apps/modules/submissionService.html#NewDraftSubmission)
|
51
|
+
* for the structure of the argument.
|
52
|
+
*/
|
17
53
|
onSaveDraft?: (newDraftSubmission: submissionService.NewDraftSubmission) => unknown;
|
54
|
+
/**
|
55
|
+
* The function to call when the user needs to navigate away from the form.
|
56
|
+
* e.g. `history.push`
|
57
|
+
*/
|
18
58
|
handleNavigateAway?: () => unknown;
|
59
|
+
/**
|
60
|
+
* Determines whether the form is submittable or not. Info page type forms
|
61
|
+
* show a "Done" button instead of a "Submit" button. Defaults to
|
62
|
+
* "CALCULATED"
|
63
|
+
*/
|
19
64
|
isInfoPage?: 'YES' | 'NO' | 'CALCULATED';
|
20
65
|
};
|
21
|
-
export type
|
66
|
+
export type OneBlinkFormControlledProps = {
|
22
67
|
definition: FormTypes.Form;
|
23
|
-
submission:
|
68
|
+
submission: SubmissionTypes.S3SubmissionData['submission'];
|
24
69
|
setFormSubmission: SetFormSubmission;
|
25
70
|
lastElementUpdated?: FormTypes.FormElement;
|
26
71
|
};
|
27
|
-
type Props =
|
72
|
+
type Props = OneBlinkFormBaseProps & OneBlinkFormControlledProps & {
|
28
73
|
isReadOnly: boolean;
|
29
74
|
};
|
30
75
|
declare function OneBlinkFormBase({ googleMapsApiKey, abnLookupAuthenticationGuid, captchaSiteKey, definition, disabled, isPreview, submission, isReadOnly, onCancel, onSubmit, onSaveDraft, setFormSubmission, buttons, primaryColour, attachmentRetentionInDays, isPendingQueueEnabled, handleNavigateAway, isInfoPage: isInfoPageProp, lastElementUpdated, }: Props): JSX.Element;
|
package/dist/OneBlinkFormBase.js
CHANGED
@@ -581,7 +581,10 @@ function OneBlinkFormBase({ googleMapsApiKey, abnLookupAuthenticationGuid, captc
|
|
581
581
|
React.createElement(CustomisableButtonInner, { label: ((_o = buttons === null || buttons === void 0 ? void 0 : buttons.saveDraft) === null || _o === void 0 ? void 0 : _o.label) || 'Save Draft', icon: (_p = buttons === null || buttons === void 0 ? void 0 : buttons.saveDraft) === null || _p === void 0 ? void 0 : _p.icon }))),
|
582
582
|
React.createElement("span", { style: { flex: 1 } }),
|
583
583
|
React.createElement("button", { className: "button ob-button ob-button__offline-submission-attempt-cancel is-light", onClick: () => setPromptOfflineSubmissionAttempt(false) }, "Cancel"),
|
584
|
-
React.createElement("button", { className: "button ob-button ob-button__offline-submission-attempt-try-again is-primary", onClick: (e) =>
|
584
|
+
React.createElement("button", { className: "button ob-button ob-button__offline-submission-attempt-try-again is-primary", onClick: (e) => {
|
585
|
+
setPromptOfflineSubmissionAttempt(false);
|
586
|
+
handleSubmit(e, false);
|
587
|
+
} }, "Try Again")) },
|
585
588
|
React.createElement("p", { className: "ob-modal__offline-submission-attempt-message" },
|
586
589
|
"You cannot submit this form while offline, please try again when connectivity is restored.",
|
587
590
|
onSaveDraft && (React.createElement("span", { className: "ob-modal__offline-submission-attempt-save-draft-message" },
|