Move isDirty to view concern. Document model is not updated until save
This commit is contained in:
@ -11,7 +11,6 @@ import type { NavigationNode } from 'types';
|
|||||||
|
|
||||||
class Collection extends BaseModel {
|
class Collection extends BaseModel {
|
||||||
isSaving: boolean = false;
|
isSaving: boolean = false;
|
||||||
hasPendingChanges: boolean = false;
|
|
||||||
ui: UiStore;
|
ui: UiStore;
|
||||||
data: Object;
|
data: Object;
|
||||||
|
|
||||||
@ -109,7 +108,6 @@ class Collection extends BaseModel {
|
|||||||
runInAction('Collection#save', () => {
|
runInAction('Collection#save', () => {
|
||||||
invariant(res && res.data, 'Data should be available');
|
invariant(res && res.data, 'Data should be available');
|
||||||
this.updateData(res.data);
|
this.updateData(res.data);
|
||||||
this.hasPendingChanges = false;
|
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.ui.showToast('Collection failed saving');
|
this.ui.showToast('Collection failed saving');
|
||||||
|
@ -15,7 +15,6 @@ type SaveOptions = { publish?: boolean, done?: boolean, autosave?: boolean };
|
|||||||
|
|
||||||
class Document extends BaseModel {
|
class Document extends BaseModel {
|
||||||
isSaving: boolean = false;
|
isSaving: boolean = false;
|
||||||
hasPendingChanges: boolean = false;
|
|
||||||
ui: *;
|
ui: *;
|
||||||
store: *;
|
store: *;
|
||||||
|
|
||||||
@ -209,7 +208,6 @@ class Document extends BaseModel {
|
|||||||
runInAction('Document#save', () => {
|
runInAction('Document#save', () => {
|
||||||
invariant(res && res.data, 'Data should be available');
|
invariant(res && res.data, 'Data should be available');
|
||||||
this.updateData(res.data);
|
this.updateData(res.data);
|
||||||
this.hasPendingChanges = false;
|
|
||||||
|
|
||||||
if (isCreating) {
|
if (isCreating) {
|
||||||
this.emit('documents.create', this);
|
this.emit('documents.create', this);
|
||||||
@ -288,13 +286,12 @@ class Document extends BaseModel {
|
|||||||
a.click();
|
a.click();
|
||||||
};
|
};
|
||||||
|
|
||||||
updateData(data: Object = {}, dirty: boolean = false) {
|
updateData(data: Object = {}) {
|
||||||
if (data.text) {
|
if (data.text) {
|
||||||
const { title, emoji } = parseTitle(data.text);
|
const { title, emoji } = parseTitle(data.text);
|
||||||
data.title = title;
|
data.title = title;
|
||||||
data.emoji = emoji;
|
data.emoji = emoji;
|
||||||
}
|
}
|
||||||
if (dirty) this.hasPendingChanges = true;
|
|
||||||
extendObservable(this, data);
|
extendObservable(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +70,7 @@ class DocumentScene extends React.Component<Props> {
|
|||||||
@observable isUploading = false;
|
@observable isUploading = false;
|
||||||
@observable isSaving = false;
|
@observable isSaving = false;
|
||||||
@observable isPublishing = false;
|
@observable isPublishing = false;
|
||||||
|
@observable isDirty = false;
|
||||||
@observable notFound = false;
|
@observable notFound = false;
|
||||||
@observable moveModalOpen: boolean = false;
|
@observable moveModalOpen: boolean = false;
|
||||||
|
|
||||||
@ -117,6 +118,7 @@ class DocumentScene extends React.Component<Props> {
|
|||||||
props.match.params.documentSlug,
|
props.match.params.documentSlug,
|
||||||
{ shareId }
|
{ shareId }
|
||||||
);
|
);
|
||||||
|
this.isDirty = false;
|
||||||
|
|
||||||
const document = this.document;
|
const document = this.document;
|
||||||
|
|
||||||
@ -167,7 +169,7 @@ class DocumentScene extends React.Component<Props> {
|
|||||||
if (!document) return;
|
if (!document) return;
|
||||||
|
|
||||||
// get the latest version of the editor text value
|
// get the latest version of the editor text value
|
||||||
const text = this.getEditorText();
|
const text = this.getEditorText ? this.getEditorText() : document.text;
|
||||||
|
|
||||||
// prevent autosave if nothing has changed
|
// prevent autosave if nothing has changed
|
||||||
if (options.autosave && document.text.trim() === text.trim()) return;
|
if (options.autosave && document.text.trim() === text.trim()) return;
|
||||||
@ -183,6 +185,7 @@ class DocumentScene extends React.Component<Props> {
|
|||||||
this.isSaving = true;
|
this.isSaving = true;
|
||||||
this.isPublishing = !!options.publish;
|
this.isPublishing = !!options.publish;
|
||||||
document = await document.save(options);
|
document = await document.save(options);
|
||||||
|
this.isDirty = false;
|
||||||
this.isSaving = false;
|
this.isSaving = false;
|
||||||
this.isPublishing = false;
|
this.isPublishing = false;
|
||||||
|
|
||||||
@ -199,6 +202,10 @@ class DocumentScene extends React.Component<Props> {
|
|||||||
this.onSave({ done: false, autosave: true });
|
this.onSave({ done: false, autosave: true });
|
||||||
}, AUTOSAVE_INTERVAL);
|
}, AUTOSAVE_INTERVAL);
|
||||||
|
|
||||||
|
updateIsDirty = debounce(() => {
|
||||||
|
this.isDirty = this.getEditorText().trim() !== this.document.text.trim();
|
||||||
|
}, 500);
|
||||||
|
|
||||||
onImageUploadStart = () => {
|
onImageUploadStart = () => {
|
||||||
this.isUploading = true;
|
this.isUploading = true;
|
||||||
};
|
};
|
||||||
@ -209,6 +216,7 @@ class DocumentScene extends React.Component<Props> {
|
|||||||
|
|
||||||
onChange = getEditorText => {
|
onChange = getEditorText => {
|
||||||
this.getEditorText = getEditorText;
|
this.getEditorText = getEditorText;
|
||||||
|
this.updateIsDirty();
|
||||||
this.autosave();
|
this.autosave();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -312,7 +320,7 @@ class DocumentScene extends React.Component<Props> {
|
|||||||
{this.isEditing && (
|
{this.isEditing && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Prompt
|
<Prompt
|
||||||
when={document.hasPendingChanges}
|
when={this.isDirty}
|
||||||
message={DISCARD_CHANGES}
|
message={DISCARD_CHANGES}
|
||||||
/>
|
/>
|
||||||
<Prompt when={this.isUploading} message={UPLOADING_WARNING} />
|
<Prompt when={this.isUploading} message={UPLOADING_WARNING} />
|
||||||
@ -322,6 +330,7 @@ class DocumentScene extends React.Component<Props> {
|
|||||||
<Header
|
<Header
|
||||||
document={document}
|
document={document}
|
||||||
isDraft={document.isDraft}
|
isDraft={document.isDraft}
|
||||||
|
isDirty={this.isDirty}
|
||||||
isEditing={this.isEditing}
|
isEditing={this.isEditing}
|
||||||
isSaving={this.isSaving}
|
isSaving={this.isSaving}
|
||||||
isPublishing={this.isPublishing}
|
isPublishing={this.isPublishing}
|
||||||
|
@ -20,6 +20,7 @@ import { Action, Separator } from 'components/Actions';
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
document: Document,
|
document: Document,
|
||||||
|
isDirty: boolean,
|
||||||
isDraft: boolean,
|
isDraft: boolean,
|
||||||
isEditing: boolean,
|
isEditing: boolean,
|
||||||
isSaving: boolean,
|
isSaving: boolean,
|
||||||
@ -87,6 +88,7 @@ class Header extends React.Component<Props> {
|
|||||||
document,
|
document,
|
||||||
isEditing,
|
isEditing,
|
||||||
isDraft,
|
isDraft,
|
||||||
|
isDirty,
|
||||||
isPublishing,
|
isPublishing,
|
||||||
isSaving,
|
isSaving,
|
||||||
savingIsDisabled,
|
savingIsDisabled,
|
||||||
@ -161,13 +163,6 @@ class Header extends React.Component<Props> {
|
|||||||
<Link onClick={this.handleEdit}>Edit</Link>
|
<Link onClick={this.handleEdit}>Edit</Link>
|
||||||
</Action>
|
</Action>
|
||||||
)}
|
)}
|
||||||
{isEditing &&
|
|
||||||
!isSaving &&
|
|
||||||
document.hasPendingChanges && (
|
|
||||||
<Action>
|
|
||||||
<Link onClick={this.props.onDiscard}>Discard</Link>
|
|
||||||
</Action>
|
|
||||||
)}
|
|
||||||
{!isEditing && (
|
{!isEditing && (
|
||||||
<Action>
|
<Action>
|
||||||
<DocumentMenu document={document} showPrint />
|
<DocumentMenu document={document} showPrint />
|
||||||
|
Reference in New Issue
Block a user