-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
2,255 additions
and
1,247 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/* eslint-disable require-jsdoc */ | ||
import Util from '../helpers/util'; | ||
import dbService from '../services/data.service'; | ||
import models from '../models'; | ||
|
||
const { | ||
checkItem, ensureBookMark, getUserBookMarks, addToCollection, | ||
findCollection, renameCollection, updateItem, deleteCollection, | ||
unCollect, getBookMarkName | ||
} = dbService; | ||
|
||
const util = new Util(); | ||
|
||
const notFound = (msg) => { | ||
util.setError(404, `${msg} not found`); | ||
return util; | ||
}; | ||
|
||
class BookMarkController { | ||
static async createBookMark(req, res) { | ||
const article = await checkItem(req.body.articleId, 'Article'); | ||
const name = req.body.name || `${article.title}-${new Date()}`; | ||
const bookmark = await ensureBookMark(req.body.articleId, name, req.auth.id); | ||
return res.status(201).json({ | ||
message: `bookmark '${name}' created`, data: bookmark[0] | ||
}); | ||
} | ||
|
||
static async editBookMark(req, res) { | ||
const oldName = req.params.name || req.data.name; | ||
const name = req.body.name || req.data.newName; | ||
const updated = updateItem(oldName, name, 'BookMark'); | ||
return res.status(200).json({ | ||
message: `bookmark ${oldName} updated to ${name}`, | ||
data: updated[1] | ||
}); | ||
} | ||
|
||
static async createCollection(req, res) { | ||
const { name, articleId, collection } = req.body; | ||
const added = await addToCollection(articleId, collection, name, req.auth.id); | ||
if (added[1]) { | ||
return res.status(201).json({ | ||
message: `bookmark '${name}' added to collection '${collection}'` | ||
}); | ||
} | ||
res.status(200).json({ | ||
message: `bookmark '${name}' already in collection '${collection}'` | ||
}); | ||
} | ||
|
||
static async getCollection(req, res) { | ||
const collection = await findCollection(req.params.collection, req.auth.id, [models.Article]); | ||
return res.status(200).json({ collection }); | ||
} | ||
|
||
static async getCollections(req, res) { | ||
const all = await getUserBookMarks(req.auth.id, [models.Article]); | ||
const collections = all.filter(x => x.collection); | ||
if (collections.length) { | ||
// reduce/map collections to collection: bookmark-count object array | ||
return res.status(200).json({ collections }); | ||
} | ||
notFound('collections').send(res); | ||
} | ||
|
||
static async updateCollection(req, res) { | ||
const { collection } = req.params; | ||
const updated = await renameCollection( | ||
req.body.collection, collection, req.auth.id | ||
); | ||
return res.status(200).json({ | ||
message: `collection '${collection}' updated to ${collection}`, | ||
data: updated | ||
}); | ||
} | ||
|
||
// delete collection and content | ||
static async deleteCollection(req, res) { | ||
const { collection } = req.params; | ||
await deleteCollection(collection); | ||
return res.status(200).json({ message: `collection '${collection}' deleted` }); | ||
} | ||
|
||
// delete from collection | ||
static async unCollect(req, res) { | ||
const { collection, name } = req.params; | ||
await unCollect(collection, name, req.auth.id); | ||
return res.status(200).json({ | ||
message: `bookmark ${name} deleted from collection ${collection}` | ||
}); | ||
} | ||
|
||
static async getUserBookMarks(req, res) { | ||
const bookmarks = await getUserBookMarks(req.auth.id); | ||
return res.status(200).json({ | ||
message: `${bookmarks.length} bookmarks found`, | ||
data: bookmarks | ||
}); | ||
} | ||
|
||
static async getUserBookMark(req, res) { | ||
const bookmark = await getBookMarkName(req.auth.id, req.params.name); | ||
return res.status(200).json({ | ||
message: `bookmark '${bookmark.name}' found`, | ||
data: bookmark | ||
}); | ||
} | ||
|
||
static async deleteUserBookMark(req, res) { | ||
const bookmark = await getBookMarkName(req.auth.id, req.params.name); | ||
bookmark.destroy(); | ||
return res.status(200).json({ | ||
message: `bookmark '${req.params.name}' deleted` | ||
}); | ||
} | ||
|
||
static async deleteUserBookMarks(req, res) { | ||
const reader = await checkItem(req.auth.id, 'user', ['articles']); | ||
const deleted = await reader.removeArticles(reader.articles); | ||
res.status(200).json({ message: `${deleted} bookmarks deleted` }); | ||
} | ||
|
||
static async copyBookmark(req, res) { | ||
const { | ||
articleId, name, newName, userId | ||
} = req.data; | ||
const copy = await ensureBookMark(articleId, newName, userId); | ||
res.status(201).json({ | ||
message: `copy of bookmark ${name} created as ${newName}`, | ||
data: copy | ||
}); | ||
} | ||
} | ||
|
||
export default BookMarkController; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* eslint-disable require-jsdoc */ | ||
import Util from '../helpers/util'; | ||
import dbService from '../services/data.service'; | ||
|
||
const { | ||
getUserBookMarks, getUserBookMark, checkExisting, | ||
checkName, checkCollection, getBookMarkName, checkItem | ||
} = dbService; | ||
|
||
const util = new Util(); | ||
|
||
const notFound = (msg) => { | ||
util.setError(404, `${msg} not found`); | ||
return util; | ||
}; | ||
|
||
let data; | ||
class BookMarkWare { | ||
static async checkBookmark(req, res, next) { | ||
const articleId = req.params.articleId || req.body.articleId; | ||
const name = req.body.oldName ? req.body.oldName : req.params.name || req.body.name; | ||
const bookmark = await getUserBookMark(req.auth.id, name, articleId); | ||
|
||
if (!bookmark) { | ||
return notFound(`bookmark ${name} with article ID ${articleId}`).send(res); | ||
} | ||
if (req.method === 'PATCH' && req.body.name === req.params.name) { | ||
return res.status(400).json({ message: 'update aborted, old and new name the same' }); | ||
} | ||
next(); | ||
} | ||
|
||
static async checkUserBookMarks(req, res, next) { | ||
const bookmarks = await getUserBookMarks(req.auth.id); | ||
if (!bookmarks.length) { | ||
return notFound('user bookmarks').send(res); | ||
} | ||
next(); | ||
} | ||
|
||
static async checkCollection(req, res, next) { | ||
const oldCollection = req.body.oldCollection || req.params.collection; | ||
const found = await checkCollection( | ||
oldCollection, req.auth.id | ||
); | ||
if (!found) { | ||
return notFound(`collection '${oldCollection}'`).send(res); | ||
} | ||
next(); | ||
} | ||
|
||
static async checkDuplicate(req, res, next) { | ||
const { articleId, name } = req.body; | ||
const existing = await checkExisting(req.auth.id, articleId); | ||
const existingName = await checkName(name, 'BookMark'); | ||
const bookmark = await getUserBookMark(req.auth.id, name, articleId); | ||
const article = await checkItem(articleId, 'Article'); | ||
if (!article) { | ||
return notFound(`article with id ${articleId}`).send(res); | ||
} | ||
if (bookmark) { | ||
return res.status(200).json({ | ||
message: `bookmark '${name}' exists`, data: bookmark | ||
}); | ||
} | ||
if (existing && existing.name) { | ||
data = existing; | ||
data.newName = name; | ||
return res.status(200).json({ | ||
message: `bookmark existing as '${existing.name}'`, | ||
options: { | ||
1: `create copy with new name ${name} on /api/v1/users/copy`, | ||
2: `update the name to ${name} on /api/v1/users/update` | ||
}, | ||
data: existing | ||
}); | ||
} | ||
if (existingName) { | ||
res.status(409).json({ | ||
message: `another bookmark with name ${name}`, | ||
data: existingName | ||
}); | ||
} | ||
next(); | ||
} | ||
|
||
static async createCopy(req, res, next) { | ||
req.data = data; | ||
next(); | ||
} | ||
|
||
static async checkBookmarkName(req, res, next) { | ||
const { name } = req.params; | ||
const bookmark = await getBookMarkName(req.auth.id, name); | ||
if (!bookmark) { | ||
return notFound(`bookmark '${name}'`).send(res); | ||
} | ||
if (req.body.name === name) { | ||
return res.status(400).json({ message: 'update aborted, old and new name the same' }); | ||
} | ||
next(); | ||
} | ||
} | ||
|
||
export default BookMarkWare; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
'use strict'; | ||
module.exports = { | ||
up: (queryInterface, Sequelize) => { | ||
return queryInterface.createTable('BookMarks', { | ||
id: { | ||
allowNull: false, | ||
autoIncrement: true, | ||
primaryKey: true, | ||
type: Sequelize.INTEGER | ||
}, | ||
articleId: { | ||
type: Sequelize.INTEGER | ||
}, | ||
userId: { | ||
type: Sequelize.INTEGER | ||
}, | ||
name: { | ||
type: Sequelize.STRING | ||
}, | ||
collection: { | ||
type: Sequelize.STRING | ||
}, | ||
createdAt: { | ||
allowNull: false, | ||
type: Sequelize.DATE | ||
}, | ||
updatedAt: { | ||
allowNull: false, | ||
type: Sequelize.DATE | ||
} | ||
}); | ||
}, | ||
down: (queryInterface, Sequelize) => { | ||
return queryInterface.dropTable('BookMarks'); | ||
} | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
'use strict'; | ||
module.exports = (sequelize, DataTypes) => { | ||
const BookMark = sequelize.define('BookMark', { | ||
articleId: DataTypes.INTEGER, | ||
userId: DataTypes.INTEGER, | ||
name: DataTypes.STRING, | ||
collection: DataTypes.STRING | ||
}, {}); | ||
BookMark.associate = function (models) { | ||
BookMark.belongsTo(models.Article, { foreignKey: 'articleId' }) | ||
BookMark.belongsTo(models.user, { foreignKey: 'userId' }) | ||
}; | ||
return BookMark; | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import express from 'express'; | ||
import BookMarkController from '../../../controllers/bookmarks.controller'; | ||
import auth from '../../../middlewares/auth'; | ||
|
||
const router = express.Router(); | ||
|
||
const { createBookMark, getUserBookMarks, editBookMark } = BookMarkController; | ||
|
||
router.post('/users/bookmarks/:articleId', auth, createBookMark); | ||
router.get('/users/bookmarks', auth, getUserBookMarks); |
Oops, something went wrong.