<commit_before>'use strict';

var fs = require('fs');
var path = require('path');
var plugin = require('./plugins');
var utils = require('./utils');
var Base = require('./base');

/**
 * Expose `Views`
 */

module.exports = Views;

/**
 * Create an instance of `Views` with the given `options`.
 *
 * ```js
 * var collection = new Views();
 * collection.addView('foo', {content: 'bar'});
 * ```
 * @param {Object} `options`
 * @api public
 */

function Views(options) {
  if (!(this instanceof Views)) {
    return new Views(options);
  }

  utils.define(this, 'isCollection', true);
  utils.isName(this, 'Views');

  Base.call(this);
  this.init(options || {});
}

/**
 * Inherit `Base`
 */

Base.extend(Views);

/**
 * Mixin prototype methods
 */

plugin.routes(Views.prototype);
plugin.engine(Views.prototype);
plugin.layout(Views.prototype);
plugin.render(Views.prototype);
plugin.errors(Views.prototype, 'Views');

/**
 * Initialize `Views` defaults
 */

Views.prototype.init = function(opts) {
  // decorate the instance
  this.use(plugin.init);
  this.use(plugin.renameKey());
  this.use(plugin.context);
  this.use(plugin.helpers);
  this.use(plugin.item('view', 'View'));

  // add constructors
  this.define('List', opts.List || require('./list'));
  this.define('View', opts.View || require('./view'));
  this.define('loaded', false);

  this.queue = [];
  this.views = {};

  // if an instance of `List` of `Views` is passed, load it now
  if (Array.isArray(opts) || opts.isList) {
    this.options = opts.options || {};
    this.addList(opts.items || opts);

  } else if (opts.isCollection) {
    this.options = opts.options;
    this.addViews(opts.views);

  } else {
    this.options = opts;
  }
};

/**
 * Set a view on the collection. This is identical to [addView](#addView)
 * except `setView` does not emit an event for each view.
 *
 * ```js
 * collection.setView('foo', {content: 'bar'});
 * ```
 *
 * @param {String|Object} `key` View key or object
 * @param {Object} `value` If key is a string, value is the view object.
 * @developer This method is decorated onto the collection in the constructor using the `createView` utility method.
 * @return {Object} returns the `view` instance.
 * @api public
 */

Views.prototype.setView = function(key, value) {
  var view = this.view(key, value);
  this.setType(view);

  var name = this.options.inflection || 'none';
  if (view.use) this.run(view);

  this.emit('load', view);
  this.emit(name, view, this);

  this.views[view.key] = view;
  return view;
};

/**
 * Similar to [setView](#setView), adds a view to the collection
 * but also fires an event and iterates over the loading `queue`
 * for loading views from the `addView` event listener. If the
 * given view is not already an instance of `View`, it will be
 * converted to one before being added to the `views` object.
 *
 * ```js
 * var views = new Views(...);
 * views.addView('a.html', {path: 'a.html', contents: '...'});
 * ```
 * @param {String} `key`
 * @param {Object} `value`
 * @return {Object} Returns the instance of the created `View` to allow chaining view methods.
 * @api public
 */

Views.prototype.addView = function(/*key, value*/) {
  var args = [].slice.call(arguments);
  this.emit.call(this, 'addView', args);

  var view = this.setView.apply(this, args);
  while (this.queue.length) {
    this.setView(this.queue.shift());
  }
  this.extendView(view);
  return view;
};

/**
 * Load multiple views onto the collection.
 *
 * ```js
 * collection.addViews({
 *   'a.html': {content: '...'},
 *   'b.html': {content: '...'},
 *   'c.html': {content: '...'}
 * });
 * ```
 * @param {Object|Array} `views`
 * @return {Object} returns the `collection` object
 * @api public
 */

Views.prototype.addViews = function(views) {
  this.emit('addViews', views);
  if (this.loaded) return this;
  if (utils.hasGlob(views)) {
    throw new Error('glob patterns are not supported by addViews');
  }
  if (Array.isArray(views)) {
    this.addList.apply(this, arguments);
    return this;
  }
  if (arguments.length > 1 && utils.isView(arguments[1])) {
    this.addView.apply(this, arguments);
    return this;
  }
  this.visit('addView', views);
  return this;
};

/**
 * Load an array of views onto the collection.
 *
 * ```js
 * collection.addList([
 *   {path: 'a.html', content: '...'},
 *   {path: 'b.html', content: '...'},
 *   {path: 'c.html', content: '...'}
 * ]);
 * ```
 * @param {Array} `list`
 * @return {Object} returns the `views` instance
 * @api public
 */

Views.prototype.addList = function(list, fn) {
  this.emit('addList', list);
  if (this.loaded) return this;
  if (utils.hasGlob(list)) {
    throw new Error('glob patterns are not supported by addList');
  }
  if (!Array.isArray(list)) {
    throw new TypeError('expected list to be an array.');
  }
  if (typeof fn !== 'function') {
    fn = utils.identity;
  }
  var len = list.length, i = -1;
  while (++i < len) {
    var view = fn(list[i]);
    this.addView(view.path, view);
  }
  return this;
};

/**
 * Get a view from the collection.
 *
 * ```js
 * collection.getView('a.html');
 * ```
 * @param {String} `key` Key of the view to get.
 * @return {Object}
 * @api public
 */

Views.prototype.getView = function(name, options, fn) {
  if (typeof name !== 'string') {
    throw new TypeError('expected a string');
  }

  if (typeof options === 'function') {
    fn = options;
    options = {};
  }

  if (typeof fn === 'function') {
    name = fn.call(this, name, {});
  }

  var view = this.views[name] || this.views[this.renameKey(name)];
  if (view) return view;

  for (var key in this.views) {
    view = this.views[key];
    if (isMatch(name, view)) {
      return view;
    }
  }

  function isMatch(name, view) {
    if (name === view.path) return true;
    if (name === view.relative) return true;
    if (name === view.basename) return true;
    if (name === view.key) return true;
    if (name === view.stem) return true;

    var fp = path.resolve(view.path);
    return path.resolve(name) === fp;
  }

  if (fs.existsSync(name)) {
    return this.addView(name, {
      contents: fs.readFileSync(name)
    });
  }

  return '';
};

/**
 * Load a view from the file system.
 *
 * ```js
 * collection.loadView(view);
 * ```
 * @param {Object} `view`
 * @return {Object}
 * @api public
 */

Views.prototype.extendView = function(view) {
  return plugin.view.all(this, view);
};

/**
 * Decorate each view on the collection with additional methods
 * and properties. This provides a way of easily overriding
 * defaults.
 *
 * ```js
 * collection.extendView(view);
 * ```
 * @param {Object} `view`
 * @return {Object}
 * @api public
 */

Views.prototype.extendView = function(view) {
  return plugin.view.all(this, view);
};

/**
 * Return true if the collection belongs to the given
 * view `type`.
 *
 * ```js
 * collection.isType('partial');
 * ```
 * @param {String} `type` (`renderable`, `partial`, `layout`)
 * @api public
 */

Views.prototype.isType = function(type) {
  if (!this.options.viewType || !this.options.viewType.length) {
    this.viewType();
  }
  return this.options.viewType.indexOf(type) !== -1;
};

/**
 * Set view types for the collection.
 *
 * @param {String} `plural` e.g. `pages`
 * @param {Object} `options`
 */

Views.prototype.viewType = function(types) {
  this.options.viewType = utils.arrayify(this.options.viewType);
  types = utils.arrayify(types);
  var len = types.length;

  while (len--) {
    var type = types[len];
    if (['partial', 'layout', 'renderable'].indexOf(type) === -1) {
      throw new Error('"' + type + '" is not a valid viewType. Valid viewTypes are: partial, renderable and layout.');
    }

    if (this.options.viewType.indexOf(type) === -1) {
      this.options.viewType.push(type);
    }
  }

  if (this.options.viewType.length === 0) {
    this.options.viewType.push('renderable');
  }
  return this.options.viewType;
};

/**
 * Update the `options.viewType` property on a view.
 *
 * @param {Object} `view` The view to update
 */

Views.prototype.setType = function(view) {
  view.options = view.options || {};
  view.options.viewType = utils.arrayify(view.options.viewType);
  var types = this.viewType();
  var len = types.length;

  while (len--) {
    var type = types[len];
    if (view.options.viewType.indexOf(type) === -1) {
      view.options.viewType.push(type);
    }
  }
  view.options.viewType.sort();
};
<commit_msg>adds `deleteItem` method and `isList` static method<commit_after>'use strict';

var fs = require('fs');
var path = require('path');
var plugin = require('./plugins');
var utils = require('./utils');
var List = require('./list');
var Base = require('./base');

/**
 * Expose `Views`
 */

module.exports = Views;

/**
 * Create an instance of `Views` with the given `options`.
 *
 * ```js
 * var collection = new Views();
 * collection.addView('foo', {content: 'bar'});
 * ```
 * @param {Object} `options`
 * @api public
 */

function Views(options) {
  if (!(this instanceof Views)) {
    return new Views(options);
  }

  utils.define(this, 'isCollection', true);
  utils.isName(this, 'Views');

  Base.call(this);
  this.init(options || {});
}

/**
 * Inherit `Base`
 */

Base.extend(Views);

/**
 * Decorate static methods
 */

plugin.is(Views);

/**
 * Mixin prototype methods
 */

plugin.routes(Views.prototype);
plugin.engine(Views.prototype);
plugin.layout(Views.prototype);
plugin.render(Views.prototype);
plugin.errors(Views.prototype, 'Views');

/**
 * Initialize `Views` defaults
 */

Views.prototype.init = function(opts) {
  // decorate the instance
  this.use(plugin.init);
  this.use(plugin.renameKey());
  this.use(plugin.context);
  this.use(plugin.helpers);
  this.use(plugin.item('view', 'View'));

  // add constructors
  this.define('List', opts.List || require('./list'));
  this.define('View', opts.View || require('./view'));
  this.define('loaded', false);

  this.queue = [];
  this.views = {};

  // if an instance of `List` of `Views` is passed, load it now
  if (Array.isArray(opts) || opts.isList) {
    this.options = opts.options || {};
    this.addList(opts.items || opts);

  } else if (opts.isCollection) {
    this.options = opts.options;
    this.addViews(opts.views);

  } else {
    this.options = opts;
  }
};

/**
 * Set a view on the collection. This is identical to [addView](#addView)
 * except `setView` does not emit an event for each view.
 *
 * ```js
 * collection.setView('foo', {content: 'bar'});
 * ```
 *
 * @param {String|Object} `key` View key or object
 * @param {Object} `value` If key is a string, value is the view object.
 * @developer This method is decorated onto the collection in the constructor using the `createView` utility method.
 * @return {Object} returns the `view` instance.
 * @api public
 */

Views.prototype.setView = function(key, value) {
  var view = this.view(key, value);

  // set the name to be used by the `inspect` method and emitter
  var name = this.options.inflection || 'view';
  utils.isName(view, name, true);

  // set the `viewType` (partial, layout, or renderable)
  this.setType(view);

  // run plugins on `view`
  if (view.use) this.run(view);

  // emit that the view has been loaded
  this.emit('load', view);
  this.emit(name, view, this);

  this.views[view.key] = view;
  return view;
};

