Feat: multi content authoring (#4139)

This commit is contained in:
Erez Rokah
2020-09-20 10:30:46 -07:00
committed by GitHub
parent 7968e01e29
commit cb2ad687ee
65 changed files with 4331 additions and 1521 deletions

View File

@ -51,8 +51,11 @@ describe('test backend implementation', () => {
const backend = new TestBackend({});
const entry = { path: 'posts/some-post.md', raw: 'content', slug: 'some-post.md' };
await backend.persistEntry(entry, [], { newEntry: true });
const entry = {
dataFiles: [{ path: 'posts/some-post.md', raw: 'content', slug: 'some-post.md' }],
assets: [],
};
await backend.persistEntry(entry, { newEntry: true });
expect(window.repoFiles).toEqual({
posts: {
@ -80,8 +83,11 @@ describe('test backend implementation', () => {
const backend = new TestBackend({});
const entry = { path: 'posts/new-post.md', raw: 'content', slug: 'new-post.md' };
await backend.persistEntry(entry, [], { newEntry: true });
const entry = {
dataFiles: [{ path: 'posts/new-post.md', raw: 'content', slug: 'new-post.md' }],
assets: [],
};
await backend.persistEntry(entry, { newEntry: true });
expect(window.repoFiles).toEqual({
pages: {
@ -108,8 +114,8 @@ describe('test backend implementation', () => {
const slug = 'dir1/dir2/some-post.md';
const path = `posts/${slug}`;
const entry = { path, raw: 'content', slug };
await backend.persistEntry(entry, [], { newEntry: true });
const entry = { dataFiles: [{ path, raw: 'content', slug }], assets: [] };
await backend.persistEntry(entry, { newEntry: true });
expect(window.repoFiles).toEqual({
posts: {
@ -143,8 +149,8 @@ describe('test backend implementation', () => {
const slug = 'dir1/dir2/some-post.md';
const path = `posts/${slug}`;
const entry = { path, raw: 'new content', slug };
await backend.persistEntry(entry, [], { newEntry: false });
const entry = { dataFiles: [{ path, raw: 'new content', slug }], assets: [] };
await backend.persistEntry(entry, { newEntry: false });
expect(window.repoFiles).toEqual({
posts: {
@ -161,7 +167,7 @@ describe('test backend implementation', () => {
});
});
describe('deleteFile', () => {
describe('deleteFiles', () => {
it('should delete entry by path', async () => {
window.repoFiles = {
posts: {
@ -173,7 +179,7 @@ describe('test backend implementation', () => {
const backend = new TestBackend({});
await backend.deleteFile('posts/some-post.md');
await backend.deleteFiles(['posts/some-post.md']);
expect(window.repoFiles).toEqual({
posts: {},
});
@ -194,7 +200,7 @@ describe('test backend implementation', () => {
const backend = new TestBackend({});
await backend.deleteFile('posts/dir1/dir2/some-post.md');
await backend.deleteFiles(['posts/dir1/dir2/some-post.md']);
expect(window.repoFiles).toEqual({
posts: {
dir1: {

View File

@ -13,6 +13,7 @@ import {
User,
Config,
ImplementationFile,
DataFile,
} from 'netlify-cms-lib-util';
import { extname, dirname } from 'path';
import AuthenticationPage from './AuthenticationPage';
@ -20,18 +21,20 @@ import AuthenticationPage from './AuthenticationPage';
type RepoFile = { path: string; content: string | AssetProxy };
type RepoTree = { [key: string]: RepoFile | RepoTree };
type Diff = {
id: string;
originalPath?: string;
path: string;
newFile: boolean;
status: string;
content: string | AssetProxy;
};
type UnpublishedRepoEntry = {
slug: string;
collection: string;
status: string;
diffs: {
id: string;
originalPath?: string;
path: string;
newFile: boolean;
status: string;
content: string | AssetProxy;
}[];
diffs: Diff[];
updatedAt: string;
};
@ -257,24 +260,25 @@ export default class TestBackend implements Implementation {
async addOrUpdateUnpublishedEntry(
key: string,
path: string,
newPath: string | undefined,
raw: string,
dataFiles: DataFile[],
assetProxies: AssetProxy[],
slug: string,
collection: string,
status: string,
) {
const currentDataFile = window.repoFilesUnpublished[key]?.diffs.find(d => d.path === path);
const originalPath = currentDataFile ? currentDataFile.originalPath : path;
const diffs = [];
diffs.push({
originalPath,
id: newPath || path,
path: newPath || path,
newFile: isEmpty(getFile(originalPath as string, window.repoFiles)),
status: 'added',
content: raw,
const diffs: Diff[] = [];
dataFiles.forEach(dataFile => {
const { path, newPath, raw } = dataFile;
const currentDataFile = window.repoFilesUnpublished[key]?.diffs.find(d => d.path === path);
const originalPath = currentDataFile ? currentDataFile.originalPath : path;
diffs.push({
originalPath,
id: newPath || path,
path: newPath || path,
newFile: isEmpty(getFile(originalPath as string, window.repoFiles)),
status: 'added',
content: raw,
});
});
assetProxies.forEach(a => {
const asset = this.normalizeAsset(a);
@ -295,22 +299,18 @@ export default class TestBackend implements Implementation {
};
}
async persistEntry(
{ path, raw, slug, newPath }: Entry,
assetProxies: AssetProxy[],
options: PersistOptions,
) {
async persistEntry(entry: Entry, options: PersistOptions) {
if (options.useWorkflow) {
const slug = entry.dataFiles[0].slug;
const key = `${options.collectionName}/${slug}`;
const currentEntry = window.repoFilesUnpublished[key];
const status =
currentEntry?.status || options.status || (this.options.initialWorkflowStatus as string);
this.addOrUpdateUnpublishedEntry(
key,
path,
newPath,
raw,
assetProxies,
entry.dataFiles,
entry.assets,
slug,
options.collectionName as string,
status,
@ -318,9 +318,12 @@ export default class TestBackend implements Implementation {
return Promise.resolve();
}
writeFile(path, raw, window.repoFiles);
assetProxies.forEach(a => {
writeFile(a.path, raw, window.repoFiles);
entry.dataFiles.forEach(dataFile => {
const { path, raw } = dataFile;
writeFile(path, raw, window.repoFiles);
});
entry.assets.forEach(a => {
writeFile(a.path, a, window.repoFiles);
});
return Promise.resolve();
}
@ -409,8 +412,10 @@ export default class TestBackend implements Implementation {
return Promise.resolve(normalizedAsset);
}
deleteFile(path: string) {
deleteFile(path, window.repoFiles);
deleteFiles(paths: string[]) {
paths.forEach(path => {
deleteFile(path, window.repoFiles);
});
return Promise.resolve();
}