diff --git a/.gitignore b/.gitignore index 2186866682..6b679b8720 100644 --- a/.gitignore +++ b/.gitignore @@ -225,4 +225,4 @@ demo**/*.css dist # Ignore demo/uploads -demo/uploads +demo/media diff --git a/demo/collections/Media.js b/demo/collections/Media.js index 19aa77f43f..2a87050f84 100644 --- a/demo/collections/Media.js +++ b/demo/collections/Media.js @@ -24,6 +24,7 @@ module.exports = { staticDir: 'demo/media', type: 'image', accept: ['.jpg', '.jpeg', '.png'], + // TODO: discuss if some sizes are required, what if not resizing? imageSizes: [ { name: 'tablet', diff --git a/demo/collections/Page.js b/demo/collections/Page.js index f416722e0f..82cdbee691 100644 --- a/demo/collections/Page.js +++ b/demo/collections/Page.js @@ -64,6 +64,7 @@ module.exports = { name: 'slides', label: 'Slides', type: 'repeater', + id: false, fields: [ { name: 'content', diff --git a/src/index.js b/src/index.js index d60f8c25ee..53e0e5cddc 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,8 @@ import bodyParser from 'body-parser'; import methodOverride from 'method-override'; import jwtStrategy from './auth/jwt'; import fileUpload from 'express-fileupload'; -// import mediaRoutes from './media/media.routes'; +import {upload as uploadMedia, update as updateMedia} from './media/requestHandlers'; +import mediaConfig from './media/media.config'; import emailRoutes from './auth/passwordResets/email.routes'; import autopopulate from './mongoose/autopopulate.plugin'; import paginate from './mongoose/paginate.plugin'; @@ -21,7 +22,6 @@ import fieldToSchemaMap from './mongoose/fieldToSchemaMap'; import authValidate from './auth/validate'; import authRequestHandlers from './auth/requestHandlers'; import passwordResetConfig from './auth/passwordResets/passwordReset.config'; -import mediaConfig from './media/media.config'; import validateCollection from './utilities/validateCollection'; import validateGlobal from './utilities/validateGlobal'; import setModelLocaleMiddleware from './mongoose/setModelLocale.middleware'; @@ -43,7 +43,7 @@ class Payload { } }); - options.app.use(fileUpload()); + options.app.use(fileUpload({})); const staticUrl = options.config.staticUrl ? options.config.staticUrl : `/${options.config.staticDir}`; options.app.use(staticUrl, express.static(options.config.staticDir)); @@ -86,8 +86,7 @@ class Payload { } // media - // TODO: finish this idea - if (config.media && config.media.static) { + if (config.media) { config.fields.push(...mediaConfig.fields); } @@ -152,13 +151,18 @@ class Payload { setModelLocaleMiddleware() ); + // TODO: this feels sloppy, need to discuss media enabled collection handlers + let createHandler = config.media ? (req, res, next) => uploadMedia(req, res, next, config.media) : create; + let updateHandler = config.media ? (req, res, next) => updateMedia(req, res, next, config.media) : update; + // TODO: Do we need a delete? + options.router.route(`/${config.slug}`) .get(config.policies.read, query) - .post(config.policies.create, create); + .post(config.policies.create, createHandler); options.router.route(`/${config.slug}/:id`) .get(config.policies.read, findOne) - .put(config.policies.update, update) + .put(config.policies.update, updateHandler) .delete(config.policies.destroy, destroy); }); @@ -172,10 +176,6 @@ class Payload { this.globals[config.label] = config; globalFields[config.slug] = {}; - if (config.media) { - // TODO: handle media the same way as on a collection - } - config.fields.forEach(field => { const fieldSchema = fieldToSchemaMap[field.type]; if (fieldSchema) globalFields[config.slug][field.name] = fieldSchema(field); diff --git a/src/media/Media.model.js b/src/media/Media.model.js deleted file mode 100644 index 43c2ebdc30..0000000000 --- a/src/media/Media.model.js +++ /dev/null @@ -1,28 +0,0 @@ -import mongoose from 'mongoose'; -import buildQueryPlugin from '../mongoose/buildQuery.plugin'; -import paginate from '../mongoose/paginate.plugin'; -import localizationPlugin from '../localization/localization.plugin'; - -const mediaModelLoader = (config) => { - const MediaSchema = new mongoose.Schema({ - name: { type: String, intl: true }, - caption: { type: String, intl: true }, - description: { type: String, intl: true }, - filename: { type: String }, - sizes: [{ - height: { type: Number}, - width: { type: Number}, - _id: false - }] - }, - { timestamps: true } - ); - - MediaSchema.plugin(paginate); - MediaSchema.plugin(buildQueryPlugin); - MediaSchema.plugin(localizationPlugin, config.localization); - - return mongoose.model('Media', MediaSchema); -}; - -export default mediaModelLoader; diff --git a/src/media/media.config.js b/src/media/media.config.js index de3815a6e0..ac9304b003 100644 --- a/src/media/media.config.js +++ b/src/media/media.config.js @@ -1,21 +1,21 @@ export default { - fields: [{ - name: 'filename', - type: 'input', - }, + fields: [ + { + name: 'filename', + type: 'input', + }, { name: 'sizes', type: 'repeater', + id: false, fields: [ { name: 'height', type: 'number', - label: 'Height' }, { name: 'width', type: 'number', - label: 'Width' }, ] } diff --git a/src/media/media.routes.js b/src/media/media.routes.js deleted file mode 100644 index 2217949676..0000000000 --- a/src/media/media.routes.js +++ /dev/null @@ -1,36 +0,0 @@ -import express from 'express'; -import passport from 'passport'; -import { upload, update } from './media.controller'; -import { query } from '../mongoose/requestHandlers'; -import bindModelMiddleware from '../mongoose/bindModel.middleware'; -import mediaModelLoader from './Media.model'; - -const router = express.Router(); -const mediaRoutes = config => { - - const mediaModel = mediaModelLoader(config); // Needs config for intl - router.all('*', bindModelMiddleware(mediaModel)); - - router - .route('') - .post( - passport.authenticate('jwt', { session: false }), - (req, res, next) => upload(req, res, next, config) - ); - - router - .route('/:_id') - .put( - passport.authenticate('jwt', { session: false }), - (req, res, next) => update(req, res, next, config) - ); - - router.route('') - .get( - query - ); - - return router; -}; - -export default mediaRoutes; diff --git a/src/media/requestHandlers.js b/src/media/requestHandlers.js index 84f2dec5f1..f4fd0e622d 100644 --- a/src/media/requestHandlers.js +++ b/src/media/requestHandlers.js @@ -3,42 +3,42 @@ import { resizeAndSave } from './imageResizer'; import httpStatus from 'http-status'; import modelById from '../mongoose/resolvers/modelById'; -export async function update(req, res, next, config) { - req.model.setDefaultLocale(req.locale); +const update = async (req, res, next, config) => { + req.model.setDefaultLocale(req.locale); - const query = { - Model: req.model, - id: req.params._id, - locale: req.locale, - }; - let doc = await modelById(query, { returnRawDoc: true }); - if (!doc) - return res.status(httpStatus.NOT_FOUND).send('Not Found'); + const query = { + Model: req.model, + id: req.params._id, + locale: req.locale, + }; + let doc = await modelById(query, {returnRawDoc: true}); + if (!doc) + return res.status(httpStatus.NOT_FOUND).send('Not Found'); - Object.keys(req.body).forEach(e => { - doc[e] = req.body[e]; - }); - - if (req.files && req.files.file) { - doc['filename'] = req.files.file.name; - let outputFilepath = `${config.staticDir}/${req.files.file.name}`; - let moveError = await req.files.file.mv(outputFilepath); - if (moveError) return res.status(500).send(moveError); - doc['sizes'] = await resizeAndSave(config, req.files.file); - } - - doc.save((saveError) => { - if (saveError) - return res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ error: saveError }); - - return res.json({ - message: 'success', - result: doc.toJSON({ virtuals: true }) + Object.keys(req.body).forEach(e => { + doc[e] = req.body[e]; }); - }); -} -export async function upload(req, res, next, config) { + if (req.files && req.files.file) { + doc['filename'] = req.files.file.name; + let outputFilepath = `${config.staticDir}/${req.files.file.name}`; + let moveError = await req.files.file.mv(outputFilepath); + if (moveError) return res.status(500).send(moveError); + doc['sizes'] = await resizeAndSave(config, req.files.file); + } + + doc.save((saveError) => { + if (saveError) + return res.status(httpStatus.INTERNAL_SERVER_ERROR).json({error: saveError}); + + return res.json({ + message: 'success', + result: doc.toJSON({virtuals: true}) + }); + }); + }; + +const upload = async (req, res, next, config) => { if (!req.files || Object.keys(req.files).length === 0) { return res.status(400).send('No files were uploaded.'); } @@ -63,12 +63,14 @@ export async function upload(req, res, next, config) { sizes: outputSizes }, (mediaCreateError, result) => { if (mediaCreateError) - return res.status(500).json({ error: mediaCreateError }); + return res.status(500).json({error: mediaCreateError}); return res.status(201) .json({ message: 'success', - result: result.toJSON({ virtuals: true }) + result: result.toJSON({virtuals: true}) }); }); -} +}; + +export {update, upload};