@e-group/material-module
Version:
EGroup Team react component modules.
454 lines (419 loc) • 14.1 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
import React, { useState, useEffect } from 'react';
import isLength from 'validator/lib/isLength';
import clsx from 'clsx';
import useInputActions from '@e-group/hooks/useInputActions';
import { makeStyles } from '@material-ui/core';
import Tooltip from '@material-ui/core/Tooltip';
import Paper from '@material-ui/core/Paper';
import Grid from '@material-ui/core/Grid';
import Typography from '@material-ui/core/Typography';
import MenuItem from '@material-ui/core/MenuItem';
import Divider from '@material-ui/core/Divider';
import InputAdornment from '@material-ui/core/InputAdornment';
import IconButton from '@material-ui/core/IconButton';
import TextField from '@e-group/material/TextField';
import Icomoon from '@e-group/material/Icomoon';
import Switch from '@e-group/material/Switch';
import TitleIcon from '@material-ui/icons/Title';
import ShortTextIcon from '@material-ui/icons/ShortText';
import SubjectIcon from '@material-ui/icons/Subject';
import RadioButtonCheckedIcon from '@material-ui/icons/RadioButtonChecked';
import CheckboxIcon from '@material-ui/icons/CheckBox';
import ArrowDropDownCircleIcon from '@material-ui/icons/ArrowDropDownCircle';
import LinearScaleIcon from '@material-ui/icons/LinearScale';
import InsertInvitationIcon from '@material-ui/icons/InsertInvitation';
import EmailIcon from '@material-ui/icons/Email';
import QuestionOptionsEditable from '../QuestionOptionsEditable';
import QuestionRatingEditable from '../QuestionRatingEditable';
import QuestionDragHandle from '../QuestionDragHandle';
const useStyles = makeStyles(theme => ({
root: {
margin: theme.spacing(1.5, 0),
boxShadow: theme.egShadows[3],
border: "1px solid #e3e6f0",
borderRadius: "0.35rem",
position: 'relative',
overflow: 'hidden'
},
active: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
width: 6,
backgroundColor: theme.egPalette.info[1]
},
main: {
padding: theme.spacing(0, 3)
},
content: {
marginBottom: theme.spacing(4)
},
actions: {
padding: theme.spacing(1, 0),
display: 'flex',
justifyContent: 'flex-end',
alignItems: 'center'
},
select: {
paddingTop: theme.spacing(2),
paddingBottom: theme.spacing(2),
lineHeight: "".concat(theme.spacing(3), "px")
},
menuItem: {
padding: theme.spacing(1, 2),
'& .MuiTypography-root': {
lineHeight: "".concat(theme.spacing(4), "px"),
minWidth: theme.spacing(17)
}
},
option: {
display: 'flex',
alignItems: 'center'
},
icon: {
marginRight: theme.spacing(2)
},
divider: {
margin: theme.spacing(1, 0)
},
text: {
width: '50%',
marginBottom: theme.spacing(2)
},
textarea: {
width: '85%',
marginBottom: theme.spacing(2)
},
vertical: {
margin: theme.spacing(0, 2),
height: theme.spacing(4)
},
switch: {
margin: 0
}
}));
const MAX_NAME = 50;
const MAX_DESC = 100;
const optionMap = {
titleBlock: {
name: '標題區塊',
icon: TitleIcon
},
text: {
name: '簡答',
icon: ShortTextIcon
},
textarea: {
name: '段落',
icon: SubjectIcon
},
choiceone: {
name: '選擇題',
icon: RadioButtonCheckedIcon
},
choicemulti: {
name: '核取方塊',
icon: CheckboxIcon
},
select: {
name: '下拉式選單',
icon: ArrowDropDownCircleIcon
},
rating: {
name: '線性刻度',
icon: LinearScaleIcon
},
date: {
name: '日期',
icon: InsertInvitationIcon
},
email: {
name: '電子郵件',
icon: EmailIcon
}
};
const QuestionEditable = (_ref) => {
let question = _ref.question,
className = _ref.className,
DragHandleProps = _ref.DragHandleProps,
_ref$optionTypes = _ref.optionTypes,
optionTypes = _ref$optionTypes === void 0 ? ['titleBlock', '|', 'text', 'textarea', '|', 'choiceone', 'choicemulti', 'select', '|', 'rating', '|', 'date', '|', 'email'] : _ref$optionTypes,
autoFocusOptionIndex = _ref.autoFocusOptionIndex,
autoFocusName = _ref.autoFocusName,
onDescChange = _ref.onDescChange,
onNameChange = _ref.onNameChange,
onNameClick = _ref.onNameClick,
onTypeChange = _ref.onTypeChange,
onRequiredChange = _ref.onRequiredChange,
onDelete = _ref.onDelete,
onOptionChange = _ref.onOptionChange,
onOptionDelete = _ref.onOptionDelete,
onOptionDragEnd = _ref.onOptionDragEnd,
onOptionCreate = _ref.onOptionCreate,
onOptionCreateOther = _ref.onOptionCreateOther,
onRatingStartChange = _ref.onRatingStartChange,
onRatingEndChange = _ref.onRatingEndChange,
onRatingStartInputChange = _ref.onRatingStartInputChange,
onRatingEndInputChange = _ref.onRatingEndInputChange,
other = _objectWithoutProperties(_ref, ["question", "className", "DragHandleProps", "optionTypes", "autoFocusOptionIndex", "autoFocusName", "onDescChange", "onNameChange", "onNameClick", "onTypeChange", "onRequiredChange", "onDelete", "onOptionChange", "onOptionDelete", "onOptionDragEnd", "onOptionCreate", "onOptionCreateOther", "onRatingStartChange", "onRatingEndChange", "onRatingStartInputChange", "onRatingEndInputChange"]);
const classes = useStyles();
const _useState = useState(question.questionName),
_useState2 = _slicedToArray(_useState, 2),
name = _useState2[0],
setName = _useState2[1];
const _useState3 = useState(question.questionType),
_useState4 = _slicedToArray(_useState3, 2),
type = _useState4[0],
setType = _useState4[1];
const _useState5 = useState(question.questionDescription),
_useState6 = _slicedToArray(_useState5, 2),
desc = _useState6[0],
setDesc = _useState6[1];
const _useState7 = useState(Boolean(question.isRequired)),
_useState8 = _slicedToArray(_useState7, 2),
isRequired = _useState8[0],
setIsRequired = _useState8[1];
const _useInputActions = useInputActions(),
inputEl = _useInputActions.inputEl,
select = _useInputActions.select;
const isNameError = !isLength(name || '', {
min: 0,
max: MAX_NAME
});
const isDescError = !isLength(desc || '', {
min: 0,
max: MAX_DESC
});
useEffect(() => {
if (autoFocusName) {
select();
} // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const handleNameChange = e => {
setName(e.target.value);
if (onNameChange && isLength(e.target.value, {
min: 0,
max: MAX_NAME
})) {
onNameChange(e, question);
}
};
const handleNameClick = e => {
if (onNameClick) {
onNameClick(e, question);
}
};
const handleDescChange = e => {
setDesc(e.target.value);
if (onDescChange && isLength(e.target.value, {
min: 0,
max: MAX_DESC
})) {
onDescChange(e, question);
}
};
const handleTypeChange = e => {
setType(e.target.value);
if (onTypeChange) {
onTypeChange(e, question);
}
};
const handleIsRequiredChange = (e, checked) => {
setIsRequired(checked);
if (onRequiredChange) {
onRequiredChange(e, question);
}
};
const handleDelete = e => {
if (onDelete) {
onDelete(e, question);
}
};
const getNameLabel = () => {
if (type === 'titleBlock') return '標題';
return '問題';
};
const renderContent = () => {
switch (type) {
case 'titleBlock':
return /*#__PURE__*/React.createElement(TextField, {
className: classes.textarea,
label: "\u5340\u584A\u63CF\u8FF0",
multiline: true,
value: desc,
onChange: handleDescChange,
error: isDescError,
helperText: isDescError ? "\u5340\u584A\u63CF\u8FF0\u8ACB\u52FF\u8D85\u904E ".concat(MAX_DESC, " \u500B\u5B57\u5143") : undefined
});
case 'text':
return /*#__PURE__*/React.createElement(TextField, {
className: classes.text,
label: "\u7C21\u7B54\u6587\u5B57",
disabled: true
});
case 'textarea':
return /*#__PURE__*/React.createElement(TextField, {
className: classes.textarea,
label: "\u8A73\u7B54\u6587\u5B57",
disabled: true
});
case 'choiceone':
return /*#__PURE__*/React.createElement(QuestionOptionsEditable, {
type: "radio",
onChange: onOptionChange,
onCreate: onOptionCreate,
onCreateOther: onOptionCreateOther,
onDelete: onOptionDelete,
onDragEnd: onOptionDragEnd,
question: question,
autoFocusIndex: autoFocusOptionIndex
});
case 'choicemulti':
return /*#__PURE__*/React.createElement(QuestionOptionsEditable, {
type: "checkbox",
onChange: onOptionChange,
onCreate: onOptionCreate,
onCreateOther: onOptionCreateOther,
onDelete: onOptionDelete,
onDragEnd: onOptionDragEnd,
question: question,
autoFocusIndex: autoFocusOptionIndex
});
case 'select':
return /*#__PURE__*/React.createElement(QuestionOptionsEditable, {
type: "select",
onChange: onOptionChange,
onCreate: onOptionCreate,
onCreateOther: onOptionCreateOther,
onDelete: onOptionDelete,
onDragEnd: onOptionDragEnd,
question: question,
autoFocusIndex: autoFocusOptionIndex
});
case 'rating':
return /*#__PURE__*/React.createElement(QuestionRatingEditable, {
question: question,
onStartChange: onRatingStartChange,
onEndChange: onRatingEndChange,
onStartInputChange: onRatingStartInputChange,
onEndInputChange: onRatingEndInputChange
});
case 'email':
return /*#__PURE__*/React.createElement(TextField, {
className: classes.text,
label: "\u96FB\u5B50\u90F5\u4EF6",
disabled: true
});
case 'date':
return /*#__PURE__*/React.createElement(TextField, {
className: classes.text,
label: "\u5E74/\u6708/\u65E5",
disabled: true,
InputProps: {
endAdornment: /*#__PURE__*/React.createElement(InputAdornment, {
position: "end"
}, /*#__PURE__*/React.createElement(InsertInvitationIcon, null))
}
});
default:
return undefined;
}
};
return /*#__PURE__*/React.createElement(Paper, _extends({
className: clsx(className, classes.root)
}, other), /*#__PURE__*/React.createElement(QuestionDragHandle, {
DragHandleProps: DragHandleProps
}), /*#__PURE__*/React.createElement("div", {
className: classes.active
}), /*#__PURE__*/React.createElement("div", {
className: classes.main
}, /*#__PURE__*/React.createElement(Grid, {
className: classes.content,
container: true,
spacing: 1,
alignItems: "flex-start"
}, /*#__PURE__*/React.createElement(Grid, {
item: true,
xs: 12,
sm: 9
}, /*#__PURE__*/React.createElement(TextField, {
inputRef: inputEl,
multiline: true,
autoFocus: autoFocusName,
onChange: handleNameChange,
onClick: handleNameClick,
fullWidth: true,
value: name,
label: getNameLabel(),
error: isNameError,
helperText: isNameError ? "".concat(getNameLabel(), "\u8ACB\u52FF\u8D85\u904E ").concat(MAX_NAME, " \u500B\u5B57\u5143") : undefined
})), /*#__PURE__*/React.createElement(Grid, {
item: true,
xs: 12,
sm: 3
}, /*#__PURE__*/React.createElement(TextField, {
SelectProps: {
classes: {
root: classes.select
}
},
fullWidth: true,
select: true,
variant: "outlined",
rounded: true,
value: type,
onChange: handleTypeChange
}, optionTypes.map((type, index) => {
var _optionMap$type$icon, _optionMap$type, _optionMap$type2;
if (type === '|') {
// eslint-disable-next-line react/no-array-index-key
return /*#__PURE__*/React.createElement(Divider, {
key: index,
className: classes.divider
});
}
if (!optionMap[type]) {
return undefined;
}
const OptionIcon = (_optionMap$type$icon = (_optionMap$type = optionMap[type]) === null || _optionMap$type === void 0 ? void 0 : _optionMap$type.icon) !== null && _optionMap$type$icon !== void 0 ? _optionMap$type$icon : 'div';
return /*#__PURE__*/React.createElement(MenuItem // eslint-disable-next-line react/no-array-index-key
, {
key: index,
className: classes.menuItem,
value: type
}, /*#__PURE__*/React.createElement("div", {
className: classes.option
}, /*#__PURE__*/React.createElement(OptionIcon, {
className: classes.icon
}), /*#__PURE__*/React.createElement(Typography, {
variant: "body2",
display: "inline"
}, (_optionMap$type2 = optionMap[type]) === null || _optionMap$type2 === void 0 ? void 0 : _optionMap$type2.name)));
}))), /*#__PURE__*/React.createElement(Grid, {
item: true,
xs: 12
}, renderContent())), /*#__PURE__*/React.createElement(Divider, null), /*#__PURE__*/React.createElement("div", {
className: classes.actions
}, /*#__PURE__*/React.createElement(Tooltip, {
title: "\u522A\u9664"
}, /*#__PURE__*/React.createElement(IconButton, {
onClick: handleDelete
}, /*#__PURE__*/React.createElement(Icomoon, {
type: "delete_1",
fontSize: "large"
}))), type !== 'titleBlock' && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Divider, {
className: classes.vertical,
orientation: "vertical"
}), /*#__PURE__*/React.createElement(Switch, {
className: classes.switch,
checked: isRequired,
onChange: handleIsRequiredChange,
labelPlacement: "start",
label: "\u5FC5\u586B"
})))));
};
export default QuestionEditable;