Open Authoring bugfixes and pagination improvements (#2523)

* Fix handling of displayURLs which are strings

* Add fromFetchArguments to unsentRequest

* Add parseLinkHeader to backendUtil

* Handle paginated endpoints in GitHub API

* Rename fork workflow to Open Authoring across the whole repo

* Fixes for bugs in GitHub API introduced by Open Authoring changes

* Fix getDeployPreview

* Fix incorrect auth header formatting GitHub implementation

cf. https://github.com/netlify/netlify-cms/pull/2456#discussion_r309633387

* Remove unused and broken method from GitHub API

cf. https://github.com/netlify/netlify-cms/pull/2456#discussion_r308687145

* Fix editorialWorkflowGit method in GitHub API

* Request published entry content from origin repo

* Better error when deleting a published post in Open Authoring

* Rename to Open Authoring in fork request message

Also adds a note to the fork request message that an existing fork of
the same repo will be used automatically.

* fix linting
This commit is contained in:
Benaiah Mischenko
2019-08-24 10:54:59 -07:00
committed by Shawn Erquhart
parent 66da66affd
commit 34e1f09105
16 changed files with 223 additions and 151 deletions

View File

@ -7,7 +7,7 @@ export const AUTH_REQUEST = 'AUTH_REQUEST';
export const AUTH_SUCCESS = 'AUTH_SUCCESS';
export const AUTH_FAILURE = 'AUTH_FAILURE';
export const AUTH_REQUEST_DONE = 'AUTH_REQUEST_DONE';
export const USE_FORK_WORKFLOW = 'USE_FORK_WORKFLOW';
export const USE_OPEN_AUTHORING = 'USE_OPEN_AUTHORING';
export const LOGOUT = 'LOGOUT';
export function authenticating() {
@ -37,9 +37,9 @@ export function doneAuthenticating() {
};
}
export function useForkWorkflow() {
export function useOpenAuthoring() {
return {
type: USE_FORK_WORKFLOW,
type: USE_OPEN_AUTHORING,
};
}
@ -59,8 +59,8 @@ export function authenticateUser() {
.currentUser()
.then(user => {
if (user) {
if (user.useForkWorkflow) {
dispatch(useForkWorkflow());
if (user.useOpenAuthoring) {
dispatch(useOpenAuthoring());
}
dispatch(authenticate(user));
} else {
@ -83,8 +83,8 @@ export function loginUser(credentials) {
return backend
.authenticate(credentials)
.then(user => {
if (user.useForkWorkflow) {
dispatch(useForkWorkflow());
if (user.useOpenAuthoring) {
dispatch(useOpenAuthoring());
}
dispatch(authenticate(user));
})

View File

@ -250,9 +250,10 @@ export function loadMediaDisplayURL(file) {
) {
return Promise.resolve();
}
if (typeof url === 'string' || typeof displayURL === 'string') {
if (typeof displayURL === 'string') {
dispatch(mediaDisplayURLRequest(id));
dispatch(mediaDisplayURLSuccess(id, displayURL));
return;
}
try {
const backend = currentBackend(state.config);

View File

@ -61,7 +61,7 @@ class Editor extends React.Component {
newEntry: PropTypes.bool.isRequired,
displayUrl: PropTypes.string,
hasWorkflow: PropTypes.bool,
useForkWorkflow: PropTypes.bool,
useOpenAuthoring: PropTypes.bool,
unpublishedEntry: PropTypes.bool,
isModification: PropTypes.bool,
collectionEntriesLoaded: PropTypes.bool,
@ -351,7 +351,7 @@ class Editor extends React.Component {
hasChanged,
displayUrl,
hasWorkflow,
useForkWorkflow,
useOpenAuthoring,
unpublishedEntry,
newEntry,
isModification,
@ -399,7 +399,7 @@ class Editor extends React.Component {
hasChanged={hasChanged}
displayUrl={displayUrl}
hasWorkflow={hasWorkflow}
useForkWorkflow={useForkWorkflow}
useOpenAuthoring={useOpenAuthoring}
hasUnpublishedChanges={unpublishedEntry}
isNewEntry={newEntry}
isModification={isModification}
@ -425,7 +425,7 @@ function mapStateToProps(state, ownProps) {
const hasChanged = entryDraft.get('hasChanged');
const displayUrl = config.get('display_url');
const hasWorkflow = config.get('publish_mode') === EDITORIAL_WORKFLOW;
const useForkWorkflow = globalUI.get('useForkWorkflow', false);
const useOpenAuthoring = globalUI.get('useOpenAuthoring', false);
const isModification = entryDraft.getIn(['entry', 'isModification']);
const collectionEntriesLoaded = !!entries.getIn(['pages', collectionName]);
const unpublishedEntry = selectUnpublishedEntry(state, collectionName, slug);
@ -445,7 +445,7 @@ function mapStateToProps(state, ownProps) {
hasChanged,
displayUrl,
hasWorkflow,
useForkWorkflow,
useOpenAuthoring,
isModification,
collectionEntriesLoaded,
currentStatus,

View File

@ -166,7 +166,7 @@ class EditorInterface extends Component {
hasChanged,
displayUrl,
hasWorkflow,
useForkWorkflow,
useOpenAuthoring,
hasUnpublishedChanges,
isNewEntry,
isModification,
@ -241,7 +241,7 @@ class EditorInterface extends Component {
displayUrl={displayUrl}
collection={collection}
hasWorkflow={hasWorkflow}
useForkWorkflow={useForkWorkflow}
useOpenAuthoring={useOpenAuthoring}
hasUnpublishedChanges={hasUnpublishedChanges}
isNewEntry={isNewEntry}
isModification={isModification}
@ -295,7 +295,7 @@ EditorInterface.propTypes = {
hasChanged: PropTypes.bool,
displayUrl: PropTypes.string,
hasWorkflow: PropTypes.bool,
useForkWorkflow: PropTypes.bool,
useOpenAuthoring: PropTypes.bool,
hasUnpublishedChanges: PropTypes.bool,
isNewEntry: PropTypes.bool,
isModification: PropTypes.bool,

View File

@ -218,7 +218,7 @@ class EditorToolbar extends React.Component {
displayUrl: PropTypes.string,
collection: ImmutablePropTypes.map.isRequired,
hasWorkflow: PropTypes.bool,
useForkWorkflow: PropTypes.bool,
useOpenAuthoring: PropTypes.bool,
hasUnpublishedChanges: PropTypes.bool,
isNewEntry: PropTypes.bool,
isModification: PropTypes.bool,
@ -380,7 +380,7 @@ class EditorToolbar extends React.Component {
onPublishAndNew,
currentStatus,
isNewEntry,
useForkWorkflow,
useOpenAuthoring,
t,
} = this.props;
if (currentStatus) {
@ -408,7 +408,7 @@ class EditorToolbar extends React.Component {
onClick={() => onChangeStatus('PENDING_REVIEW')}
icon={currentStatus === status.get('PENDING_REVIEW') && 'check'}
/>
{useForkWorkflow ? (
{useOpenAuthoring ? (
''
) : (
<StatusDropdownItem
@ -418,7 +418,7 @@ class EditorToolbar extends React.Component {
/>
)}
</ToolbarDropdown>
{useForkWorkflow ? (
{useOpenAuthoring ? (
''
) : (
<ToolbarDropdown

View File

@ -55,7 +55,7 @@ class Workflow extends Component {
static propTypes = {
collections: ImmutablePropTypes.orderedMap,
isEditorialWorkflow: PropTypes.bool.isRequired,
isForkWorkflow: PropTypes.bool,
isOpenAuthoring: PropTypes.bool,
isFetching: PropTypes.bool,
unpublishedEntries: ImmutablePropTypes.map,
loadUnpublishedEntries: PropTypes.func.isRequired,
@ -75,7 +75,7 @@ class Workflow extends Component {
render() {
const {
isEditorialWorkflow,
isForkWorkflow,
isOpenAuthoring,
isFetching,
unpublishedEntries,
updateUnpublishedEntryStatus,
@ -127,7 +127,7 @@ class Workflow extends Component {
handleChangeStatus={updateUnpublishedEntryStatus}
handlePublish={publishUnpublishedEntry}
handleDelete={deleteUnpublishedEntry}
isForkWorkflow={isForkWorkflow}
isOpenAuthoring={isOpenAuthoring}
/>
</WorkflowContainer>
);
@ -137,8 +137,8 @@ class Workflow extends Component {
function mapStateToProps(state) {
const { collections, config, globalUI } = state;
const isEditorialWorkflow = config.get('publish_mode') === EDITORIAL_WORKFLOW;
const isForkWorkflow = globalUI.get('useForkWorkflow', false);
const returnObj = { collections, isEditorialWorkflow, isForkWorkflow };
const isOpenAuthoring = globalUI.get('useOpenAuthoring', false);
const returnObj = { collections, isEditorialWorkflow, isOpenAuthoring };
if (isEditorialWorkflow) {
returnObj.isFetching = state.editorialWorkflow.getIn(['pages', 'isFetching'], false);

View File

@ -17,7 +17,7 @@ const WorkflowListContainer = styled.div`
grid-template-columns: 33.3% 33.3% 33.3%;
`;
const WorkflowListContainerForkWorkflow = styled.div`
const WorkflowListContainerOpenAuthoring = styled.div`
min-height: 60%;
display: grid;
grid-template-columns: 50% 50% 0%;
@ -134,7 +134,7 @@ class WorkflowList extends React.Component {
handlePublish: PropTypes.func.isRequired,
handleDelete: PropTypes.func.isRequired,
t: PropTypes.func.isRequired,
isForkWorkflow: PropTypes.bool,
isOpenAuthoring: PropTypes.bool,
};
handleChangeStatus = (newStatus, dragProps) => {
@ -162,7 +162,7 @@ class WorkflowList extends React.Component {
// eslint-disable-next-line react/display-name
renderColumns = (entries, column) => {
const { isForkWorkflow } = this.props;
const { isOpenAuthoring } = this.props;
if (!entries) return null;
if (!column) {
@ -180,8 +180,8 @@ class WorkflowList extends React.Component {
styles.column,
styles.columnPosition(idx),
isHovered && styles.columnHovered,
isForkWorkflow && currColumn === 'pending_publish' && styles.hiddenColumn,
isForkWorkflow && currColumn === 'pending_review' && styles.hiddenRightBorder,
isOpenAuthoring && currColumn === 'pending_publish' && styles.hiddenColumn,
isOpenAuthoring && currColumn === 'pending_review' && styles.hiddenRightBorder,
]}
>
<ColumnHeader name={currColumn}>
@ -248,8 +248,8 @@ class WorkflowList extends React.Component {
render() {
const columns = this.renderColumns(this.props.entries);
const ListContainer = this.props.isForkWorkflow
? WorkflowListContainerForkWorkflow
const ListContainer = this.props.isOpenAuthoring
? WorkflowListContainerOpenAuthoring
: WorkflowListContainer;
return <ListContainer>{columns}</ListContainer>;
}

View File

@ -1,16 +1,16 @@
import { Map } from 'immutable';
import { USE_FORK_WORKFLOW } from 'Actions/auth';
import { USE_OPEN_AUTHORING } from 'Actions/auth';
/*
* Reducer for some global UI state that we want to share between components
* */
const globalUI = (state = Map({ isFetching: false, useForkWorkflow: false }), action) => {
const globalUI = (state = Map({ isFetching: false, useOpenAuthoring: false }), action) => {
// Generic, global loading indicator
if (action.type.indexOf('REQUEST') > -1) {
return state.set('isFetching', true);
} else if (action.type.indexOf('SUCCESS') > -1 || action.type.indexOf('FAILURE') > -1) {
return state.set('isFetching', false);
} else if (action.type === USE_FORK_WORKFLOW) {
return state.set('useForkWorkflow', true);
} else if (action.type === USE_OPEN_AUTHORING) {
return state.set('useOpenAuthoring', true);
}
return state;
};