Skip to content
Snippets Groups Projects

Add feedback

Merged Christos requested to merge add-feedback into master
1 file
+ 11
6
Compare changes
  • Side-by-side
  • Inline
 
/* eslint-disable react/destructuring-assignment */
 
/* 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 EditorComponent = ({ node, view, getPos }) => {
 
const editorRef = useRef();
 
 
const context = useContext(WaxContext);
 
let gapContainerView;
 
const questionId = node.attrs.id;
 
const isEditable = context.view.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()), ...context.app.getPlugins()];
 
 
finalPlugins = finalPlugins.concat([...plugins]);
 
 
useEffect(() => {
 
gapContainerView = new EditorView(
 
{
 
mount: editorRef.current,
 
},
 
{
 
editable: () => isEditable,
 
state: EditorState.create({
 
doc: node,
 
plugins: finalPlugins,
 
}),
 
// This is the magic part
 
dispatchTransaction,
 
disallowedTools: [
 
'Images',
 
'Lists',
 
'lift',
 
'Tables',
 
'FillTheGap',
 
'MultipleChoice',
 
],
 
handleDOMEvents: {
 
mousedown: () => {
 
context.view.main.dispatch(
 
context.view.main.state.tr
 
.setMeta('outsideView', questionId)
 
.setSelection(
 
new TextSelection(
 
context.view.main.state.tr.doc.resolve(
 
getPos() +
 
2 +
 
context.view[questionId].state.selection.to,
 
),
 
),
 
),
 
);
 
context.updateView({}, questionId);
 
if (gapContainerView.hasFocus()) gapContainerView.focus();
 
},
 
},
 
 
attributes: {
 
spellcheck: 'false',
 
},
 
},
 
);
 
 
// Set Each note into Wax's Context
 
context.updateView(
 
{
 
[questionId]: gapContainerView,
 
},
 
questionId,
 
);
 
gapContainerView.focus();
 
}, []);
 
 
const dispatchTransaction = tr => {
 
const { state, transactions } = gapContainerView.state.applyTransaction(tr);
 
gapContainerView.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 EditorComponent;