fix: ensure draft changes (#3306)
This commit is contained in:
@ -219,10 +219,15 @@ export function discardDraft() {
|
||||
return { type: DRAFT_DISCARD };
|
||||
}
|
||||
|
||||
export function changeDraftField(field: string, value: string, metadata: Record<string, unknown>) {
|
||||
export function changeDraftField(
|
||||
field: string,
|
||||
value: string,
|
||||
metadata: Record<string, unknown>,
|
||||
entries: EntryMap[],
|
||||
) {
|
||||
return {
|
||||
type: DRAFT_CHANGE_FIELD,
|
||||
payload: { field, value, metadata },
|
||||
payload: { field, value, metadata, entries },
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -227,6 +227,11 @@ export class Editor extends React.Component {
|
||||
if (entry) this.props.createDraftFromEntry(entry, metadata);
|
||||
};
|
||||
|
||||
handleChangeDraftField = (field, value, metadata) => {
|
||||
const entries = [this.props.unPublishedEntry, this.props.publishedEntry].filter(Boolean);
|
||||
this.props.changeDraftField(field, value, metadata, entries);
|
||||
};
|
||||
|
||||
handleChangeStatus = newStatusName => {
|
||||
const {
|
||||
entryDraft,
|
||||
@ -378,7 +383,6 @@ export class Editor extends React.Component {
|
||||
entryDraft,
|
||||
fields,
|
||||
collection,
|
||||
changeDraftField,
|
||||
changeDraftFieldValidation,
|
||||
user,
|
||||
hasChanged,
|
||||
@ -421,7 +425,7 @@ export class Editor extends React.Component {
|
||||
fields={fields}
|
||||
fieldsMetaData={entryDraft.get('fieldsMetaData')}
|
||||
fieldsErrors={entryDraft.get('fieldsErrors')}
|
||||
onChange={changeDraftField}
|
||||
onChange={this.handleChangeDraftField}
|
||||
onValidate={changeDraftFieldValidation}
|
||||
onPersist={this.handlePersistEntry}
|
||||
onDelete={this.handleDeleteEntry}
|
||||
@ -463,8 +467,9 @@ function mapStateToProps(state, ownProps) {
|
||||
const useOpenAuthoring = globalUI.get('useOpenAuthoring', false);
|
||||
const isModification = entryDraft.getIn(['entry', 'isModification']);
|
||||
const collectionEntriesLoaded = !!entries.getIn(['pages', collectionName]);
|
||||
const unpublishedEntry = selectUnpublishedEntry(state, collectionName, slug);
|
||||
const currentStatus = unpublishedEntry && unpublishedEntry.getIn(['metaData', 'status']);
|
||||
const unPublishedEntry = selectUnpublishedEntry(state, collectionName, slug);
|
||||
const publishedEntry = selectEntry(state, collectionName, slug);
|
||||
const currentStatus = unPublishedEntry && unPublishedEntry.getIn(['metaData', 'status']);
|
||||
const deployPreview = selectDeployPreview(state, collectionName, slug);
|
||||
const localBackup = entryDraft.get('localBackup');
|
||||
const draftKey = entryDraft.get('key');
|
||||
@ -488,6 +493,8 @@ function mapStateToProps(state, ownProps) {
|
||||
deployPreview,
|
||||
localBackup,
|
||||
draftKey,
|
||||
publishedEntry,
|
||||
unPublishedEntry,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -179,14 +179,14 @@ describe('Frontmatter', () => {
|
||||
'title: YAML',
|
||||
'---',
|
||||
'Some content',
|
||||
'On another line\n',
|
||||
'On another line',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
|
||||
it('should stringify YAML with missing body', () => {
|
||||
expect(FrontmatterInfer.toFile({ tags: ['front matter', 'yaml'], title: 'YAML' })).toEqual(
|
||||
['---', 'tags:', ' - front matter', ' - yaml', 'title: YAML', '---', '', ''].join('\n'),
|
||||
['---', 'tags:', ' - front matter', ' - yaml', 'title: YAML', '---', ''].join('\n'),
|
||||
);
|
||||
});
|
||||
|
||||
@ -206,7 +206,7 @@ describe('Frontmatter', () => {
|
||||
'title: YAML',
|
||||
'---',
|
||||
'Some content',
|
||||
'On another line\n',
|
||||
'On another line',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
@ -227,7 +227,7 @@ describe('Frontmatter', () => {
|
||||
'title: YAML',
|
||||
'~~~',
|
||||
'Some content',
|
||||
'On another line\n',
|
||||
'On another line',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
@ -248,7 +248,7 @@ describe('Frontmatter', () => {
|
||||
'title: YAML',
|
||||
'^^^',
|
||||
'Some content',
|
||||
'On another line\n',
|
||||
'On another line',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
@ -267,7 +267,7 @@ describe('Frontmatter', () => {
|
||||
'title = "TOML"',
|
||||
'+++',
|
||||
'Some content',
|
||||
'On another line\n',
|
||||
'On another line',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
@ -286,7 +286,7 @@ describe('Frontmatter', () => {
|
||||
'title = "TOML"',
|
||||
'~~~',
|
||||
'Some content',
|
||||
'On another line\n',
|
||||
'On another line',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
@ -308,7 +308,7 @@ describe('Frontmatter', () => {
|
||||
' "title": "JSON"',
|
||||
'}',
|
||||
'Some content',
|
||||
'On another line\n',
|
||||
'On another line',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
@ -330,8 +330,24 @@ describe('Frontmatter', () => {
|
||||
' "title": "JSON"',
|
||||
'~~~',
|
||||
'Some content',
|
||||
'On another line\n',
|
||||
'On another line',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
|
||||
it('should trim last line break if added by grey-matter', () => {
|
||||
expect(
|
||||
frontmatterYAML().toFile({
|
||||
body: 'noLineBreak',
|
||||
}),
|
||||
).toEqual('noLineBreak');
|
||||
});
|
||||
|
||||
it('should not trim last line break if not added by grey-matter', () => {
|
||||
expect(
|
||||
frontmatterYAML().toFile({
|
||||
body: 'withLineBreak\n',
|
||||
}),
|
||||
).toEqual('withLineBreak\n');
|
||||
});
|
||||
});
|
||||
|
@ -70,9 +70,11 @@ class FrontmatterFormatter {
|
||||
const format = this.format || inferFrontmatterFormat(content);
|
||||
if (this.customDelimiter) this.format.delimiters = this.customDelimiter;
|
||||
const result = matter(content, { engines: parsers, ...format });
|
||||
// in the absent of a body when serializing an entry we use an empty one
|
||||
// when calling `toFile`, so we don't want to add it when parsing.
|
||||
return {
|
||||
...result.data,
|
||||
body: result.content,
|
||||
...(result.content.trim() && { body: result.content }),
|
||||
};
|
||||
}
|
||||
|
||||
@ -83,8 +85,13 @@ class FrontmatterFormatter {
|
||||
const format = this.format || getFormatOpts('yaml');
|
||||
if (this.customDelimiter) this.format.delimiters = this.customDelimiter;
|
||||
|
||||
// gray-matter always adds a line break at the end which trips our
|
||||
// change detection logic
|
||||
// https://github.com/jonschlinkert/gray-matter/issues/96
|
||||
const trimLastLineBreak = body.slice(-1) !== '\n' ? true : false;
|
||||
// `sortedKeys` is not recognized by gray-matter, so it gets passed through to the parser
|
||||
return matter.stringify(body, meta, { engines: parsers, sortedKeys, ...format });
|
||||
const file = matter.stringify(body, meta, { engines: parsers, sortedKeys, ...format });
|
||||
return trimLastLineBreak && file.slice(-1) === '\n' ? file.substring(0, file.length - 1) : file;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,13 +88,14 @@ const entryDraftReducer = (state = Map(), action) => {
|
||||
});
|
||||
return state.set('localBackup', newState);
|
||||
}
|
||||
case DRAFT_CHANGE_FIELD:
|
||||
case DRAFT_CHANGE_FIELD: {
|
||||
return state.withMutations(state => {
|
||||
state.setIn(['entry', 'data', action.payload.field], action.payload.value);
|
||||
state.mergeDeepIn(['fieldsMetaData'], fromJS(action.payload.metadata));
|
||||
state.set('hasChanged', true);
|
||||
const newData = state.getIn(['entry', 'data']);
|
||||
state.set('hasChanged', !action.payload.entries.some(e => newData.equals(e.get('data'))));
|
||||
});
|
||||
|
||||
}
|
||||
case DRAFT_VALIDATION_ERRORS:
|
||||
if (action.payload.errors.length === 0) {
|
||||
return state.deleteIn(['fieldsErrors', action.payload.uniquefieldId]);
|
||||
|
Reference in New Issue
Block a user