Skip to content

Commit

Permalink
[WIP] Dependency resolution
Browse files Browse the repository at this point in the history
Change immediately-resolved promises to Promise.resolve
  • Loading branch information
Benaiah committed Feb 28, 2017
1 parent 0b2eac3 commit abb067c
Showing 1 changed file with 91 additions and 4 deletions.
95 changes: 91 additions & 4 deletions src/actions/editorialWorkflow.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import uuid from 'uuid';
import Immutable from 'immutable';
import { actions as notifActions } from 'redux-notifications';
import { closeEntry } from './editor';
import { BEGIN, COMMIT, REVERT } from 'redux-optimist';
Expand Down Expand Up @@ -35,6 +36,10 @@ export const UNPUBLISHED_ENTRY_PUBLISH_FAILURE = 'UNPUBLISHED_ENTRY_PUBLISH_FAIL

export const UNPUBLISHED_ENTRY_REGISTER_DEPENDENCY = 'UNPUBLISHED_ENTRY_REGISTER_DEPENDENCY';

export const UNPUBLISHED_ENTRY_DEPENDENCIES_REQUEST = 'UNPUBLISHED_ENTRY_DEPENDENCIES_REQUEST';
export const UNPUBLISHED_ENTRY_DEPENDENCIES_SUCCESS = 'UNPUBLISHED_ENTRY_DEPENDENCIES_SUCCESS';
export const UNPUBLISHED_ENTRY_DEPENDENCIES_FAILURE = 'UNPUBLISHED_ENTRY_DEPENDENCIES_FAILURE';

/*
* Simple Action Creators (Internal)
*/
Expand Down Expand Up @@ -185,22 +190,41 @@ function unpublishedEntryPublishError(collection, slug, transactionID) {
function unpublishedEntryRegisterDependency(field, collection, slug) {
return {
type: UNPUBLISHED_ENTRY_REGISTER_DEPENDENCY,
payload: {field, collection, slug},
payload: { field, collection, slug },
};
}

function unpublishedEntryDependenciesRequest(collection, slug) {
return {
type: UNPUBLISHED_ENTRY_DEPENDENCIES_REQUEST,
payload: { collection, slug },
};
}

function unpublishedEntryDependenciesSuccess(collection, slug, dependencies) {
return {
type: UNPUBLISHED_ENTRY_DEPENDENCIES_SUCCESS,
payload: { collection, slug, dependencies },
};
}

function unpublishedEntryDependenciesError(collection, slug, error) {
return {
type: UNPUBLISHED_ENTRY_DEPENDENCIES_FAILURE,
payload: { collection, slug, error },
};
}

/*
* Exported Thunk Action Creators
*/

export const registerUnpublishedEntryDependency = unpublishedEntryRegisterDependency;

export function loadUnpublishedEntry(collection, slug) {
return (dispatch, getState) => {
const state = getState();
const backend = currentBackend(state.config);
dispatch(unpublishedEntryLoading(collection, slug));
backend.unpublishedEntry(collection, slug)
return backend.unpublishedEntry(collection, slug)
.then(entry => dispatch(unpublishedEntryLoaded(collection, entry)))
.catch((error) => {
if (error instanceof EditorialWorkflowError && error.notUnderEditorialWorkflow) {
Expand Down Expand Up @@ -302,3 +326,66 @@ export function publishUnpublishedEntry(collection, slug) {
});
};
}

export const registerUnpublishedEntryDependency = unpublishedEntryRegisterDependency;

const getDepsPath = dep => [
"entities",
dep,
"metaData",
"dependencies",
];

const getEventualDependencies = (paths, loadedDeps, state, dispatch) =>
paths.filter(path => !loadedDeps.includes(path)).map((path) => {
const [pathCollectionName, pathSlug] = path.split(".");
const pathCollection = state.collections.get(pathCollectionName);
// Wait for the entry to load
return dispatch(loadUnpublishedEntry(pathCollection, pathSlug))
// Return the path at the end so we can use it in .thens later
.then(() => path);
});

const traverse = (collectedDeps, path, getState, dispatch) => {
const state = getState();

if (collectedDeps.get(path) === true) {
return Promise.resolve(collectedDeps);
}

const newDeps = collectedDeps.set(path, true);
const depsPath = getDepsPath(path);

if (!state.editorialWorkflow.hasIn(depsPath) ||
state.editorialWorkflow.getIn(depsPath).size === 0) {
// This path has no dependencies
return Promise.resolve(newDeps);
}

const theseDependencies = state.editorialWorkflow.getIn(depsPath);

const eventualDeps = getEventualDependencies(theseDependencies, collectedDeps, state, dispatch);

// This is a manual version of Bluebird's Promise.reduce
return eventualDeps.reduce((depsPromise, depPromise) =>
Promise.all([depsPromise, depPromise]).then(
([deps, dep]) => traverse(deps, dep, getState, dispatch)),
Promise.resolve(newDeps));
};

export function getUnpublishedEntryDependencies(collection, slug) {
return (dispatch, getState) => {
dispatch(unpublishedEntryDependenciesRequest(collection, slug));

// Begin traversal
return traverse(new Immutable.Map(), `${ collection }.${ slug }`, getState, dispatch)
.then((dependencyMap) => {
const state = getState();
const dependencies = dependencyMap.keySeq().toList();
const filteredDependencies = dependencies.filter(
dep => state.editorialWorkflow.hasIn(["entities", dep]));
return dispatch(unpublishedEntryDependenciesSuccess(collection, slug, filteredDependencies));
})
.catch(err => dispatch(unpublishedEntryDependenciesError(collection, slug, err)));
};
}

0 comments on commit abb067c

Please sign in to comment.