@oneblink/apps-react 0.5.6 → 0.5.7

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.
@@ -12,6 +12,7 @@ export declare type BaseProps = {
12
12
  captchaSiteKey?: string;
13
13
  buttons?: FormsAppsTypes.FormsListStyles['buttons'];
14
14
  primaryColour?: string;
15
+ attachmentRetentionInDays?: number;
15
16
  onSaveDraft?: (newDraftSubmission: submissionService.NewDraftSubmission) => unknown;
16
17
  };
17
18
  export declare type ControlledProps = {
@@ -22,6 +23,6 @@ export declare type ControlledProps = {
22
23
  declare type Props = BaseProps & ControlledProps & {
23
24
  isReadOnly: boolean;
24
25
  };
25
- declare function OneBlinkFormBase({ googleMapsApiKey, abnLookupAuthenticationGuid, captchaSiteKey, definition, disabled, isPreview, submission, isReadOnly, onCancel, onSubmit, onSaveDraft, setFormSubmission, buttons, primaryColour, }: Props): JSX.Element;
26
+ declare function OneBlinkFormBase({ googleMapsApiKey, abnLookupAuthenticationGuid, captchaSiteKey, definition, disabled, isPreview, submission, isReadOnly, onCancel, onSubmit, onSaveDraft, setFormSubmission, buttons, primaryColour, attachmentRetentionInDays, }: Props): JSX.Element;
26
27
  declare const _default: React.MemoExoticComponent<typeof OneBlinkFormBase>;
27
28
  export default _default;
@@ -20,12 +20,14 @@ import { GoogleMapsApiKeyContext } from './hooks/useGoogleMapsApiKey';
20
20
  import { AbnLookupAuthenticationGuidContext } from './hooks/useAbnLookupAuthenticationGuid';
21
21
  import { CaptchaSiteKeyContext } from './hooks/useCaptchaSiteKey';
22
22
  import { FormIsReadOnlyContext } from './hooks/useFormIsReadOnly';
23
+ import { AttachmentBlobsProvider } from './hooks/attachments/useAttachmentBlobs';
23
24
  import checkIfAttachmentsAreUploading from './services/checkIfAttachmentsAreUploading';
24
25
  import useIsOffline from './hooks/useIsOffline';
25
26
  import CustomisableButtonInner from './components/CustomisableButtonInner';
26
27
  import checkBsbsAreInvalid from './services/checkBsbsAreInvalid';
27
28
  import checkIfBsbsAreValidating from './services/checkIfBsbsAreValidating';
28
- function OneBlinkFormBase({ googleMapsApiKey, abnLookupAuthenticationGuid, captchaSiteKey, definition, disabled, isPreview, submission, isReadOnly, onCancel, onSubmit, onSaveDraft, setFormSubmission, buttons, primaryColour, }) {
29
+ import checkIfAttachmentsExist from './services/checkIfAttachmentsExist';
30
+ function OneBlinkFormBase({ googleMapsApiKey, abnLookupAuthenticationGuid, captchaSiteKey, definition, disabled, isPreview, submission, isReadOnly, onCancel, onSubmit, onSaveDraft, setFormSubmission, buttons, primaryColour, attachmentRetentionInDays, }) {
29
31
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
30
32
  const isOffline = useIsOffline();
31
33
  const theme = React.useMemo(() => createMuiTheme({
@@ -254,6 +256,23 @@ function OneBlinkFormBase({ googleMapsApiKey, abnLookupAuthenticationGuid, captc
254
256
  if (!checkBsbsCanBeSubmitted(submissionData.submission)) {
255
257
  return;
256
258
  }
259
+ // check if attachments exist
260
+ const newSubmission = checkIfAttachmentsExist(definition, submissionData.submission, attachmentRetentionInDays);
261
+ if (newSubmission) {
262
+ setFormSubmission((currentFormSubmission) => ({
263
+ ...currentFormSubmission,
264
+ submission: newSubmission,
265
+ }));
266
+ bulmaToast.toast({
267
+ message: "Some files that were included in your submission have been removed based on your administrator's data retention policy, please remove them and upload them again.",
268
+ // @ts-expect-error bulma sets this string as a class, so we are hacking in our own classes
269
+ type: 'ob-toast is-danger cypress-invalid-submit-attempt',
270
+ duration: 4000,
271
+ pauseOnHover: true,
272
+ closeOnClick: true,
273
+ });
274
+ return;
275
+ }
257
276
  allowNavigation();
258
277
  onSubmit({
259
278
  definition,
@@ -261,16 +280,18 @@ function OneBlinkFormBase({ googleMapsApiKey, abnLookupAuthenticationGuid, captc
261
280
  captchaTokens: submissionData.captchaTokens,
262
281
  });
263
282
  }, [
264
- allowNavigation,
265
- checkAttachmentsCanBeSubmitted,
266
- definition,
267
283
  disabled,
268
- formElementsValidation,
269
- getCurrentSubmissionData,
270
284
  isReadOnly,
271
- onSubmit,
272
- checkBsbsCanBeSubmitted,
285
+ getCurrentSubmissionData,
273
286
  checkBsbAreValidating,
287
+ formElementsValidation,
288
+ checkAttachmentsCanBeSubmitted,
289
+ checkBsbsCanBeSubmitted,
290
+ definition,
291
+ attachmentRetentionInDays,
292
+ allowNavigation,
293
+ onSubmit,
294
+ setFormSubmission,
274
295
  ]);
275
296
  const handleSaveDraft = React.useCallback(() => {
276
297
  if (disabled)
@@ -406,16 +427,18 @@ function OneBlinkFormBase({ googleMapsApiKey, abnLookupAuthenticationGuid, captc
406
427
  React.createElement(GoogleMapsApiKeyContext.Provider, { value: googleMapsApiKey },
407
428
  React.createElement(AbnLookupAuthenticationGuidContext.Provider, { value: abnLookupAuthenticationGuid },
408
429
  React.createElement(CaptchaSiteKeyContext.Provider, { value: captchaSiteKey },
409
- React.createElement(FormIsReadOnlyContext.Provider, { value: isReadOnly }, visiblePages.map((pageElement) => (React.createElement(PageFormElements, { key: pageElement.id, isActive: pageElement.id === currentPage.id, formId: definition.id, formElementsConditionallyShown: formElementsConditionallyShown, formElementsValidation: formElementsValidation, displayValidationMessages: hasAttemptedSubmit ||
410
- isDisplayingCurrentPageError, pageElement: pageElement, onChange: handleChange, model: submission, setFormSubmission: setFormSubmission }))))))))))),
430
+ React.createElement(AttachmentBlobsProvider, null,
431
+ React.createElement(FormIsReadOnlyContext.Provider, { value: isReadOnly }, visiblePages.map((pageElement) => (React.createElement(PageFormElements, { key: pageElement.id, isActive: pageElement.id === currentPage.id, formId: definition.id, formElementsConditionallyShown: formElementsConditionallyShown, formElementsValidation: formElementsValidation, displayValidationMessages: hasAttemptedSubmit ||
432
+ isDisplayingCurrentPageError, pageElement: pageElement, onChange: handleChange, model: submission, setFormSubmission: setFormSubmission })))))))))))),
411
433
  isShowingMultiplePages && (React.createElement("div", { className: "steps-actions" },
412
434
  React.createElement("div", { className: "steps-action" },
413
435
  React.createElement("button", { type: "button", onClick: goToPreviousPage, disabled: isFirstVisiblePage, className: "button is-light cypress-pages-previous" },
414
436
  React.createElement("span", { className: "icon" },
415
437
  React.createElement("i", { className: "material-icons" }, "keyboard_arrow_left")),
416
438
  React.createElement("span", null, "Back"))),
417
- React.createElement("div", { className: "step-progress-mobile cypress-steps-mobile" }, visiblePages.map((page) => (React.createElement("div", { key: page.id, className: clsx('step-progress-mobile-dot', {
439
+ React.createElement("div", { className: "step-progress-mobile cypress-steps-mobile" }, visiblePages.map((page, index) => (React.createElement("div", { key: page.id, className: clsx('step-progress-mobile-dot', {
418
440
  'is-active': currentPage.id === page.id,
441
+ 'is-completed': currentPageIndex > index,
419
442
  'has-background-danger': currentPage.id !== page.id &&
420
443
  checkDisplayPageError(page),
421
444
  }) })))),
@@ -1 +1 @@
1
- {"version":3,"file":"OneBlinkFormBase.js","sourceRoot":"","sources":["../src/OneBlinkFormBase.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport {\n createTheme as createMuiTheme,\n ThemeProvider,\n Tooltip,\n} from '@material-ui/core'\nimport { Prompt, useHistory } from 'react-router-dom'\nimport clsx from 'clsx'\nimport * as bulmaToast from 'bulma-toast'\nimport { localisationService, submissionService } from '@oneblink/apps'\nimport { FormTypes, FormsAppsTypes } from '@oneblink/types'\n\nimport Modal from './components/Modal'\nimport OneBlinkAppsErrorOriginalMessage from './components/OneBlinkAppsErrorOriginalMessage'\nimport cleanFormSubmissionModel from './services/cleanFormSubmissionModel'\nimport PageFormElements from './components/PageFormElements'\nimport useFormValidation from './hooks/useFormValidation'\nimport useConditionalLogic from './hooks/useConditionalLogic'\nimport usePages from './hooks/usePages'\nimport useLookups from './hooks/useLookups'\nimport { FormDefinitionContext } from './hooks/useFormDefinition'\nimport { InjectPagesContext } from './hooks/useInjectPages'\nimport { ExecutedLookupProvider } from './hooks/useExecutedLookupCallback'\nimport useDynamicOptionsLoaderState from './hooks/useDynamicOptionsLoaderState'\nimport { GoogleMapsApiKeyContext } from './hooks/useGoogleMapsApiKey'\nimport { AbnLookupAuthenticationGuidContext } from './hooks/useAbnLookupAuthenticationGuid'\nimport { CaptchaSiteKeyContext } from './hooks/useCaptchaSiteKey'\nimport { FormIsReadOnlyContext } from './hooks/useFormIsReadOnly'\nimport checkIfAttachmentsAreUploading from './services/checkIfAttachmentsAreUploading'\nimport useIsOffline from './hooks/useIsOffline'\nimport CustomisableButtonInner from './components/CustomisableButtonInner'\nimport {\n FormElementsValidation,\n FormElementValueChangeHandler,\n FormSubmissionModel,\n SetFormSubmission,\n} from './types/form'\nimport checkBsbsAreInvalid from './services/checkBsbsAreInvalid'\nimport checkIfBsbsAreValidating from './services/checkIfBsbsAreValidating'\n\nexport type BaseProps = {\n onCancel: () => unknown\n onSubmit: (newFormSubmission: submissionService.NewFormSubmission) => unknown\n disabled?: boolean\n isPreview?: boolean\n googleMapsApiKey?: string\n abnLookupAuthenticationGuid?: string\n captchaSiteKey?: string\n buttons?: FormsAppsTypes.FormsListStyles['buttons']\n primaryColour?: string\n onSaveDraft?: (\n newDraftSubmission: submissionService.NewDraftSubmission,\n ) => unknown\n}\n\nexport type ControlledProps = {\n definition: FormTypes.Form\n submission: FormSubmissionModel\n setFormSubmission: SetFormSubmission\n}\n\ntype Props = BaseProps &\n ControlledProps & {\n isReadOnly: boolean\n }\n\nfunction OneBlinkFormBase({\n googleMapsApiKey,\n abnLookupAuthenticationGuid,\n captchaSiteKey,\n definition,\n disabled,\n isPreview,\n submission,\n isReadOnly,\n onCancel,\n onSubmit,\n onSaveDraft,\n setFormSubmission,\n buttons,\n primaryColour,\n}: Props) {\n const isOffline = useIsOffline()\n\n const theme = React.useMemo(\n () =>\n createMuiTheme({\n palette: {\n primary: {\n main: primaryColour || '#4c8da7',\n },\n },\n }),\n [primaryColour],\n )\n\n //\n //\n // #region Form Definition\n\n const pages = React.useMemo<FormTypes.PageElement[]>(() => {\n if (definition.isMultiPage) {\n return definition.elements.reduce(\n (\n pageElements: FormTypes.PageElement[],\n formElement: FormTypes.FormElement,\n ) => {\n if (formElement.type === 'page') {\n pageElements.push(formElement)\n }\n return pageElements\n },\n [],\n )\n } else {\n return [\n {\n type: 'page',\n id: definition.id.toString(),\n label: definition.name,\n elements: definition.elements,\n conditionallyShow: false,\n requiresAllConditionallyShowPredicates: false,\n },\n ]\n }\n }, [\n definition.elements,\n definition.id,\n definition.isMultiPage,\n definition.name,\n ])\n\n // #endregion\n //\n //\n\n //\n //\n // #region Unsaved Changed\n\n const history = useHistory()\n\n const [\n { isDirty, isNavigationAllowed, hasConfirmedNavigation, goToLocation },\n setUnsavedChangesState,\n ] = React.useState<{\n isDirty: boolean\n isNavigationAllowed: boolean\n hasConfirmedNavigation: boolean | null\n goToLocation: Location | null\n }>({\n isDirty: false,\n isNavigationAllowed: false,\n hasConfirmedNavigation: null,\n goToLocation: null,\n })\n const handleBlockedNavigation = React.useCallback((location) => {\n setUnsavedChangesState((current) => ({\n ...current,\n goToLocation: location,\n hasConfirmedNavigation: false,\n }))\n return false\n }, [])\n\n const handleKeepGoing = React.useCallback(() => {\n setUnsavedChangesState((current) => ({\n ...current,\n goToLocation: null,\n hasConfirmedNavigation: null,\n }))\n }, [])\n\n const handleDiscardUnsavedChanges = React.useCallback(() => {\n setUnsavedChangesState((current) => ({\n ...current,\n isNavigationAllowed: true,\n hasConfirmedNavigation: true,\n }))\n }, [])\n\n React.useEffect(() => {\n if (hasConfirmedNavigation) {\n // Navigate to the previous blocked location with your navigate function\n if (goToLocation) {\n history.push(`${goToLocation.pathname}${goToLocation.search}`)\n } else {\n onCancel()\n }\n }\n }, [goToLocation, hasConfirmedNavigation, history, onCancel])\n\n const handleCancel = React.useCallback(() => {\n if (isDirty) {\n setUnsavedChangesState((current) => ({\n ...current,\n hasConfirmedNavigation: false,\n }))\n } else {\n onCancel()\n }\n }, [isDirty, onCancel])\n\n const allowNavigation = React.useCallback(() => {\n setUnsavedChangesState((current) => ({\n ...current,\n isNavigationAllowed: true,\n }))\n }, [])\n\n // #endregion Unsaved Changed\n //\n //\n\n //\n //\n // #region Conditional Logic\n\n const { formElementsConditionallyShown, conditionalLogicError } =\n useConditionalLogic(definition, submission)\n\n // #endregion\n //\n //\n\n //\n //\n // #region Validation\n\n const { validate, executedLookup, executeLookupFailed } =\n useFormValidation(pages)\n\n const formElementsValidation = React.useMemo<\n FormElementsValidation | undefined\n >(\n () => validate(submission, formElementsConditionallyShown),\n [formElementsConditionallyShown, submission, validate],\n )\n\n // #endregion\n //\n //\n\n //\n //\n // #region Pages\n\n const {\n visiblePages,\n isFirstVisiblePage,\n isLastVisiblePage,\n isDisplayingCurrentPageError,\n isShowingMultiplePages,\n isStepsHeaderActive,\n toggleStepsNavigation,\n currentPageIndex,\n currentPage,\n currentPageNumber,\n checkDisplayPageError,\n setPageId,\n goToPreviousPage,\n goToNextPage,\n scrollToTopOfPageHTMLElementRef,\n } = usePages({\n pages,\n formElementsValidation,\n formElementsConditionallyShown,\n })\n\n // #endregion\n //\n //\n\n //\n //\n // #region Dynamic Options\n\n const loadDynamicOptionsState = useDynamicOptionsLoaderState(\n definition,\n setFormSubmission,\n )\n\n // #endregion\n //\n //\n\n //\n //\n // #region Submissions\n\n const [hasAttemptedSubmit, setHasAttemptedSubmit] = React.useState(false)\n const getCurrentSubmissionData = React.useCallback(\n (stripBinaryData) => {\n const { model, captchaTokens } = cleanFormSubmissionModel(\n submission,\n definition.elements,\n formElementsConditionallyShown,\n stripBinaryData,\n )\n return {\n submission: model,\n captchaTokens,\n }\n },\n [definition.elements, formElementsConditionallyShown, submission],\n )\n\n const obFormContainerHTMLElementRef = React.useRef<HTMLDivElement>(null)\n React.useEffect(() => {\n const obFormContainerHTMLElement = obFormContainerHTMLElementRef.current\n if (obFormContainerHTMLElement) {\n console.log(\n 'Setting toast notifications to be appended to HTML Element',\n obFormContainerHTMLElement,\n )\n bulmaToast.setDefaults({\n position: 'bottom-right',\n opacity: 0.95,\n appendTo: obFormContainerHTMLElement,\n })\n }\n return () => {\n bulmaToast.resetDefaults()\n }\n }, [])\n\n const checkAttachmentsCanBeSubmitted = React.useCallback(\n (submission: FormSubmissionModel) => {\n // Prevent submission until all attachment uploads are finished\n // Unless the user is offline, in which case, the uploads will\n // be taken care of by a pending queue...hopefully.\n if (isOffline) {\n return true\n }\n\n if (checkIfAttachmentsAreUploading(definition, submission)) {\n bulmaToast.toast({\n message:\n 'Attachments are still uploading, please wait for them to finish before trying again.',\n // @ts-expect-error bulma sets this string as a class, so we are hacking in our own classes\n type: 'ob-toast is-primary cypress-still-uploading-toast',\n duration: 4000,\n pauseOnHover: true,\n closeOnClick: true,\n })\n return false\n }\n\n return true\n },\n [definition, isOffline],\n )\n\n const checkBsbsCanBeSubmitted = React.useCallback(\n (submission: FormSubmissionModel) => {\n return !checkBsbsAreInvalid(definition, submission)\n },\n [definition],\n )\n\n const checkBsbAreValidating = React.useCallback(\n (submission: FormSubmissionModel) => {\n if (checkIfBsbsAreValidating(definition, submission)) {\n bulmaToast.toast({\n message:\n 'Bsb(s) are still being validated, please wait for them to finish before trying again.',\n // @ts-expect-error bulma sets this string as a class, so we are hacking in our own classes\n type: 'ob-toast is-primary cypress-still-validating-toast',\n duration: 4000,\n pauseOnHover: true,\n closeOnClick: true,\n })\n return false\n }\n\n return true\n },\n [definition],\n )\n\n const handleSubmit = React.useCallback(\n (event) => {\n event.preventDefault()\n if (disabled || isReadOnly) return\n setHasAttemptedSubmit(true)\n\n const submissionData = getCurrentSubmissionData(false)\n if (!checkBsbAreValidating(submissionData.submission)) {\n return\n }\n if (formElementsValidation) {\n console.log('Validation errors', formElementsValidation)\n bulmaToast.toast({\n message: 'Please fix validation errors',\n // @ts-expect-error bulma sets this string as a class, so we are hacking in our own classes\n type: 'ob-toast is-danger cypress-invalid-submit-attempt',\n duration: 4000,\n pauseOnHover: true,\n closeOnClick: true,\n })\n return\n }\n\n if (!checkAttachmentsCanBeSubmitted(submissionData.submission)) {\n return\n }\n\n if (!checkBsbsCanBeSubmitted(submissionData.submission)) {\n return\n }\n\n allowNavigation()\n\n onSubmit({\n definition,\n submission: submissionData.submission,\n captchaTokens: submissionData.captchaTokens,\n })\n },\n [\n allowNavigation,\n checkAttachmentsCanBeSubmitted,\n definition,\n disabled,\n formElementsValidation,\n getCurrentSubmissionData,\n isReadOnly,\n onSubmit,\n checkBsbsCanBeSubmitted,\n checkBsbAreValidating,\n ],\n )\n\n const handleSaveDraft = React.useCallback(() => {\n if (disabled) return\n if (onSaveDraft) {\n allowNavigation()\n\n // For drafts we don't need to save the captcha tokens,\n // they will need to prove they are not robot again\n const { submission } = getCurrentSubmissionData(false)\n if (!checkBsbAreValidating(submission)) {\n return\n }\n if (!checkAttachmentsCanBeSubmitted(submission)) {\n return\n }\n\n onSaveDraft({\n definition,\n submission,\n })\n }\n }, [\n allowNavigation,\n checkAttachmentsCanBeSubmitted,\n definition,\n disabled,\n getCurrentSubmissionData,\n onSaveDraft,\n checkBsbAreValidating,\n ])\n\n // #endregion\n //\n //\n\n //\n //\n // #region Lookups\n\n const { handlePagesLookupResult } = useLookups(\n definition.id,\n setFormSubmission,\n )\n\n // #endregion\n //\n //\n\n //\n //\n // #region Submission/Definition Changes\n\n const handleChange = React.useCallback<FormElementValueChangeHandler>(\n (element, value) => {\n if (disabled || element.type === 'page' || element.type === 'section') {\n return\n }\n\n setUnsavedChangesState((current) => ({\n ...current,\n isDirty: true,\n }))\n\n setFormSubmission((currentFormSubmission) => ({\n ...currentFormSubmission,\n submission: {\n ...currentFormSubmission.submission,\n [element.name]:\n typeof value === 'function'\n ? value(currentFormSubmission.submission[element.name])\n : value,\n },\n }))\n },\n [disabled, setFormSubmission],\n )\n\n // #endregion\n //\n //\n\n if (conditionalLogicError) {\n return (\n <>\n <div className=\"has-text-centered\">\n <i className=\"material-icons has-text-warning icon-x-large\">error</i>\n <h3 className=\"title is-3\">Bad Form Configuration</h3>\n <p className=\"cypress-conditional-logic-error-message\">\n {conditionalLogicError.message}\n </p>\n <p className=\"has-text-grey\">\n {localisationService.formatDatetimeLong(new Date())}\n </p>\n </div>\n </>\n )\n }\n\n if (loadDynamicOptionsState) {\n return (\n <>\n <div className=\"has-text-centered\">\n <i className=\"material-icons has-text-warning icon-x-large\">error</i>\n <h3 className=\"title is-3\">{loadDynamicOptionsState.error.title}</h3>\n <p>{loadDynamicOptionsState.error.message}</p>\n <p className=\"has-text-grey\">\n {localisationService.formatDatetimeLong(new Date())}\n </p>\n </div>\n\n <OneBlinkAppsErrorOriginalMessage\n error={loadDynamicOptionsState.error.originalError}\n />\n </>\n )\n }\n\n return (\n <ThemeProvider theme={theme}>\n <div className=\"ob-form-container\" ref={obFormContainerHTMLElementRef}>\n <form\n name=\"obForm\"\n className={`ob-form cypress-ob-form ob-form__page-${\n currentPageIndex + 1\n }`}\n noValidate\n onSubmit={handleSubmit}\n >\n <div>\n <div ref={scrollToTopOfPageHTMLElementRef} />\n {isShowingMultiplePages && (\n <div\n className={clsx('ob-steps-navigation', {\n 'is-active': isStepsHeaderActive,\n })}\n >\n <div\n className={clsx('ob-steps-navigation__header', {\n 'is-active': isStepsHeaderActive,\n })}\n onClick={toggleStepsNavigation}\n >\n <span className=\"icon is-invisible\">\n <i className=\"material-icons\">keyboard_arrow_down</i>\n </span>\n <div className=\"steps-header-active-page\">\n {isDisplayingCurrentPageError ? (\n <span className=\"icon\">\n <i className=\"material-icons has-text-danger is-size-4\">\n warning\n </i>\n </span>\n ) : (\n <span className=\"steps-header-active-page-icon\">\n {currentPageNumber}\n </span>\n )}\n <span className=\"steps-header-active-page-label cypress-tablet-step-title\">\n {currentPage ? currentPage.label : ''}\n </span>\n </div>\n <span className=\"dropdown icon\">\n <i className=\"material-icons\">keyboard_arrow_down</i>\n </span>\n </div>\n\n <div\n className={clsx('ob-steps-navigation__steps', {\n 'is-active': isStepsHeaderActive,\n })}\n >\n <div className=\"steps is-small is-horizontal-tablet cypress-steps\">\n {visiblePages.map(\n (page: FormTypes.PageElement, index: number) => {\n const hasErrors = checkDisplayPageError(page)\n return (\n <div\n key={page.id}\n id={`steps-navigation-step-${page.id}`}\n className={clsx('step-item cypress-step-item', {\n 'is-active': currentPage.id === page.id,\n 'is-completed': currentPageIndex > index,\n 'is-error': hasErrors,\n })}\n onClick={(e) => {\n e.stopPropagation()\n if (page.id !== currentPage.id) {\n setPageId(page.id)\n }\n }}\n >\n <div\n className=\"step-marker step-marker-error ob-step-marker cypress-step-marker\"\n // @ts-expect-error ???\n name={`cypress-page-stepper-${index + 1}`}\n value={index + 1}\n >\n {hasErrors ? (\n <Tooltip title=\"Page has errors\">\n <span className=\"icon tooltip has-tooltip-top cypress-page-error\">\n <i className=\"material-icons has-text-danger is-size-3\">\n warning\n </i>\n </span>\n </Tooltip>\n ) : (\n <span>{index + 1}</span>\n )}\n </div>\n <div className=\"step-details ob-step-details\">\n <p className=\"step-title ob-step-title cypress-desktop-step-title\">\n {page.label}\n </p>\n </div>\n </div>\n )\n },\n )}\n </div>\n </div>\n </div>\n )}\n\n <div\n className={clsx('ob-steps-navigation__background', {\n 'is-active': isStepsHeaderActive,\n })}\n onClick={toggleStepsNavigation}\n />\n\n <div className=\"steps\">\n <div\n className={clsx('steps-content', {\n 'is-single-step': !isShowingMultiplePages,\n })}\n >\n <FormDefinitionContext.Provider value={definition}>\n <InjectPagesContext.Provider value={handlePagesLookupResult}>\n <ExecutedLookupProvider\n executedLookup={executedLookup}\n executeLookupFailed={executeLookupFailed}\n >\n <GoogleMapsApiKeyContext.Provider\n value={googleMapsApiKey}\n >\n <AbnLookupAuthenticationGuidContext.Provider\n value={abnLookupAuthenticationGuid}\n >\n <CaptchaSiteKeyContext.Provider\n value={captchaSiteKey}\n >\n <FormIsReadOnlyContext.Provider value={isReadOnly}>\n {visiblePages.map(\n (pageElement: FormTypes.PageElement) => (\n <PageFormElements\n key={pageElement.id}\n isActive={pageElement.id === currentPage.id}\n formId={definition.id}\n formElementsConditionallyShown={\n formElementsConditionallyShown\n }\n formElementsValidation={\n formElementsValidation\n }\n displayValidationMessages={\n hasAttemptedSubmit ||\n isDisplayingCurrentPageError\n }\n pageElement={pageElement}\n onChange={handleChange}\n model={submission}\n setFormSubmission={setFormSubmission}\n />\n ),\n )}\n </FormIsReadOnlyContext.Provider>\n </CaptchaSiteKeyContext.Provider>\n </AbnLookupAuthenticationGuidContext.Provider>\n </GoogleMapsApiKeyContext.Provider>\n </ExecutedLookupProvider>\n </InjectPagesContext.Provider>\n </FormDefinitionContext.Provider>\n </div>\n\n {isShowingMultiplePages && (\n <div className=\"steps-actions\">\n <div className=\"steps-action\">\n <button\n type=\"button\"\n onClick={goToPreviousPage}\n disabled={isFirstVisiblePage}\n className=\"button is-light cypress-pages-previous\"\n >\n <span className=\"icon\">\n <i className=\"material-icons\">keyboard_arrow_left</i>\n </span>\n <span>Back</span>\n </button>\n </div>\n <div className=\"step-progress-mobile cypress-steps-mobile\">\n {visiblePages.map((page: FormTypes.PageElement) => (\n <div\n key={page.id}\n className={clsx('step-progress-mobile-dot', {\n 'is-active': currentPage.id === page.id,\n 'has-background-danger':\n currentPage.id !== page.id &&\n checkDisplayPageError(page),\n })}\n />\n ))}\n </div>\n <div className=\"steps-action\">\n <button\n type=\"button\"\n onClick={goToNextPage}\n disabled={isLastVisiblePage}\n className=\"button is-light cypress-pages-next\"\n >\n <span>Next</span>\n <span className=\"icon\">\n <i className=\"material-icons\">keyboard_arrow_right</i>\n </span>\n </button>\n </div>\n </div>\n )}\n </div>\n {!isReadOnly && (\n <div className=\"buttons ob-buttons ob-buttons-submit\">\n {onSaveDraft && !definition.isInfoPage && (\n <button\n type=\"button\"\n className=\"button ob-button is-primary ob-button-save-draft cypress-save-draft-form\"\n onClick={handleSaveDraft}\n disabled={isPreview || disabled}\n >\n <CustomisableButtonInner\n label={buttons?.saveDraft?.label || 'Save Draft'}\n icon={buttons?.saveDraft?.icon}\n />\n </button>\n )}\n <span className=\"ob-buttons-submit__spacer\"></span>\n {!definition.isInfoPage && (\n <button\n type=\"button\"\n className=\"button ob-button is-light ob-button-submit-cancel cypress-cancel-form\"\n onClick={handleCancel}\n disabled={isPreview || disabled}\n >\n <CustomisableButtonInner\n label={buttons?.cancel?.label || 'Cancel'}\n icon={buttons?.cancel?.icon}\n />\n </button>\n )}\n {isLastVisiblePage && (\n <button\n type=\"submit\"\n className=\"button ob-button is-success ob-button-submit cypress-submit-form-button cypress-submit-form\"\n disabled={isPreview || disabled}\n >\n <CustomisableButtonInner\n label={\n definition.isInfoPage\n ? 'Done'\n : buttons?.submit?.label || 'Submit'\n }\n icon={buttons?.submit?.icon}\n />\n </button>\n )}\n </div>\n )}\n </div>\n </form>\n\n {!isReadOnly && (\n <React.Fragment>\n <Prompt\n when={isDirty && !isNavigationAllowed}\n message={handleBlockedNavigation}\n />\n <Modal\n isOpen={hasConfirmedNavigation === false}\n title=\"Unsaved Changes\"\n cardClassName=\"cypress-cancel-confirm\"\n titleClassName=\"cypress-cancel-confirm-title\"\n bodyClassName=\"cypress-cancel-confirm-body\"\n actions={\n <>\n {onSaveDraft && (\n <button\n type=\"button\"\n className=\"button ob-button is-success cypress-cancel-confirm-save-draft\"\n onClick={handleSaveDraft}\n >\n <CustomisableButtonInner\n label={buttons?.saveDraft?.label || 'Save Draft'}\n icon={buttons?.saveDraft?.icon}\n />\n </button>\n )}\n <span style={{ flex: 1 }}></span>\n <button\n type=\"button\"\n className=\"button ob-button is-light cypress-cancel-confirm-back\"\n onClick={handleKeepGoing}\n >\n <CustomisableButtonInner\n label={buttons?.cancelPromptNo?.label || 'Back'}\n icon={buttons?.cancelPromptNo?.icon}\n />\n </button>\n <button\n type=\"button\"\n className=\"button ob-button is-primary cypress-cancel-confirm-discard\"\n onClick={handleDiscardUnsavedChanges}\n >\n <CustomisableButtonInner\n label={buttons?.cancelPromptYes?.label || 'Discard'}\n icon={buttons?.cancelPromptYes?.icon}\n />\n </button>\n </>\n }\n >\n <p>\n You have unsaved changes, are you sure you want discard them?\n </p>\n </Modal>\n </React.Fragment>\n )}\n </div>\n </ThemeProvider>\n )\n}\n\nexport default React.memo(OneBlinkFormBase)\n"]}
1
+ {"version":3,"file":"OneBlinkFormBase.js","sourceRoot":"","sources":["../src/OneBlinkFormBase.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport {\n createTheme as createMuiTheme,\n ThemeProvider,\n Tooltip,\n} from '@material-ui/core'\nimport { Prompt, useHistory } from 'react-router-dom'\nimport clsx from 'clsx'\nimport * as bulmaToast from 'bulma-toast'\nimport { localisationService, submissionService } from '@oneblink/apps'\nimport { FormTypes, FormsAppsTypes } from '@oneblink/types'\n\nimport Modal from './components/Modal'\nimport OneBlinkAppsErrorOriginalMessage from './components/OneBlinkAppsErrorOriginalMessage'\nimport cleanFormSubmissionModel from './services/cleanFormSubmissionModel'\nimport PageFormElements from './components/PageFormElements'\nimport useFormValidation from './hooks/useFormValidation'\nimport useConditionalLogic from './hooks/useConditionalLogic'\nimport usePages from './hooks/usePages'\nimport useLookups from './hooks/useLookups'\nimport { FormDefinitionContext } from './hooks/useFormDefinition'\nimport { InjectPagesContext } from './hooks/useInjectPages'\nimport { ExecutedLookupProvider } from './hooks/useExecutedLookupCallback'\nimport useDynamicOptionsLoaderState from './hooks/useDynamicOptionsLoaderState'\nimport { GoogleMapsApiKeyContext } from './hooks/useGoogleMapsApiKey'\nimport { AbnLookupAuthenticationGuidContext } from './hooks/useAbnLookupAuthenticationGuid'\nimport { CaptchaSiteKeyContext } from './hooks/useCaptchaSiteKey'\nimport { FormIsReadOnlyContext } from './hooks/useFormIsReadOnly'\nimport { AttachmentBlobsProvider } from './hooks/attachments/useAttachmentBlobs'\nimport checkIfAttachmentsAreUploading from './services/checkIfAttachmentsAreUploading'\nimport useIsOffline from './hooks/useIsOffline'\nimport CustomisableButtonInner from './components/CustomisableButtonInner'\nimport {\n FormElementsValidation,\n FormElementValueChangeHandler,\n FormSubmissionModel,\n SetFormSubmission,\n} from './types/form'\nimport checkBsbsAreInvalid from './services/checkBsbsAreInvalid'\nimport checkIfBsbsAreValidating from './services/checkIfBsbsAreValidating'\nimport checkIfAttachmentsExist from './services/checkIfAttachmentsExist'\n\nexport type BaseProps = {\n onCancel: () => unknown\n onSubmit: (newFormSubmission: submissionService.NewFormSubmission) => unknown\n disabled?: boolean\n isPreview?: boolean\n googleMapsApiKey?: string\n abnLookupAuthenticationGuid?: string\n captchaSiteKey?: string\n buttons?: FormsAppsTypes.FormsListStyles['buttons']\n primaryColour?: string\n attachmentRetentionInDays?: number\n onSaveDraft?: (\n newDraftSubmission: submissionService.NewDraftSubmission,\n ) => unknown\n}\n\nexport type ControlledProps = {\n definition: FormTypes.Form\n submission: FormSubmissionModel\n setFormSubmission: SetFormSubmission\n}\n\ntype Props = BaseProps &\n ControlledProps & {\n isReadOnly: boolean\n }\n\nfunction OneBlinkFormBase({\n googleMapsApiKey,\n abnLookupAuthenticationGuid,\n captchaSiteKey,\n definition,\n disabled,\n isPreview,\n submission,\n isReadOnly,\n onCancel,\n onSubmit,\n onSaveDraft,\n setFormSubmission,\n buttons,\n primaryColour,\n attachmentRetentionInDays,\n}: Props) {\n const isOffline = useIsOffline()\n\n const theme = React.useMemo(\n () =>\n createMuiTheme({\n palette: {\n primary: {\n main: primaryColour || '#4c8da7',\n },\n },\n }),\n [primaryColour],\n )\n\n //\n //\n // #region Form Definition\n\n const pages = React.useMemo<FormTypes.PageElement[]>(() => {\n if (definition.isMultiPage) {\n return definition.elements.reduce(\n (\n pageElements: FormTypes.PageElement[],\n formElement: FormTypes.FormElement,\n ) => {\n if (formElement.type === 'page') {\n pageElements.push(formElement)\n }\n return pageElements\n },\n [],\n )\n } else {\n return [\n {\n type: 'page',\n id: definition.id.toString(),\n label: definition.name,\n elements: definition.elements,\n conditionallyShow: false,\n requiresAllConditionallyShowPredicates: false,\n },\n ]\n }\n }, [\n definition.elements,\n definition.id,\n definition.isMultiPage,\n definition.name,\n ])\n\n // #endregion\n //\n //\n\n //\n //\n // #region Unsaved Changed\n\n const history = useHistory()\n\n const [\n { isDirty, isNavigationAllowed, hasConfirmedNavigation, goToLocation },\n setUnsavedChangesState,\n ] = React.useState<{\n isDirty: boolean\n isNavigationAllowed: boolean\n hasConfirmedNavigation: boolean | null\n goToLocation: Location | null\n }>({\n isDirty: false,\n isNavigationAllowed: false,\n hasConfirmedNavigation: null,\n goToLocation: null,\n })\n const handleBlockedNavigation = React.useCallback((location) => {\n setUnsavedChangesState((current) => ({\n ...current,\n goToLocation: location,\n hasConfirmedNavigation: false,\n }))\n return false\n }, [])\n\n const handleKeepGoing = React.useCallback(() => {\n setUnsavedChangesState((current) => ({\n ...current,\n goToLocation: null,\n hasConfirmedNavigation: null,\n }))\n }, [])\n\n const handleDiscardUnsavedChanges = React.useCallback(() => {\n setUnsavedChangesState((current) => ({\n ...current,\n isNavigationAllowed: true,\n hasConfirmedNavigation: true,\n }))\n }, [])\n\n React.useEffect(() => {\n if (hasConfirmedNavigation) {\n // Navigate to the previous blocked location with your navigate function\n if (goToLocation) {\n history.push(`${goToLocation.pathname}${goToLocation.search}`)\n } else {\n onCancel()\n }\n }\n }, [goToLocation, hasConfirmedNavigation, history, onCancel])\n\n const handleCancel = React.useCallback(() => {\n if (isDirty) {\n setUnsavedChangesState((current) => ({\n ...current,\n hasConfirmedNavigation: false,\n }))\n } else {\n onCancel()\n }\n }, [isDirty, onCancel])\n\n const allowNavigation = React.useCallback(() => {\n setUnsavedChangesState((current) => ({\n ...current,\n isNavigationAllowed: true,\n }))\n }, [])\n\n // #endregion Unsaved Changed\n //\n //\n\n //\n //\n // #region Conditional Logic\n\n const { formElementsConditionallyShown, conditionalLogicError } =\n useConditionalLogic(definition, submission)\n\n // #endregion\n //\n //\n\n //\n //\n // #region Validation\n\n const { validate, executedLookup, executeLookupFailed } =\n useFormValidation(pages)\n\n const formElementsValidation = React.useMemo<\n FormElementsValidation | undefined\n >(\n () => validate(submission, formElementsConditionallyShown),\n [formElementsConditionallyShown, submission, validate],\n )\n\n // #endregion\n //\n //\n\n //\n //\n // #region Pages\n\n const {\n visiblePages,\n isFirstVisiblePage,\n isLastVisiblePage,\n isDisplayingCurrentPageError,\n isShowingMultiplePages,\n isStepsHeaderActive,\n toggleStepsNavigation,\n currentPageIndex,\n currentPage,\n currentPageNumber,\n checkDisplayPageError,\n setPageId,\n goToPreviousPage,\n goToNextPage,\n scrollToTopOfPageHTMLElementRef,\n } = usePages({\n pages,\n formElementsValidation,\n formElementsConditionallyShown,\n })\n\n // #endregion\n //\n //\n\n //\n //\n // #region Dynamic Options\n\n const loadDynamicOptionsState = useDynamicOptionsLoaderState(\n definition,\n setFormSubmission,\n )\n\n // #endregion\n //\n //\n\n //\n //\n // #region Submissions\n\n const [hasAttemptedSubmit, setHasAttemptedSubmit] = React.useState(false)\n const getCurrentSubmissionData = React.useCallback(\n (stripBinaryData) => {\n const { model, captchaTokens } = cleanFormSubmissionModel(\n submission,\n definition.elements,\n formElementsConditionallyShown,\n stripBinaryData,\n )\n return {\n submission: model,\n captchaTokens,\n }\n },\n [definition.elements, formElementsConditionallyShown, submission],\n )\n\n const obFormContainerHTMLElementRef = React.useRef<HTMLDivElement>(null)\n React.useEffect(() => {\n const obFormContainerHTMLElement = obFormContainerHTMLElementRef.current\n if (obFormContainerHTMLElement) {\n console.log(\n 'Setting toast notifications to be appended to HTML Element',\n obFormContainerHTMLElement,\n )\n bulmaToast.setDefaults({\n position: 'bottom-right',\n opacity: 0.95,\n appendTo: obFormContainerHTMLElement,\n })\n }\n return () => {\n bulmaToast.resetDefaults()\n }\n }, [])\n\n const checkAttachmentsCanBeSubmitted = React.useCallback(\n (submission: FormSubmissionModel) => {\n // Prevent submission until all attachment uploads are finished\n // Unless the user is offline, in which case, the uploads will\n // be taken care of by a pending queue...hopefully.\n if (isOffline) {\n return true\n }\n\n if (checkIfAttachmentsAreUploading(definition, submission)) {\n bulmaToast.toast({\n message:\n 'Attachments are still uploading, please wait for them to finish before trying again.',\n // @ts-expect-error bulma sets this string as a class, so we are hacking in our own classes\n type: 'ob-toast is-primary cypress-still-uploading-toast',\n duration: 4000,\n pauseOnHover: true,\n closeOnClick: true,\n })\n return false\n }\n\n return true\n },\n [definition, isOffline],\n )\n\n const checkBsbsCanBeSubmitted = React.useCallback(\n (submission: FormSubmissionModel) => {\n return !checkBsbsAreInvalid(definition, submission)\n },\n [definition],\n )\n\n const checkBsbAreValidating = React.useCallback(\n (submission: FormSubmissionModel) => {\n if (checkIfBsbsAreValidating(definition, submission)) {\n bulmaToast.toast({\n message:\n 'Bsb(s) are still being validated, please wait for them to finish before trying again.',\n // @ts-expect-error bulma sets this string as a class, so we are hacking in our own classes\n type: 'ob-toast is-primary cypress-still-validating-toast',\n duration: 4000,\n pauseOnHover: true,\n closeOnClick: true,\n })\n return false\n }\n\n return true\n },\n [definition],\n )\n\n const handleSubmit = React.useCallback(\n (event) => {\n event.preventDefault()\n if (disabled || isReadOnly) return\n setHasAttemptedSubmit(true)\n\n const submissionData = getCurrentSubmissionData(false)\n if (!checkBsbAreValidating(submissionData.submission)) {\n return\n }\n if (formElementsValidation) {\n console.log('Validation errors', formElementsValidation)\n bulmaToast.toast({\n message: 'Please fix validation errors',\n // @ts-expect-error bulma sets this string as a class, so we are hacking in our own classes\n type: 'ob-toast is-danger cypress-invalid-submit-attempt',\n duration: 4000,\n pauseOnHover: true,\n closeOnClick: true,\n })\n return\n }\n\n if (!checkAttachmentsCanBeSubmitted(submissionData.submission)) {\n return\n }\n\n if (!checkBsbsCanBeSubmitted(submissionData.submission)) {\n return\n }\n\n // check if attachments exist\n const newSubmission = checkIfAttachmentsExist(\n definition,\n submissionData.submission,\n attachmentRetentionInDays,\n )\n if (newSubmission) {\n setFormSubmission((currentFormSubmission) => ({\n ...currentFormSubmission,\n submission: newSubmission,\n }))\n bulmaToast.toast({\n message:\n \"Some files that were included in your submission have been removed based on your administrator's data retention policy, please remove them and upload them again.\",\n // @ts-expect-error bulma sets this string as a class, so we are hacking in our own classes\n type: 'ob-toast is-danger cypress-invalid-submit-attempt',\n duration: 4000,\n pauseOnHover: true,\n closeOnClick: true,\n })\n return\n }\n\n allowNavigation()\n\n onSubmit({\n definition,\n submission: submissionData.submission,\n captchaTokens: submissionData.captchaTokens,\n })\n },\n [\n disabled,\n isReadOnly,\n getCurrentSubmissionData,\n checkBsbAreValidating,\n formElementsValidation,\n checkAttachmentsCanBeSubmitted,\n checkBsbsCanBeSubmitted,\n definition,\n attachmentRetentionInDays,\n allowNavigation,\n onSubmit,\n setFormSubmission,\n ],\n )\n\n const handleSaveDraft = React.useCallback(() => {\n if (disabled) return\n if (onSaveDraft) {\n allowNavigation()\n\n // For drafts we don't need to save the captcha tokens,\n // they will need to prove they are not robot again\n const { submission } = getCurrentSubmissionData(false)\n if (!checkBsbAreValidating(submission)) {\n return\n }\n if (!checkAttachmentsCanBeSubmitted(submission)) {\n return\n }\n\n onSaveDraft({\n definition,\n submission,\n })\n }\n }, [\n allowNavigation,\n checkAttachmentsCanBeSubmitted,\n definition,\n disabled,\n getCurrentSubmissionData,\n onSaveDraft,\n checkBsbAreValidating,\n ])\n\n // #endregion\n //\n //\n\n //\n //\n // #region Lookups\n\n const { handlePagesLookupResult } = useLookups(\n definition.id,\n setFormSubmission,\n )\n\n // #endregion\n //\n //\n\n //\n //\n // #region Submission/Definition Changes\n\n const handleChange = React.useCallback<FormElementValueChangeHandler>(\n (element, value) => {\n if (disabled || element.type === 'page' || element.type === 'section') {\n return\n }\n\n setUnsavedChangesState((current) => ({\n ...current,\n isDirty: true,\n }))\n\n setFormSubmission((currentFormSubmission) => ({\n ...currentFormSubmission,\n submission: {\n ...currentFormSubmission.submission,\n [element.name]:\n typeof value === 'function'\n ? value(currentFormSubmission.submission[element.name])\n : value,\n },\n }))\n },\n [disabled, setFormSubmission],\n )\n\n // #endregion\n //\n //\n\n if (conditionalLogicError) {\n return (\n <>\n <div className=\"has-text-centered\">\n <i className=\"material-icons has-text-warning icon-x-large\">error</i>\n <h3 className=\"title is-3\">Bad Form Configuration</h3>\n <p className=\"cypress-conditional-logic-error-message\">\n {conditionalLogicError.message}\n </p>\n <p className=\"has-text-grey\">\n {localisationService.formatDatetimeLong(new Date())}\n </p>\n </div>\n </>\n )\n }\n\n if (loadDynamicOptionsState) {\n return (\n <>\n <div className=\"has-text-centered\">\n <i className=\"material-icons has-text-warning icon-x-large\">error</i>\n <h3 className=\"title is-3\">{loadDynamicOptionsState.error.title}</h3>\n <p>{loadDynamicOptionsState.error.message}</p>\n <p className=\"has-text-grey\">\n {localisationService.formatDatetimeLong(new Date())}\n </p>\n </div>\n\n <OneBlinkAppsErrorOriginalMessage\n error={loadDynamicOptionsState.error.originalError}\n />\n </>\n )\n }\n\n return (\n <ThemeProvider theme={theme}>\n <div className=\"ob-form-container\" ref={obFormContainerHTMLElementRef}>\n <form\n name=\"obForm\"\n className={`ob-form cypress-ob-form ob-form__page-${\n currentPageIndex + 1\n }`}\n noValidate\n onSubmit={handleSubmit}\n >\n <div>\n <div ref={scrollToTopOfPageHTMLElementRef} />\n {isShowingMultiplePages && (\n <div\n className={clsx('ob-steps-navigation', {\n 'is-active': isStepsHeaderActive,\n })}\n >\n <div\n className={clsx('ob-steps-navigation__header', {\n 'is-active': isStepsHeaderActive,\n })}\n onClick={toggleStepsNavigation}\n >\n <span className=\"icon is-invisible\">\n <i className=\"material-icons\">keyboard_arrow_down</i>\n </span>\n <div className=\"steps-header-active-page\">\n {isDisplayingCurrentPageError ? (\n <span className=\"icon\">\n <i className=\"material-icons has-text-danger is-size-4\">\n warning\n </i>\n </span>\n ) : (\n <span className=\"steps-header-active-page-icon\">\n {currentPageNumber}\n </span>\n )}\n <span className=\"steps-header-active-page-label cypress-tablet-step-title\">\n {currentPage ? currentPage.label : ''}\n </span>\n </div>\n <span className=\"dropdown icon\">\n <i className=\"material-icons\">keyboard_arrow_down</i>\n </span>\n </div>\n\n <div\n className={clsx('ob-steps-navigation__steps', {\n 'is-active': isStepsHeaderActive,\n })}\n >\n <div className=\"steps is-small is-horizontal-tablet cypress-steps\">\n {visiblePages.map(\n (page: FormTypes.PageElement, index: number) => {\n const hasErrors = checkDisplayPageError(page)\n return (\n <div\n key={page.id}\n id={`steps-navigation-step-${page.id}`}\n className={clsx('step-item cypress-step-item', {\n 'is-active': currentPage.id === page.id,\n 'is-completed': currentPageIndex > index,\n 'is-error': hasErrors,\n })}\n onClick={(e) => {\n e.stopPropagation()\n if (page.id !== currentPage.id) {\n setPageId(page.id)\n }\n }}\n >\n <div\n className=\"step-marker step-marker-error ob-step-marker cypress-step-marker\"\n // @ts-expect-error ???\n name={`cypress-page-stepper-${index + 1}`}\n value={index + 1}\n >\n {hasErrors ? (\n <Tooltip title=\"Page has errors\">\n <span className=\"icon tooltip has-tooltip-top cypress-page-error\">\n <i className=\"material-icons has-text-danger is-size-3\">\n warning\n </i>\n </span>\n </Tooltip>\n ) : (\n <span>{index + 1}</span>\n )}\n </div>\n <div className=\"step-details ob-step-details\">\n <p className=\"step-title ob-step-title cypress-desktop-step-title\">\n {page.label}\n </p>\n </div>\n </div>\n )\n },\n )}\n </div>\n </div>\n </div>\n )}\n\n <div\n className={clsx('ob-steps-navigation__background', {\n 'is-active': isStepsHeaderActive,\n })}\n onClick={toggleStepsNavigation}\n />\n\n <div className=\"steps\">\n <div\n className={clsx('steps-content', {\n 'is-single-step': !isShowingMultiplePages,\n })}\n >\n <FormDefinitionContext.Provider value={definition}>\n <InjectPagesContext.Provider value={handlePagesLookupResult}>\n <ExecutedLookupProvider\n executedLookup={executedLookup}\n executeLookupFailed={executeLookupFailed}\n >\n <GoogleMapsApiKeyContext.Provider\n value={googleMapsApiKey}\n >\n <AbnLookupAuthenticationGuidContext.Provider\n value={abnLookupAuthenticationGuid}\n >\n <CaptchaSiteKeyContext.Provider\n value={captchaSiteKey}\n >\n <AttachmentBlobsProvider>\n <FormIsReadOnlyContext.Provider\n value={isReadOnly}\n >\n {visiblePages.map(\n (pageElement: FormTypes.PageElement) => (\n <PageFormElements\n key={pageElement.id}\n isActive={\n pageElement.id === currentPage.id\n }\n formId={definition.id}\n formElementsConditionallyShown={\n formElementsConditionallyShown\n }\n formElementsValidation={\n formElementsValidation\n }\n displayValidationMessages={\n hasAttemptedSubmit ||\n isDisplayingCurrentPageError\n }\n pageElement={pageElement}\n onChange={handleChange}\n model={submission}\n setFormSubmission={setFormSubmission}\n />\n ),\n )}\n </FormIsReadOnlyContext.Provider>\n </AttachmentBlobsProvider>\n </CaptchaSiteKeyContext.Provider>\n </AbnLookupAuthenticationGuidContext.Provider>\n </GoogleMapsApiKeyContext.Provider>\n </ExecutedLookupProvider>\n </InjectPagesContext.Provider>\n </FormDefinitionContext.Provider>\n </div>\n\n {isShowingMultiplePages && (\n <div className=\"steps-actions\">\n <div className=\"steps-action\">\n <button\n type=\"button\"\n onClick={goToPreviousPage}\n disabled={isFirstVisiblePage}\n className=\"button is-light cypress-pages-previous\"\n >\n <span className=\"icon\">\n <i className=\"material-icons\">keyboard_arrow_left</i>\n </span>\n <span>Back</span>\n </button>\n </div>\n <div className=\"step-progress-mobile cypress-steps-mobile\">\n {visiblePages.map((page: FormTypes.PageElement, index) => (\n <div\n key={page.id}\n className={clsx('step-progress-mobile-dot', {\n 'is-active': currentPage.id === page.id,\n 'is-completed': currentPageIndex > index,\n 'has-background-danger':\n currentPage.id !== page.id &&\n checkDisplayPageError(page),\n })}\n />\n ))}\n </div>\n <div className=\"steps-action\">\n <button\n type=\"button\"\n onClick={goToNextPage}\n disabled={isLastVisiblePage}\n className=\"button is-light cypress-pages-next\"\n >\n <span>Next</span>\n <span className=\"icon\">\n <i className=\"material-icons\">keyboard_arrow_right</i>\n </span>\n </button>\n </div>\n </div>\n )}\n </div>\n {!isReadOnly && (\n <div className=\"buttons ob-buttons ob-buttons-submit\">\n {onSaveDraft && !definition.isInfoPage && (\n <button\n type=\"button\"\n className=\"button ob-button is-primary ob-button-save-draft cypress-save-draft-form\"\n onClick={handleSaveDraft}\n disabled={isPreview || disabled}\n >\n <CustomisableButtonInner\n label={buttons?.saveDraft?.label || 'Save Draft'}\n icon={buttons?.saveDraft?.icon}\n />\n </button>\n )}\n <span className=\"ob-buttons-submit__spacer\"></span>\n {!definition.isInfoPage && (\n <button\n type=\"button\"\n className=\"button ob-button is-light ob-button-submit-cancel cypress-cancel-form\"\n onClick={handleCancel}\n disabled={isPreview || disabled}\n >\n <CustomisableButtonInner\n label={buttons?.cancel?.label || 'Cancel'}\n icon={buttons?.cancel?.icon}\n />\n </button>\n )}\n {isLastVisiblePage && (\n <button\n type=\"submit\"\n className=\"button ob-button is-success ob-button-submit cypress-submit-form-button cypress-submit-form\"\n disabled={isPreview || disabled}\n >\n <CustomisableButtonInner\n label={\n definition.isInfoPage\n ? 'Done'\n : buttons?.submit?.label || 'Submit'\n }\n icon={buttons?.submit?.icon}\n />\n </button>\n )}\n </div>\n )}\n </div>\n </form>\n\n {!isReadOnly && (\n <React.Fragment>\n <Prompt\n when={isDirty && !isNavigationAllowed}\n message={handleBlockedNavigation}\n />\n <Modal\n isOpen={hasConfirmedNavigation === false}\n title=\"Unsaved Changes\"\n cardClassName=\"cypress-cancel-confirm\"\n titleClassName=\"cypress-cancel-confirm-title\"\n bodyClassName=\"cypress-cancel-confirm-body\"\n actions={\n <>\n {onSaveDraft && (\n <button\n type=\"button\"\n className=\"button ob-button is-success cypress-cancel-confirm-save-draft\"\n onClick={handleSaveDraft}\n >\n <CustomisableButtonInner\n label={buttons?.saveDraft?.label || 'Save Draft'}\n icon={buttons?.saveDraft?.icon}\n />\n </button>\n )}\n <span style={{ flex: 1 }}></span>\n <button\n type=\"button\"\n className=\"button ob-button is-light cypress-cancel-confirm-back\"\n onClick={handleKeepGoing}\n >\n <CustomisableButtonInner\n label={buttons?.cancelPromptNo?.label || 'Back'}\n icon={buttons?.cancelPromptNo?.icon}\n />\n </button>\n <button\n type=\"button\"\n className=\"button ob-button is-primary cypress-cancel-confirm-discard\"\n onClick={handleDiscardUnsavedChanges}\n >\n <CustomisableButtonInner\n label={buttons?.cancelPromptYes?.label || 'Discard'}\n icon={buttons?.cancelPromptYes?.icon}\n />\n </button>\n </>\n }\n >\n <p>\n You have unsaved changes, are you sure you want discard them?\n </p>\n </Modal>\n </React.Fragment>\n )}\n </div>\n </ThemeProvider>\n )\n}\n\nexport default React.memo(OneBlinkFormBase)\n"]}
@@ -14,7 +14,7 @@ const FormElementFile = ({ element, onRemove, file, onChange, disableUpload, })
14
14
  await downloadAttachment(file);
15
15
  }, [file]);
16
16
  const handleRetry = React.useMemo(() => {
17
- if (file.type === 'ERROR') {
17
+ if (file.type === 'ERROR' && file.data) {
18
18
  return () => {
19
19
  onChange(file._id, {
20
20
  type: 'NEW',
@@ -1 +1 @@
1
- {"version":3,"file":"FormElementFile.js","sourceRoot":"","sources":["../../../src/form-elements/FormElementFiles/FormElementFile.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,kBAAkB,MAAM,8BAA8B,CAAA;AAE7D,OAAO,aAA2B,MAAM,uCAAuC,CAAA;AAC/E,OAAO,QAAQ,MAAM,uCAAuC,CAAA;AAW5D,MAAM,eAAe,GAAG,CAAC,EACvB,OAAO,EACP,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,aAAa,GACP,EAAE,EAAE;IACV,MAAM,gBAAgB,GAAG,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAA;IAE9E,MAAM,YAAY,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QAC1C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YACd,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;SACzB;QACD,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC3B,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAA;IAEpB,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE;QAClD,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAA;IAChC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;IAEV,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACrC,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE;YACzB,OAAO,GAAG,EAAE;gBACV,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE;oBACjB,IAAI,EAAE,KAAK;oBACX,GAAG,EAAE,IAAI,CAAC,GAAG;oBACb,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,SAAS,EAAE,IAAI,CAAC,SAAS;iBAC1B,CAAC,CAAA;YACJ,CAAC,CAAA;SACF;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAA;IAEpB,OAAO,CACL,oBAAC,QAAQ,IACP,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,gBAAgB,CAAC,WAAW,EACzC,cAAc,EAAE,aAAa,EAC7B,kBAAkB,EAAE,gBAAgB,CAAC,kBAAkB,EACvD,iBAAiB,EAAE,gBAAgB,CAAC,iBAAiB,EACrD,iBAAiB,EAAE,gBAAgB,CAAC,iBAAiB,EACrD,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,EACnC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EACvB,UAAU,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,EACrE,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,WAAW,GACpB,CACH,CAAA;AACH,CAAC,CAAA;AAED,eAAe,KAAK,CAAC,IAAI,CAAQ,eAAe,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport downloadAttachment from '../../services/download-file'\nimport { FormTypes } from '@oneblink/types'\nimport useAttachment, { OnChange } from '../../hooks/attachments/useAttachment'\nimport FileCard from '../../components/attachments/FileCard'\nimport { Attachment } from '../../types/attachments'\n\ntype Props = {\n element: FormTypes.FilesElement\n onRemove: (id: string) => void\n file: Attachment\n disableUpload: boolean\n onChange: OnChange\n}\n\nconst FormElementFile = ({\n element,\n onRemove,\n file,\n onChange,\n disableUpload,\n}: Props) => {\n const attachmentResult = useAttachment(file, element, onChange, disableUpload)\n\n const handleRemove = React.useCallback(() => {\n if (!file.type) {\n return onRemove(file.id)\n }\n return onRemove(file._id)\n }, [file, onRemove])\n\n const handleDownload = React.useCallback(async () => {\n await downloadAttachment(file)\n }, [file])\n\n const handleRetry = React.useMemo(() => {\n if (file.type === 'ERROR') {\n return () => {\n onChange(file._id, {\n type: 'NEW',\n _id: file._id,\n data: file.data,\n fileName: file.fileName,\n isPrivate: file.isPrivate,\n })\n }\n }\n }, [file, onChange])\n\n return (\n <FileCard\n element={element}\n isUploading={attachmentResult.isUploading}\n isUploadPaused={disableUpload}\n uploadErrorMessage={attachmentResult.uploadErrorMessage}\n loadImageUrlError={attachmentResult.loadImageUrlError}\n isLoadingImageUrl={attachmentResult.isLoadingImageUrl}\n imageUrl={attachmentResult.imageUrl}\n fileName={file.fileName}\n onDownload={attachmentResult.canDownload ? handleDownload : undefined}\n onRemove={handleRemove}\n onRetry={handleRetry}\n />\n )\n}\n\nexport default React.memo<Props>(FormElementFile)\n"]}
1
+ {"version":3,"file":"FormElementFile.js","sourceRoot":"","sources":["../../../src/form-elements/FormElementFiles/FormElementFile.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,kBAAkB,MAAM,8BAA8B,CAAA;AAE7D,OAAO,aAA2B,MAAM,uCAAuC,CAAA;AAC/E,OAAO,QAAQ,MAAM,uCAAuC,CAAA;AAW5D,MAAM,eAAe,GAAG,CAAC,EACvB,OAAO,EACP,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,aAAa,GACP,EAAE,EAAE;IACV,MAAM,gBAAgB,GAAG,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAA;IAE9E,MAAM,YAAY,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QAC1C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YACd,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;SACzB;QACD,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC3B,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAA;IAEpB,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE;QAClD,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAA;IAChC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;IAEV,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACrC,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE;YACtC,OAAO,GAAG,EAAE;gBACV,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE;oBACjB,IAAI,EAAE,KAAK;oBACX,GAAG,EAAE,IAAI,CAAC,GAAG;oBACb,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,SAAS,EAAE,IAAI,CAAC,SAAS;iBAC1B,CAAC,CAAA;YACJ,CAAC,CAAA;SACF;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAA;IAEpB,OAAO,CACL,oBAAC,QAAQ,IACP,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,gBAAgB,CAAC,WAAW,EACzC,cAAc,EAAE,aAAa,EAC7B,kBAAkB,EAAE,gBAAgB,CAAC,kBAAkB,EACvD,iBAAiB,EAAE,gBAAgB,CAAC,iBAAiB,EACrD,iBAAiB,EAAE,gBAAgB,CAAC,iBAAiB,EACrD,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,EACnC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EACvB,UAAU,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,EACrE,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,WAAW,GACpB,CACH,CAAA;AACH,CAAC,CAAA;AAED,eAAe,KAAK,CAAC,IAAI,CAAQ,eAAe,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport downloadAttachment from '../../services/download-file'\nimport { FormTypes } from '@oneblink/types'\nimport useAttachment, { OnChange } from '../../hooks/attachments/useAttachment'\nimport FileCard from '../../components/attachments/FileCard'\nimport { Attachment } from '../../types/attachments'\n\ntype Props = {\n element: FormTypes.FilesElement\n onRemove: (id: string) => void\n file: Attachment\n disableUpload: boolean\n onChange: OnChange\n}\n\nconst FormElementFile = ({\n element,\n onRemove,\n file,\n onChange,\n disableUpload,\n}: Props) => {\n const attachmentResult = useAttachment(file, element, onChange, disableUpload)\n\n const handleRemove = React.useCallback(() => {\n if (!file.type) {\n return onRemove(file.id)\n }\n return onRemove(file._id)\n }, [file, onRemove])\n\n const handleDownload = React.useCallback(async () => {\n await downloadAttachment(file)\n }, [file])\n\n const handleRetry = React.useMemo(() => {\n if (file.type === 'ERROR' && file.data) {\n return () => {\n onChange(file._id, {\n type: 'NEW',\n _id: file._id,\n data: file.data,\n fileName: file.fileName,\n isPrivate: file.isPrivate,\n })\n }\n }\n }, [file, onChange])\n\n return (\n <FileCard\n element={element}\n isUploading={attachmentResult.isUploading}\n isUploadPaused={disableUpload}\n uploadErrorMessage={attachmentResult.uploadErrorMessage}\n loadImageUrlError={attachmentResult.loadImageUrlError}\n isLoadingImageUrl={attachmentResult.isLoadingImageUrl}\n imageUrl={attachmentResult.imageUrl}\n fileName={file.fileName}\n onDownload={attachmentResult.canDownload ? handleDownload : undefined}\n onRemove={handleRemove}\n onRetry={handleRetry}\n />\n )\n}\n\nexport default React.memo<Props>(FormElementFile)\n"]}
@@ -5,11 +5,13 @@ import useIsOffline from '../useIsOffline';
5
5
  import { checkIfContentTypeIsImage } from '../../services/attachments';
6
6
  import useAuth from '../../hooks/useAuth';
7
7
  import { urlToBlobAsync } from '../../services/blob-utils';
8
+ import useAttachmentBlobs from '../../hooks/attachments/useAttachmentBlobs';
8
9
  export default function useAttachment(value, element, onChange, disableUpload) {
9
10
  const isPrivate = element.storageType === 'private';
10
11
  const form = useFormDefinition();
11
12
  const isOffline = useIsOffline();
12
13
  const { isLoggedIn, isUsingFormsKey } = useAuth();
14
+ const { storeAttachmentBlobLocally, getAttachmentBlobLocally } = useAttachmentBlobs();
13
15
  const isAuthenticated = isLoggedIn || isUsingFormsKey;
14
16
  const [imageUrlState, setImageUrlState] = React.useState({});
15
17
  // TRIGGER UPLOAD
@@ -20,10 +22,12 @@ export default function useAttachment(value, element, onChange, disableUpload) {
20
22
  !formId ||
21
23
  !value ||
22
24
  typeof value !== 'object' ||
23
- value.type !== 'NEW') {
25
+ value.type !== 'NEW' ||
26
+ !value.data) {
24
27
  return;
25
28
  }
26
29
  const newAttachment = value;
30
+ const data = value.data;
27
31
  let ignore = false;
28
32
  const abortController = new AbortController();
29
33
  const effect = async () => {
@@ -32,13 +36,17 @@ export default function useAttachment(value, element, onChange, disableUpload) {
32
36
  const upload = await submissionService.uploadAttachment({
33
37
  formId,
34
38
  fileName: newAttachment.fileName,
35
- contentType: newAttachment.data.type,
36
- data: newAttachment.data,
39
+ contentType: data.type,
40
+ data,
37
41
  isPrivate,
38
42
  }, abortController.signal);
39
43
  if (ignore) {
40
44
  return;
41
45
  }
46
+ // Store Blob in Context if image is private
47
+ if (isPrivate) {
48
+ storeAttachmentBlobLocally({ attachmentId: upload.id, blob: data });
49
+ }
42
50
  console.log('Successfully Uploaded attachment!', upload);
43
51
  // UPDATE ATTACHMENT
44
52
  onChange(newAttachment._id, upload);
@@ -60,7 +68,15 @@ export default function useAttachment(value, element, onChange, disableUpload) {
60
68
  ignore = true;
61
69
  abortController.abort();
62
70
  };
63
- }, [disableUpload, form === null || form === void 0 ? void 0 : form.id, isOffline, isPrivate, onChange, value]);
71
+ }, [
72
+ disableUpload,
73
+ form === null || form === void 0 ? void 0 : form.id,
74
+ isOffline,
75
+ isPrivate,
76
+ onChange,
77
+ storeAttachmentBlobLocally,
78
+ value,
79
+ ]);
64
80
  // TRIGGER DOWNLOAD
65
81
  React.useEffect(() => {
66
82
  if (!value) {
@@ -74,6 +90,9 @@ export default function useAttachment(value, element, onChange, disableUpload) {
74
90
  return;
75
91
  }
76
92
  if (value.type) {
93
+ if (!value.data) {
94
+ return;
95
+ }
77
96
  if (!checkIfContentTypeIsImage(value.data.type)) {
78
97
  // Not an image which we will represent as null
79
98
  setImageUrlState({
@@ -102,13 +121,22 @@ export default function useAttachment(value, element, onChange, disableUpload) {
102
121
  });
103
122
  return;
104
123
  }
105
- // If user is not logged in, we can't download private images.
106
- // Luckily, the imageUrl should already be set as the blob
107
- // url from when they uploaded it. Same applies if they are offline.
124
+ // Check for locally stored Blob. Blob should be stored locally for private uploaded images only
125
+ const locallyStoredAttachment = getAttachmentBlobLocally(value.id);
126
+ if (locallyStoredAttachment) {
127
+ const imageUrl = URL.createObjectURL(locallyStoredAttachment.blob);
128
+ console.log('Created object url from locally stored Blob for private image attachment', imageUrl);
129
+ setImageUrlState({
130
+ imageUrl,
131
+ });
132
+ return;
133
+ }
134
+ // If user is not logged in or is offline, we can't download private images.
135
+ // If the blob was not stored locally (above) for some reason, the user is SOL
108
136
  if (!isAuthenticated || isOffline) {
109
- setImageUrlState((currentState) => ({
110
- imageUrl: currentState.imageUrl || null,
111
- }));
137
+ setImageUrlState({
138
+ imageUrl: null,
139
+ });
112
140
  return;
113
141
  }
114
142
  let ignore = false;
@@ -120,6 +148,8 @@ export default function useAttachment(value, element, onChange, disableUpload) {
120
148
  if (ignore) {
121
149
  return;
122
150
  }
151
+ // Store private image attachment in Context
152
+ storeAttachmentBlobLocally({ attachmentId: value.id, blob });
123
153
  const imageUrl = URL.createObjectURL(blob);
124
154
  console.log('Created object url from private attachment for image', imageUrl);
125
155
  setImageUrlState({
@@ -141,7 +171,13 @@ export default function useAttachment(value, element, onChange, disableUpload) {
141
171
  ignore = true;
142
172
  abortController.abort();
143
173
  };
144
- }, [isAuthenticated, isOffline, value]);
174
+ }, [
175
+ getAttachmentBlobLocally,
176
+ isAuthenticated,
177
+ isOffline,
178
+ storeAttachmentBlobLocally,
179
+ value,
180
+ ]);
145
181
  React.useEffect(() => {
146
182
  return () => {
147
183
  const imageUrl = imageUrlState.imageUrl;
@@ -166,11 +202,28 @@ export default function useAttachment(value, element, onChange, disableUpload) {
166
202
  }
167
203
  }, [value]);
168
204
  const canDownload = React.useMemo(() => {
169
- return (!!value &&
170
- (typeof value === 'string' ||
171
- !!value.type ||
172
- !value.isPrivate ||
173
- isAuthenticated));
205
+ if (!value) {
206
+ return false;
207
+ }
208
+ // legacy attachment as base64 data
209
+ if (typeof value === 'string') {
210
+ return true;
211
+ }
212
+ // attachments still uploading or failed to upload
213
+ if (value.type) {
214
+ // can only be downloaded if we still have the data
215
+ return !!value.data;
216
+ }
217
+ // attachments that have been uploaded
218
+ // public attachments can always be downloaded
219
+ if (!value.isPrivate) {
220
+ return true;
221
+ }
222
+ // private attachments can only be downloaded if user is authenticated
223
+ if (isAuthenticated) {
224
+ return true;
225
+ }
226
+ return false;
174
227
  }, [isAuthenticated, value]);
175
228
  return {
176
229
  isUploading,
@@ -1 +1 @@
1
- {"version":3,"file":"useAttachment.js","sourceRoot":"","sources":["../../../src/hooks/attachments/useAttachment.ts"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport { submissionService } from '@oneblink/apps'\nimport { FormTypes } from '@oneblink/types'\nimport useFormDefinition from '../useFormDefinition'\nimport useIsOffline from '../useIsOffline'\nimport {\n Attachment,\n AttachmentNew,\n FormElementBinaryStorageValue,\n} from '../../types/attachments'\nimport { checkIfContentTypeIsImage } from '../../services/attachments'\nimport useAuth from '../../hooks/useAuth'\nimport { urlToBlobAsync } from '../../services/blob-utils'\n\nexport type OnChange = (id: string, attachment: Attachment) => void\n\nexport default function useAttachment(\n value: FormElementBinaryStorageValue,\n element: FormTypes.FormElementBinaryStorage,\n onChange: OnChange,\n disableUpload?: boolean,\n) {\n const isPrivate = element.storageType === 'private'\n const form = useFormDefinition()\n const isOffline = useIsOffline()\n const { isLoggedIn, isUsingFormsKey } = useAuth()\n\n const isAuthenticated = isLoggedIn || isUsingFormsKey\n\n const [imageUrlState, setImageUrlState] = React.useState<{\n imageUrl?: string | null\n loadImageUrlError?: Error\n }>({})\n\n // TRIGGER UPLOAD\n React.useEffect(() => {\n const formId = form?.id\n\n if (\n isOffline ||\n disableUpload ||\n !formId ||\n !value ||\n typeof value !== 'object' ||\n value.type !== 'NEW'\n ) {\n return\n }\n\n const newAttachment = value as AttachmentNew\n\n let ignore = false\n const abortController = new AbortController()\n\n const effect = async () => {\n try {\n console.log(\n 'Attempting to upload attachment...',\n newAttachment.fileName,\n )\n const upload = await submissionService.uploadAttachment(\n {\n formId,\n fileName: newAttachment.fileName,\n contentType: newAttachment.data.type,\n data: newAttachment.data,\n isPrivate,\n },\n abortController.signal,\n )\n if (ignore) {\n return\n }\n\n console.log('Successfully Uploaded attachment!', upload)\n\n // UPDATE ATTACHMENT\n onChange(newAttachment._id, upload)\n } catch (error) {\n if (ignore) {\n return\n }\n\n console.warn(\n 'Failed to upload attachment...',\n newAttachment.fileName,\n error,\n )\n onChange(newAttachment._id, {\n ...newAttachment,\n type: 'ERROR',\n errorMessage: (error as Error).message,\n })\n }\n }\n\n effect()\n\n return () => {\n ignore = true\n abortController.abort()\n }\n }, [disableUpload, form?.id, isOffline, isPrivate, onChange, value])\n\n // TRIGGER DOWNLOAD\n React.useEffect(() => {\n if (!value) {\n return\n }\n\n // If the value is string we will assume a base64 data uri\n if (typeof value === 'string') {\n setImageUrlState({\n imageUrl: value,\n })\n return\n }\n\n if (value.type) {\n if (!checkIfContentTypeIsImage(value.data.type)) {\n // Not an image which we will represent as null\n setImageUrlState({\n imageUrl: null,\n })\n return\n }\n\n const imageUrl = URL.createObjectURL(value.data)\n console.log('Created object url from blob for image', imageUrl)\n setImageUrlState({\n imageUrl,\n })\n return\n }\n\n if (!checkIfContentTypeIsImage(value.contentType)) {\n // Not an image which we will represent as null\n setImageUrlState({\n imageUrl: null,\n })\n return\n }\n\n // If the file is a public url we can finish here and just use that\n if (!value.isPrivate) {\n setImageUrlState({\n imageUrl: value.url,\n })\n return\n }\n\n // If user is not logged in, we can't download private images.\n // Luckily, the imageUrl should already be set as the blob\n // url from when they uploaded it. Same applies if they are offline.\n if (!isAuthenticated || isOffline) {\n setImageUrlState((currentState) => ({\n imageUrl: currentState.imageUrl || null,\n }))\n return\n }\n\n let ignore = false\n const abortController = new AbortController()\n const privateImageUrl = value.url\n\n const effect = async () => {\n try {\n const blob = await urlToBlobAsync(\n privateImageUrl,\n true,\n abortController.signal,\n )\n if (ignore) {\n return\n }\n\n const imageUrl = URL.createObjectURL(blob)\n console.log(\n 'Created object url from private attachment for image',\n imageUrl,\n )\n setImageUrlState({\n imageUrl,\n })\n } catch (error) {\n if (ignore) {\n return\n }\n console.warn('Error loading file:', error)\n setImageUrlState({\n loadImageUrlError: error as Error,\n })\n }\n }\n effect()\n\n return () => {\n ignore = true\n abortController.abort()\n }\n }, [isAuthenticated, isOffline, value])\n\n React.useEffect(() => {\n return () => {\n const imageUrl = imageUrlState.imageUrl\n if (imageUrl && imageUrl.startsWith('blob:')) {\n console.log('revoking image url:', imageUrl)\n URL.revokeObjectURL(imageUrl)\n }\n }\n }, [imageUrlState.imageUrl])\n\n const isUploading = React.useMemo(() => {\n return !!(\n value &&\n typeof value !== 'string' &&\n value.type &&\n value.type === 'NEW'\n )\n }, [value])\n\n const uploadErrorMessage = React.useMemo(() => {\n if (\n value &&\n typeof value !== 'string' &&\n value.type &&\n value.type === 'ERROR'\n ) {\n return value.errorMessage\n }\n }, [value])\n\n const canDownload = React.useMemo(() => {\n return (\n !!value &&\n (typeof value === 'string' ||\n !!value.type ||\n !value.isPrivate ||\n isAuthenticated)\n )\n }, [isAuthenticated, value])\n\n return {\n isUploading,\n uploadErrorMessage,\n isLoadingImageUrl: imageUrlState.imageUrl === undefined,\n ...imageUrlState,\n canDownload,\n }\n}\n"]}
1
+ {"version":3,"file":"useAttachment.js","sourceRoot":"","sources":["../../../src/hooks/attachments/useAttachment.ts"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport { submissionService } from '@oneblink/apps'\nimport { FormTypes } from '@oneblink/types'\nimport useFormDefinition from '../useFormDefinition'\nimport useIsOffline from '../useIsOffline'\nimport {\n Attachment,\n AttachmentNew,\n FormElementBinaryStorageValue,\n} from '../../types/attachments'\nimport { checkIfContentTypeIsImage } from '../../services/attachments'\nimport useAuth from '../../hooks/useAuth'\nimport { urlToBlobAsync } from '../../services/blob-utils'\nimport useAttachmentBlobs from '../../hooks/attachments/useAttachmentBlobs'\n\nexport type OnChange = (id: string, attachment: Attachment) => void\n\nexport default function useAttachment(\n value: FormElementBinaryStorageValue,\n element: FormTypes.FormElementBinaryStorage,\n onChange: OnChange,\n disableUpload?: boolean,\n) {\n const isPrivate = element.storageType === 'private'\n const form = useFormDefinition()\n const isOffline = useIsOffline()\n const { isLoggedIn, isUsingFormsKey } = useAuth()\n const { storeAttachmentBlobLocally, getAttachmentBlobLocally } =\n useAttachmentBlobs()\n\n const isAuthenticated = isLoggedIn || isUsingFormsKey\n\n const [imageUrlState, setImageUrlState] = React.useState<{\n imageUrl?: string | null\n loadImageUrlError?: Error\n }>({})\n\n // TRIGGER UPLOAD\n React.useEffect(() => {\n const formId = form?.id\n\n if (\n isOffline ||\n disableUpload ||\n !formId ||\n !value ||\n typeof value !== 'object' ||\n value.type !== 'NEW' ||\n !value.data\n ) {\n return\n }\n\n const newAttachment = value as AttachmentNew\n const data = value.data\n\n let ignore = false\n const abortController = new AbortController()\n\n const effect = async () => {\n try {\n console.log(\n 'Attempting to upload attachment...',\n newAttachment.fileName,\n )\n const upload = await submissionService.uploadAttachment(\n {\n formId,\n fileName: newAttachment.fileName,\n contentType: data.type,\n data,\n isPrivate,\n },\n abortController.signal,\n )\n if (ignore) {\n return\n }\n // Store Blob in Context if image is private\n if (isPrivate) {\n storeAttachmentBlobLocally({ attachmentId: upload.id, blob: data })\n }\n\n console.log('Successfully Uploaded attachment!', upload)\n\n // UPDATE ATTACHMENT\n onChange(newAttachment._id, upload)\n } catch (error) {\n if (ignore) {\n return\n }\n\n console.warn(\n 'Failed to upload attachment...',\n newAttachment.fileName,\n error,\n )\n onChange(newAttachment._id, {\n ...newAttachment,\n type: 'ERROR',\n errorMessage: (error as Error).message,\n })\n }\n }\n\n effect()\n\n return () => {\n ignore = true\n abortController.abort()\n }\n }, [\n disableUpload,\n form?.id,\n isOffline,\n isPrivate,\n onChange,\n storeAttachmentBlobLocally,\n value,\n ])\n\n // TRIGGER DOWNLOAD\n React.useEffect(() => {\n if (!value) {\n return\n }\n\n // If the value is string we will assume a base64 data uri\n if (typeof value === 'string') {\n setImageUrlState({\n imageUrl: value,\n })\n return\n }\n\n if (value.type) {\n if (!value.data) {\n return\n }\n\n if (!checkIfContentTypeIsImage(value.data.type)) {\n // Not an image which we will represent as null\n setImageUrlState({\n imageUrl: null,\n })\n return\n }\n\n const imageUrl = URL.createObjectURL(value.data)\n console.log('Created object url from blob for image', imageUrl)\n setImageUrlState({\n imageUrl,\n })\n return\n }\n\n if (!checkIfContentTypeIsImage(value.contentType)) {\n // Not an image which we will represent as null\n setImageUrlState({\n imageUrl: null,\n })\n return\n }\n\n // If the file is a public url we can finish here and just use that\n if (!value.isPrivate) {\n setImageUrlState({\n imageUrl: value.url,\n })\n return\n }\n\n // Check for locally stored Blob. Blob should be stored locally for private uploaded images only\n const locallyStoredAttachment = getAttachmentBlobLocally(value.id)\n if (locallyStoredAttachment) {\n const imageUrl = URL.createObjectURL(locallyStoredAttachment.blob)\n console.log(\n 'Created object url from locally stored Blob for private image attachment',\n imageUrl,\n )\n setImageUrlState({\n imageUrl,\n })\n return\n }\n\n // If user is not logged in or is offline, we can't download private images.\n // If the blob was not stored locally (above) for some reason, the user is SOL\n if (!isAuthenticated || isOffline) {\n setImageUrlState({\n imageUrl: null,\n })\n return\n }\n\n let ignore = false\n const abortController = new AbortController()\n const privateImageUrl = value.url\n\n const effect = async () => {\n try {\n const blob = await urlToBlobAsync(\n privateImageUrl,\n true,\n abortController.signal,\n )\n if (ignore) {\n return\n }\n // Store private image attachment in Context\n storeAttachmentBlobLocally({ attachmentId: value.id, blob })\n const imageUrl = URL.createObjectURL(blob)\n console.log(\n 'Created object url from private attachment for image',\n imageUrl,\n )\n setImageUrlState({\n imageUrl,\n })\n } catch (error) {\n if (ignore) {\n return\n }\n console.warn('Error loading file:', error)\n setImageUrlState({\n loadImageUrlError: error as Error,\n })\n }\n }\n effect()\n\n return () => {\n ignore = true\n abortController.abort()\n }\n }, [\n getAttachmentBlobLocally,\n isAuthenticated,\n isOffline,\n storeAttachmentBlobLocally,\n value,\n ])\n\n React.useEffect(() => {\n return () => {\n const imageUrl = imageUrlState.imageUrl\n if (imageUrl && imageUrl.startsWith('blob:')) {\n console.log('revoking image url:', imageUrl)\n URL.revokeObjectURL(imageUrl)\n }\n }\n }, [imageUrlState.imageUrl])\n\n const isUploading = React.useMemo(() => {\n return !!(\n value &&\n typeof value !== 'string' &&\n value.type &&\n value.type === 'NEW'\n )\n }, [value])\n\n const uploadErrorMessage = React.useMemo(() => {\n if (\n value &&\n typeof value !== 'string' &&\n value.type &&\n value.type === 'ERROR'\n ) {\n return value.errorMessage\n }\n }, [value])\n\n const canDownload = React.useMemo(() => {\n if (!value) {\n return false\n }\n\n // legacy attachment as base64 data\n if (typeof value === 'string') {\n return true\n }\n\n // attachments still uploading or failed to upload\n if (value.type) {\n // can only be downloaded if we still have the data\n return !!value.data\n }\n\n // attachments that have been uploaded\n // public attachments can always be downloaded\n if (!value.isPrivate) {\n return true\n }\n\n // private attachments can only be downloaded if user is authenticated\n if (isAuthenticated) {\n return true\n }\n\n return false\n }, [isAuthenticated, value])\n\n return {\n isUploading,\n uploadErrorMessage,\n isLoadingImageUrl: imageUrlState.imageUrl === undefined,\n ...imageUrlState,\n canDownload,\n }\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+ declare type AttachmentObjectBlob = {
3
+ attachmentId: string;
4
+ blob: Blob;
5
+ };
6
+ declare type RegisterAttachmentParam = {
7
+ blob: Blob;
8
+ attachmentId: string;
9
+ };
10
+ declare type AttachmentBlobsContextValue = {
11
+ storeAttachmentBlobLocally: (options: RegisterAttachmentParam) => void;
12
+ getAttachmentBlobLocally: (attachmentId: string) => AttachmentObjectBlob | undefined;
13
+ };
14
+ declare type Props = {
15
+ children: React.ReactNode;
16
+ };
17
+ export declare const AttachmentBlobsProvider: ({ children }: Props) => JSX.Element;
18
+ declare const useAttachmentBlobs: () => AttachmentBlobsContextValue;
19
+ export default useAttachmentBlobs;