/**
 * Similar to [setView](#setView), adds a view to the collection
 * but also fires an event and iterates over the loading `queue`
 * for loading views from the `addView` event listener. If the
 * given view is not already an instance of `View`, it will be
 * converted to one before being added to the `views` object.
 *
 * ```js
 * var views = new Views(...);
 * views.addView('a.html', {path: 'a.html', contents: '...'});
 * ```
 * @param {String} `key`
 * @param {Object} `value`
 * @return {Object} Returns the instance of the created `View` to allow chaining view methods.
 * @api public
 */

Views.prototype.addView = function(/*key, value*/) {
  var args = [].slice.call(arguments);
  this.emit.call(this, 'addView', args);

  var view = this.setView.apply(this, args);
  while (this.queue.length) {
    this.setView(this.queue.shift());
  }
  this.extendView(view);
  return view;
};

/**
 * Delete a view from collection `views`.
 *
 * ```js
 * views.deleteView('foo.html');
 * ```
 * @param {String} `key`
 * @return {Object} Returns the instance for chaining
 * @api public
 */

Views.prototype.deleteView = function(view) {
  if (typeof view === 'string') {
    view = this.getView(view);
  }
  delete this.views[view.key];
  return this;
};

/**
 * Load multiple views onto the collection.
 *
 * ```js
 * collection.addViews({
 *   'a.html': {content: '...'},
 *   'b.html': {content: '...'},
 *   'c.html': {content: '...'}
 * });
 * ```
 * @param {Object|Array} `views`
 * @return {Object} returns the `collection` object
 * @api public
 */

Views.prototype.addViews = function(views) {
  this.emit('addViews', views);
  if (this.loaded) return this;
  if (utils.hasGlob(views)) {
    throw new Error('glob patterns are not supported by addViews');
  }
  if (Array.isArray(views)) {
    this.addList.apply(this, arguments);
    return this;
  }
  if (arguments.length > 1 && utils.isView(arguments[1])) {
    this.addView.apply(this, arguments);
    return this;
  }
  this.visit('addView', views);
  return this;
};

/**
 * Load an array of views onto the collection.
 *
 * ```js
 * collection.addList([
 *   {path: 'a.html', content: '...'},
 *   {path: 'b.html', content: '...'},
 *   {path: 'c.html', content: '...'}
 * ]);
 * ```
 * @param {Array} `list`
 * @return {Object} returns the `views` instance
 * @api public
 */

Views.prototype.addList = function(list, fn) {
  this.emit('addList', list);
  if (this.loaded) return this;
  if (utils.hasGlob(list)) {
    throw new Error('glob patterns are not supported by addList');
  }
  if (!Array.isArray(list)) {
    throw new TypeError('expected list to be an array.');
  }
  if (typeof fn !== 'function') {
    fn = utils.identity;
  }
  var len = list.length, i = -1;
  while (++i < len) {
    var view = fn(list[i]);
    this.addView(view.path, view);
  }
  return this;
};

/**
 * Get a view from the collection.
 *
 * ```js
 * collection.getView('a.html');
 * ```
 * @param {String} `key` Key of the view to get.
 * @return {Object}
 * @api public
 */

Views.prototype.getView = function(name, options, fn) {
  if (typeof name !== 'string') {
    throw new TypeError('expected a string');
  }

  if (typeof options === 'function') {
    fn = options;
    options = {};
  }

  if (typeof fn === 'function') {
    name = fn.call(this, name, {});
  }

  var view = this.views[name] || this.views[this.renameKey(name)];
  if (view) return view;

  for (var key in this.views) {
    view = this.views[key];
    if (isMatch(name, view)) {
      return view;
    }
  }

  function isMatch(name, view) {
    if (name === view.path) return true;
    if (name === view.relative) return true;
    if (name === view.basename) return true;
    if (name === view.key) return true;
    if (name === view.stem) return true;

    var fp = path.resolve(view.path);
    return path.resolve(name) === fp;
  }

  if (fs.existsSync(name)) {
    return this.addView(name, {
      contents: fs.readFileSync(name)
    });
  }

  return '';
};

/**
 * Load a view from the file system.
 *
 * ```js
 * collection.loadView(view);
 * ```
 * @param {Object} `view`
 * @return {Object}
 * @api public
 */

Views.prototype.extendView = function(view) {
  return plugin.view.all(this, view);
};

/**
 * Decorate each view on the collection with additional methods
 * and properties. This provides a way of easily overriding
 * defaults.
 *
 * ```js
 * collection.extendView(view);
 * ```
 * @param {Object} `view`
 * @return {Object}
 * @api public
 */

Views.prototype.extendView = function(view) {
  return plugin.view.all(this, view);
};

/**
 * Return true if the collection belongs to the given
 * view `type`.
 *
 * ```js
 * collection.isType('partial');
 * ```
 * @param {String} `type` (`renderable`, `partial`, `layout`)
 * @api public
 */

Views.prototype.isType = function(type) {
  if (!this.options.viewType || !this.options.viewType.length) {
    this.viewType();
  }
  return this.options.viewType.indexOf(type) !== -1;
};

/**
 * Set view types for the collection.
 *
 * @param {String} `plural` e.g. `pages`
 * @param {Object} `options`
 */

Views.prototype.viewType = function(types) {
  this.options.viewType = utils.arrayify(this.options.viewType);
  types = utils.arrayify(types);
  var len = types.length;

  while (len--) {
    var type = types[len];
    if (['partial', 'layout', 'renderable'].indexOf(type) === -1) {
      throw new Error('"' + type + '" is not a valid viewType. Valid viewTypes are: partial, renderable and layout.');
    }

    if (this.options.viewType.indexOf(type) === -1) {
      this.options.viewType.push(type);
    }
  }

  if (this.options.viewType.length === 0) {
    this.options.viewType.push('renderable');
  }
  return this.options.viewType;
};

/**
 * Update the `options.viewType` property on a view.
 *
 * @param {Object} `view` The view to update
 */

Views.prototype.setType = function(view) {
  view.options = view.options || {};
  view.options.viewType = utils.arrayify(view.options.viewType);
  var types = this.viewType();
  var len = types.length;

  while (len--) {
    var type = types[len];
    if (view.options.viewType.indexOf(type) === -1) {
      view.options.viewType.push(type);
    }
  }
  view.options.viewType.sort();
};
<|endoftext|>


<commit_before>'use strict'

const Game = require('./game')

$(document).ready( () => {
  keyboardMoves()
  startPlayers()
})

let canvas = document.getElementById('game')
let context = canvas.getContext('2d')
let game = new Game

var drawOne = () => {
  context.fillStyle = "#FF0000"
  context.fillRect(game.bikeOne.x, game.bikeOne.y, game.bikeOne.width, game.bikeOne.height)
}

var drawTwo = () => {
  context.fillStyle = "#FFFF00"
  context.fillRect(game.bikeTwo.x, game.bikeTwo.y, game.bikeTwo.width, game.bikeTwo.height)
}

var startPlayers = () => {
  $('#start').on('click', function(event) {
    playerOneRight(); playerTwoLeft(); playerTwoLeft()
  })
}

function keyboardMoves () {
  $(document).on('keydown', function(event) {
    if (game.gameStatus !== "alive") {
      alert(game.gameStatus)
    } else {
      switch(event.which) {
          case 65:
          return playerOneMove(game.bikeOne.moveLeft)

          case 87:
          return playerOneMove(game.bikeOne.moveUp)

          case 68:
          return playerOneMove(game.bikeOne.moveRight)

          case 83:
          return playerOneMove(game.bikeOne.moveDown)

          case 74:
          return playerTwoMove(game.bikeTwo.moveLeft)

          case 73:
          return playerTwoMove(game.bikeTwo.moveUp)

          case 76:
          return playerTwoMove(game.bikeTwo.moveRight)

          case 75:
          return playerTwoMove(game.bikeTwo.moveDown)

          default: return
      }
      event.preventDefault()
    }
  })
}

var playerOneMove = (direction) => {
  requestAnimationFrame( function gameLoop() {
    drawOne(); this.direction;
    game.fillBikeTrailOne
  })
}

var playerTwoMove = (direction) => {
  requestAnimationFrame( function gameLoop() {
    drawTwo(); this.direction;
    game.fillBikeTrailTwo
  })
}
// var resetGame = () => {
//   $('#reset').on('click', function(event) {
//     location.reload()
//   }
// })
<commit_msg>one less line<commit_after>'use strict'

const Game = require('./game')

$(document).ready( () => {
  keyboardMoves(); startPlayers()
})

let canvas = document.getElementById('game')
let context = canvas.getContext('2d')
let game = new Game

var drawOne = () => {
  context.fillStyle = "#FF0000"
  context.fillRect(game.bikeOne.x, game.bikeOne.y, game.bikeOne.width, game.bikeOne.height)
}

var drawTwo = () => {
  context.fillStyle = "#FFFF00"
  context.fillRect(game.bikeTwo.x, game.bikeTwo.y, game.bikeTwo.width, game.bikeTwo.height)
}

var startPlayers = () => {
  $('#start').on('click', function(event) {
    playerOneRight(); playerTwoLeft(); playerTwoLeft()
  })
}

function keyboardMoves () {
  $(document).on('keydown', function(event) {
    if (game.gameStatus !== "alive") {
      alert(game.gameStatus)
    } else {
      switch(event.which) {
          case 65:
          return playerOneMove(game.bikeOne.moveLeft)

          case 87:
          return playerOneMove(game.bikeOne.moveUp)

          case 68:
          return playerOneMove(game.bikeOne.moveRight)

          case 83:
          return playerOneMove(game.bikeOne.moveDown)

          case 74:
          return playerTwoMove(game.bikeTwo.moveLeft)

          case 73:
          return playerTwoMove(game.bikeTwo.moveUp)

          case 76:
          return playerTwoMove(game.bikeTwo.moveRight)

          case 75:
          return playerTwoMove(game.bikeTwo.moveDown)

          default: return
      }
      event.preventDefault()
    }
  })
}

var playerOneMove = (direction) => {
  requestAnimationFrame( function gameLoop() {
    drawOne(); this.direction;
    game.fillBikeTrailOne
  })
}

var playerTwoMove = (direction) => {
  requestAnimationFrame( function gameLoop() {
    drawTwo(); this.direction;
    game.fillBikeTrailTwo
  })
}
// var resetGame = () => {
//   $('#reset').on('click', function(event) {
//     location.reload()
//   }
// })
<|endoftext|>


<commit_before>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var sys = require('sys');
var path = require('path');

var sprintf = require('extern/sprintf').sprintf;

var config = require('util/config');
var misc = require('util/misc');

var norris = require('norris');
var runit_templates = require('runit/templates/base');
var RunitServiceDirectory = require('runit/services').RunitServiceDirectory;
var get_service_dir = require('runit/services').get_service_dir;

var create_service = function(instance_name, instance_path, entry_file, application_type, callback) {
  var runit = get_service_dir();

  runit_templates.get_application_template(instance_name, instance_path, entry_file, application_type, function(error, template) {
    if (error) {
      return callback(error);
    }

    runit.create_service_layout(instance_name, template, function(error) {
      if (error) {
        return callback(error);
      }

      callback();
    });
  });
};

