Build a blog with Areto Node.js framework

Photo controller

The PhotoController class defines a controller of the photo model.

modules/admin/controllers/PhotoController.js

'use strict';
const Base = require('../components/CrudController');
module.exports = class PhotoController extends Base {

  static getConstants () {
    return {
      METHODS: {
        'assign-main': ['post']
      }
    };
  }

  getModelClass () {
    return require('../models/Photo');
  }
};
module.exports.init(module);
const async = require('async');
const Article = require('../models/Article');
Create photo

The actionCreate method creates a photo model. The async.series array of asynchronous methods receives data to select one article of the list (Article.findToSelect). You can assign a photo to it.

modules/admin/controllers/PhotoController.js

...
actionCreate () {
  let model = new (this.getModelClass());
  model.scenario = 'create';
  let params = {model};
  async.series([
    cb => Article.findToSelect().all(cb)
  ], (err, result)=> {
    if (err) {
      return cb(err);
    }
    params.articles = result[0];
    if (this.isPost()) {
      model.load(this.getBodyParams()).save(err => {
        err ? this.throwError(err)
            : model.isNewRecord ? this.render('create', params) : this.backToRef();
      });
    } else { 
      this.render('create', params);
    }  
  });
}
...
View uploaded photo

The actionView method calls the parent to get the necessary relations.

modules/admin/controllers/PhotoController.js

...
actionView () {
  super.actionView('article');
}
...
Update photo

The actionUpload method uploads a file to the server. If the file is validated, a photo model will be created. Initial model is not linked to any article.

modules/admin/controllers/PhotoController.js

...
actionUpload () {
  let File = require('../models/File');
  let file = new File;
  file.upload(this, err => {
    if (err) {
      this.throwError(err);
    } else if (file.hasError()) {
      this.sendText(this.translate(file.getFirstError()), 400);
    } else {
      let photo = new (this.getModelClass());
      photo.set('file', file.getId());
      photo.validate(err => {
        if (err) {
          this.throwError(err);
        } else if (photo.hasError()) {
          this.sendText(this.translate(photo.getFirstError()), 400);
        } else {
          this.sendText(file.getId());
        }
      }, ['file']);
    }            
  });
}
...

The actionAssignMain method sets the main photo of the article. The forceSave function saves article without any data validation. If the photo is not related to any article, then set flash error messages (one-off message to a user session), and user will be redirected to the viewing page.

modules/admin/controllers/PhotoController.js

...
actionAssignMain () {
  this.getModel(model => {
    let article = model.get('article');
    if (article) {
      article.set('mainPhotoId', model.getId());
      article.forceSave(err => {
        err ? this.throwError(err) : this.redirect(['article/view', article]);
      });
    } else {
      this.setFlash('danger', 'Article not found');
      this.redirect(['view', model]);
    }
  }, 'article');
}
...