Skip to content
Snippets Groups Projects
AcceptTrackChange.js 3.47 KiB
Newer Older
import { Mapping, RemoveMarkStep, ReplaceStep } from 'prosemirror-transform';
import { Slice } from 'prosemirror-model';
import removeNode from './removeNode';

const checkFromConfig = (mark, user, config) => {
  if (mark.attrs.username === user.username && !config.own.accept) {
    return false;
  }

  if (mark.attrs.username !== user.username && !config.others.accept) {
    return false;
  }

  return true;
};

const acceptTrackChange = (state, dispatch, user, activeTrackChange) => {
  const {
    tr,
    selection: { from, to },
  } = state;

  tr.setMeta('AcceptReject', true);
  const map = new Mapping();

  state.doc.nodesBetween(
    activeTrackChange.from,
    activeTrackChange.to,
    (node, pos) => {
      if (
        node.attrs.track &&
        node.attrs.track.find(track => track.type === 'deletion')
      ) {
        removeNode(tr, node, pos, map);
      }
      if (
        node.marks &&
        node.marks.find(mark => mark.type.name === 'deletion')
      ) {
        const deletionMark = node.marks.find(
          mark => mark.type.name === 'deletion',
        );

        const configCheck = checkFromConfig(deletionMark, user, this.config);
        if (!configCheck) return;

        const deletionStep = new ReplaceStep(
          map.map(Math.max(pos, from)),
          map.map(Math.min(pos + node.nodeSize, to)),
          Slice.empty,
        );
        tr.step(deletionStep);
        map.appendMap(deletionStep.getMap());
      } else if (
        node.attrs.track &&
        node.attrs.track.find(track => track.type === 'insertion')
      ) {
        const track = node.attrs.track.filter(
          track => track.type !== 'insertion',
        );
        tr.setNodeMarkup(
          map.map(pos),
          null,
          Object.assign(node.attrs.track, { track }),
          node.marks,
        );
      } else if (
        node.marks &&
        node.marks.find(mark => mark.type.name === 'insertion')
      ) {
        const insertionMark = node.marks.find(
          mark => mark.type.name === 'insertion',
        );
        // const configCheck = checkFromConfig(insertionMark, user, this.config);
        // if (!configCheck) return;

        tr.step(
          new RemoveMarkStep(
            map.map(Math.max(pos, from)),
            map.map(Math.min(pos + node.nodeSize, to)),
            insertionMark,
          ),
        );
      } else if (
        node.marks &&
        node.marks.find(mark => mark.type.name === 'format_change')
      ) {
        const formatChangeMark = node.marks.find(
          mark => mark.type.name === 'format_change',
        );
        // const configCheck = checkFromConfig(
        //   formatChangeMark,
        //   user,
        //   this.config,
        // );
        // if (!configCheck) return;

        tr.step(
          new RemoveMarkStep(
            activeTrackChange.from,
            activeTrackChange.to,
            formatChangeMark,
          ),
        );
      } else if (
        node.attrs.track &&
        node.attrs.track.find(track => track.type === 'block_change')
      ) {
        const blockChangeTrack = node.attrs.track.find(
          track => track.type === 'block_change',
        );

        const track = node.attrs.track.filter(
          track => track !== blockChangeTrack,
        );

        tr.setNodeMarkup(
          map.map(pos),
          null,
          Object.assign(node.attrs.track, { track }),
          node.marks,
        );
      }
    },
  );
  if (tr.steps.length) dispatch(tr);
};

export default acceptTrackChange;