exports.create_service = create_service;
<commit_msg>Add jsdoc of function<commit_after>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var sys = require('sys');
var path = require('path');

var sprintf = require('extern/sprintf').sprintf;

var config = require('util/config');
var misc = require('util/misc');

var norris = require('norris');
var runit_templates = require('runit/templates/base');
var RunitServiceDirectory = require('runit/services').RunitServiceDirectory;
var get_service_dir = require('runit/services').get_service_dir;

/**
 * Creates an instance of a service, building out the runit application directory.
 * @param {String} instance_name Name of the instance.
 * @param {String} instance_path Path to of the instance
 * @param {String} entry_file Path of the file to run inside runit
 * @param {String} application_type Type of the application template to use, must be "shell" or "nodejs" at this time.
 * @param {Function} callback Callback on completion, first parameter if present is an error.
 */
exports.create_service = function(instance_name, instance_path, entry_file, application_type, callback)
{
  var runit = get_service_dir();

  runit_templates.get_application_template(instance_name, instance_path, entry_file, application_type, function(error, template) {
    if (error) {
      return callback(error);
    }

    runit.create_service_layout(instance_name, template, function(error) {
      if (error) {
        return callback(error);
      }
      callback();
    });
  });
};

<|endoftext|>


<commit_before>/**
 * The grid that shows examiners on a single group.
 */
Ext.define('devilry_subjectadmin.view.managestudents.ExaminersInGroupGrid', {
    extend: 'Ext.grid.Panel',
    alias: 'widget.examinersingroupgrid',
    cls: 'devilry_subjectadmin_examinersingroupgrid',
    hideHeaders: true,
    disableSelection: true,
    border: false,
    requires: [
        'Ext.XTemplate',
        'devilry_theme.Icons'
    ],

    rowTpl: [
        '
',
            '
',
                '<tpl if="user.full_name">',
                    '
{user.full_name}
',
                '<tpl else>',
                    '', gettext('Full name missing'), '',
                '</tpl>',
            '
',
            '
{user.username}
',
        '
'
    ],

    initComponent: function() {
        var me = this;
        var rowTplCompiled = Ext.create('Ext.XTemplate', this.rowTpl);
        Ext.apply(this, {
            columns: [{
                header: 'Name',
                flex: 1,
                dataIndex: 'id',
                renderer: function(unused1, unused2, examinerRecord) {
                    return rowTplCompiled.apply(examinerRecord.data);
                }
            }]
        });
        this.callParent(arguments);
    }
});
<commit_msg>devilry_subjectadmin...ExaminersInGroupGrid: Remove unused import.<commit_after>/**
 * The grid that shows examiners on a single group.
 */
Ext.define('devilry_subjectadmin.view.managestudents.ExaminersInGroupGrid', {
    extend: 'Ext.grid.Panel',
    alias: 'widget.examinersingroupgrid',
    cls: 'devilry_subjectadmin_examinersingroupgrid',
    hideHeaders: true,
    disableSelection: true,
    border: false,
    requires: [
        'Ext.XTemplate'
    ],

    rowTpl: [
        '
',
            '
',
                '<tpl if="user.full_name">',
                    '
{user.full_name}
',
                '<tpl else>',
                    '', gettext('Full name missing'), '',
                '</tpl>',
            '
',
            '
{user.username}
',
        '
'
    ],

    initComponent: function() {
        var me = this;
        var rowTplCompiled = Ext.create('Ext.XTemplate', this.rowTpl);
        Ext.apply(this, {
            columns: [{
                header: 'Name',
                flex: 1,
                dataIndex: 'id',
                renderer: function(unused1, unused2, examinerRecord) {
                    return rowTplCompiled.apply(examinerRecord.data);
                }
            }]
        });
        this.callParent(arguments);
    }
});
<|endoftext|>


<commit_before>import Controller from '@ember/controller';
import envConfig from 'ghost-admin/config/environment';
import {action} from '@ember/object';
import {currencies, getCurrencyOptions, getSymbol} from 'ghost-admin/utils/currency';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency-decorators';
import {timeout} from 'ember-concurrency';
import {tracked} from '@glimmer/tracking';

const CURRENCIES = currencies.map((currency) => {
    return {
        value: currency.isoCode.toLowerCase(),
        label: `${currency.isoCode} - ${currency.name}`,
        isoCode: currency.isoCode
    };
});

export default class MembersAccessController extends Controller {
    @service config;
    @service membersUtils;
    @service settings;
    @service store;

    @tracked showLeavePortalModal = false;
    @tracked showLeaveRouteModal = false;
    @tracked showPortalSettings = false;
    @tracked showStripeConnect = false;

    @tracked product = null;
    @tracked stripePrices = [];
    @tracked paidSignupRedirect;
    @tracked freeSignupRedirect;
    @tracked stripeMonthlyAmount = 5;
    @tracked stripeYearlyAmount = 50;
    @tracked currency = 'usd';
    @tracked stripePlanError = '';

    @tracked portalPreviewUrl = '';

    queryParams = ['showPortalSettings'];

    get allCurrencies() {
        return getCurrencyOptions();
    }

    get siteUrl() {
        return this.config.get('blogUrl');
    }

    get selectedCurrency() {
        return CURRENCIES.findBy('value', this.currency);
    }

    get isConnectDisallowed() {
        const siteUrl = this.config.get('blogUrl');
        return envConfig.environment !== 'development' && !/^https:/.test(siteUrl);
    }

    leaveRoute(transition) {
        if (this.settings.get('hasDirtyAttributes')) {
            transition.abort();
            this.leaveSettingsTransition = transition;
            this.showLeaveRouteModal = true;
        }
    }

    _validateSignupRedirect(url, type) {
        const siteUrl = this.config.get('blogUrl');
        let errMessage = `Please enter a valid URL`;
        this.settings.get('errors').remove(type);
        this.settings.get('hasValidated').removeObject(type);

        if (url === null) {
            this.settings.get('errors').add(type, errMessage);
            this.settings.get('hasValidated').pushObject(type);
            return false;
        }

        if (url === undefined) {
            // Not initialised
            return;
        }

        if (url.href.startsWith(siteUrl)) {
            const path = url.href.replace(siteUrl, '');
            this.settings.set(type, path);
        } else {
            this.settings.set(type, url.href);
        }
    }

    @action
    setStripePlansCurrency(event) {
        const newCurrency = event.value;
        this.currency = newCurrency;
    }

    @action
    setPaidSignupRedirect(url) {
        this.paidSignupRedirect = url;
    }

    @action
    setFreeSignupRedirect(url) {
        this.freeSignupRedirect = url;
    }

    @action
    validatePaidSignupRedirect() {
        return this._validateSignupRedirect(this.paidSignupRedirect, 'membersPaidSignupRedirect');
    }

    @action
    validateFreeSignupRedirect() {
        return this._validateSignupRedirect(this.freeSignupRedirect, 'membersFreeSignupRedirect');
    }

    @action
    validateStripePlans() {
        this.stripePlanError = undefined;

        try {
            const yearlyAmount = this.stripeYearlyAmount;
            const monthlyAmount = this.stripeMonthlyAmount;
            const symbol = getSymbol(this.currency);
            if (!yearlyAmount || yearlyAmount < 1 || !monthlyAmount || monthlyAmount < 1) {
                throw new TypeError(`Subscription amount must be at least ${symbol}1.00`);
            }

            this.updatePortalPreview();
        } catch (err) {
            this.stripePlanError = err.message;
        }
    }

    @action
    closeStripeConnect() {
        this.showStripeConnect = false;
    }

    @action
    openPortalSettings() {
        this.saveSettingsTask.perform();
        this.showPortalSettings = true;
    }

    @action
    closePortalSettings() {
        const changedAttributes = this.settings.changedAttributes();
        if (changedAttributes && Object.keys(changedAttributes).length > 0) {
            this.showLeavePortalModal = true;
        } else {
            this.showPortalSettings = false;
            this.updatePortalPreview();
        }
    }

    @action
    async confirmClosePortalSettings() {
        this.settings.rollbackAttributes();
        this.showPortalSettings = false;
        this.showLeavePortalModal = false;
        this.updatePortalPreview();
    }

    @action
    cancelClosePortalSettings() {
        this.showLeavePortalModal = false;
    }

    @action
    async confirmLeave() {
        this.settings.rollbackAttributes();
        this.leaveSettingsTransition.retry();
    }

    @action
    cancelLeave() {
        this.showLeaveRouteModal = false;
        this.leaveSettingsTransition = null;
    }

    @action
    updatePortalPreview() {
        // TODO: can these be worked out from settings in membersUtils?
        const monthlyPrice = this.stripeMonthlyAmount * 100;
        const yearlyPrice = this.stripeYearlyAmount * 100;
        let portalPlans = this.settings.get('portalPlans') || [];
        const currentMontlyPriceId = this.settings.get('membersMonthlyPriceId');
        const currentYearlyPriceId = this.settings.get('membersYearlyPriceId');
        let isMonthlyChecked = false;
        let isYearlyChecked = false;
        if (portalPlans.includes(currentMontlyPriceId)) {
            isMonthlyChecked = true;
        }

        if (portalPlans.includes(currentYearlyPriceId)) {
            isYearlyChecked = true;
        }

        this.portalPreviewUrl = this.membersUtils.getPortalPreviewUrl({
            button: false,
            monthlyPrice,
            yearlyPrice,
            currency: this.currency,
            isMonthlyChecked,
            isYearlyChecked,
            portalPlans: null
        });

        this.resizePortalPreviewTask.perform();
    }

    @action
    portalPreviewLoaded(event) {
        this.portalPreviewIframe = event.target;
        this.resizePortalPreviewTask.perform();
    }

    @action
    portalPreviewDestroyed() {
        this.portalPreviewIframe = null;
        this.resizePortalPreviewTask.cancelAll();
    }

    @task({restartable: true})
    *resizePortalPreviewTask() {
        if (this.portalPreviewIframe && this.portalPreviewIframe.contentWindow) {
            yield timeout(100); // give time for portal to re-render

            const portalIframe = this.portalPreviewIframe.contentWindow.document.querySelector('#ghost-portal-root iframe');
            if (!portalIframe) {
                return;
            }

            const portalContainer = portalIframe.contentWindow.document.querySelector('.gh-portal-popup-container');
            if (!portalContainer) {
                return;
            }

            const height = portalContainer.clientHeight;
            this.portalPreviewIframe.parentNode.style.height = `${height}px`;
        }
    }

    @action
    setup() {
        this.fetchDefaultProduct.perform();
        this.updatePortalPreview();
    }

