Skip to content
Snippets Groups Projects
Commit 95c1e8fb authored by chris's avatar chris
Browse files

iamges in answers

parent 56fc8373
No related branches found
No related tags found
No related merge requests found
import React, { useContext, useRef, useEffect } from 'react'; import React, { useContext, useRef, useEffect } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { EditorView } from 'prosemirror-view'; import { EditorView } from 'prosemirror-view';
import { EditorState, TextSelection } from 'prosemirror-state'; import { EditorState, TextSelection, NodeSelection } from 'prosemirror-state';
import { StepMap } from 'prosemirror-transform'; import { StepMap } from 'prosemirror-transform';
import { keymap } from 'prosemirror-keymap'; import { keymap } from 'prosemirror-keymap';
import { baseKeymap } from 'prosemirror-commands'; import { baseKeymap, chainCommands } from 'prosemirror-commands';
import { undo, redo } from 'prosemirror-history'; import { undo, redo } from 'prosemirror-history';
import { WaxContext, ComponentPlugin } from 'wax-prosemirror-core'; import { WaxContext, ComponentPlugin } from 'wax-prosemirror-core';
import {
splitListItem,
liftListItem,
sinkListItem,
} from 'prosemirror-schema-list';
import Placeholder from '../plugins/placeholder'; import Placeholder from '../plugins/placeholder';
import FakeCursorPlugin from '../../MultipleDropDownService/plugins/FakeCursorPlugin'; import FakeCursorPlugin from '../../MultipleDropDownService/plugins/FakeCursorPlugin';
...@@ -26,7 +31,7 @@ const EditorWrapper = styled.div` ...@@ -26,7 +31,7 @@ const EditorWrapper = styled.div`
} }
:empty::before { :empty::before {
content: 'Type your answer'; content: 'Type your question';
color: #aaa; color: #aaa;
float: left; float: left;
font-style: italic; font-style: italic;
...@@ -50,9 +55,10 @@ const EditorWrapper = styled.div` ...@@ -50,9 +55,10 @@ const EditorWrapper = styled.div`
} }
} }
`; `;
let WaxOverlays = () => true; let WaxOverlays = () => true;
const EditorComponent = ({ node, view, getPos }) => { const QuestionEditorComponent = ({ node, view, getPos }) => {
const editorRef = useRef(); const editorRef = useRef();
const context = useContext(WaxContext); const context = useContext(WaxContext);
...@@ -71,15 +77,46 @@ const EditorComponent = ({ node, view, getPos }) => { ...@@ -71,15 +77,46 @@ const EditorComponent = ({ node, view, getPos }) => {
const createKeyBindings = () => { const createKeyBindings = () => {
const keys = getKeys(); const keys = getKeys();
Object.keys(baseKeymap).forEach(key => { Object.keys(baseKeymap).forEach(key => {
keys[key] = baseKeymap[key]; if (keys[key]) {
keys[key] = chainCommands(keys[key], baseKeymap[key]);
} else {
keys[key] = baseKeymap[key];
}
}); });
return keys; return keys;
}; };
const pressEnter = (state, dispatch) => {
if (state.selection.node && state.selection.node.type.name === 'image') {
const { $from, to } = state.selection;
const same = $from.sharedDepth(to);
const pos = $from.before(same);
dispatch(state.tr.setSelection(NodeSelection.create(state.doc, pos)));
return true;
}
// LISTS
if (splitListItem(state.schema.nodes.list_item)(state)) {
splitListItem(state.schema.nodes.list_item)(state, dispatch);
return true;
}
return false;
};
const getKeys = () => { const getKeys = () => {
return { return {
'Mod-z': () => undo(view.state, view.dispatch), 'Mod-z': () => undo(view.state, view.dispatch),
'Mod-y': () => redo(view.state, view.dispatch), 'Mod-y': () => redo(view.state, view.dispatch),
'Mod-[': liftListItem(view.state.schema.nodes.list_item),
'Mod-]': sinkListItem(view.state.schema.nodes.list_item),
// Enter: () =>
// splitListItem(questionView.state.schema.nodes.list_item)(
// questionView.state,
// questionView.dispatch,
// ),
Enter: pressEnter,
}; };
}; };
...@@ -92,7 +129,7 @@ const EditorComponent = ({ node, view, getPos }) => { ...@@ -92,7 +129,7 @@ const EditorComponent = ({ node, view, getPos }) => {
}; };
finalPlugins = finalPlugins.concat([ finalPlugins = finalPlugins.concat([
createPlaceholder('Type your answer'), createPlaceholder('Type your question'),
...plugins, ...plugins,
]); ]);
...@@ -109,16 +146,19 @@ const EditorComponent = ({ node, view, getPos }) => { ...@@ -109,16 +146,19 @@ const EditorComponent = ({ node, view, getPos }) => {
plugins: finalPlugins, plugins: finalPlugins,
}), }),
dispatchTransaction, dispatchTransaction,
disallowedTools: ['Lists', 'lift', 'MultipleChoice'], disallowedTools: ['MultipleChoice'],
handleDOMEvents: { handleDOMEvents: {
mousedown: () => { mousedown: () => {
context.updateView({}, questionId);
main.dispatch( main.dispatch(
main.state.tr main.state.tr
.setMeta('outsideView', questionId) .setMeta('outsideView', questionId)
.setSelection( .setSelection(
new TextSelection( new TextSelection(
main.state.tr.doc.resolve( main.state.tr.doc.resolve(
getPos() + context.pmViews[questionId].state.selection.to, getPos() +
1 +
context.pmViews[questionId].state.selection.to,
), ),
), ),
), ),
...@@ -131,7 +171,9 @@ const EditorComponent = ({ node, view, getPos }) => { ...@@ -131,7 +171,9 @@ const EditorComponent = ({ node, view, getPos }) => {
// ), // ),
// ), // ),
// ); // );
context.updateView({}, questionId); context.updateView({}, questionId);
if (questionView.hasFocus()) questionView.focus(); if (questionView.hasFocus()) questionView.focus();
}, },
blur: (editorView, event) => { blur: (editorView, event) => {
...@@ -183,4 +225,4 @@ const EditorComponent = ({ node, view, getPos }) => { ...@@ -183,4 +225,4 @@ const EditorComponent = ({ node, view, getPos }) => {
); );
}; };
export default EditorComponent; export default QuestionEditorComponent;
import React from 'react'; import React from 'react';
import QuestionEditorComponent from './QuestionEditorComponent'; import EditorComponent from './EditorComponent';
export default ({ node, view, getPos }) => { export default ({ node, view, getPos }) => {
return <QuestionEditorComponent getPos={getPos} node={node} view={view} />; return <EditorComponent getPos={getPos} node={node} view={view} />;
}; };
import React, { useContext, useRef, useEffect } from 'react';
import styled from 'styled-components';
import { EditorView } from 'prosemirror-view';
import { EditorState, TextSelection, NodeSelection } from 'prosemirror-state';
import { StepMap } from 'prosemirror-transform';
import { keymap } from 'prosemirror-keymap';
import { baseKeymap, chainCommands } from 'prosemirror-commands';
import { undo, redo } from 'prosemirror-history';
import { WaxContext, ComponentPlugin } from 'wax-prosemirror-core';
import {
splitListItem,
liftListItem,
sinkListItem,
} from 'prosemirror-schema-list';
import Placeholder from '../plugins/placeholder';
import FakeCursorPlugin from '../../MultipleDropDownService/plugins/FakeCursorPlugin';
const EditorWrapper = styled.div`
border: none;
display: flex;
flex: 2 1 auto;
justify-content: left;
.ProseMirror {
white-space: break-spaces;
width: 100%;
word-wrap: break-word;
&:focus {
outline: none;
}
:empty::before {
content: 'Type your question';
color: #aaa;
float: left;
font-style: italic;
pointer-events: none;
}
p:first-child {
margin: 0;
}
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;
}
}
`;
let WaxOverlays = () => true;
const QuestionEditorComponent = ({ node, view, getPos }) => {
const editorRef = useRef();
const context = useContext(WaxContext);
const {
app,
pmViews: { main },
} = context;
let questionView;
const questionId = node.attrs.id;
const isEditable = main.props.editable(editable => {
return editable;
});
let finalPlugins = [FakeCursorPlugin()];
const createKeyBindings = () => {
const keys = getKeys();
Object.keys(baseKeymap).forEach(key => {
if (keys[key]) {
keys[key] = chainCommands(keys[key], baseKeymap[key]);
} else {
keys[key] = baseKeymap[key];
}
});
return keys;
};
const pressEnter = (state, dispatch) => {
if (state.selection.node && state.selection.node.type.name === 'image') {
const { $from, to } = state.selection;
const same = $from.sharedDepth(to);
const pos = $from.before(same);
dispatch(state.tr.setSelection(NodeSelection.create(state.doc, pos)));
return true;
}
// LISTS
if (splitListItem(state.schema.nodes.list_item)(state)) {
splitListItem(state.schema.nodes.list_item)(state, dispatch);
return true;
}
return false;
};
const getKeys = () => {
return {
'Mod-z': () => undo(view.state, view.dispatch),
'Mod-y': () => redo(view.state, view.dispatch),
'Mod-[': liftListItem(view.state.schema.nodes.list_item),
'Mod-]': sinkListItem(view.state.schema.nodes.list_item),
// Enter: () =>
// splitListItem(questionView.state.schema.nodes.list_item)(
// questionView.state,
// questionView.dispatch,
// ),
Enter: pressEnter,
};
};
const plugins = [keymap(createKeyBindings()), ...app.getPlugins()];
const createPlaceholder = placeholder => {
return Placeholder({
content: placeholder,
});
};
finalPlugins = finalPlugins.concat([
createPlaceholder('Type your question'),
...plugins,
]);
useEffect(() => {
WaxOverlays = ComponentPlugin('waxOverlays');
questionView = new EditorView(
{
mount: editorRef.current,
},
{
editable: () => isEditable,
state: EditorState.create({
doc: node,
plugins: finalPlugins,
}),
dispatchTransaction,
disallowedTools: ['MultipleChoice'],
handleDOMEvents: {
mousedown: () => {
context.updateView({}, questionId);
main.dispatch(
main.state.tr
.setMeta('outsideView', questionId)
.setSelection(
new TextSelection(
main.state.tr.doc.resolve(
getPos() +
1 +
context.pmViews[questionId].state.selection.to,
),
),
),
);
context.updateView({}, questionId);
if (questionView.hasFocus()) questionView.focus();
},
blur: (editorView, event) => {
if (questionView && event.relatedTarget === null) {
questionView.focus();
}
},
},
attributes: {
spellcheck: 'false',
},
},
);
// Set Each note into Wax's Context
context.updateView(
{
[questionId]: questionView,
},
questionId,
);
if (questionView.hasFocus()) questionView.focus();
}, []);
const dispatchTransaction = tr => {
const { state, transactions } = questionView.state.applyTransaction(tr);
questionView.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} />
<WaxOverlays activeViewId={questionId} />
</EditorWrapper>
);
};
export default QuestionEditorComponent;
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment