Single file collections (#132)

* Files based collections skeleton

* listing file based cards

* create new entry with collection

* moved lookupEntry to main backend

* Editing single page Collections file

* List widget basic implementation

* Adjustments for test-repo

* check if value exists before trying to iterate over
This commit is contained in:
Cássio Souza
2016-10-21 20:42:14 -02:00
committed by GitHub
parent cca338df79
commit 2496ec09a4
18 changed files with 190 additions and 102 deletions

View File

@ -3,6 +3,7 @@ import GitHubBackend from './github/implementation';
import NetlifyGitBackend from './netlify-git/implementation';
import { resolveFormat } from '../formats/formats';
import { createEntry } from '../valueObjects/Entry';
import { FILES, FOLDER } from '../constants/collectionTypes';
class LocalStorageAuthStore {
storageKey = 'nf-cms-user';
@ -18,15 +19,15 @@ class LocalStorageAuthStore {
}
const slugFormatter = (template, entryData) => {
var date = new Date();
return template.replace(/\{\{([^\}]+)\}\}/g, function(_, name) {
const date = new Date();
return template.replace(/\{\{([^\}]+)\}\}/g, (_, name) => {
switch (name) {
case 'year':
return date.getFullYear();
case 'month':
return ('0' + (date.getMonth() + 1)).slice(-2);
return (`0${ date.getMonth() + 1 }`).slice(-2);
case 'day':
return ('0' + date.getDate()).slice(-2);
return (`0${ date.getDate() }`).slice(-2);
case 'slug':
const identifier = entryData.get('title', entryData.get('path'));
return identifier.trim().toLowerCase().replace(/[^a-z0-9\.\-\_]+/gi, '-');
@ -65,13 +66,31 @@ class Backend {
});
}
listEntries(collection, page, perPage) {
return this.implementation.entries(collection, page, perPage).then((response) => {
return {
pagination: response.pagination,
entries: response.entries.map(this.entryWithFormat(collection))
};
});
listEntries(collection) {
const type = collection.get('type');
if (type === FOLDER) {
return this.implementation.entriesByFolder(collection)
.then(loadedEntries => (
loadedEntries.map(loadedEntry => createEntry(collection.get('name'), loadedEntry.file.path.split('/').pop().replace(/\.[^\.]+$/, ''), loadedEntry.file.path, { raw: loadedEntry.data }))
))
.then(entries => (
{
entries: entries.map(this.entryWithFormat(collection)),
}
));
} else if (type === FILES) {
const collectionFiles = collection.get('files').map(collectionFile => ({ path: collectionFile.get('file'), label: collectionFile.get('label') }));
return this.implementation.entriesByFiles(collection, collectionFiles)
.then(loadedEntries => (
loadedEntries.map(loadedEntry => createEntry(collection.get('name'), loadedEntry.file.path.split('/').pop().replace(/\.[^\.]+$/, ''), loadedEntry.file.path, { raw: loadedEntry.data, label: loadedEntry.file.label }))
))
.then(entries => (
{
entries: entries.map(this.entryWithFormat(collection)),
}
));
}
return Promise.reject(`Couldn't process collection type ${ type }`);
}
// We have the file path. Fetch and parse the file.
@ -82,12 +101,19 @@ class Backend {
// Will fetch the whole list of files from GitHub and load each file, then looks up for entry.
// (Files are persisted in local storage - only expensive on the first run for each file).
lookupEntry(collection, slug) {
return this.implementation.lookupEntry(collection, slug).then(this.entryWithFormat(collection));
const type = collection.get('type');
if (type === FOLDER) {
return this.implementation.entriesByFolder(collection)
.then(loadedEntries => (
loadedEntries.map(loadedEntry => createEntry(collection.get('name'), loadedEntry.file.path.split('/').pop().replace(/\.[^\.]+$/, ''), loadedEntry.file.path, { raw: loadedEntry.data }))
))
.then(response => response.filter(entry => entry.slug === slug)[0])
.then(this.entryWithFormat(collection));
}
}
newEntry(collection) {
const newEntry = createEntry();
return this.entryWithFormat(collection)(newEntry);
return createEntry(collection.get('name'));
}
entryWithFormat(collectionOrEntity) {
@ -95,8 +121,10 @@ class Backend {
const format = resolveFormat(collectionOrEntity, entry);
if (entry && entry.raw) {
entry.data = format && format.fromFile(entry.raw);
return entry;
} else {
return format.fromFile(entry);
}
return entry;
};
}
@ -104,7 +132,7 @@ class Backend {
return this.implementation.unpublishedEntries(page, perPage).then((response) => {
return {
pagination: response.pagination,
entries: response.entries.map(this.entryWithFormat('editorialWorkflow'))
entries: response.entries.map(this.entryWithFormat('editorialWorkflow')),
};
});
}
@ -126,28 +154,28 @@ class Backend {
if (newEntry) {
const slug = slugFormatter(collection.get('slug'), entryDraft.getIn(['entry', 'data']));
entryObj = {
path: `${collection.get('folder')}/${slug}.md`,
slug: slug,
raw: this.entryToRaw(collection, entryData)
path: `${ collection.get('folder') }/${ slug }.md`,
slug,
raw: this.entryToRaw(collection, entryData),
};
} else {
entryObj = {
path: entryDraft.getIn(['entry', 'path']),
slug: entryDraft.getIn(['entry', 'slug']),
raw: this.entryToRaw(collection, entryData)
raw: this.entryToRaw(collection, entryData),
};
}
const commitMessage = (newEntry ? 'Created ' : 'Updated ') +
collection.get('label') + ' “' +
entryDraft.getIn(['entry', 'data', 'title']) + '”';
const commitMessage = `${ (newEntry ? 'Created ' : 'Updated ') +
collection.get('label') }${
entryDraft.getIn(['entry', 'data', 'title']) }`;
const mode = config.get('publish_mode');
const collectionName = collection.get('name');
return this.implementation.persistEntry(entryObj, MediaFiles, {
newEntry, parsedData, commitMessage, collectionName, mode, ...options
newEntry, parsedData, commitMessage, collectionName, mode, ...options,
});
}
@ -186,11 +214,11 @@ export function resolveBackend(config) {
case 'netlify-git':
return new Backend(new NetlifyGitBackend(config, slugFormatter), authStore);
default:
throw `Backend not found: ${name}`;
throw `Backend not found: ${ name }`;
}
}
export const currentBackend = (function() {
export const currentBackend = (function () {
let backend = null;
return (config) => {
@ -199,4 +227,4 @@ export const currentBackend = (function() {
return backend = resolveBackend(config);
}
};
})();
}());