From f42df241e60afd6831a74378964a639e34db0bfe Mon Sep 17 00:00:00 2001 From: chris <kokosias@yahoo.gr> Date: Wed, 30 Mar 2022 00:19:03 +0300 Subject: [PATCH] ui in progress --- .../components/ContainerEditor.js | 85 ++++++++++++++++++ .../components/ContainerEditor.js | 8 +- .../components/DropDownComponent.js | 89 +++++++++++++++++++ .../components/EditorComponent.js | 5 +- .../components/FeedbackComponent.js | 3 +- .../components/MatchingContainerComponent.js | 75 ++++++++-------- .../schema/matchingContainerNode.js | 2 + 7 files changed, 227 insertions(+), 40 deletions(-) create mode 100644 wax-prosemirror-services/src/EssayService/components/ContainerEditor.js create mode 100644 wax-prosemirror-services/src/MatchingService/components/DropDownComponent.js diff --git a/wax-prosemirror-services/src/EssayService/components/ContainerEditor.js b/wax-prosemirror-services/src/EssayService/components/ContainerEditor.js new file mode 100644 index 000000000..273c90844 --- /dev/null +++ b/wax-prosemirror-services/src/EssayService/components/ContainerEditor.js @@ -0,0 +1,85 @@ +/* eslint-disable react/prop-types */ + +import React, { useContext, useRef, useEffect } from 'react'; +import styled from 'styled-components'; +import { EditorView } from 'prosemirror-view'; +import { EditorState } from 'prosemirror-state'; +import { StepMap } from 'prosemirror-transform'; +import { WaxContext } from 'wax-prosemirror-core'; + +const EditorWrapper = styled.div` + > .ProseMirror { + padding: 0px; + &:focus { + outline: none; + } + } +`; + +const ContainerEditor = ({ node, view, getPos, isEditable, autoFocus }) => { + const editorRef = useRef(); + + const context = useContext(WaxContext); + const { app } = context; + + let containerView; + const questionId = node.attrs.id; + + useEffect(() => { + containerView = new EditorView( + { + mount: editorRef.current, + }, + { + editable: () => false, + state: EditorState.create({ + doc: node, + plugins: [...app.getPlugins()], + }), + dispatchTransaction, + disallowedTools: [ + 'Images', + 'Lists', + 'lift', + 'Tables', + 'FillTheGap', + 'MultipleChoice', + ], + }, + ); + + // Set Each note into Wax's Context + context.updateView( + { + [questionId]: containerView, + }, + questionId, + ); + }, []); + + const dispatchTransaction = tr => { + const { state, transactions } = containerView.state.applyTransaction(tr); + containerView.updateState(state); + context.updateView({}, questionId); + + if (!tr.getMeta('fromOutside')) { + const outerTr = view.state.tr; + const offsetMap = StepMap.offset(getPos() + 1); + for (let i = 0; i < transactions.length; i++) { + const { steps } = transactions[i]; + for (let j = 0; j < steps.length; j++) + outerTr.step(steps[j].map(offsetMap)); + } + if (outerTr.docChanged) + view.dispatch(outerTr.setMeta('outsideView', questionId)); + } + }; + + return ( + <EditorWrapper> + <div ref={editorRef} /> + </EditorWrapper> + ); +}; + +export default ContainerEditor; diff --git a/wax-prosemirror-services/src/MatchingService/components/ContainerEditor.js b/wax-prosemirror-services/src/MatchingService/components/ContainerEditor.js index 273c90844..5d3a1f966 100644 --- a/wax-prosemirror-services/src/MatchingService/components/ContainerEditor.js +++ b/wax-prosemirror-services/src/MatchingService/components/ContainerEditor.js @@ -8,11 +8,17 @@ import { StepMap } from 'prosemirror-transform'; import { WaxContext } from 'wax-prosemirror-core'; const EditorWrapper = styled.div` + width: 70% !important; > .ProseMirror { - padding: 0px; + padding: 0px !important; + box-shadow: none !important; + width: 100% !important; &:focus { outline: none; } + p { + margin: 0; + } } `; diff --git a/wax-prosemirror-services/src/MatchingService/components/DropDownComponent.js b/wax-prosemirror-services/src/MatchingService/components/DropDownComponent.js new file mode 100644 index 000000000..1cc9281f8 --- /dev/null +++ b/wax-prosemirror-services/src/MatchingService/components/DropDownComponent.js @@ -0,0 +1,89 @@ +/* eslint-disable no-underscore-dangle */ +import React, { useContext, useMemo, useEffect, useState } from 'react'; +import styled from 'styled-components'; +import { WaxContext } from 'wax-prosemirror-core'; +import { ReactDropDownStyles } from 'wax-prosemirror-components'; +import Dropdown from 'react-dropdown'; +import { v4 as uuidv4 } from 'uuid'; + +const Wrapper = styled.div` + ${ReactDropDownStyles}; +`; +const DropdownStyled = styled(Dropdown)` + display: inline-flex; + cursor: not-allowed; + 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: 122%; + display: flex; + flex-direction: column; + align-items: flex-start; + .Dropdown-option { + width: 120%; + } + } +`; + +const DropComponent = ({ options }) => { + const context = useContext(WaxContext); + const { + pmViews: { main }, + } = context; + + const dropDownOptions = [ + { + label: 'Option 1', + value: '0', + }, + { + label: 'Long Option 2', + value: '1', + }, + { + label: 'Option 3', + value: '2', + }, + { + label: 'Option 4', + value: '3', + }, + ]; + + useEffect(() => {}, []); + + const onChange = option => {}; + + const MultipleDropDown = useMemo( + () => ( + <Wrapper key={uuidv4()}> + <DropdownStyled + key={uuidv4()} + onChange={option => onChange(option)} + options={dropDownOptions} + placeholder="Choose Option" + select + value="test" + /> + </Wrapper> + ), + [], + ); + + return MultipleDropDown; +}; + +export default DropComponent; diff --git a/wax-prosemirror-services/src/MatchingService/components/EditorComponent.js b/wax-prosemirror-services/src/MatchingService/components/EditorComponent.js index c1f858b5e..0b39e5299 100644 --- a/wax-prosemirror-services/src/MatchingService/components/EditorComponent.js +++ b/wax-prosemirror-services/src/MatchingService/components/EditorComponent.js @@ -16,12 +16,15 @@ const EditorWrapper = styled.div` display: flex; flex: 2 1 auto; justify-content: left; + width: 100%; > .ProseMirror { white-space: break-spaces; - width: 100%; + width: 100% !important; word-wrap: break-word; padding: 0 !important; + border-bottom: 1px solid black; + box-shadow: none !important; &:focus { outline: none; diff --git a/wax-prosemirror-services/src/MatchingService/components/FeedbackComponent.js b/wax-prosemirror-services/src/MatchingService/components/FeedbackComponent.js index 0afd56b88..1ea470dc2 100644 --- a/wax-prosemirror-services/src/MatchingService/components/FeedbackComponent.js +++ b/wax-prosemirror-services/src/MatchingService/components/FeedbackComponent.js @@ -9,7 +9,6 @@ import { DocumentHelpers } from 'wax-prosemirror-utilities'; const FeedBack = styled.div` color: black; margin-top: 10px; - padding: 10px; `; const FeedBackLabel = styled.span` @@ -37,7 +36,7 @@ export default ({ node, view, getPos, readOnly }) => { const { pmViews: { main }, } = context; - const [feedBack, setFeedBack] = useState(' '); + const [feedBack, setFeedBack] = useState(''); const [isFirstRun, setFirstRun] = useState(true); const [typing, setTyping] = useState(false); const feedBackRef = useRef(null); diff --git a/wax-prosemirror-services/src/MatchingService/components/MatchingContainerComponent.js b/wax-prosemirror-services/src/MatchingService/components/MatchingContainerComponent.js index c8cbf1bef..8d28d8b6c 100644 --- a/wax-prosemirror-services/src/MatchingService/components/MatchingContainerComponent.js +++ b/wax-prosemirror-services/src/MatchingService/components/MatchingContainerComponent.js @@ -5,56 +5,49 @@ import { Icon } from 'wax-prosemirror-components'; import styled from 'styled-components'; import FeedbackComponent from './FeedbackComponent'; import ContainerEditor from './ContainerEditor'; - -const MatchingContainer = styled.div` - border: 3px solid #f5f5f7; - margin-bottom: 30px; -`; +import DropDownComponent from './DropDownComponent'; const MatchingWrapper = styled.div` display: flex; flex-direction: column; - margin-bottom: ; margin: 0px 38px 15px 38px; margin-top: 10px; `; +const MatchingContainer = styled.div` + border: 3px solid #f5f5f7; + margin-bottom: 30px; + padding: 10px; +`; + const QuestionWrapper = styled.div` display: flex; flex-direction: row; `; -const LeftArea = styled.div` - display: flex; - flex-dierection: row; -`; -const RightArea = styled.div` - display: flex; -`; const InputsContainer = styled.div` display: flex; flex-direction: column; - - input { - margin-bottom: 10px; - } + width: 100%; `; -const FirstOption = styled.div` +const Option = styled.div` display: flex; flex-direction: row; + width: 100%; `; const CreateOptions = styled.div` display: flex; - margin-top: 10px; border: 1px solid black; `; const ActionButton = styled.button` + height: 24px; border: none; background: transparent; cursor: pointer; + padding-left: 0; `; const StyledIconAction = styled(Icon)` @@ -106,23 +99,33 @@ export default ({ node, view, getPos }) => { <span>Matching</span> <MatchingContainer className="matching"> <QuestionWrapper> - <LeftArea> - <InputsContainer> - <FirstOption> - <ContainerEditor getPos={getPos} node={node} view={view} /> - {!readOnly && ( - <ActionButton - onClick={() => addOption(node.attrs.id)} - type="button" - > - <StyledIconAction name="plusSquare" /> - </ActionButton> - )} - </FirstOption> - {inputList} - </InputsContainer> - </LeftArea> - <RightArea>Right</RightArea> + <InputsContainer> + <Option> + {!readOnly && ( + <ActionButton + onClick={() => addOption(node.attrs.id)} + type="button" + > + <StyledIconAction name="plusSquare" /> + </ActionButton> + )} + <ContainerEditor getPos={getPos} node={node} view={view} /> + <DropDownComponent /> + </Option> + <Option> + {!readOnly && ( + <ActionButton + onClick={() => addOption(node.attrs.id)} + type="button" + > + <StyledIconAction name="plusSquare" /> + </ActionButton> + )} + <ContainerEditor getPos={getPos} node={node} view={view} /> + <DropDownComponent /> + </Option> + {inputList} + </InputsContainer> </QuestionWrapper> <CreateOptions> <OptionArea>Options Area</OptionArea> diff --git a/wax-prosemirror-services/src/MatchingService/schema/matchingContainerNode.js b/wax-prosemirror-services/src/MatchingService/schema/matchingContainerNode.js index bc0ba1c2b..6f22b4ccf 100644 --- a/wax-prosemirror-services/src/MatchingService/schema/matchingContainerNode.js +++ b/wax-prosemirror-services/src/MatchingService/schema/matchingContainerNode.js @@ -7,6 +7,8 @@ const matchingContainerNode = { }, group: 'block questions', atom: true, + selectable: false, + draggable: false, content: 'block*', parseDOM: [ { -- GitLab