Explorar o código

use codemirror merge

yuto-oweseek %!s(int64=4) %!d(string=hai) anos
pai
achega
73a0dd3c36
Modificáronse 1 ficheiros con 119 adicións e 108 borrados
  1. 119 108
      packages/app/src/components/PageEditor/ConflictDiffModal.tsx

+ 119 - 108
packages/app/src/components/PageEditor/ConflictDiffModal.tsx

@@ -1,4 +1,6 @@
-import React, { useState, useRef, FC } from 'react';
+import React, {
+  useState, useRef, useEffect, FC,
+} from 'react';
 import PropTypes from 'prop-types';
 import {
   Modal, ModalHeader, ModalBody, ModalFooter,
@@ -7,10 +9,14 @@ import { parseISO, format } from 'date-fns';
 import { useTranslation } from 'react-i18next';
 // TODO: consider whether to use codemirrorEditor
 import { UnControlled as CodeMirrorAny } from 'react-codemirror2';
+import CodeMirror2 from 'codemirror/lib/codemirror';
 import PageContainer from '../../client/services/PageContainer';
 import EditorContainer from '../../client/services/EditorContainer';
 
-require('codemirror/mode/htmlmixed/htmlmixed');
+
+require('codemirror/lib/codemirror.css');
+require('codemirror/addon/merge/merge');
+require('codemirror/addon/merge/merge.css');
 const DMP = require('diff_match_patch');
 
 // avoid typescript type error
@@ -29,17 +35,28 @@ export const ConflictDiffModal: FC<ConflictDiffModalProps> = (props) => {
   const { t } = useTranslation('');
   const resolvedRevision = useRef<string>('');
   const [isRevisionselected, setIsRevisionSelected] = useState<boolean>(false);
+  const [codeMirrorRef, setCodeMirrorRef] = useState<HTMLDivElement | null>(null);
 
   const { pageContainer, editorContainer } = props;
   const { request, origin, latest } = pageContainer.state.revisionsOnConflict || { request: {}, origin: {}, latest: {} };
 
-  const codeMirrorRevisionOption = {
-    mode: 'htmlmixed',
-    lineNumbers: true,
-    tabSize: 2,
-    indentUnit: 2,
-    readOnly: true,
-  };
+  useEffect(() => {
+    if (codeMirrorRef) {
+      CodeMirror2.MergeView(codeMirrorRef, {
+        value: origin.revisionBody,
+        origLeft: request.revisionBody,
+        origRight: latest.revisionBody,
+        lineNumbers: true,
+        collapseIdentical: true,
+        highlightDifferences: true,
+        connect: 'connect',
+        allowEditingOriginals: false,
+        readOnly: true,
+        revertButtons: false,
+        showDifferences: true,
+      });
+    }
+  }, [codeMirrorRef, origin, request, latest]);
 
   const onCancel = () => {
     if (props.onCancel != null) {
@@ -70,118 +87,112 @@ export const ConflictDiffModal: FC<ConflictDiffModalProps> = (props) => {
       </ModalHeader>
       <ModalBody>
         {Object.keys(pageContainer.state.revisionsOnConflict || {}).length > 0
-          && (
-            <div className="row mx-2">
-              <div className="col-12 text-center mt-2 mb-4">
-                <h2 className="font-weight-bold">{t('modal_resolve_conflict.resolve_conflict_message')}</h2>
-              </div>
-              <div className="col-12 col-md-4 border border-dark">
-                <h3 className="font-weight-bold my-2">{t('modal_resolve_conflict.requested_revision')}</h3>
-                <div className="d-flex align-items-center my-3">
-                  <div>
-                    <img height="40px" className="rounded-circle" src={request.userImgPath} />
-                  </div>
-                  <div className="ml-3 text-muted">
-                    <p className="my-0">updated by {request.userName}</p>
-                    <p className="my-0">{format(parseISO(request.createdAt), 'yyyy/MM/dd HH:mm:ss')}</p>
-                  </div>
+        && (
+          <div className="row">
+            <div className="col-12 text-center mt-2 mb-4">
+              <h2 className="font-weight-bold">{t('modal_resolve_conflict.resolve_conflict_message')}</h2>
+            </div>
+            <div className="col-4">
+              <h3 className="font-weight-bold my-2">{t('modal_resolve_conflict.requested_revision')}</h3>
+              <div className="d-flex align-items-center my-3">
+                <div>
+                  <img height="40px" className="rounded-circle" src={request.userImgPath} />
                 </div>
-                <CodeMirror
-                  value={request.revisionBody}
-                  options={codeMirrorRevisionOption}
-                />
-                <div className="text-center my-4">
-                  <button
-                    type="button"
-                    className="btn btn-primary"
-                    onClick={() => {
-                      setIsRevisionSelected(true);
-                      resolvedRevision.current = request.revisionBody;
-                    }}
-                  >
-                    <i className="icon-fw icon-arrow-down-circle"></i>
-                    {t('modal_resolve_conflict.select_revision', { revision: 'request' })}
-                  </button>
+                <div className="ml-3 text-muted">
+                  <p className="my-0">updated by {request.userName}</p>
+                  <p className="my-0">{format(parseISO(request.createdAt), 'yyyy/MM/dd HH:mm:ss')}</p>
                 </div>
               </div>
-              <div className="col-12 col-md-4 border border-dark">
-                <h3 className="font-weight-bold my-2">{t('origin_revision')}</h3>
-                <div className="d-flex align-items-center my-3">
-                  <div>
-                    <img height="40px" className="rounded-circle" src={origin.userImgPath} />
-                  </div>
-                  <div className="ml-3 text-muted">
-                    <p className="my-0">updated by {origin.userName}</p>
-                    <p className="my-0">{format(parseISO(origin.createdAt), 'yyyy/MM/dd HH:mm:ss')}</p>
-                  </div>
+            </div>
+            <div className="col-4">
+              <h3 className="font-weight-bold my-2">{t('modal_resolve_conflict.origin_revision')}</h3>
+              <div className="d-flex align-items-center my-3">
+                <div>
+                  <img height="40px" className="rounded-circle" src={origin.userImgPath} />
                 </div>
-                <CodeMirror
-                  value={origin.revisionBody}
-                  options={codeMirrorRevisionOption}
-                />
-                <div className="text-center my-4">
-                  <button
-                    type="button"
-                    className="btn btn-primary"
-                    onClick={() => {
-                      setIsRevisionSelected(true);
-                      resolvedRevision.current = origin.revisionBody;
-                    }}
-                  >
-                    <i className="icon-fw icon-arrow-down-circle"></i>
-                    {t('modal_resolve_conflict.select_revision', { revision: 'origin' })}
-                  </button>
+                <div className="ml-3 text-muted">
+                  <p className="my-0">updated by {origin.userName}</p>
+                  <p className="my-0">{format(parseISO(origin.createdAt), 'yyyy/MM/dd HH:mm:ss')}</p>
                 </div>
               </div>
-              <div className="col-12 col-md-4 border border-dark">
-                <h3 className="font-weight-bold my-2">{t('modal_resolve_conflict.latest_revision')}</h3>
-                <div className="d-flex align-items-center my-3">
-                  <div>
-                    <img height="40px" className="rounded-circle" src={latest.userImgPath} />
-                  </div>
-                  <div className="ml-3 text-muted">
-                    <p className="my-0">updated by {latest.userName}</p>
-                    <p className="my-0">{format(parseISO(latest.createdAt), 'yyyy/MM/dd HH:mm:ss')}</p>
-                  </div>
+            </div>
+            <div className="col-4">
+              <h3 className="font-weight-bold my-2">{t('modal_resolve_conflict.latest_revision')}</h3>
+              <div className="d-flex align-items-center my-3">
+                <div>
+                  <img height="40px" className="rounded-circle" src={latest.userImgPath} />
                 </div>
-                <CodeMirror
-                  value={latest.revisionBody}
-                  options={codeMirrorRevisionOption}
-                />
-                <div className="text-center my-4">
-                  <button
-                    type="button"
-                    className="btn btn-primary"
-                    onClick={() => {
-                      setIsRevisionSelected(true);
-                      resolvedRevision.current = latest.revisionBody;
-                    }}
-                  >
-                    <i className="icon-fw icon-arrow-down-circle"></i>
-                    {t('modal_resolve_conflict.select_revision', { revision: 'latest' })}
-                  </button>
+                <div className="ml-3 text-muted">
+                  <p className="my-0">updated by {latest.userName}</p>
+                  <p className="my-0">{format(parseISO(latest.createdAt), 'yyyy/MM/dd HH:mm:ss')}</p>
                 </div>
               </div>
-              <div className="col-12 border border-dark">
-                <h3 className="font-weight-bold my-2">{t('modal_resolve_conflict.selected_editable_revision')}</h3>
-                <CodeMirror
-                  value={resolvedRevision.current}
-                  options={{
-                    mode: 'htmlmixed',
-                    lineNumbers: true,
-                    tabSize: 2,
-                    indentUnit: 2,
-                    placeholder: t('modal_resolve_conflict.resolve_conflict_message'),
+            </div>
+            <div className="col-12" ref={(el) => { setCodeMirrorRef(el) }}></div>
+            <div className="col-4">
+              <div className="text-center my-4">
+                <button
+                  type="button"
+                  className="btn btn-primary"
+                  onClick={() => {
+                    setIsRevisionSelected(true);
+                    resolvedRevision.current = request.revisionBody;
                   }}
-                  onChange={(editor, data, pageBody) => {
-                    if (pageBody === '') setIsRevisionSelected(false);
-                    resolvedRevision.current = pageBody;
+                >
+                  <i className="icon-fw icon-arrow-down-circle"></i>
+                  {t('modal_resolve_conflict.select_revision', { revision: 'request' })}
+                </button>
+              </div>
+            </div>
+            <div className="col-4">
+              <div className="text-center my-4">
+                <button
+                  type="button"
+                  className="btn btn-primary"
+                  onClick={() => {
+                    setIsRevisionSelected(true);
+                    resolvedRevision.current = origin.revisionBody;
                   }}
-                />
+                >
+                  <i className="icon-fw icon-arrow-down-circle"></i>
+                  {t('modal_resolve_conflict.select_revision', { revision: 'origin' })}
+                </button>
               </div>
             </div>
-          )
-        }
+            <div className="col-4">
+              <div className="text-center my-4">
+                <button
+                  type="button"
+                  className="btn btn-primary"
+                  onClick={() => {
+                    setIsRevisionSelected(true);
+                    resolvedRevision.current = latest.revisionBody;
+                  }}
+                >
+                  <i className="icon-fw icon-arrow-down-circle"></i>
+                  {t('modal_resolve_conflict.select_revision', { revision: 'latest' })}
+                </button>
+              </div>
+            </div>
+            <div className="col-12 border border-dark">
+              <h3 className="font-weight-bold my-2">{t('modal_resolve_conflict.selected_editable_revision')}</h3>
+              <CodeMirror
+                value={resolvedRevision.current}
+                options={{
+                  mode: 'htmlmixed',
+                  lineNumbers: true,
+                  tabSize: 2,
+                  indentUnit: 2,
+                  placeholder: t('modal_resolve_conflict.resolve_conflict_message'),
+                }}
+                onChange={(editor, data, pageBody) => {
+                  if (pageBody === '') setIsRevisionSelected(false);
+                  resolvedRevision.current = pageBody;
+                }}
+              />
+            </div>
+          </div>
+        )}
       </ModalBody>
       <ModalFooter>
         <button