|
@@ -1,12 +1,13 @@
|
|
|
-import React, { useState, useEffect, FC } from 'react';
|
|
|
|
|
|
|
+import React, { useState, FC } from 'react';
|
|
|
import PropTypes from 'prop-types';
|
|
import PropTypes from 'prop-types';
|
|
|
import {
|
|
import {
|
|
|
- Modal, ModalHeader, ModalBody, ModalFooter, Button,
|
|
|
|
|
|
|
+ Modal, ModalHeader, ModalBody, ModalFooter,
|
|
|
} from 'reactstrap';
|
|
} from 'reactstrap';
|
|
|
-// import CodeMirror from 'codemirror/lib/codemirror';
|
|
|
|
|
|
|
+import { parseISO, format } from 'date-fns';
|
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
import { UnControlled as CodeMirror } from 'react-codemirror2';
|
|
import { UnControlled as CodeMirror } from 'react-codemirror2';
|
|
|
import PageContainer from '../../client/services/PageContainer';
|
|
import PageContainer from '../../client/services/PageContainer';
|
|
|
|
|
+import { toastError } from '../../client/util/apiNotification';
|
|
|
|
|
|
|
|
require('codemirror/addon/lint/css-lint');
|
|
require('codemirror/addon/lint/css-lint');
|
|
|
require('codemirror/addon/hint/css-hint');
|
|
require('codemirror/addon/hint/css-hint');
|
|
@@ -16,6 +17,15 @@ require('codemirror/addon/edit/closebrackets');
|
|
|
require('codemirror/mode/css/css');
|
|
require('codemirror/mode/css/css');
|
|
|
require('~/client/util/codemirror/autorefresh.ext');
|
|
require('~/client/util/codemirror/autorefresh.ext');
|
|
|
|
|
|
|
|
|
|
+require('codemirror/addon/hint/show-hint');
|
|
|
|
|
+require('codemirror/addon/edit/matchbrackets');
|
|
|
|
|
+require('codemirror/addon/edit/closebrackets');
|
|
|
|
|
+require('codemirror/mode/htmlmixed/htmlmixed');
|
|
|
|
|
+require('~/client/util/codemirror/autorefresh.ext');
|
|
|
|
|
+
|
|
|
|
|
+require('jquery-ui/ui/widgets/resizable');
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
require('jquery-ui/ui/widgets/resizable');
|
|
require('jquery-ui/ui/widgets/resizable');
|
|
|
|
|
|
|
|
const DMP = require('diff_match_patch');
|
|
const DMP = require('diff_match_patch');
|
|
@@ -31,13 +41,11 @@ type ConflictDiffModalProps = {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
export const ConflictDiffModal: FC<ConflictDiffModalProps> = (props) => {
|
|
export const ConflictDiffModal: FC<ConflictDiffModalProps> = (props) => {
|
|
|
- const [val, setVal] = useState('value 1');
|
|
|
|
|
- const [orig, setOrig] = useState('value 2');
|
|
|
|
|
const [resolvedRevision, SetResolvedRevision] = useState<string>(INITIAL_TEXT);
|
|
const [resolvedRevision, SetResolvedRevision] = useState<string>(INITIAL_TEXT);
|
|
|
- const [codeMirrorRef, setCodeMirrorRef] = useState<HTMLDivElement | null>(null);
|
|
|
|
|
const { t } = useTranslation('');
|
|
const { t } = useTranslation('');
|
|
|
|
|
|
|
|
const { pageContainer } = props;
|
|
const { pageContainer } = props;
|
|
|
|
|
+ const { request, origin, latest } = pageContainer.state.revisionsOnConflict;
|
|
|
|
|
|
|
|
|
|
|
|
|
const onCancel = () => {
|
|
const onCancel = () => {
|
|
@@ -54,8 +62,8 @@ export const ConflictDiffModal: FC<ConflictDiffModalProps> = (props) => {
|
|
|
await pageContainer.save(resolvedRevision);
|
|
await pageContainer.save(resolvedRevision);
|
|
|
window.location.href = pageContainer.state.path || '/';
|
|
window.location.href = pageContainer.state.path || '/';
|
|
|
}
|
|
}
|
|
|
- catch (e) {
|
|
|
|
|
- console.log(e);
|
|
|
|
|
|
|
+ catch (error) {
|
|
|
|
|
+ toastError(error);
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
@@ -70,57 +78,94 @@ export const ConflictDiffModal: FC<ConflictDiffModalProps> = (props) => {
|
|
|
&& (
|
|
&& (
|
|
|
<div className="row mx-2">
|
|
<div className="row mx-2">
|
|
|
<div className="col-12 text-center mt-2 mb-4">
|
|
<div className="col-12 text-center mt-2 mb-4">
|
|
|
- <h2>{`Selected revision: ${val}`}</h2>
|
|
|
|
|
|
|
+ <h2 className="font-weight-bold">{t('modal_resolve_conflict.resolve_conflict_message')}</h2>
|
|
|
</div>
|
|
</div>
|
|
|
<div className="col-4 border border-dark">
|
|
<div className="col-4 border border-dark">
|
|
|
- <h3 className="font-weight-bold">Previous Revision</h3>
|
|
|
|
|
|
|
+ <h3 className="font-weight-bold my-2">Request Revision</h3>
|
|
|
|
|
+ <div className="d-flex">
|
|
|
|
|
+ <p>{format(parseISO(request.createdAt), 'yyyy/MM/dd HH:mm:ss')}</p>
|
|
|
|
|
+ <img className="border-rounded" src={request.userImgPath} />
|
|
|
|
|
+ </div>
|
|
|
<CodeMirror
|
|
<CodeMirror
|
|
|
value={pageContainer.state.revisionsOnConflict?.request.revisionBody}
|
|
value={pageContainer.state.revisionsOnConflict?.request.revisionBody}
|
|
|
- onChange={() => {
|
|
|
|
|
|
|
+ options={{
|
|
|
|
|
+ mode: 'htmlmixed',
|
|
|
|
|
+ lineNumbers: true,
|
|
|
|
|
+ tabSize: 2,
|
|
|
|
|
+ indentUnit: 2,
|
|
|
|
|
+ matchBrackets: true,
|
|
|
|
|
+ autoCloseBrackets: true,
|
|
|
}}
|
|
}}
|
|
|
/>
|
|
/>
|
|
|
- <Button
|
|
|
|
|
- outline
|
|
|
|
|
- color="secondary"
|
|
|
|
|
- size="sm"
|
|
|
|
|
- className="btn-comment-reply"
|
|
|
|
|
- onClick={() => { SetResolvedRevision(pageContainer.state.revisionsOnConflict?.request.revisionBody) }}
|
|
|
|
|
- >
|
|
|
|
|
- <i className="icon-fw icon-action-undo"></i>Use previous
|
|
|
|
|
- </Button>
|
|
|
|
|
|
|
+ <div className="text-center my-4">
|
|
|
|
|
+ <button
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ className="btn btn-primary"
|
|
|
|
|
+ onClick={() => { SetResolvedRevision(pageContainer.state.revisionsOnConflict?.request.revisionBody) }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <i className="icon-fw icon-action-redo"></i>
|
|
|
|
|
+ {t('modal_resolve_conflict.resolve_and_save')}
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
<div className="col-4 border border-dark">
|
|
<div className="col-4 border border-dark">
|
|
|
- <h3 className="font-weight-bold">Original Revision</h3>
|
|
|
|
|
|
|
+ <h3 className="font-weight-bold my-2">Original Revision</h3>
|
|
|
|
|
+ <div className="d-flex">
|
|
|
|
|
+ <p>{format(parseISO(origin.createdAt), 'yyyy/MM/dd HH:mm:ss')}</p>
|
|
|
|
|
+ <img className="border-rounded" src={origin.userImgPath} />
|
|
|
|
|
+ </div>
|
|
|
<CodeMirror
|
|
<CodeMirror
|
|
|
value={pageContainer.state.revisionsOnConflict?.origin.revisionBody}
|
|
value={pageContainer.state.revisionsOnConflict?.origin.revisionBody}
|
|
|
|
|
+ options={{
|
|
|
|
|
+ mode: 'htmlmixed',
|
|
|
|
|
+ lineNumbers: true,
|
|
|
|
|
+ tabSize: 2,
|
|
|
|
|
+ indentUnit: 2,
|
|
|
|
|
+ matchBrackets: true,
|
|
|
|
|
+ autoCloseBrackets: true,
|
|
|
|
|
+ }}
|
|
|
/>
|
|
/>
|
|
|
- <Button
|
|
|
|
|
- outline
|
|
|
|
|
- color="secondary"
|
|
|
|
|
- size="sm"
|
|
|
|
|
- className="btn-comment-reply"
|
|
|
|
|
- onClick={() => { SetResolvedRevision(pageContainer.state.revisionsOnConflict?.origin.revisionBody) }}
|
|
|
|
|
- >
|
|
|
|
|
- <i className="icon-fw icon-action-undo"></i>Use Original
|
|
|
|
|
- </Button>
|
|
|
|
|
|
|
+ <div className="text-center my-4">
|
|
|
|
|
+ <button
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ className="btn btn-primary"
|
|
|
|
|
+ onClick={() => { SetResolvedRevision(pageContainer.state.revisionsOnConflict?.origin.revisionBody) }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <i className="icon-fw icon-action-redo"></i>
|
|
|
|
|
+ {t('modal_resolve_conflict.resolve_and_save')}
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
<div className="col-4 border border-dark">
|
|
<div className="col-4 border border-dark">
|
|
|
- <h3 className="font-weight-bold">Latest Revision</h3>
|
|
|
|
|
|
|
+ <h3 className="font-weight-bold my-2">Latest Revision</h3>
|
|
|
|
|
+ <div className="d-flex">
|
|
|
|
|
+ <p>{format(parseISO(latest.createdAt), 'yyyy/MM/dd HH:mm:ss')}</p>
|
|
|
|
|
+ <img className="border-rounded" src={latest.userImgPath} />
|
|
|
|
|
+ </div>
|
|
|
<CodeMirror
|
|
<CodeMirror
|
|
|
value={pageContainer.state.revisionsOnConflict?.latest.revisionBody}
|
|
value={pageContainer.state.revisionsOnConflict?.latest.revisionBody}
|
|
|
|
|
+ options={{
|
|
|
|
|
+ mode: 'htmlmixed',
|
|
|
|
|
+ lineNumbers: true,
|
|
|
|
|
+ tabSize: 2,
|
|
|
|
|
+ indentUnit: 2,
|
|
|
|
|
+ matchBrackets: true,
|
|
|
|
|
+ autoCloseBrackets: true,
|
|
|
|
|
+ }}
|
|
|
/>
|
|
/>
|
|
|
- <Button
|
|
|
|
|
- outline
|
|
|
|
|
- color="secondary"
|
|
|
|
|
- size="sm"
|
|
|
|
|
- className="btn-comment-reply"
|
|
|
|
|
- onClick={() => { SetResolvedRevision(pageContainer.state.revisionsOnConflict?.latest.revisionBody) }}
|
|
|
|
|
- >
|
|
|
|
|
- <i className="icon-fw icon-action-undo"></i>Use Latest
|
|
|
|
|
- </Button>
|
|
|
|
|
|
|
+ <div className="text-center my-4">
|
|
|
|
|
+ <button
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ className="btn btn-primary"
|
|
|
|
|
+ onClick={() => { SetResolvedRevision(pageContainer.state.revisionsOnConflict?.latest.revisionBody) }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <i className="icon-fw icon-action-redo"></i>
|
|
|
|
|
+ {t('modal_resolve_conflict.resolve_and_save')}
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
<div className="col-12 border border-dark">
|
|
<div className="col-12 border border-dark">
|
|
|
- <h3>Selected Revision</h3>
|
|
|
|
|
|
|
+ <h3 className="font-weight-bold my-2">Selected Revision</h3>
|
|
|
<CodeMirror
|
|
<CodeMirror
|
|
|
value={resolvedRevision}
|
|
value={resolvedRevision}
|
|
|
/>
|
|
/>
|
|
@@ -135,14 +180,14 @@ export const ConflictDiffModal: FC<ConflictDiffModalProps> = (props) => {
|
|
|
type="button"
|
|
type="button"
|
|
|
className="btn btn-outline-secondary"
|
|
className="btn btn-outline-secondary"
|
|
|
onClick={onCancel}
|
|
onClick={onCancel}
|
|
|
- disabled={resolvedRevision === INITIAL_TEXT}
|
|
|
|
|
>
|
|
>
|
|
|
{t('Cancel')}
|
|
{t('Cancel')}
|
|
|
</button>
|
|
</button>
|
|
|
<button
|
|
<button
|
|
|
type="button"
|
|
type="button"
|
|
|
- className="btn btn-outline-primary ml-3"
|
|
|
|
|
|
|
+ className="btn btn-primary ml-3"
|
|
|
onClick={onResolveConflict}
|
|
onClick={onResolveConflict}
|
|
|
|
|
+ disabled={resolvedRevision === INITIAL_TEXT}
|
|
|
>
|
|
>
|
|
|
{t('modal_resolve_conflict.resolve_and_save')}
|
|
{t('modal_resolve_conflict.resolve_and_save')}
|
|
|
</button>
|
|
</button>
|