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

149 lines (131 loc) 4.94 kB
import React, { useState, Fragment } from 'react'; import _ from 'lodash'; import { FormGroup, ControlLabel as RawControlLabel, HelpBlock as RawHelpBlock, Input, InputNumber, SelectPicker, Toggle, PanelGroup, Panel, Icon } from 'rsuite'; import classNames from 'classnames'; import Controller from '../controller'; import isValidDate from '../../../../src/helpers/is-valid-date'; import useControl from '../helpers/use-control'; import matchPath from '../helpers/match-path'; import ControlLabel from '../views/control-label'; import HelpBlock from '../views/help-block'; import ErrorBlock from '../views/error-block'; const makeKey = (name, jsonSchema) => { if (!_.isEmpty(jsonSchema['$id'])) { return jsonSchema['$id']; } else if (!_.isEmpty(jsonSchema.id)) { return jsonSchema.id; } else { return `${name}-${jsonSchema.type}`; } } const ObjectControl = props => { const { jsonSchema, level, value = {}, onChange, currentPath } = props; const { permissions, canRead, canWrite, log, error, path, hideTitles } = useControl(props); if (!canRead) { log('is hidden, no read permission'); return <div />; } const isAdmin = permissions.includes('*'); let requireds = jsonSchema.required || []; const options = jsonSchema.options || {}; let properties = jsonSchema.properties; const { layout = 'vertical' } = options; // add all required field from dependencies Object.entries(jsonSchema.dependencies || {}) .forEach(([field, fields]) => { // if the key of the dependencies is present if (value[field] != null && value[field] !== '') { // if it's an array, just add the fields to the requireds array, if it's an object // then merge properties and requireds array (that allows some fields to appear in some conditions) if (_.isArray(fields)) { requireds = _.uniq([...requireds, ...fields]); } else { requireds = _.uniq([...requireds, ...fields.required]); properties = { ...properties, ...fields.properties }; } } }); if (!canWrite) { log(`whole object and children are read only, no write permission, available permissions %c"${permissions.join(',')}"`) } const { collapsed = false } = options; const items = Object.entries(properties) .filter(([field, schema]) => { const { options = { }} = schema; // filter out elements without view permission const canRead = isAdmin || _.isEmpty(options.readPermission) || permissions.includes(options.readPermission); if (!canRead) { log(`hidden field %c"${field}"%c, no read permission`); } return canRead; }) .map(([field, schema]) => { // return an empty element if current path doesn't match allowed paths const controllerPath = `${currentPath}/${field}`; if (!matchPath(controllerPath, path)) { return <Fragment />; } let fieldError; if (error && !_.isEmpty(error.errors)) { fieldError = error.errors.find(error => error.id === schema['$id']); } const controller = ( <Controller field={field} currentPath={controllerPath} jsonSchema={options.layout === 'accordion' || options.layout === 'panel' ? _.omit(schema, 'title') : schema} value={value[field]} key={makeKey(field, schema)} level={level + 1} required={requireds.includes(field)} readOnly={!canWrite ? true : undefined} error={fieldError} onChange={newValue => { onChange({ ...value, [field]: newValue }); }} /> ); // wrap into panel if layout and if title of the forms are not hidden (when using path to show only a portion of // the form, it doesn't always make sense to show all the titles) if (['accordion','panel'].includes(layout) && !hideTitles) { return ( <Panel key={makeKey(field, schema)} header={!_.isEmpty(schema.title) ? schema.title : 'No title'} collapsible defaultExpanded={!collapsed}> {controller} </Panel> ) } else { return controller; } }); if (['accordion','panel'].includes(layout) && !hideTitles) { return ( <Fragment> {!_.isEmpty(jsonSchema.title) && <div className={classNames('title', { [`title-${level}`]: true })}>{jsonSchema.title}</div>} <PanelGroup accordion={layout === 'accordion'} defaultActiveKey={1}> {items} </PanelGroup> </Fragment> ) } else { return ( <div className={classNames('rs-form rs-form-vertical rs-form-fluid', { [layout]: true })}> {!_.isEmpty(jsonSchema.title) && !hideTitles && ( <div className={classNames('title', { [`title-${level}`]: true })}>{jsonSchema.title}</div> )} {items} </div> ); } } export default ObjectControl;