Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
@skava/ui / dist / forms / form / ObserverForm.js
Size: Mime:
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});

const tslib_1 = require("tslib");

var ObserverForm_1;

const react_1 = tslib_1.__importDefault(require("react"));

const exotic_1 = require("exotic");

const mobx_react_1 = require("xmobx/mobx-react");

const mobx_1 = require("xmobx/mobx");

const deps_1 = require("../deps");

const ObserverInput_1 = tslib_1.__importDefault(require("../input/ObserverInput"));

const deps_2 = require("../deps");

const FormState_1 = tslib_1.__importDefault(require("./FormState"));

const _elements_1 = require("./_elements");

const fixture_1 = require("./fixture");

const deps_3 = require("./deps");
/**
 * @todo https://www.w3.org/TR/wai-aria/states_and_properties#aria-errormessage
 *
 *
 * @note need to add refs like in my example, or pass in states
 * @todo - finish
 */


const handleCancel = event => {
  event.preventDefault();
};

let ObserverForm = ObserverForm_1 = class ObserverForm extends react_1.default.Component {
  constructor(props) {
    super(props);
    /**
     * @todo !!! PUT THESE AS GETTERS AND SETTERS TO DEPRECATE
     */

    /**
     * @todo renderProps
     */

    this.Form = _elements_1.FormElement;
    this.Input = ObserverInput_1.default;
    this.SubmitButton = _elements_1.SubmitButton;
    this.CancelButton = _elements_1.CancelButton;
    this.shouldResetFormOnUnmount = false;
    /**
     * should have a simple object with wording & classnames, one property
     * @todo could also pass these in via defaultProps
     */

    this.defaultSubmitButtonLabel = fixture_1.wording.submit;
    this.defaultCancelButtonLabel = fixture_1.wording.cancel;
    /**
     * state...
     */

    this.isSubmitButtonNeeded = true;
    this.isCancelButtonNeeded = false;
    this.handleCancel = handleCancel;

    this.validateInputItem = item => {
      console.log('validateInputItem', item);
      const {
        isHidden,
        isDisabled,
        validationType,
        value,
        errorMessageFor,
        type
      } = item; // @todo - dedupe the other place & split out

      if ((!exotic_1.isSafe(isHidden) || !isHidden) && exotic_1.isSafe(validationType)) {
        if (validationType === 'month' || validationType === 'year') {
          if (this.state.validateExpiryDate(item) === false) {
            this.state.hasAllValidInputs = false;
            item.errorMessage = deps_2.errorMessage(errorMessageFor);
            item.isValidInput = false;
          }
        } else if (validationType === 'creditCard' || validationType === 'securityCode') {
          if (this.state.validateCreditCard(item) === false) {
            this.state.hasAllValidInputs = false;
            item.errorMessage = deps_2.errorMessage(errorMessageFor);
            item.isValidInput = false;
          }
        } else if (validationType === 'confirmPassword') {
          if (this.state.validateConfirmPassword(item) === false) {
            this.state.hasAllValidInputs = false;
          }
        } else if (validationType === 'newPassword') {
          if (this.state.validateNewPassword(item) === false) {
            this.state.hasAllValidInputs = false;
          }
        } else if (validationType === 'selectOption') {
          const {
            label
          } = item;

          if (deps_1.isValidSelect({
            value,
            label
          })) {
            item.isValidInput = true;
          } else {
            item.errorMessage = deps_2.errorMessage(errorMessageFor);
            item.isValidInput = false;
            this.state.hasAllValidInputs = false;
          }
        } else if (type === 'groupElements') {
          item.props.elementList.forEach(this.validateInputItem);
        } else {
          const hasPassedValidation = item.isEnabled ? deps_2.isValid(value, validationType) : true;

          if (hasPassedValidation === false) {
            /**
             * @todo @standard validationMessage
             */
            item.errorMessage = deps_2.errorMessage(errorMessageFor);
            item.isValidInput = false; // item.setIsValid(false)

            this.state.hasAllValidInputs = false;
            this.goToTop();
          } else {
            item.isValidInput = true;
          }
        }
      }
    };
    /**
     * @todo - using super when it's a bound fn may not work?
     * @listens onSubmit
     */


    this.goToTop = () => {
      let topOffset = 0;
      const element = document.getElementById('topHeader');

      if (element) {
        const headerOffset = element.offsetHeight / 2;
        const target = this.state.form && this.state.form.offsetTop;
        topOffset = target === 0 ? headerOffset : target - headerOffset;
        document.body.scrollTop = topOffset;
        document.documentElement.scrollTop = topOffset;
      } else {
        console.log('Cannot scroll to top as the header is not present');
      }
    };

    this.handleSubmit = event => {
      if (this.validateForm()) {
        const serialized = this.state.toSerialized();
        console.log('[form] valid & serialized: ', serialized);
        this.onSubmitValid(serialized);
        return serialized;
      } else {
        console.log('[form] Form has invalid inputs!');
        const serialized = {
          hasError: true
        };
        this.onSubmitError(serialized);
        return serialized;
      }
    };
    /**
     * @todo @name handleCancelClick
     * @deprecated should remove, not part of form at all
     */


    this.onCancelClick = event => {
      event.preventDefault();

      if (this.props.onHandleCancel) {
        this.props.onHandleCancel(this.props, this.props.cancelState);
      } else {
        this.handleCancel(event);
      }
    };

    this.renderInput = (item, index) => {
      const instantiated = this._toInput(item, index);

      const attributes = {};

      if (this.classList.input) {
        attributes.className = this.classList.input;
      }

      if (instantiated.isEnabled) {
        return react_1.default.createElement(this.Input, Object.assign({
          key: instantiated.name || instantiated.identifier || index,
          state: instantiated
        }, attributes, instantiated));
      } else {
        return '';
      }
    };
    /**
     * @private
     * @inheritdoc
     * @description compat
     *              so it returns the inputState
     *              will deprecate when not using .map
     */


    this._onPrefil = inputState => this.onPrefil(inputState) || inputState;

    this._onInputInit = (input, index) => {
      const inputState = this._toInput(input, index);

      this.onInputInit(inputState);
    };

    this._toInput = (input, index) => {
      return deps_3.isInputState(input) ? input : deps_3.toInputStateAt(this.state, index);
    }; // @caution


    this.classList = this.classList || {};
    this.state = props.state;

    if (!exotic_1.isSafe(this.state) || Object.keys(this.state).length <= 0) {
      console.warn('did not pass state prop - use defaultProps');
      this.state = new FormState_1.default(props);
    }

    if (exotic_1.isFunction(this.state.setProps)) {
      this.state.setProps(props);
    } else {
      console.warn('!!! FORM MISSING SETPROPS !!!');
    }
  }

  static from(list) {
    let inputList = list;

    if (exotic_1.isArray(list)) {
      inputList = {
        inputList: list
      };
    }

    const state = new FormState_1.default(inputList);
    return function FormFrom(props) {
      return react_1.default.createElement(ObserverForm_1, Object.assign({
        state: state
      }, props));
    };
  }
  /**
   * @todo - debounce
   */


  validateForm() {
    // @todo - should calling this.state.validate(), this.state.isValid()
    // Resetting the form validation state
    this.state.hasAllValidInputs = true;
    this.state.inputsList.forEach(this.validateInputItem);
    return this.state.hasAllValidInputs;
  }
  /**
   * @tutorial https://mobx.js.org/refguide/create-transformer.html
   * @description Lifecycle event hook
   * @listens onSubmit
   * @see handleSubmit
   */


  onSubmitValid(serialized) {} //

  /**
   * @description Lifecycle event hook
   * @listens onSubmit
   * @see handleSubmit
   */


  onSubmitError(serialized) {//
  }

  renderInputList() {
    // console.log('total list', this.state.inputList)
    // log('renderingInputList', {
    //   list: this.state.list,
    //   self: this,
    // })
    //
    // wonder if there is something amis with rehydrating it
    return this.state.inputsList.map(this.renderInput);
  }
  /**
   * @see componentWillMount
   * @listens componentWillMount
   * @event prefil
   */


  onPrefil(inputState) {//
  }

  onInputInit(input, index) {} //

  /**
   * @todo put prefil as action on state
   * @todo do a timeout loader
   *
   * !!!!!! changed from componentWillMount => componentDidMount
   *
   * @name onPrefil
   * @name prefilItem
   * @name prefilInputItem
   * @name prefilInput
   */


  componentDidMount() {
    console.debug('[forms] componentDidMount'); // don't want to assign to state

    let inputsList = this.state.inputsList; // this causes many issues?

    inputsList = inputsList.map(this._toInput); // call the action

    this.state.setInputsList(inputsList);

    if (exotic_1.isFunction(this.onPrefil)) {
      inputsList = inputsList.map(this._onPrefil);
      this.state.setInputsList(inputsList);
    }

    if (exotic_1.isFunction(this._onInputInit)) {
      inputsList.forEach(this._onInputInit);
    }
  }

  componentWillReceiveProps(prevProps, nextProps) {
    this.classList = deps_3.toClassList(this);
  }

  componentWillUnmount() {
    console.debug('[forms] componentWillUnmount');

    if (exotic_1.isTrue(this.shouldResetFormOnUnmount)) {
      this.state.inputsList.map(this.resetFormState);
    } // remove subscribers, make  backup
    // this.state.__INPUTS_LIST = JSON.stringify(this.inputsList, null, 2)
    // this.state.inputsList = []

  }
  /**
   * @todo this is FormState or InputStateTType?
   */


  resetFormState(inputState) {
    // To reset textbox
    if (inputState.type !== 'button' && inputState.type !== 'label' && inputState.type !== 'select') {
      inputState.setValue('');
      inputState.isValidInput = true;
    } // To reset groupElements


    if (inputState.elementList.length > 0) {
      inputState.elementList.forEach(inputElement => {
        if (inputElement.type !== 'button' && inputElement.type !== 'label' && inputState.type !== 'select') {
          inputElement.setValue('');
          inputElement.isValidInput = true;
        } else if (inputState.type === 'select') {
          inputState.setValue(inputState.label);
        }
      });
    }

    if (inputState.type === 'select') {
      inputState.setValue(inputState.label);
    } // To reset the 'show password' state


    if (inputState.name === 'password') {
      inputState.type = 'password';
    }
  }

  render() {
    const classList = deps_3.toClassList(this);
    const {
      isSubmitButtonNeeded,
      isCancelButtonNeeded,
      onSubmit,
      formId
    } = this; // @todo - this should be computed just once, at mount...

    const listView = this.renderInputList(); // has to be dom element to render ref to element

    return react_1.default.createElement(this.Form // data-is-valid={this.state.hasAllValidInputs}
    // isValid={this.state.hasAllValidInputs}
    , {
      "aria-invalid": this.state.hasAllValidInputs === false,
      setRef: this.state.setFormReference,
      className: classList.form,
      handleSubmit: onSubmit,
      formId: formId
    }, listView, react_1.default.createElement("div", {
      className: classList.buttonGroup
    }, isSubmitButtonNeeded && react_1.default.createElement(this.SubmitButton, {
      type: 'submit',
      className: classList.submitButton,
      onClick: this.handleSubmit,
      onSubmit: this.handleSubmit,
      "data-qa": this.submitDataQa
    }, this.defaultSubmitButtonLabel), isCancelButtonNeeded && react_1.default.createElement(this.CancelButton, {
      className: classList.cancelButton,
      onClick: this.onCancelClick,
      "data-qa": this.cancelDataQa
    }, this.defaultCancelButtonLabel)));
  }

};

tslib_1.__decorate([mobx_1.action.bound], ObserverForm.prototype, "validateForm", null);

tslib_1.__decorate([mobx_1.action.bound], ObserverForm.prototype, "resetFormState", null);

ObserverForm = ObserverForm_1 = tslib_1.__decorate([mobx_react_1.observer], ObserverForm);
exports.ObservableForm = ObserverForm;
exports.Form = ObserverForm;
exports.ObserverForm = ObserverForm;
exports.default = ObserverForm; //# sourceMappingURL=ObserverForm.js.map