All files / FormModal FormModal.js

33.33% Statements 12/36
14.81% Branches 4/27
37.5% Functions 3/8
33.33% Lines 12/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153            26x                     3x   3x           3x 3x           3x                                                                                             3x 3x                   3x 3x                                                     3x                             26x                                      
import PropTypes from 'prop-types';
 
import { Form } from 'react-final-form';
import { Button, Modal, ModalFooter } from '@folio/stripes/components';
import { useKintIntl } from '../hooks';
 
const FormModal = ({
  children,
  intlKey: passedIntlKey,
  intlNS: passedIntlNS,
  labelOverrides = {},
  modalProps: { footer, onClose, ...modalProps },
  onError, // Optional handler to run onSuccess for default handleSaveAndClear
  onSubmit,
  onSuccess, // Optional handler to run onSuccess for default handleSaveAndClear
  ...formProps
}) => {
  const kintIntl = useKintIntl(passedIntlKey, passedIntlNS);
 
  return (
    <Form
      onSubmit={onSubmit}
      {...formProps}
    >
      {({ handleSubmit, form: { getState, restart } }) => {
        const formState = getState();
        const handleClose = (e) => {
          onClose(e);
          restart();
        };
 
        // Handle asynchronous submit functions differently to synchronous ones
        const handleSaveAndClear = (...onSaveProps) => {
          try {
            const submitReturn = handleSubmit(...onSaveProps);
 
            // Figure out if we're in an async or sync submit function
            if (typeof submitReturn === 'object' && typeof submitReturn.then === 'function') {
              // Async function
              return submitReturn.then((incomingParams) => {
                restart();
                return incomingParams;
              }).then((incomingParams) => {
                if (onSuccess && typeof onSuccess === 'function') {
                  // Allow onSuccess to dictate what continues downstream
                  return onSuccess(incomingParams);
                }
                return incomingParams;
              }).catch((incomingParams) => {
                if (onError && typeof onError === 'function') {
                  // Allow onError to dictate what continues downstream
                  return onError(incomingParams);
                }
                return incomingParams;
              });
            } else if (onSuccess && typeof onSuccess === 'function') {
              // Sync function and we have an onSuccess handler
 
              // onSuccess dictates return
              const returnShape = onSuccess(submitReturn);
              restart();
              return returnShape;
            } else {
              // Sync function and we have no onSuccess handler
 
              restart();
              return submitReturn;
            }
          } catch (err) {
            // Sync function catch
            if (onError && typeof onError === 'function') {
              // Allow onError to dictate what continues downstream
              return onError(err);
            }
 
            return null;
          }
        };
 
        const renderFooter = () => {
          Iif (footer) {
            return footer({
              formState,
              handleSubmit: handleSaveAndClear,
              handleClose,
              handleSubmitNoRestart: handleSubmit, // DEPRECATED -- should use handleSubmitRaw
              handleSubmitRaw: handleSubmit
            });
          }
 
          const { invalid, pristine, submitting, validating } = formState;
          return (
            <ModalFooter>
              <Button
                buttonStyle="primary"
                disabled={submitting || invalid || pristine || validating}
                marginBottom0
                onClick={handleSaveAndClear}
                type="submit"
              >
                {kintIntl.formatKintMessage({
                  id: 'saveAndClose',
                  overrideValue: labelOverrides.saveAndClose
                })}
              </Button>
              <Button
                marginBottom0
                onClick={handleClose}
              >
                {kintIntl.formatKintMessage({
                  id: 'cancel',
                  overrideValue: labelOverrides.cancel
                })}
              </Button>
            </ModalFooter>
          );
        };
 
        return (
          <Modal
            enforceFocus={false}
            footer={renderFooter()}
            onClose={handleClose}
            {...modalProps}
          >
            {children}
          </Modal>
        );
      }}
    </Form>
  );
};
 
FormModal.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(PropTypes.node),
    PropTypes.node,
    PropTypes.func,
  ]),
  intlKey: PropTypes.string,
  intlNS: PropTypes.string,
  labelOverrides: PropTypes.object,
  modalProps: PropTypes.shape({
    footer: PropTypes.func,
    onClose: PropTypes.func,
  }),
  onError: PropTypes.func,
  onSubmit: PropTypes.func,
  onSuccess: PropTypes.func
};
 
export default FormModal;