Skip to content

Commit

Permalink
Feat/collection config (#118)
Browse files Browse the repository at this point in the history
* Feat/get all collections directories (#117)

* feat: add RootType Directory

This commit adds a RootType to the Directory class so that we can
retrieve directories from the root of a repo.

* feat: new endpoint for retrieving information on all folders

This commit introduces a new GET `/:siteName/folders/all` endpoint
which:
1) gets the names of all collections/folders within the repo
2) gets the collection.yml directory config file for each collection

* fix: remove _ before sending folder name

Co-authored-by: jiehao <[email protected]>

* feat: create CollectionConfig which extends Config class, with methods for creating and deleting the collection.yml file

* feat: updates Collection class to use CollectionConfig for create, delete and rename functions

* fix: updates folders listAll route to use CollectionConfig

* fix: adds more details to inline comment for .list()

* feat: adds functions to support adding and removing item from CollectionConfig

* fix: removes endpoint variable

* fix: uses passed siteName variable instead of class variable

* fix: destructures err response status

* fix: allows Collection.create to take in optional orderArray

* fix: rename config to collectionConfig in Collection for clarity

* fix: updates Collection.rename to modify collectionName in collection.yml after git tree changes

* fix: typo in variable names

Co-authored-by: kwajiehao <[email protected]>
Co-authored-by: jiehao <[email protected]>
  • Loading branch information
3 people authored Mar 4, 2021
1 parent b5e3e3b commit c5d982c
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 46 deletions.
60 changes: 28 additions & 32 deletions classes/Collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const base64 = require('base-64')
const Bluebird = require('bluebird')
const _ = require('lodash')

const { Config } = require('./Config.js')
const { Config, CollectionConfig } = require('./Config.js')
const { File, CollectionPageType, DataType } = require('./File.js')
const { getCommitAndTreeSha, getTree, sendTree, deslugifyCollectionName } = require('../utils/utils.js')

Expand All @@ -16,6 +16,7 @@ class Collection {
}

