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