    async saveProduct() {
        if (this.product) {
            const stripePrices = this.product.stripePrices || [];
            const monthlyAmount = this.stripeMonthlyAmount * 100;
            const yearlyAmount = this.stripeYearlyAmount * 100;
            const getActivePrice = (prices, type, amount) => {
                return prices.find((price) => {
                    return (
                        price.active && price.amount === amount && price.type === 'recurring' &&
                        price.interval === type && price.currency.toLowerCase() === this.currency.toLowerCase()
                    );
                });
            };
            const monthlyPrice = getActivePrice(stripePrices, 'month', monthlyAmount);
            const yearlyPrice = getActivePrice(stripePrices, 'year', yearlyAmount);

            if (!monthlyPrice) {
                stripePrices.push(
                    {
                        nickname: 'Monthly',
                        amount: monthlyAmount,
                        active: 1,
                        currency: this.currency,
                        interval: 'month',
                        type: 'recurring'
                    }
                );
            }
            if (!yearlyPrice) {
                stripePrices.push(
                    {
                        nickname: 'Yearly',
                        amount: this.stripeYearlyAmount * 100,
                        active: 1,
                        currency: this.currency,
                        interval: 'year',
                        type: 'recurring'
                    }
                );
            }
            if (monthlyPrice && yearlyPrice) {
                this.updatePortalPlans(monthlyPrice.id, yearlyPrice.id);
                this.settings.set('membersMonthlyPriceId', monthlyPrice.id);
                this.settings.set('membersYearlyPriceId', yearlyPrice.id);
                return this.product;
            } else {
                this.product.set('stripePrices', stripePrices);
                const savedProduct = await this.product.save();
                const updatedStripePrices = savedProduct.stripePrices || [];
                const updatedMonthlyPrice = getActivePrice(updatedStripePrices, 'month', monthlyAmount);
                const updatedYearlyPrice = getActivePrice(updatedStripePrices, 'year', yearlyAmount);
                this.updatePortalPlans(updatedMonthlyPrice.id, updatedYearlyPrice.id);
                this.settings.set('membersMonthlyPriceId', updatedMonthlyPrice.id);
                this.settings.set('membersYearlyPriceId', updatedYearlyPrice.id);
                return savedProduct;
            }
        }
    }

    updatePortalPlans(monthlyPriceId, yearlyPriceId) {
        let portalPlans = this.settings.get('portalPlans') || [];
        const currentMontlyPriceId = this.settings.get('membersMonthlyPriceId');
        const currentYearlyPriceId = this.settings.get('membersYearlyPriceId');
        if (portalPlans.includes(currentMontlyPriceId)) {
            portalPlans = portalPlans.filter(priceId => priceId !== currentMontlyPriceId);
            portalPlans.push(monthlyPriceId);
        }

        if (portalPlans.includes(currentYearlyPriceId)) {
            portalPlans = portalPlans.filter(priceId => priceId !== currentYearlyPriceId);
            portalPlans.push(yearlyPriceId);
        }
        this.settings.set('portalPlans', portalPlans);
    }

    getPrice(prices, type) {
        const monthlyPriceId = this.settings.get('membersMonthlyPriceId');
        const yearlyPriceId = this.settings.get('membersYearlyPriceId');

        if (type === 'monthly') {
            return (
                prices.find(price => price.id === monthlyPriceId) ||
                prices.find(price => price.nickname === 'Monthly') ||
                prices.find(price => price.interval === 'month')
            );
        }

        if (type === 'yearly') {
            return (
                prices.find(price => price.id === yearlyPriceId) ||
                prices.find(price => price.nickname === 'Yearly') ||
                prices.find(price => price.interval === 'year')
            );
        }
        return null;
    }

    @task({drop: true})
    *fetchDefaultProduct() {
        const products = yield this.store.query('product', {include: 'stripe_prices'});
        this.product = products.firstObject;
        this.stripePrices = [];
        if (this.product) {
            this.stripePrices = this.product.get('stripePrices') || [];
            const activePrices = this.stripePrices.filter(price => !!price.active);
            const monthlyPrice = this.getPrice(activePrices, 'monthly');
            const yearlyPrice = this.getPrice(activePrices, 'yearly');
            if (monthlyPrice && monthlyPrice.amount) {
                this.stripeMonthlyAmount = (monthlyPrice.amount / 100);
                this.currency = monthlyPrice.currency;
            }
            if (yearlyPrice && yearlyPrice.amount) {
                this.stripeYearlyAmount = (yearlyPrice.amount / 100);
            }
            this.updatePortalPreview();
        }
    }

    @task({drop: true})
    *saveSettingsTask() {
        yield this.validateStripePlans();

        if (this.stripePlanError) {
            return;
        }

        if (this.settings.get('errors').length !== 0) {
            return;
        }

        yield this.saveProduct();
        const result = yield this.settings.save();

        this.updatePortalPreview();

        return result;
    }

    reset() {
        this.showLeaveRouteModal = false;
        this.showLeavePortalModal = false;
        this.showPortalSettings = false;
    }
}
<commit_msg>Fixed portal plans change not triggering recompute<commit_after>import Controller from '@ember/controller';
import envConfig from 'ghost-admin/config/environment';
import {action} from '@ember/object';
import {currencies, getCurrencyOptions, getSymbol} from 'ghost-admin/utils/currency';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency-decorators';
import {timeout} from 'ember-concurrency';
import {tracked} from '@glimmer/tracking';

const CURRENCIES = currencies.map((currency) => {
    return {
        value: currency.isoCode.toLowerCase(),
        label: `${currency.isoCode} - ${currency.name}`,
        isoCode: currency.isoCode
    };
});

export default class MembersAccessController extends Controller {
    @service config;
    @service membersUtils;
    @service settings;
    @service store;

    @tracked showLeavePortalModal = false;
    @tracked showLeaveRouteModal = false;
    @tracked showPortalSettings = false;
    @tracked showStripeConnect = false;

    @tracked product = null;
    @tracked stripePrices = [];
    @tracked paidSignupRedirect;
    @tracked freeSignupRedirect;
    @tracked stripeMonthlyAmount = 5;
    @tracked stripeYearlyAmount = 50;
    @tracked currency = 'usd';
    @tracked stripePlanError = '';

    @tracked portalPreviewUrl = '';

    queryParams = ['showPortalSettings'];

    get allCurrencies() {
        return getCurrencyOptions();
    }

    get siteUrl() {
        return this.config.get('blogUrl');
    }

    get selectedCurrency() {
        return CURRENCIES.findBy('value', this.currency);
    }

    get isConnectDisallowed() {
        const siteUrl = this.config.get('blogUrl');
        return envConfig.environment !== 'development' && !/^https:/.test(siteUrl);
    }

    leaveRoute(transition) {
        if (this.settings.get('hasDirtyAttributes')) {
            transition.abort();
            this.leaveSettingsTransition = transition;
            this.showLeaveRouteModal = true;
        }
    }

    _validateSignupRedirect(url, type) {
        const siteUrl = this.config.get('blogUrl');
        let errMessage = `Please enter a valid URL`;
        this.settings.get('errors').remove(type);
        this.settings.get('hasValidated').removeObject(type);

        if (url === null) {
            this.settings.get('errors').add(type, errMessage);
            this.settings.get('hasValidated').pushObject(type);
            return false;
        }

        if (url === undefined) {
            // Not initialised
            return;
        }

        if (url.href.startsWith(siteUrl)) {
            const path = url.href.replace(siteUrl, '');
            this.settings.set(type, path);
        } else {
            this.settings.set(type, url.href);
        }
    }

    @action
    setStripePlansCurrency(event) {
        const newCurrency = event.value;
        this.currency = newCurrency;
    }

    @action
    setPaidSignupRedirect(url) {
        this.paidSignupRedirect = url;
    }

    @action
    setFreeSignupRedirect(url) {
        this.freeSignupRedirect = url;
    }

    @action
    validatePaidSignupRedirect() {
        return this._validateSignupRedirect(this.paidSignupRedirect, 'membersPaidSignupRedirect');
    }

    @action
    validateFreeSignupRedirect() {
        return this._validateSignupRedirect(this.freeSignupRedirect, 'membersFreeSignupRedirect');
    }

    @action
    validateStripePlans() {
        this.stripePlanError = undefined;

        try {
            const yearlyAmount = this.stripeYearlyAmount;
            const monthlyAmount = this.stripeMonthlyAmount;
            const symbol = getSymbol(this.currency);
            if (!yearlyAmount || yearlyAmount < 1 || !monthlyAmount || monthlyAmount < 1) {
                throw new TypeError(`Subscription amount must be at least ${symbol}1.00`);
            }

            this.updatePortalPreview();
        } catch (err) {
            this.stripePlanError = err.message;
        }
    }

    @action
    closeStripeConnect() {
        this.showStripeConnect = false;
    }

    @action
    openPortalSettings() {
        this.saveSettingsTask.perform();
        this.showPortalSettings = true;
    }

    @action
    closePortalSettings() {
        const changedAttributes = this.settings.changedAttributes();
        if (changedAttributes && Object.keys(changedAttributes).length > 0) {
            this.showLeavePortalModal = true;
        } else {
            this.showPortalSettings = false;
            this.updatePortalPreview();
        }
    }

    @action
    async confirmClosePortalSettings() {
        this.settings.rollbackAttributes();
        this.showPortalSettings = false;
        this.showLeavePortalModal = false;
        this.updatePortalPreview();
    }

    @action
    cancelClosePortalSettings() {
        this.showLeavePortalModal = false;
    }

    @action
    async confirmLeave() {
        this.settings.rollbackAttributes();
        this.leaveSettingsTransition.retry();
    }

    @action
    cancelLeave() {
        this.showLeaveRouteModal = false;
        this.leaveSettingsTransition = null;
    }

    @action
    updatePortalPreview() {
        // TODO: can these be worked out from settings in membersUtils?
        const monthlyPrice = this.stripeMonthlyAmount * 100;
        const yearlyPrice = this.stripeYearlyAmount * 100;
        let portalPlans = this.settings.get('portalPlans') || [];
        const currentMontlyPriceId = this.settings.get('membersMonthlyPriceId');
        const currentYearlyPriceId = this.settings.get('membersYearlyPriceId');
        let isMonthlyChecked = false;
        let isYearlyChecked = false;
        if (portalPlans.includes(currentMontlyPriceId)) {
            isMonthlyChecked = true;
        }

        if (portalPlans.includes(currentYearlyPriceId)) {
            isYearlyChecked = true;
        }

        this.portalPreviewUrl = this.membersUtils.getPortalPreviewUrl({
            button: false,
            monthlyPrice,
            yearlyPrice,
            currency: this.currency,
            isMonthlyChecked,
            isYearlyChecked,
            portalPlans: null
        });

        this.resizePortalPreviewTask.perform();
    }

    @action
    portalPreviewLoaded(event) {
        this.portalPreviewIframe = event.target;
        this.resizePortalPreviewTask.perform();
    }

    @action
    portalPreviewDestroyed() {
        this.portalPreviewIframe = null;
        this.resizePortalPreviewTask.cancelAll();
    }

    @task({restartable: true})
    *resizePortalPreviewTask() {
        if (this.portalPreviewIframe && this.portalPreviewIframe.contentWindow) {
            yield timeout(100); // give time for portal to re-render

            const portalIframe = this.portalPreviewIframe.contentWindow.document.querySelector('#ghost-portal-root iframe');
            if (!portalIframe) {
                return;
            }

            const portalContainer = portalIframe.contentWindow.document.querySelector('.gh-portal-popup-container');
            if (!portalContainer) {
                return;
            }

            const height = portalContainer.clientHeight;
            this.portalPreviewIframe.parentNode.style.height = `${height}px`;
        }
    }

    @action
    setup() {
        this.fetchDefaultProduct.perform();
        this.updatePortalPreview();
    }

