diff --git a/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/Button.js b/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/Button.js new file mode 100644 index 0000000000000000000000000000000000000000..d11dd309036929a40de93cf2d60d38f72abe245b --- /dev/null +++ b/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/Button.js @@ -0,0 +1,89 @@ +import React from 'react'; +import styled, { css } from 'styled-components'; +import PropTypes from 'prop-types'; +import { Button as AntButton } from 'antd'; +import { omit } from 'lodash'; + +import { darken, lighten } from '@pubsweet/ui-toolkit'; + +const colors = { + danger: 'colorError', + error: 'colorError', + success: 'colorSuccess', + // warn: 'colorWarning', +}; + +const StyledButton = styled(AntButton)` + ${props => { + const { status, theme, type } = props; + if (!Object.keys(colors).includes(status)) return null; + const color = theme[colors[status]]; + + // primary + if (type === 'primary') + return css` + background-color: ${color}; + border-color: ${color}; + color: ${theme.colorTextReverse}; + + &:hover, + &:focus, + &:active { + border-color: ${color}; + color: ${theme.colorTextReverse}; + } + + &:hover, + &:focus { + background-color: ${lighten(color, 0.25)}; + } + + &:active { + background-color: ${darken(color, 0.25)}; + } + `; + + // non-primary + return css` + color: ${color}; + border-color: ${color}; + + &:hover, + &:focus { + color: ${lighten(color, 0.25)}; + border-color: ${lighten(color, 0.25)}; + } + + &:active { + color: ${darken(color, 0.25)}; + border-color: ${darken(color, 0.25)}; + } + `; + }} +`; +/** + * API is the same as https://ant.design/components/button/#API, except for the + * `danger` prop, which is ommited in favour of `status`, described below. + */ + +const Button = props => { + const { children, className, ...rest } = props; + const passProps = omit(rest, 'danger'); + + return ( + // eslint-disable-next-line react/jsx-props-no-spreading + <StyledButton className={className} {...passProps}> + {children} + </StyledButton> + ); +}; + +Button.propTypes = { + status: PropTypes.oneOf(['error', 'danger', 'success']), +}; + +Button.defaultProps = { + status: null, +}; + +export default Button; diff --git a/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/EditorComponent.js b/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/EditorComponent.js index 1359e83cccac04281b69160f52375ca98c8db886..e8c4dd509c916ed58c07179c19946692ceb06eb8 100644 --- a/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/EditorComponent.js +++ b/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/EditorComponent.js @@ -9,6 +9,36 @@ import { baseKeymap } from 'prosemirror-commands'; import { undo, redo } from 'prosemirror-history'; import { WaxContext } from 'wax-prosemirror-core'; +const EditorWrapper = styled.div` + border: none; + display: flex; + flex: 2 1 auto; + justify-content: left; + margin-right: 15px; + + .ProseMirror { + white-space: break-spaces; + width: 100%; + word-wrap: break-word; + + &:focus { + outline: none; + } + + p.empty-node:first-child::before { + content: attr(data-content); + } + + .empty-node::before { + color: rgb(170, 170, 170); + float: left; + font-style: italic; + height: 0px; + pointer-events: none; + } + } +`; + const EditorComponent = ({ node, view, getPos }) => { const editorRef = useRef(); @@ -109,7 +139,11 @@ const EditorComponent = ({ node, view, getPos }) => { }; }; - return <div ref={editorRef} />; + return ( + <EditorWrapper> + <div ref={editorRef} /> + </EditorWrapper> + ); }; export default EditorComponent; diff --git a/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/QuestionComponent.js b/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/QuestionComponent.js index b0904b6dd07dd25bd9880dc140d2a82b3d8b7f9d..651acb0b01d18c16844cbc75df7dcf4a0081add2 100644 --- a/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/QuestionComponent.js +++ b/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/QuestionComponent.js @@ -3,60 +3,76 @@ import React, { useContext, useRef, useState } from 'react'; import styled from 'styled-components'; import { TextSelection } from 'prosemirror-state'; import { WaxContext } from 'wax-prosemirror-core'; +import { PlusSquareOutlined, DeleteOutlined } from '@ant-design/icons'; + import EditorComponent from './EditorComponent'; import FeedbackComponent from './FeedbackComponent'; +import SwitchComponent from './SwitchComponent'; +import Button from './Button'; -const QuestionWrapper = styled.div` +const Wrapper = styled.div` display: flex; flex-direction: column; - &:before { - bottom: -20px; - content: 'Answer ' counter(question-item-multiple); - counter-increment: question-item-multiple; - position: relative; - } + width: 100%; `; -const QuestionWrapperInner = styled.div` - border: 1px solid #a5a1a2; - border-radius: 4px; +const InfoRow = styled.div` + color: black; display: flex; - flex-direction: column; - padding: 4px; + flex-direction: row; + padding: 10px 0px 4px 0px; `; -const CorrectLabel = styled.span` - margin-left: auto; +const QuestionNunber = styled.span``; + +const QuestionControlsWrapper = styled.div` + display: flex; + flex-direction: row; `; -const ChooseAnswer = styled.div` +const QuestionWrapper = styled.div` border: 1px solid #a5a1a2; border-radius: 4px; + color: black; display: flex; - flex-direction: row; - height: 25px; - margin-left: auto; - padding: 4px; - >div: first-of-type { - padding-right: 4px; - } + flex: 2 1 auto; + flex-direction: column; + padding: 10px; `; -const YesNoContainer = styled.div` - bottom: 3px; - color: #a5a1a2; - position: relative; +const IconsWrapper = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + + button { + border: none; + } + + span { + cursor: pointer; + } `; -const Question = styled.div` +const QuestionData = styled.div` + align-items: normal; display: flex; flex-direction: row; +`; - .ProseMirror { - background: #ebebf0; - padding: 5px; - width: 90%; - } +const FeedBack = styled.div` + color: black; + margin-top: 10px; +`; + +const FeedBackLabel = styled.span` + font-weight: 700; +`; + +const FeedBackInput = styled.input` + border: none; + display: flex; + width: 100%; `; export default ({ node, view, getPos }) => { @@ -66,11 +82,12 @@ export default ({ node, view, getPos }) => { } = context; const [showExplanation, setShowExplanation] = useState(false); - const [explanationValue, setExplanationValue] = useState(''); - const explanationRef = useRef(null); + const [feadBack, setFeedBack] = useState(''); + + const feedBackRef = useRef(null); const onChangeExplanationInput = () => { - setExplanationValue(explanationRef.current.value); + setFeedBack(feedBackRef.current.value); }; const clickMe = () => { @@ -99,30 +116,79 @@ export default ({ node, view, getPos }) => { const setNoYesValues = () => {}; + const addOption = () => {}; + + const questionNumber = 1; + const questionText = ''; + const readOnly = false; + const feedBackInput = ''; + const showAddIcon = true; + const showRemoveIcon = true; + return ( - <QuestionWrapper> - <CorrectLabel>Correct?</CorrectLabel> - <QuestionWrapperInner> - <Question> - <EditorComponent node={node} view={view} getPos={getPos} /> - <ChooseAnswer> - <YesNoContainer onClick={setNoYesValues}>No</YesNoContainer> - <YesNoContainer onClick={setNoYesValues}>Yes</YesNoContainer> - </ChooseAnswer> - </Question> - <button onClick={clickMe}>Show Explanation</button> - {showExplanation && ( - <input - type="text" - onKeyDown={handleKeyDown} - ref={explanationRef} - onChange={onChangeExplanationInput} - placeholder="type your explanation" - value={explanationValue} - ></input> - )} - <button onClick={removeOption}> X </button> - </QuestionWrapperInner> - </QuestionWrapper> + <Wrapper> + <InfoRow> + <QuestionNunber>Answer {questionNumber}</QuestionNunber> + </InfoRow> + <QuestionControlsWrapper> + <QuestionWrapper> + <QuestionData> + <EditorComponent node={node} view={view} getPos={getPos} /> + + <SwitchComponent /> + </QuestionData> + <FeedBack> + <FeedBackLabel>Feedback</FeedBackLabel> + <FeedBackInput + onChange={feedBackInput} + placeholder="Insert feedback" + ref={feedBackRef} + type="text" + value={feadBack} + /> + </FeedBack> + </QuestionWrapper> + <IconsWrapper> + {showAddIcon && !readOnly && ( + <Button + icon={ + <PlusSquareOutlined onClick={addOption} title="Add Option" /> + } + /> + )} + {showRemoveIcon && !readOnly && ( + <Button + icon={ + <DeleteOutlined onClick={removeOption} title="Delete Option" /> + } + /> + )} + </IconsWrapper> + </QuestionControlsWrapper> + </Wrapper> + + // <QuestionWrapper> + // <CorrectLabel>Correct?</CorrectLabel> + // <QuestionWrapperInner> + // <Question> + // <EditorComponent node={node} view={view} getPos={getPos} /> + // <ChooseAnswer> + // <SwitchComponent /> + // </ChooseAnswer> + // </Question> + // <button onClick={clickMe}>Show Explanation</button> + // {showExplanation && ( + // <input + // type="text" + // onKeyDown={handleKeyDown} + // ref={explanationRef} + // onChange={onChangeExplanationInput} + // placeholder="type your explanation" + // value={explanationValue} + // ></input> + // )} + // <button onClick={removeOption}> X </button> + // </QuestionWrapperInner> + // </QuestionWrapper> ); }; diff --git a/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/Switch.js b/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/Switch.js index 294ad2a305f5be79e4d4fa4502cb322dc9f18c44..6cad91dad18729472a4554e0c2fa2ce76f3f6d3c 100644 --- a/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/Switch.js +++ b/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/Switch.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import styled, { css } from 'styled-components'; import { Switch as AntSwitch } from 'antd'; -import { grid } from '@coko/client'; +import { grid } from '@pubsweet/ui-toolkit'; const Wrapper = styled.span``; diff --git a/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/SwitchComponent.js b/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/SwitchComponent.js index c3d4c88644a024b4590b212e4636213c032716c3..467fd62b00e46d77fc73cd8c02ca0096f96bdc07 100644 --- a/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/SwitchComponent.js +++ b/editors/demo/src/HHMI/MultipleChoiceQuestionService/components/SwitchComponent.js @@ -8,6 +8,7 @@ const StyledSwitch = styled(Switch)` span:nth-child(1) { bottom: 36px; + display: flex; left: 4px; position: relative; width: 0px; diff --git a/editors/demo/src/HHMI/layout/HhmiLayout.js b/editors/demo/src/HHMI/layout/HhmiLayout.js index fc036fddac106ba2bbe54740a10a5ce0e17676f8..0ea5183ac3b9c061b7ff91eecbd4d1af5f671ef5 100644 --- a/editors/demo/src/HHMI/layout/HhmiLayout.js +++ b/editors/demo/src/HHMI/layout/HhmiLayout.js @@ -3,6 +3,7 @@ import styled, { ThemeProvider } from 'styled-components'; import { WaxContext, ComponentPlugin } from 'wax-prosemirror-core'; import { grid, th } from '@pubsweet/ui-toolkit'; import { cokoTheme } from '../theme'; +import 'antd/dist/antd.css'; import EditorElements from './EditorElements'; /* Katex css */