fix: Improved handling of simultaneous edits
This commit is contained in:
@ -128,22 +128,6 @@ class SocketProvider extends React.Component<Props> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Move this to the document scene once data loading
|
||||
// has been refactored to be friendlier there.
|
||||
if (
|
||||
auth.user &&
|
||||
documentId === ui.activeDocumentId &&
|
||||
document.updatedBy.id !== auth.user.id
|
||||
) {
|
||||
ui.showToast(`Document updated by ${document.updatedBy.name}`, {
|
||||
timeout: 30 * 1000,
|
||||
action: {
|
||||
text: 'Refresh',
|
||||
onClick: () => window.location.reload(),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,12 @@ import Revision from 'models/Revision';
|
||||
import User from 'models/User';
|
||||
import DocumentsStore from 'stores/DocumentsStore';
|
||||
|
||||
type SaveOptions = { publish?: boolean, done?: boolean, autosave?: boolean };
|
||||
type SaveOptions = {
|
||||
publish?: boolean,
|
||||
done?: boolean,
|
||||
autosave?: boolean,
|
||||
lastRevision?: number,
|
||||
};
|
||||
|
||||
export default class Document extends BaseModel {
|
||||
@observable isSaving: boolean = false;
|
||||
@ -185,7 +190,7 @@ export default class Document extends BaseModel {
|
||||
id: this.id,
|
||||
title: this.title,
|
||||
text: this.text,
|
||||
lastRevision: this.revision,
|
||||
lastRevision: options.lastRevision,
|
||||
...options,
|
||||
});
|
||||
} finally {
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
documentMoveUrl,
|
||||
documentHistoryUrl,
|
||||
documentEditUrl,
|
||||
documentUrl,
|
||||
} from 'utils/routeHelpers';
|
||||
import { emojiToUrl } from 'utils/emoji';
|
||||
|
||||
@ -74,11 +75,13 @@ class DocumentScene extends React.Component<Props> {
|
||||
@observable isDirty: boolean = false;
|
||||
@observable isEmpty: boolean = true;
|
||||
@observable moveModalOpen: boolean = false;
|
||||
@observable lastRevision: number;
|
||||
@observable title: string;
|
||||
|
||||
constructor(props) {
|
||||
super();
|
||||
this.title = props.document.title;
|
||||
this.lastRevision = props.document.revision;
|
||||
this.loadEditor();
|
||||
}
|
||||
|
||||
@ -86,6 +89,29 @@ class DocumentScene extends React.Component<Props> {
|
||||
this.updateIsDirty();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { auth, document } = this.props;
|
||||
|
||||
if (this.props.readOnly) {
|
||||
this.lastRevision = document.revision;
|
||||
} else if (prevProps.document.revision !== this.lastRevision) {
|
||||
if (auth.user && document.updatedBy.id !== auth.user.id) {
|
||||
this.props.ui.showToast(
|
||||
`Document updated by ${document.updatedBy.name}`,
|
||||
{
|
||||
timeout: 30 * 1000,
|
||||
action: {
|
||||
text: 'Reload',
|
||||
onClick: () => {
|
||||
window.location.href = documentUrl(document);
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keydown('m')
|
||||
goToMove(ev) {
|
||||
if (!this.props.readOnly) return;
|
||||
@ -174,7 +200,11 @@ class DocumentScene extends React.Component<Props> {
|
||||
handleOpenMoveModal = () => (this.moveModalOpen = true);
|
||||
|
||||
onSave = async (
|
||||
options: { done?: boolean, publish?: boolean, autosave?: boolean } = {}
|
||||
options: {
|
||||
done?: boolean,
|
||||
publish?: boolean,
|
||||
autosave?: boolean,
|
||||
} = {}
|
||||
) => {
|
||||
const { document } = this.props;
|
||||
|
||||
@ -202,10 +232,14 @@ class DocumentScene extends React.Component<Props> {
|
||||
let isNew = !document.id;
|
||||
this.isSaving = true;
|
||||
this.isPublishing = !!options.publish;
|
||||
const savedDocument = await document.save(options);
|
||||
|
||||
try {
|
||||
const savedDocument = await document.save({
|
||||
...options,
|
||||
lastRevision: this.lastRevision,
|
||||
});
|
||||
this.isDirty = false;
|
||||
this.isSaving = false;
|
||||
this.isPublishing = false;
|
||||
this.lastRevision = savedDocument.revision;
|
||||
|
||||
if (options.done) {
|
||||
this.props.history.push(savedDocument.url);
|
||||
@ -214,6 +248,12 @@ class DocumentScene extends React.Component<Props> {
|
||||
this.props.history.push(documentEditUrl(savedDocument));
|
||||
this.props.ui.setActiveDocument(savedDocument);
|
||||
}
|
||||
} catch (err) {
|
||||
this.props.ui.showToast(err.message);
|
||||
} finally {
|
||||
this.isSaving = false;
|
||||
this.isPublishing = false;
|
||||
}
|
||||
};
|
||||
|
||||
autosave = debounce(() => {
|
||||
|
Reference in New Issue
Block a user