Skip to content
Snippets Groups Projects
DropDownComponent.js 2.8 KiB
Newer Older
chris's avatar
chris committed
/* eslint-disable no-underscore-dangle */
chris's avatar
chris committed
import React, { useContext, useMemo, useEffect, useState } from 'react';
chris's avatar
chris committed
import styled from 'styled-components';
chris's avatar
chris committed
import { find } from 'lodash';
chris's avatar
chris committed
import { ReactDropDownStyles } from 'wax-prosemirror-components';
chris's avatar
chris committed
import { WaxContext } from 'wax-prosemirror-core';
import { DocumentHelpers } from 'wax-prosemirror-utilities';
chris's avatar
chris committed
import Dropdown from 'react-dropdown';
import { v4 as uuidv4 } from 'uuid';

const Wrapper = styled.div`
  ${ReactDropDownStyles};
`;
const DropdownStyled = styled(Dropdown)`
  display: inline-flex;
  cursor: not-allowed;
chris's avatar
chris committed
  margin-left: auto;
chris's avatar
chris committed
  opacity: ${props => (props.select ? 1 : 0.4)};
  pointer-events: ${props => (props.select ? 'default' : 'none')};
  .Dropdown-control {
    border: none;
    padding: 8px 30px 8px 10px;

    &:hover {
      box-shadow: none;
    }
  }

  .Dropdown-arrow {
    top: 17px;
  }

  .Dropdown-menu {
chris's avatar
chris committed
    width: 102%;
chris's avatar
chris committed
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    .Dropdown-option {
chris's avatar
chris committed
      width: 100%;
chris's avatar
chris committed
    }
  }
`;

chris's avatar
chris committed
const DropComponent = ({ getPos, node, view }) => {
chris's avatar
chris committed
  const [selectedOption, setSelectedOption] = useState(undefined);
chris's avatar
chris committed

chris's avatar
chris committed
  const context = useContext(WaxContext);
  const {
    pmViews: { main },
  } = context;

chris's avatar
chris committed
  const onChange = option => {
    setSelectedOption(option);
chris's avatar
chris committed

    const allNodes = getNodes(main);
    allNodes.forEach(singleNode => {
      if (singleNode.attrs.id === node.attrs.id) {
        main.dispatch(
          main.state.tr
            .setMeta('addToHistory', false)
            .setNodeMarkup(getPos() + 3, undefined, {
              ...singleNode.attrs,
              answer: option,
            }),
        );
      }
    });
chris's avatar
chris committed
  };

  useEffect(() => {
    const value = selectedOption ? selectedOption.value : '';
    const found = find(node.attrs.options, { value });

chris's avatar
chris committed
    if (!found) {
      setSelectedOption(undefined);
    }
chris's avatar
chris committed
  }, [node.attrs.options]);
chris's avatar
chris committed

  const MultipleDropDown = useMemo(
    () => (
      <Wrapper key={uuidv4()}>
        <DropdownStyled
          key={uuidv4()}
          onChange={option => onChange(option)}
chris's avatar
chris committed
          options={node.attrs.options}
chris's avatar
chris committed
          placeholder="Select option"
chris's avatar
chris committed
          select
chris's avatar
chris committed
          value={
            selectedOption === 'undedfined' ? 'Select Option' : selectedOption
          }
chris's avatar
chris committed
        />
      </Wrapper>
    ),
chris's avatar
chris committed
    [node.attrs.options, selectedOption],
chris's avatar
chris committed
  );

  return MultipleDropDown;
};

export default DropComponent;
chris's avatar
chris committed

const getNodes = view => {
  const allNodes = DocumentHelpers.findBlockNodes(view.state.doc);
  const matchingOptions = [];
  allNodes.forEach(node => {
    if (node.node.type.name === 'paragraph') {
      node.node.content.content.forEach(optionNode => {
        if (optionNode.type.name === 'matching_option')
          matchingOptions.push(optionNode);
      });
    }
  });
  return matchingOptions;
};