Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix auto-generating filenames #273

Merged
merged 4 commits into from Jan 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/_frontend/actions.md
Expand Up @@ -29,8 +29,8 @@ Async action for fetching the requested page.

### > `putPage(id)`

Async action for creating/updating the requested page. The edited/new content comes
from `state.metadata`
Async action for creating/updating the requested page. The updated content comes
from `state.metadata`. If the filename is not provided, it is auto-generated from the title.

### > `deletePage(id)`

Expand All @@ -52,7 +52,7 @@ Async action for fetching the requested document. The response includes the docu

### > `putDocument(id, collection_name)`

Async action for creating/updating the requested document. The response includes the document body. The updated content comes from `state.metadata`
Async action for creating/updating the requested document. The response includes the document body. The updated content comes from `state.metadata`. If the filename is not provided, it is auto-generated from the title.

### > `deleteDocument(collection_name, id)`

Expand Down
52 changes: 27 additions & 25 deletions docs/_frontend/containers.md
Expand Up @@ -51,10 +51,24 @@ for front matters other than `title`, `body`, `path` and `draft`.
}
```

## Views
## Notifications

Container for showing notifications at the right bottom of the screen

### PropTypes

```javascript
{
notification: Object
}
```


# Views

Contains all of the views linked with the routes.

### Configuration
## Configuration

Container for Configuration view. Consists of a YAML editor and a save button.
The button is activated when the editor changes.
Expand All @@ -72,7 +86,7 @@ The button is activated when the editor changes.
}
```

### Pages
## Pages

Container for Pages view. Lists available pages.

Expand All @@ -88,7 +102,7 @@ Container for Pages view. Lists available pages.
}
```

### PageEdit
## PageEdit

Container for editing a page.

Expand All @@ -112,7 +126,7 @@ Container for editing a page.
}
```

### PageNew
## PageNew

Container for creating a new page.

Expand All @@ -131,7 +145,7 @@ Container for creating a new page.
}
```

### Documents
## Documents

Container for Documents view. Lists documents of a collection (including posts).

Expand All @@ -148,7 +162,7 @@ Container for Documents view. Lists documents of a collection (including posts).
}
```

### DocumentEdit
## DocumentEdit

Container for editing a document.

Expand All @@ -172,7 +186,7 @@ Container for editing a document.
}
```

### DocumentNew
## DocumentNew

Container for creating a new document.

Expand All @@ -191,7 +205,7 @@ Container for creating a new document.
}
```

### DataFiles
## DataFiles

Container for DataFiles view. Lists data files.

Expand All @@ -207,7 +221,7 @@ Container for DataFiles view. Lists data files.
}
```

### DataFileEdit
## DataFileEdit

Container for editing a data file.

Expand All @@ -229,7 +243,7 @@ Container for editing a data file.
}
```

### DataFileNew
## DataFileNew

Container for creating a new data file

Expand All @@ -247,7 +261,7 @@ Container for creating a new data file
}
```

### StaticFiles
## StaticFiles

Container for StaticFiles view. Lists all of static files and let users upload/delete static files. It uses `react-dropzone` for drag & drop file uploading.
Uploaded files are previewed via `FilePreview` component.
Expand All @@ -265,18 +279,6 @@ Uploaded files are previewed via `FilePreview` component.
}
```

### NotFound
## NotFound

Component for 404 page. react-router renders this component for all non-existing routes.

### Notifications

Container for showing notifications at the right bottom of the screen

### PropTypes

