<commit_before>import { Model as ObjectionModel } from 'objection'

import './RelationSynchronizer'
import './RelationValidator'
import './inflect'

const as = require('as-type')

export class Model extends ObjectionModel {
	static descriptiveName = null
	static eager = null
	static eagerFilters = null

	static $$app = null

	static app(app) {
		if(!app.isNil) {
			this.$$app = app
		} else {
			return this.$$app
		}
	}

	$app() {
		return this.constructor.app()
	}

	static findById(id) {
		return this.query().findById(id)
	}

	static findByRouteParameter(value) {
		return this.findById(value)
	}

	static routeBind(name, description) {
		description = description || `${name} Value`

		this.app().routes.bind(name, (value, resolve, reject) => {
			this.findByRouteParameter(value).then(row => {
				if(row.isNil) {
					reject(new NotFoundError(`${this.describe()} Not found`))
					return
				}

				resolve(row)
			})
		}, { swagger: { name, description } })
	}

	static buildRelations() {
		return { }
	}

	static getRelations() {
		if(this.relationMappings.isNil) {
			this.relationMappings = this.buildRelations()
		}

		return super.getRelations()
	}

	static hasOne(modelClass, foreignKey = null, localKey = null) {
		return this._hasOneOrMany(this.HasOneRelation, modelClass, foreignKey, localKey)
	}

	static hasMany(modelClass, foreignKey = null, localKey = null) {
		return this._hasOneOrMany(this.HasManyRelation, modelClass, foreignKey, localKey)
	}

	static _hasOneOrMany(relation, modelClass, foreignKey = null, localKey = null) {
		foreignKey = foreignKey || inflect.foreignKey(this.name)

		if(localKey.isNil) {
			localKey = this.getFullIdColumn()
		} else {
			localKey = `${this.tableName}.${localKey}`
		}

		return {
			relation: relation,
			modelClass: modelClass,
			join: {
				from: `${modelClass.tableName}.${foreignKey}`,
				to: localKey
			}
		}
	}

	static belongsTo(modelClass, foreignKey = null, otherKey = null) {
		foreignKey = foreignKey || inflect.foreignKey(modelClass.name)

		if(otherKey.isNil) {
			otherKey = modelClass.getFullIdColumn()
		} else {
			otherKey = `${modelClass.tableName}.${otherKey}`
		}

		return {
			relation: this.BelongsToOneRelation,
			modelClass: modelClass,
			join: {
				from: `${this.tableName}.${foreignKey}`,
				to: otherKey
			}
		}
	}

	static belongsToMany(modelClass, tableName = null, foreignKey = null, otherKey = null) {
		tableName = tableName || [ this.tableName, modelClass.tableName ].sort().join('_')
		foreignKey = foreignKey || inflect.foreignKey(modelClass.name)
		otherKey = otherKey || inflect.foreignKey(this.name)

		return {
			relation: this.ManyToManyRelation,
			modelClass: modelClass,
			join: {
				from: this.getFullIdColumn(),
				through: {
					from: `${tableName}.${otherKey}`,
					to: `${tableName}.${foreignKey}`
				},
				to: modelClass.getFullIdColumn()
			}
		}
	}

	$sync(relation, ids) {
		return (new RelationSynchronizer(this, relation)).sync(ids)
	}

	$relate(relation, ids) {
		return (new RelationSynchronizer(this, relation)).relate(ids)
	}

	$unrelate(relation, ids) {
		return (new RelationSynchronizer(this, relation)).unrelate(ids)
	}

	$parseDatabaseJson(json) {
		json = super.$parseDatabaseJson(json)
		const schema = this.constructor.jsonSchema

		if(schema.isNil || schema.properties.isNil) {
			return json
		}

		for(const field of Object.keys(schema.properties)) {
			if(typeof json[field] === 'undefined') {
				continue
			}

			const property = schema.properties[field]

			// Boolean values can be converted to JSON as "0"/"1", convert back to boolean
			if(property.type === 'boolean') {
				json[field] = as.boolean(json[field])
			}

			// Number values can be converted to JSON as strings, convert back to numbers
			if(property.type === 'number' || property.type === 'float' || property.type === 'double') {
				json[field] = as.float(json[field])
			} else if(property.type === 'integer') {
				json[field] = as.integer(json[field])
			}
		}

		return json
	}

	$beforeValidate(jsonSchema, json, opt) {
		const properties = jsonSchema.properties || { }

		for(const field of Object.keys(properties)) {
			const value = json[field]

			if(value.isNil) {
				continue
			}

			let fieldType = properties[field].type
			let allowsNull = false

			if(Array.isArray(fieldType) && fieldType.length > 1) {
				allowsNull = fieldType.indexOf('null') >= 0
				fieldType = fieldType[0]
			}

			if(fieldType === 'boolean') {
				json[field] = as.boolean(json[field])
			} else if(fieldType === 'integer') {
				json[field] = as.integer(json[field])
			} else if(fieldType === 'number' || fieldType === 'float' || fieldType === 'double') {
				json[field] = as.float(json[field])
			} else if(fieldType === 'string' && typeof value === 'string' && value.length === 0 && allowsNull) {
				json[field] = null
			}
		}

		return super.$beforeValidate(jsonSchema, json, opt)
	}

	$beforeSave(inserting) {
		return new Promise(resolve => {
			const now = (new Date).toISOString()
			this.updated_at = now

			if(inserting) {
				this.created_at = now
			}

			resolve()
		}).then(() => RelationValidator(this))
	}

	$beforeInsert() {
		return this.$beforeSave(true)
	}

	$beforeUpdate() {
		return this.$beforeSave(false)
	}

	static describe() {
		if(!this.descriptiveName.isNil) {
			return this.descriptiveName
		}

		return inflect.singular(this.tableName)
	}

}
<commit_msg>Fixed type coercion of nulls<commit_after>import { Model as ObjectionModel } from 'objection'

import './RelationSynchronizer'
import './RelationValidator'
import './inflect'

const as = require('as-type')

export class Model extends ObjectionModel {
	static descriptiveName = null
	static eager = null
	static eagerFilters = null

	static $$app = null

	static app(app) {
		if(!app.isNil) {
			this.$$app = app
		} else {
			return this.$$app
		}
	}

	$app() {
		return this.constructor.app()
	}

	static findById(id) {
		return this.query().findById(id)
	}

	static findByRouteParameter(value) {
		return this.findById(value)
	}

	static routeBind(name, description) {
		description = description || `${name} Value`

		this.app().routes.bind(name, (value, resolve, reject) => {
			this.findByRouteParameter(value).then(row => {
				if(row.isNil) {
					reject(new NotFoundError(`${this.describe()} Not found`))
					return
				}

				resolve(row)
			})
		}, { swagger: { name, description } })
	}

	static buildRelations() {
		return { }
	}

	static getRelations() {
		if(this.relationMappings.isNil) {
			this.relationMappings = this.buildRelations()
		}

		return super.getRelations()
	}

	static hasOne(modelClass, foreignKey = null, localKey = null) {
		return this._hasOneOrMany(this.HasOneRelation, modelClass, foreignKey, localKey)
	}

	static hasMany(modelClass, foreignKey = null, localKey = null) {
		return this._hasOneOrMany(this.HasManyRelation, modelClass, foreignKey, localKey)
	}

	static _hasOneOrMany(relation, modelClass, foreignKey = null, localKey = null) {
		foreignKey = foreignKey || inflect.foreignKey(this.name)

		if(localKey.isNil) {
			localKey = this.getFullIdColumn()
		} else {
			localKey = `${this.tableName}.${localKey}`
		}

		return {
			relation: relation,
			modelClass: modelClass,
			join: {
				from: `${modelClass.tableName}.${foreignKey}`,
				to: localKey
			}
		}
	}

	static belongsTo(modelClass, foreignKey = null, otherKey = null) {
		foreignKey = foreignKey || inflect.foreignKey(modelClass.name)

		if(otherKey.isNil) {
			otherKey = modelClass.getFullIdColumn()
		} else {
			otherKey = `${modelClass.tableName}.${otherKey}`
		}

		return {
			relation: this.BelongsToOneRelation,
			modelClass: modelClass,
			join: {
				from: `${this.tableName}.${foreignKey}`,
				to: otherKey
			}
		}
	}

	static belongsToMany(modelClass, tableName = null, foreignKey = null, otherKey = null) {
		tableName = tableName || [ this.tableName, modelClass.tableName ].sort().join('_')
		foreignKey = foreignKey || inflect.foreignKey(modelClass.name)
		otherKey = otherKey || inflect.foreignKey(this.name)

		return {
			relation: this.ManyToManyRelation,
			modelClass: modelClass,
			join: {
				from: this.getFullIdColumn(),
				through: {
					from: `${tableName}.${otherKey}`,
					to: `${tableName}.${foreignKey}`
				},
				to: modelClass.getFullIdColumn()
			}
		}
	}

	$sync(relation, ids) {
		return (new RelationSynchronizer(this, relation)).sync(ids)
	}

	$relate(relation, ids) {
		return (new RelationSynchronizer(this, relation)).relate(ids)
	}

	$unrelate(relation, ids) {
		return (new RelationSynchronizer(this, relation)).unrelate(ids)
	}

	$parseDatabaseJson(json) {
		json = super.$parseDatabaseJson(json)
		const schema = this.constructor.jsonSchema

		if(schema.isNil || schema.properties.isNil) {
			return json
		}

		for(const field of Object.keys(schema.properties)) {
			if(json[field].isNil) {
				continue
			}

			const property = schema.properties[field]

			// Boolean values can be converted to JSON as "0"/"1", convert back to boolean
			if(property.type === 'boolean') {
				json[field] = as.boolean(json[field])
			}

			// Number values can be converted to JSON as strings, convert back to numbers
			if(property.type === 'number' || property.type === 'float' || property.type === 'double') {
				json[field] = as.float(json[field])
			} else if(property.type === 'integer') {
				json[field] = as.integer(json[field])
			}
		}

		return json
	}

	$beforeValidate(jsonSchema, json, opt) {
		const properties = jsonSchema.properties || { }

		for(const field of Object.keys(properties)) {
			const value = json[field]

			if(value.isNil) {
				continue
			}

			let fieldType = properties[field].type
			let allowsNull = false

			if(Array.isArray(fieldType) && fieldType.length > 1) {
				allowsNull = fieldType.indexOf('null') >= 0
				fieldType = fieldType[0]
			}

			if(fieldType === 'boolean') {
				json[field] = as.boolean(json[field])
			} else if(fieldType === 'integer') {
				json[field] = as.integer(json[field])
			} else if(fieldType === 'number' || fieldType === 'float' || fieldType === 'double') {
				json[field] = as.float(json[field])
			} else if(fieldType === 'string' && typeof value === 'string' && value.length === 0 && allowsNull) {
				json[field] = null
			}
		}

		return super.$beforeValidate(jsonSchema, json, opt)
	}

	$beforeSave(inserting) {
		return new Promise(resolve => {
			const now = (new Date).toISOString()
			this.updated_at = now

			if(inserting) {
				this.created_at = now
			}

			resolve()
		}).then(() => RelationValidator(this))
	}

	$beforeInsert() {
		return this.$beforeSave(true)
	}

	$beforeUpdate() {
		return this.$beforeSave(false)
	}

	static describe() {
		if(!this.descriptiveName.isNil) {
			return this.descriptiveName
		}

		return inflect.singular(this.tableName)
	}

}
<|endoftext|>


<commit_before>var RSS_VERSION = "0.1.8";
var React = require('react');

var VersionPrinter = React.createClass({
  render: function() {
    return({RSS_VERSION});
  }
});

module.exports = VersionPrinter;
React.render(<VersionPrinter />, document.getElementById('r_ss_version'));
<commit_msg>bump version printer<commit_after>var RSS_VERSION = "0.1.9";
var React = require('react');

