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
138 lines (128 loc) • 4.06 kB
JavaScript
import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { sortableHandle, sortableElement } from 'react-sortable-hoc';
import IconTooltip from '../../badge-icon-tooltip';
import { isFirstOfNested } from '../helpers';
import SurveyEditorContext from '../context';
import Tag from './tag';
const INDENT_SIZE = 8;
const DragHandle = sortableHandle(() => <div className="grippy"></div>);
const Question = ({
question,
onSelect = () => {},
active = false,
level = null
}) => {
const { questions } = useContext(SurveyEditorContext);
const forks = (_.isArray(question.data) ? question.data : [])
.filter(answer => answer.jump != null)
.map(answer => {
const jumpTo = questions.find(question => question.id === answer.jump);
if (jumpTo != null) {
return (
<IconTooltip
key={jumpTo.tag}
icon="code-fork"
text={jumpTo.tag}
color="orange"
tooltip={`Jump to ${jumpTo.tag} if user selects "${answer.answer}"`}
/>
);
}
});
let warnings;
if (question.parent != null && isFirstOfNested(questions, question)) {
// find at least a question which jumps to this question, since it's nested
// it will never be reached in the survey, only check for the first of the group
// of nested questions
const hasJump = _(questions).chain()
.filter(question => question.type === 'multiple')
.map(question => _.isArray(question.data) ? question.data : [])
.flatten()
.some(answer => answer.jump === question.id)
.value();
if (!hasJump) {
warnings = (
<IconTooltip
icon="exclamation-triangle"
key="jump-warning"
color="red"
tooltip={`No conditional jump to this question.
This is a nested question and can only be reached in the survey with a conditional answer in a multiple choice question`}
/>
);
}
}
return (
<div className={classNames('ui-survey-question', { active })}>
{level != null && (
<div className="indent" style={{ flex: `0 0 ${INDENT_SIZE * level}px`}}/>
)}
<DragHandle />
<div className="content" onClick={e => {
e.preventDefault();
onSelect(question)
}}>
<div className="meta">
<Tag>{question.tag}</Tag>
<div className="icons">
{forks}
{warnings}
{question.type === 'multiple' && (
<IconTooltip
icon="list"
text={question.data.length}
tooltip="Multiple choice question"
/>
)}
{question.type === 'text' && (
<IconTooltip
icon="font"
tooltip="Free text question"
/>
)}
{question.type === 'number' && (
<IconTooltip
icon="percent"
tooltip="Numeric question"
/>
)}
{question.type === 'image' && (
<IconTooltip
icon="image"
tooltip="Image question"
/>
)}
</div>
</div>
<div className="title">
{question.title}
</div>
</div>
<div className="selection-bar">
</div>
</div>
);
};
Question.propTypes = {
question: PropTypes.shape({
id: PropTypes.string.isRequired,
level: PropTypes.number,
tag: PropTypes.string,
title: PropTypes.string.isRequired,
type: PropTypes.oneOf(['multiple', 'string', 'number', 'image']).isRequired,
data: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.shape({
answer: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
jump: PropTypes.string,
value: PropTypes.string
}))
])
}),
onSelect: PropTypes.func,
active: PropTypes.bool,
level: PropTypes.number
};
export default sortableElement(Question);