Skip to content
Snippets Groups Projects
MatchingOptionComponent.js 4.14 KiB
Newer Older
chris's avatar
chris committed
/* eslint-disable react/prop-types */
import React, { useContext } from 'react';
chris's avatar
chris committed
import { v4 as uuidv4 } from 'uuid';
import { TextSelection } from 'prosemirror-state';
import { Fragment } from 'prosemirror-model';
import styled from 'styled-components';
import { Icon } from 'wax-prosemirror-components';
import { WaxContext } from 'wax-prosemirror-core';
chris's avatar
chris committed
import EditorComponent from './EditorComponent';
chris's avatar
chris committed
import DropDownComponent from './DropDownComponent';
chris's avatar
chris committed
import TestModeDropDownComponent from './TestModeDropDownComponent';
chris's avatar
chris committed

const Option = styled.div`
  display: flex;
  flex-direction: row;
  padding-bottom: 10px;
chris's avatar
chris committed
`;

const ButtonsContainer = styled.div`
  display: flex;
  flex-direction: column;
  justify-content: center;
chris's avatar
chris committed
`;

const DropDownContainer = styled.div`
  display: flex;
  flex-direction: column;
  justify-content: center;
chris's avatar
chris committed
`;
chris's avatar
chris committed

chris's avatar
chris committed
const ActionButton = styled.button`
  background: transparent;
chris's avatar
chris committed
  cursor: pointer;
chris's avatar
chris committed
  padding-left: 0;
`;

const StyledIconAction = styled(Icon)`
  height: 24px;
  width: 24px;
`;

chris's avatar
chris committed
const AnswerContainer = styled.div`
  display: flex;
  flex-direction: column;
chris's avatar
chris committed
`;
const CorrectAnswer = styled.span`
  span {
    color: #008000;
  }
`;

const Answer = styled.span`
  span {
    color: ${props => (props.isCorrect ? '#008000' : '#FF3030')};
  }
`;

chris's avatar
chris committed
export default ({ node, view, getPos }) => {
chris's avatar
chris committed
  const context = useContext(WaxContext);
  const {
    pmViews: { main },
  } = context;

  const isEditable = main.props.editable(editable => {
    return editable;
  });

  const readOnly = !isEditable;
chris's avatar
chris committed
  const customProps = main.props.customValues;
  const { testMode, showFeedBack } = customProps;
chris's avatar
chris committed

  const addAnswer = () => {
    const nodeId = node.attrs.id;
    const newAnswerId = uuidv4();
    main.state.doc.descendants((editorNode, index) => {
      if (editorNode.type.name === 'matching_option') {
        if (editorNode.attrs.id === nodeId) {
          main.dispatch(
            main.state.tr.setSelection(
              new TextSelection(
                main.state.tr.doc.resolve(editorNode.nodeSize + index),
              ),
            ),
          );

          const newOption = main.state.config.schema.nodes.matching_option.create(
            { id: newAnswerId },
            Fragment.empty,
          );
          main.dispatch(main.state.tr.replaceSelectionWith(newOption));
        }
      }
    });
  };

chris's avatar
chris committed
  const removeAnswer = () => {
    main.state.doc.descendants((sinlgeNode, pos) => {
      if (sinlgeNode.attrs.id === node.attrs.id) {
        main.dispatch(
          main.state.tr.deleteRange(pos, pos + sinlgeNode.nodeSize),
        );
      }
    });
  };

chris's avatar
chris committed
  const answer = node.attrs.options.find(
    option => option.value === node.attrs.answer,
  );

  const correct = node.attrs.options.find(
    option => option.value === node.attrs.correct,
  );

  const isCorrect = node.attrs.correct === node.attrs.answer;

chris's avatar
chris committed
  return (
chris's avatar
chris committed
    <Option>
chris's avatar
chris committed
      {!readOnly && (
chris's avatar
chris committed
        <ButtonsContainer>
          <ActionButton onClick={addAnswer} type="button">
            <StyledIconAction name="plusSquare" />
          </ActionButton>
          {!node.attrs.isfirst && (
            <ActionButton onClick={removeAnswer} type="button">
              <StyledIconAction name="deleteOutlined" />
            </ActionButton>
          )}
        </ButtonsContainer>
chris's avatar
chris committed
      )}
      <EditorComponent getPos={getPos} node={node} view={view} />
chris's avatar
chris committed
      <DropDownContainer>
        {(!readOnly || (readOnly && !testMode && !showFeedBack)) && (
chris's avatar
chris committed
          <DropDownComponent getPos={getPos} node={node} view={view} />
        )}
chris's avatar
chris committed

        {readOnly && testMode && !showFeedBack && (
chris's avatar
chris committed
          <TestModeDropDownComponent getPos={getPos} node={node} view={view} />
chris's avatar
chris committed
        )}

        {readOnly && showFeedBack && (
chris's avatar
chris committed
          <AnswerContainer>
            <CorrectAnswer>
              Correct : &nbsp;{correct && <span>{correct.label} </span>}
            </CorrectAnswer>
            <Answer isCorrect={isCorrect}>
              Answer : &nbsp;
              {answer && <span>{answer.label} </span>}
            </Answer>
          </AnswerContainer>
chris's avatar
chris committed
        )}
chris's avatar
chris committed
      </DropDownContainer>
    </Option>
chris's avatar
chris committed
  );
chris's avatar
chris committed
};