var VersionPrinter = React.createClass({
  render: function() {
    return({RSS_VERSION});
  }
});

module.exports = VersionPrinter;
React.render(<VersionPrinter />, document.getElementById('r_ss_version'));
<|endoftext|>


<commit_before>import path from 'path';

const addTargets = { 'babylon': true, 'default': false };

/**
 * Defines the default runtime targets for testing against published modules.
 *
 * @type {*[]}
 */
const s_DEFAULT_TARGET = [];

if (addTargets.babylon)
{
   s_DEFAULT_TARGET.push({
      name: 'babylon',
      cli: 'tjsdoc-babylon/src/TJSDocBabylonCLI.js', // TODO: This may need to be changed to 'dist' due to require.
      tjsdoc: 'tjsdoc-babylon',
      runtime: 'tjsdoc-babylon',
      publisher: 'tjsdoc-publisher-static-html',
      type: 'ecmascript'
   });
}

/**
 * Defines the development runtime targets for testing against local source code.
 *
 * @type {*[]}
 */
const s_DEV_TARGET = [];

if (addTargets.babylon)
{
   s_DEV_TARGET.push({
      name: 'babylon',
      cli: path.resolve('../tjsdoc-babylon/src/TJSDocBabylonCLI.js'),
      tjsdoc: path.resolve('../tjsdoc-babylon/src/TJSDocBabylon.js'),
      runtime: path.resolve('../tjsdoc-babylon/src/TJSDocBabylon.js'),
      publisher: path.resolve('../tjsdoc-publisher-static-html/src/Publisher.js'),
      type: 'ecmascript'
   });
}

if (addTargets.default)
{
   s_DEV_TARGET.push({
      name: 'default',
      cli: path.resolve('../tjsdoc/src/TJSDocCLI.js'),
      tjsdoc: path.resolve('../tjsdoc/src/TJSDoc.js'),
      runtime: path.resolve('../tjsdoc-babylon/src/TJSDocBabylon.js'),
      publisher: path.resolve('../tjsdoc-publisher-static-html/src/Publisher.js'),
      type: 'ecmascript'
   });
}

/**
 * Defines the runtime targets for each NPM test script.
 *
 * @type {object}
 */
const targets =
{
   'dev-test': s_DEV_TARGET,
   'dev-test-coverage': s_DEV_TARGET,
   'dev-test-npm': s_DEV_TARGET,

   'test': s_DEFAULT_TARGET,
   'test-coverage': s_DEFAULT_TARGET
};

/**
 * Defines local test category overrides.
 *
 * @type {{config: boolean, doc: boolean, html: boolean, html_doc: boolean}}
 */
const category =
{
   cli: false,
   config: false,
   html: false,
   html_doc: false,
   runtime_babylon: false,
   runtime_common: true
};

const emptyDest = true;

const generateMain = true;

export { category, emptyDest, generateMain, targets };
<commit_msg>created 'config_raw_data' test category.<commit_after>import path from 'path';

const addTargets = { 'babylon': true, 'default': false };

/**
 * Defines the default runtime targets for testing against published modules.
 *
 * @type {*[]}
 */
const s_DEFAULT_TARGET = [];

if (addTargets.babylon)
{
   s_DEFAULT_TARGET.push({
      name: 'babylon',
      cli: 'tjsdoc-babylon/src/TJSDocBabylonCLI.js', // TODO: This may need to be changed to 'dist' due to require.
      tjsdoc: 'tjsdoc-babylon',
      runtime: 'tjsdoc-babylon',
      publisher: 'tjsdoc-publisher-static-html',
      type: 'ecmascript'
   });
}

/**
 * Defines the development runtime targets for testing against local source code.
 *
 * @type {*[]}
 */
const s_DEV_TARGET = [];

if (addTargets.babylon)
{
   s_DEV_TARGET.push({
      name: 'babylon',
      cli: path.resolve('../tjsdoc-babylon/src/TJSDocBabylonCLI.js'),
      tjsdoc: path.resolve('../tjsdoc-babylon/src/TJSDocBabylon.js'),
      runtime: path.resolve('../tjsdoc-babylon/src/TJSDocBabylon.js'),
      publisher: path.resolve('../tjsdoc-publisher-static-html/src/Publisher.js'),
      type: 'ecmascript'
   });
}

if (addTargets.default)
{
   s_DEV_TARGET.push({
      name: 'default',
      cli: path.resolve('../tjsdoc/src/TJSDocCLI.js'),
      tjsdoc: path.resolve('../tjsdoc/src/TJSDoc.js'),
      runtime: path.resolve('../tjsdoc-babylon/src/TJSDocBabylon.js'),
      publisher: path.resolve('../tjsdoc-publisher-static-html/src/Publisher.js'),
      type: 'ecmascript'
   });
}

/**
 * Defines the runtime targets for each NPM test script.
 *
 * @type {object}
 */
const targets =
{
   'dev-test': s_DEV_TARGET,
   'dev-test-coverage': s_DEV_TARGET,
   'dev-test-npm': s_DEV_TARGET,

   'test': s_DEFAULT_TARGET,
   'test-coverage': s_DEFAULT_TARGET
};

/**
 * Defines local test category overrides.
 *
 * @type {{config: boolean, doc: boolean, html: boolean, html_doc: boolean}}
 */
const category =
{
   cli: false,
   config: false,
   config_raw_data: false,
   html: false,
   html_doc: false,
   runtime_babylon: false,
   runtime_common: true
};

const emptyDest = true;

const generateMain = true;

export { category, emptyDest, generateMain, targets };
<|endoftext|>


<commit_before>/* -*- mode: espresso; espresso-indent-level: 2; indent-tabs-mode: nil -*- */
/* vim: set softtabstop=2 shiftwidth=2 tabstop=2 expandtab: */

"use strict";

var NeuronNavigator = function()
{
  this.widgetID = this.registerInstance();
  this.registerSource();
};

NeuronNavigator.prototype = {};
$.extend(NeuronNavigator.prototype, new InstanceRegistry());
$.extend(NeuronNavigator.prototype, new SkeletonSource());

/* Implement interfaces */

NeuronNavigator.prototype.getName = function()
{
    return "Neuron Navigator " + this.widgetID;
};

NeuronNavigator.prototype.destroy = function()
{
  this.unregisterInstance();
  this.unregisterSource();
};

NeuronNavigator.prototype.append = function() {};
NeuronNavigator.prototype.clear = function(source_chain) {};
NeuronNavigator.prototype.removeSkeletons = function() {};
NeuronNavigator.prototype.updateModels = function() {};

NeuronNavigator.prototype.getSelectedSkeletons = function() {
  return [];
};

NeuronNavigator.prototype.hasSkeleton = function(skeleton_id) {
  return false;
};

NeuronNavigator.prototype.getSelectedSkeletonModels = function() {
  return {};
};

NeuronNavigator.prototype.highlight = function(skeleton_id)
{
  return;
};

/* Non-interface methods */

NeuronNavigator.prototype.init_ui = function(container)
{
  // Create a navigation bar to see the current path of nodes
  var navigation_bar = document.createElement('div');
  navigation_bar.setAttribute('id', 'navigator_navi_bar' + this.widgetID);
  navigation_bar.setAttribute('class', 'navigator_navi_bar');
  container.appendChild(navigation_bar);

  // Create a containe where all the content of every node will be placed in
  var content = document.createElement('div');
  content.setAttribute('id', 'navigatior_content' + this.widgetID);
  content.setAttribute('class', 'navigator_content');
  container.appendChild(content);

  // Add home node as starting point without any parent
  var home_node = new NeuronNavigatorHomeNode(this.widgetID);
  this.select_node(home_node);
};

NeuronNavigator.prototype.select_node = function(node)
{
  // Set the navigation bar contents
  $('#navigator_navi_bar' + this.widgetID).empty().append(
      node.create_path(this));

  // Set the actual content
  $('#navigatior_content' + this.widgetID).empty().append(
      node.create_content(this));
};

/**
 * A class representing a node in the graph of the navigator.
 */
var NeuronNavigatorNode = function(name)
{
  this.name = name;
};

NeuronNavigatorNode.prototype.link = function(parent_node)
{
  this.parent_node = parent_node;
};

NeuronNavigatorNode.prototype.create_path = function(navigator)
{
  var path_link = document.createElement('a');
  path_link.setAttribute('href', '#');
  path_link.setAttribute('class', 'navigator_navi_bar_element');
  path_link.innerHTML = this.name;
  $(path_link).click($.proxy(function() {
    navigator.select_node(this);
  }, this));

  if (this.parent_node) {
    var path_elements = this.parent_node.create_path(navigator);
    path_elements.push(document.createTextNode(" > "));
    path_elements.push(path_link);
    return path_elements;
  } else {
    return [path_link];
  }
};

NeuronNavigatorNode.prototype.create_content = function(navigator)
{
  return undefined;
};

NeuronNavigatorNode.prototype.create_path_link = function(text)
{
  var option = document.createElement('a');
  option.setAttribute('href', '#');
  option.setAttribute('class', 'navigator_content_option');
  // Add text to option, if passed
  if (text)
  {
    option.innerHTML = text;
  }

  return option;
};

/**
 * The home node of the navigator. It links to annotation
 * and users nodes.
 */
var NeuronNavigatorHomeNode = function()
{
  // A home node acts as the root node and has therefore no parent.
  this.link(null);
};

NeuronNavigatorHomeNode.prototype = {};
$.extend(NeuronNavigatorHomeNode.prototype, new NeuronNavigatorNode("Home"));

NeuronNavigatorHomeNode.prototype.create_content = function(navigator)
{
  var content = document.createElement('div');

  var annotations_link = this.create_path_link("Annotations");
  content.appendChild(annotations_link);
  $(annotations_link).click($.proxy(function() {
      var annotations_node = new NeuronNavigatorAnnotationsNode();
      annotations_node.link(this);
      navigator.select_node(annotations_node);
  }, this));

  var users_link = this.create_path_link("Users");
  content.appendChild(users_link);
  $(users_link).click($.proxy(function() {
      var users_node = new NeuronNavigatorUsersNode();
      users_node.link(this);
      navigator.select_node(users_node);
  }, this));

  return content;
};

/**
 * The annotations node of the navigator. It links to annotations.
 */
var NeuronNavigatorAnnotationsNode = function() {};

NeuronNavigatorAnnotationsNode.prototype = {};
$.extend(NeuronNavigatorAnnotationsNode.prototype,
    new NeuronNavigatorNode("Annotations"));

NeuronNavigatorAnnotationsNode.prototype.create_content = function(navigator)
{
  var content = document.createElement('div');
  content.setAttribute('id', 'navigator_annotations_content' +
      navigator.widgetID);
  content.innerHTML = "Please wait while the available annotatios are requested";

  // Make node easily accessible in created methods
  var self = this;

  // Get the list of currently available annotations
  requestQueue.register(django_url + project.id + '/annotations/list',
      'GET', {}, function(status, data, text) {
        var e = $.parseJSON(data);
        if (status != 200) {
          alert("The server returned an unexpected status (" +
            status + ") with error message:\n" + text);
        } else {
          // Create a list of annotation links
          var annotations = e.map(function(a) {
            var annotations_link = self.create_path_link(a);
            $(annotations_link).click(function() {
                var annotations_node = new NeuronNavigatorFilterNode(a);
                annotations_node.link(self);
                navigator.select_node(annotations_node);
            });
            return annotations_link;
          });
          // Add all annotation links
          $('#navigator_annotations_content' + navigator.widgetID).empty().
            append(annotations);
        }
      });

  return content;
};

/**
 * The users node of the navigator. It links to users.
 */
