From 90d4b39fc15a344916b35b575c140375be700cca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Zen?= Date: Tue, 6 Sep 2016 17:18:27 -0300 Subject: [PATCH] Load unpublished entries --- src/actions/editorialWorkflow.js | 3 +-- src/backends/github/API.js | 32 ++++++++++++++++++++++----- src/backends/github/implementation.js | 27 +++++++++++++++++++--- src/containers/CollectionPage.js | 2 +- src/reducers/editorialWorkflow.js | 2 +- src/valueObjects/Entry.js | 1 + 6 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/actions/editorialWorkflow.js b/src/actions/editorialWorkflow.js index 6f478892..0c6d6817 100644 --- a/src/actions/editorialWorkflow.js +++ b/src/actions/editorialWorkflow.js @@ -41,8 +41,7 @@ function unpublishedEntriesFailed(error) { export function loadUnpublishedEntries() { return (dispatch, getState) => { const state = getState(); - if (state.publish_mode !== EDITORIAL_WORKFLOW) return; - + if (state.config.get('publish_mode') !== EDITORIAL_WORKFLOW) return; const backend = currentBackend(state.config); dispatch(unpublishedEntriesLoading()); backend.unpublishedEntries().then( diff --git a/src/backends/github/API.js b/src/backends/github/API.js index 3fe28ea5..c4cbc03c 100644 --- a/src/backends/github/API.js +++ b/src/backends/github/API.js @@ -100,7 +100,7 @@ export default class API { }); } - retrieveMetadata(key, data) { + retrieveMetadata(key) { const cache = LocalForage.getItem(`gh.meta.${key}`); return cache.then((cached) => { if (cached && cached.expires > Date.now()) { return cached.data; } @@ -109,7 +109,9 @@ export default class API { params: { ref: 'refs/meta/_netlify_cms' }, headers: { Accept: 'application/vnd.github.VERSION.raw' }, cache: 'no-store', - }).then((result) => { + }) + .then(response => JSON.parse(response)) + .then((result) => { LocalForage.setItem(`gh.meta.${key}`, { expires: Date.now() + 300000, // In 5 minutes data: result, @@ -119,20 +121,19 @@ export default class API { }).catch(error => null); } - readFile(path, sha) { + readFile(path, sha, branch = this.branch) { const cache = sha ? LocalForage.getItem(`gh.${sha}`) : Promise.resolve(null); return cache.then((cached) => { if (cached) { return cached; } return this.request(`${this.repoURL}/contents/${path}`, { headers: { Accept: 'application/vnd.github.VERSION.raw' }, - params: { ref: this.branch }, + params: { ref: branch }, cache: false }).then((result) => { if (sha) { LocalForage.setItem(`gh.${sha}`, result); } - return result; }); }); @@ -144,6 +145,22 @@ export default class API { }); } + readUnpublishedBranchFile(contentKey) { + let metaData; + return this.retrieveMetadata(contentKey) + .then(data => { + metaData = data; + return this.readFile(data.objects.entry, null, data.branch); + }) + .then(file => { + return { metaData, file }; + }); + } + + listUnpublishedBranches() { + return this.request(`${this.repoURL}/git/refs/heads/cms`); + } + persistFiles(entry, mediaFiles, options) { let filename, part, parts, subtree; const fileTree = {}; @@ -180,7 +197,10 @@ export default class API { collection: options.collectionName, title: options.parsedData.title, description: options.parsedData.description, - objects: files.map(file => file.path) + objects: { + entry: entry.path, + files: mediaFiles.map(file => file.path) + } })) .then(this.createPR(options.commitMessage, `cms/${contentKey}`)); } else { diff --git a/src/backends/github/implementation.js b/src/backends/github/implementation.js index d2dd26d1..a4540ce1 100644 --- a/src/backends/github/implementation.js +++ b/src/backends/github/implementation.js @@ -64,9 +64,30 @@ export default class GitHub { } unpublishedEntries() { - return Promise.resolve({ - pagination: {}, - entries: [] + return this.api.listUnpublishedBranches().then((branches) => { + const sem = semaphore(MAX_CONCURRENT_DOWNLOADS); + const promises = []; + branches.map((branch) => { + promises.push(new Promise((resolve, reject) => { + const contentKey = branch.ref.split('refs/heads/cms/').pop(); + return sem.take(() => this.api.readUnpublishedBranchFile(contentKey).then((data) => { + const entryPath = data.metaData.objects.entry; + const entry = createEntry(entryPath, entryPath.split('/').pop().replace(/\.[^\.]+$/, ''), data.file); + entry.metaData = data.metaData; + resolve(entry); + sem.leave(); + }).catch((err) => { + sem.leave(); + reject(err); + })); + })); + }); + return Promise.all(promises); + }).then((entries) => { + return { + pagination: {}, + entries + }; }); } } diff --git a/src/containers/CollectionPage.js b/src/containers/CollectionPage.js index 9fe0a622..cad69722 100644 --- a/src/containers/CollectionPage.js +++ b/src/containers/CollectionPage.js @@ -10,7 +10,7 @@ import EntryListing from '../components/EntryListing'; class DashboardPage extends React.Component { componentDidMount() { const { collection, dispatch } = this.props; - dispatch(loadUnpublishedEntries); + dispatch(loadUnpublishedEntries()); if (collection) { dispatch(loadEntries(collection)); } diff --git a/src/reducers/editorialWorkflow.js b/src/reducers/editorialWorkflow.js index 23f071f1..aef48f0d 100644 --- a/src/reducers/editorialWorkflow.js +++ b/src/reducers/editorialWorkflow.js @@ -12,7 +12,7 @@ const unpublishedEntries = (state = Map({ entities: Map(), pages: Map() }), acti const { entries, pages } = action.payload; return state.withMutations((map) => { entries.forEach((entry) => ( - map.setIn(['entities', `${entry.metadata.status}.${entry.slug}`], fromJS(entry).set('isFetching', false)) + map.setIn(['entities', `${entry.metaData.status}.${entry.slug}`], fromJS(entry).set('isFetching', false)) )); map.set('pages', Map({ ...pages, diff --git a/src/valueObjects/Entry.js b/src/valueObjects/Entry.js index 36ce0de0..ab247a6c 100644 --- a/src/valueObjects/Entry.js +++ b/src/valueObjects/Entry.js @@ -4,5 +4,6 @@ export function createEntry(path = '', slug = '', raw = '') { returnObj.slug = slug; returnObj.raw = raw; returnObj.data = {}; + returnObj.metaData = {}; return returnObj; }