```javascript
{
notification: Object
}
```
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -28,7 +28,7 @@
"isomorphic-fetch": "^2.2.1",
"js-yaml": "^3.6.1",
"lodash": "^4.13.1",
"moment": "^2.13.0",
"moment": "^2.17.1",
"react": "15.3.2",
"react-ace": "4.1.0",
"react-dom": "15.3.2",
Expand Down
16 changes: 11 additions & 5 deletions src/actions/collections.js
Expand Up @@ -62,7 +62,7 @@ export function putDocument(id, collection) {

// if no path given, generate filename from the title
if (!path && title) {
path = generateFilenameFromTitle(title, collection); // override empty path
path = generateFilenameFromTitle(metadata, collection); // override empty path
} else { // validate otherwise
const errors = validateDocument(metadata, collection);
if (errors.length) {
Expand Down Expand Up @@ -91,12 +91,18 @@ export function putDocument(id, collection) {
};
}

const generateFilenameFromTitle = (title, collection) => {
const generateFilenameFromTitle = (metadata, collection) => {
if (collection == 'posts') {
const date = moment().format('YYYY-MM-DD');
return `${date}-${slugify(title)}.md`;
// if date is provided, use it, otherwise generate it with today's date
let date;
if (metadata.date) {
date = metadata.date.split(' ')[0];
} else {
date = moment().format('YYYY-MM-DD');
}
return `${date}-${slugify(metadata.title)}.md`;
}
return `${slugify(title)}.md`;
return `${slugify(metadata.title)}.md`;
};

const validateDocument = (metadata, collection) => {
Expand Down
39 changes: 36 additions & 3 deletions src/actions/tests/collections.spec.js
Expand Up @@ -8,7 +8,14 @@ import nock from 'nock';
import expect from 'expect';
import _ from 'underscore';

import { collections, collection, doc, new_doc } from './fixtures';
import {
collections,
collection,
doc,
new_doc,
post,
new_post_with_date
} from './fixtures';

const middlewares = [ thunk ];
const mockStore = configureMockStore(middlewares);
Expand Down Expand Up @@ -111,7 +118,7 @@ describe('Actions::Collections', () => {

it('updates the document successfully', () => {
nock(API)
.put(`/collections${doc.id+doc.ext}`)
.put(`/collections/${doc.collection}/${filename}`)
.reply(200, doc);

const expectedActions = [
Expand All @@ -129,7 +136,7 @@ describe('Actions::Collections', () => {

it('creates PUT_DOCUMENT_FAILURE when updating document failed', () => {
nock(API)
.put(`/collections${doc.id+doc.ext}`)
.put(`/collections/${doc.collection}/${filename}`)
.replyWithError('something awful happened');

const expectedActions = [
Expand Down Expand Up @@ -181,6 +188,32 @@ describe('Actions::Collections', () => {
});
});

it('creates the post with autogenerated filename', () => {
nock(API)
.put(`/collections/${new_post_with_date.collection}/${new_post_with_date.path}`)
.reply(200, post);

const expectedActions = [
{ type: types.CLEAR_ERRORS },
{ type: types.PUT_DOCUMENT_SUCCESS, doc: post }
];

const store = mockStore({
metadata: {
metadata: {
...new_post_with_date,
path: '',
front_matter: { date: new_post_with_date.date }
}
}
});

return store.dispatch(actions.putDocument(null, new_post_with_date.collection))
.then(() => {
expect(store.getActions()).toEqual(expectedActions);
});
});

it('creates VALIDATION_ERROR if required field is not provided.', () => {
const expectedActions = [
{
Expand Down
27 changes: 27 additions & 0 deletions src/actions/tests/fixtures/index.js
Expand Up @@ -64,6 +64,33 @@ export const new_doc = {
foo: "bar"
};

export const post = {
path: "2016-04-01-awesome-post.md",
id: "/2016/04/01/awesome-post",
relative_path: "_post/awesome-post.md",
url: "/posts/awesome-post.html",
collection: "posts",
draft: false,
categories: [],
some_front_matter: "default",
title: "Awesome Post",
slug: "awesome-post",
ext: ".md",
tags: [],
date: "2016-04-01 00:00:00 +0200",
http_url: null,
api_url: "http://localhost:4000/_api/collections/posts/awesome-post.md"
};

export const new_post_with_date = {
collection: "posts",
raw_content: "# Test Post",
title: "Awesome Post",
date: "2016-04-01 00:00:00 +0200",
path: "2016-04-01-awesome-post.md",
foo: "bar"
};

export const page = {
name: "contact.md",
raw_content: "# This is the base Jekyll theme.",
Expand Down
9 changes: 5 additions & 4 deletions src/containers/views/Documents.js
Expand Up @@ -58,12 +58,13 @@ export class Documents extends Component {
renderRows() {
const { documents } = this.props;
return _.map(documents, doc => {
const { id, slug, title, http_url, ext, collection, path } = doc;
const { id, slug, title, http_url, collection, path } = doc;
const filename = getFilenameFromPath(path);
const to = `${ADMIN_PREFIX}/collections/${collection}/${filename}`;
const date = moment(doc.date).format("hh:mm:ss") == '12:00:00' ?
moment(doc.date).format("LL") :
moment(doc.date).format("LLL");
let date = doc.date.substring(0, doc.date.lastIndexOf(" ")); // w/o timezone
date = moment(date).format("hh:mm:ss") == '12:00:00' ?
moment(date).format("ll") :
moment(date).format("lll");

return (
<tr key={id}>
Expand Down
1 change: 1 addition & 0 deletions src/containers/views/tests/fixtures/index.js
Expand Up @@ -15,6 +15,7 @@ export const doc = {
draft: false,
http_url: '/the-revenant.html',
slug: 'the-revenant',
date: '2016-03-01 00:00:00 +0200',
front_matter: {
foo: "bar"
}
Expand Down