var NeuronNavigatorUsersNode = function() {};

NeuronNavigatorUsersNode.prototype = {};
$.extend(NeuronNavigatorUsersNode.prototype,
    new NeuronNavigatorNode("Users"));

NeuronNavigatorUsersNode.prototype.create_content = function(navigator)
{
  var content = document.createElement('div');
  content.setAttribute('id', 'navigator_users_content' +
      navigator.widgetID);
  content.innerHTML = "Please wait while the existing users are requested";

  // Make node easily accessible in created methods
  var self = this;

  // Get the list of currently available annotations
  requestQueue.register(django_url + 'user-list',
      'GET', {}, function(status, data, text) {
        var e = $.parseJSON(data);
        if (status != 200) {
          alert("The server returned an unexpected status (" +
            status + ") with error message:\n" + text);
        } else {
          // Create a list of user links
          var users = e.map(function(u) {
            var user_link = self.create_path_link(u.full_name +
                " (" + u.login + ")");
            $(user_link).click(function() {
                var filter_node = new NeuronNavigatorFilterNode(undefined, u);
                filter_node.link(self);
                navigator.select_node(filter_node);
            });
            return user_link;
          });
          // Add all annotation links
          $('#navigator_users_content' + navigator.widgetID).empty().
            append(users);
        }
      });

  return content;
};

/**
 * The filter node of the navigator. It filters output based on a
 * set of annotations and/or users. The content it creates lists
 * user, neuron, annotation and co-annotation links.
 */
var NeuronNavigatorFilterNode = function(included_annotation,
    included_user)
{
  this.included_annotation = included_annotation;
  this.included_user = included_user;

  var filter_names = []

  if (included_annotation) {
    filter_names.push("A: " + included_annotation);
  }

  if (included_user) {
    filter_names.push("U: " + included_user.login);
  }

  if (filter_names.length > 0) {
    this.name = filter_names.join(', ');
  }
};

NeuronNavigatorFilterNode.prototype = {};
$.extend(NeuronNavigatorFilterNode.prototype,
    new NeuronNavigatorNode("Empty Filter"));

NeuronNavigatorFilterNode.prototype.create_content = function(navigator)
{
  var content = document.createElement('div');
  content.innerHTML = "Filtered content";

  return content;
};
<commit_msg>Neuron navigator: keep navigator instance in nodes and separate filters<commit_after>/* -*- mode: espresso; espresso-indent-level: 2; indent-tabs-mode: nil -*- */
/* vim: set softtabstop=2 shiftwidth=2 tabstop=2 expandtab: */

"use strict";

var NeuronNavigator = function()
{
  this.widgetID = this.registerInstance();
  this.registerSource();
};

NeuronNavigator.prototype = {};
$.extend(NeuronNavigator.prototype, new InstanceRegistry());
$.extend(NeuronNavigator.prototype, new SkeletonSource());

/* Implement interfaces */

NeuronNavigator.prototype.getName = function()
{
    return "Neuron Navigator " + this.widgetID;
};

NeuronNavigator.prototype.destroy = function()
{
  this.unregisterInstance();
  this.unregisterSource();
};

NeuronNavigator.prototype.append = function() {};
NeuronNavigator.prototype.clear = function(source_chain) {};
NeuronNavigator.prototype.removeSkeletons = function() {};
NeuronNavigator.prototype.updateModels = function() {};

NeuronNavigator.prototype.getSelectedSkeletons = function() {
  return [];
};

NeuronNavigator.prototype.hasSkeleton = function(skeleton_id) {
  return false;
};

NeuronNavigator.prototype.getSelectedSkeletonModels = function() {
  return {};
};

NeuronNavigator.prototype.highlight = function(skeleton_id)
{
  return;
};

/* Non-interface methods */

NeuronNavigator.prototype.init_ui = function(container)
{
  // Create a navigation bar to see the current path of nodes
  var navigation_bar = document.createElement('div');
  navigation_bar.setAttribute('id', 'navigator_navi_bar' + this.widgetID);
  navigation_bar.setAttribute('class', 'navigator_navi_bar');
  container.appendChild(navigation_bar);

  // Create a containe where all the content of every node will be placed in
  var content = document.createElement('div');
  content.setAttribute('id', 'navigatior_content' + this.widgetID);
  content.setAttribute('class', 'navigator_content');
  container.appendChild(content);

  // Add home node as starting point without any parent
  var home_node = new NeuronNavigatorHomeNode(this.widgetID);
  home_node.link(this, null);
  this.select_node(home_node);
};

NeuronNavigator.prototype.select_node = function(node)
{
  // Set the navigation bar contents
  $('#navigator_navi_bar' + this.widgetID).empty().append(
      node.create_path(this));

  // Set the actual content
  $('#navigatior_content' + this.widgetID).empty().append(
      node.create_content(this));
};

/**
 * A class representing a node in the graph of the navigator.
 */
var NeuronNavigatorNode = function(name)
{
  this.name = name;
  this.navigator = null;
};

NeuronNavigatorNode.prototype.link = function(navigator, parent_node)
{
  this.navigator = navigator;
  this.parent_node = parent_node;
};

NeuronNavigatorNode.prototype.create_path = function()
{
  var path_link = document.createElement('a');
  path_link.setAttribute('href', '#');
  path_link.setAttribute('class', 'navigator_navi_bar_element');
  path_link.innerHTML = this.name;
  $(path_link).click($.proxy(function() {
    this.navigator.select_node(this);
  }, this));

  if (this.parent_node) {
    var path_elements = this.parent_node.create_path();
    path_elements.push(document.createTextNode(" > "));
    path_elements.push(path_link);
    return path_elements;
  } else {
    return [path_link];
  }
};

NeuronNavigatorNode.prototype.create_content = function()
{
  return undefined;
};

NeuronNavigatorNode.prototype.create_annotations_link = function()
{
  var annotations_link = this.create_path_link("Annotations");
  $(annotations_link).click($.proxy(function() {
      var annotations_node = new NeuronNavigatorAnnotationsNode();
      annotations_node.link(this.navigator, this);
      this.navigator.select_node(annotations_node);
  }, this));

  return annotations_link;
};

NeuronNavigatorNode.prototype.create_users_link = function()
{
  var users_link = this.create_path_link("Users");
  $(users_link).click($.proxy(function() {
      var users_node = new NeuronNavigatorUsersNode();
      users_node.link(this.navigator, this);
      this.navigator.select_node(users_node);
  }, this));

  return users_link;
};

NeuronNavigatorNode.prototype.create_neurons_link = function()
{
  var neurons_link = this.create_path_link("Neurons");
  $(neurons_link).click($.proxy(function() {
      // TODO
  }, this));

  return neurons_link
};

NeuronNavigatorNode.prototype.create_path_link = function(text)
{
  var option = document.createElement('a');
  option.setAttribute('href', '#');
  option.setAttribute('class', 'navigator_content_option');
  // Add text to option, if passed
  if (text)
  {
    option.innerHTML = text;
  }

  return option;
};

/**
 * The home node of the navigator. It links to annotation
 * and users nodes.
 */
var NeuronNavigatorHomeNode = function()
{
  // A home node acts as the root node and has therefore no parent.
  this.link(null);
};

NeuronNavigatorHomeNode.prototype = {};
$.extend(NeuronNavigatorHomeNode.prototype, new NeuronNavigatorNode("Home"));

NeuronNavigatorHomeNode.prototype.create_content = function()
{
  var content = document.createElement('div');

  var annotations_link = this.create_annotations_link();
  var users_link = this.create_users_link();
  content.appendChild(annotations_link);
  content.appendChild(users_link);

  return content;
};

/**
 * The annotations node of the navigator. It links to annotations.
 */
var NeuronNavigatorAnnotationsNode = function() {};

NeuronNavigatorAnnotationsNode.prototype = {};
$.extend(NeuronNavigatorAnnotationsNode.prototype,
    new NeuronNavigatorNode("Annotations"));

NeuronNavigatorAnnotationsNode.prototype.create_content = function()
{
  var content = document.createElement('div');
  content.setAttribute('id', 'navigator_annotations_content' +
      this.navigator.widgetID);
  content.innerHTML = "Please wait while the available annotatios are requested";

  // Make node easily accessible in created methods
  var self = this;

  // Get the list of currently available annotations
  requestQueue.register(django_url + project.id + '/annotations/list',
      'GET', {}, function(status, data, text) {
        var e = $.parseJSON(data);
        if (status != 200) {
          alert("The server returned an unexpected status (" +
            status + ") with error message:\n" + text);
        } else {
          // Create a list of annotation links
          var annotations = e.map(function(a) {
            var annotations_link = self.create_path_link(a);
            $(annotations_link).click(function() {
                var annotations_node = new NeuronNavigatorAnnotationFilterNode(a);
                annotations_node.link(self.navigator, self);
                self.navigator.select_node(annotations_node);
            });
            return annotations_link;
          });
          // Add all annotation links
          $('#navigator_annotations_content' + self.navigator.widgetID).empty().
            append(annotations);
        }
      });

  return content;
};

/**
 * The users node of the navigator. It links to users.
 */
var NeuronNavigatorUsersNode = function() {};

NeuronNavigatorUsersNode.prototype = {};
$.extend(NeuronNavigatorUsersNode.prototype,
    new NeuronNavigatorNode("Users"));

NeuronNavigatorUsersNode.prototype.create_content = function()
{
  var content = document.createElement('div');
  content.setAttribute('id', 'navigator_users_content' +
      this.navigator.widgetID);
  content.innerHTML = "Please wait while the existing users are requested";

  // Make node easily accessible in created methods
  var self = this;

  // Get the list of currently available annotations
  requestQueue.register(django_url + 'user-list',
      'GET', {}, function(status, data, text) {
        var e = $.parseJSON(data);
        if (status != 200) {
          alert("The server returned an unexpected status (" +
            status + ") with error message:\n" + text);
        } else {
          // Create a list of user links
          var users = e.map(function(u) {
            var user_link = self.create_path_link(u.full_name +
                " (" + u.login + ")");
            $(user_link).click(function() {
                var filter_node = new NeuronNavigatorUserFilterNode(undefined, u);
                filter_node.link(self.navigator, self);
                self.navigator.select_node(filter_node);
            });
            return user_link;
          });
          // Add all annotation links
          $('#navigator_users_content' + self.navigator.widgetID).empty().
            append(users);
        }
      });

  return content;
};

/**
 * The annotation filter node of the navigator filters output based on the
 * existence of an annotations. The content it creates lists user, neuron,
 * annotation and co-annotation links.
 */
var NeuronNavigatorAnnotationFilterNode = function(included_annotation)
{
  this.included_annotation = included_annotation;
  this.name = "A: " + included_annotation;
};

NeuronNavigatorAnnotationFilterNode.prototype = {};
$.extend(NeuronNavigatorAnnotationFilterNode.prototype,
    new NeuronNavigatorNode("Empty Annotation Filter"));

NeuronNavigatorAnnotationFilterNode.prototype.create_content = function()
{
  /* An annotation filter node, will display options to add ad user filter,
   * another annotation filter or to select a neuron.
   */
  var content = document.createElement('div');

  var annotations_link = this.create_annotations_link();
  var users_link = this.create_users_link();
  var neurons_link = this.create_neurons_link();
  content.appendChild(annotations_link);
  content.appendChild(users_link);
  content.appendChild(neurons_link);

  return content;
};

/**
 * The user filter node of the navigator filters output based on the
 * ownership by a particular user. The content it creates lists user, neuron,
 * annotation and co-annotation links.
 */
var NeuronNavigatorUserFilterNode = function(included_user)
{
  this.included_user = included_user;
  this.name = "U: " + included_user;
};

