|
@@ -4,9 +4,11 @@ import { Container } from 'unstated';
|
|
|
import * as entities from 'entities';
|
|
import * as entities from 'entities';
|
|
|
import * as toastr from 'toastr';
|
|
import * as toastr from 'toastr';
|
|
|
import { pagePathUtils } from '@growi/core';
|
|
import { pagePathUtils } from '@growi/core';
|
|
|
|
|
+
|
|
|
import loggerFactory from '~/utils/logger';
|
|
import loggerFactory from '~/utils/logger';
|
|
|
-import { toastError } from '../util/apiNotification';
|
|
|
|
|
|
|
+import { EditorMode } from '~/stores/ui';
|
|
|
|
|
|
|
|
|
|
+import { toastError } from '../util/apiNotification';
|
|
|
import {
|
|
import {
|
|
|
DetachCodeBlockInterceptor,
|
|
DetachCodeBlockInterceptor,
|
|
|
RestoreCodeBlockInterceptor,
|
|
RestoreCodeBlockInterceptor,
|
|
@@ -52,9 +54,6 @@ export default class PageContainer extends Container {
|
|
|
path,
|
|
path,
|
|
|
tocHtml: '',
|
|
tocHtml: '',
|
|
|
|
|
|
|
|
- isBookmarked: false,
|
|
|
|
|
- sumOfBookmarks: 0,
|
|
|
|
|
-
|
|
|
|
|
seenUsers: [],
|
|
seenUsers: [],
|
|
|
seenUserIds: [],
|
|
seenUserIds: [],
|
|
|
sumOfSeenUsers: [],
|
|
sumOfSeenUsers: [],
|
|
@@ -86,12 +85,15 @@ export default class PageContainer extends Container {
|
|
|
|
|
|
|
|
// latest(on remote) information
|
|
// latest(on remote) information
|
|
|
remoteRevisionId: revisionId,
|
|
remoteRevisionId: revisionId,
|
|
|
|
|
+ remoteRevisionBody: null,
|
|
|
|
|
+ remoteRevisionUpdateAt: null,
|
|
|
revisionIdHackmdSynced: mainContent.getAttribute('data-page-revision-id-hackmd-synced') || null,
|
|
revisionIdHackmdSynced: mainContent.getAttribute('data-page-revision-id-hackmd-synced') || null,
|
|
|
lastUpdateUsername: mainContent.getAttribute('data-page-last-update-username') || null,
|
|
lastUpdateUsername: mainContent.getAttribute('data-page-last-update-username') || null,
|
|
|
deleteUsername: mainContent.getAttribute('data-page-delete-username') || null,
|
|
deleteUsername: mainContent.getAttribute('data-page-delete-username') || null,
|
|
|
pageIdOnHackmd: mainContent.getAttribute('data-page-id-on-hackmd') || null,
|
|
pageIdOnHackmd: mainContent.getAttribute('data-page-id-on-hackmd') || null,
|
|
|
hasDraftOnHackmd: !!mainContent.getAttribute('data-page-has-draft-on-hackmd'),
|
|
hasDraftOnHackmd: !!mainContent.getAttribute('data-page-has-draft-on-hackmd'),
|
|
|
isHackmdDraftUpdatingInRealtime: false,
|
|
isHackmdDraftUpdatingInRealtime: false,
|
|
|
|
|
+ isConflictDiffModalOpen: false,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// parse creator, lastUpdateUser and revisionAuthor
|
|
// parse creator, lastUpdateUser and revisionAuthor
|
|
@@ -103,6 +105,7 @@ export default class PageContainer extends Container {
|
|
|
}
|
|
}
|
|
|
try {
|
|
try {
|
|
|
this.state.revisionAuthor = JSON.parse(mainContent.getAttribute('data-page-revision-author'));
|
|
this.state.revisionAuthor = JSON.parse(mainContent.getAttribute('data-page-revision-author'));
|
|
|
|
|
+ this.state.lastUpdateUser = JSON.parse(mainContent.getAttribute('data-page-revision-author'));
|
|
|
}
|
|
}
|
|
|
catch (e) {
|
|
catch (e) {
|
|
|
logger.warn('The data of \'data-page-revision-author\' is invalid', e);
|
|
logger.warn('The data of \'data-page-revision-author\' is invalid', e);
|
|
@@ -126,7 +129,6 @@ export default class PageContainer extends Container {
|
|
|
// as it is stored in a separate collection to like and seen user
|
|
// as it is stored in a separate collection to like and seen user
|
|
|
// data so it has a separate api endpoint.
|
|
// data so it has a separate api endpoint.
|
|
|
this.initialPageLoad();
|
|
this.initialPageLoad();
|
|
|
- this.retrieveBookmarkInfo();
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
this.setTocHtml = this.setTocHtml.bind(this);
|
|
this.setTocHtml = this.setTocHtml.bind(this);
|
|
@@ -325,8 +327,12 @@ export default class PageContainer extends Container {
|
|
|
setLatestRemotePageData(s2cMessagePageUpdated) {
|
|
setLatestRemotePageData(s2cMessagePageUpdated) {
|
|
|
const newState = {
|
|
const newState = {
|
|
|
remoteRevisionId: s2cMessagePageUpdated.revisionId,
|
|
remoteRevisionId: s2cMessagePageUpdated.revisionId,
|
|
|
|
|
+ remoteRevisionBody: s2cMessagePageUpdated.revisionBody,
|
|
|
|
|
+ remoteRevisionUpdateAt: s2cMessagePageUpdated.revisionUpdateAt,
|
|
|
revisionIdHackmdSynced: s2cMessagePageUpdated.revisionIdHackmdSynced,
|
|
revisionIdHackmdSynced: s2cMessagePageUpdated.revisionIdHackmdSynced,
|
|
|
|
|
+ // TODO // TODO remove lastUpdateUsername and refactor parts that lastUpdateUsername is used
|
|
|
lastUpdateUsername: s2cMessagePageUpdated.lastUpdateUsername,
|
|
lastUpdateUsername: s2cMessagePageUpdated.lastUpdateUsername,
|
|
|
|
|
+ lastUpdateUser: s2cMessagePageUpdated.remoteLastUpdateUser,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
if (s2cMessagePageUpdated.hasDraftOnHackmd != null) {
|
|
if (s2cMessagePageUpdated.hasDraftOnHackmd != null) {
|
|
@@ -355,6 +361,7 @@ export default class PageContainer extends Container {
|
|
|
revisionId: revision._id,
|
|
revisionId: revision._id,
|
|
|
revisionCreatedAt: new Date(revision.createdAt).getTime() / 1000,
|
|
revisionCreatedAt: new Date(revision.createdAt).getTime() / 1000,
|
|
|
remoteRevisionId: revision._id,
|
|
remoteRevisionId: revision._id,
|
|
|
|
|
+ revisionAuthor: revision.author,
|
|
|
revisionIdHackmdSynced: page.revisionHackmdSynced,
|
|
revisionIdHackmdSynced: page.revisionHackmdSynced,
|
|
|
hasDraftOnHackmd: page.hasDraftOnHackmd,
|
|
hasDraftOnHackmd: page.hasDraftOnHackmd,
|
|
|
markdown: revision.body,
|
|
markdown: revision.body,
|
|
@@ -369,7 +376,7 @@ export default class PageContainer extends Container {
|
|
|
// PageEditor component
|
|
// PageEditor component
|
|
|
const pageEditor = this.appContainer.getComponentInstance('PageEditor');
|
|
const pageEditor = this.appContainer.getComponentInstance('PageEditor');
|
|
|
if (pageEditor != null) {
|
|
if (pageEditor != null) {
|
|
|
- if (editorMode !== 'edit') {
|
|
|
|
|
|
|
+ if (editorMode !== EditorMode.Editor) {
|
|
|
pageEditor.updateEditorValue(newState.markdown);
|
|
pageEditor.updateEditorValue(newState.markdown);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -377,13 +384,36 @@ export default class PageContainer extends Container {
|
|
|
const pageEditorByHackmd = this.appContainer.getComponentInstance('PageEditorByHackmd');
|
|
const pageEditorByHackmd = this.appContainer.getComponentInstance('PageEditorByHackmd');
|
|
|
if (pageEditorByHackmd != null) {
|
|
if (pageEditorByHackmd != null) {
|
|
|
// reset
|
|
// reset
|
|
|
- if (editorMode !== 'hackmd') {
|
|
|
|
|
|
|
+ if (editorMode !== EditorMode.HackMD) {
|
|
|
pageEditorByHackmd.reset();
|
|
pageEditorByHackmd.reset();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // hidden input
|
|
|
|
|
- $('input[name="revision_id"]').val(newState.revisionId);
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * update page meta data
|
|
|
|
|
+ * @param {object} page Page instance
|
|
|
|
|
+ * @param {object} revision Revision instance
|
|
|
|
|
+ * @param {String[]} tags Array of Tag
|
|
|
|
|
+ */
|
|
|
|
|
+ updatePageMetaData(page, revision, tags) {
|
|
|
|
|
+
|
|
|
|
|
+ const newState = {
|
|
|
|
|
+ revisionId: revision._id,
|
|
|
|
|
+ revisionCreatedAt: new Date(revision.createdAt).getTime() / 1000,
|
|
|
|
|
+ remoteRevisionId: revision._id,
|
|
|
|
|
+ revisionAuthor: revision.author,
|
|
|
|
|
+ revisionIdHackmdSynced: page.revisionHackmdSynced,
|
|
|
|
|
+ hasDraftOnHackmd: page.hasDraftOnHackmd,
|
|
|
|
|
+ updatedAt: page.updatedAt,
|
|
|
|
|
+ };
|
|
|
|
|
+ if (tags != null) {
|
|
|
|
|
+ newState.tags = tags;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.setState(newState);
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -395,7 +425,6 @@ export default class PageContainer extends Container {
|
|
|
async save(markdown, editorMode, optionsToSave = {}) {
|
|
async save(markdown, editorMode, optionsToSave = {}) {
|
|
|
const { pageId, path } = this.state;
|
|
const { pageId, path } = this.state;
|
|
|
let { revisionId } = this.state;
|
|
let { revisionId } = this.state;
|
|
|
-
|
|
|
|
|
const options = Object.assign({}, optionsToSave);
|
|
const options = Object.assign({}, optionsToSave);
|
|
|
|
|
|
|
|
if (editorMode === 'hackmd') {
|
|
if (editorMode === 'hackmd') {
|
|
@@ -574,4 +603,21 @@ export default class PageContainer extends Container {
|
|
|
retrieveMyBookmarkList() {
|
|
retrieveMyBookmarkList() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ async resolveConflict(markdown, editorMode) {
|
|
|
|
|
+
|
|
|
|
|
+ const { pageId, remoteRevisionId, path } = this.state;
|
|
|
|
|
+ const editorContainer = this.appContainer.getContainer('EditorContainer');
|
|
|
|
|
+ const options = editorContainer.getCurrentOptionsToSave();
|
|
|
|
|
+ const optionsToSave = Object.assign({}, options);
|
|
|
|
|
+
|
|
|
|
|
+ const res = await this.updatePage(pageId, remoteRevisionId, markdown, optionsToSave);
|
|
|
|
|
+
|
|
|
|
|
+ editorContainer.clearDraft(path);
|
|
|
|
|
+ this.updateStateAfterSave(res.page, res.tags, res.revision, editorMode);
|
|
|
|
|
+
|
|
|
|
|
+ editorContainer.setState({ tags: res.tags });
|
|
|
|
|
+
|
|
|
|
|
+ return res;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
}
|
|
}
|