fix(netlify-cms-core): avoid partially loaded collection list (#1964)

This commit is contained in:
Bartholomew 2018-12-19 21:28:45 +01:00 committed by Shawn Erquhart
parent 42d6478117
commit cedcbf89a5
5 changed files with 38 additions and 20 deletions

View File

@ -445,6 +445,7 @@ export function deleteUnpublishedEntry(collection, slug) {
export function publishUnpublishedEntry(collection, slug) { export function publishUnpublishedEntry(collection, slug) {
return (dispatch, getState) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const collections = state.collections;
const backend = currentBackend(state.config); const backend = currentBackend(state.config);
const transactionID = uuid(); const transactionID = uuid();
dispatch(unpublishedEntryPublishRequest(collection, slug, transactionID)); dispatch(unpublishedEntryPublishRequest(collection, slug, transactionID));
@ -459,6 +460,7 @@ export function publishUnpublishedEntry(collection, slug) {
}), }),
); );
dispatch(unpublishedEntryPublished(collection, slug, transactionID)); dispatch(unpublishedEntryPublished(collection, slug, transactionID));
dispatch(loadEntry(collections.get(collection), slug));
}) })
.catch(error => { .catch(error => {
dispatch( dispatch(

View File

@ -25,15 +25,15 @@ class EntriesCollection extends React.Component {
}; };
componentDidMount() { componentDidMount() {
const { collection, loadEntries } = this.props; const { collection, entriesLoaded, loadEntries } = this.props;
if (collection) { if (collection && !entriesLoaded) {
loadEntries(collection); loadEntries(collection);
} }
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
const { collection, loadEntries } = this.props; const { collection, entriesLoaded, loadEntries } = this.props;
if (collection !== prevProps.collection) { if (collection !== prevProps.collection && !entriesLoaded) {
loadEntries(collection); loadEntries(collection);
} }
} }
@ -68,12 +68,13 @@ function mapStateToProps(state, ownProps) {
const page = state.entries.getIn(['pages', collection.get('name'), 'page']); const page = state.entries.getIn(['pages', collection.get('name'), 'page']);
const entries = selectEntries(state, collection.get('name')); const entries = selectEntries(state, collection.get('name'));
const entriesLoaded = !!state.entries.getIn(['pages', collection.get('name')]);
const isFetching = state.entries.getIn(['pages', collection.get('name'), 'isFetching'], false); const isFetching = state.entries.getIn(['pages', collection.get('name'), 'isFetching'], false);
const rawCursor = selectCollectionEntriesCursor(state.cursors, collection.get('name')); const rawCursor = selectCollectionEntriesCursor(state.cursors, collection.get('name'));
const cursor = Cursor.create(rawCursor).clearData(); const cursor = Cursor.create(rawCursor).clearData();
return { publicFolder, collection, page, entries, isFetching, viewStyle, cursor }; return { publicFolder, collection, page, entries, entriesLoaded, isFetching, viewStyle, cursor };
} }
const mapDispatchToProps = { const mapDispatchToProps = {

View File

@ -227,15 +227,7 @@ class Editor extends React.Component {
handlePublishEntry = async (opts = {}) => { handlePublishEntry = async (opts = {}) => {
const { createNew = false } = opts; const { createNew = false } = opts;
const { const { publishUnpublishedEntry, entryDraft, collection, slug, currentStatus, t } = this.props;
publishUnpublishedEntry,
entryDraft,
collection,
slug,
currentStatus,
loadEntry,
t,
} = this.props;
if (currentStatus !== status.last()) { if (currentStatus !== status.last()) {
window.alert(t('editor.editor.onPublishingNotReady')); window.alert(t('editor.editor.onPublishingNotReady'));
return; return;
@ -250,8 +242,6 @@ class Editor extends React.Component {
if (createNew) { if (createNew) {
navigateToNewEntry(collection.get('name')); navigateToNewEntry(collection.get('name'));
} else {
loadEntry(collection, slug);
} }
}; };

View File

@ -42,4 +42,23 @@ describe('entries', () => {
), ),
); );
}); });
it('should handle loaded entry', () => {
const entry = { slug: 'a', path: '' };
expect(reducer(initialState, actions.entryLoaded(Map({ name: 'posts' }), entry))).toEqual(
OrderedMap(
fromJS({
posts: { name: 'posts' },
entities: {
'posts.a': { slug: 'a', path: '' },
},
pages: {
posts: {
ids: ['a'],
},
},
}),
),
);
});
}); });

View File

@ -15,6 +15,7 @@ let collection;
let loadedEntries; let loadedEntries;
let append; let append;
let page; let page;
let slug;
const entries = (state = Map({ entities: Map(), pages: Map() }), action) => { const entries = (state = Map({ entities: Map(), pages: Map() }), action) => {
switch (action.type) { switch (action.type) {
@ -25,10 +26,15 @@ const entries = (state = Map({ entities: Map(), pages: Map() }), action) => {
); );
case ENTRY_SUCCESS: case ENTRY_SUCCESS:
return state.setIn( collection = action.payload.collection;
['entities', `${action.payload.collection}.${action.payload.entry.slug}`], slug = action.payload.entry.slug;
fromJS(action.payload.entry), return state.withMutations(map => {
); map.setIn(['entities', `${collection}.${slug}`], fromJS(action.payload.entry));
const ids = map.getIn(['pages', collection, 'ids'], List());
if (!ids.includes(slug)) {
map.setIn(['pages', collection, 'ids'], ids.unshift(slug));
}
});
case ENTRIES_REQUEST: case ENTRIES_REQUEST:
return state.setIn(['pages', action.payload.collection, 'isFetching'], true); return state.setIn(['pages', action.payload.collection, 'isFetching'], true);