    async saveProduct() {
        if (this.product) {
            const stripePrices = this.product.stripePrices || [];
            const monthlyAmount = this.stripeMonthlyAmount * 100;
            const yearlyAmount = this.stripeYearlyAmount * 100;
            const getActivePrice = (prices, type, amount) => {
                return prices.find((price) => {
                    return (
                        price.active && price.amount === amount && price.type === 'recurring' &&
                        price.interval === type && price.currency.toLowerCase() === this.currency.toLowerCase()
                    );
                });
            };
            const monthlyPrice = getActivePrice(stripePrices, 'month', monthlyAmount);
            const yearlyPrice = getActivePrice(stripePrices, 'year', yearlyAmount);

            if (!monthlyPrice) {
                stripePrices.push(
                    {
                        nickname: 'Monthly',
                        amount: monthlyAmount,
                        active: 1,
                        currency: this.currency,
                        interval: 'month',
                        type: 'recurring'
                    }
                );
            }
            if (!yearlyPrice) {
                stripePrices.push(
                    {
                        nickname: 'Yearly',
                        amount: this.stripeYearlyAmount * 100,
                        active: 1,
                        currency: this.currency,
                        interval: 'year',
                        type: 'recurring'
                    }
                );
            }
            if (monthlyPrice && yearlyPrice) {
                this.updatePortalPlans(monthlyPrice.id, yearlyPrice.id);
                this.settings.set('membersMonthlyPriceId', monthlyPrice.id);
                this.settings.set('membersYearlyPriceId', yearlyPrice.id);
                return this.product;
            } else {
                this.product.set('stripePrices', stripePrices);
                const savedProduct = await this.product.save();
                const updatedStripePrices = savedProduct.stripePrices || [];
                const updatedMonthlyPrice = getActivePrice(updatedStripePrices, 'month', monthlyAmount);
                const updatedYearlyPrice = getActivePrice(updatedStripePrices, 'year', yearlyAmount);
                this.updatePortalPlans(updatedMonthlyPrice.id, updatedYearlyPrice.id);
                this.settings.set('membersMonthlyPriceId', updatedMonthlyPrice.id);
                this.settings.set('membersYearlyPriceId', updatedYearlyPrice.id);
                return savedProduct;
            }
        }
    }

    updatePortalPlans(monthlyPriceId, yearlyPriceId) {
        let portalPlans = this.settings.get('portalPlans') || [];
        const currentMontlyPriceId = this.settings.get('membersMonthlyPriceId');
        const currentYearlyPriceId = this.settings.get('membersYearlyPriceId');
        if (portalPlans.includes(currentMontlyPriceId)) {
            portalPlans = portalPlans.filter(priceId => priceId !== currentMontlyPriceId);
            portalPlans.pushObject(monthlyPriceId);
        }

        if (portalPlans.includes(currentYearlyPriceId)) {
            portalPlans = portalPlans.filter(priceId => priceId !== currentYearlyPriceId);
            portalPlans.pushObject(yearlyPriceId);
        }
        this.settings.set('portalPlans', portalPlans);
    }

    getPrice(prices, type) {
        const monthlyPriceId = this.settings.get('membersMonthlyPriceId');
        const yearlyPriceId = this.settings.get('membersYearlyPriceId');

        if (type === 'monthly') {
            return (
                prices.find(price => price.id === monthlyPriceId) ||
                prices.find(price => price.nickname === 'Monthly') ||
                prices.find(price => price.interval === 'month')
            );
        }

        if (type === 'yearly') {
            return (
                prices.find(price => price.id === yearlyPriceId) ||
                prices.find(price => price.nickname === 'Yearly') ||
                prices.find(price => price.interval === 'year')
            );
        }
        return null;
    }

    @task({drop: true})
    *fetchDefaultProduct() {
        const products = yield this.store.query('product', {include: 'stripe_prices'});
        this.product = products.firstObject;
        this.stripePrices = [];
        if (this.product) {
            this.stripePrices = this.product.get('stripePrices') || [];
            const activePrices = this.stripePrices.filter(price => !!price.active);
            const monthlyPrice = this.getPrice(activePrices, 'monthly');
            const yearlyPrice = this.getPrice(activePrices, 'yearly');
            if (monthlyPrice && monthlyPrice.amount) {
                this.stripeMonthlyAmount = (monthlyPrice.amount / 100);
                this.currency = monthlyPrice.currency;
            }
            if (yearlyPrice && yearlyPrice.amount) {
                this.stripeYearlyAmount = (yearlyPrice.amount / 100);
            }
            this.updatePortalPreview();
        }
    }

    @task({drop: true})
    *saveSettingsTask() {
        yield this.validateStripePlans();

        if (this.stripePlanError) {
            return;
        }

        if (this.settings.get('errors').length !== 0) {
            return;
        }

        yield this.saveProduct();
        const result = yield this.settings.save();

        this.updatePortalPreview();

        return result;
    }

    reset() {
        this.showLeaveRouteModal = false;
        this.showLeavePortalModal = false;
        this.showPortalSettings = false;
    }
}
<|endoftext|>


<commit_before>/**
 * sails-generate-bower
 *
 * Usage:
 * `sails generate bower`
 *
 * @type {Object}
 */

var path = require('path'),
    merge = require('./merge-json'),
    insertAfter = require('./insert-after'),
    update = require('./update');

var templates = require('path').resolve(__dirname,'../templates');

module.exports = {

	templatesDirectory: templates,

	before: require('./before'),

	targets: {

        './assets/images/logos': { folder: {} },
        './assets/images/logos/angularjs.png': { copy: 'assets/images/logos/angularjs.png' },
        './assets/images/logos/nodejs.png': { copy: 'assets/images/logos/nodejs.png' },
        './assets/images/logos/sails-logo.png': { copy: 'assets/images/logos/sails-logo.png' },
        './assets/src': { folder: {} },
        './assets/src/app': { folder: {} },
        './assets/src/app/app.js': { template: 'assets/src/app/app.js' },
        './assets/src/app/about': { folder: {} },
        './assets/src/app/about/index.js': { template: 'assets/src/app/about/index.js' },
        './assets/src/app/about/index.tpl.html': { template: 'assets/src/app/about/index.tpl.html' },
        './assets/src/app/header': { folder: {} },
        './assets/src/app/header/index.js': { template: 'assets/src/app/header/index.js' },
        './assets/src/app/header/index.tpl.html': { template: 'assets/src/app/header/index.tpl.html' },
        './assets/src/app/home': { folder: {} },
        './assets/src/app/home/index.js': { template: 'assets/src/app/home/index.js' },
        './assets/src/app/home/index.tpl.html': { template: 'assets/src/app/home/index.tpl.html' },
        './assets/src/app/users': { folder: {} },
        './assets/src/app/users/index.js': { template: 'assets/src/app/users/index.js' },
        './assets/src/app/users/index.tpl.html': { template: 'assets/src/app/users/index.tpl.html' },
        './assets/src/common': { folder: {} },
        './assets/src/common/directives': { folder: {} },
        './assets/src/common/directives/blink.js': { template: 'assets/src/common/directives/blink.js' },
        './assets/src/common/models': { folder: {} },
        './assets/src/common/models/index.js': { template: 'assets/src/common/models/index.js' },
        './assets/src/common/models/User.js': { template: 'assets/src/common/models/User.js' },
        './assets/src/common/services': { folder: {} },
        './assets/src/common/services/config.js': { template: 'assets/src/common/services/config.js' },
        './assets/src/common/services/index.js': { template: 'assets/src/common/services/index.js' },
        './assets/src/common/services/lodash.js': { template: 'assets/src/common/services/lodash.js' },
        './assets/src/common/services/title.js': { template: 'assets/src/common/services/title.js' },
        './assets/src/common/services/utils.js': { template: 'assets/src/common/services/utils.js' },
        './api/controllers/HomeController.js': { copy: 'api/controllers/HomeController.js' },
        './views/home': { folder: {} },
        './views/home/index.ejs': { copy: 'views/home/index.ejs' },

		'./': { exec: function (scope, cb) { console.log('Running generator (sails-generate-angular-gulp) @ `'+scope.rootPath+'`...'); cb(); }},

		'./bower.json': { exec: merge(path.join(templates, 'bower.json'))},

		'./tasks/config/html2js.js': {copy: path.join(templates, '/tasks/config/html2js.js')},

        './config/blueprints.js': { exec: insertAfter('prefix: \'', [['/api']]) },

        './views/layout.ejs': { exec: update(path.join(templates, '/views/layout.ejs')) },

        './tasks/pipeline.js': { exec: insertAfter('installing new tasks.', [['\nvar ngTemplateFilesToInject = [\n  \'src/app/**/*tpl.html\'\n];']], 'first place)', [['\nmodule.exports.ngTemplateFilesToInject = ngTemplateFilesToInject.map(function(path) {\n  return \'assets/\' + path;\n});']])},

		'./tasks/register/compileAssets.js': { exec: insertAfter('\'jst:dev\',', [['\n          \'html2js:dev\',']]) },
        './tasks/config/sails-linker-gulp.js': { exec: insertAfter('growl) {', [['\n    gulp.task(\'sails-linker-gulp:devTplNg\', function() {\n		// Read templates\n		return gulp.src([\'.tmp/public/index.html\', \'views/**/*.html\', \'views/**/*.ejs\'])\n				// Link the ng Templates\n				.pipe(plugins.linker({\n					scripts: [\'.tmp/public/templates.js\'],\n					startTag: \'<!--TEMPLATES-->\',\n					endTag: \'<!--TEMPLATES END-->\',\n					fileTmpl: \'<script type=\"text/javascript\" src=\"%s\"></script>\',\n					appRoot: \'.tmp/public\',\n				}))\n				// Write modified files to www/\n				.pipe(gulp.dest(\'views/\'))\n				.pipe(plugins.if(growl, plugins.notify({ message: \'sails-linker-gulp devTpl task complete\' })));\n	});']]) },
        './tasks/config/copy.js': { exec: insertAfter('\'!assets/images{,/**}\'', [[', \'!assets/src/app/**/*.html\'']]) },
        './config/routes.js': { exec: insertAfter('.routes = {', [['\n\'get /home\': \'HomeController.index\','], ['\n\'get /about\': \'HomeController.index\',']]) },
		'./package.json': { exec: merge(path.join(templates, 'package.json')) },
        './tasks/register/linkAssets.js': { exec: insertAfter('\'sails-linker-gulp:devTpl\',', [['\n            \'sails-linker-gulp:devTplNg\',']]) }

    }
};
<commit_msg>add better exclude for angular template files<commit_after>/**
 * sails-generate-bower
 *
 * Usage:
 * `sails generate bower`
 *
 * @type {Object}
 */

var path = require('path'),
    merge = require('./merge-json'),
    insertAfter = require('./insert-after'),
    update = require('./update');

var templates = require('path').resolve(__dirname,'../templates');

