UNPKG

node-red-contrib-chatbot

Version:

REDBot a Chat bot for a full featured chat bot for Telegram, Facebook Messenger and Slack. Almost no coding skills required

108 lines (98 loc) 3.75 kB
import React, { useState, Fragment, useContext, useReducer, useCallback } from 'react'; import _ from 'lodash'; import reducer from './reducer'; import ModalWrapper from './model-wrapper'; const isValid = validation => Object.values(validation).every(item => !item.hasError); const ModalContext = React.createContext({}); /** * useModal * @param {Object} props * @param {React.View} props.view * @param {String} props.align Alignment of the buttons: left, center, right * @param {String} props.title Title of the modal * @param {String} props.labelSubmit Submit button * @param {String} props.labelCancel Cancel button * @param {String} props.className * @param {String} props.size Size of the modal * @param {React} props.custom Custom view, additional button in the footer * @param {String} props.enableSummit Enable or disable the submit button, takes as argument the current value of the form * @return {Object} * @return {Function} return.open Open the modal setting the initial state of the modal * * @return {Function} return.update Update the internal state of the modal and wait * @return {Function} return.validate Set the validation info for the form * @return {Function} return.error Set the server side error for the form */ const useModal = props => { const context = useContext(ModalContext); const { dispatch } = context; const [id] = useState(_.uniqueId('modal_')); const open = useCallback((modalProps, params) => { return new Promise(resolve => dispatch({ type: 'appendView', id, resolve, initialValue: modalProps, ...props, ...params })) }); const validate = useCallback(validation => dispatch({ type: 'mergeModalProps', id, props: { validation } })); const close = useCallback(() => dispatch({ type: 'removeView', id })); const disable = useCallback(() => dispatch({ type: 'mergeModalProps', id, props: { disabled: true } })); const enable = useCallback(() => dispatch({ type: 'mergeModalProps', id, props: { disabled: false } })); const error = useCallback(error => dispatch({ type: 'mergeModalProps', id, props: { error } })); const update = useCallback(value => { return new Promise(resolve => dispatch({ type: 'appendView', id, resolve, updateValue: value })) }); const openWith = useCallback(async (modalProps, enableSubmit) => { let result = await open(modalProps, { enableSubmit }); close(); return result; }); const openWithModel = useCallback(async (modalProps, model) => { let validation = null; let value = { ...modalProps }; do { value = await open(value); if (value != null) { validation = model.check(value); if (!isValid(validation)) { // translate validation object const errors = {}; Object.keys(validation) .forEach(field => { if (validation[field].hasError) { errors[field] = validation[field].errorMessage; } }) validate(errors); } else { validate(null); } } } while (value != null && !isValid(validation)); close(); return value; }); return { open, close, error, validate, disable, enable, openWith, openWithModel, update }; }; const ModalProvider = ({ children }) => { const [state, dispatch] = useReducer(reducer, { modals: [] }); const { modals } = state; return ( <ModalContext.Provider value={{ dispatch, }}> {!_.isEmpty(modals) && ( <Fragment> {modals.map(({ id, view, props }) => <ModalWrapper view={view} key={id} {...props} />)} </Fragment> )} {children} </ModalContext.Provider> ); }; export { ModalProvider, useModal };