diff --git a/editors/demo/src/HHMI/HHMI.js b/editors/demo/src/HHMI/HHMI.js index e9f619292ce7185011a76da79d66bb050c4f31a4..c49a48477690b159694b12aeecc57c2a6cf250a8 100644 --- a/editors/demo/src/HHMI/HHMI.js +++ b/editors/demo/src/HHMI/HHMI.js @@ -29,7 +29,7 @@ const SubmitButton = styled.button` `; const t = `<p class="paragraph"></p></div><div id="d4fa43fc-3a92-4591-a8a4-e6271e42fc323" class="multiple-choice"><div class="multiple-choice-question" id="38de8538-647a-489d-8474-f92d0d256c32"><p class="paragraph">question</p></div><div class="multiple-choice-option" id="debb868e-bbfe-4ba2-bf93-c963153ff791" correct="false" answer="false" feedback="feedback 1"><p class="paragraph">answer 1</p></div><div class="multiple-choice-option" id="810bcf10-4fcb-4d1e-9dab-ce35cbd28527" correct="true" answer="true" feedback="feedback 2"><p class="paragraph">answer 2</p></div></div><div id="d4fa43fc-3a92-4591-a8a4-e6271e42fc02" class="fill-the-gap" feedback="some feedback"><p class="paragraph">first <span id="16ec8f33-db5b-4839-9567-8aa73b776bcf" class="fill-the-gap" answer="">answer1; answer2; answer3</span> second <span id="72f23a71-e774-4834-acba-f357afb6a243" class="fill-the-gap" answer="">answer 4; answer5;</span></p></div>`; -const aa = `<p class="paragraph"></p><div id="3166af11-2905-4426-afd6-620cc7044b3f" class="multiple-drop-down-container" feedback=""><p class="paragraph">etrt etre t<span id="306f1656-3319-4cb5-ab9a-53e28354501d" class="multiple-drop-down-option" options="[{"label":"ert eterter","value":"9a871b4b-a7bd-486c-a060-9665e59d89fa"},{"label":"etertrte","value":"5bd745c6-6bc9-40a8-8188-86590ceff7e3"},{"label":"eterter","value":"b4543396-d41f-4167-b9fd-a505d5d73715"}]"></span> </p></div>`; +const aa = `<p class="paragraph"></p><div id="3166af11-2905-4426-afd6-620cc7044b3f" class="multiple-drop-down-container" feedback="" correct="b4543396-d41f-4167-b9fd-a505d5d73715"><p class="paragraph">etrt etre t<span id="306f1656-3319-4cb5-ab9a-53e28354501d" class="multiple-drop-down-option" options="[{"label":"ert eterter","value":"9a871b4b-a7bd-486c-a060-9665e59d89fa"},{"label":"etertrte","value":"5bd745c6-6bc9-40a8-8188-86590ceff7e3"},{"label":"eterter","value":"b4543396-d41f-4167-b9fd-a505d5d73715"}]"></span> </p></div>`; const Hhmi = () => { const [submited, isSubmited] = useState(false); const [readOnly, isReadOnly] = useState(false); @@ -55,7 +55,7 @@ const Hhmi = () => { value={aa} readonly={readOnly} layout={HhmiLayout} - // onChange={source => console.log(source)} + onChange={source => console.log(source)} /> </> ); diff --git a/wax-prosemirror-services/src/MultipleDropDownService/components/DropDownComponent.js b/wax-prosemirror-services/src/MultipleDropDownService/components/DropDownComponent.js index 622e9b40aff5c696b7b293da43288575b6120456..6c1dc27ffab6c839871509efdbea82f986079102 100644 --- a/wax-prosemirror-services/src/MultipleDropDownService/components/DropDownComponent.js +++ b/wax-prosemirror-services/src/MultipleDropDownService/components/DropDownComponent.js @@ -11,6 +11,7 @@ import { v4 as uuidv4 } from 'uuid'; import styled from 'styled-components'; import { Icon } from 'wax-prosemirror-components'; import { NodeSelection } from 'prosemirror-state'; +import RadioButton from './RadioButton'; const TriangleTop = styled.div` width: 0; @@ -42,6 +43,7 @@ const Options = styled.div` const Option = styled.div` display: flex; flex-direction: row; + width: 96%; `; const AddOption = styled.div` @@ -84,10 +86,10 @@ const AddOption = styled.div` const IconRemove = styled(Icon)` cursor: pointer; position: relative; - top: 4px; + top: 2px; left: 6px; - height: 10px; - width: 10px; + height: 16px; + width: 16px; `; let previousNode = ''; @@ -171,40 +173,44 @@ export default ({ setPosition, position }) => { setOptionText(''); }; - return ( - <> - <TriangleTop /> - <DropDownComponent> - <Options> - {options.map(value => { - return ( - <Option key={uuidv4()}> - <span>{value.label}</span> - <span - aria-hidden="true" - onClick={() => removeOption(value.value)} - role="button" - > - <IconRemove name="removeTag" /> - </span> - </Option> - ); - })} - </Options> - <AddOption> - <input - onChange={updateOptionText} - onKeyPress={handleKeyDown} - placeholder="Type an option and press enter..." - ref={addOptionRef} - type="text" - value={optionText} - /> - {/* <button onMouseUp={addOption} type="button"> + if (!readOnly) { + return ( + <> + <TriangleTop /> + <DropDownComponent> + <Options> + {options.map(value => { + return ( + <Option key={uuidv4()}> + <RadioButton item={value} node={currentNode} /> + <span + aria-hidden="true" + onClick={() => removeOption(value.value)} + role="button" + style={{ marginLeft: 'auto' }} + > + <IconRemove name="deleteOutlined" /> + </span> + </Option> + ); + })} + </Options> + <AddOption> + <input + onChange={updateOptionText} + onKeyPress={handleKeyDown} + placeholder="Type an option and press enter..." + ref={addOptionRef} + type="text" + value={optionText} + /> + {/* <button onMouseUp={addOption} type="button"> Add </button> */} - </AddOption> - </DropDownComponent> - </> - ); + </AddOption> + </DropDownComponent> + </> + ); + } + return null; }; diff --git a/wax-prosemirror-services/src/MultipleDropDownService/components/MultipleDropDownComponent.js b/wax-prosemirror-services/src/MultipleDropDownService/components/MultipleDropDownComponent.js index 99bb3c0ae44281518a33ebaca5e13497fe571db3..90f95347301154dcd9603f751a52f2d62b35c939 100644 --- a/wax-prosemirror-services/src/MultipleDropDownService/components/MultipleDropDownComponent.js +++ b/wax-prosemirror-services/src/MultipleDropDownService/components/MultipleDropDownComponent.js @@ -3,6 +3,7 @@ import React, { useContext, useEffect, useState } from 'react'; import { WaxContext } from 'wax-prosemirror-core'; import { Icon } from 'wax-prosemirror-components'; import styled, { css } from 'styled-components'; +import ReadOnlyDropDown from './ReadOnlyDropDown'; const activeStylesContainer = css` background: #535e76; @@ -51,9 +52,12 @@ export default ({ node, view, getPos }) => { } }, [posFrom]); - return ( - <StyledIconActionContainer isActive={isActive}> - <StyledIconAction isActive={isActive} name="mulitpleDropDown" /> - </StyledIconActionContainer> - ); + if (!(readOnly && customProps && !customProps.showFeedBack)) { + return ( + <StyledIconActionContainer isActive={isActive}> + <StyledIconAction isActive={isActive} name="mulitpleDropDown" /> + </StyledIconActionContainer> + ); + } + return <ReadOnlyDropDown options={node.attrs.options} />; }; diff --git a/wax-prosemirror-services/src/MultipleDropDownService/components/RadioButton.js b/wax-prosemirror-services/src/MultipleDropDownService/components/RadioButton.js new file mode 100644 index 0000000000000000000000000000000000000000..3adb5055a3e598eef972c8e39b81072527451864 --- /dev/null +++ b/wax-prosemirror-services/src/MultipleDropDownService/components/RadioButton.js @@ -0,0 +1,93 @@ +/* eslint-disable react/prop-types */ +import React, { useContext, useEffect, useState } from 'react'; +import { WaxContext } from 'wax-prosemirror-core'; +import { NodeSelection } from 'prosemirror-state'; +import styled from 'styled-components'; + +const CheckContainer = styled.label` + display: block; + position: relative; + padding-left: 20px; + margin-bottom: 5px; + cursor: pointer; + user-select: none; + + input { + position: absolute; + opacity: 0; + cursor: pointer; + height: 0; + width: 0; + } + + &:hover input ~ span { + background-color: #ccc; + } + + input:checked ~ span { + background-color: #535e76; + } + + input:checked ~ .span:after { + display: block; + } + + span:after { + top: 9px; + left: 9px; + width: 8px; + height: 8px; + border-radius: 50%; + background: white; + } +`; + +const RadioBtn = styled.span` + position: absolute; + top: 0; + left: 0; + height: 15px; + width: 15px; + background-color: #eee; + border-radius: 50%; + + &:after { + content: ''; + position: absolute; + display: none; + } +`; + +export default ({ item, node }) => { + const context = useContext(WaxContext); + const { activeView } = context; + const [correctOption, setCorrectOption] = useState(node.node.attrs.correct); + + const onChange = () => { + const { tr } = activeView.state; + tr.setNodeMarkup(node.from, undefined, { + ...node.node.attrs, + correct: item.value, + }); + const resolvedPos = tr.doc.resolve(node.from); + tr.setSelection(new NodeSelection(resolvedPos)); + activeView.dispatch(tr.setMeta('reject', true)); + }; + + useEffect(() => { + setCorrectOption(item.value); + }, [correctOption]); + + return ( + <CheckContainer> + {item.label} + <input + checked={correctOption === item.value} + name="radio" + onChange={onChange} + type="radio" + /> + <RadioBtn /> + </CheckContainer> + ); +}; diff --git a/wax-prosemirror-services/src/MultipleDropDownService/components/ReadOnlyDropDown.js b/wax-prosemirror-services/src/MultipleDropDownService/components/ReadOnlyDropDown.js new file mode 100644 index 0000000000000000000000000000000000000000..8638a53c73fe07f90c6fba82ace407626544c8ad --- /dev/null +++ b/wax-prosemirror-services/src/MultipleDropDownService/components/ReadOnlyDropDown.js @@ -0,0 +1,78 @@ +/* eslint-disable no-underscore-dangle */ +import React, { useContext, useMemo, useEffect, useState } from 'react'; +import styled from 'styled-components'; +import { find } from 'lodash'; +import { ReactDropDownStyles } from 'wax-prosemirror-components'; +import { WaxContext } from 'wax-prosemirror-core'; +import { DocumentHelpers } from 'wax-prosemirror-utilities'; +import Dropdown from 'react-dropdown'; +import { v4 as uuidv4 } from 'uuid'; + +const Wrapper = styled.div` + display: inline-flex; + ${ReactDropDownStyles}; +`; +const DropdownStyled = styled(Dropdown)` + display: inline-flex; + cursor: not-allowed; + margin-left: auto; + opacity: ${props => (props.select ? 1 : 0.4)}; + pointer-events: ${props => (props.select ? 'default' : 'none')}; + .Dropdown-control { + // border: none; + padding: 8px 30px 8px 10px; + + &:hover { + box-shadow: none; + } + } + + .Dropdown-arrow { + top: 17px; + } + + .Dropdown-menu { + width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + .Dropdown-option { + width: 100%; + } + } +`; + +const DropComponent = ({ options }) => { + const [selectedOption, setSelectedOption] = useState(undefined); + + const context = useContext(WaxContext); + const { + pmViews: { main }, + } = context; + + const onChange = option => {}; + + useEffect(() => {}, []); + + const MultipleDropDown = useMemo( + () => ( + <Wrapper key={uuidv4()}> + <DropdownStyled + key={uuidv4()} + onChange={option => onChange(option)} + options={options} + placeholder="Select option" + select + value={ + selectedOption === 'undedfined' ? 'Select Option' : selectedOption + } + /> + </Wrapper> + ), + [selectedOption], + ); + + return MultipleDropDown; +}; + +export default DropComponent; diff --git a/wax-prosemirror-services/src/MultipleDropDownService/schema/multipleDropDownOptionNode.js b/wax-prosemirror-services/src/MultipleDropDownService/schema/multipleDropDownOptionNode.js index d1abebe3b56dff1cc076ff12d05f2577c557a312..9c63e91882c42c092b40c2054d0f3b305737d8c0 100644 --- a/wax-prosemirror-services/src/MultipleDropDownService/schema/multipleDropDownOptionNode.js +++ b/wax-prosemirror-services/src/MultipleDropDownService/schema/multipleDropDownOptionNode.js @@ -3,6 +3,7 @@ const multipleDropDownOptionNode = { class: { default: 'multiple-drop-down-option' }, id: { default: '' }, options: { default: [] }, + correct: { default: '' }, }, group: 'inline questions', content: 'text*', @@ -17,6 +18,7 @@ const multipleDropDownOptionNode = { id: dom.getAttribute('id'), class: dom.getAttribute('class'), options: JSON.parse(dom.getAttribute('options')), + correct: dom.getAttribute('correct'), }; }, }, @@ -28,6 +30,7 @@ const multipleDropDownOptionNode = { id: node.attrs.id, class: node.attrs.class, options: JSON.stringify(node.attrs.options), + correct: node.attrs.correct, }, 0, ];