Skip to content

Commit

Permalink
Feat: nested collections (#3716)
Browse files Browse the repository at this point in the history
  • Loading branch information
erezrokah authored Jun 18, 2020
1 parent b4c47ca commit af7bbbd
Show file tree
Hide file tree
Showing 89 changed files with 6,715 additions and 4,065 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1597,7 +1597,7 @@
"status": 200
},
{
"body": "{\"base_tree\":\"e774625f38ae12e6bdc27574f3238a20bf71b6ca\",\"tree\":[{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":null},{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":\"5ed1cbc40b517ab0b1dba1f9486d6c2723e7020e\"}]}",
"body": "{\"base_tree\":\"e774625f38ae12e6bdc27574f3238a20bf71b6ca\",\"tree\":[{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":\"5ed1cbc40b517ab0b1dba1f9486d6c2723e7020e\"}]}",
"method": "POST",
"url": "/.netlify/git/github/git/trees",
"headers": {
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -1284,7 +1284,7 @@
"status": 200
},
{
"body": "{\"base_tree\":\"d8e02516ac6e201f752b6c1916a2a850fa0ae2eb\",\"tree\":[{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":null},{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":\"5ed1cbc40b517ab0b1dba1f9486d6c2723e7020e\"}]}",
"body": "{\"base_tree\":\"d8e02516ac6e201f752b6c1916a2a850fa0ae2eb\",\"tree\":[{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":\"5ed1cbc40b517ab0b1dba1f9486d6c2723e7020e\"}]}",
"method": "POST",
"url": "/repos/forkOwner/repo/git/trees",
"headers": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,7 @@
"status": 200
},
{
"body": "{\"base_tree\":\"8ac793644b57607b35a15858b44ed7d90b794e73\",\"tree\":[{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":null},{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":\"5ed1cbc40b517ab0b1dba1f9486d6c2723e7020e\"}]}",
"body": "{\"base_tree\":\"8ac793644b57607b35a15858b44ed7d90b794e73\",\"tree\":[{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":\"5ed1cbc40b517ab0b1dba1f9486d6c2723e7020e\"}]}",
"method": "POST",
"url": "/repos/owner/repo/git/trees",
"headers": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,7 @@
"status": 200
},
{
"body": "{\"base_tree\":\"c502fbb54c429d6b7fc056e86ad5739bb96283a0\",\"tree\":[{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":null},{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":\"5ed1cbc40b517ab0b1dba1f9486d6c2723e7020e\"}]}",
"body": "{\"base_tree\":\"c502fbb54c429d6b7fc056e86ad5739bb96283a0\",\"tree\":[{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":\"5ed1cbc40b517ab0b1dba1f9486d6c2723e7020e\"}]}",
"method": "POST",
"url": "/repos/owner/repo/git/trees",
"headers": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1462,7 +1462,7 @@
"status": 200
},
{
"body": "{\"base_tree\":\"a9e732737e1a806d311ba91ff6c42de528a69b5d\",\"tree\":[{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":null},{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":\"5ed1cbc40b517ab0b1dba1f9486d6c2723e7020e\"}]}",
"body": "{\"base_tree\":\"a9e732737e1a806d311ba91ff6c42de528a69b5d\",\"tree\":[{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":\"5ed1cbc40b517ab0b1dba1f9486d6c2723e7020e\"}]}",
"method": "POST",
"url": "/repos/forkOwner/repo/git/trees",
"headers": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1286,7 +1286,7 @@
"status": 200
},
{
"body": "{\"base_tree\":\"49f07bd3fa298db5d2f430a5b04bbfa60978eed8\",\"tree\":[{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":null},{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":\"5ed1cbc40b517ab0b1dba1f9486d6c2723e7020e\"}]}",
"body": "{\"base_tree\":\"49f07bd3fa298db5d2f430a5b04bbfa60978eed8\",\"tree\":[{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":\"5ed1cbc40b517ab0b1dba1f9486d6c2723e7020e\"}]}",
"method": "POST",
"url": "/repos/owner/repo/git/trees",
"headers": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1234,7 +1234,7 @@
"status": 200
},
{
"body": "{\"base_tree\":\"1c11a4511b2208a3a3d159035962f5ac267df45c\",\"tree\":[{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":null},{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":\"5ed1cbc40b517ab0b1dba1f9486d6c2723e7020e\"}]}",
"body": "{\"base_tree\":\"1c11a4511b2208a3a3d159035962f5ac267df45c\",\"tree\":[{\"path\":\"content/posts/1970-01-01-first-title.md\",\"mode\":\"100644\",\"type\":\"blob\",\"sha\":\"5ed1cbc40b517ab0b1dba1f9486d6c2723e7020e\"}]}",
"method": "POST",
"url": "/repos/owner/repo/git/trees",
"headers": {
Expand Down
123 changes: 122 additions & 1 deletion cypress/integration/editorial_workflow_spec_test_backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ import {
populateEntry,
publishAndCreateNewEntryInEditor,
publishAndDuplicateEntryInEditor,
assertNotification,
assertFieldValidationError,
} from '../utils/steps';
import { workflowStatus, editorStatus, publishTypes } from '../utils/constants';
import { workflowStatus, editorStatus, publishTypes, notifications } from '../utils/constants';

const entry1 = {
title: 'first title',
Expand Down Expand Up @@ -192,4 +194,123 @@ describe('Test Backend Editorial Workflow', () => {
updateWorkflowStatusInEditor(editorStatus.ready);
publishAndDuplicateEntryInEditor(entry1);
});

const inSidebar = func => {
cy.get('[class*=SidebarNavList]').within(func);
};

const inGrid = func => {
cy.get('[class*=CardsGrid]').within(func);
};

it('can access nested collection items', () => {
login();

inSidebar(() => cy.contains('a', 'Pages').click());
inSidebar(() => cy.contains('a', 'Directory'));
inGrid(() => cy.contains('a', 'Root Page'));
inGrid(() => cy.contains('a', 'Directory'));

inSidebar(() => cy.contains('a', 'Directory').click());

inGrid(() => cy.contains('a', 'Sub Directory'));
inGrid(() => cy.contains('a', 'Another Sub Directory'));

inSidebar(() => cy.contains('a', 'Sub Directory').click());
inGrid(() => cy.contains('a', 'Nested Directory'));
cy.url().should(
'eq',
'http://localhost:8080/#/collections/pages/filter/directory/sub-directory',
);

inSidebar(() => cy.contains('a', 'Pages').click());
inSidebar(() => cy.contains('a', 'Pages').click());

inGrid(() => cy.contains('a', 'Another Sub Directory').should('not.exist'));
});

it('can navigate to nested entry', () => {
login();

inSidebar(() => cy.contains('a', 'Pages').click());
inSidebar(() => cy.contains('a', 'Directory').click());
inGrid(() => cy.contains('a', 'Another Sub Directory').click());

cy.url().should(
'eq',
'http://localhost:8080/#/collections/pages/entries/directory/another-sub-directory/index',
);
});

it(`can create a new entry with custom path`, () => {
login();

inSidebar(() => cy.contains('a', 'Pages').click());
inSidebar(() => cy.contains('a', 'Directory').click());
inSidebar(() => cy.contains('a', 'Sub Directory').click());
cy.contains('a', 'New Page').click();

cy.get('[id^="path-field"]').should('have.value', 'directory/sub-directory');
cy.get('[id^="path-field"]').type('/new-path');
cy.get('[id^="title-field"]').type('New Path Title');
cy.clock().then(clock => {
clock.tick(150);
});
cy.contains('button', 'Save').click();
assertNotification(notifications.saved);
updateWorkflowStatusInEditor(editorStatus.ready);
publishEntryInEditor(publishTypes.publishNow);
exitEditor();

inGrid(() => cy.contains('a', 'New Path Title'));
inSidebar(() => cy.contains('a', 'Directory').click());
inSidebar(() => cy.contains('a', 'Directory').click());
inGrid(() => cy.contains('a', 'New Path Title').should('not.exist'));
});

it(`can't create an entry with an existing path`, () => {
login();

inSidebar(() => cy.contains('a', 'Pages').click());
inSidebar(() => cy.contains('a', 'Directory').click());
inSidebar(() => cy.contains('a', 'Sub Directory').click());

cy.contains('a', 'New Page').click();
cy.get('[id^="title-field"]').type('New Path Title');
cy.clock().then(clock => {
clock.tick(150);
});
cy.contains('button', 'Save').click();

assertFieldValidationError({
message: `Path 'directory/sub-directory' already exists`,
fieldLabel: 'Path',
});
});

it('can move an existing entry to a new path', () => {
login();

inSidebar(() => cy.contains('a', 'Pages').click());
inGrid(() => cy.contains('a', 'Directory').click());

cy.get('[id^="path-field"]').should('have.value', 'directory');
cy.get('[id^="path-field"]').clear();
cy.get('[id^="path-field"]').type('new-directory');
cy.get('[id^="title-field"]').clear();
cy.get('[id^="title-field"]').type('New Directory');
cy.clock().then(clock => {
clock.tick(150);
});
cy.contains('button', 'Save').click();
assertNotification(notifications.saved);
updateWorkflowStatusInEditor(editorStatus.ready);
publishEntryInEditor(publishTypes.publishNow);
exitEditor();

inSidebar(() => cy.contains('a', 'New Directory').click());

inGrid(() => cy.contains('a', 'Sub Directory'));
inGrid(() => cy.contains('a', 'Another Sub Directory'));
});
});
1 change: 1 addition & 0 deletions cypress/integration/simple_workflow_spec_test_backend.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import '../utils/dismiss-local-backup';
import {
login,
newPost,
Expand Down
2 changes: 1 addition & 1 deletion cypress/plugins/gitlab.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ async function deleteRepositories({ owner, repo, tempDir }) {
console.log('Deleting repository', `${owner}/${repo}`);
await fs.remove(tempDir);

let client = getGitLabClient(token);
const client = getGitLabClient(token);
await client.Projects.remove(`${owner}/${repo}`).catch(errorHandler);
}

Expand Down
4 changes: 2 additions & 2 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ const matchRoute = (route, fetchArgs) => {
const options = fetchArgs[1];

const method = options && options.method ? options.method : 'GET';
let body = options && options.body;
let routeBody = route.body;
const body = options && options.body;
const routeBody = route.body;

let bodyMatch = false;
if (routeBody?.encoding === 'base64' && ['File', 'Blob'].includes(body?.constructor.name)) {
Expand Down
1 change: 1 addition & 0 deletions cypress/utils/mock-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const retrieveRecordedExpectations = async () => {
(Host.includes('bitbucket.org') && httpRequest.path.includes('info/lfs')) ||
Host.includes('api.media.atlassian.com') ||
Host.some(host => host.includes('netlify.com')) ||
Host.some(host => host.includes('netlify.app')) ||
Host.some(host => host.includes('s3.amazonaws.com'))
);
});
Expand Down
4 changes: 3 additions & 1 deletion cypress/utils/steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function assertColorOn(cssProperty, color, opts) {
}

function exitEditor() {
cy.contains('a[href^="#/collections/"]', 'Writing in').click();
cy.contains('a', 'Writing in').click();
}

function goToWorkflow() {
Expand Down Expand Up @@ -684,4 +684,6 @@ module.exports = {
duplicatePostAndPublish,
publishAndCreateNewEntryInEditor,
publishAndDuplicateEntryInEditor,
assertNotification,
assertFieldValidationError,
};
13 changes: 11 additions & 2 deletions dev-test/backends/test/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ collections: # A list of collections the CMS should be able to edit
tagname: ''

- { label: 'Body', name: 'body', widget: 'markdown', hint: 'Main content goes here.' }
meta:
- { label: 'SEO Description', name: 'description', widget: 'text' }

- name: 'faq' # Used in routes, ie.: /admin/collections/:slug/edit
label: 'FAQ' # Used in the UI
Expand Down Expand Up @@ -247,3 +245,14 @@ collections: # A list of collections the CMS should be able to edit
- { label: 'Date', name: 'date', widget: 'date' }
- { label: 'Image', name: 'image', widget: 'image' }
- { label: 'File', name: 'file', widget: 'file' }
- name: pages # a nested collection
label: Pages
label_singular: 'Page'
folder: _pages
create: true
nested: { depth: 100 }
fields:
- label: Title
name: title
widget: string
meta: { path: { widget: string, label: 'Path', index_file: 'index' } }
30 changes: 30 additions & 0 deletions dev-test/backends/test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,36 @@
content: "---\ntitle: \"This FAQ item # " + i + "\"\ndate: " + dateString + "T00:99:99.999Z\n---\n\n# Loren ipsum dolor sit amet"
}
}
window.repoFiles._pages = {
directory: {
'sub-directory': {
'nested-directory': {
'index.md': {
path: '_pages/directory/sub-directory/nested-directory/index.md',
content: '---\ntitle: "Nested Directory"\n---\n',
},
},
'index.md': {
path: '_pages/directory/sub-directory/index.md',
content: '---\ntitle: "Sub Directory"\n---\n',
},
},
'another-sub-directory': {
'index.md': {
path: '_pages/directory/another-sub-directory/index.md',
content: '---\ntitle: "Another Sub Directory"\n---\n',
},
},
'index.md': {
path: '_pages/directory/index.md',
content: '---\ntitle: "Directory"\n---\n',
},
},
'index.md': {
path: '_pages/index.md',
content: '---\ntitle: "Root Page"\n---\n',
},
};
</script>
</head>
<body>
Expand Down
13 changes: 11 additions & 2 deletions dev-test/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ collections: # A list of collections the CMS should be able to edit
tagname: ''

- { label: 'Body', name: 'body', widget: 'markdown', hint: 'Main content goes here.' }
meta:
- { label: 'SEO Description', name: 'description', widget: 'text' }

- name: 'faq' # Used in routes, ie.: /admin/collections/:slug/edit
label: 'FAQ' # Used in the UI
Expand Down Expand Up @@ -247,3 +245,14 @@ collections: # A list of collections the CMS should be able to edit
- { label: 'Date', name: 'date', widget: 'date' }
- { label: 'Image', name: 'image', widget: 'image' }
- { label: 'File', name: 'file', widget: 'file' }
- name: pages # a nested collection
label: Pages
label_singular: 'Page'
folder: _pages
create: true
nested: { depth: 100 }
fields:
- label: Title
name: title
widget: string
meta: { path: { widget: string, label: 'Path', index_file: 'index' } }
30 changes: 30 additions & 0 deletions dev-test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,36 @@
content: "---\ntitle: \"This FAQ item # " + i + "\"\ndate: " + dateString + "T00:99:99.999Z\n---\n\n# Loren ipsum dolor sit amet"
}
}
window.repoFiles._pages = {
directory: {
'sub-directory': {
'nested-directory': {
'index.md': {
path: '_pages/directory/sub-directory/nested-directory/index.md',
content: '---\ntitle: "Nested Directory"\n---\n',
},
},
'index.md': {
path: '_pages/directory/sub-directory/index.md',
content: '---\ntitle: "Sub Directory"\n---\n',
},
},
'another-sub-directory': {
'index.md': {
path: '_pages/directory/another-sub-directory/index.md',
content: '---\ntitle: "Another Sub Directory"\n---\n',
},
},
'index.md': {
path: '_pages/directory/index.md',
content: '---\ntitle: "Directory"\n---\n',
},
},
'index.md': {
path: '_pages/index.md',
content: '---\ntitle: "Root Page"\n---\n',
},
};
</script>
</head>
<body>
Expand Down
Loading

0 comments on commit af7bbbd

Please sign in to comment.