Skip to content
Snippets Groups Projects
AcceptTrackChange.js 3.56 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;
};

chris's avatar
chris committed
const acceptTrackChange = (
  dispatch,
  user,
  activeTrackChange,
  acceptConfig,
chris's avatar
chris committed
  context,
  trackData,
chris's avatar
chris committed
) => {
chris's avatar
chris committed
  const { activeView } = context;
  const { state } = activeView;
  const {
    tr,
chris's avatar
chris committed
    selection: { from },
  } = state;
chris's avatar
chris committed

  let { to } = activeTrackChange;
chris's avatar
chris committed

chris's avatar
chris committed
  if (trackData?.node?.type?.name === 'figure') {
chris's avatar
chris committed
    to = activeTrackChange.from + 3;
chris's avatar
chris committed
  } else if (activeTrackChange.from === to) {
    to += 1;
chris's avatar
chris committed
  }

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

chris's avatar
chris committed
  state.doc.nodesBetween(activeTrackChange.from, 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',
      );
chris's avatar
chris committed
      const configCheck = checkFromConfig(deletionMark, user, acceptConfig);
      if (!configCheck) return;
chris's avatar
chris committed
      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, acceptConfig);
      if (!configCheck) return;

      tr.step(
        new RemoveMarkStep(
          map.map(Math.max(pos, from)),
          map.map(Math.min(pos + node.nodeSize, to)),
chris's avatar
chris committed
          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, acceptConfig);
      if (!configCheck) return;
chris's avatar
chris committed
      tr.step(
        new RemoveMarkStep(
          activeTrackChange.from,
          activeTrackChange.to,
chris's avatar
chris committed
          formatChangeMark,
chris's avatar
chris committed
        ),
      );
    } 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',
      );
chris's avatar
chris committed
      const track = node.attrs.track.filter(
        track => track !== blockChangeTrack,
      );
chris's avatar
chris committed
      tr.setNodeMarkup(
        map.map(pos),
        null,
        {
          class: node.attrs.class,
          track: [],
        },
        // Object.assign(node.attrs.track, { track }),
        node.marks,
      );
    }
  });
  if (tr.steps.length) dispatch(tr);
};

export default acceptTrackChange;