Skip to content
Snippets Groups Projects
Commit 7294a71e authored by chris's avatar chris
Browse files

add remove numerical answer node

parent 6b74b598
No related branches found
No related tags found
1 merge request!511Numerical answer
......@@ -11,7 +11,27 @@ class NumericalAnswerQuestion extends Tools {
name = 'Numerical Answer';
get run() {
return main => {};
return main => {
const { dispatch } = main;
const { state } = main;
helpers.checkifEmpty(main);
const { $from, $to } = main.state.selection;
const range = $from.blockRange($to);
const { tr } = main.state;
const wrapping =
range &&
findWrapping(
range,
state.config.schema.nodes.numerical_answer_container,
{
id: uuidv4(),
},
);
if (!wrapping) return false;
tr.wrap(range, wrapping);
dispatch(tr);
};
}
get active() {
......
import { Service } from 'wax-prosemirror-core';
import NumericalAnswerContainerNode from './schema/NumericalAnswerContainerNode';
import NumericalAnswerQuestion from './NumericalAnswerQuestion';
import NumericalAnswerContainerNodeView from './NumericalAnswerContainerNodeView';
import NumericalAnswerContainerComponent from './components/NumericalAnswerContainerComponent';
import './numericalAnswer.css';
class NumericalAnswerService extends Service {
......@@ -13,6 +14,12 @@ class NumericalAnswerService extends Service {
createNode({
numerical_answer_container: NumericalAnswerContainerNode,
});
addPortal({
nodeView: NumericalAnswerContainerNodeView,
component: NumericalAnswerContainerComponent,
context: this.app,
});
}
dependencies = [];
......
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 gapContainerView;
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(() => {
gapContainerView = new EditorView(
{
mount: editorRef.current,
},
{
editable: () => isEditable,
state: EditorState.create({
doc: node,
plugins: finalPlugins,
}),
dispatchTransaction,
disallowedTools: [
'Images',
'Lists',
'lift',
'Tables',
'FillTheGap',
'MultipleChoice',
],
type: 'filltheGapContaier',
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 (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 ContainerEditor;
......@@ -6,7 +6,7 @@ import {
Icon,
} from 'wax-prosemirror-core';
import styled from 'styled-components';
import ContainerEditor from './ContainerEditor';
import EditorComponent from './EditorComponent';
import FeedbackComponent from '../../MultipleChoiceQuestionService/components/FeedbackComponent';
const NumericalAnswerWrapper = styled.div`
......@@ -65,7 +65,6 @@ export default ({ node, view, getPos }) => {
const removeQuestion = () => {
const allNodes = getNodes(context.pmViews.main);
allNodes.forEach(singleNode => {
if (singleNode.node.attrs.id === node.attrs.id) {
context.pmViews.main.dispatch(
......@@ -95,7 +94,7 @@ export default ({ node, view, getPos }) => {
)}
</div>
<NumericalAnswerContainer className="numerical-answer">
<ContainerEditor getPos={getPos} node={node} view={view} />
<EditorComponent getPos={getPos} node={node} view={view} />
{!testMode && !(readOnly && feedback === '') && (
<FeedbackComponent
......
/* fill The Gap */
.numerical-answer {}
.ProseMirror .numerical-answer .ProseMirror {
box-shadow: none;
border-bottom: 3px solid #F5F5F7;
line-height: 2.2;
padding: 25px 10px 20px 10px;
}
.ProseMirror .numerical-answer span>.ProseMirror {
box-shadow: none;
line-height: 1.6;
}
\ No newline at end of file
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