NeuronNavigatorUserFilterNode.prototype = {};
$.extend(NeuronNavigatorUserFilterNode.prototype,
    new NeuronNavigatorNode("Empty User Filter"));

NeuronNavigatorUserFilterNode.prototype.create_content = function()
{
  var content = document.createElement('div');

  var annotations_link = this.create_annotations_link();
  var users_link = this.create_users_link();
  var neurons_link = this.create_neurons_link();
  content.appendChild(annotations_link);
  content.appendChild(users_link);
  content.appendChild(neurons_link);

  return content;
};
<|endoftext|>


<commit_before>import {
  call,
  fork,
  join,
  take,
  race,
  cancel,
  put,
  all,
  cancelled,
  getContext,
  setContext,
} from 'redux-saga/effects';

import {
  createSuccessAction,
  createErrorAction,
  createAbortAction,
  getActionPayload,
  isRequestAction,
} from './actions';
import {
  REQUESTS_CONFIG,
  INCORRECT_PAYLOAD_ERROR,
  RUN_BY_INTERCEPTOR,
  INTERCEPTORS,
} from './constants';

/* eslint-disable */
let delay =
  require('redux-saga').delay || require('@redux-saga/delay-p').default;
/* eslint-enable */

export const voidCallback = () => {};

export const defaultConfig = {
  driver: null,
  onRequest: null,
  onSuccess: null,
  onError: null,
  onAbort: null,
};

export function createRequestInstance(config) {
  return setContext({
    [REQUESTS_CONFIG]: { ...defaultConfig, ...config },
  });
}

export function getRequestsConfig() {
  return getContext(REQUESTS_CONFIG);
}

export function* getRequestInstance(driverType = null) {
  const config = yield getRequestsConfig();
  const driver = driverType
    ? config.driver[driverType]
    : config.driver.default || config.driver;
  return driver.requestInstance;
}

const getDriver = (requestsConfig, action) =>
  action.meta && action.meta.driver
    ? requestsConfig.driver[action.meta.driver]
    : requestsConfig.driver.default || requestsConfig.driver;

export function* sendRequest(
  action,
  {
    dispatchRequestAction = false,
    silent = false,
    runOnRequest = null,
    runOnSuccess = null,
    runOnError = null,
    runOnAbort = null,
  } = {},
) {
  if (!isRequestAction(action)) {
    throw new Error(INCORRECT_PAYLOAD_ERROR);
  }
  const runByInterceptor = yield getContext(RUN_BY_INTERCEPTOR);
  const requestsConfig = yield getRequestsConfig();

  if (dispatchRequestAction && !silent) {
    action = { ...action, meta: { ...action.meta, runByWatcher: false } };
    yield put(action);
  }

  const driver = yield call(getDriver, requestsConfig, action);
  const actionPayload = getActionPayload(action);

  if (
    requestsConfig.onRequest &&
    (runOnRequest !== null
      ? runOnRequest
      : runByInterceptor !== INTERCEPTORS.ON_REQUEST)
  ) {
    yield setContext({ [RUN_BY_INTERCEPTOR]: INTERCEPTORS.ON_REQUEST });

    actionPayload.request = yield call(
      requestsConfig.onRequest,
      actionPayload.request,
      action,
    );
  }

  const abortSource = driver.getAbortSource();

  try {
    let response;
    let responseError;

    try {
      if (!Array.isArray(actionPayload.request)) {
        response = yield call(
          [driver, 'sendRequest'],
          actionPayload.request,
          abortSource,
          action,
        );
      } else {
        response = yield all(
          actionPayload.request.map(requestItem =>
            call([driver, 'sendRequest'], requestItem, abortSource, action),
          ),
        );
      }
    } catch (e) {
      responseError = e;
    }

    if (responseError) {
      if (
        requestsConfig.onError &&
        (runOnError !== null
          ? runOnError
          : runByInterceptor !== INTERCEPTORS.ON_ERROR)
      ) {
        yield setContext({ [RUN_BY_INTERCEPTOR]: INTERCEPTORS.ON_ERROR });

        const { response: onErrorResponse, error: onErrorError } = yield call(
          requestsConfig.onError,
          responseError,
          action,
        );

        if (onErrorResponse) {
          response = onErrorResponse;
        } else {
          responseError = onErrorError;
        }
      }

      if (!response) {
        const errorPayload = yield call(driver.getErrorPayload, responseError);

        if (!silent) {
          yield put(createErrorAction(action, errorPayload));
        }

        return { error: responseError };
      }
    }

    if (
      requestsConfig.onSuccess &&
      (runOnSuccess !== null
        ? runOnSuccess
        : runByInterceptor !== INTERCEPTORS.ON_SUCCESS &&
          runByInterceptor !== INTERCEPTORS.ON_ERROR)
    ) {
      yield setContext({ [RUN_BY_INTERCEPTOR]: INTERCEPTORS.ON_SUCCESS });
      response = yield call(requestsConfig.onSuccess, response, action);
    }

    const successPayload = yield call(
      driver.getSuccessPayload,
      response,
      actionPayload.request,
    );

    if (!silent) {
      yield put(createSuccessAction(action, successPayload));
    }

    return { response };
  } finally {
    if (yield cancelled()) {
      yield call([driver, 'abortRequest'], abortSource);

      if (
        requestsConfig.onAbort &&
        (runOnAbort !== null
          ? runOnAbort
          : runByInterceptor !== INTERCEPTORS.ON_ABORT)
      ) {
        yield setContext({ [RUN_BY_INTERCEPTOR]: INTERCEPTORS.ON_ABORT });
        yield call(requestsConfig.onAbort, action);
      }

      if (!silent) {
        yield put(createAbortAction(action));
      }
    }
  }
}

const isGetRequest = request =>
  !request.method || request.method.toLowerCase() === 'get';

const watchRequestsDefaultConfig = {
  takeLatest: action => {
    const { request } = getActionPayload(action);

    return Array.isArray(request)
      ? request.every(isGetRequest)
      : isGetRequest(request);
  },
  abortOn: null,
  getLastActionKey: action => action.type,
};

export function* cancelSendRequestOnAction(abortOn, task) {
  const { abortingAction } = yield race({
    abortingAction: take(abortOn),
    taskFinished: join(task),
    timeout: call(delay, 10000), // taskFinished doesnt work for aborted tasks
  });

  if (abortingAction) {
    yield cancel(task);
  }
}

const isWatchable = a =>
  isRequestAction(a) && (!a.meta || a.meta.runByWatcher !== false);

export function* watchRequests(commonConfig = {}) {
  const lastTasks = {};
  const config = { ...watchRequestsDefaultConfig, ...commonConfig };

  while (true) {
    const action = yield take(isWatchable);
    const lastActionKey = config.getLastActionKey(action);
    const takeLatest =
      action.meta && action.meta.takeLatest !== undefined
        ? action.meta.takeLatest
        : typeof config.takeLatest === 'function'
        ? config.takeLatest(action)
        : config.takeLatest;

    if (takeLatest) {
      const activeTask = lastTasks[lastActionKey];

      if (activeTask) {
        yield cancel(activeTask);
      }
    }

    const newTask = yield fork(sendRequest, action);

    if (takeLatest) {
      lastTasks[lastActionKey] = newTask;
    }

    const abortOn =
      action.meta && action.meta.abortOn ? action.meta.abortOn : config.abortOn;

    if (abortOn) {
      yield fork(cancelSendRequestOnAction, abortOn, newTask);
    }
  }
}
<commit_msg>Changed delay import var to const<commit_after>import {
  call,
  fork,
  join,
  take,
  race,
  cancel,
  put,
  all,
  cancelled,
  getContext,
  setContext,
} from 'redux-saga/effects';

import {
  createSuccessAction,
  createErrorAction,
  createAbortAction,
  getActionPayload,
  isRequestAction,
} from './actions';
import {
  REQUESTS_CONFIG,
  INCORRECT_PAYLOAD_ERROR,
  RUN_BY_INTERCEPTOR,
  INTERCEPTORS,
} from './constants';

/* eslint-disable */
const delay =
  require('redux-saga').delay || require('@redux-saga/delay-p').default;
/* eslint-enable */

export const voidCallback = () => {};

export const defaultConfig = {
  driver: null,
  onRequest: null,
  onSuccess: null,
  onError: null,
  onAbort: null,
};

export function createRequestInstance(config) {
  return setContext({
    [REQUESTS_CONFIG]: { ...defaultConfig, ...config },
  });
}

export function getRequestsConfig() {
  return getContext(REQUESTS_CONFIG);
}

export function* getRequestInstance(driverType = null) {
  const config = yield getRequestsConfig();
  const driver = driverType
    ? config.driver[driverType]
    : config.driver.default || config.driver;
  return driver.requestInstance;
}

const getDriver = (requestsConfig, action) =>
  action.meta && action.meta.driver
    ? requestsConfig.driver[action.meta.driver]
    : requestsConfig.driver.default || requestsConfig.driver;

export function* sendRequest(
  action,
  {
    dispatchRequestAction = false,
    silent = false,
    runOnRequest = null,
    runOnSuccess = null,
    runOnError = null,
    runOnAbort = null,
  } = {},
) {
  if (!isRequestAction(action)) {
    throw new Error(INCORRECT_PAYLOAD_ERROR);
  }
  const runByInterceptor = yield getContext(RUN_BY_INTERCEPTOR);
  const requestsConfig = yield getRequestsConfig();

  if (dispatchRequestAction && !silent) {
    action = { ...action, meta: { ...action.meta, runByWatcher: false } };
    yield put(action);
  }

  const driver = yield call(getDriver, requestsConfig, action);
  const actionPayload = getActionPayload(action);

  if (
    requestsConfig.onRequest &&
    (runOnRequest !== null
      ? runOnRequest
      : runByInterceptor !== INTERCEPTORS.ON_REQUEST)
  ) {
    yield setContext({ [RUN_BY_INTERCEPTOR]: INTERCEPTORS.ON_REQUEST });

    actionPayload.request = yield call(
      requestsConfig.onRequest,
      actionPayload.request,
      action,
    );
  }

  const abortSource = driver.getAbortSource();

  try {
    let response;
    let responseError;

    try {
      if (!Array.isArray(actionPayload.request)) {
        response = yield call(
          [driver, 'sendRequest'],
          actionPayload.request,
          abortSource,
          action,
        );
      } else {
        response = yield all(
          actionPayload.request.map(requestItem =>
            call([driver, 'sendRequest'], requestItem, abortSource, action),
          ),
        );
      }
    } catch (e) {
      responseError = e;
    }

    if (responseError) {
      if (
        requestsConfig.onError &&
        (runOnError !== null
          ? runOnError
          : runByInterceptor !== INTERCEPTORS.ON_ERROR)
      ) {
        yield setContext({ [RUN_BY_INTERCEPTOR]: INTERCEPTORS.ON_ERROR });

        const { response: onErrorResponse, error: onErrorError } = yield call(
          requestsConfig.onError,
          responseError,
          action,
        );

        if (onErrorResponse) {
          response = onErrorResponse;
        } else {
          responseError = onErrorError;
        }
      }

      if (!response) {
        const errorPayload = yield call(driver.getErrorPayload, responseError);

        if (!silent) {
          yield put(createErrorAction(action, errorPayload));
        }

        return { error: responseError };
      }
    }

    if (
      requestsConfig.onSuccess &&
      (runOnSuccess !== null
        ? runOnSuccess
        : runByInterceptor !== INTERCEPTORS.ON_SUCCESS &&
          runByInterceptor !== INTERCEPTORS.ON_ERROR)
    ) {
      yield setContext({ [RUN_BY_INTERCEPTOR]: INTERCEPTORS.ON_SUCCESS });
      response = yield call(requestsConfig.onSuccess, response, action);
    }

    const successPayload = yield call(
      driver.getSuccessPayload,
      response,
      actionPayload.request,
    );

    if (!silent) {
      yield put(createSuccessAction(action, successPayload));
    }

    return { response };
  } finally {
    if (yield cancelled()) {
      yield call([driver, 'abortRequest'], abortSource);

      if (
        requestsConfig.onAbort &&
        (runOnAbort !== null
          ? runOnAbort
          : runByInterceptor !== INTERCEPTORS.ON_ABORT)
      ) {
        yield setContext({ [RUN_BY_INTERCEPTOR]: INTERCEPTORS.ON_ABORT });
        yield call(requestsConfig.onAbort, action);
      }

      if (!silent) {
        yield put(createAbortAction(action));
      }
    }
  }
}

