CartoDB/cartodb20

View on GitHub
lib/assets/javascripts/dashboard/data/group-users-collection.js

Summary

Maintainability
B
4 hrs
Test Coverage
const _ = require('underscore');
const $ = require('jquery');
const Backbone = require('backbone');
const User = require('dashboard/data/user-model');
const checkAndBuildOpts = require('builder/helpers/required-opts');

const REQUIRED_OPTS = [
  'configModel'
];

/**
 * A collection representing a set of users in a group.
 */
module.exports = Backbone.Collection.extend({

  model: User,

  initialize: function (models, opts) {
    checkAndBuildOpts(opts, REQUIRED_OPTS, this);
    if (!opts.group) throw new Error('group is required');
    this.group = opts.group;
  },

  url: function () {
    return this.group.url.apply(this.group, arguments) + '/users';
  },

  parse: function (response) {
    this.total_entries = response.total_entries;
    this.total_user_entries = response.total_user_entries;

    return response.users;
  },

  /**
   * Batch add users
   * @param {Array} userIds
   * @return {Object} a deferred jqXHR object
   */
  addInBatch: function (userIds, password) {
    return this._batchAsyncProcessUsers('POST', userIds, password);
  },

  removeInBatch: function (userIds, password) {
    var self = this;
    return this._batchAsyncProcessUsers('DELETE', userIds, password)
      .done(function () {
        _.each(userIds, self.remove.bind(self));
      });
  },

  _batchAsyncProcessUsers: function (method, ids, password) {
    var self = this;

    // postpone relving promise since the fetch is requries for collection to have accurate state
    var deferred = $.Deferred();
    $.ajax({
      type: method,
      url: this._configModel.get('base_url') + this.url(),
      data: {
        users: ids,
        password_confirmation: password
      },
      success: function () {
        var args = arguments;

        // because add/remove don't return any data, so need to fetch to get accurate state
        self.fetch({
          success: function () {
            deferred.resolve.apply(deferred, args);
          },
          error: function () {
            // could not update state, but resolve anyway since batch operation worked
            // might have inconsistent state though
            deferred.resolve.apply(deferred, args);
          }
        });
      },
      error: function () {
        deferred.reject.apply(deferred, arguments);
      }
    });

    return deferred;
  },

  // @return {Number, undefined} may be undefined until a first fetch is done
  totalCount: function () {
    return this.total_user_entries;
  }

});