module.exports = {

	templatesDirectory: templates,

	before: require('./before'),

	targets: {

        './assets/images/logos': { folder: {} },
        './assets/images/logos/angularjs.png': { copy: 'assets/images/logos/angularjs.png' },
        './assets/images/logos/nodejs.png': { copy: 'assets/images/logos/nodejs.png' },
        './assets/images/logos/sails-logo.png': { copy: 'assets/images/logos/sails-logo.png' },
        './assets/src': { folder: {} },
        './assets/src/app': { folder: {} },
        './assets/src/app/app.js': { template: 'assets/src/app/app.js' },
        './assets/src/app/about': { folder: {} },
        './assets/src/app/about/index.js': { template: 'assets/src/app/about/index.js' },
        './assets/src/app/about/index.tpl.html': { template: 'assets/src/app/about/index.tpl.html' },
        './assets/src/app/header': { folder: {} },
        './assets/src/app/header/index.js': { template: 'assets/src/app/header/index.js' },
        './assets/src/app/header/index.tpl.html': { template: 'assets/src/app/header/index.tpl.html' },
        './assets/src/app/home': { folder: {} },
        './assets/src/app/home/index.js': { template: 'assets/src/app/home/index.js' },
        './assets/src/app/home/index.tpl.html': { template: 'assets/src/app/home/index.tpl.html' },
        './assets/src/app/users': { folder: {} },
        './assets/src/app/users/index.js': { template: 'assets/src/app/users/index.js' },
        './assets/src/app/users/index.tpl.html': { template: 'assets/src/app/users/index.tpl.html' },
        './assets/src/common': { folder: {} },
        './assets/src/common/directives': { folder: {} },
        './assets/src/common/directives/blink.js': { template: 'assets/src/common/directives/blink.js' },
        './assets/src/common/models': { folder: {} },
        './assets/src/common/models/index.js': { template: 'assets/src/common/models/index.js' },
        './assets/src/common/models/User.js': { template: 'assets/src/common/models/User.js' },
        './assets/src/common/services': { folder: {} },
        './assets/src/common/services/config.js': { template: 'assets/src/common/services/config.js' },
        './assets/src/common/services/index.js': { template: 'assets/src/common/services/index.js' },
        './assets/src/common/services/lodash.js': { template: 'assets/src/common/services/lodash.js' },
        './assets/src/common/services/title.js': { template: 'assets/src/common/services/title.js' },
        './assets/src/common/services/utils.js': { template: 'assets/src/common/services/utils.js' },
        './api/controllers/HomeController.js': { copy: 'api/controllers/HomeController.js' },
        './views/home': { folder: {} },
        './views/home/index.ejs': { copy: 'views/home/index.ejs' },

		'./': { exec: function (scope, cb) { console.log('Running generator (sails-generate-angular-gulp) @ `'+scope.rootPath+'`...'); cb(); }},

		'./bower.json': { exec: merge(path.join(templates, 'bower.json'))},

		'./tasks/config/html2js.js': {copy: path.join(templates, '/tasks/config/html2js.js')},

        './config/blueprints.js': { exec: insertAfter('prefix: \'', [['/api']]) },

        './views/layout.ejs': { exec: update(path.join(templates, '/views/layout.ejs')) },

        './tasks/pipeline.js': { exec: insertAfter('installing new tasks.', [['\nvar ngTemplateFilesToInject = [\n  \'src/app/**/*tpl.html\'\n];']], 'first place)', [['\nmodule.exports.ngTemplateFilesToInject = ngTemplateFilesToInject.map(function(path) {\n  return \'assets/\' + path;\n});']])},

		'./tasks/register/compileAssets.js': { exec: insertAfter('\'jst:dev\',', [['\n          \'html2js:dev\',']]) },
        './tasks/config/sails-linker-gulp.js': { exec: insertAfter('growl) {', [['\n    gulp.task(\'sails-linker-gulp:devTplNg\', function() {\n		// Read templates\n		return gulp.src([\'.tmp/public/index.html\', \'views/**/*.html\', \'views/**/*.ejs\'])\n				// Link the ng Templates\n				.pipe(plugins.linker({\n					scripts: [\'.tmp/public/templates.js\'],\n					startTag: \'<!--TEMPLATES-->\',\n					endTag: \'<!--TEMPLATES END-->\',\n					fileTmpl: \'<script type=\"text/javascript\" src=\"%s\"></script>\',\n					appRoot: \'.tmp/public\',\n				}))\n				// Write modified files to www/\n				.pipe(gulp.dest(\'views/\'))\n				.pipe(plugins.if(growl, plugins.notify({ message: \'sails-linker-gulp devTpl task complete\' })));\n	});']]) },
        './tasks/config/copy.js': { exec: insertAfter('coffee|less|', [['[tpl.html]']]) },
        './config/routes.js': { exec: insertAfter('.routes = {', [['\n\'get /home\': \'HomeController.index\','], ['\n\'get /about\': \'HomeController.index\',']]) },
		'./package.json': { exec: merge(path.join(templates, 'package.json')) },
        './tasks/register/linkAssets.js': { exec: insertAfter('\'sails-linker-gulp:devTpl\',', [['\n            \'sails-linker-gulp:devTplNg\',']]) }

    }
};
<|endoftext|>


<commit_before>
/**
 * Module dependencies.
 */

var parser = require('socket.io-parser')
  , encode = parser.encode
  , decode = parser.decode
  , debug = require('debug')('socket.io:client');

/**
 * Module exports.
 */

module.exports = Client;

/**
 * Client constructor.
 *
 * @param {Server} server instance
 * @param {Socket} connection
 * @api private
 */

function Client(server, conn){
  this.server = server;
  this.conn = conn;
  this.id = conn.id;
  this.request = conn.request;
  this.setup();
  this.sockets = [];
  this.nsps = {};
}

/**
 * Sets up event listeners.
 *
 * @api private
 */

Client.prototype.setup = function(){
  this.onclose = this.onclose.bind(this);
  this.ondata = this.ondata.bind(this);
  this.conn.on('data', this.ondata);
  this.conn.on('close', this.onclose);
};

/**
 * Connects a client to a namespace.
 *
 * @param {String} namespace name
 * @api private
 */

Client.prototype.connect = function(name){
  debug('connecting to namespace %s', name);
  var nsp = this.server.of(name);
  var self = this;
  var socket = nsp.add(this, function(){
    self.sockets.push(socket);
    self.nsps[nsp.name] = socket;
  });
};

/**
 * Disconnects from all namespaces and closes transport.
 *
 * @api private
 */

Client.prototype.disconnect = function(){
  var socket;
  // we don't use a for loop because the length of
  // `sockets` changes upon each iteration
  while (socket = this.sockets.shift()) {
    socket.disconnect();
  }
  this.close();
};

/**
 * Removes a socket. Called by each `Socket`.
 *
 * @api private
 */

Client.prototype.remove = function(socket){
  var i = this.sockets.indexOf(socket);
  if (~i) {
    var nsp = this.sockets[i].nsp.name;
    this.sockets.splice(i, 1);
    delete this.nsps[nsp];
  } else {
    debug('ignoring remove for %s', socket.id);
  }
};

/**
 * Closes the underlying connection.
 *
 * @api private
 */

Client.prototype.close = function(){
  if ('open' == this.conn.readyState) {
    debug('forcing transport close');
    this.conn.close();
    this.onclose('forced server close');
  }
};

/**
 * Writes a packet to the transport.
 *
 * @param {Object} packet object
 * @api private
 */

Client.prototype.packet = function(packet){
  if ('open' == this.conn.readyState) {
    debug('writing packet %j', packet);
    this.conn.write(encode(packet));
  } else {
    debug('ignoring packet write %j', packet);
  }
};

/**
 * Called with incoming transport data.
 *
 * @api private
 */

Client.prototype.ondata = function(data){
  var packet = decode(data.toString());
  debug('got packet %j', packet);

  if (parser.CONNECT == packet.type) {
    this.connect(packet.nsp);
  } else {
    var socket = this.nsps[packet.nsp];
    if (socket) {
      socket.onpacket(packet);
    } else {
      debug('no socket for namespace %s', packet.nsp);
    }
  }
};

/**
 * Called upon transport close.
 *
 * @param {String} reason
 * @api private
 */

Client.prototype.onclose = function(reason){
  debug('client close with reason %s', reason);

  // ignore a potential subsequent `close` event
  this.destroy();

  // `nsps` and `sockets` are cleaned up seamlessly
  this.sockets.forEach(function(socket){
    socket.onclose(reason);
  });
};

/**
 * Cleans up event listeners.
 *
 * @api private
 */

Client.prototype.destroy = function(){
  this.conn.removeListener('data', this.ondata);
  this.conn.removeListener('close', this.onclose);
};
<commit_msg>client: fix style<commit_after>
/**
 * Module dependencies.
 */

var parser = require('socket.io-parser');
var encode = parser.encode;
var decode = parser.decode;
var debug = require('debug')('socket.io:client');

/**
 * Module exports.
 */

module.exports = Client;

/**
 * Client constructor.
 *
 * @param {Server} server instance
 * @param {Socket} connection
 * @api private
 */

function Client(server, conn){
  this.server = server;
  this.conn = conn;
  this.id = conn.id;
  this.request = conn.request;
  this.setup();
  this.sockets = [];
  this.nsps = {};
}

/**
 * Sets up event listeners.
 *
 * @api private
 */

Client.prototype.setup = function(){
  this.onclose = this.onclose.bind(this);
  this.ondata = this.ondata.bind(this);
  this.conn.on('data', this.ondata);
  this.conn.on('close', this.onclose);
};

/**
 * Connects a client to a namespace.
 *
 * @param {String} namespace name
 * @api private
 */

Client.prototype.connect = function(name){
  debug('connecting to namespace %s', name);
  var nsp = this.server.of(name);
  var self = this;
  var socket = nsp.add(this, function(){
    self.sockets.push(socket);
    self.nsps[nsp.name] = socket;
  });
};

/**
 * Disconnects from all namespaces and closes transport.
 *
 * @api private
 */

Client.prototype.disconnect = function(){
  var socket;
  // we don't use a for loop because the length of
  // `sockets` changes upon each iteration
  while (socket = this.sockets.shift()) {
    socket.disconnect();
  }
  this.close();
};

/**
 * Removes a socket. Called by each `Socket`.
 *
 * @api private
 */

Client.prototype.remove = function(socket){
  var i = this.sockets.indexOf(socket);
  if (~i) {
    var nsp = this.sockets[i].nsp.name;
    this.sockets.splice(i, 1);
    delete this.nsps[nsp];
  } else {
    debug('ignoring remove for %s', socket.id);
  }
};

/**
 * Closes the underlying connection.
 *
 * @api private
 */

Client.prototype.close = function(){
  if ('open' == this.conn.readyState) {
    debug('forcing transport close');
    this.conn.close();
    this.onclose('forced server close');
  }
};

/**
 * Writes a packet to the transport.
 *
 * @param {Object} packet object
 * @api private
 */

Client.prototype.packet = function(packet){
  if ('open' == this.conn.readyState) {
    debug('writing packet %j', packet);
    this.conn.write(encode(packet));
  } else {
    debug('ignoring packet write %j', packet);
  }
};

/**
 * Called with incoming transport data.
 *
 * @api private
 */

Client.prototype.ondata = function(data){
  var packet = decode(data.toString());
  debug('got packet %j', packet);

  if (parser.CONNECT == packet.type) {
    this.connect(packet.nsp);
  } else {
    var socket = this.nsps[packet.nsp];
    if (socket) {
      socket.onpacket(packet);
    } else {
      debug('no socket for namespace %s', packet.nsp);
    }
  }
};

/**
 * Called upon transport close.
 *
 * @param {String} reason
 * @api private
 */

