Feat: multi content authoring (#4139)
This commit is contained in:
@ -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: {
|
||||
|
@ -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();
|
||||
}
|
||||
|
Reference in New Issue
Block a user