const isGetRequest = request =>
  !request.method || request.method.toLowerCase() === 'get';

const watchRequestsDefaultConfig = {
  takeLatest: action => {
    const { request } = getActionPayload(action);

    return Array.isArray(request)
      ? request.every(isGetRequest)
      : isGetRequest(request);
  },
  abortOn: null,
  getLastActionKey: action => action.type,
};

export function* cancelSendRequestOnAction(abortOn, task) {
  const { abortingAction } = yield race({
    abortingAction: take(abortOn),
    taskFinished: join(task),
    timeout: call(delay, 10000), // taskFinished doesnt work for aborted tasks
  });

  if (abortingAction) {
    yield cancel(task);
  }
}

const isWatchable = a =>
  isRequestAction(a) && (!a.meta || a.meta.runByWatcher !== false);

export function* watchRequests(commonConfig = {}) {
  const lastTasks = {};
  const config = { ...watchRequestsDefaultConfig, ...commonConfig };

  while (true) {
    const action = yield take(isWatchable);
    const lastActionKey = config.getLastActionKey(action);
    const takeLatest =
      action.meta && action.meta.takeLatest !== undefined
        ? action.meta.takeLatest
        : typeof config.takeLatest === 'function'
        ? config.takeLatest(action)
        : config.takeLatest;

    if (takeLatest) {
      const activeTask = lastTasks[lastActionKey];

      if (activeTask) {
        yield cancel(activeTask);
      }
    }

    const newTask = yield fork(sendRequest, action);

    if (takeLatest) {
      lastTasks[lastActionKey] = newTask;
    }

    const abortOn =
      action.meta && action.meta.abortOn ? action.meta.abortOn : config.abortOn;

    if (abortOn) {
      yield fork(cancelSendRequestOnAction, abortOn, newTask);
    }
  }
}
<|endoftext|>


<commit_before>'use strict';

var expect = require('chai').expect;
var utils = require('../public/javascripts/utils.js');

describe('utils', function() {

  describe('#humanFileSize', function() {
    it('check 1000 bytes', function() {
      expect(utils.humanFileSize(1000, true)).to.equal("1.0 kB");
    });

    it('check 1024 bytes', function() {
      expect(utils.humanFileSize(1024, false)).to.equal("1.0 KiB");
    });

  });

});
<commit_msg>Fix Lint Errors<commit_after>'use strict';

var expect = require('chai').expect;
var utils = require('../public/javascripts/utils.js');

describe('utils', function() {

  describe('#humanFileSize', function() {
    it('check 1000 bytes', function() {
      expect(utils.humanFileSize(1000, true)).to.equal('1.0 kB');
    });

    it('check 1024 bytes', function() {
      expect(utils.humanFileSize(1024, false)).to.equal('1.0 KiB');
    });

  });

});
<|endoftext|>


<commit_before>import {expect} from 'chai';
import models from '../server/models';
import * as utils from '../test/utils';

const {
  Transaction,
  Group,
  User
} = models;

describe('Group model', () => {

  let group = {};

  const groupData = {
    slug: 'tipbox',
    name: 'tipbox',
    currency: 'USD',
    tags: ['#brusselstogether']
  };

  const users = [{
    username: 'xdamman',
    email: 'xdamman@opencollective.com'
  },{
    username: 'piamancini',
    email: 'pia@opencollective.com'
  }];

  const transactions = [{
    createdAt: new Date('2016-06-14'),
    amount: -10,
    netAmountInGroupCurrency: -1000,
    currency: 'USD',
    type: 'expense',
    description: 'pizza',
    tags: ['food']
  },{
    createdAt: new Date('2016-07-14'),
    amount: -150,
    netAmountInGroupCurrency: -15000,
    currency: 'USD',
    type: 'expense',
    description: 'stickers',
    tags: ['marketing']
  },{
    createdAt: new Date('2016-06-15'),
    amount: 250,
    netAmountInGroupCurrency: 25000,
    currency: 'USD',
    type: 'donation',
    UserId: 1
  },{
    createdAt: new Date('2016-07-16'),
    amount: 500,
    netAmountInGroupCurrency: 50000,
    currency: 'USD',
    type: 'donation',
    UserId: 2
  }];

  before(() => utils.resetTestDB());

  before(() => Group.create(groupData)
    .tap(g => group = g)
    .tap(() => User.createMany(users))
    .tap(() => Transaction.createMany(transactions, { GroupId: group.id })));

  it('returns a default logo if no logo', () => {
    expect(group.logo).to.equal('https://opencollective.com/static/images/1px.png');
  });

  it('computes the balance ', () =>
    group.getBalance().then(balance => {
      let sum = 0;
      transactions.map(t => sum += t.netAmountInGroupCurrency);
      expect(balance).to.equal(sum);
    }));

  it('computes the balance until a certain month', (done) => {
    const until = new Date('2016-07-01');
    group.getBalance(until).then(balance => {
      let sum = 0;
      transactions.map(t => {
        if (t.createdAt < until)
          sum += t.netAmountInGroupCurrency
      });
      expect(balance).to.equal(sum);
      done();
    })
  });

  it('computes the number of backers', (done) => {
    group.getBackersCount()
      .then(count => {
        expect(count).to.equal(users.length);
        done();
      })
  });

  it('computes the number of backers until a certain month', (done) => {
    const until = new Date('2016-07-01');
    group.getBackersCount(until).then(count => {
      const backers = {};
      transactions.map(t => {
        if (t.amount > 0 && t.createdAt < until)
          backers[t.UserId] = t.amount;
      });
      expect(count).to.equal(Object.keys(backers).length);
      done();
    })
  });

  it('gets all the expenses', (done) => {
    let totalExpenses = 0;
    transactions.map(t => {
      if (t.netAmountInGroupCurrency < 0)
        totalExpenses++;
    });

    group.getExpenses()
      .then(expenses => {
        expect(expenses.length).to.equal(totalExpenses);
        done();
      })
      .catch(e => {
        console.error('error', e, e.stack);
      });
  });

  it('gets all the expenses in a given month', (done) => {
    const startDate = new Date('2016-06-01');
    const endDate = new Date('2016-07-01');

    let totalExpenses = 0;

    transactions.map(t => {
      if (t.netAmountInGroupCurrency < 0 && t.createdAt > startDate && t.createdAt < endDate)
        totalExpenses++;
    });

    group.getExpenses(null, startDate, endDate)
      .then(expenses => {
        expect(expenses.length).to.equal(totalExpenses);
        done();
      })
      .catch(e => {
        console.error('error', e, e.stack);
      });
  });

  it('get the related groups', (done) => {
    Group.createMany(utils.data('relatedGroups'))
    .then(() => group.getRelatedGroups(3, 0))
    .then(relatedGroups => {
      expect(relatedGroups).to.have.length(3);
      expect(relatedGroups[0].settings.style.hero).to.have.property('cover');
      done();
    })
  });
});
<commit_msg>fix tests<commit_after>import {expect} from 'chai';
import models from '../server/models';
import * as utils from '../test/utils';

const {
  Transaction,
  Group,
  User
} = models;

describe('Group model', () => {

  let group = {};

  const groupData = {
    slug: 'tipbox',
    name: 'tipbox',
    currency: 'USD',
    tags: ['#brusselstogether']
  };

  const users = [{
    username: 'xdamman',
    email: 'xdamman@opencollective.com'
  },{
    username: 'piamancini',
    email: 'pia@opencollective.com'
  }];

  const transactions = [{
    createdAt: new Date('2016-06-14'),
    amount: -10,
    netAmountInGroupCurrency: -1000,
    currency: 'USD',
    type: 'expense',
    description: 'pizza',
    tags: ['food']
  },{
    createdAt: new Date('2016-07-14'),
    amount: -150,
    netAmountInGroupCurrency: -15000,
    currency: 'USD',
    type: 'expense',
    description: 'stickers',
    tags: ['marketing']
  },{
    createdAt: new Date('2016-06-15'),
    amount: 250,
    netAmountInGroupCurrency: 25000,
    currency: 'USD',
    type: 'donation',
    UserId: 1
  },{
    createdAt: new Date('2016-07-16'),
    amount: 500,
    netAmountInGroupCurrency: 50000,
    currency: 'USD',
    type: 'donation',
    UserId: 2
  }];

  before(() => utils.resetTestDB());

  before(() => Group.create(groupData)
    .tap(g => group = g)
    .tap(() => User.createMany(users))
    .tap(() => Transaction.createMany(transactions, { GroupId: group.id })));

  it('returns a default logo if no logo', () => {
    expect(group.logo).to.contain('/static/images/1px.png');
  });

  it('computes the balance ', () =>
    group.getBalance().then(balance => {
      let sum = 0;
      transactions.map(t => sum += t.netAmountInGroupCurrency);
      expect(balance).to.equal(sum);
    }));

  it('computes the balance until a certain month', (done) => {
    const until = new Date('2016-07-01');
    group.getBalance(until).then(balance => {
      let sum = 0;
      transactions.map(t => {
        if (t.createdAt < until)
          sum += t.netAmountInGroupCurrency
      });
      expect(balance).to.equal(sum);
      done();
    })
  });

  it('computes the number of backers', (done) => {
    group.getBackersCount()
      .then(count => {
        expect(count).to.equal(users.length);
        done();
      })
  });

  it('computes the number of backers until a certain month', (done) => {
    const until = new Date('2016-07-01');
    group.getBackersCount(until).then(count => {
      const backers = {};
      transactions.map(t => {
        if (t.amount > 0 && t.createdAt < until)
          backers[t.UserId] = t.amount;
      });
      expect(count).to.equal(Object.keys(backers).length);
      done();
    })
  });

  it('gets all the expenses', (done) => {
    let totalExpenses = 0;
    transactions.map(t => {
      if (t.netAmountInGroupCurrency < 0)
        totalExpenses++;
    });

    group.getExpenses()
      .then(expenses => {
        expect(expenses.length).to.equal(totalExpenses);
        done();
      })
      .catch(e => {
        console.error('error', e, e.stack);
      });
  });

  it('gets all the expenses in a given month', (done) => {
    const startDate = new Date('2016-06-01');
    const endDate = new Date('2016-07-01');

    let totalExpenses = 0;

    transactions.map(t => {
      if (t.netAmountInGroupCurrency < 0 && t.createdAt > startDate && t.createdAt < endDate)
        totalExpenses++;
    });

    group.getExpenses(null, startDate, endDate)
      .then(expenses => {
        expect(expenses.length).to.equal(totalExpenses);
        done();
      })
      .catch(e => {
        console.error('error', e, e.stack);
      });
  });

  it('get the related groups', (done) => {
    Group.createMany(utils.data('relatedGroups'))
    .then(() => group.getRelatedGroups(3, 0))
    .then(relatedGroups => {
      expect(relatedGroups).to.have.length(3);
      expect(relatedGroups[0].settings.style.hero).to.have.property('cover');
      done();
    })
  });
});
<|endoftext|>


<commit_before>/**
 @ngdoc service
 * @name umbraco.services.overlayService
 *
 * @description
 * Added in Umbraco 8.0. Application-wide service for handling overlays.
 */
