Skip to content

Commit

Permalink
cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
barthc committed Dec 1, 2018
1 parent 9598baf commit 05aa868
Show file tree
Hide file tree
Showing 22 changed files with 256 additions and 110 deletions.
18 changes: 16 additions & 2 deletions packages/netlify-cms-backend-github/src/API.js
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,8 @@ export default class API {
const contentKey = entry.slug;
const branchName = this.generateBranchName(contentKey);
const unpublished = options.unpublished || false;
if (!unpublished) {
const slugChanged = entry.slugChanged;
if (!unpublished || slugChanged) {
// Open new editorial review workflow for this entry - Create new metadata and commit to new branch`
let prResponse;

Expand All @@ -376,7 +377,18 @@ export default class API {
prResponse = pr;
return this.user();
})
.then(user => {
.then(async user => {
// Keep track of the entry initial parent slug
let parentSlug = entry.oldSlug || entry.slug;
let parentPath = entry.oldPath || entry.path;
if (slugChanged) {
await this.retrieveMetadata(entry.oldSlug).then(metaData => {
if (metaData) {
parentSlug = metaData.parentSlug;
parentPath = metaData.parentPath;
}
});
}
return this.storeMetadata(contentKey, {
type: 'PR',
pr: {
Expand All @@ -389,6 +401,8 @@ export default class API {
collection: options.collectionName,
title: options.parsedData && options.parsedData.title,
description: options.parsedData && options.parsedData.description,
parentSlug,
parentPath,
objects: {
entry: {
path: entry.path,
Expand Down
5 changes: 4 additions & 1 deletion packages/netlify-cms-backend-gitlab/src/API.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,10 @@ export default class API {
persistFiles = (files, { commitMessage, newEntry }) =>
Promise.all(
files.map(file =>
this.uploadAndCommit(file, { commitMessage, updateFile: newEntry === false }),
this.uploadAndCommit(file, {
commitMessage,
updateFile: newEntry === false && file.slugChanged === false,
}),
),
);

Expand Down
14 changes: 6 additions & 8 deletions packages/netlify-cms-backend-test/src/implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,15 @@ export default class TestRepo {
const existingEntryIndex = unpubStore.findIndex(
e => e.metaData.collection === collection && e.slug === slug,
);
unpubStore.splice(existingEntryIndex, 1);
if (existingEntryIndex >= 0) {
unpubStore.splice(existingEntryIndex, 1);
}
return Promise.resolve();
}

persistEntry({ path, raw, slug }, mediaFiles, options = {}) {
persistEntry({ path, raw, slug, oldPath, oldSlug }, mediaFiles, options = {}) {
if (options.useWorkflow) {
const unpubStore = window.repoFilesUnpublished;
const oldPath = options.oldPath;
const existingPath = oldPath || path;
const existingEntryIndex = unpubStore.findIndex(e => e.file.path === existingPath);
if (existingEntryIndex >= 0) {
Expand All @@ -170,6 +171,8 @@ export default class TestRepo {
status: this.options.initialWorkflowStatus,
title: options.parsedData && options.parsedData.title,
description: options.parsedData && options.parsedData.description,
parentSlug: oldSlug || slug,
parentPath: oldPath || path,
},
slug,
};
Expand All @@ -186,11 +189,6 @@ export default class TestRepo {
if (newEntry) {
window.repoFiles[folder][fileName] = { content: raw };
} else {
if (options.oldPath) {
const oldFileName = options.oldPath.substring(path.lastIndexOf('/') + 1);
window.repoFiles[folder][fileName] = window.repoFiles[folder][oldFileName];
delete window.repoFiles[folder][oldFileName];
}
window.repoFiles[folder][fileName].content = raw;
}
return Promise.resolve();
Expand Down
12 changes: 11 additions & 1 deletion packages/netlify-cms-core/src/__tests__/backend.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { resolveBackend } from '../backend';
import { resolveBackend, generateUniqueSlug } from '../backend';
import registry from 'Lib/registry';
import { Map } from 'immutable';

jest.mock('Lib/registry');

Expand Down Expand Up @@ -108,4 +109,13 @@ describe('Backend', () => {
expect(result.length).toBe(1);
});
});

describe('uniqueSlug', () => {
it('generates unique slug', () => {
expect(generateUniqueSlug('title', Map(), ['title'])).toEqual('title-1');
expect(generateUniqueSlug('title', Map({ sanitize_replacement: '_' }), ['title'])).toEqual(
'title_1',
);
});
});
});
30 changes: 25 additions & 5 deletions packages/netlify-cms-core/src/actions/editorialWorkflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { actions as notifActions } from 'redux-notifications';
import { BEGIN, COMMIT, REVERT } from 'redux-optimist';
import { serializeValues } from 'Lib/serializeEntryValues';
import { currentBackend } from 'src/backend';
import { getAsset } from 'Reducers';
import { selectFields } from 'Reducers/collections';
import { getAsset, selectUnpublishedEntry } from 'Reducers';
import { selectFields, selectSlugField } from 'Reducers/collections';
import { selectSlugEntries } from 'Reducers/entries';
import { selectUnpublishedSlugEntriesByCollection } from 'Reducers/editorialWorkflow';
import { EDITORIAL_WORKFLOW } from 'Constants/publishModes';
import { EDITORIAL_WORKFLOW_ERROR } from 'netlify-cms-lib-util';
import { loadEntry } from './entries';
import { loadEntry, deleteEntry } from './entries';
import ValidationErrorTypes from 'Constants/validationErrorTypes';

const { notifSend } = notifActions;
Expand Down Expand Up @@ -99,12 +99,13 @@ function unpublishedEntriesFailed(error) {
};
}

function unpublishedEntryPersisting(collection, entry, transactionID) {
function unpublishedEntryPersisting(collection, entry, slug, transactionID) {
return {
type: UNPUBLISHED_ENTRY_PERSIST_REQUEST,
payload: {
collection: collection.get('name'),
entry,
slug,
},
optimist: { type: BEGIN, id: transactionID },
};
Expand Down Expand Up @@ -263,6 +264,7 @@ export function loadUnpublishedEntries(collections) {
return (dispatch, getState) => {
const state = getState();
if (state.config.get('publish_mode') !== EDITORIAL_WORKFLOW) return;
if (state.editorialWorkflow.get('isFetched')) return;
const backend = currentBackend(state.config);
dispatch(unpublishedEntriesLoading());
backend
Expand Down Expand Up @@ -328,11 +330,16 @@ export function persistUnpublishedEntry(collection, existingUnpublishedEntry) {
* update the entry and entryDraft with the serialized values.
*/
const fields = selectFields(collection, entry.get('slug'));
const slugField = selectSlugField(collection);
const serializedData = serializeValues(entryDraft.getIn(['entry', 'data']), fields);
const serializedEntry = entry.set('data', serializedData);
const serializedEntryDraft = entryDraft.set('entry', serializedEntry);
const manualSlug = serializedData.get(slugField);
const entrySlug = serializedEntry.get('slug');
const slugChanged = manualSlug && entrySlug && manualSlug !== entrySlug;
const selectedSlug = manualSlug || entrySlug;

dispatch(unpublishedEntryPersisting(collection, serializedEntry, transactionID));
dispatch(unpublishedEntryPersisting(collection, serializedEntry, selectedSlug, transactionID));
const persistAction = existingUnpublishedEntry
? backend.persistUnpublishedEntry
: backend.persistEntry;
Expand All @@ -343,6 +350,7 @@ export function persistUnpublishedEntry(collection, existingUnpublishedEntry) {
serializedEntryDraft,
assetProxies.toJS(),
state.integrations,
selectedSlug,
unavailableSlugs,
];

Expand All @@ -358,6 +366,10 @@ export function persistUnpublishedEntry(collection, existingUnpublishedEntry) {
}),
);
dispatch(unpublishedEntryPersisted(collection, serializedEntry, transactionID, newSlug));
if (slugChanged && selectUnpublishedEntry(state, collection.get('name'), entrySlug)) {
// Delete previous entry
dispatch(deleteUnpublishedEntry(collection.get('name'), entrySlug));
}
} catch (error) {
dispatch(
notifSend({
Expand Down Expand Up @@ -456,6 +468,10 @@ export function publishUnpublishedEntry(collection, slug) {
const state = getState();
const backend = currentBackend(state.config);
const transactionID = uuid();
const unpublishedEntry = selectUnpublishedEntry(state, collection, slug);
const parentSlug = unpublishedEntry.getIn(['metaData', 'parentSlug']);
const slugChanged = parentSlug && parentSlug !== slug;

dispatch(unpublishedEntryPublishRequest(collection, slug, transactionID));
return backend
.publishUnpublishedEntry(collection, slug)
Expand All @@ -468,6 +484,10 @@ export function publishUnpublishedEntry(collection, slug) {
}),
);
dispatch(unpublishedEntryPublished(collection, slug, transactionID));
if (slugChanged) {
// Delete parent entry
dispatch(deleteEntry(state.collections.get(collection), parentSlug));
}
})
.catch(error => {
dispatch(
Expand Down
18 changes: 14 additions & 4 deletions packages/netlify-cms-core/src/actions/entries.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ export function entryPersisted(collection, entry, slug) {
payload: {
collectionName: collection.get('name'),
entrySlug: entry.get('slug'),
slugField: selectSlugField(collection),
/**
* Pass slug from backend for newly created entries.
*/
Expand Down Expand Up @@ -202,10 +201,10 @@ export function changeDraft(entry) {
};
}

export function changeDraftField(field, value, metadata) {
export function changeDraftField(field, value, metadata, hasChanged = true) {
return {
type: DRAFT_CHANGE_FIELD,
payload: { field, value, metadata },
payload: { field, value, metadata, hasChanged },
};
}

Expand Down Expand Up @@ -438,9 +437,15 @@ export function persistEntry(collection) {
* update the entry and entryDraft with the serialized values.
*/
const fields = selectFields(collection, entry.get('slug'));
const slugField = selectSlugField(collection);
const serializedData = serializeValues(entryDraft.getIn(['entry', 'data']), fields);
const serializedEntry = entry.set('data', serializedData);
const serializedEntryDraft = entryDraft.set('entry', serializedEntry);
const manualSlug = slugField && serializedData.get(slugField);
const entrySlug = serializedEntry.get('slug');
const selectedSlug = manualSlug || entrySlug;
const slugChanged = manualSlug && entrySlug && manualSlug !== entrySlug;

dispatch(entryPersisting(collection, serializedEntry));
return backend
.persistEntry(
Expand All @@ -449,6 +454,7 @@ export function persistEntry(collection) {
serializedEntryDraft,
assetProxies.toJS(),
state.integrations,
selectedSlug,
unavailableSlugs,
)
.then(slug => {
Expand All @@ -462,6 +468,10 @@ export function persistEntry(collection) {
}),
);
dispatch(entryPersisted(collection, serializedEntry, slug));
if (slugChanged) {
// Delete previous entry
dispatch(deleteEntry(collection, entrySlug));
}
})
.catch(error => {
console.error(error);
Expand Down Expand Up @@ -508,7 +518,7 @@ export function deleteEntry(collection, slug) {
};
}

export function autoSlugValue(collection) {
export function getSlug(collection) {
return (entryData, config, unavailableSlugs) => {
return slugFormatter(collection, entryData, config, unavailableSlugs);
};
Expand Down
36 changes: 22 additions & 14 deletions packages/netlify-cms-core/src/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,15 @@ export const generateUniqueSlug = (slug, slugConfig, publishedOrDraftSlugs) => {
let sanitizedSlug = sanitizeSlug(slug, slugConfig);
let uniqueSlug = sanitizedSlug;
while (publishedOrDraftSlugs.includes(uniqueSlug)) {
uniqueSlug = sanitizeSlug(`${sanitizedSlug} ${i++}`, slugConfig);
uniqueSlug = sanitizeSlug(`${sanitizedSlug} ${i++}`, slugConfig)
// Remove single quotes.
.replace(/[']/g, '')

// Replace periods with dashes.
.replace(/[.]/g, '-')

// Convert slug to lower-case
.toLocaleLowerCase();
}
return uniqueSlug;
};
Expand Down Expand Up @@ -381,12 +389,12 @@ class Backend {
entryDraft,
MediaFiles,
integrations,
selectedSlug,
unavailableSlugs,
options = {},
) {
const newEntry = entryDraft.getIn(['entry', 'newRecord']) || false;
const slugField = selectSlugField(collection);
const manualSlug = entryDraft.getIn(['entry', 'data', slugField], '');

const parsedData = {
title: entryDraft.getIn(['entry', 'data', 'title'], 'No Title'),
Expand All @@ -404,27 +412,28 @@ class Backend {
config.get('slug'),
unavailableSlugs,
);
const slug = manualSlug || autoSlug;
const slug = selectedSlug || autoSlug;

const path = selectEntryPath(collection, slug);
entryObj = {
path,
slug,
slugChanged: false,
raw: this.entryToRaw(collection, entryDraft.get('entry'), slugField),
};
} else {
let path = entryDraft.getIn(['entry', 'path']);
let slug = entryDraft.getIn(['entry', 'slug']);
if (manualSlug && manualSlug != slug) {
Object.assign(options, { oldSlug: slug, oldPath: path });
path = selectEntryPath(collection, manualSlug);
slug = manualSlug;
}
const path = entryDraft.getIn(['entry', 'path']);
const slug = entryDraft.getIn(['entry', 'slug']);
const selectedPath = selectEntryPath(collection, selectedSlug);
entryObj = {
path,
slug,
path: selectedPath,
slug: selectedSlug,
slugChanged: false,
raw: this.entryToRaw(collection, entryDraft.get('entry'), slugField),
};
if (selectedSlug !== slug) {
Object.assign(entryObj, { slugChanged: true, oldSlug: slug, oldPath: path });
}
}

const commitMessage = commitMessageFormatter(newEntry ? 'create' : 'update', config, {
Expand All @@ -447,7 +456,6 @@ class Backend {
parsedData,
commitMessage,
collectionName,
manualSlug,
useWorkflow,
...updatedOptions,
};
Expand Down Expand Up @@ -497,7 +505,7 @@ class Backend {
entryToRaw(collection, entry, slugField) {
const format = resolveFormat(collection, entry.toJS());
const fieldsOrder = this.fieldsOrder(collection, entry);
// Remove slug field value
// Remove slug field and value
const data = entry.get('data').delete(slugField);
return format && format.toFile(data.toJS(), fieldsOrder);
}
Expand Down
Loading

0 comments on commit 05aa868

Please sign in to comment.