async list() {
// to be removed in future PRs as collection data is no longer stored in _config.yml
try {
const config = new Config(this.accessToken, this.siteName)
const { content, sha } = await config.read()
Expand All @@ -29,18 +30,17 @@ class Collection {

async create(collectionName) {
try {
const config = new Config(this.accessToken, this.siteName)
const { content, sha } = await config.read()
const contentObject = yaml.safeLoad(base64.decode(content))

// TO-DO: Verify that collection doesn't already exist

contentObject.collections[`${collectionName}`] = {
output: true
const collectionConfig = new CollectionConfig(this.accessToken, this.siteName, collectionName)
const contentObject = {
collections: {
[collectionName]: {
output: true,
order: orderArray || [],
},
}
}
const newContent = base64.encode(yaml.safeDump(contentObject))

await config.update(newContent, sha)
await collectionConfig.create(newContent)

const nav = new File(this.accessToken, this.siteName)
const dataType = new DataType()
Expand All @@ -63,15 +63,10 @@ class Collection {

async delete(collectionName) {
try {
// Delete collection in config
const config = new Config(this.accessToken, this.siteName)
const { content, sha } = await config.read()
const contentObject = yaml.safeLoad(base64.decode(content))

delete contentObject.collections[`${collectionName}`]
const newContent = base64.encode(yaml.safeDump(contentObject))

await config.update(newContent, sha)
// Delete collection config
const collectionConfig = new CollectionConfig(this.accessToken, this.siteName, collectionName)
const { sha } = await collectionConfig.read()
await collectionConfig.delete(sha)

// Delete collection in nav if it exists
const nav = new File(this.accessToken, this.siteName)
Expand Down Expand Up @@ -110,18 +105,6 @@ class Collection {
async rename(oldCollectionName, newCollectionName) {
try {
const commitMessage = `Rename collection from ${oldCollectionName} to ${newCollectionName}`
// Rename collection in config
const config = new Config(this.accessToken, this.siteName)
const { content, sha } = await config.read()
const contentObject = yaml.safeLoad(base64.decode(content))

contentObject.collections[`${newCollectionName}`] = {
output: true
}
delete contentObject.collections[`${oldCollectionName}`]
const newContent = base64.encode(yaml.safeDump(contentObject))

await config.update(newContent, sha)

// Rename collection in nav if it exists
const nav = new File(this.accessToken, this.siteName)
Expand Down Expand Up @@ -162,6 +145,19 @@ class Collection {
}
})
await sendTree(newGitTree, currentCommitSha, this.siteName, this.accessToken, commitMessage);

// Update collection.yml in newCollection with newCollection name
const collectionConfig = new CollectionConfig(this.accessToken, this.siteName, newCollectionName)
const { content: configContent, sha: configSha } = await collectionConfig.read()
const configContentObject = yaml.safeLoad(base64.decode(configContent))
const newConfigContentObject = {
collections: {
[newCollectionName]: configContentObject.collections[oldCollectionName]
}
}
const newConfigContent = base64.encode(yaml.safeDump(newConfigContentObject))
await collectionConfig.update(newConfigContent, configSha)

} catch (err) {
throw err
}
Expand Down
106 changes: 99 additions & 7 deletions classes/Config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
const axios = require('axios');
const validateStatus = require('../utils/axios-utils')
const yaml = require('js-yaml')
const base64 = require('base-64')
const _ = require('lodash')

// Import logger
const logger = require('../logger/logger');
Expand All @@ -14,17 +17,16 @@ class Config {
constructor(accessToken, siteName) {
this.accessToken = accessToken
this.siteName = siteName
this.endpoint = `https://api.github.com/repos/${GITHUB_ORG_NAME}/${this.siteName}/contents/_config.yml`
}

async read() {
try {
const endpoint = `https://api.github.com/repos/${GITHUB_ORG_NAME}/${this.siteName}/contents/_config.yml`

const params = {
"ref": BRANCH_REF,
}

const resp = await axios.get(endpoint, {
const resp = await axios.get(this.endpoint, {
validateStatus,
params,
headers: {
Expand All @@ -45,16 +47,14 @@ class Config {
}

async update(newContent, sha) {
const endpoint = `https://api.github.com/repos/${GITHUB_ORG_NAME}/${this.siteName}/contents/_config.yml`

const params = {
"message": 'Edit config',
"content": newContent,
"branch": BRANCH_REF,
"sha": sha
}

await axios.put(endpoint, params, {
await axios.put(this.endpoint, params, {
headers: {
Authorization: `token ${this.accessToken}`,
"Content-Type": "application/json"
Expand All @@ -63,4 +63,96 @@ class Config {
}
}

module.exports = { Config }
class CollectionConfig extends Config {
constructor(accessToken, siteName, collectionName) {
super(accessToken, siteName)
this.collectionName = collectionName
this.endpoint = `https://api.github.com/repos/${GITHUB_ORG_NAME}/${siteName}/contents/_${collectionName}/collection.yml`
}

async create(content) {
try {
const params = {
"message": `Create file: _${this.collectionName}/collection.yml`,
"content": content,
"branch": BRANCH_REF,
}

const resp = await axios.put(this.endpoint, params, {
headers: {
Authorization: `token ${this.accessToken}`,
"Content-Type": "application/json"
}
})

return { sha: resp.data.content.sha }
} catch (err) {
const { status } = err.response
if (status === 422 || status === 409) throw new ConflictError(inputNameConflictErrorMsg(fileName))
throw err.response
}
}


async delete (sha) {
try {
const params = {
"message": `Delete file: _${this.collectionName}/collection.yml`,
"branch": BRANCH_REF,
"sha": sha
}

await axios.delete(this.endpoint, {
params,
headers: {
Authorization: `token ${this.accessToken}`,
"Content-Type": "application/json"
}
})
} catch (err) {
const status = err.response.status
if (status === 404) throw new NotFoundError ('File does not exist')
throw err
}
}

async addItemToOrder(item) {
const collectionName = this.collectionName

const { content, sha } = await this.read()
const contentObject = yaml.safeLoad(base64.decode(content))

let index
if (item.split('/').length === 2) {
// if file in subfolder, get index of last file in subfolder
index = _.findLastIndex(
contentObject.collections[collectionName].order,
(f) => f.split('/')[0] === item.split('/')[0]
) + 1
} else {
// get index of last file in collection
index = contentObject.collections[collectionName].order.length
}
contentObject.collections[collectionName].order.splice(index, 0, item)
const newContent = base64.encode(yaml.safeDump(contentObject))

await this.update(newContent, sha)
}

async deleteItemFromOrder(item) {
const collectionName = this.collectionName

const { content, sha } = await this.read()
const contentObject = yaml.safeLoad(base64.decode(content))

const index = contentObject.collections[collectionName].order.indexOf(item);
contentObject.collections[collectionName].order.splice(index, 1)
const newContent = base64.encode(yaml.safeDump(contentObject))

await this.update(newContent, sha)
}
}



module.exports = { Config, CollectionConfig }
13 changes: 6 additions & 7 deletions routes/folders.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ const Bluebird = require('bluebird')
const { attachReadRouteHandlerWrapper } = require('../middleware/routeHandler')

// Import classes
const { File, CollectionPageType } = require('../classes/File.js');
const { Directory, RootType, FolderType } = require('../classes/Directory.js');
const { CollectionConfig } = require('../classes/Config')
const { Directory, RootType, FolderType } = require('../classes/Directory');

const ISOMER_TEMPLATE_DIRS = ['_data', '_includes', '_site', '_layouts']

Expand Down Expand Up @@ -44,11 +44,10 @@ async function listAllFolderContent (req, res, next) {
}, [])

const allFolderContent = await Bluebird.map(allFolders, async (folder) => {
const IsomerFile = new File(accessToken, siteName)
const collectionPageType = new CollectionPageType(folder.slice(1))
IsomerFile.setFileType(collectionPageType)
const { sha, content } = await IsomerFile.read('collection.yml')
return { name: folder.slice(1), sha, content }
const collectionName = folder.slice(1)
const config = new CollectionConfig(accessToken, siteName, collectionName)
const { sha, content } = await config.read()
return { name: collectionName, sha, content }
})

res.status(200).json({ allFolderContent })
Expand Down

0 comments on commit c5d982c

Please sign in to comment.