feat: content in sub folders (#2897)
This commit is contained in:
committed by
Shawn Erquhart
parent
766ade1a3c
commit
afcfe5b6d5
@ -155,6 +155,14 @@ export default class API {
|
||||
return `${this.repo}/${collectionName}/${slug}`;
|
||||
}
|
||||
|
||||
slugFromContentKey(contentKey, collectionName) {
|
||||
if (!this.useOpenAuthoring) {
|
||||
return contentKey.substring(collectionName.length + 1);
|
||||
}
|
||||
|
||||
return contentKey.substring(this.repo.length + collectionName.length + 2);
|
||||
}
|
||||
|
||||
generateBranchName(contentKey) {
|
||||
return `${CMS_BRANCH_PREFIX}/${contentKey}`;
|
||||
}
|
||||
@ -365,7 +373,9 @@ export default class API {
|
||||
|
||||
listFiles(path, { repoURL = this.repoURL, branch = this.branch } = {}) {
|
||||
const folderPath = path.replace(/\/$/, '');
|
||||
return this.request(`${repoURL}/git/trees/${branch}:${folderPath}`).then(res =>
|
||||
return this.request(`${repoURL}/git/trees/${branch}:${folderPath}`, {
|
||||
params: { recursive: 10 },
|
||||
}).then(res =>
|
||||
res.tree
|
||||
.filter(file => file.type === 'blob')
|
||||
.map(file => ({
|
||||
@ -448,8 +458,9 @@ export default class API {
|
||||
const { state: currentState, merged_at: mergedAt } = originPRInfo;
|
||||
if (currentState === 'closed' && mergedAt) {
|
||||
// The PR has been merged; delete the unpublished entry
|
||||
const [, collectionName, slug] = contentKey.split('/');
|
||||
this.deleteUnpublishedEntry(collectionName, slug);
|
||||
const { collection } = metadata;
|
||||
const slug = this.slugFromContentKey(contentKey, collection);
|
||||
this.deleteUnpublishedEntry(collection, slug);
|
||||
return;
|
||||
} else if (currentState === 'closed' && !mergedAt) {
|
||||
if (status !== 'draft') {
|
||||
|
@ -186,6 +186,26 @@ export default class GraphQLAPI extends API {
|
||||
}
|
||||
}
|
||||
|
||||
getAllFiles(entries, path) {
|
||||
const allFiles = entries.reduce((acc, item) => {
|
||||
if (item.type === 'tree') {
|
||||
return [...acc, ...this.getAllFiles(item.object.entries, `${path}/${item.name}`)];
|
||||
} else if (item.type === 'blob') {
|
||||
return [
|
||||
...acc,
|
||||
{
|
||||
...item,
|
||||
path: `${path}/${item.name}`,
|
||||
size: item.blob && item.blob.size,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
return allFiles;
|
||||
}
|
||||
|
||||
async listFiles(path, { repoURL = this.repoURL, branch = this.branch } = {}) {
|
||||
const { owner, name } = this.getOwnerAndNameFromRepoUrl(repoURL);
|
||||
const { data } = await this.query({
|
||||
@ -194,14 +214,8 @@ export default class GraphQLAPI extends API {
|
||||
});
|
||||
|
||||
if (data.repository.object) {
|
||||
const files = data.repository.object.entries
|
||||
.filter(({ type }) => type === 'blob')
|
||||
.map(e => ({
|
||||
...e,
|
||||
path: `${path}/${e.name}`,
|
||||
size: e.blob && e.blob.size,
|
||||
}));
|
||||
return files;
|
||||
const allFiles = this.getAllFiles(data.repository.object.entries, path);
|
||||
return allFiles;
|
||||
} else {
|
||||
throw new APIError('Not Found', 404, 'GitHub');
|
||||
}
|
||||
|
@ -0,0 +1,72 @@
|
||||
import GraphQLAPI from '../GraphQLAPI';
|
||||
|
||||
global.fetch = jest.fn().mockRejectedValue(new Error('should not call fetch inside tests'));
|
||||
|
||||
describe('github GraphQL API', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe('editorialWorkflowGit', () => {
|
||||
it('should should flatten nested tree into a list of files', () => {
|
||||
const api = new GraphQLAPI({ branch: 'gh-pages', repo: 'my-repo' });
|
||||
const entries = [
|
||||
{
|
||||
name: 'post-1.md',
|
||||
sha: 'sha-1',
|
||||
type: 'blob',
|
||||
blob: { size: 1 },
|
||||
},
|
||||
{
|
||||
name: 'post-2.md',
|
||||
sha: 'sha-2',
|
||||
type: 'blob',
|
||||
blob: { size: 2 },
|
||||
},
|
||||
{
|
||||
name: '2019',
|
||||
sha: 'dir-sha',
|
||||
type: 'tree',
|
||||
object: {
|
||||
entries: [
|
||||
{
|
||||
name: 'nested-post.md',
|
||||
sha: 'nested-post-sha',
|
||||
type: 'blob',
|
||||
blob: { size: 3 },
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
const path = 'posts';
|
||||
|
||||
expect(api.getAllFiles(entries, path)).toEqual([
|
||||
{
|
||||
name: 'post-1.md',
|
||||
sha: 'sha-1',
|
||||
type: 'blob',
|
||||
size: 1,
|
||||
path: 'posts/post-1.md',
|
||||
blob: { size: 1 },
|
||||
},
|
||||
{
|
||||
name: 'post-2.md',
|
||||
sha: 'sha-2',
|
||||
type: 'blob',
|
||||
size: 2,
|
||||
path: 'posts/post-2.md',
|
||||
blob: { size: 2 },
|
||||
},
|
||||
{
|
||||
name: 'nested-post.md',
|
||||
sha: 'nested-post-sha',
|
||||
type: 'blob',
|
||||
size: 3,
|
||||
path: 'posts/2019/nested-post.md',
|
||||
blob: { size: 3 },
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
@ -389,7 +389,6 @@ export default class GitHub {
|
||||
promises.push(
|
||||
new Promise(resolve => {
|
||||
const contentKey = this.api.contentKeyFromRef(ref);
|
||||
const slug = contentKey.split('/').pop();
|
||||
return sem.take(() =>
|
||||
this.api
|
||||
.readUnpublishedBranchFile(contentKey)
|
||||
@ -399,7 +398,7 @@ export default class GitHub {
|
||||
sem.leave();
|
||||
} else {
|
||||
resolve({
|
||||
slug,
|
||||
slug: this.api.slugFromContentKey(contentKey, data.metaData.collection),
|
||||
file: { path: data.metaData.objects.entry.path },
|
||||
data: data.fileData,
|
||||
metaData: data.metaData,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import gql from 'graphql-tag';
|
||||
import { oneLine } from 'common-tags';
|
||||
import * as fragments from './fragments';
|
||||
|
||||
export const repoPermission = gql`
|
||||
@ -92,17 +93,47 @@ export const statues = gql`
|
||||
${fragments.object}
|
||||
`;
|
||||
|
||||
const buildFilesQuery = (depth = 10) => {
|
||||
const PLACE_HOLDER = 'PLACE_HOLDER';
|
||||
let query = oneLine`
|
||||
...ObjectParts
|
||||
... on Tree {
|
||||
entries {
|
||||
...FileEntryParts
|
||||
${PLACE_HOLDER}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
for (let i = 0; i < depth - 1; i++) {
|
||||
query = query.replace(
|
||||
PLACE_HOLDER,
|
||||
oneLine`
|
||||
object {
|
||||
... on Tree {
|
||||
entries {
|
||||
...FileEntryParts
|
||||
${PLACE_HOLDER}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
);
|
||||
}
|
||||
|
||||
query = query.replace(PLACE_HOLDER, '');
|
||||
|
||||
return query;
|
||||
};
|
||||
|
||||
const filesQuery = buildFilesQuery();
|
||||
|
||||
export const files = gql`
|
||||
query files($owner: String!, $name: String!, $expression: String!) {
|
||||
repository(owner: $owner, name: $name) {
|
||||
...RepositoryParts
|
||||
object(expression: $expression) {
|
||||
...ObjectParts
|
||||
... on Tree {
|
||||
entries {
|
||||
...FileEntryParts
|
||||
}
|
||||
}
|
||||
${filesQuery}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user