Client.prototype.onclose = function(reason){
  debug('client close with reason %s', reason);

  // ignore a potential subsequent `close` event
  this.destroy();

  // `nsps` and `sockets` are cleaned up seamlessly
  this.sockets.forEach(function(socket){
    socket.onclose(reason);
  });
};

/**
 * Cleans up event listeners.
 *
 * @api private
 */

Client.prototype.destroy = function(){
  this.conn.removeListener('data', this.ondata);
  this.conn.removeListener('close', this.onclose);
};
<|endoftext|>


<commit_before>var merohcCRMControllers = angular.module('merohc.crm.controllers', ['ui.router']);

merohcCRMControllers.controller('CompanyListController', ['$scope', '$http', '$location', '$state', 'merohc-config' , function ($scope, $http, $location, $state, merohcConfig) {

  $scope.items = '';

  $scope.filteredItems = $scope.items;

  $scope.searchTerm="";

  $scope.selectedItem=$scope.items[0];

  $scope.targetId="";

  $scope.setTargetId=function(targetId){
    $scope.targetId=targetId;
  }

  $scope.selectItem=function(selectedCompany){
    $scope.selectedItem = selectedCompany;
    $state.go('crm.companies.view', { companyId: selectedCompany.id });
  };

  $scope.selectItemById=function(id){
    for (var index in $scope.items) {
      var company = $scope.items[index];
      if (company.id===id){
        $scope.selectedItem=company;
      }
    }
  }

  $scope.isItemSelected=function(selectedCompany){
    return selectedCompany===$scope.selectedItem;
  };

  $scope.filter=function(){
    $scope.filteredItems=[];
    for (var index in $scope.items) {
      var company = $scope.items[index];
      var regexp = new RegExp($scope.searchTerm,"i");
      if (company.name.match(regexp)){
        $scope.filteredItems.push(company);
      }
    }
  };

  $scope.updateItem = function(oldItem, newItem) {
    for (var index in $scope.items) {
      var company = $scope.items[index];
      if (company.id===oldItem.id){
        $scope.items[index]=newItem;
      }
    }

    $scope.filter();
  }

  $scope.addItem = function(newItem) {
    $scope.items.push(newItem);
    $scope.filter();
    $state.go('crm.companies.view', { companyId: newItem.id })
  }

  $scope.deleteItem = function(oldItem) {

    for (var index in $scope.items) {
      var company = $scope.items[index];
      if (company.id===oldItem.id){
        if (index > -1) {
          $scope.items.splice(index, 1);
        }
      }
    }
    $state.go("crm.companies");
    $scope.refresh();
  }

  $scope.refresh=function(){
    $http.get(merohcConfig.BASE_URL + '/company').success(function(data){
      $scope.items = data;
      $scope.filter();
    });
  };

  $scope.refresh();

}]);

merohcCRMControllers.controller('CompanyDetailController',
    ['$scope', '$http', '$state', 'merohc-config',
    function ($scope, $http, $state, merohcConfig){

  $scope.companyId=$state.params.companyId;

  $scope.updateCompany=function(){
    if ($scope.companyId){
      $http.get(merohcConfig.BASE_URL + '/company/'+encodeURIComponent($scope.companyId)).success(function(data){
        $scope.company = data;
      });
    }
  };

  $scope.deleteCompany=function(){
    //FIXME JC 151212 - Should ask confirmation for deletion
    if ($scope.companyId){
      $http.delete(merohcConfig.BASE_URL + '/company/'+encodeURIComponent($scope.companyId)).success(function(data){
        $scope.deleteItem($scope.company);
      });
    }
  }

  $scope.editCompany=function(){
    $state.go('crm.companies.edit', { companyId: $scope.companyId });
  }

  //get back contact details for the company
  /*$scope.updateContactDetails=function(){
    if ($scope.companyId){
      $http.get('services/v1/ContactDetails?field=target&value='+$scope.companyId).success(function(data){
        $scope.contactDetails = data;
      });
    }
  };

  //get back notes for the company
  $scope.updateNotes=function(){
    if ($scope.companyId){
      $http.get('services/v1/Note?field=target&value='+$scope.companyId).success(function(data){
        $scope.notes = data;
      });
    }
  };*/

  //get back employees for the company
  $scope.updateEmployees=function(){
    if ($scope.companyId){
      $http.get(merohcConfig.BASE_URL + '/company/'+encodeURIComponent($scope.companyId)+'/employee').success(function(data){
        $scope.employees = data;
      });
    }
  };

  //get back invoices for the company
  /*$scope.updateInvoices=function(){
    if ($scope.companyId){
      $http.get('services/v1/Invoice?field=payer&value='+$scope.companyId).success(function(data){
        $scope.invoices = data;
      });
    }
  };*/

  $scope.updateCompany();
  /*$scope.updateContactDetails();
  $scope.updateNotes();*/
  $scope.updateEmployees();
  /*$scope.updateInvoices();*/

}]);

merohcCRMControllers.controller('CompanyCreateController', ['$scope', '$http', '$window', 'merohc-config',function ($scope, $http, $window, merohcConfig) {

  $scope.saveCompany = function(){
    $http({
            method  : 'PUT',
            url     : merohcConfig.BASE_URL + '/company/add',
            data    : $.param($scope.company),  // pass in data as strings
            headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
         })
          .success(function(data) {

            //update company and selectedItem in parent scope
            $scope.addItem(data);
            $scope.$parent.selectedItem=data;
          });
  };

  $scope.cancel = function(){
    $window.history.back();
  }

}]);

merohcCRMControllers.controller('CompanyEditController', ['$scope', '$http', '$window', '$state', 'merohc-config',function ($scope, $http, $window, $state, merohcConfig) {

  $scope.companyId=$state.params.companyId;

  $scope.updateCompany=function(){
    if ($scope.companyId){
      $http.get(merohcConfig.BASE_URL + '/company/'+encodeURIComponent($scope.companyId)).success(function(data){
        $scope.company = data;
        $scope.oldCompany = angular.copy(data);
      });
    }
  };

  $scope.saveCompany = function(){
    $http({
            method  : 'POST',
            url     : merohcConfig.BASE_URL + '/company',
            data    : $.param($scope.company),  // pass in data as strings
            headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
         })
          .success(function(data) {

            //update company and selectedItem in parent scope
            $scope.updateItem($scope.oldCompany, data);
            $scope.$parent.selectedItem=data;

            $state.go('^')
          });
  };

  $scope.cancel = function(){
    $window.history.back();
  }

  $scope.updateCompany();

}]);

merohcCRMControllers.controller('EmployeeCreateController', ['$scope', '$http', '$state', '$stateParams', 'merohc-config',function ($scope, $http, $state, $stateParams, merohcConfig) {

  $scope.saveEmployee = function(){
    $http({
            method  : 'PUT',
            url     : merohcConfig.BASE_URL + '/company/'+ $stateParams.companyId +'/employee/add',
            data    : $.param($scope.employee),  // pass in data as strings
            headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
         })
          .success(function(data) {
            $state.go('crm.companies.view', { companyId: $stateParams.companyId })
          });
  };

  $scope.cancel = function(){
    $state.go('crm.companies.view', { companyId: $stateParams.companyId })
  }

}]);

merohcCRMControllers.controller('PersonListController', function ($scope, $http, $location, $state) {

  $scope.items = '';

  $scope.filteredItems = $scope.items;

  $scope.searchTerm="";

  $scope.selectedItem=$scope.items[0];

  $scope.targetId="";

  $scope.setTargetId=function(targetId){
    $scope.targetId=targetId;
  }

  $scope.selectItem=function(selectedPerson){
    $scope.selectedItem = selectedPerson;
    $state.go('crm.persons.view', { personId: selectedPerson.id });
  };

  $scope.selectItemById=function(id){
    for (var index in $scope.items) {
      var company = $scope.items[index];
      if (company.id===id){
        $scope.selectedItem=company;
      }
    }
  }

  $scope.isItemSelected=function(selectedCompany){
    return selectedCompany===$scope.selectedItem;
  };

  $scope.filter=function(){
    $scope.filteredItems=[];
    for (var index in $scope.items) {
      var company = $scope.items[index];
      var regexp = new RegExp($scope.searchTerm,"i");
      if (company.Person.firstName.match(regexp)||company.Person.lastName.match(regexp)){
        $scope.filteredItems.push(company);
      }
    }
  };

  $scope.updateItem = function(oldItem, newItem) {
    for (var index in $scope.items) {
      var company = $scope.items[index];
      if (company===oldItem){
        $scope.items[index]=newItem;
      }
    }

    $scope.filter();
  }

  $scope.addItem = function(newItem) {
    $scope.items.push(newItem);
    $scope.filter();
  }

  $scope.deleteItem = function(oldItem) {
    var index = $scope.items.indexOf(oldItem);

    if (index > -1) {
        $scope.items.splice(index, 1);
    }

    $scope.filter();
  }

  $scope.refresh=function(){
    $http.get('services/v1/Person').success(function(data){
      $scope.items = data;
      $scope.filter();
    });
  };

  $scope.refresh();

});

merohcCRMControllers.controller('PersonCreateController', function ($scope, $http, $window) {

  $scope.saveCompany = function(){
    $http({
            method  : 'PUT',
            url     : 'companies/add',
            data    : $.param($scope.company),  // pass in data as strings
            headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
         })
          .success(function(data) {

            //update company and selectedItem in parent scope
            $scope.addItem(data);
            $scope.$parent.selectedItem=data;

            $window.history.back();
          });
  };

  $scope.cancel = function(){
    $window.history.back();
  }

});

merohcCRMControllers.controller('PersonDetailController', function ($scope, $http, $state){

  $scope.personId=$state.params.personId;

  $scope.updatePerson=function(){
      if ($scope.personId){
        $http.get('services/v1/Person/'+$scope.personId).success(function(data){
          $scope.person = data;
        });
      }
    };

  //get back contact details for the person
  $scope.updateContactDetails=function(){
    if ($scope.personId){
      $http.get('services/v1/ContactDetails?field=target&value='+$scope.personId).success(function(data){
        $scope.contactDetails = data;
      });
    }
  };

  //get back notes for the person
  $scope.updateNotes=function(){
    if ($scope.personId){
      $http.get('services/v1/Note?field=target&value='+$scope.personId).success(function(data){
        $scope.notes = data;
      });
    }
  };

  //get back employees for the person
  $scope.updateEmployees=function(){
    if ($scope.personId){
      $http.get('services/v1/Employee?field=company&value='+$scope.personId).success(function(data){
        $scope.employees = data;
      });
    }
  };

  $scope.updatePerson();
  $scope.updateContactDetails();
  $scope.updateNotes();
  $scope.updateEmployees();

});

merohcCRMControllers.controller('NoteController', function ($scope, $http, $state){

  $scope.noteId=$state.params.noteId;

  $scope.updateNote=function(){
    if ($scope.noteId){
      $http.get('services/v1/Note/'+$scope.noteId).success(function(data){
        $scope.note = data;
      });
    }
  };

  $scope.updateNote();
});

