From 50aa6e5b5d71085acb81c2cfad25e288284d712a Mon Sep 17 00:00:00 2001 From: gweiying <39231249+gweiying@users.noreply.github.com> Date: Wed, 17 Mar 2021 18:29:17 +0800 Subject: [PATCH] Feat/update pageroutes (#133) * 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 * fix: resolving merge conflicts * fix: restores comments that were accidentally deleted * fix: applies missing URI decoding to page routes * fix: updates CollectionConfig to return and accept spliced index * fix: updates renameCollectionPage to use updated CollectionConfig functions * fix: adds updateItemInOrder and read methods to CollectionConfig * fix: updates collectionPages route to use updated CollectionConfig methods * fix: changes updateItemInOrder to use single read and update API call * fix: removes unused imports Co-authored-by: kwajiehao <31984694+kwajiehao@users.noreply.github.com> Co-authored-by: jiehao --- classes/Config.js | 56 ++++++++++++++++++++++++--------------- routes/collectionPages.js | 53 ++++++++++++------------------------ routes/pages.js | 51 +++++++++++++---------------------- 3 files changed, 69 insertions(+), 91 deletions(-) diff --git a/classes/Config.js b/classes/Config.js index 7e82f0a66..37032ea1d 100644 --- a/classes/Config.js +++ b/classes/Config.js @@ -4,9 +4,6 @@ const yaml = require('js-yaml') const base64 = require('base-64') const _ = require('lodash') -// Import logger -const logger = require('../logger/logger'); - // Import error const { NotFoundError } = require('../errors/NotFoundError') const { ConflictError, inputNameConflictErrorMsg } = require('../errors/ConflictError') @@ -116,22 +113,28 @@ class CollectionConfig extends Config { } } - async addItemToOrder(item) { - const collectionName = this.collectionName - - const { content, sha } = await this.read() + async read() { + const { content, sha } = await super.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 + return { contentObject, sha } + } + + async addItemToOrder(item, index) { + const collectionName = this.collectionName + const { contentObject, sha } = await this.read() + + if (index === undefined) { + 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)) @@ -141,12 +144,21 @@ class CollectionConfig extends Config { async deleteItemFromOrder(item) { const collectionName = this.collectionName - - const { content, sha } = await this.read() - const contentObject = yaml.safeLoad(base64.decode(content)) + const { contentObject, sha } = await this.read() + const index = contentObject.collections[collectionName].order.indexOf(item) + contentObject.collections[collectionName].order.splice(index, 1) + const newContent = base64.encode(yaml.safeDump(contentObject)) - const index = contentObject.collections[collectionName].order.indexOf(item); + await this.update(newContent, sha) + return { index, item } + } + + async updateItemInOrder(oldItem, newItem) { + const collectionName = this.collectionName + const { contentObject, sha } = await this.read() + const index = contentObject.collections[collectionName].order.indexOf(oldItem) contentObject.collections[collectionName].order.splice(index, 1) + contentObject.collections[collectionName].order.splice(index, 0, newItem) const newContent = base64.encode(yaml.safeDump(contentObject)) await this.update(newContent, sha) diff --git a/routes/collectionPages.js b/routes/collectionPages.js index 834147811..4ecf35376 100644 --- a/routes/collectionPages.js +++ b/routes/collectionPages.js @@ -16,7 +16,6 @@ const { const { Collection } = require('../classes/Collection') const { CollectionConfig } = require('../classes/Config'); const { File, CollectionPageType } = require('../classes/File'); -const { update } = require('lodash'); // Import utils const { readCollectionPageUtilFunc } = require('../utils/route-utils') @@ -100,30 +99,6 @@ async function listCollectionPagesDetails(req, res, next) { res.status(200).json({ collectionPages: collectionHierarchy }) } -// Create new page in collection -async function createNewcollectionPage (req, res, next) { - const { accessToken } = req - - const { siteName, collectionName } = req.params - const { pageName, content } = req.body - - // Check if collection exists and create if it does not - const IsomerCollection = new Collection(accessToken, siteName) - const collections = await IsomerCollection.list() - if (!collections.includes(collectionName)) { - await IsomerCollection.create(collectionName) - } - // TO-DO: - // Validate pageName and content - - const IsomerFile = new File(accessToken, siteName) - const collectionPageType = new CollectionPageType(collectionName) - IsomerFile.setFileType(collectionPageType) - const { sha } = await IsomerFile.create(pageName, content) - - res.status(200).json({ collectionName, pageName, content, sha }) -} - // // Create new page in collection async function createCollectionPage (req, res, next) { const { accessToken } = req @@ -153,7 +128,8 @@ async function readCollectionPage(req, res, next) { const IsomerFile = new File(accessToken, siteName) const collectionPageType = new CollectionPageType(collectionName) IsomerFile.setFileType(collectionPageType) - const { sha, content } = await IsomerFile.read(pageName) + const { sha, content: encodedContent } = await IsomerFile.read(pageName) + const content = Base64.decode(encodedContent) // TO-DO: // Validate content @@ -166,10 +142,8 @@ async function updateCollectionPage (req, res, next) { const { accessToken } = req const { siteName, pageName: encodedPageName, collectionName } = req.params - const { content: unencodedContent, sha } = req.body + const { content: pageContent, sha } = req.body const pageName = decodeURIComponent(encodedPageName) - - const content = base64.encode(unencodedContent) // TO-DO: // Validate pageName and content @@ -177,9 +151,9 @@ async function updateCollectionPage (req, res, next) { const IsomerFile = new File(accessToken, siteName) const collectionPageType = new CollectionPageType(collectionName) IsomerFile.setFileType(collectionPageType) - const { newSha } = await IsomerFile.update(pageName, content, sha) + const { newSha } = await IsomerFile.update(pageName, Base64.encode(pageContent), sha) - res.status(200).json({ collectionName, pageName, content, sha: newSha }) + res.status(200).json({ collectionName, pageName, pageContent, sha: newSha }) } // Delete page in collection @@ -197,6 +171,9 @@ async function deleteCollectionPage (req, res, next) { IsomerFile.setFileType(collectionPageType) await IsomerFile.delete(pageName, sha) + const collectionConfig = new CollectionConfig(accessToken, siteName, collectionName) + await collectionConfig.deleteItemFromOrder(pageName) + // Check if collection has any pages left, and delete if none left const collectionPages = await IsomerFile.list() if (collectionPages.length === 1 && collectionPages[0].fileName === 'collection.yml') { @@ -211,10 +188,13 @@ async function deleteCollectionPage (req, res, next) { async function renameCollectionPage (req, res, next) { const { accessToken } = req - const { siteName, pageName: encodedPageName, collectionName, newPageName } = req.params - const { sha, content } = req.body + const { siteName, pageName: encodedPageName, collectionName, newPageName: encodedNewPageName } = req.params + const { sha, content: pageContent } = req.body + const pageName = decodeURIComponent(encodedPageName) + const newPageName = decodeURIComponent(encodedNewPageName) + const collectionConfig = new CollectionConfig(accessToken, siteName, collectionName) // TO-DO: // Validate that collection exists // Validate pageName and content @@ -224,15 +204,16 @@ async function renameCollectionPage (req, res, next) { const IsomerFile = new File(accessToken, siteName) const collectionPageType = new CollectionPageType(collectionName) IsomerFile.setFileType(collectionPageType) - const { sha: newSha } = await IsomerFile.create(newPageName, content) + const { sha: newSha } = await IsomerFile.create(newPageName, Base64.encode(pageContent)) await IsomerFile.delete(pageName, sha) + await collectionConfig.updateItemInOrder(pageName, newPageName) + - res.status(200).json({ collectionName, pageName: newPageName, content, sha: newSha }) + res.status(200).json({ collectionName, pageName: newPageName, pageContent, sha: newSha }) } router.get('/:siteName/collections/:collectionName', attachReadRouteHandlerWrapper(listCollectionPages)) router.get('/:siteName/collections/:collectionName/pages', attachReadRouteHandlerWrapper(listCollectionPagesDetails)) -router.post('/:siteName/collections/:collectionName/pages', attachRollbackRouteHandlerWrapper(createNewcollectionPage)) // to remove router.post('/:siteName/collections/:collectionName/pages/new/:pageName', attachRollbackRouteHandlerWrapper(createCollectionPage)) router.get('/:siteName/collections/:collectionName/pages/:pageName', attachReadRouteHandlerWrapper(readCollectionPage)) router.post('/:siteName/collections/:collectionName/pages/:pageName', attachWriteRouteHandlerWrapper(updateCollectionPage)) diff --git a/routes/pages.js b/routes/pages.js index 4eb730927..37ac1ea68 100644 --- a/routes/pages.js +++ b/routes/pages.js @@ -15,8 +15,6 @@ const { // Import classes const { File, PageType, CollectionPageType } = require('../classes/File.js') const { Collection } = require('../classes/Collection.js'); -const { Directory, FolderType } = require('../classes/Directory'); -const { create } = require('lodash'); const { CollectionConfig } = require('../classes/Config'); const { deslugifyCollectionName } = require('../utils/utils') @@ -63,24 +61,6 @@ async function listPages (req, res, next) { res.status(200).json({ pages }) } -// Create new page -async function createNewPage (req, res, next) { - const { accessToken } = req - - const { siteName } = req.params - const { pageName, content } = req.body - - // TO-DO: - // Validate pageName and content - - const IsomerFile = new File(accessToken, siteName) - const pageType = new PageType() - IsomerFile.setFileType(pageType) - const { sha } = await IsomerFile.create(pageName, content) - - res.status(200).json({ pageName, content, sha }) -} - async function createPage (req, res, next) { const { accessToken } = req @@ -100,12 +80,15 @@ async function createPage (req, res, next) { async function readPage(req, res, next) { const { accessToken } = req - const { siteName, pageName } = req.params + const { siteName, pageName: encodedPageName } = req.params + const pageName = decodeURIComponent(encodedPageName) const IsomerFile = new File(accessToken, siteName) const pageType = new PageType() IsomerFile.setFileType(pageType) - const { sha, content } = await IsomerFile.read(pageName) + const { sha, content: encodedContent } = await IsomerFile.read(pageName) + + const content = Base64.decode(encodedContent) // TO-DO: // Validate content @@ -117,9 +100,9 @@ async function readPage(req, res, next) { async function updatePage(req, res, next) { const { accessToken } = req - const { siteName, pageName } = req.params - const { content: unencodedContent, sha } = req.body - const content = base64.encode(unencodedContent) + const { siteName, pageName: encodedPageName } = req.params + const { content: pageContent, sha } = req.body + const pageName = decodeURIComponent(encodedPageName) // TO-DO: // Validate pageName and content @@ -127,17 +110,18 @@ async function updatePage(req, res, next) { const IsomerFile = new File(accessToken, siteName) const pageType = new PageType() IsomerFile.setFileType(pageType) - const { newSha } = await IsomerFile.update(pageName, content, sha) + const { newSha } = await IsomerFile.update(pageName, Base64.encode(pageContent), sha) - res.status(200).json({ pageName, content, sha: newSha }) + res.status(200).json({ pageName, pageContent, sha: newSha }) } // Delete page async function deletePage (req, res, next) { const { accessToken } = req - const { siteName, pageName } = req.params + const { siteName, pageName: encodedPageName } = req.params const { sha } = req.body + const pageName = decodeURIComponent(encodedPageName) const IsomerFile = new File(accessToken, siteName) const pageType = new PageType() @@ -151,19 +135,21 @@ async function deletePage (req, res, next) { async function renamePage(req, res, next) { const { accessToken } = req - const { siteName, pageName, newPageName } = req.params - const { sha, content } = req.body + const { siteName, pageName: encodedPageName, newPageName: encodedNewPageName } = req.params + const { sha, content: pageContent } = req.body // TO-DO: // Validate pageName and content + const pageName = decodeURIComponent(encodedPageName) + const newPageName = decodeURIComponent(encodedNewPageName) const IsomerFile = new File(accessToken, siteName) const pageType = new PageType() IsomerFile.setFileType(pageType) - const { sha: newSha } = await IsomerFile.create(newPageName, content) + const { sha: newSha } = await IsomerFile.create(newPageName, Base64.encode(pageContent)) await IsomerFile.delete(pageName, sha) - res.status(200).json({ pageName: newPageName, content, sha: newSha }) + res.status(200).json({ pageName: newPageName, pageContent, sha: newSha }) } // Move unlinked pages @@ -215,7 +201,6 @@ async function moveUnlinkedPages (req, res, next) { router.get('/:siteName/pages', attachReadRouteHandlerWrapper(listPages)) -router.post('/:siteName/pages', attachWriteRouteHandlerWrapper(createNewPage)) // to remove router.post('/:siteName/pages/new/:pageName', attachWriteRouteHandlerWrapper(createPage)) router.get('/:siteName/pages/:pageName', attachReadRouteHandlerWrapper(readPage)) router.post('/:siteName/pages/:pageName', attachWriteRouteHandlerWrapper(updatePage))