fix: keep editor slug path (#2934)
* fix: keep editor slug path * fix: cleanup * refactor: remove unused path preview component
This commit is contained in:
parent
09ca1a7f03
commit
3c4865f2a7
@ -104,8 +104,8 @@ describe('test backend implementation', () => {
|
|||||||
|
|
||||||
const backend = new TestBackend();
|
const backend = new TestBackend();
|
||||||
|
|
||||||
const slug = encodeURIComponent('dir1/dir2/some-post.md');
|
const slug = 'dir1/dir2/some-post.md';
|
||||||
const path = `posts/${decodeURIComponent(slug)}`;
|
const path = `posts/${slug}`;
|
||||||
const entry = { path, raw: 'content', slug };
|
const entry = { path, raw: 'content', slug };
|
||||||
await backend.persistEntry(entry, [], { newEntry: true });
|
await backend.persistEntry(entry, [], { newEntry: true });
|
||||||
|
|
||||||
@ -138,8 +138,8 @@ describe('test backend implementation', () => {
|
|||||||
|
|
||||||
const backend = new TestBackend();
|
const backend = new TestBackend();
|
||||||
|
|
||||||
const slug = encodeURIComponent('dir1/dir2/some-post.md');
|
const slug = 'dir1/dir2/some-post.md';
|
||||||
const path = `posts/${decodeURIComponent(slug)}`;
|
const path = `posts/${slug}`;
|
||||||
const entry = { path, raw: 'new content', slug };
|
const entry = { path, raw: 'new content', slug };
|
||||||
await backend.persistEntry(entry, [], { newEntry: false });
|
await backend.persistEntry(entry, [], { newEntry: false });
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ class App extends React.Component {
|
|||||||
path="/collections/:name/new"
|
path="/collections/:name/new"
|
||||||
render={props => <Editor {...props} newRecord />}
|
render={props => <Editor {...props} newRecord />}
|
||||||
/>
|
/>
|
||||||
<Route path="/collections/:name/entries/:slug" component={Editor} />
|
<Route path="/collections/:name/entries/*" component={Editor} />
|
||||||
<Route
|
<Route
|
||||||
path="/search/:searchTerm"
|
path="/search/:searchTerm"
|
||||||
render={props => <Collection {...props} isSearchResults />}
|
render={props => <Collection {...props} isSearchResults />}
|
||||||
|
@ -94,8 +94,7 @@ const EntryCard = ({
|
|||||||
const label = entry.get('label');
|
const label = entry.get('label');
|
||||||
const entryData = entry.get('data');
|
const entryData = entry.get('data');
|
||||||
const defaultTitle = label || entryData.get(inferedFields.titleField);
|
const defaultTitle = label || entryData.get(inferedFields.titleField);
|
||||||
const slug = entry.get('slug');
|
const path = `/collections/${collection.get('name')}/entries/${entry.get('slug')}`;
|
||||||
const path = `/collections/${collection.get('name')}/entries/${encodeURIComponent(slug)}`;
|
|
||||||
const summary = collection.get('summary');
|
const summary = collection.get('summary');
|
||||||
const date = parseDateFromEntry(entry, collection) || null;
|
const date = parseDateFromEntry(entry, collection) || null;
|
||||||
const identifier = entryData.get(selectIdentifier(collection));
|
const identifier = entryData.get(selectIdentifier(collection));
|
||||||
|
@ -40,7 +40,7 @@ const navigateCollection = collectionPath => history.push(`/collections/${collec
|
|||||||
const navigateToCollection = collectionName => navigateCollection(collectionName);
|
const navigateToCollection = collectionName => navigateCollection(collectionName);
|
||||||
const navigateToNewEntry = collectionName => navigateCollection(`${collectionName}/new`);
|
const navigateToNewEntry = collectionName => navigateCollection(`${collectionName}/new`);
|
||||||
const navigateToEntry = (collectionName, slug) =>
|
const navigateToEntry = (collectionName, slug) =>
|
||||||
navigateCollection(`${collectionName}/entries/${encodeURIComponent(slug)}`);
|
navigateCollection(`${collectionName}/entries/${slug}`);
|
||||||
|
|
||||||
export class Editor extends React.Component {
|
export class Editor extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -435,7 +435,7 @@ export class Editor extends React.Component {
|
|||||||
|
|
||||||
function mapStateToProps(state, ownProps) {
|
function mapStateToProps(state, ownProps) {
|
||||||
const { collections, entryDraft, auth, config, entries, globalUI } = state;
|
const { collections, entryDraft, auth, config, entries, globalUI } = state;
|
||||||
const slug = ownProps.match.params.slug && decodeURIComponent(ownProps.match.params.slug);
|
const slug = ownProps.match.params[0];
|
||||||
const collection = collections.get(ownProps.match.params.name);
|
const collection = collections.get(ownProps.match.params.name);
|
||||||
const collectionName = collection.get('name');
|
const collectionName = collection.get('name');
|
||||||
const newEntry = ownProps.newRecord === true;
|
const newEntry = ownProps.newRecord === true;
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { translate } from 'react-polyglot';
|
|
||||||
import styled from '@emotion/styled';
|
|
||||||
import { colors, transitions } from 'netlify-cms-ui-default';
|
|
||||||
import { selectDraftPath } from 'Selectors/entryDraft';
|
|
||||||
|
|
||||||
const PathLabel = styled.label`
|
|
||||||
color: ${colors.text};
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 600;
|
|
||||||
border: 0;
|
|
||||||
padding-left: 5px;
|
|
||||||
transition: all ${transitions.main};
|
|
||||||
position: relative;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const PathPreview = ({ value }) => {
|
|
||||||
return <PathLabel data-testid="site_path-preview">{value}</PathLabel>;
|
|
||||||
};
|
|
||||||
|
|
||||||
PathPreview.propTypes = {
|
|
||||||
value: PropTypes.string.isRequired,
|
|
||||||
t: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapStateToProps = (state, ownProps) => {
|
|
||||||
const collection = ownProps.collection;
|
|
||||||
const entry = ownProps.entry;
|
|
||||||
const newRecord = entry.get('newRecord');
|
|
||||||
|
|
||||||
const value = newRecord ? selectDraftPath(state, collection, entry) : entry.get('path');
|
|
||||||
|
|
||||||
return { value };
|
|
||||||
};
|
|
||||||
|
|
||||||
const ConnectedPathPreview = connect(mapStateToProps)(translate()(PathPreview));
|
|
||||||
|
|
||||||
ConnectedPathPreview.propTypes = {
|
|
||||||
collection: ImmutablePropTypes.map.isRequired,
|
|
||||||
entry: ImmutablePropTypes.map.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ConnectedPathPreview;
|
|
@ -1,84 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Map } from 'immutable';
|
|
||||||
import { createStore } from 'redux';
|
|
||||||
import { Provider } from 'react-redux';
|
|
||||||
import { render } from '@testing-library/react';
|
|
||||||
import ConnectedPathPreview, { PathPreview } from '../PathPreview';
|
|
||||||
|
|
||||||
jest.mock('Reducers', () => {
|
|
||||||
return () => ({});
|
|
||||||
});
|
|
||||||
jest.mock('Selectors/entryDraft');
|
|
||||||
jest.mock('react-polyglot', () => {
|
|
||||||
return {
|
|
||||||
translate: () => Component => props => <Component {...props} t={jest.fn(key => key)} />,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('PathPreview', () => {
|
|
||||||
it('should render successfully and match snapshot', () => {
|
|
||||||
const props = {
|
|
||||||
value: 'posts/2019/index.md',
|
|
||||||
t: jest.fn(key => key),
|
|
||||||
};
|
|
||||||
const { asFragment } = render(<PathPreview {...props} />);
|
|
||||||
|
|
||||||
expect(asFragment()).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function renderWithRedux(ui, { initialState, store = createStore(() => ({}), initialState) } = {}) {
|
|
||||||
return {
|
|
||||||
...render(<Provider store={store}>{ui}</Provider>),
|
|
||||||
store,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('ConnectedPathPreview', () => {
|
|
||||||
const { selectDraftPath } = require('Selectors/entryDraft');
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use existing path when newRecord is false', () => {
|
|
||||||
const props = {
|
|
||||||
collection: Map({
|
|
||||||
name: 'posts',
|
|
||||||
}),
|
|
||||||
entry: Map({
|
|
||||||
newRecord: false,
|
|
||||||
data: {},
|
|
||||||
path: 'existing-path/index.md',
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
const { asFragment, getByTestId } = renderWithRedux(<ConnectedPathPreview {...props} />);
|
|
||||||
|
|
||||||
expect(selectDraftPath).toHaveBeenCalledTimes(0);
|
|
||||||
|
|
||||||
expect(getByTestId('site_path-preview')).toHaveTextContent('existing-path/index.md');
|
|
||||||
|
|
||||||
expect(asFragment()).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should evaluate preview path when newRecord is true', () => {
|
|
||||||
selectDraftPath.mockReturnValue('preview-path/index.md');
|
|
||||||
const props = {
|
|
||||||
collection: Map({
|
|
||||||
name: 'posts',
|
|
||||||
}),
|
|
||||||
entry: Map({
|
|
||||||
newRecord: true,
|
|
||||||
data: {},
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
const { asFragment, getByTestId } = renderWithRedux(<ConnectedPathPreview {...props} />);
|
|
||||||
|
|
||||||
expect(selectDraftPath).toHaveBeenCalledTimes(1);
|
|
||||||
expect(selectDraftPath).toHaveBeenCalledWith({}, props.collection, props.entry);
|
|
||||||
|
|
||||||
expect(getByTestId('site_path-preview')).toHaveTextContent('preview-path/index.md');
|
|
||||||
|
|
||||||
expect(asFragment()).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,70 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`ConnectedPathPreview should evaluate preview path when newRecord is true 1`] = `
|
|
||||||
<DocumentFragment>
|
|
||||||
.emotion-0 {
|
|
||||||
color: #798291;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 600;
|
|
||||||
border: 0;
|
|
||||||
padding-left: 5px;
|
|
||||||
-webkit-transition: all .2s ease;
|
|
||||||
transition: all .2s ease;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
<label
|
|
||||||
class="emotion-0 emotion-1"
|
|
||||||
data-testid="site_path-preview"
|
|
||||||
>
|
|
||||||
preview-path/index.md
|
|
||||||
</label>
|
|
||||||
</DocumentFragment>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`ConnectedPathPreview should use existing path when newRecord is false 1`] = `
|
|
||||||
<DocumentFragment>
|
|
||||||
.emotion-0 {
|
|
||||||
color: #798291;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 600;
|
|
||||||
border: 0;
|
|
||||||
padding-left: 5px;
|
|
||||||
-webkit-transition: all .2s ease;
|
|
||||||
transition: all .2s ease;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
<label
|
|
||||||
class="emotion-0 emotion-1"
|
|
||||||
data-testid="site_path-preview"
|
|
||||||
>
|
|
||||||
existing-path/index.md
|
|
||||||
</label>
|
|
||||||
</DocumentFragment>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`PathPreview should render successfully and match snapshot 1`] = `
|
|
||||||
<DocumentFragment>
|
|
||||||
.emotion-0 {
|
|
||||||
color: #798291;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 600;
|
|
||||||
border: 0;
|
|
||||||
padding-left: 5px;
|
|
||||||
-webkit-transition: all .2s ease;
|
|
||||||
transition: all .2s ease;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
<label
|
|
||||||
class="emotion-0 emotion-1"
|
|
||||||
data-testid="site_path-preview"
|
|
||||||
>
|
|
||||||
posts/2019/index.md
|
|
||||||
</label>
|
|
||||||
</DocumentFragment>
|
|
||||||
`;
|
|
@ -14,7 +14,7 @@ function mapStateToProps(state, ownProps) {
|
|||||||
showDelete: !ownProps.newEntry && selectAllowDeletion(collection),
|
showDelete: !ownProps.newEntry && selectAllowDeletion(collection),
|
||||||
};
|
};
|
||||||
if (isEditorialWorkflow) {
|
if (isEditorialWorkflow) {
|
||||||
const slug = ownProps.match.params.slug && decodeURIComponent(ownProps.match.params.slug);
|
const slug = ownProps.match.params[0];
|
||||||
const unpublishedEntry = selectUnpublishedEntry(state, collection.get('name'), slug);
|
const unpublishedEntry = selectUnpublishedEntry(state, collection.get('name'), slug);
|
||||||
if (unpublishedEntry) {
|
if (unpublishedEntry) {
|
||||||
returnObj.unpublishedEntry = true;
|
returnObj.unpublishedEntry = true;
|
||||||
|
@ -205,10 +205,7 @@ class WorkflowList extends React.Component {
|
|||||||
{entries.map(entry => {
|
{entries.map(entry => {
|
||||||
const timestamp = moment(entry.getIn(['metaData', 'timeStamp'])).format('MMMM D');
|
const timestamp = moment(entry.getIn(['metaData', 'timeStamp'])).format('MMMM D');
|
||||||
const slug = entry.get('slug');
|
const slug = entry.get('slug');
|
||||||
const editLink = `collections/${entry.getIn([
|
const editLink = `collections/${entry.getIn(['metaData', 'collection'])}/entries/${slug}`;
|
||||||
'metaData',
|
|
||||||
'collection',
|
|
||||||
])}/entries/${encodeURIComponent(slug)}`;
|
|
||||||
const ownStatus = entry.getIn(['metaData', 'status']);
|
const ownStatus = entry.getIn(['metaData', 'status']);
|
||||||
const collection = entry.getIn(['metaData', 'collection']);
|
const collection = entry.getIn(['metaData', 'collection']);
|
||||||
const isModification = entry.get('isModification');
|
const isModification = entry.get('isModification');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user