(function () {
    "use strict";

    function overlayService(eventsService, backdropService) {

        var currentOverlay = null;

        function open(newOverlay) {

            // prevent two open overlays at the same time
            if(currentOverlay) {
                close();
            }

            var backdropOptions = {};
            var overlay = newOverlay;

            // set the default overlay position to center
            if(!overlay.position) {
                overlay.position = "center";
            }

            // set the default overlay size to small
            if(!overlay.size) {
                overlay.size = "small";
            }

            // use a default empty view if nothing is set
            if(!overlay.view) {
                overlay.view = "views/common/overlays/default/default.html";
            }

            // option to disable backdrop clicks
            if(overlay.disableBackdropClick) {
                backdropOptions.disableEventsOnClick = true;
            }

            overlay.show = true;
            backdropService.open(backdropOptions);
            currentOverlay = overlay;
            eventsService.emit("appState.overlay", overlay);
        }

        function close() {
            backdropService.close();
            currentOverlay = null;
            eventsService.emit("appState.overlay", null);
        }

        function ysod(error) {
            const overlay = {
                view: "views/common/overlays/ysod/ysod.html",
                error: error,
                close: function() {
                    close();
                }
            };
            open(overlay);
        }

        var service = {
            open: open,
            close: close,
            ysod: ysod
        };

        return service;

    }

    angular.module("umbraco.services").factory("overlayService", overlayService);

})();
<commit_msg>Introduced confirm and confirmDelete functions in the Angular overlay service (#6526)<commit_after>/**
 @ngdoc service
 * @name umbraco.services.overlayService
 *
 * @description
 * Added in Umbraco 8.0. Application-wide service for handling overlays.
 */
(function () {
    "use strict";

    function overlayService(eventsService, backdropService) {

        var currentOverlay = null;

        function open(newOverlay) {

            // prevent two open overlays at the same time
            if(currentOverlay) {
                close();
            }

            var backdropOptions = {};
            var overlay = newOverlay;

            // set the default overlay position to center
            if(!overlay.position) {
                overlay.position = "center";
            }

            // set the default overlay size to small
            if(!overlay.size) {
                overlay.size = "small";
            }

            // use a default empty view if nothing is set
            if(!overlay.view) {
                overlay.view = "views/common/overlays/default/default.html";
            }

            // option to disable backdrop clicks
            if(overlay.disableBackdropClick) {
                backdropOptions.disableEventsOnClick = true;
            }

            overlay.show = true;
            backdropService.open(backdropOptions);
            currentOverlay = overlay;
            eventsService.emit("appState.overlay", overlay);
        }

        function close() {
            backdropService.close();
            currentOverlay = null;
            eventsService.emit("appState.overlay", null);
        }

        function ysod(error) {
            const overlay = {
                view: "views/common/overlays/ysod/ysod.html",
                error: error,
                close: function() {
                    close();
                }
            };
            open(overlay);
        }

        function confirm(overlay) {

            if (!overlay.closeButtonLabelKey) overlay.closeButtonLabelKey = "general_cancel";
            if (!overlay.view) overlay.view = "views/common/overlays/confirm/confirm.html";
            if (!overlay.close) overlay.close = function () { close(); };

            switch (overlay.confirmType) {

                case "delete":
                    if (!overlay.confirmMessageStyle) overlay.confirmMessageStyle = "danger";
                    if (!overlay.submitButtonStyle) overlay.submitButtonStyle = "danger";
                    if (!overlay.submitButtonLabelKey) overlay.submitButtonLabelKey = "contentTypeEditor_yesDelete";
                    break;

                default:
                    if (!overlay.submitButtonLabelKey) overlay.submitButtonLabelKey = "general_confirm";

            }

            open(overlay);

        }

        function confirmDelete(overlay) {
            confirm(overlay);
        }

        var service = {
            open: open,
            close: close,
            ysod: ysod,
            confirm: confirm,
            confirmDelete: confirmDelete
        };

        return service;

    }

    angular.module("umbraco.services").factory("overlayService", overlayService);

})();
<|endoftext|>


<commit_before>// master array for fraenks
var fraenks = [];

// setting up menu
$(document).ready(function() {

  // name prompt menu item
  $('#menu-your-name').on("click", function() {
    bootbox.prompt("
What is your name?
Your name is only used for the fränk high score table.", function(result) {
      if (result === null) {
//          no name given
      } else {
//          send name to server
      }
    })
  });

  // about menu item
  $('#menu-about').on("click", function() {
    bootbox.alert("
About fränk
fränk is an experimental multiplayer game using Raspberry Pi as a gaming hub. This game was created by Jani Turunen, 2013.");
  });

  // connection test menu item
  $('#menu-connection-test').on("click", function() {
    bootbox.alert("
Hit OK to ping server ...
", function() {
      socket.emit('ping',Date.now().toString());
    });
  });

  // instructions menu item
  $('#menu-instructions').on("click", function() {
    bootbox.alert("
How to play fränk
Green is good, red is bad. Fastest player to släp a slab gets it. Single game lasts for 20 rounds. You can enter your name for high score purposes at any time via the menu.");
  });

});

// setting up socket
var socket = io.connect(window.location.hostname);

// when socket receives ping respond with pong
socket.on('pong', function (data) {
  var lag = Date.now() - parseInt(data);
  bootbox.alert("
Ping time: "+lag+"ms
");
})

// when socket receives ping respond with pong
socket.on('fraenks', function (data) {
  // delete all existing fraenks
  $('.fraenk').remove();
  fraenks = []

  // create new ones
  jQuery.each(data, function(frank) {
    var f = new fraenk();
    f.create(data[frank].id);
    f.animate(19,11);
    f.wander();
    fraenks.push(f);
  });
})

socket.on('kill', function(data) {
  $('#'+data[0].id).remove();
});

function fraenk() {
  this.id = null;
  this.create = function(id) {
    this.id = id;
    this.ele = $('
').appendTo('body');
    this.ele.on('click', function() {
      $(this).remove();
      socket.emit('kill',$(this).attr('id'));
    });
  },
  this.animate = function(max, min) {
    var f = Math.floor(Math.random() * (max - min + 1)) + min;
    this.ele.sprite({fps: f, no_of_frames: 4})
  },
  this.wander = function() {
    this.ele.spRandom({top: 0, bottom: $(document).height(), left: 0, right: $(document).width()})
  }
}

socket.emit('ready'); // telling server we're ready<commit_msg>rules etc<commit_after>// master array for fraenks
var fraenks = [];

// setting up menu
$(document).ready(function() {

  // name prompt menu item
  $('#menu-your-name').on("click", function() {
/*    bootbox.prompt("
What is your name?
Your name is only used for the fränk high score table.", function(result) {
      if (result === null) {
//          no name given
      } else {
//          send name to server
      }
    })*/
    bootbox.alert("note yet...");
  });

  // about menu item
  $('#menu-about').on("click", function() {
    bootbox.alert("
About fränk
fränk is an experimental multiplayer game that can be deployed locally, for example using Raspberry Pi as a gaming hub, but also in the internet. This game was created by Jani Turunen, 2013.");
  });

  // connection test menu item
  $('#menu-connection-test').on("click", function() {
    bootbox.alert("
Hit OK to ping server ...
", function() {
      socket.emit('ping',Date.now().toString());
    });
  });

  // instructions menu item
  $('#menu-instructions').on("click", function() {
    bootbox.alert("
How to play fränk
At this point, just keep clicking! We'll add scores and gameplay later!");
  });

});

// setting up socket
var socket = io.connect(window.location.hostname);

// when socket receives ping respond with pong
socket.on('pong', function (data) {
  var lag = Date.now() - parseInt(data);
  bootbox.alert("
Ping time: "+lag+"ms
");
})

// when socket receives ping respond with pong
socket.on('fraenks', function (data) {
  // delete all existing fraenks
  $('.fraenk').remove();
  fraenks = []

  // create new ones
  jQuery.each(data, function(frank) {
    var f = new fraenk();
    f.create(data[frank].id);
    f.animate(19,11);
    f.wander();
    fraenks.push(f);
  });
})

socket.on('kill', function(data) {
  $('#'+data[0].id).remove();
});

function fraenk() {
  this.id = null;
  this.create = function(id) {
    this.id = id;
    this.ele = $('
').appendTo('body');
    this.ele.on('click', function() {
      $(this).remove();
      socket.emit('kill',$(this).attr('id'));
    });
  },
  this.animate = function(max, min) {
    var f = Math.floor(Math.random() * (max - min + 1)) + min;
    this.ele.sprite({fps: f, no_of_frames: 4})
  },
  this.wander = function() {
    this.ele.spRandom({top: 0, bottom: $(document).height(), left: 0, right: $(document).width()})
  }
}

socket.emit('ready'); // telling server we're ready<|endoftext|>


<commit_before>console.log(React);
console.log(ReactDOM);

var socket;
var userConnected;

socket = io.connect('http://localhost:1337');
socket.on('connect', addUser);
socket.on('updatechat', processMessage);
socket.on('updateusers', updateUserList);

// Add the addUser function, which clals the emit method on the socket to call
// the adduser method on the chat server.
function addUser() {
    var userNamePromt = swal({
        title: "Please enter your username",
        type: "input",
        showCancelButton: false,
        closeOnConfirm: false,
        animation: "slide-from-top",
        inputPlaceholder: "e.g Gavin Belson or Mr.Robot"
    }, function(inputValue){
        if (inputValue === false) return false;
        if (inputValue === "") {
             swal.showInputError("Hey, we need you to enter your username!");
             return false
         }
         inputValue = inputValue.replace(/<(?:.|\n)*?>/gm, '');
         swal("Nice!", "Your username is " + inputValue, "success");
         socket.emit('adduser', inputValue);
     });

    // Checks if the user is connected
    if(socket.socket.connected) {
        userConnected = true;
    } else {
        userConnected = false;
    }

}

// Get the current timestamp to display in the chat next to the message.
function getCurrentTime() {
    var datetime = new Date();
    var hours = datetime.getHours();
    var minutes = datetime.getMinutes();
    var seconds = datetime.getSeconds();

    if (seconds < 10) {
        seconds = '0' + seconds;
    }

    return hours + ':' + minutes + ':' + seconds;
}

// processMessage function is called when the chat service sends a message.
// jQuery object with the response and insert message after converstaion.
function processMessage(username, data) {
    $('' + '[' + getCurrentTime() + '] ' + '' + username + ': ' + data + '
').insertAfter($('#conversation'));
}

// updateUserList function is called when server sends an updated user list.
function updateUserList(data) {
    $('#users').empty();
    $.each(data, function(key, value) {
        $('#users').append('
 ' + key + '
');
    });
}

var TopBarBox = React.createClass({
  render: function() {
    return (

Chat Server

Menu

 GitHub

 Download

 Twitter

    );
  }
});

var ChatNoticeBox = React.createClass({
    render: function() {
        return (

Bonsua! Chat Server is built with Node.js, Express.js and Socket.io

        )
    }
});

var MessageBox = React.createClass({
    getInitialState: function() {
        return {
            message: ''
        };
    },
    handleMessageChange: function(e) {
        this.setState({message: e.target.value});
    },
    handleClick: function() {
        var message = this.state.message;
        var data = document.getElementById('data');
        message = message.replace(/<(?:.|\n)*?>/gm, '');
        if(!message) {
            sweetAlert("Oops...", "You've didn\'t entered a message!", "error");
        } else {
            socket.emit('sendchat', message);
        }
        this.state.message = this.setState({message: ''});
        data.value = '';
        data.focus();
    },
    handleKeyPress: function(e) {
        if (e.key === 'Enter') {
            e.preventDefault();
            $(this).blur();
            $('#datasend').focus().click();
        }
    },
    render: function() {
        return (

                <input id="data" placeholder="Message.." onChange={this.handleMessageChange} onKeyUp={this.handleKeyPress} />
                <input id="datasend" className="button send-msg" type="button" onClick={this.handleClick} value="Send message" />

        )
    },
});

var UserListBox = React.createClass({
    render: function() {
        return (

Users

        )
    }
});

ReactDOM.render(<TopBarBox />, document.getElementById('nav-wrap'));
ReactDOM.render(<ChatNoticeBox />, document.getElementById('chat-notice'));
ReactDOM.render(<MessageBox />, document.getElementById('message-wrap'));
ReactDOM.render(<UserListBox />, document.getElementById('users-wrap'));
<commit_msg>Removed testing variables<commit_after>var socket;
var userConnected;

socket = io.connect('http://localhost:1337');
socket.on('connect', addUser);
socket.on('updatechat', processMessage);
socket.on('updateusers', updateUserList);

// Add the addUser function, which clals the emit method on the socket to call
// the adduser method on the chat server.
function addUser() {
    var userNamePromt = swal({
        title: "Please enter your username",
        type: "input",
        showCancelButton: false,
        closeOnConfirm: false,
        animation: "slide-from-top",
        inputPlaceholder: "e.g Gavin Belson or Mr.Robot"
    }, function(inputValue){
        if (inputValue === false) return false;
        if (inputValue === "") {
             swal.showInputError("Hey, we need you to enter your username!");
             return false
         }
         inputValue = inputValue.replace(/<(?:.|\n)*?>/gm, '');
         swal("Nice!", "Your username is " + inputValue, "success");
         socket.emit('adduser', inputValue);
     });

    // Checks if the user is connected
    if(socket.socket.connected) {
        userConnected = true;
    } else {
        userConnected = false;
    }

}

// Get the current timestamp to display in the chat next to the message.
function getCurrentTime() {
    var datetime = new Date();
    var hours = datetime.getHours();
    var minutes = datetime.getMinutes();
    var seconds = datetime.getSeconds();

    if (seconds < 10) {
        seconds = '0' + seconds;
    }

    return hours + ':' + minutes + ':' + seconds;
}

// processMessage function is called when the chat service sends a message.
// jQuery object with the response and insert message after converstaion.
function processMessage(username, data) {
    $('' + '[' + getCurrentTime() + '] ' + '' + username + ': ' + data + '
').insertAfter($('#conversation'));
}

// updateUserList function is called when server sends an updated user list.
function updateUserList(data) {
    $('#users').empty();
    $.each(data, function(key, value) {
        $('#users').append('
 ' + key + '
');
    });
}

var TopBarBox = React.createClass({
  render: function() {
    return (

Chat Server

Menu

 GitHub

 Download

 Twitter

    );
  }
});

var ChatNoticeBox = React.createClass({
    render: function() {
        return (

Bonsua! Chat Server is built with Node.js, Express.js and Socket.io

        )
    }
});

var MessageBox = React.createClass({
    getInitialState: function() {
        return {
            message: ''
        };
    },
    handleMessageChange: function(e) {
        this.setState({message: e.target.value});
    },
    handleClick: function() {
        var message = this.state.message;
        var data = document.getElementById('data');
        message = message.replace(/<(?:.|\n)*?>/gm, '');
        if(!message) {
            sweetAlert("Oops...", "You've didn\'t entered a message!", "error");
        } else {
            socket.emit('sendchat', message);
        }
        this.state.message = this.setState({message: ''});
        data.value = '';
        data.focus();
    },
    handleKeyPress: function(e) {
        if (e.key === 'Enter') {
            e.preventDefault();
            $(this).blur();
            $('#datasend').focus().click();
        }
    },
    render: function() {
        return (

                <input id="data" placeholder="Message.." onChange={this.handleMessageChange} onKeyUp={this.handleKeyPress} />
                <input id="datasend" className="button send-msg" type="button" onClick={this.handleClick} value="Send message" />

        )
    },
});

var UserListBox = React.createClass({
    render: function() {
        return (

Users

        )
    }
});

ReactDOM.render(<TopBarBox />, document.getElementById('nav-wrap'));
ReactDOM.render(<ChatNoticeBox />, document.getElementById('chat-notice'));
ReactDOM.render(<MessageBox />, document.getElementById('message-wrap'));
ReactDOM.render(<UserListBox />, document.getElementById('users-wrap'));
<|endoftext|>


<commit_before>'use strict';

const { util: { checkType } } = require('../../core');

const MetricsAggregationBase = require('./metrics-aggregation-base');

/**
 * A multi-value metrics aggregation that calculates one or more percentiles
 * over numeric values extracted from the aggregated documents. These values can
 * be extracted either from specific numeric fields in the documents, or be
 * generated by a provided script.
 *
 * [Elasticsearch reference](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-percentile-aggregation.html)
 *
 * Aggregation that calculates one or more percentiles over numeric values
 * extracted from the aggregated documents.
 *
 * @example
 * const agg = bob.percentilesAggregation('load_time_outlier', 'load_time');
 *
 * @example
 * // Convert load time from mills to seconds on-the-fly using script
 * const agg = bob.percentilesAggregation('load_time_outlier').script(
 *     bob.script('inline', "doc['load_time'].value / params.timeUnit")
 *         .lang('painless')
 *         .params({ timeUnit: 1000 })
 * );
 *
 * @param {string} name The name which will be used to refer to this aggregation.
 * @param {string=} field The field to aggregate on
 *
 * @extends MetricsAggregationBase
 */
class PercentilesAggregation extends MetricsAggregationBase {
    // eslint-disable-next-line require-jsdoc
    constructor(name, field) {
        super(name, 'percentiles', field);
    }

    /**
     * Enable the response to be returned as a keyed object where the key is the
     * bucket interval.
     *
     * @example
     * // Return the ranges as an array rather than a hash
     * const agg = bob.percentilesAggregation('balance_outlier', 'balance').keyed(
     *     false
     * );
     *
     * @param {boolean} keyed To enable keyed response or not. True by default
     * @returns {PercentilesAggregation} returns `this` so that calls can be chained
     */
    keyed(keyed) {
        this._aggsDef.keyed = keyed;
        return this;
    }

    /**
     * Specifies the percents of interest.
     * Requested percentiles must be a value between 0-100 inclusive
     *
     * @example
     * // Specify particular percentiles to calculate
     * const agg = bob.percentilesAggregation(
     *     'load_time_outlier',
     *     'load_time'
     * ).percents([95, 99, 99.9]);
     *
     * @param {Array} percents Parameter to specify particular percentiles to calculate
     * @returns {PercentilesAggregation} returns `this` so that calls can be chained
     * @throws {TypeError} If `percents` is not an instance of Array
     */
    percents(percents) {
        checkType(percents, Array);
        this._aggsDef.percents = percents;
        return this;
    }

    /**
     * Compression controls memory usage and approximation error. The compression
     * value limits the maximum number of nodes to 100 * compression. By
     * increasing the compression value, you can increase the accuracy of your
     * percentiles at the cost of more memory. Larger compression values also make
     * the algorithm slower since the underlying tree data structure grows in
     * size, resulting in more expensive operations. The default compression
     * value is 100.
     *
     * @example
     * const agg = bob.percentilesAggregation(
     *     'load_time_outlier',
     *     'load_time'
     * ).tdigest(200);
     *
     * @param {number} compression Parameter to balance memory utilization with estimation accuracy.
     * @returns {PercentilesAggregation} returns `this` so that calls can be chained
     */
    tdigest(compression) {
        this._aggsDef.tdigest = { compression };
        return this;
    }

    /**
     * Compression controls memory usage and approximation error. The compression
     * value limits the maximum number of nodes to 100 * compression. By
     * increasing the compression value, you can increase the accuracy of your
     * percentiles at the cost of more memory. Larger compression values also make
     * the algorithm slower since the underlying tree data structure grows in
     * size, resulting in more expensive operations. The default compression
     * value is 100.
     *
     * Alias for `tdigest`
     *
     * @example
     * const agg = bob.percentilesAggregation(
     *     'load_time_outlier',
     *     'load_time'
     * ).compression(200);
     *
     * @param {number} compression Parameter to balance memory utilization with estimation accuracy.
     * @returns {PercentileRanksAggregation} returns `this` so that calls can be chained
     */
    compression(compression) {
        this._aggsDef.tdigest = { compression };
        return this;
    }

    /**
     * HDR Histogram (High Dynamic Range Histogram) is an alternative implementation
     * that can be useful when calculating percentiles for latency measurements
     * as it can be faster than the t-digest implementation
     * with the trade-off of a larger memory footprint.
     *
     * The HDR Histogram can be used by specifying the method parameter in the request.
     *
     * @example
     * const agg = bob.percentilesAggregation('load_time_outlier', 'load_time')
     *     .percents([95, 99, 99.9])
     *     .hdr(3);
     *
     * @param {number} numberOfSigDigits The resolution of values
     * for the histogram in number of significant digits
     * @returns {PercentilesAggregation} returns `this` so that calls can be chained
     */
    hdr(numberOfSigDigits) {
        this._aggsDef.hdr = { number_of_significant_value_digits: numberOfSigDigits };
        return this;
    }
}

module.exports = PercentilesAggregation;
<commit_msg>docs(PercentilesAggregation): Correct returns annotation<commit_after>'use strict';

const { util: { checkType } } = require('../../core');

const MetricsAggregationBase = require('./metrics-aggregation-base');

/**
 * A multi-value metrics aggregation that calculates one or more percentiles
 * over numeric values extracted from the aggregated documents. These values can
 * be extracted either from specific numeric fields in the documents, or be
 * generated by a provided script.
 *
 * [Elasticsearch reference](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-percentile-aggregation.html)
 *
 * Aggregation that calculates one or more percentiles over numeric values
 * extracted from the aggregated documents.
 *
 * @example
 * const agg = bob.percentilesAggregation('load_time_outlier', 'load_time');
 *
 * @example
 * // Convert load time from mills to seconds on-the-fly using script
 * const agg = bob.percentilesAggregation('load_time_outlier').script(
 *     bob.script('inline', "doc['load_time'].value / params.timeUnit")
 *         .lang('painless')
 *         .params({ timeUnit: 1000 })
 * );
 *
 * @param {string} name The name which will be used to refer to this aggregation.
 * @param {string=} field The field to aggregate on
 *
 * @extends MetricsAggregationBase
 */
class PercentilesAggregation extends MetricsAggregationBase {
    // eslint-disable-next-line require-jsdoc
    constructor(name, field) {
        super(name, 'percentiles', field);
    }

    /**
     * Enable the response to be returned as a keyed object where the key is the
     * bucket interval.
     *
     * @example
     * // Return the ranges as an array rather than a hash
     * const agg = bob.percentilesAggregation('balance_outlier', 'balance').keyed(
     *     false
     * );
     *
     * @param {boolean} keyed To enable keyed response or not. True by default
     * @returns {PercentilesAggregation} returns `this` so that calls can be chained
     */
    keyed(keyed) {
        this._aggsDef.keyed = keyed;
        return this;
    }

    /**
     * Specifies the percents of interest.
     * Requested percentiles must be a value between 0-100 inclusive
     *
     * @example
     * // Specify particular percentiles to calculate
     * const agg = bob.percentilesAggregation(
     *     'load_time_outlier',
     *     'load_time'
     * ).percents([95, 99, 99.9]);
     *
     * @param {Array} percents Parameter to specify particular percentiles to calculate
     * @returns {PercentilesAggregation} returns `this` so that calls can be chained
     * @throws {TypeError} If `percents` is not an instance of Array
     */
    percents(percents) {
        checkType(percents, Array);
        this._aggsDef.percents = percents;
        return this;
    }

    /**
     * Compression controls memory usage and approximation error. The compression
     * value limits the maximum number of nodes to 100 * compression. By
     * increasing the compression value, you can increase the accuracy of your
     * percentiles at the cost of more memory. Larger compression values also make
     * the algorithm slower since the underlying tree data structure grows in
     * size, resulting in more expensive operations. The default compression
     * value is 100.
     *
     * @example
     * const agg = bob.percentilesAggregation(
     *     'load_time_outlier',
     *     'load_time'
     * ).tdigest(200);
     *
     * @param {number} compression Parameter to balance memory utilization with estimation accuracy.
     * @returns {PercentilesAggregation} returns `this` so that calls can be chained
     */
    tdigest(compression) {
        this._aggsDef.tdigest = { compression };
        return this;
    }

    /**
     * Compression controls memory usage and approximation error. The compression
     * value limits the maximum number of nodes to 100 * compression. By
     * increasing the compression value, you can increase the accuracy of your
     * percentiles at the cost of more memory. Larger compression values also make
     * the algorithm slower since the underlying tree data structure grows in
     * size, resulting in more expensive operations. The default compression
     * value is 100.
     *
     * Alias for `tdigest`
     *
     * @example
     * const agg = bob.percentilesAggregation(
     *     'load_time_outlier',
     *     'load_time'
     * ).compression(200);
     *
     * @param {number} compression Parameter to balance memory utilization with estimation accuracy.
     * @returns {PercentilesAggregation} returns `this` so that calls can be chained
     */
    compression(compression) {
        this._aggsDef.tdigest = { compression };
        return this;
    }

    /**
     * HDR Histogram (High Dynamic Range Histogram) is an alternative implementation
     * that can be useful when calculating percentiles for latency measurements
     * as it can be faster than the t-digest implementation
     * with the trade-off of a larger memory footprint.
     *
     * The HDR Histogram can be used by specifying the method parameter in the request.
     *
     * @example
     * const agg = bob.percentilesAggregation('load_time_outlier', 'load_time')
     *     .percents([95, 99, 99.9])
     *     .hdr(3);
     *
     * @param {number} numberOfSigDigits The resolution of values
     * for the histogram in number of significant digits
     * @returns {PercentilesAggregation} returns `this` so that calls can be chained
     */
    hdr(numberOfSigDigits) {
        this._aggsDef.hdr = { number_of_significant_value_digits: numberOfSigDigits };
        return this;
    }
}

module.exports = PercentilesAggregation;
<|endoftext|>


<commit_before>angular.module( 'App.Client.GameButtons' ).directive( 'gjClientGameButtons', function()
{
	return {
		restrict: 'E',
		templateUrl: '/app/components/client/game-buttons/game-buttons.html',
		scope: {
			game: '=game',
			overlay: '=?overlayVariant',
			small: '=?smallVariant',
			onShowLaunchOptions: '&?onShowLaunchOptions',
			onHideLaunchOptions: '&?onHideLaunchOptions',
			onShowOptions: '&?onShowOptions',
			onHideOptions: '&?onHideOptions',
			label: '@?',
		},
		controllerAs: 'ctrl',
		bindToController: true,
		controller: function( $q, $scope, Client_Library, Client_Launcher, Client_Installer, LocalDb_Package, Client_InstallPackageModal, Device, Api, Popover, Analytics,
			Game, Game_Package, Game_Release, Game_Build, Game_Build_LaunchOption )
		{
			var _this = this;
			var os = Device.os();
			var arch = Device.arch();

			$scope.Client_Library = Client_Library;
			$scope.LocalDb_Package = LocalDb_Package;

			this.hasInstallableBuilds = this.game.hasDesktopSupport();
			this.canInstall = this.game.canInstall( os, arch );

			this.localPackage = null;
			this.isLoadingPackageData = false;
			this.packageDataPromise = null;

			this.installTooltip = null;
			if ( !this.hasInstallableBuilds ) {
				this.installTooltip = 'This game doesn\'t have any installable builds yet.';
			}
			else if ( !this.canInstall ) {
				this.installTooltip = 'This game is not available for installing on your OS.';
			}

			// We try to pull a package with some action on it.
			// For example, if a package is installing, we want to pull that one to show.
			$scope.$watch( function()
			{
				return Client_Library.findActiveForGame( _this.game.id );
			},
			function( localPackage )
			{
				_this.localPackage = localPackage;
			} );

			this.install = function()
			{
				Analytics.trackEvent( 'client-game-buttons', 'install' );

				if ( !this.packageDataPromise ) {
					this.packageDataPromise = Api.sendRequest( '/web/discover/games/packages/' + _this.game.id )
						.then( function( payload )
						{
							var packageData = Game_Package.processPackagePayload( payload );
							packageData.installableBuilds = Game.pluckInstallableBuilds( packageData.packages, os, arch );

							return packageData;
						} );
				}

				this.packageDataPromise
					.then( function( packageData )
					{
						// If more than one package for their OS, then we have to show an install package modal.
						if ( _.size( _.groupBy( packageData.installableBuilds, 'game_package_id' ) ) > 1 ) {
							Client_InstallPackageModal.show( _this.game );
							return;
						}

						var build = packageData.installableBuilds[0];
						Client_Library.installPackage(
							_this.game,
							build._package,
							build._release,
							build,
							build._launch_options
						);
					} );
			};

			this.pause = function()
			{
				Analytics.trackEvent( 'client-game-buttons', 'pause-install' );
				Client_Installer.pause( this.localPackage );
			};

			this.resume = function()
			{
				Analytics.trackEvent( 'client-game-buttons', 'resume-install' );
				Client_Installer.resume( this.localPackage );
			};

			this.cancel = function()
			{
				Analytics.trackEvent( 'client-game-buttons', 'cancel-install' );
				this.localPackage.$uninstall();
			};

			this.retryInstall = function()
			{
				Analytics.trackEvent( 'client-game-buttons', 'retry-install' );
				Client_Installer.retryInstall( this.localPackage );
			};

			this.launch = function( localPackage )
			{
				// If already running, do nothing.
				if ( localPackage.isRunning() ) {
					return;
				}

				Analytics.trackEvent( 'client-game-buttons', 'launch' );
				Popover.hideAll();
				Client_Launcher.launch( localPackage );
			};

			this.openFolder = function( localPackage )
			{
				var fs = require( 'fs' );
				var path = require( 'path' );
				var gui = require( 'nw.gui' );

				fs.readdir( path.resolve( localPackage.install_dir ), function( err, files )
				{
					if ( err ) {
						return;
					}

					// Just open the first file in the folder.
					// This way we open within the package folder instead of the parent folder.
					gui.Shell.showItemInFolder( path.resolve( localPackage.install_dir, files[0] ) );
				} );
			};

			this.uninstallPackage = function( localPackage )
			{
				// If running, do nothing.
				if ( localPackage.isRunning() ) {
					return;
				}

				Analytics.trackEvent( 'client-game-buttons', 'uninstall' );
				Popover.hideAll();
				return localPackage.$uninstall();
			};
		}
	};
} );
<commit_msg>Fix bug where it was installing 32bit builds through search instead of 64bit if you're on 64bit computer.<commit_after>angular.module( 'App.Client.GameButtons' ).directive( 'gjClientGameButtons', function()
{
	return {
		restrict: 'E',
		templateUrl: '/app/components/client/game-buttons/game-buttons.html',
		scope: {
			game: '=game',
			overlay: '=?overlayVariant',
			small: '=?smallVariant',
			onShowLaunchOptions: '&?onShowLaunchOptions',
			onHideLaunchOptions: '&?onHideLaunchOptions',
			onShowOptions: '&?onShowOptions',
			onHideOptions: '&?onHideOptions',
			label: '@?',
		},
		controllerAs: 'ctrl',
		bindToController: true,
		controller: function( $q, $scope, Client_Library, Client_Launcher, Client_Installer, LocalDb_Package, Client_InstallPackageModal, Device, Api, Popover, Analytics,
			Game, Game_Package, Game_Release, Game_Build, Game_Build_LaunchOption )
		{
			var _this = this;
			var os = Device.os();
			var arch = Device.arch();

			$scope.Client_Library = Client_Library;
			$scope.LocalDb_Package = LocalDb_Package;

			this.hasInstallableBuilds = this.game.hasDesktopSupport();
			this.canInstall = this.game.canInstall( os, arch );

			this.localPackage = null;
			this.isLoadingPackageData = false;
			this.packageDataPromise = null;

			this.installTooltip = null;
			if ( !this.hasInstallableBuilds ) {
				this.installTooltip = 'This game doesn\'t have any installable builds yet.';
			}
			else if ( !this.canInstall ) {
				this.installTooltip = 'This game is not available for installing on your OS.';
			}

			// We try to pull a package with some action on it.
			// For example, if a package is installing, we want to pull that one to show.
			$scope.$watch( function()
			{
				return Client_Library.findActiveForGame( _this.game.id );
			},
			function( localPackage )
			{
				_this.localPackage = localPackage;
			} );

			this.install = function()
			{
				Analytics.trackEvent( 'client-game-buttons', 'install' );

				if ( !this.packageDataPromise ) {
					this.packageDataPromise = Api.sendRequest( '/web/discover/games/packages/' + _this.game.id )
						.then( function( payload )
						{
							var packageData = Game_Package.processPackagePayload( payload );
							packageData.installableBuilds = Game.pluckInstallableBuilds( packageData.packages, os, arch );

							return packageData;
						} );
				}

				this.packageDataPromise
					.then( function( packageData )
					{
						// If more than one package for their OS, then we have to show an install package modal.
						if ( _.size( _.groupBy( packageData.installableBuilds, 'game_package_id' ) ) > 1 ) {
							Client_InstallPackageModal.show( _this.game );
							return;
						}

						var build = Game.chooseBestBuild( packageData.installableBuilds, os, arch );
						Client_Library.installPackage(
							_this.game,
							build._package,
							build._release,
							build,
							build._launch_options
						);
					} );
			};

			this.pause = function()
			{
				Analytics.trackEvent( 'client-game-buttons', 'pause-install' );
				Client_Installer.pause( this.localPackage );
			};

			this.resume = function()
			{
				Analytics.trackEvent( 'client-game-buttons', 'resume-install' );
				Client_Installer.resume( this.localPackage );
			};

			this.cancel = function()
			{
				Analytics.trackEvent( 'client-game-buttons', 'cancel-install' );
				this.localPackage.$uninstall();
			};

			this.retryInstall = function()
			{
				Analytics.trackEvent( 'client-game-buttons', 'retry-install' );
				Client_Installer.retryInstall( this.localPackage );
			};

			this.launch = function( localPackage )
			{
				// If already running, do nothing.
				if ( localPackage.isRunning() ) {
					return;
				}

				Analytics.trackEvent( 'client-game-buttons', 'launch' );
				Popover.hideAll();
				Client_Launcher.launch( localPackage );
			};

			this.openFolder = function( localPackage )
			{
				var fs = require( 'fs' );
				var path = require( 'path' );
				var gui = require( 'nw.gui' );

				fs.readdir( path.resolve( localPackage.install_dir ), function( err, files )
				{
					if ( err ) {
						return;
					}

					// Just open the first file in the folder.
					// This way we open within the package folder instead of the parent folder.
					gui.Shell.showItemInFolder( path.resolve( localPackage.install_dir, files[0] ) );
				} );
			};

			this.uninstallPackage = function( localPackage )
			{
				// If running, do nothing.
				if ( localPackage.isRunning() ) {
					return;
				}

				Analytics.trackEvent( 'client-game-buttons', 'uninstall' );
				Popover.hideAll();
				return localPackage.$uninstall();
			};
		}
	};
} );
<|endoftext|>