Build a blog with Areto Node.js framework

Article controller

The ArticleController class is responsible for the actions of the article.

modules/admin/controllers/ArticleController.js

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

  getModelClass () {
    return require('../models/Article');
  }
};
module.exports.init(module);                                      
const ActiveDataProvider = require('areto/data/ActiveDataProvider');
Article list

The actionIndex method lists articles to search and sort by ID, status or title. Each article is loaded together with related models (author, mainPhoto) are required to display it in the list.

modules/admin/controllers/ArticleController.js

...
actionIndex () {
  let Class = this.getModelClass();
  let provider = new ActiveDataProvider({
    controller: this,
    query: Class.findBySearch(this.getQueryParam('search')).with('author', 'mainPhoto'),
    pagination: {},
    sort: {
      attrs: {
        [Class.PK]: true,
        status: true,
        title: true
      },
      defaultOrder: {
        [Class.PK]: -1
      }
    }
  });
  provider.prepare(err => {
    err ? this.throwError(err) : this.render('index', {provider});
  });
}
...
View article Article view

The actionView method shows an article. The author, photos, mainPhoto, tags related models are loaded along with the article. Paging the list of comments related to an article formed from the relComments relation by using the ActiveDataProvider data provider.

modules/admin/controllers/ArticleController.js

...
actionView () {
  this.getModel(model => {
    let comments = new ActiveDataProvider({
      controller: this,
      query: model.relComments(),
      sort: {
        attrs: {
          [model.PK]: true
        },
        defaultOrder: {
          [model.PK]: -1
        }
      }
    });
    comments.prepare(err => {
      err ? this.throwError(err)
          : this.render('view', {model, comments});
    });
  }, ['author', 'photos', 'mainPhoto', 'tags']);
}
...
Create article

The actionCreate method creates a new article. The authorId attribute containing the article author, is set by the current user.

modules/admin/controllers/ArticleController.js

...
actionCreate () {        
  let model = new (this.getModelClass());
  if (this.isPost()) {
    model.load(this.getBodyParams());
    model.set('authorId', this.user.getId());
    model.save(err => {
      if (err) {
        this.throwError(err);
      } else if (model.isNewRecord) {
        this.render('create', {model});
      } else {
        this.backToRef();
      }
    });            
  } else {
    this.render('create', {model});
  }
}
...
Article update

The actionUpdate updates an article. The found article is checked for access for the current user. Parameters ({ authorId: model.get('authorId') }) used for initialization of the business rules of access, are passed to the can asynchronous function by the last argument.

modules/admin/controllers/ArticleController.js

...
actionUpdate () {        
  this.getModel(model => {
    this.user.can('updateArticle', (err, access)=>{
      if (err) {
        return this.throwError(err);
      }
      if (!access) {
        return this.throwForbidden();
      }
      if (this.isGet()) {
        return this.render('update', {model});
      }
      model.load(this.getBodyParams()).save(err => {
        if (err) {
          this.throwError(err);
        } else if (model.hasError()) {
          this.render('update', {model});
        } else {
          this.backToRef();
        }
      });
    }, { authorId: model.get('authorId') });
  }, 'photos', 'tags');
}
...