fix: call createDraftFromEntry after entry is loaded instead in Editor (#3418)
* fix: call createDraftFromEntry after entry is loaded instead in Editor
This commit is contained in:
parent
c9b82551ed
commit
2409323dba
@ -64,7 +64,7 @@ describe('editorialWorkflow actions', () => {
|
|||||||
|
|
||||||
return store.dispatch(actions.loadUnpublishedEntry(collection, slug)).then(() => {
|
return store.dispatch(actions.loadUnpublishedEntry(collection, slug)).then(() => {
|
||||||
const actions = store.getActions();
|
const actions = store.getActions();
|
||||||
expect(actions).toHaveLength(3);
|
expect(actions).toHaveLength(4);
|
||||||
expect(actions[0]).toEqual({
|
expect(actions[0]).toEqual({
|
||||||
type: 'UNPUBLISHED_ENTRY_REQUEST',
|
type: 'UNPUBLISHED_ENTRY_REQUEST',
|
||||||
payload: {
|
payload: {
|
||||||
@ -80,6 +80,12 @@ describe('editorialWorkflow actions', () => {
|
|||||||
entry: { ...entry, mediaFiles: [{ file: { name: 'name' }, id: '1', draft: true }] },
|
entry: { ...entry, mediaFiles: [{ file: { name: 'name' }, id: '1', draft: true }] },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
expect(actions[3]).toEqual({
|
||||||
|
type: 'DRAFT_CREATE_FROM_ENTRY',
|
||||||
|
payload: {
|
||||||
|
entry,
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -111,7 +117,7 @@ describe('editorialWorkflow actions', () => {
|
|||||||
|
|
||||||
return store.dispatch(actions.publishUnpublishedEntry('posts', slug)).then(() => {
|
return store.dispatch(actions.publishUnpublishedEntry('posts', slug)).then(() => {
|
||||||
const actions = store.getActions();
|
const actions = store.getActions();
|
||||||
expect(actions).toHaveLength(6);
|
expect(actions).toHaveLength(7);
|
||||||
|
|
||||||
expect(actions[0]).toEqual({
|
expect(actions[0]).toEqual({
|
||||||
type: 'UNPUBLISHED_ENTRY_PUBLISH_REQUEST',
|
type: 'UNPUBLISHED_ENTRY_PUBLISH_REQUEST',
|
||||||
@ -155,6 +161,12 @@ describe('editorialWorkflow actions', () => {
|
|||||||
collection: 'posts',
|
collection: 'posts',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
expect(actions[6]).toEqual({
|
||||||
|
type: 'DRAFT_CREATE_FROM_ENTRY',
|
||||||
|
payload: {
|
||||||
|
entry,
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ import {
|
|||||||
import { selectFields } from '../reducers/collections';
|
import { selectFields } from '../reducers/collections';
|
||||||
import { EDITORIAL_WORKFLOW, status, Status } from '../constants/publishModes';
|
import { EDITORIAL_WORKFLOW, status, Status } from '../constants/publishModes';
|
||||||
import { EDITORIAL_WORKFLOW_ERROR } from 'netlify-cms-lib-util';
|
import { EDITORIAL_WORKFLOW_ERROR } from 'netlify-cms-lib-util';
|
||||||
import { loadEntry, entryDeleted, getMediaAssets } from './entries';
|
import { loadEntry, entryDeleted, getMediaAssets, createDraftFromEntry } from './entries';
|
||||||
import { createAssetProxy } from '../valueObjects/AssetProxy';
|
import { createAssetProxy } from '../valueObjects/AssetProxy';
|
||||||
import { addAssets } from './media';
|
import { addAssets } from './media';
|
||||||
import { loadMedia } from './mediaLibrary';
|
import { loadMedia } from './mediaLibrary';
|
||||||
@ -290,6 +290,7 @@ export function loadUnpublishedEntry(collection: Collection, slug: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatch(unpublishedEntryLoaded(collection, { ...entry, mediaFiles }));
|
dispatch(unpublishedEntryLoaded(collection, { ...entry, mediaFiles }));
|
||||||
|
dispatch(createDraftFromEntry(entry));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.name === EDITORIAL_WORKFLOW_ERROR && error.notUnderEditorialWorkflow) {
|
if (error.name === EDITORIAL_WORKFLOW_ERROR && error.notUnderEditorialWorkflow) {
|
||||||
dispatch(unpublishedEntryRedirected(collection, slug));
|
dispatch(unpublishedEntryRedirected(collection, slug));
|
||||||
|
@ -201,10 +201,10 @@ export function emptyDraftCreated(entry: EntryValue) {
|
|||||||
/*
|
/*
|
||||||
* Exported simple Action Creators
|
* Exported simple Action Creators
|
||||||
*/
|
*/
|
||||||
export function createDraftFromEntry(entry: EntryMap, metadata?: Map<string, unknown>) {
|
export function createDraftFromEntry(entry: EntryValue) {
|
||||||
return {
|
return {
|
||||||
type: DRAFT_CREATE_FROM_ENTRY,
|
type: DRAFT_CREATE_FROM_ENTRY,
|
||||||
payload: { entry, metadata },
|
payload: { entry },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,12 +339,12 @@ export function loadEntry(collection: Collection, slug: string) {
|
|||||||
const backend = currentBackend(state.config);
|
const backend = currentBackend(state.config);
|
||||||
await waitForMediaLibraryToLoad(dispatch, getState());
|
await waitForMediaLibraryToLoad(dispatch, getState());
|
||||||
dispatch(entryLoading(collection, slug));
|
dispatch(entryLoading(collection, slug));
|
||||||
return backend
|
|
||||||
.getEntry(getState(), collection, slug)
|
try {
|
||||||
.then((loadedEntry: EntryValue) => {
|
const loadedEntry = await backend.getEntry(getState(), collection, slug);
|
||||||
return dispatch(entryLoaded(collection, loadedEntry));
|
dispatch(entryLoaded(collection, loadedEntry));
|
||||||
})
|
dispatch(createDraftFromEntry(loadedEntry));
|
||||||
.catch((error: Error) => {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
dispatch(
|
dispatch(
|
||||||
notifSend({
|
notifSend({
|
||||||
@ -357,7 +357,7 @@ export function loadEntry(collection: Collection, slug: string) {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
dispatch(entryLoadError(error, collection, slug));
|
dispatch(entryLoadError(error, collection, slug));
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import { logoutUser } from 'Actions/auth';
|
|||||||
import {
|
import {
|
||||||
loadEntry,
|
loadEntry,
|
||||||
loadEntries,
|
loadEntries,
|
||||||
createDraftFromEntry,
|
|
||||||
createDraftDuplicateFromEntry,
|
createDraftDuplicateFromEntry,
|
||||||
createEmptyDraft,
|
createEmptyDraft,
|
||||||
discardDraft,
|
discardDraft,
|
||||||
@ -30,7 +29,6 @@ import {
|
|||||||
deleteUnpublishedEntry,
|
deleteUnpublishedEntry,
|
||||||
} from 'Actions/editorialWorkflow';
|
} from 'Actions/editorialWorkflow';
|
||||||
import { loadDeployPreview } from 'Actions/deploys';
|
import { loadDeployPreview } from 'Actions/deploys';
|
||||||
import { deserializeValues } from 'Lib/serializeEntryValues';
|
|
||||||
import { selectEntry, selectUnpublishedEntry, selectDeployPreview } from 'Reducers';
|
import { selectEntry, selectUnpublishedEntry, selectDeployPreview } from 'Reducers';
|
||||||
import { selectFields } from 'Reducers/collections';
|
import { selectFields } from 'Reducers/collections';
|
||||||
import { status, EDITORIAL_WORKFLOW } from 'Constants/publishModes';
|
import { status, EDITORIAL_WORKFLOW } from 'Constants/publishModes';
|
||||||
@ -48,7 +46,6 @@ export class Editor extends React.Component {
|
|||||||
changeDraftField: PropTypes.func.isRequired,
|
changeDraftField: PropTypes.func.isRequired,
|
||||||
changeDraftFieldValidation: PropTypes.func.isRequired,
|
changeDraftFieldValidation: PropTypes.func.isRequired,
|
||||||
collection: ImmutablePropTypes.map.isRequired,
|
collection: ImmutablePropTypes.map.isRequired,
|
||||||
createDraftFromEntry: PropTypes.func.isRequired,
|
|
||||||
createDraftDuplicateFromEntry: PropTypes.func.isRequired,
|
createDraftDuplicateFromEntry: PropTypes.func.isRequired,
|
||||||
createEmptyDraft: PropTypes.func.isRequired,
|
createEmptyDraft: PropTypes.func.isRequired,
|
||||||
discardDraft: PropTypes.func.isRequired,
|
discardDraft: PropTypes.func.isRequired,
|
||||||
@ -198,18 +195,9 @@ export class Editor extends React.Component {
|
|||||||
|
|
||||||
if (prevProps.entry === this.props.entry) return;
|
if (prevProps.entry === this.props.entry) return;
|
||||||
|
|
||||||
const { entry, newEntry, fields, collection } = this.props;
|
const { newEntry, collection } = this.props;
|
||||||
|
|
||||||
if (entry && !entry.get('isFetching') && !entry.get('error')) {
|
if (newEntry) {
|
||||||
/**
|
|
||||||
* Deserialize entry values for widgets with registered serializers before
|
|
||||||
* creating the entry draft.
|
|
||||||
*/
|
|
||||||
const values = deserializeValues(entry.get('data'), fields);
|
|
||||||
const deserializedEntry = entry.set('data', values);
|
|
||||||
const fieldsMetaData = this.props.entryDraft && this.props.entryDraft.get('fieldsMetaData');
|
|
||||||
this.createDraft(deserializedEntry, fieldsMetaData);
|
|
||||||
} else if (newEntry) {
|
|
||||||
prevProps.createEmptyDraft(collection, this.props.location.search);
|
prevProps.createEmptyDraft(collection, this.props.location.search);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,10 +212,6 @@ export class Editor extends React.Component {
|
|||||||
this.props.persistLocalBackup(entry, collection);
|
this.props.persistLocalBackup(entry, collection);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
createDraft = (entry, metadata) => {
|
|
||||||
if (entry) this.props.createDraftFromEntry(entry, metadata);
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChangeDraftField = (field, value, metadata) => {
|
handleChangeDraftField = (field, value, metadata) => {
|
||||||
const entries = [this.props.unPublishedEntry, this.props.publishedEntry].filter(Boolean);
|
const entries = [this.props.unPublishedEntry, this.props.publishedEntry].filter(Boolean);
|
||||||
this.props.changeDraftField(field, value, metadata, entries);
|
this.props.changeDraftField(field, value, metadata, entries);
|
||||||
@ -509,7 +493,6 @@ const mapDispatchToProps = {
|
|||||||
retrieveLocalBackup,
|
retrieveLocalBackup,
|
||||||
persistLocalBackup,
|
persistLocalBackup,
|
||||||
deleteLocalBackup,
|
deleteLocalBackup,
|
||||||
createDraftFromEntry,
|
|
||||||
createDraftDuplicateFromEntry,
|
createDraftDuplicateFromEntry,
|
||||||
createEmptyDraft,
|
createEmptyDraft,
|
||||||
discardDraft,
|
discardDraft,
|
||||||
|
@ -25,7 +25,6 @@ describe('Editor', () => {
|
|||||||
changeDraftField: jest.fn(),
|
changeDraftField: jest.fn(),
|
||||||
changeDraftFieldValidation: jest.fn(),
|
changeDraftFieldValidation: jest.fn(),
|
||||||
collection: fromJS({ name: 'posts' }),
|
collection: fromJS({ name: 'posts' }),
|
||||||
createDraftFromEntry: jest.fn(),
|
|
||||||
createDraftDuplicateFromEntry: jest.fn(),
|
createDraftDuplicateFromEntry: jest.fn(),
|
||||||
createEmptyDraft: jest.fn(),
|
createEmptyDraft: jest.fn(),
|
||||||
discardDraft: jest.fn(),
|
discardDraft: jest.fn(),
|
||||||
@ -215,32 +214,4 @@ describe('Editor', () => {
|
|||||||
props.collection,
|
props.collection,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create draft from entry when done fetching', () => {
|
|
||||||
const { rerender } = render(
|
|
||||||
<Editor
|
|
||||||
{...props}
|
|
||||||
entryDraft={fromJS({ entry: {} })}
|
|
||||||
entry={fromJS({ isFetching: false, mediaFiles: [] })}
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
|
|
||||||
jest.clearAllMocks();
|
|
||||||
rerender(
|
|
||||||
<Editor
|
|
||||||
{...props}
|
|
||||||
entryDraft={fromJS({
|
|
||||||
entry: {},
|
|
||||||
fieldsMetaData: {},
|
|
||||||
})}
|
|
||||||
entry={fromJS({ isFetching: false, mediaFiles: [{ id: '1' }], data: {} })}
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(props.createDraftFromEntry).toHaveBeenCalledTimes(1);
|
|
||||||
expect(props.createDraftFromEntry).toHaveBeenCalledWith(
|
|
||||||
fromJS({ isFetching: false, data: {}, mediaFiles: [{ id: '1' }] }),
|
|
||||||
fromJS({}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@ -36,12 +36,9 @@ const entryDraftReducer = (state = Map(), action) => {
|
|||||||
case DRAFT_CREATE_FROM_ENTRY:
|
case DRAFT_CREATE_FROM_ENTRY:
|
||||||
// Existing Entry
|
// Existing Entry
|
||||||
return state.withMutations(state => {
|
return state.withMutations(state => {
|
||||||
state.set('entry', action.payload.entry);
|
state.set('entry', fromJS(action.payload.entry));
|
||||||
state.setIn(['entry', 'newRecord'], false);
|
state.setIn(['entry', 'newRecord'], false);
|
||||||
// An existing entry may already have metadata. If we surfed away and back to its
|
state.set('fieldsMetaData', Map());
|
||||||
// editor page, the metadata will have been fetched already, so we shouldn't
|
|
||||||
// clear it as to not break relation lists.
|
|
||||||
state.set('fieldsMetaData', action.payload.metadata || Map());
|
|
||||||
state.set('fieldsErrors', Map());
|
state.set('fieldsErrors', Map());
|
||||||
state.set('hasChanged', false);
|
state.set('hasChanged', false);
|
||||||
state.set('key', uuid());
|
state.set('key', uuid());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user