merohcCRMControllers.controller('ContactDetailsController', function ($scope, $http, $state){

  $scope.contactDetailsId=$state.params.contactDetailsId;

  $scope.updateContactDetails=function(){
    if ($scope.contactDetailsId){
      $http.get('services/v1/ContactDetails/'+$scope.contactDetailsId).success(function(data){
        $scope.contactDetails = data;
      });
    }
  };

  $scope.updateContactDetails();
});<commit_msg>Remove $window use<commit_after>var merohcCRMControllers = angular.module('merohc.crm.controllers', ['ui.router']);

merohcCRMControllers.controller('CompanyListController', ['$scope', '$http', '$location', '$state', 'merohc-config' , function ($scope, $http, $location, $state, merohcConfig) {

  $scope.items = '';

  $scope.filteredItems = $scope.items;

  $scope.searchTerm="";

  $scope.selectedItem=$scope.items[0];

  $scope.targetId="";

  $scope.setTargetId=function(targetId){
    $scope.targetId=targetId;
  }

  $scope.selectItem=function(selectedCompany){
    $scope.selectedItem = selectedCompany;
    $state.go('crm.companies.view', { companyId: selectedCompany.id });
  };

  $scope.selectItemById=function(id){
    for (var index in $scope.items) {
      var company = $scope.items[index];
      if (company.id===id){
        $scope.selectedItem=company;
      }
    }
  }

  $scope.isItemSelected=function(selectedCompany){
    return selectedCompany===$scope.selectedItem;
  };

  $scope.filter=function(){
    $scope.filteredItems=[];
    for (var index in $scope.items) {
      var company = $scope.items[index];
      var regexp = new RegExp($scope.searchTerm,"i");
      if (company.name.match(regexp)){
        $scope.filteredItems.push(company);
      }
    }
  };

  $scope.updateItem = function(oldItem, newItem) {
    for (var index in $scope.items) {
      var company = $scope.items[index];
      if (company.id===oldItem.id){
        $scope.items[index]=newItem;
      }
    }

    $scope.filter();
  }

  $scope.addItem = function(newItem) {
    $scope.items.push(newItem);
    $scope.filter();
    $state.go('crm.companies.view', { companyId: newItem.id })
  }

  $scope.deleteItem = function(oldItem) {

    for (var index in $scope.items) {
      var company = $scope.items[index];
      if (company.id===oldItem.id){
        if (index > -1) {
          $scope.items.splice(index, 1);
        }
      }
    }
    $state.go("crm.companies");
    $scope.refresh();
  }

  $scope.refresh=function(){
    $http.get(merohcConfig.BASE_URL + '/company').success(function(data){
      $scope.items = data;
      $scope.filter();
    });
  };

  $scope.refresh();

}]);

merohcCRMControllers.controller('CompanyDetailController',
    ['$scope', '$http', '$state', 'merohc-config',
    function ($scope, $http, $state, merohcConfig){

  $scope.companyId=$state.params.companyId;

  $scope.updateCompany=function(){
    if ($scope.companyId){
      $http.get(merohcConfig.BASE_URL + '/company/'+encodeURIComponent($scope.companyId)).success(function(data){
        $scope.company = data;
      });
    }
  };

  $scope.deleteCompany=function(){
    //FIXME JC 151212 - Should ask confirmation for deletion
    if ($scope.companyId){
      $http.delete(merohcConfig.BASE_URL + '/company/'+encodeURIComponent($scope.companyId)).success(function(data){
        $scope.deleteItem($scope.company);
      });
    }
  }

  $scope.editCompany=function(){
    $state.go('crm.companies.edit', { companyId: $scope.companyId });
  }

  //get back contact details for the company
  /*$scope.updateContactDetails=function(){
    if ($scope.companyId){
      $http.get('services/v1/ContactDetails?field=target&value='+$scope.companyId).success(function(data){
        $scope.contactDetails = data;
      });
    }
  };

  //get back notes for the company
  $scope.updateNotes=function(){
    if ($scope.companyId){
      $http.get('services/v1/Note?field=target&value='+$scope.companyId).success(function(data){
        $scope.notes = data;
      });
    }
  };*/

  //get back employees for the company
  $scope.updateEmployees=function(){
    if ($scope.companyId){
      $http.get(merohcConfig.BASE_URL + '/company/'+encodeURIComponent($scope.companyId)+'/employee').success(function(data){
        $scope.employees = data;
      });
    }
  };

  //get back invoices for the company
  /*$scope.updateInvoices=function(){
    if ($scope.companyId){
      $http.get('services/v1/Invoice?field=payer&value='+$scope.companyId).success(function(data){
        $scope.invoices = data;
      });
    }
  };*/

  $scope.updateCompany();
  /*$scope.updateContactDetails();
  $scope.updateNotes();*/
  $scope.updateEmployees();
  /*$scope.updateInvoices();*/

}]);

merohcCRMControllers.controller('CompanyCreateController', ['$scope', '$http', '$state', 'merohc-config',function ($scope, $http, $state, merohcConfig) {

  $scope.saveCompany = function(){
    $http({
            method  : 'PUT',
            url     : merohcConfig.BASE_URL + '/company/add',
            data    : $.param($scope.company),  // pass in data as strings
            headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
         })
          .success(function(data) {

            //update company and selectedItem in parent scope
            $scope.addItem(data);
            $scope.$parent.selectedItem=data;
          });
  };

  $scope.cancel = function(){
    $state.go('crm.companies');
  }

}]);

merohcCRMControllers.controller('CompanyEditController', ['$scope', '$http', '$state', 'merohc-config',function ($scope, $http, $state, merohcConfig) {

  $scope.companyId=$state.params.companyId;

  $scope.updateCompany=function(){
    if ($scope.companyId){
      $http.get(merohcConfig.BASE_URL + '/company/'+encodeURIComponent($scope.companyId)).success(function(data){
        $scope.company = data;
        $scope.oldCompany = angular.copy(data);
      });
    }
  };

  $scope.saveCompany = function(){
    $http({
            method  : 'POST',
            url     : merohcConfig.BASE_URL + '/company',
            data    : $.param($scope.company),  // pass in data as strings
            headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
         })
          .success(function(data) {

            //update company and selectedItem in parent scope
            $scope.updateItem($scope.oldCompany, data);
            $scope.$parent.selectedItem=data;

            $state.go('^')
          });
  };

  $scope.cancel = function(){
    $state.go('crm.companies.view', {companyId : $scope.companyId});
  }

  $scope.updateCompany();

}]);

merohcCRMControllers.controller('EmployeeCreateController', ['$scope', '$http', '$state', '$stateParams', 'merohc-config',function ($scope, $http, $state, $stateParams, merohcConfig) {

  $scope.saveEmployee = function(){
    $http({
            method  : 'PUT',
            url     : merohcConfig.BASE_URL + '/company/'+ $stateParams.companyId +'/employee/add',
            data    : $.param($scope.employee),  // pass in data as strings
            headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
         })
          .success(function(data) {
            $state.go('crm.companies.view', { companyId: $stateParams.companyId })
          });
  };

  $scope.cancel = function(){
    $state.go('crm.companies.view', { companyId: $stateParams.companyId })
  }

}]);

merohcCRMControllers.controller('PersonListController', function ($scope, $http, $location, $state) {

  $scope.items = '';

  $scope.filteredItems = $scope.items;

  $scope.searchTerm="";

  $scope.selectedItem=$scope.items[0];

  $scope.targetId="";

  $scope.setTargetId=function(targetId){
    $scope.targetId=targetId;
  }

  $scope.selectItem=function(selectedPerson){
    $scope.selectedItem = selectedPerson;
    $state.go('crm.persons.view', { personId: selectedPerson.id });
  };

  $scope.selectItemById=function(id){
    for (var index in $scope.items) {
      var company = $scope.items[index];
      if (company.id===id){
        $scope.selectedItem=company;
      }
    }
  }

  $scope.isItemSelected=function(selectedCompany){
    return selectedCompany===$scope.selectedItem;
  };

  $scope.filter=function(){
    $scope.filteredItems=[];
    for (var index in $scope.items) {
      var company = $scope.items[index];
      var regexp = new RegExp($scope.searchTerm,"i");
      if (company.Person.firstName.match(regexp)||company.Person.lastName.match(regexp)){
        $scope.filteredItems.push(company);
      }
    }
  };

  $scope.updateItem = function(oldItem, newItem) {
    for (var index in $scope.items) {
      var company = $scope.items[index];
      if (company===oldItem){
        $scope.items[index]=newItem;
      }
    }

    $scope.filter();
  }

  $scope.addItem = function(newItem) {
    $scope.items.push(newItem);
    $scope.filter();
  }

  $scope.deleteItem = function(oldItem) {
    var index = $scope.items.indexOf(oldItem);

    if (index > -1) {
        $scope.items.splice(index, 1);
    }

    $scope.filter();
  }

  $scope.refresh=function(){
    $http.get('services/v1/Person').success(function(data){
      $scope.items = data;
      $scope.filter();
    });
  };

  $scope.refresh();

});

merohcCRMControllers.controller('PersonCreateController', function ($scope, $http, $window) {

  $scope.saveCompany = function(){
    $http({
            method  : 'PUT',
            url     : 'companies/add',
            data    : $.param($scope.company),  // pass in data as strings
            headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
         })
          .success(function(data) {

            //update company and selectedItem in parent scope
            $scope.addItem(data);
            $scope.$parent.selectedItem=data;

            $window.history.back();
          });
  };

  $scope.cancel = function(){
    $window.history.back();
  }

});

merohcCRMControllers.controller('PersonDetailController', function ($scope, $http, $state){

  $scope.personId=$state.params.personId;

  $scope.updatePerson=function(){
      if ($scope.personId){
        $http.get('services/v1/Person/'+$scope.personId).success(function(data){
          $scope.person = data;
        });
      }
    };

  //get back contact details for the person
  $scope.updateContactDetails=function(){
    if ($scope.personId){
      $http.get('services/v1/ContactDetails?field=target&value='+$scope.personId).success(function(data){
        $scope.contactDetails = data;
      });
    }
  };

  //get back notes for the person
  $scope.updateNotes=function(){
    if ($scope.personId){
      $http.get('services/v1/Note?field=target&value='+$scope.personId).success(function(data){
        $scope.notes = data;
      });
    }
  };

  //get back employees for the person
  $scope.updateEmployees=function(){
    if ($scope.personId){
      $http.get('services/v1/Employee?field=company&value='+$scope.personId).success(function(data){
        $scope.employees = data;
      });
    }
  };

  $scope.updatePerson();
  $scope.updateContactDetails();
  $scope.updateNotes();
  $scope.updateEmployees();

});

merohcCRMControllers.controller('NoteController', function ($scope, $http, $state){

  $scope.noteId=$state.params.noteId;

  $scope.updateNote=function(){
    if ($scope.noteId){
      $http.get('services/v1/Note/'+$scope.noteId).success(function(data){
        $scope.note = data;
      });
    }
  };

  $scope.updateNote();
});

merohcCRMControllers.controller('ContactDetailsController', function ($scope, $http, $state){

  $scope.contactDetailsId=$state.params.contactDetailsId;

  $scope.updateContactDetails=function(){
    if ($scope.contactDetailsId){
      $http.get('services/v1/ContactDetails/'+$scope.contactDetailsId).success(function(data){
        $scope.contactDetails = data;
      });
    }
  };

  $scope.updateContactDetails();
});<|endoftext|>