From 7c6bc79a1a1a6c0b0e67c30950a9a989ce2f69a1 Mon Sep 17 00:00:00 2001 From: chris <kokosias@yahoo.gr> Date: Mon, 25 Apr 2022 16:50:37 +0300 Subject: [PATCH] new components --- .../components/ContainerEditor.js | 155 ++++++++++++++++++ .../components/FeedbackComponent.js | 0 .../MultipleDropDownContainerComponent.js | 50 ++++++ 3 files changed, 205 insertions(+) create mode 100644 wax-prosemirror-services/src/MultipleDropDownService/components/ContainerEditor.js create mode 100644 wax-prosemirror-services/src/MultipleDropDownService/components/FeedbackComponent.js create mode 100644 wax-prosemirror-services/src/MultipleDropDownService/components/MultipleDropDownContainerComponent.js diff --git a/wax-prosemirror-services/src/MultipleDropDownService/components/ContainerEditor.js b/wax-prosemirror-services/src/MultipleDropDownService/components/ContainerEditor.js new file mode 100644 index 000000000..12e97db7c --- /dev/null +++ b/wax-prosemirror-services/src/MultipleDropDownService/components/ContainerEditor.js @@ -0,0 +1,155 @@ +/* eslint-disable react/prop-types */ + +import React, { useContext, useRef, useEffect } from 'react'; +import styled from 'styled-components'; +import { EditorView } from 'prosemirror-view'; +import { EditorState, TextSelection } from 'prosemirror-state'; +import { StepMap } from 'prosemirror-transform'; +import { keymap } from 'prosemirror-keymap'; +import { baseKeymap } from 'prosemirror-commands'; +import { undo, redo } from 'prosemirror-history'; +import { WaxContext } from 'wax-prosemirror-core'; + +const EditorWrapper = styled.div` + > .ProseMirror { + padding: 5px; + &: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 ContainerEditor = ({ node, view, getPos }) => { + const editorRef = useRef(); + + const context = useContext(WaxContext); + const { + app, + pmViews: { main }, + } = context; + + let multipleDropDownContainerNodeView; + const questionId = node.attrs.id; + const isEditable = main.props.editable(editable => { + return editable; + }); + + let finalPlugins = []; + + const createKeyBindings = () => { + const keys = getKeys(); + Object.keys(baseKeymap).forEach(key => { + keys[key] = baseKeymap[key]; + }); + return keys; + }; + + const getKeys = () => { + return { + 'Mod-z': () => undo(view.state, view.dispatch), + 'Mod-y': () => redo(view.state, view.dispatch), + }; + }; + + const plugins = [keymap(createKeyBindings()), ...app.getPlugins()]; + + finalPlugins = finalPlugins.concat([...plugins]); + + useEffect(() => { + multipleDropDownContainerNodeView = new EditorView( + { + mount: editorRef.current, + }, + { + editable: () => isEditable, + state: EditorState.create({ + doc: node, + plugins: finalPlugins, + }), + dispatchTransaction, + disallowedTools: [ + 'Images', + 'Lists', + 'lift', + 'Tables', + 'FillTheGap', + 'MultipleChoice', + ], + handleDOMEvents: { + mousedown: () => { + main.dispatch( + main.state.tr + .setMeta('outsideView', questionId) + .setSelection( + new TextSelection( + main.state.tr.doc.resolve( + getPos() + + 2 + + context.pmViews[questionId].state.selection.to, + ), + ), + ), + ); + context.updateView({}, questionId); + if (multipleDropDownContainerNodeView.hasFocus()) + multipleDropDownContainerNodeView.focus(); + }, + }, + + attributes: { + spellcheck: 'false', + }, + }, + ); + + // Set Each note into Wax's Context + context.updateView( + { + [questionId]: multipleDropDownContainerNodeView, + }, + questionId, + ); + multipleDropDownContainerNodeView.focus(); + }, []); + + const dispatchTransaction = tr => { + const { + state, + transactions, + } = multipleDropDownContainerNodeView.state.applyTransaction(tr); + multipleDropDownContainerNodeView.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/MultipleDropDownService/components/FeedbackComponent.js b/wax-prosemirror-services/src/MultipleDropDownService/components/FeedbackComponent.js new file mode 100644 index 000000000..e69de29bb diff --git a/wax-prosemirror-services/src/MultipleDropDownService/components/MultipleDropDownContainerComponent.js b/wax-prosemirror-services/src/MultipleDropDownService/components/MultipleDropDownContainerComponent.js new file mode 100644 index 000000000..b71a8b772 --- /dev/null +++ b/wax-prosemirror-services/src/MultipleDropDownService/components/MultipleDropDownContainerComponent.js @@ -0,0 +1,50 @@ +/* eslint-disable react/prop-types */ +import React, { useContext } from 'react'; +import { WaxContext } from 'wax-prosemirror-core'; +import styled from 'styled-components'; +import ContainerEditor from './ContainerEditor'; +import FeedbackComponent from './FeedbackComponent'; + +const FillTheGapContainer = styled.div` + border: 3px solid #f5f5f7; + margin-bottom: 30px; +`; + +const FillTheGapWrapper = styled.div` + margin-bottom: ; + margin: 0px 38px 15px 38px; + + margin-top: 10px; +`; + +export default ({ node, view, getPos }) => { + const context = useContext(WaxContext); + const { + pmViews: { main }, + } = context; + + const customProps = main.props.customValues; + + const isEditable = main.props.editable(editable => { + return editable; + }); + + const readOnly = !isEditable; + + return ( + <FillTheGapWrapper> + <span>Multiple Drop Down</span> + <FillTheGapContainer className="fill-the-gap"> + <ContainerEditor getPos={getPos} node={node} view={view} /> + {!(readOnly && customProps && !customProps.showFeedBack) && ( + <FeedbackComponent + getPos={getPos} + node={node} + readOnly={readOnly} + view={view} + /> + )} + </FillTheGapContainer> + </FillTheGapWrapper> + ); +}; -- GitLab