<commit_before>//TODO refactor this.. :)
ant.charts.map = function (container, width, height) {
	this.scale = 100;
	this.translate = [width / 2, height / 2];
	this.refCenter = [.5, .5];
	this.translate = [width * this.refCenter [0], height * this.refCenter [1]];
	this.center = {lat: 34.5133, lon: -94.1629};
	this.width = width;
	this.height = height;
	this.container = container;
	this.topology = {};
	this.features = {};
	this.rateById = d3.map ();
	this.svg = d3.select (container).append ("svg").attr ("width", width).attr ("height", height);
	this.topologies = {};
	this.projection = d3.geo.mercator ();
	this.redraw = function (topo, quantifier, plot) {
		if (!topo) {
			for (t in this.topologies) {
				this.redraw (t, quantifier, plot);
			}
			return;
		}
		this.topologies[topo].redraw (quantifier, plot);
	}
	this.setScaleAndCenter = function (s, c) {
		this.scale = s;
		this.center = c;
		this.redraw ();
	}
	this.setScale = function (s) {
		this.scale = s;
		this.redraw ();
	}
	this.setCenter = function (c) {
		this.center = c;
		this.redraw ();
	}
	this.getPath = function () {
		if (!this.center) throw "No center defined";
		//TODO accomodate the lack of center coordinate.
		this.projection
			.scale(this.scale)
			.rotate ([-this.center.lon, 0])
			.center ([0, this.center.lat])
			.translate (this.translate);

		return d3.geo.path ().projection (this.projection);
	}
	this.getArc = function () {
		return d3.geo.greatArc().precision(3);
	}
	/*
	this.lineConnectElements = function (elmA, elmB) {
		var path = this.getPath ();
		var arc = this.getArc ();
		var a = d3.select(elmA);

		var centroidA = path.centroid (a.datum ());
		var b = d3.select (elmB);
		var centroidB = path.centroid (b.datum ())
		var links = [];

		links.push ({"source": path.projection().invert (centroidA), "target": path.projection ().invert (centroidB)});
		var layer = this.svg.append ("g").attr ("class", "lineLayer");
		layer.append ("path")
			.data (links)
			.attr ("d", function (x) { return path(arc (x)); })
			.attr ("vector-effect", "non-scaling-stroke")
			.style ({'stroke-width': 1, 'stroke': '#B10000', 'stroke-linejoin': 'round', 'fill': 'none'})
	},
	*/
	this.zoomSelector = null,
	this.zoomContext = 20,
	this.reZoom = function () {
		if (this.zoomSelector != null) {
			this.zoomTo (this.zoomSelector, this.zoomContext);
		}
	},
	this.removeClass = function (selector, cls) {
		this.svg.selectAll (selector).classed (cls, false);
	},
	this.addClass = function (selector, cls) {
		this.svg.selectAll (selector).classed (cls, true);
	}
	this.zoomTo = function (selector, context) {
		if (!context) context = this.context
		var e = this.svg.selectAll (selector);
		if (!e) throw "No element found: " + selector;
		this.zoomSelector = selector;
		this.zoomContext = context;
		var path = this.getPath ();
		var width = this.width;
		var height = this.height;
		var bounds = path.bounds(e.datum ()),
			dx = bounds[1][0] - bounds[0][0],
			dy = bounds[1][1] - bounds[0][1],
			x = (bounds[0][0] + bounds[1][0]) / 2,
			y = (bounds[0][1] + bounds[1][1]) / 2,
			scale = (context / 100) / Math.max(dx / width, dy / height),
			translate = [width * this.refCenter [0] - scale * x, height * this.refCenter [1] - scale * y];

		this.svg
			.selectAll ("path")
			.attr ("vector-effect", "non-scaling-stroke")
			.attr ("transform", "translate(" + translate + ")scale(" + scale + ")");
		this.svg
			.selectAll ("text")
			.attr ("vector-effect", "non-scaling-stroke")
			.attr ("transform", "translate(" + translate + ")scale(" + scale + ")");
		this.svg
			.selectAll ("circle")
			.attr ("vector-effect", "non-scaling-stroke")
			.attr ("transform", "translate(" + translate + ")scale(" + scale + ")")
	}
	this.addFeatures = function (topo, collection, key, quantifier, plot) {
		if (!plot) plot = "lines"
		if (this.topologies [topo]) throw "A topology " + topo + " already exists.";
		if (collection && collection.objects) {
			var features = collection.objects [key];
			if (features) {
				this.svg.append ("g")
					.attr ("class", topo);
				this.topologies [topo] = new ant.charts.map.topology (this.svg, topo, this.getPath (), collection, features);
				this.redraw (topo, quantifier, plot);

				return this.topologies [topo];
			} else {
				throw "No Features found: (" + topo + ")" + key;
			}
		} else {
			throw "Empty features collections? " + topo;
		}
	}
	return this;
};
ant.charts.map.topology = function (cont, name, path, t, f) {
	this.container = cont;
	this.name = name;
	this.topology = t;
	this.features = f;
	this.path = path;
	this.redraw = function (setId, quantifier, plot) {
		this.callbacks = {};
		if (!plot) plot = "lines";
		this.container.select ("g." + this.name).selectAll ("text").remove ();
		var path = this.path;

		var qn = quantifier ? $.proxy (
				function (selector, d, plot) {
					var attrs = quantifier.fn.apply (quantifier.context, [d, quantifier.args, quantifier.data])
					if (attrs) {
						if (plot == "points") {
							attrs.cx = path.centroid (d) [0];
							attrs.cy = path.centroid (d) [1];
						}
						if (attrs.text) {
							var xs = {"x": path.centroid (d)[0], "y": path.centroid (d)[1]};
							d3.select (selector.parentNode)
								.append ("svg:text")
								.attr (xs)
								.attr (attrs)
								.text (attrs.text);
						}
						// This section adds the data-* attributes returned from the quantifier to the element...!!!
						// This allows the cascading of visualizations
						var data = attrs.data;
						attrs.data = null;
						selector.attr (attrs);
						if (data) {
							for (var d in data) {
								var val = data [d];
								if (val === Object (val)) {
									val = JSON.stringify (val);
								}
								selector.attr ("data-" + d, val);
							}
						}
					}
				},
			quantifier) : function (selector, d) { selector.attr ("class", ""); };

		if (plot == "lines") {
			this.container.select ("g." + this.name).selectAll ("path")
				.data (topojson.feature (this.topology, this.features).features)
				.each (function (d) { qn (d3.select (this), d, plot); })
				.attr ("id", setId)
				.attr ("d", function (x) { return path (x); })
				.enter ()
				.append ("path")
				.on ("click", this.createCallback ("click"))
				.on ("mouseover", this.createCallback ("mouseover"))
				.on ("mouseout", this.createCallback ("mouseout"))
		}
		if (plot == "points") {
			this.container.select ("g." + this.name).selectAll ("circle")
				.data (topojson.feature (this.topology, this.features).features)
				.each (function (d) { qn (d3.select (this), d, plot); })
				.attr ("id", setId)
				.enter ()
				.append ("circle")
				.on ("click", this.createCallback ("click"))
				.on ("mouseover", this.createCallback ("mouseover"))
				.on ("mouseout", this.createCallback ("mouseout"))
		}
	}
	this.createCallback = function (type) {
		var me = this;
		return function () {
			var args = [];
			for (var a in arguments) {
				args.push (arguments [a]);
			}
			args.push (this);
			me.callback.apply (me, [type, args]);
		}
	}
	this.callbacks = {};
	this.on = function (ev, cb, scope) {
		if (!this.callbacks [ev]) {
			this.callbacks [ev] = [];
		}
		if (!scope) { scope = this; }
		this.callbacks [ev].push ({ scope: scope, callback: cb});
	}
	this.removeCallback = function (ev, cb) {
		for (var x in this.callbacks [ev]) {
			if (this.callbacks [ev] [x].callback == cb) {
				this.callbacks [ev].splice (x, 1);
			}
		}
	}
	this.callback = function (ev, args) {
		if (!this.callbacks [ev]) return;
		for (cb in this.callbacks [ev]) {
			if (cb) {
				var x = this.callbacks [ev][cb];
				x.callback.apply (x.scope, args);
			}
		}
	}
}
<commit_msg>Changed the default scale to 200000 instead of 100 while I work on #7<commit_after>//TODO refactor this.. :)
ant.charts.map = function (container, width, height) {
	this.scale = 200000;
	this.translate = [width / 2, height / 2];
	this.refCenter = [.5, .5];
	this.translate = [width * this.refCenter [0], height * this.refCenter [1]];
	this.center = {lat: 34.5133, lon: -94.1629};
	this.width = width;
	this.height = height;
	this.container = container;
	this.topology = {};
	this.features = {};
	this.rateById = d3.map ();
	this.svg = d3.select (container).append ("svg").attr ("width", width).attr ("height", height);
	this.topologies = {};
	this.projection = d3.geo.mercator ();
	this.redraw = function (topo, quantifier, plot) {
		if (!topo) {
			for (t in this.topologies) {
				this.redraw (t, quantifier, plot);
			}
			return;
		}
		this.topologies[topo].redraw (quantifier, plot);
	}
	this.setScaleAndCenter = function (s, c) {
		this.scale = s;
		this.center = c;
		this.redraw ();
	}
	this.setScale = function (s) {
		this.scale = s;
		this.redraw ();
	}
	this.setCenter = function (c) {
		this.center = c;
		this.redraw ();
	}
	this.getPath = function () {
		if (!this.center) throw "No center defined";
		//TODO accomodate the lack of center coordinate.
		this.projection
			.scale(this.scale)
			.rotate ([-this.center.lon, 0])
			.center ([0, this.center.lat])
			.translate (this.translate);

		return d3.geo.path ().projection (this.projection);
	}
	this.getArc = function () {
		return d3.geo.greatArc().precision(3);
	}
	/*
	this.lineConnectElements = function (elmA, elmB) {
		var path = this.getPath ();
		var arc = this.getArc ();
		var a = d3.select(elmA);

		var centroidA = path.centroid (a.datum ());
		var b = d3.select (elmB);
		var centroidB = path.centroid (b.datum ())
		var links = [];

		links.push ({"source": path.projection().invert (centroidA), "target": path.projection ().invert (centroidB)});
		var layer = this.svg.append ("g").attr ("class", "lineLayer");
		layer.append ("path")
			.data (links)
			.attr ("d", function (x) { return path(arc (x)); })
			.attr ("vector-effect", "non-scaling-stroke")
			.style ({'stroke-width': 1, 'stroke': '#B10000', 'stroke-linejoin': 'round', 'fill': 'none'})
	},
	*/
	this.zoomSelector = null,
	this.zoomContext = 20,
	this.reZoom = function () {
		if (this.zoomSelector != null) {
			this.zoomTo (this.zoomSelector, this.zoomContext);
		}
	},
	this.removeClass = function (selector, cls) {
		this.svg.selectAll (selector).classed (cls, false);
	},
	this.addClass = function (selector, cls) {
		this.svg.selectAll (selector).classed (cls, true);
	}
	this.zoomTo = function (selector, context) {
		if (!context) context = this.context
		var e = this.svg.selectAll (selector);
		if (!e) throw "No element found: " + selector;
		this.zoomSelector = selector;
		this.zoomContext = context;
		var path = this.getPath ();
		var width = this.width;
		var height = this.height;
		var bounds = path.bounds(e.datum ()),
			dx = bounds[1][0] - bounds[0][0],
			dy = bounds[1][1] - bounds[0][1],
			x = (bounds[0][0] + bounds[1][0]) / 2,
			y = (bounds[0][1] + bounds[1][1]) / 2,
			scale = (context / 100) / Math.max(dx / width, dy / height),
			translate = [width * this.refCenter [0] - scale * x, height * this.refCenter [1] - scale * y];

		this.svg
			.selectAll ("path")
			.attr ("vector-effect", "non-scaling-stroke")
			.attr ("transform", "translate(" + translate + ")scale(" + scale + ")");
		this.svg
			.selectAll ("text")
			.attr ("vector-effect", "non-scaling-stroke")
			.attr ("transform", "translate(" + translate + ")scale(" + scale + ")");
		this.svg
			.selectAll ("circle")
			.attr ("vector-effect", "non-scaling-stroke")
			.attr ("transform", "translate(" + translate + ")scale(" + scale + ")")
	}
	this.addFeatures = function (topo, collection, key, quantifier, plot) {
		if (!plot) plot = "lines"
		if (this.topologies [topo]) throw "A topology " + topo + " already exists.";
		if (collection && collection.objects) {
			var features = collection.objects [key];
			if (features) {
				this.svg.append ("g")
					.attr ("class", topo);
				this.topologies [topo] = new ant.charts.map.topology (this.svg, topo, this.getPath (), collection, features);
				this.redraw (topo, quantifier, plot);

				return this.topologies [topo];
			} else {
				throw "No Features found: (" + topo + ")" + key;
			}
		} else {
			throw "Empty features collections? " + topo;
		}
	}
	return this;
};
ant.charts.map.topology = function (cont, name, path, t, f) {
	this.container = cont;
	this.name = name;
	this.topology = t;
	this.features = f;
	this.path = path;
	this.redraw = function (setId, quantifier, plot) {
		this.callbacks = {};
		if (!plot) plot = "lines";
		this.container.select ("g." + this.name).selectAll ("text").remove ();
		var path = this.path;

		var qn = quantifier ? $.proxy (
				function (selector, d, plot) {
					var attrs = quantifier.fn.apply (quantifier.context, [d, quantifier.args, quantifier.data])
					if (attrs) {
						if (plot == "points") {
							attrs.cx = path.centroid (d) [0];
							attrs.cy = path.centroid (d) [1];
						}
						if (attrs.text) {
							var xs = {"x": path.centroid (d)[0], "y": path.centroid (d)[1]};
							d3.select (selector.parentNode)
								.append ("svg:text")
								.attr (xs)
								.attr (attrs)
								.text (attrs.text);
						}
						// This section adds the data-* attributes returned from the quantifier to the element...!!!
						// This allows the cascading of visualizations
						var data = attrs.data;
						attrs.data = null;
						selector.attr (attrs);
						if (data) {
							for (var d in data) {
								var val = data [d];
								if (val === Object (val)) {
									val = JSON.stringify (val);
								}
								selector.attr ("data-" + d, val);
							}
						}
					}
				},
			quantifier) : function (selector, d) { selector.attr ("class", ""); };

		if (plot == "lines") {
			this.container.select ("g." + this.name).selectAll ("path")
				.data (topojson.feature (this.topology, this.features).features)
				.each (function (d) { qn (d3.select (this), d, plot); })
				.attr ("id", setId)
				.attr ("d", function (x) { return path (x); })
				.enter ()
				.append ("path")
				.on ("click", this.createCallback ("click"))
				.on ("mouseover", this.createCallback ("mouseover"))
				.on ("mouseout", this.createCallback ("mouseout"))
		}
		if (plot == "points") {
			this.container.select ("g." + this.name).selectAll ("circle")
				.data (topojson.feature (this.topology, this.features).features)
				.each (function (d) { qn (d3.select (this), d, plot); })
				.attr ("id", setId)
				.enter ()
				.append ("circle")
				.on ("click", this.createCallback ("click"))
				.on ("mouseover", this.createCallback ("mouseover"))
				.on ("mouseout", this.createCallback ("mouseout"))
		}
	}
	this.createCallback = function (type) {
		var me = this;
		return function () {
			var args = [];
			for (var a in arguments) {
				args.push (arguments [a]);
			}
			args.push (this);
			me.callback.apply (me, [type, args]);
		}
	}
	this.callbacks = {};
	this.on = function (ev, cb, scope) {
		if (!this.callbacks [ev]) {
			this.callbacks [ev] = [];
		}
		if (!scope) { scope = this; }
		this.callbacks [ev].push ({ scope: scope, callback: cb});
	}
	this.removeCallback = function (ev, cb) {
		for (var x in this.callbacks [ev]) {
			if (this.callbacks [ev] [x].callback == cb) {
				this.callbacks [ev].splice (x, 1);
			}
		}
	}
	this.callback = function (ev, args) {
		if (!this.callbacks [ev]) return;
		for (cb in this.callbacks [ev]) {
			if (cb) {
				var x = this.callbacks [ev][cb];
				x.callback.apply (x.scope, args);
			}
		}
	}
}
<|endoftext|>


<commit_before>const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
    template: './client/index.html',
    filename: 'index.html',
    inject: 'body'
});

module.exports = {
    entry: './client/index.js',
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: process.env.NODE_ENV === 'production' ? '[name].[chunkhash].js' : '[name].js'
    },
    module: {
        loaders: [
            { test: /\.(t|j)sx?$/, use: { loader: 'awesome-typescript-loader' } },
            { enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
        ]
    },
    resolve: {
        extensions: ['*', '.js', '.jsx', '.ts', '.tsx', '.json']
    },
    plugins: [
        HtmlWebpackPluginConfig,
        new CopyWebpackPlugin([
            { from: 'img', to: 'img' }
        ])
    ],
    devtool: "source-map"
};
<commit_msg>Fixed webpack not detecting changes<commit_after>const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
    template: './client/index.html',
    filename: 'index.html',
    inject: 'body'
});

module.exports = {
    entry: './client/index.js',
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: process.env.NODE_ENV === 'production' ? '[name].[chunkhash].js' : '[name].js'
    },
    module: {
        loaders: [
            { test: /\.(t|j)sx?$/, use: { loader: 'awesome-typescript-loader' } },
            { enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
        ]
    },
    resolve: {
        extensions: ['.ts', '.tsx', '.js', '.jsx', '.json']
    },
    plugins: [
        HtmlWebpackPluginConfig,
        new CopyWebpackPlugin([
            { from: 'img', to: 'img' }
        ])
    ],
    devtool: "source-map"
};
<|endoftext|>


<commit_before>BattleTapez = typeof BattleTapez === "undefined" ? {} : BattleTapez;

BattleTapez.HowToScoreDirective = function () {
    return {
        restrict: 'E',
        templateUrl: '../partials/how-to-score.html'
    };
};<commit_msg>trying to fix a bug in the how to score page<commit_after>BattleTapez = typeof BattleTapez === "undefined" ? {} : BattleTapez;

BattleTapez.HowToScoreDirective = function () {
    return {
        restrict: 'E',
        templateUrl: 'partials/how-to-score.html'
    };
};<|endoftext|>


<commit_before>const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');

const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
    template: './client/index.html',
    filename: 'index.html',
    inject: 'body'
});

module.exports = env => {
    return {
        entry: './client/index.js',
        output: {
            path: path.resolve(__dirname, 'build'),
            filename: process.env.NODE_ENV === 'production' ? '[name].[chunkhash].js' : '[name].js'
        },
        module: {
            rules: [
                { test: /\.(t|j)sx?$/, use: { loader: 'awesome-typescript-loader' } },
                { enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
            ]
        },
        resolve: {
            extensions: ['.ts', '.tsx', '.js', '.jsx', '.json']
        },
        plugins: [
            HtmlWebpackPluginConfig,
            new CopyWebpackPlugin([
                { from: 'img', to: 'img' }
            ]),
            new webpack.EnvironmentPlugin({
                GMAPS_API_KEY: null,
                CCAPI_URL: "http://127.0.0.1:5000"
            })
        ],
        devtool: "source-map"
    }
};
<commit_msg>Only include directories that need to be loaded into a-ts-loader<commit_after>const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');

const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
    template: './client/index.html',
    filename: 'index.html',
    inject: 'body'
});

module.exports = env => {
    return {
        entry: './client/index.js',
        output: {
            path: path.resolve(__dirname, 'build'),
            filename: process.env.NODE_ENV === 'production' ? '[name].[chunkhash].js' : '[name].js'
        },
        module: {
            rules: [
                {
                    test: /\.(t|j)sx?$/,
                    include: [ path.resolve(__dirname, 'client') ],
                    use: { loader: 'awesome-typescript-loader' }
                },
                {
                    enforce: "pre",
                    test: /\.js$/,
                    include: [ path.resolve(__dirname, 'client') ],
                    loader: "source-map-loader"
                }
            ]
        },
        resolve: {
            extensions: ['.ts', '.tsx', '.js', '.jsx', '.json']
        },
        plugins: [
            HtmlWebpackPluginConfig,
            new CopyWebpackPlugin([
                { from: 'img', to: 'img' }
            ]),
            new webpack.EnvironmentPlugin({
                GMAPS_API_KEY: null,
                CCAPI_URL: "http://127.0.0.1:5000"
            })
        ],
        devtool: "source-map"
    }
};
<|endoftext|>


<commit_before>// Copyright 2012 YDN Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Database schema.
 *
 * This data structure is immutable.
 */

goog.provide('ydn.db.schema.Database');
goog.require('ydn.db.Key');
goog.require('ydn.db.schema.Store');
goog.require('ydn.db.schema.fulltext.Catalog');

/**
 *
 * @param {DatabaseSchema|number|string=} opt_version version, if string,
 * it must be parse to int.
 * @param {!Array.<!ydn.db.schema.Store>=} opt_stores store schemas.
 * @constructor
 * @struct
 */
ydn.db.schema.Database = function(opt_version, opt_stores) {

  /**
   * @type {number|undefined}
   */
  var ver;
  /**
   * @type {DatabaseSchema}
   */
  var json;
  var stores = opt_stores;
  if (goog.isObject(opt_version)) {
    json = opt_version;
    if (goog.DEBUG) {
      var fields = ['version', 'stores', 'fullTextCatalogs'];
      for (var key in json) {
        if (json.hasOwnProperty(key) && goog.array.indexOf(fields, key) == -1) {
          throw new ydn.debug.error.ArgumentException('Unknown field: ' + key +
              ' in schema.');
        }
      }
    }
    ver = json['version'];
    stores = [];
    var stores_json = json.stores || [];
    if (goog.DEBUG && !goog.isArray(stores_json)) {
      throw new ydn.debug.error.ArgumentException('stores must be array');
    }
    /**
     * Default ext store name.
     * @type {string|undefined}
     * @private
     */
    this.default_text_store_name_ = json['defaultTextStoreName'];
    for (var i = 0; i < stores_json.length; i++) {
      var store = ydn.db.schema.Store.fromJSON(stores_json[i]);
      if (goog.DEBUG) {
        var idx = goog.array.findIndex(stores, function(x) {
          return x.name == store.getName();
        });
        if (idx != -1) {
          throw new ydn.debug.error.ArgumentException('duplicate store name "' +
              store.getName() + '".');
        }

      }
      stores.push(store);
    }
  } else if (goog.isString(opt_version)) {
    ver = opt_version.length == 0 ?
        undefined : parseFloat(opt_version);
  } else if (goog.isNumber(opt_version)) {
    ver = opt_version;
  }

  if (goog.isDef(ver)) {
    if (!goog.isNumber(ver) || ver < 0) {
      throw new ydn.debug.error.ArgumentException('Invalid version: ' +
          ver + ' (' + opt_version + ')');
    }
    if (isNaN(ver)) {
      ver = undefined;
    }
  }
  if (goog.isDef(opt_stores) && (!goog.isArray(opt_stores) ||
      opt_stores.length > 0 && !(opt_stores[0] instanceof ydn.db.schema.Store)))
  {
    throw new ydn.debug.error.ArgumentException('stores');
  }

  /**
   * @type {number|undefined}
   */
  this.version = ver;

  this.is_auto_version_ = !goog.isDef(this.version);

  /**
   * @final
   * @type {!Array.<!ydn.db.schema.Store>}
   */
  this.stores = stores || [];
  var full_text_indexes = [];
  if (json && json.fullTextCatalogs) {
    goog.asserts.assertArray(json.fullTextCatalogs, 'fullTextCatalogs');
    for (var i = 0; i < json.fullTextCatalogs.length; i++) {
      var full_text_index = ydn.db.schema.fulltext.Catalog.fromJson(
          json.fullTextCatalogs[i]);
      full_text_indexes[i] = full_text_index;
      if (!this.getStore(full_text_index.getName())) {
        var p_indexes = [
          new ydn.db.schema.Index('k', ydn.db.schema.DataType.TEXT),
          new ydn.db.schema.Index('v', ydn.db.schema.DataType.TEXT)
        ];
        var full_text_store_schema = new ydn.db.schema.Store(
            full_text_index.getName(), 'id', false, undefined, p_indexes);
        this.stores.push(full_text_store_schema);
      }
    }
  }
  /**
   * @final
   * @type {Array.<ydn.db.schema.fulltext.Catalog>}
   * @private
   */
  this.full_text_schema_ = full_text_indexes;
};

/**
 * @return {number} number of full text indexes.
 */
ydn.db.schema.Database.prototype.countFullTextIndex = function() {
  return this.full_text_schema_.length;
};

/**
 * @param {number} idx
 * @return {ydn.db.schema.fulltext.Catalog}
 */
ydn.db.schema.Database.prototype.fullTextIndex = function(idx) {
  return this.full_text_schema_[idx];
};

/**
 * @param {string} name
 * @return {ydn.db.schema.fulltext.Catalog}
 */
ydn.db.schema.Database.prototype.getFullTextIndex = function(name) {
  return goog.array.find(this.full_text_schema_, function(x) {
    return x.getName() == name;
  });
};

/**
 * Get default text store.
 * @return string}
 */
ydn.db.schema.Database.prototype.getDefaultTextStoreName = function() {
  goog.asserts.assertString(this.default_text_store_name_,
      'defaultTextStoreName is not defined in the database schema');
  return this.default_text_store_name_;
};

/**
 * @override
 * @return {!DatabaseSchema} database schema in json.
 */
ydn.db.schema.Database.prototype.toJSON = function() {

  var stores = goog.array.map(this.stores, function(x) {return x.toJSON()});

  var sch = /** @type {DatabaseSchema} */ ({});
  sch.stores = stores;
  if (goog.isDef(this.version)) {
    sch.version = this.version;
  }
  return sch;
};

/**
 *
 * @type {boolean} auto version status.
 * @private
 */
ydn.db.schema.Database.prototype.is_auto_version_ = false;

/**
 * Current database version.
 * @type {number|undefined}
 */
ydn.db.schema.Database.prototype.version;

/**
 * Get schema version.
 * @return {number|undefined} version.
 */
ydn.db.schema.Database.prototype.getVersion = function() {
  return this.version;
};

/**
 * Update database schema for auto schema mode.
 * @param {number} version must be number type.
 */
ydn.db.schema.Database.prototype.setVersion = function(version) {
  goog.asserts.assert(this.is_auto_version_,
      'autoversion schema cannot set a version');
  goog.asserts.assertNumber(version, 'version must be a number');
  this.version = version;
};

/**
 *
 * @return {boolean} true if auto version.
 */
ydn.db.schema.Database.prototype.isAutoVersion = function() {
  return this.is_auto_version_;
};

/**
 *
 * @return {boolean} true if auto schema.
 */
ydn.db.schema.Database.prototype.isAutoSchema = function() {
  return false;
};

/**
 *
 * @return {!Array.<string>} list of store names.
 */
ydn.db.schema.Database.prototype.getStoreNames = function() {
  return goog.array.map(this.stores, function(x) {return x.getName();});
};

/**
 *
 * @param {number} idx index of stores.
 * @return {ydn.db.schema.Store} store schema at the index.
 */
ydn.db.schema.Database.prototype.store = function(idx) {
  return this.stores[idx] || null;
};

/**
 *
 * @return {number} number of store.
 */
ydn.db.schema.Database.prototype.count = function() {
  return this.stores.length;
};

/**
 *
 * @param {string} name store name.
 * @return {ydn.db.schema.Store} store if found.
 */
ydn.db.schema.Database.prototype.getStore = function(name) {
  return /** @type {ydn.db.schema.Store} */ (goog.array.find(this.stores,
      function(x) {
        return x.getName() == name;
      }));
};

/**
 * Get index of store.
 * @param {string} name store name.
 * @return {number} index of store -1 if not found.
 */
ydn.db.schema.Database.prototype.getIndexOf = function(name) {
  return goog.array.indexOf(this.stores,
      function(x) {
        return x.name == name;
      });
};

/**
 *
 * @param {string} name store name.
 * @return {boolean} return true if name found in stores.
 */
ydn.db.schema.Database.prototype.hasStore = function(name) {

  return goog.array.some(this.stores, function(x) {
    return x.getName() == name;
  });
};

/**
 * Return an explination what is different between the schemas.
 * @param {ydn.db.schema.Database} schema schema from sniffing.
 * @param {boolean} hint_websql hint the give schema, so that property
 * that could not be reflect from the connection are filled.
 * @param {boolean} hint_idb hint the give schema, so that property
 * that could not be reflect from the connection are filled.
 * @return {string} return empty string if the two are similar.
 */
ydn.db.schema.Database.prototype.difference = function(schema, hint_websql,
                                                       hint_idb) {
  if (!schema || this.stores.length != schema.stores.length) {
    return 'Number of store: ' + this.stores.length + ' vs ' +
        schema.stores.length;
  }
  for (var i = 0; i < this.stores.length; i++) {
    var store = schema.getStore(this.stores[i].getName());
    // hint to sniffed schema, so that some lost info are recovered.
    if (store) {
      if (hint_websql) {
        store = store.hintForWebSql(this.stores[i]);
      }
      if (hint_idb) {
        store.hintForIdb(this.stores[i]);
      }
      var msg = this.stores[i].difference(store);
      if (msg.length > 0) {
        return 'store: "' + this.stores[i].getName() + '" ' + msg;
      }
    } else {
      return 'missing object store "' + this.stores[i].getName() + '"';
    }
  }

  return '';
};

/**
 *
 * @param {ydn.db.schema.Database} schema schema.
 * @return {boolean} true if given schema is similar to this schema.
 */
ydn.db.schema.Database.prototype.similar = function(schema) {
  return this.difference(schema, false, false).length == 0;
};

/**
 * @param name
 * @return {ydn.db.schema.fulltext.Catalog}
 */
ydn.db.schema.Database.prototype.getFullTextSchema = function(name) {
  return goog.array.find(this.full_text_schema_, function(x) {
    return x.getName() == name;
  });
};

/**
 *
 * @return {!Array.<string>} Return list of store names.
 */
ydn.db.schema.Database.prototype.listStores = function() {
  if (!this.store_names) {
    /**
     * @final
     * @type {!Array.<string>}
     */
    this.store_names = goog.array.map(this.stores, function(x) {
      return x.getName();
    });
  }
  return this.store_names;
};
<commit_msg>fulltextsearch table use fixed schema to reduce storage space.<commit_after>// Copyright 2012 YDN Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Database schema.
 *
 * This data structure is immutable.
 */

goog.provide('ydn.db.schema.Database');
goog.require('ydn.db.Key');
goog.require('ydn.db.schema.Store');
goog.require('ydn.db.schema.fulltext.Catalog');

/**
 *
 * @param {DatabaseSchema|number|string=} opt_version version, if string,
 * it must be parse to int.
 * @param {!Array.<!ydn.db.schema.Store>=} opt_stores store schemas.
 * @constructor
 * @struct
 */
ydn.db.schema.Database = function(opt_version, opt_stores) {

  /**
   * @type {number|undefined}
   */
  var ver;
  /**
   * @type {DatabaseSchema}
   */
  var json;
  var stores = opt_stores;
  if (goog.isObject(opt_version)) {
    json = opt_version;
    if (goog.DEBUG) {
      var fields = ['version', 'stores', 'fullTextCatalogs'];
      for (var key in json) {
        if (json.hasOwnProperty(key) && goog.array.indexOf(fields, key) == -1) {
          throw new ydn.debug.error.ArgumentException('Unknown field: ' + key +
              ' in schema.');
        }
      }
    }
    ver = json['version'];
    stores = [];
    var stores_json = json.stores || [];
    if (goog.DEBUG && !goog.isArray(stores_json)) {
      throw new ydn.debug.error.ArgumentException('stores must be array');
    }
    /**
     * Default ext store name.
     * @type {string|undefined}
     * @private
     */
    this.default_text_store_name_ = json['defaultTextStoreName'];
    for (var i = 0; i < stores_json.length; i++) {
      var store = ydn.db.schema.Store.fromJSON(stores_json[i]);
      if (goog.DEBUG) {
        var idx = goog.array.findIndex(stores, function(x) {
          return x.name == store.getName();
        });
        if (idx != -1) {
          throw new ydn.debug.error.ArgumentException('duplicate store name "' +
              store.getName() + '".');
        }

      }
      stores.push(store);
    }
  } else if (goog.isString(opt_version)) {
    ver = opt_version.length == 0 ?
        undefined : parseFloat(opt_version);
  } else if (goog.isNumber(opt_version)) {
    ver = opt_version;
  }

  if (goog.isDef(ver)) {
    if (!goog.isNumber(ver) || ver < 0) {
      throw new ydn.debug.error.ArgumentException('Invalid version: ' +
          ver + ' (' + opt_version + ')');
    }
    if (isNaN(ver)) {
      ver = undefined;
    }
  }
  if (goog.isDef(opt_stores) && (!goog.isArray(opt_stores) ||
      opt_stores.length > 0 && !(opt_stores[0] instanceof ydn.db.schema.Store)))
  {
    throw new ydn.debug.error.ArgumentException('stores');
  }

  /**
   * @type {number|undefined}
   */
  this.version = ver;

  this.is_auto_version_ = !goog.isDef(this.version);

  /**
   * @final
   * @type {!Array.<!ydn.db.schema.Store>}
   */
  this.stores = stores || [];
  var full_text_indexes = [];
  if (json && json.fullTextCatalogs) {
    goog.asserts.assertArray(json.fullTextCatalogs, 'fullTextCatalogs');
    for (var i = 0; i < json.fullTextCatalogs.length; i++) {
      var full_text_index = ydn.db.schema.fulltext.Catalog.fromJson(
          json.fullTextCatalogs[i]);
      full_text_indexes[i] = full_text_index;
      if (!this.getStore(full_text_index.getName())) {
        var p_indexes = [
          new ydn.db.schema.Index('k', ydn.db.schema.DataType.TEXT),
          new ydn.db.schema.Index('v', ydn.db.schema.DataType.TEXT)
        ];
        var full_text_store_schema = new ydn.db.schema.Store(
            full_text_index.getName(), 'id', false, undefined, p_indexes,
            false, true, false);
        this.stores.push(full_text_store_schema);
      }
    }
  }
  /**
   * @final
   * @type {Array.<ydn.db.schema.fulltext.Catalog>}
   * @private
   */
  this.full_text_schema_ = full_text_indexes;
};

/**
 * @return {number} number of full text indexes.
 */
ydn.db.schema.Database.prototype.countFullTextIndex = function() {
  return this.full_text_schema_.length;
};

/**
 * @param {number} idx
 * @return {ydn.db.schema.fulltext.Catalog}
 */
ydn.db.schema.Database.prototype.fullTextIndex = function(idx) {
  return this.full_text_schema_[idx];
};

/**
 * @param {string} name
 * @return {ydn.db.schema.fulltext.Catalog}
 */
ydn.db.schema.Database.prototype.getFullTextIndex = function(name) {
  return goog.array.find(this.full_text_schema_, function(x) {
    return x.getName() == name;
  });
};

/**
 * Get default text store.
 * @return string}
 */
ydn.db.schema.Database.prototype.getDefaultTextStoreName = function() {
  goog.asserts.assertString(this.default_text_store_name_,
      'defaultTextStoreName is not defined in the database schema');
  return this.default_text_store_name_;
};

/**
 * @override
 * @return {!DatabaseSchema} database schema in json.
 */
ydn.db.schema.Database.prototype.toJSON = function() {

  var stores = goog.array.map(this.stores, function(x) {return x.toJSON()});

  var sch = /** @type {DatabaseSchema} */ ({});
  sch.stores = stores;
  if (goog.isDef(this.version)) {
    sch.version = this.version;
  }
  return sch;
};

/**
 *
 * @type {boolean} auto version status.
 * @private
 */
ydn.db.schema.Database.prototype.is_auto_version_ = false;

/**
 * Current database version.
 * @type {number|undefined}
 */
ydn.db.schema.Database.prototype.version;

/**
 * Get schema version.
 * @return {number|undefined} version.
 */
ydn.db.schema.Database.prototype.getVersion = function() {
  return this.version;
};

/**
 * Update database schema for auto schema mode.
 * @param {number} version must be number type.
 */
ydn.db.schema.Database.prototype.setVersion = function(version) {
  goog.asserts.assert(this.is_auto_version_,
      'autoversion schema cannot set a version');
  goog.asserts.assertNumber(version, 'version must be a number');
  this.version = version;
};

/**
 *
 * @return {boolean} true if auto version.
 */
ydn.db.schema.Database.prototype.isAutoVersion = function() {
  return this.is_auto_version_;
};

/**
 *
 * @return {boolean} true if auto schema.
 */
ydn.db.schema.Database.prototype.isAutoSchema = function() {
  return false;
};

/**
 *
 * @return {!Array.<string>} list of store names.
 */
ydn.db.schema.Database.prototype.getStoreNames = function() {
  return goog.array.map(this.stores, function(x) {return x.getName();});
};

/**
 *
 * @param {number} idx index of stores.
 * @return {ydn.db.schema.Store} store schema at the index.
 */
ydn.db.schema.Database.prototype.store = function(idx) {
  return this.stores[idx] || null;
};

/**
 *
 * @return {number} number of store.
 */
ydn.db.schema.Database.prototype.count = function() {
  return this.stores.length;
};

/**
 *
 * @param {string} name store name.
 * @return {ydn.db.schema.Store} store if found.
 */
ydn.db.schema.Database.prototype.getStore = function(name) {
  return /** @type {ydn.db.schema.Store} */ (goog.array.find(this.stores,
      function(x) {
        return x.getName() == name;
      }));
};

/**
 * Get index of store.
 * @param {string} name store name.
 * @return {number} index of store -1 if not found.
 */
ydn.db.schema.Database.prototype.getIndexOf = function(name) {
  return goog.array.indexOf(this.stores,
      function(x) {
        return x.name == name;
      });
};

/**
 *
 * @param {string} name store name.
 * @return {boolean} return true if name found in stores.
 */
ydn.db.schema.Database.prototype.hasStore = function(name) {

  return goog.array.some(this.stores, function(x) {
    return x.getName() == name;
  });
};

/**
 * Return an explination what is different between the schemas.
 * @param {ydn.db.schema.Database} schema schema from sniffing.
 * @param {boolean} hint_websql hint the give schema, so that property
 * that could not be reflect from the connection are filled.
 * @param {boolean} hint_idb hint the give schema, so that property
 * that could not be reflect from the connection are filled.
 * @return {string} return empty string if the two are similar.
 */
ydn.db.schema.Database.prototype.difference = function(schema, hint_websql,
                                                       hint_idb) {
  if (!schema || this.stores.length != schema.stores.length) {
    return 'Number of store: ' + this.stores.length + ' vs ' +
        schema.stores.length;
  }
  for (var i = 0; i < this.stores.length; i++) {
    var store = schema.getStore(this.stores[i].getName());
    // hint to sniffed schema, so that some lost info are recovered.
    if (store) {
      if (hint_websql) {
        store = store.hintForWebSql(this.stores[i]);
      }
      if (hint_idb) {
        store.hintForIdb(this.stores[i]);
      }
      var msg = this.stores[i].difference(store);
      if (msg.length > 0) {
        return 'store: "' + this.stores[i].getName() + '" ' + msg;
      }
    } else {
      return 'missing object store "' + this.stores[i].getName() + '"';
    }
  }

  return '';
};

/**
 *
 * @param {ydn.db.schema.Database} schema schema.
 * @return {boolean} true if given schema is similar to this schema.
 */
ydn.db.schema.Database.prototype.similar = function(schema) {
  return this.difference(schema, false, false).length == 0;
};

/**
 * @param name
 * @return {ydn.db.schema.fulltext.Catalog}
 */
ydn.db.schema.Database.prototype.getFullTextSchema = function(name) {
  return goog.array.find(this.full_text_schema_, function(x) {
    return x.getName() == name;
  });
};

/**
 *
 * @return {!Array.<string>} Return list of store names.
 */
ydn.db.schema.Database.prototype.listStores = function() {
  if (!this.store_names) {
    /**
     * @final
     * @type {!Array.<string>}
     */
    this.store_names = goog.array.map(this.stores, function(x) {
      return x.getName();
    });
  }
  return this.store_names;
};
<|endoftext|>


<commit_before>var types = {"enum": ["pad", "fit", "none"]};

export default {
  "defs": {
    "autosize": {
      "oneOf": [
        types,
        {
          "type": "object",
          "properties": {
            "type": types,
            "resize": {"type": "boolean"},
            "contains": {"enum": ["content", "padding"]}
          },
          "required": ["type"],
          "additionalProperties": false
        }
      ],
      "default": "pad"
    }
  }
};
<commit_msg>Add autosize fit-x, fit-y to schema.<commit_after>var types = {"enum": ["pad", "fit", "fit-x", "fit-y", "none"]};

export default {
  "defs": {
    "autosize": {
      "oneOf": [
        types,
        {
          "type": "object",
          "properties": {
            "type": types,
            "resize": {"type": "boolean"},
            "contains": {"enum": ["content", "padding"]}
          },
          "required": ["type"],
          "additionalProperties": false
        }
      ],
      "default": "pad"
    }
  }
};
<|endoftext|>


<commit_before>import $ from "jquery";

import render_unsubscribe_private_stream_modal from "../templates/confirm_dialog/confirm_unsubscribe_private_stream.hbs";
import render_stream_member_list_entry from "../templates/stream_settings/stream_member_list_entry.hbs";
import render_stream_subscription_request_result from "../templates/stream_settings/stream_subscription_request_result.hbs";

import * as blueslip from "./blueslip";
import * as channel from "./channel";
import * as confirm_dialog from "./confirm_dialog";
import * as hash_util from "./hash_util";
import {$t, $t_html} from "./i18n";
import * as input_pill from "./input_pill";
import * as ListWidget from "./list_widget";
import {page_params} from "./page_params";
import * as peer_data from "./peer_data";
import * as people from "./people";
import * as pill_typeahead from "./pill_typeahead";
import * as settings_data from "./settings_data";
import * as stream_data from "./stream_data";
import * as stream_pill from "./stream_pill";
import * as sub_store from "./sub_store";
import * as ui from "./ui";
import * as user_group_pill from "./user_group_pill";
import * as user_pill from "./user_pill";

export let pill_widget;
let current_stream_id;
let subscribers_list_widget;

function create_item_from_text(text, current_items) {
    const funcs = [
        stream_pill.create_item_from_stream_name,
        user_group_pill.create_item_from_group_name,
        user_pill.create_item_from_email,
    ];
    for (const func of funcs) {
        const item = func(text, current_items);
        if (item) {
            return item;
        }
    }
    return undefined;
}

function get_text_from_item(item) {
    const funcs = [
        stream_pill.get_stream_name_from_item,
        user_group_pill.get_group_name_from_item,
        user_pill.get_email_from_item,
    ];
    for (const func of funcs) {
        const text = func(item);
        if (text) {
            return text;
        }
    }
    return undefined;
}

function set_up_pill_typeahead({pill_container, get_users}) {
    const opts = {
        user_source: get_users,
        stream: true,
        user_group: true,
        user: true,
    };
    pill_typeahead.set_up(pill_container.find(".input"), pill_widget, opts);
}

function format_member_list_elem(person) {
    return render_stream_member_list_entry({
        name: person.full_name,
        user_id: person.user_id,
        email: settings_data.email_for_user_settings(person),
        displaying_for_admin: page_params.is_admin,
        show_email: settings_data.show_email(),
    });
}

function get_sub(stream_id) {
    const sub = sub_store.get(stream_id);
    if (!sub) {
        blueslip.error("get_sub() failed id lookup: " + stream_id);
        return undefined;
    }
    return sub;
}

function show_stream_subscription_request_result({
    message,
    add_class,
    remove_class,
    subscribed_users,
    already_subscribed_users,
    ignored_deactivated_users,
}) {
    const stream_subscription_req_result_elem = $(
        ".stream_subscription_request_result",
    ).expectOne();
    const html = render_stream_subscription_request_result({
        message,
        subscribed_users,
        already_subscribed_users,
        ignored_deactivated_users,
    });
    ui.get_content_element(stream_subscription_req_result_elem).html(html);
    if (add_class) {
        stream_subscription_req_result_elem.addClass(add_class);
    }
    if (remove_class) {
        stream_subscription_req_result_elem.removeClass(remove_class);
    }
}

export function enable_subscriber_management({sub, parent_container}) {
    const stream_id = sub.stream_id;

    const pill_container = parent_container.find(".pill-container");

    // current_stream_id and pill_widget are module-level variables
    current_stream_id = stream_id;

    pill_widget = input_pill.create({
        container: pill_container,
        create_item_from_text,
        get_text_from_item,
    });

    function get_users_for_subscriber_typeahead() {
        const potential_subscribers = peer_data.potential_subscribers(stream_id);
        return user_pill.filter_taken_users(potential_subscribers, pill_widget);
    }

    set_up_pill_typeahead({pill_container, get_users: get_users_for_subscriber_typeahead});

    const user_ids = peer_data.get_subscribers(stream_id);

    // We track a single subscribers_list_widget for this module, since we
    // only ever have one list of subscribers visible at a time.
    subscribers_list_widget = make_list_widget({
        parent_container,
        name: "stream_subscribers",
        user_ids,
    });
}

function make_list_widget({parent_container, name, user_ids}) {
    const users = people.get_users_from_ids(user_ids);
    people.sort_but_pin_current_user_on_top(users);

    const list_container = parent_container.find(".subscriber_table");
    list_container.empty();

    const simplebar_container = parent_container.find(".subscriber_list_container");

    return ListWidget.create(list_container, users, {
        name,
        modifier(item) {
            return format_member_list_elem(item);
        },
        filter: {
            element: parent_container.find(".search"),
            predicate(person, value) {
                const matcher = people.build_person_matcher(value);
                const match = matcher(person);

                return match;
            },
        },
        simplebar_container,
    });
}

export function invite_user_to_stream(user_ids, sub, success, failure) {
    // TODO: use stream_id when backend supports it
    const stream_name = sub.name;
    return channel.post({
        url: "/json/users/me/subscriptions",
        data: {
            subscriptions: JSON.stringify([{name: stream_name}]),
            principals: JSON.stringify(user_ids),
        },
        success,
        error: failure,
    });
}

export function remove_user_from_stream(user_id, sub, success, failure) {
    // TODO: use stream_id when backend supports it
    const stream_name = sub.name;
    return channel.del({
        url: "/json/users/me/subscriptions",
        data: {subscriptions: JSON.stringify([stream_name]), principals: JSON.stringify([user_id])},
        success,
        error: failure,
    });
}

function submit_add_subscriber_form(stream_id) {
    const sub = get_sub(stream_id);
    if (!sub) {
        return;
    }

    let user_ids = user_pill.get_user_ids(pill_widget);
    user_ids = user_ids.concat(stream_pill.get_user_ids(pill_widget));
    user_ids = user_ids.concat(user_group_pill.get_user_ids(pill_widget));
    const deactivated_users = new Set();
    user_ids = user_ids.filter((user_id) => {
        if (!people.is_person_active(user_id)) {
            deactivated_users.add(user_id);
            return false;
        }
        return true;
    });

    user_ids = new Set(user_ids);

    if (user_ids.has(page_params.user_id) && sub.subscribed) {
        // We don't want to send a request to subscribe ourselves
        // if we are already subscribed to this stream. This
        // case occurs when creating user pills from a stream.
        user_ids.delete(page_params.user_id);
    }
    let ignored_deactivated_users;
    if (deactivated_users.size > 0) {
        ignored_deactivated_users = Array.from(deactivated_users);
        ignored_deactivated_users = ignored_deactivated_users.map((user_id) =>
            people.get_by_user_id(user_id),
        );
    }
    if (user_ids.size === 0) {
        show_stream_subscription_request_result({
            message: $t({defaultMessage: "No user to subscribe."}),
            add_class: "text-error",
            remove_class: "text-success",
            ignored_deactivated_users,
        });
        return;
    }
    user_ids = Array.from(user_ids);

    function invite_success(data) {
        pill_widget.clear();
        const subscribed_users = Object.keys(data.subscribed).map((email) =>
            people.get_by_email(email),
        );
        const already_subscribed_users = Object.keys(data.already_subscribed).map((email) =>
            people.get_by_email(email),
        );

        show_stream_subscription_request_result({
            add_class: "text-success",
            remove_class: "text-error",
            subscribed_users,
            already_subscribed_users,
            ignored_deactivated_users,
        });
    }

    function invite_failure(xhr) {
        const error = JSON.parse(xhr.responseText);
        show_stream_subscription_request_result({
            message: error.msg,
            add_class: "text-error",
            remove_class: "text-success",
        });
    }

    invite_user_to_stream(user_ids, sub, invite_success, invite_failure);
}

function remove_subscriber({stream_id, target_user_id, list_entry}) {
    const sub = get_sub(stream_id);
    if (!sub) {
        return;
    }

    function removal_success(data) {
        let message;

        if (stream_id !== current_stream_id) {
            blueslip.info("Response for subscription removal came too late.");
            return;
        }

        if (data.removed.length > 0) {
            // Remove the user from the subscriber list.
            list_entry.remove();
            message = $t({defaultMessage: "Unsubscribed successfully!"});
            // The rest of the work is done via the subscription -> remove event we will get
        } else {
            message = $t({defaultMessage: "User is already not subscribed."});
        }
        show_stream_subscription_request_result({
            message,
            add_class: "text-success",
            remove_class: "text-remove",
        });
    }

    function removal_failure() {
        show_stream_subscription_request_result({
            message: $t({defaultMessage: "Error removing user from this stream."}),
            add_class: "text-error",
            remove_class: "text-success",
        });
    }

    function remove_user_from_private_stream() {
        remove_user_from_stream(target_user_id, sub, removal_success, removal_failure);
    }

    if (sub.invite_only && people.is_my_user_id(target_user_id)) {
        const html_body = render_unsubscribe_private_stream_modal();

        confirm_dialog.launch({
            html_heading: $t_html(
                {defaultMessage: "Unsubscribe from {stream_name}"},
                {stream_name: sub.name},
            ),
            html_body,
            on_click: remove_user_from_private_stream,
        });
        return;
    }

    remove_user_from_stream(target_user_id, sub, removal_success, removal_failure);
}

export function update_subscribers_list(sub) {
    // This is for the "Stream membership" section of the right panel.
    // Render subscriptions only if stream settings is open
    if (!hash_util.is_editing_stream(sub.stream_id)) {
        blueslip.info("ignoring subscription for stream that is no longer being edited");
        return;
    }

    if (sub.stream_id !== current_stream_id) {
        // This should never happen if the prior check works correctly.
        blueslip.error("current_stream_id does not match sub.stream_id for some reason");
        return;
    }

    if (!stream_data.can_view_subscribers(sub)) {
        $(".subscriber_list_settings_container").hide();
    } else {
        // Re-render the whole list when we add new users.  This is
        // inefficient for the single-user case, but using the big-hammer
        // approach is superior when you do things like add subscribers
        // from an existing stream or a user group.
        const subscriber_ids = peer_data.get_subscribers(sub.stream_id);
        update_subscribers_list_widget(subscriber_ids);
        $(".subscriber_list_settings_container").show();
    }
}

function update_subscribers_list_widget(subscriber_ids) {
    // This re-renders the subscribers_list_widget with a new
    // list of subscriber_ids.
    const users = people.get_users_from_ids(subscriber_ids);
    people.sort_but_pin_current_user_on_top(users);
    subscribers_list_widget.replace_list_data(users);
}

export function initialize() {
    $("#manage_streams_container").on(
        "keyup",
        ".edit_subscribers_for_stream .subscriber_list_add form",
        (e) => {
            if (e.key === "Enter") {
                e.preventDefault();
                submit_add_subscriber_form(current_stream_id);
            }
        },
    );

    $("#manage_streams_container").on(
        "submit",
        ".edit_subscribers_for_stream .subscriber_list_add form",
        (e) => {
            e.preventDefault();
            submit_add_subscriber_form(current_stream_id);
        },
    );

    $("#manage_streams_container").on(
        "submit",
        ".edit_subscribers_for_stream .subscriber_list_remove form",
        (e) => {
            e.preventDefault();

            const list_entry = $(e.target).closest("tr");
            const target_user_id = Number.parseInt(list_entry.attr("data-subscriber-id"), 10);
            const stream_id = current_stream_id;

            remove_subscriber({stream_id, target_user_id, list_entry});
        },
    );
}
<commit_msg>subscribers: Extract get_pill_user_ids().<commit_after>import $ from "jquery";

import render_unsubscribe_private_stream_modal from "../templates/confirm_dialog/confirm_unsubscribe_private_stream.hbs";
import render_stream_member_list_entry from "../templates/stream_settings/stream_member_list_entry.hbs";
import render_stream_subscription_request_result from "../templates/stream_settings/stream_subscription_request_result.hbs";

import * as blueslip from "./blueslip";
import * as channel from "./channel";
import * as confirm_dialog from "./confirm_dialog";
import * as hash_util from "./hash_util";
import {$t, $t_html} from "./i18n";
import * as input_pill from "./input_pill";
import * as ListWidget from "./list_widget";
import {page_params} from "./page_params";
import * as peer_data from "./peer_data";
import * as people from "./people";
import * as pill_typeahead from "./pill_typeahead";
import * as settings_data from "./settings_data";
import * as stream_data from "./stream_data";
import * as stream_pill from "./stream_pill";
import * as sub_store from "./sub_store";
import * as ui from "./ui";
import * as user_group_pill from "./user_group_pill";
import * as user_pill from "./user_pill";

export let pill_widget;
let current_stream_id;
let subscribers_list_widget;

function create_item_from_text(text, current_items) {
    const funcs = [
        stream_pill.create_item_from_stream_name,
        user_group_pill.create_item_from_group_name,
        user_pill.create_item_from_email,
    ];
    for (const func of funcs) {
        const item = func(text, current_items);
        if (item) {
            return item;
        }
    }
    return undefined;
}

function get_text_from_item(item) {
    const funcs = [
        stream_pill.get_stream_name_from_item,
        user_group_pill.get_group_name_from_item,
        user_pill.get_email_from_item,
    ];
    for (const func of funcs) {
        const text = func(item);
        if (text) {
            return text;
        }
    }
    return undefined;
}

function set_up_pill_typeahead({pill_container, get_users}) {
    const opts = {
        user_source: get_users,
        stream: true,
        user_group: true,
        user: true,
    };
    pill_typeahead.set_up(pill_container.find(".input"), pill_widget, opts);
}

function format_member_list_elem(person) {
    return render_stream_member_list_entry({
        name: person.full_name,
        user_id: person.user_id,
        email: settings_data.email_for_user_settings(person),
        displaying_for_admin: page_params.is_admin,
        show_email: settings_data.show_email(),
    });
}

function get_sub(stream_id) {
    const sub = sub_store.get(stream_id);
    if (!sub) {
        blueslip.error("get_sub() failed id lookup: " + stream_id);
        return undefined;
    }
    return sub;
}

function show_stream_subscription_request_result({
    message,
    add_class,
    remove_class,
    subscribed_users,
    already_subscribed_users,
    ignored_deactivated_users,
}) {
    const stream_subscription_req_result_elem = $(
        ".stream_subscription_request_result",
    ).expectOne();
    const html = render_stream_subscription_request_result({
        message,
        subscribed_users,
        already_subscribed_users,
        ignored_deactivated_users,
    });
    ui.get_content_element(stream_subscription_req_result_elem).html(html);
    if (add_class) {
        stream_subscription_req_result_elem.addClass(add_class);
    }
    if (remove_class) {
        stream_subscription_req_result_elem.removeClass(remove_class);
    }
}

export function enable_subscriber_management({sub, parent_container}) {
    const stream_id = sub.stream_id;

    const pill_container = parent_container.find(".pill-container");

    // current_stream_id and pill_widget are module-level variables
    current_stream_id = stream_id;

    pill_widget = input_pill.create({
        container: pill_container,
        create_item_from_text,
        get_text_from_item,
    });

    function get_users_for_subscriber_typeahead() {
        const potential_subscribers = peer_data.potential_subscribers(stream_id);
        return user_pill.filter_taken_users(potential_subscribers, pill_widget);
    }

    set_up_pill_typeahead({pill_container, get_users: get_users_for_subscriber_typeahead});

    const user_ids = peer_data.get_subscribers(stream_id);

    // We track a single subscribers_list_widget for this module, since we
    // only ever have one list of subscribers visible at a time.
    subscribers_list_widget = make_list_widget({
        parent_container,
        name: "stream_subscribers",
        user_ids,
    });
}

function make_list_widget({parent_container, name, user_ids}) {
    const users = people.get_users_from_ids(user_ids);
    people.sort_but_pin_current_user_on_top(users);

    const list_container = parent_container.find(".subscriber_table");
    list_container.empty();

    const simplebar_container = parent_container.find(".subscriber_list_container");

    return ListWidget.create(list_container, users, {
        name,
        modifier(item) {
            return format_member_list_elem(item);
        },
        filter: {
            element: parent_container.find(".search"),
            predicate(person, value) {
                const matcher = people.build_person_matcher(value);
                const match = matcher(person);

                return match;
            },
        },
        simplebar_container,
    });
}

export function invite_user_to_stream(user_ids, sub, success, failure) {
    // TODO: use stream_id when backend supports it
    const stream_name = sub.name;
    return channel.post({
        url: "/json/users/me/subscriptions",
        data: {
            subscriptions: JSON.stringify([{name: stream_name}]),
            principals: JSON.stringify(user_ids),
        },
        success,
        error: failure,
    });
}

export function remove_user_from_stream(user_id, sub, success, failure) {
    // TODO: use stream_id when backend supports it
    const stream_name = sub.name;
    return channel.del({
        url: "/json/users/me/subscriptions",
        data: {subscriptions: JSON.stringify([stream_name]), principals: JSON.stringify([user_id])},
        success,
        error: failure,
    });
}

export function get_pill_user_ids() {
    const user_ids = user_pill.get_user_ids(pill_widget);
    const stream_user_ids = stream_pill.get_user_ids(pill_widget);
    const group_user_ids = user_group_pill.get_user_ids(pill_widget);
    return [...user_ids, ...stream_user_ids, ...group_user_ids];
}

function submit_add_subscriber_form(stream_id) {
    const sub = get_sub(stream_id);
    if (!sub) {
        return;
    }

    const pill_user_ids = get_pill_user_ids();

    const deactivated_users = new Set();
    const active_user_ids = pill_user_ids.filter((user_id) => {
        if (!people.is_person_active(user_id)) {
            deactivated_users.add(user_id);
            return false;
        }
        return true;
    });

    const user_id_set = new Set(active_user_ids);

    if (user_id_set.has(page_params.user_id) && sub.subscribed) {
        // We don't want to send a request to subscribe ourselves
        // if we are already subscribed to this stream. This
        // case occurs when creating user pills from a stream.
        user_id_set.delete(page_params.user_id);
    }
    let ignored_deactivated_users;
    if (deactivated_users.size > 0) {
        ignored_deactivated_users = Array.from(deactivated_users);
        ignored_deactivated_users = ignored_deactivated_users.map((user_id) =>
            people.get_by_user_id(user_id),
        );
    }
    if (user_id_set.size === 0) {
        show_stream_subscription_request_result({
            message: $t({defaultMessage: "No user to subscribe."}),
            add_class: "text-error",
            remove_class: "text-success",
            ignored_deactivated_users,
        });
        return;
    }

    const user_ids = Array.from(user_id_set);

    function invite_success(data) {
        pill_widget.clear();
        const subscribed_users = Object.keys(data.subscribed).map((email) =>
            people.get_by_email(email),
        );
        const already_subscribed_users = Object.keys(data.already_subscribed).map((email) =>
            people.get_by_email(email),
        );

        show_stream_subscription_request_result({
            add_class: "text-success",
            remove_class: "text-error",
            subscribed_users,
            already_subscribed_users,
            ignored_deactivated_users,
        });
    }

    function invite_failure(xhr) {
        const error = JSON.parse(xhr.responseText);
        show_stream_subscription_request_result({
            message: error.msg,
            add_class: "text-error",
            remove_class: "text-success",
        });
    }

    invite_user_to_stream(user_ids, sub, invite_success, invite_failure);
}

function remove_subscriber({stream_id, target_user_id, list_entry}) {
    const sub = get_sub(stream_id);
    if (!sub) {
        return;
    }

    function removal_success(data) {
        let message;

        if (stream_id !== current_stream_id) {
            blueslip.info("Response for subscription removal came too late.");
            return;
        }

        if (data.removed.length > 0) {
            // Remove the user from the subscriber list.
            list_entry.remove();
            message = $t({defaultMessage: "Unsubscribed successfully!"});
            // The rest of the work is done via the subscription -> remove event we will get
        } else {
            message = $t({defaultMessage: "User is already not subscribed."});
        }
        show_stream_subscription_request_result({
            message,
            add_class: "text-success",
            remove_class: "text-remove",
        });
    }

    function removal_failure() {
        show_stream_subscription_request_result({
            message: $t({defaultMessage: "Error removing user from this stream."}),
            add_class: "text-error",
            remove_class: "text-success",
        });
    }

    function remove_user_from_private_stream() {
        remove_user_from_stream(target_user_id, sub, removal_success, removal_failure);
    }

    if (sub.invite_only && people.is_my_user_id(target_user_id)) {
        const html_body = render_unsubscribe_private_stream_modal();

        confirm_dialog.launch({
            html_heading: $t_html(
                {defaultMessage: "Unsubscribe from {stream_name}"},
                {stream_name: sub.name},
            ),
            html_body,
            on_click: remove_user_from_private_stream,
        });
        return;
    }

    remove_user_from_stream(target_user_id, sub, removal_success, removal_failure);
}

export function update_subscribers_list(sub) {
    // This is for the "Stream membership" section of the right panel.
    // Render subscriptions only if stream settings is open
    if (!hash_util.is_editing_stream(sub.stream_id)) {
        blueslip.info("ignoring subscription for stream that is no longer being edited");
        return;
    }

    if (sub.stream_id !== current_stream_id) {
        // This should never happen if the prior check works correctly.
        blueslip.error("current_stream_id does not match sub.stream_id for some reason");
        return;
    }

    if (!stream_data.can_view_subscribers(sub)) {
        $(".subscriber_list_settings_container").hide();
    } else {
        // Re-render the whole list when we add new users.  This is
        // inefficient for the single-user case, but using the big-hammer
        // approach is superior when you do things like add subscribers
        // from an existing stream or a user group.
        const subscriber_ids = peer_data.get_subscribers(sub.stream_id);
        update_subscribers_list_widget(subscriber_ids);
        $(".subscriber_list_settings_container").show();
    }
}

function update_subscribers_list_widget(subscriber_ids) {
    // This re-renders the subscribers_list_widget with a new
    // list of subscriber_ids.
    const users = people.get_users_from_ids(subscriber_ids);
    people.sort_but_pin_current_user_on_top(users);
    subscribers_list_widget.replace_list_data(users);
}

export function initialize() {
    $("#manage_streams_container").on(
        "keyup",
        ".edit_subscribers_for_stream .subscriber_list_add form",
        (e) => {
            if (e.key === "Enter") {
                e.preventDefault();
                submit_add_subscriber_form(current_stream_id);
            }
        },
    );

    $("#manage_streams_container").on(
        "submit",
        ".edit_subscribers_for_stream .subscriber_list_add form",
        (e) => {
            e.preventDefault();
            submit_add_subscriber_form(current_stream_id);
        },
    );

    $("#manage_streams_container").on(
        "submit",
        ".edit_subscribers_for_stream .subscriber_list_remove form",
        (e) => {
            e.preventDefault();

            const list_entry = $(e.target).closest("tr");
            const target_user_id = Number.parseInt(list_entry.attr("data-subscriber-id"), 10);
            const stream_id = current_stream_id;

            remove_subscriber({stream_id, target_user_id, list_entry});
        },
    );
}
<|endoftext|>


<commit_before>import { existyValue } from '../lib/helpers';
import cached from './fields/cached';
import DayScheduleType from './day_schedule';
import {
  GraphQLString,
  GraphQLObjectType,
  GraphQLFloat,
  GraphQLList,
} from 'graphql';

const LocationType = new GraphQLObjectType({
  name: 'Location',
  fields: () => ({
    cached,
    id: {
      type: GraphQLString,
    },
    city: {
      type: GraphQLString,
    },
    country: {
      type: GraphQLString,
    },
    coordinates: {
      type: new GraphQLObjectType({
        name: 'coordinates',
        fields: {
          lat: {
            type: GraphQLFloat,
          },
          lng: {
            type: GraphQLFloat,
          },
        },
      }),
    },
    display: {
      type: GraphQLString,
    },
    address: {
      type: GraphQLString,
    },
    address_2: {
      type: GraphQLString,
    },
    postal_code: {
      type: GraphQLString,
    },
    state: {
      type: GraphQLString,
    },
    phone: {
      type: GraphQLString,
      resolve: ({ phone }) => existyValue(phone),
    },
    day_schedules: {
      type: new GraphQLList(DayScheduleType),
      resolve: ({ day_schedules }) => day_schedules,
    },
  }),
});

const Location = {
  type: LocationType,
  description: 'A Location',
};

export default Location;
<commit_msg>Force existence of city<commit_after>import { existyValue } from '../lib/helpers';
import cached from './fields/cached';
import DayScheduleType from './day_schedule';
import {
  GraphQLString,
  GraphQLObjectType,
  GraphQLFloat,
  GraphQLList,
} from 'graphql';

const LocationType = new GraphQLObjectType({
  name: 'Location',
  fields: () => ({
    cached,
    id: {
      type: GraphQLString,
    },
    city: {
      type: GraphQLString,
      resolve: ({ city }) => existyValue(city),
    },
    country: {
      type: GraphQLString,
    },
    coordinates: {
      type: new GraphQLObjectType({
        name: 'coordinates',
        fields: {
          lat: {
            type: GraphQLFloat,
          },
          lng: {
            type: GraphQLFloat,
          },
        },
      }),
    },
    display: {
      type: GraphQLString,
    },
    address: {
      type: GraphQLString,
    },
    address_2: {
      type: GraphQLString,
    },
    postal_code: {
      type: GraphQLString,
    },
    state: {
      type: GraphQLString,
    },
    phone: {
      type: GraphQLString,
      resolve: ({ phone }) => existyValue(phone),
    },
    day_schedules: {
      type: new GraphQLList(DayScheduleType),
      resolve: ({ day_schedules }) => day_schedules,
    },
  }),
});

const Location = {
  type: LocationType,
  description: 'A Location',
};

export default Location;
<|endoftext|>


<commit_before>$(document).ready(function(){

	// slide down sub menu bar from head_panel
	$('#head_panel_main').mouseover(function() {
		$('#submenu').slideDown('slow', function() {
		});
		$('#submenu_docs').slideUp('slow');
	});

	// hide sub menu when mouse leave
	$('#mouseleave').mouseleave(function() {
		$('#submenu').slideUp('slow');
	});

	// slide down sub menu bar from head_panel
	$('#head_panel_docs').mouseover(function() {
		$('#submenu_docs').slideDown('slow', function() {
		});
		$('#submenu').slideUp('slow');
	});

	// hide sub menu when mouse leave
	$('#mouseleave').mouseleave(function() {
		$('#submenu_docs').slideUp('slow');
	});

	// toggle display method on team/index.html
	$("#toggle_display").click(function () {
		$("#sortbygroup").toggle();
		$("#sortbyname").toggle();
		$("#listbygroup").toggle();
		$("#listbyname").toggle();
	});

});

<commit_msg>drop down menu no longer piles up<commit_after>$(document).ready(function(){

	// slide down sub menu bar from head_panel
	$('#head_panel_main').mouseover(function() {
		$('#submenu_docs').slideUp('slow');
		$('#submenu').slideDown('slow', function() {
		});
	});

	// hide sub menu when mouse leave
	$('#mouseleave').mouseleave(function() {
		$('#submenu').slideUp('slow');
	});

	// slide down sub menu bar from head_panel
	$('#head_panel_docs').mouseover(function() {
		$('#submenu').slideUp('slow');
		$('#submenu_docs').slideDown('slow', function() {
		});
	});

	// hide sub menu when mouse leave
	$('#mouseleave').mouseleave(function() {
		$('#submenu_docs').slideUp('slow');
	});

	// toggle display method on team/index.html
	$("#toggle_display").click(function () {
		$("#sortbygroup").toggle();
		$("#sortbyname").toggle();
		$("#listbygroup").toggle();
		$("#listbyname").toggle();
	});

});

<|endoftext|>


<commit_before>/**
 * Copyright 2012 Joyent, Inc.  All rights reserved.
 *
 * An image in SDC IMGAPI.
 */

var util = require('util'),
    format = util.format;
var ldap = require('ldapjs');

var Validator = require('../lib/schema/validator');

var UUID_RE = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;

//---- API

function SDCImage() {
    Validator.call(this, {
        name: 'sdcimage',
        required: {
            v: 1,
            uuid: 1,
            name: 1,
            owner: 1,
            disabled: 1,
            type: 1,
            os: 1,
            type: 1,
            activated: 1
        },
        optional: {
            published_at: 1,
            files: 1,
            description: 1,
            requirements: 1,
            acl: 0,  /* zero or more */
            datacenter: 0,  /* one or more */
            urn: 1  /* DEPRECATED */
        }
    });
}
util.inherits(SDCImage, Validator);

SDCImage.prototype.validate = function validate(entry, callback) {
    // Leaving validation to IMGAPI.
    return callback();
};

///--- Exports

module.exports = {
    createInstance: function createInstance() {
        return new SDCImage();
    }
};
<commit_msg>IMGAPI-93: require a 'state' field on sdcimage objects<commit_after>/**
 * Copyright 2012 Joyent, Inc.  All rights reserved.
 *
 * An image in SDC IMGAPI.
 */

var util = require('util'),
    format = util.format;
var ldap = require('ldapjs');

var Validator = require('../lib/schema/validator');

var UUID_RE = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;

//---- API

function SDCImage() {
    Validator.call(this, {
        name: 'sdcimage',
        required: {
            v: 1,
            uuid: 1,
            name: 1,
            owner: 1,
            disabled: 1,
            type: 1,
            os: 1,
            type: 1,
            activated: 1,
            state: 1
        },
        optional: {
            published_at: 1,
            files: 1,
            description: 1,
            requirements: 1,
            acl: 0,  /* zero or more */
            datacenter: 0,  /* one or more */
            urn: 1  /* DEPRECATED */
        }
    });
}
util.inherits(SDCImage, Validator);

SDCImage.prototype.validate = function validate(entry, callback) {
    // Leaving validation to IMGAPI.
    return callback();
};

///--- Exports

module.exports = {
    createInstance: function createInstance() {
        return new SDCImage();
    }
};
<|endoftext|>


<commit_before>define('lyria/checkpoints', ['eventmap', 'mixer', 'deleteitem', 'performance'], function(EventMap, mixer, deleteItem, performance) {

  var Checkpoints = (function() {

    /**
     * Checkpoints constructor
     *
     * @class Checkpoints
     * @constructor
     */
    var Checkpoints = function() {
      // Mix-in eventmap
      mixer([this, Checkpoints.prototype], new EventMap());

      // Set start time
      this.startTime = performance.now();

      // List of all passed checkpoints
      this.checkpointList = [];
    };

    /**
     * Pass a checkpoint
     *
     * @param {String} name
     */
    Checkpoints.prototype.pass = function(name) {
      // A checkpoint can only be passed once
      if (this.hasPassed(name)) {
        return;
      }

      this.checkpointList.push(name);

      this.trigger('pass', name, (performance.now() - this.startTime));
    };

    /**
     * Passes a checkpoint
     *
     * @param {String} name
     */
    Checkpoints.prototype.hasPassed = function(name) {
      return (this.checkpointList.indexOf(name) !== -1);
    };

    /**
     * Reset a single or all checkpoints
     *
     * @param {String} name
     */
    Checkpoints.prototype.reset = function(name) {
      if (this.checkpointList.length === 0) {
        return;
      }

      if (name == null) {
        var oldList = this.checkpointList;
        this.checkpointList = [];
        this.trigger('reset', oldList);
        return;
      }

      var index = this.checkpointList.indexOf(name);

      if (index === -1) {
        return;
      }

      this.checkpointList = deleteItem(this.checkpointList, index);
      this.trigger('reset', name);
    };

    return Checkpoints;
  })();

  return Checkpoints;

});
<commit_msg>lyria/checkpoints is now an anonymous module<commit_after>define(['eventmap', 'mixer', 'deleteitem', 'performance'], function(EventMap, mixer, deleteItem, performance) {

  var Checkpoints = (function() {

    /**
     * Checkpoints constructor
     *
     * @class Checkpoints
     * @constructor
     */
    var Checkpoints = function() {
      // Mix-in eventmap
      mixer([this, Checkpoints.prototype], new EventMap());

      // Set start time
      this.startTime = performance.now();

      // List of all passed checkpoints
      this.checkpointList = [];
    };

    /**
     * Pass a checkpoint
     *
     * @param {String} name
     */
    Checkpoints.prototype.pass = function(name) {
      // A checkpoint can only be passed once
      if (this.hasPassed(name)) {
        return;
      }

      this.checkpointList.push(name);

      this.trigger('pass', name, (performance.now() - this.startTime));
    };

    /**
     * Passes a checkpoint
     *
     * @param {String} name
     */
    Checkpoints.prototype.hasPassed = function(name) {
      return (this.checkpointList.indexOf(name) !== -1);
    };

    /**
     * Reset a single or all checkpoints
     *
     * @param {String} name
     */
    Checkpoints.prototype.reset = function(name) {
      if (this.checkpointList.length === 0) {
        return;
      }

      if (name == null) {
        var oldList = this.checkpointList;
        this.checkpointList = [];
        this.trigger('reset', oldList);
        return;
      }

      var index = this.checkpointList.indexOf(name);

      if (index === -1) {
        return;
      }

      this.checkpointList = deleteItem(this.checkpointList, index);
      this.trigger('reset', name);
    };

    return Checkpoints;
  })();

  return Checkpoints;

});
<|endoftext|>


<commit_before>/**
 * Constant that identifies the map canvas.
 * @type {string}
 */
var MAP_ELEMENT = "map_canvas";

/**
 * Callback that is called when the location is successfully retrieved.
 * @param position
 */
function successLocationCallback (position) {
	//success callback
	userLocation.moveToLocation(position.coords.latitude, position.coords.longitude);
	if (!userLocation.positionMarker) {
		userLocation.positionMarker = new google.maps.Marker({
			position: userLocation.map.getCenter(),
			map: userLocation.map,
			clickable: false,
			icon: "static/stadtgedaechtnis/img/marker_position.png"
		});
	}
	//TODO: maybe add accuracy?
}

/**
 * Callback that is called when the location couldn't be retrieved.
 * @param error
 */
function errorLocationCallback (error) {
	// error callback
	alert(error.id);
	userLocation.moveToLocation(this.DEFAULT_LAT, this.DEFAULT_LONG);
	//TODO: show hint that location couldn't be retrieved
}

/**
 * Location object to enable/disable tracking the location and to retrieve the current or fallback location.
 * @param trackLocation
 * @constructor
 */
function Location() {
	this.DEFAULT_LAT = 50.258;
	this.DEFAULT_LONG = 10.965;
	this.DEFAULT_LOCATION = new google.maps.LatLng(50.258, 10.965);

	this.currentLocation = this.DEFAULT_LOCATION;
	this.positionMarker = null;

	var trackingID;
	var tracking = false;

	/**
	 * enable location tracking
	 */
	this.__defineGetter__("trackLocation", function () {
		return tracking;
	})

	/**
	 * disable location tracking
	 */
	this.__defineSetter__("trackLocation", function (trackLocation) {
		if (Modernizr.geolocation) {
			if (trackLocation) {
				trackingID = navigator.geolocation.watchPosition(successLocationCallback, errorLocationCallback, {enableHighAccuracy: true});
			} else if (!trackLocation) {
				navigator.geolocation.clearWatch(trackingID);
			}
			tracking = trackLocation;
		}
	})

}

/**
 * Move the map to the current location or the fallback
 * @returns {google.maps.LatLng|*}
 */
Location.prototype.moveToCurrentLocationOrFallback = function () {
	if (Modernizr.geolocation) {
		navigator.geolocation.getCurrentPosition(successLocationCallback, errorLocationCallback,{enableHighAccuracy: true});
	} else {
		this.moveToLocation(this.DEFAULT_LAT, this.DEFAULT_LONG);
		//TODO: show hint that browser doesn't support location
	}
};

/**
 * Moves the map to the given location
 * @param lat
 * @param long
 */
Location.prototype.moveToLocation = function(lat, long) {
	if (this.map) {
		var newLocation = new google.maps.LatLng(lat, long);
		this.currentLocation = newLocation;
		this.map.panTo(newLocation);
		if (this.map.positionMarker) {
			this.map.positionMarker.setPosition(newLocation);
		}
	}
}

var userLocation = new Location();

/**
 * Global map Options
 * @type {{center: google.maps.LatLng, zoom: number, mapTypeId: *, disableDefaultUI: boolean, zoomControl: boolean}}
 */
var mapOptions = {
	center: userLocation.DEFAULT_LOCATION,
	zoom: 17,
	mapTypeId: google.maps.MapTypeId.SATELLITE,
	disableDefaultUI: false,
	zoomControl: true
};

/**
 * Initializes the map
 */
function initialize_Map() {
	userLocation.map = new google.maps.Map(document.getElementById(MAP_ELEMENT),
		mapOptions);
	userLocation.moveToCurrentLocationOrFallback();
	userLocation.trackLocation = true;
}<commit_msg>update map type control<commit_after>/**
 * Constant that identifies the map canvas.
 * @type {string}
 */
var MAP_ELEMENT = "map_canvas";

/**
 * Callback that is called when the location is successfully retrieved.
 * @param position
 */
function successLocationCallback (position) {
	//success callback
	userLocation.moveToLocation(position.coords.latitude, position.coords.longitude);
	if (!userLocation.positionMarker) {
		userLocation.positionMarker = new google.maps.Marker({
			position: userLocation.map.getCenter(),
			map: userLocation.map,
			clickable: false,
			icon: "static/stadtgedaechtnis/img/marker_position.png"
		});
	}
	//TODO: maybe add accuracy?
}

/**
 * Callback that is called when the location couldn't be retrieved.
 * @param error
 */
function errorLocationCallback (error) {
	// error callback
	alert(error.id);
	userLocation.moveToLocation(this.DEFAULT_LAT, this.DEFAULT_LONG);
	//TODO: show hint that location couldn't be retrieved
}

/**
 * Location object to enable/disable tracking the location and to retrieve the current or fallback location.
 * @param trackLocation
 * @constructor
 */
function Location() {
	this.DEFAULT_LAT = 50.258;
	this.DEFAULT_LONG = 10.965;
	this.DEFAULT_LOCATION = new google.maps.LatLng(50.258, 10.965);

	this.currentLocation = this.DEFAULT_LOCATION;
	this.positionMarker = null;

	var trackingID;
	var tracking = false;

	/**
	 * enable location tracking
	 */
	this.__defineGetter__("trackLocation", function () {
		return tracking;
	})

	/**
	 * disable location tracking
	 */
	this.__defineSetter__("trackLocation", function (trackLocation) {
		if (Modernizr.geolocation) {
			if (trackLocation) {
				trackingID = navigator.geolocation.watchPosition(successLocationCallback, errorLocationCallback, {enableHighAccuracy: true});
			} else if (!trackLocation) {
				navigator.geolocation.clearWatch(trackingID);
			}
			tracking = trackLocation;
		}
	})

}

/**
 * Move the map to the current location or the fallback
 * @returns {google.maps.LatLng|*}
 */
Location.prototype.moveToCurrentLocationOrFallback = function () {
	if (Modernizr.geolocation) {
		navigator.geolocation.getCurrentPosition(successLocationCallback, errorLocationCallback,{enableHighAccuracy: true});
	} else {
		this.moveToLocation(this.DEFAULT_LAT, this.DEFAULT_LONG);
		//TODO: show hint that browser doesn't support location
	}
};

/**
 * Moves the map to the given location
 * @param lat
 * @param long
 */
Location.prototype.moveToLocation = function(lat, long) {
	if (this.map) {
		var newLocation = new google.maps.LatLng(lat, long);
		this.currentLocation = newLocation;
		this.map.panTo(newLocation);
		if (this.map.positionMarker) {
			this.map.positionMarker.setPosition(newLocation);
		}
	}
}

var userLocation = new Location();

/**
 * Global map Options
 * @type {{center: google.maps.LatLng, zoom: number, mapTypeId: *, disableDefaultUI: boolean, zoomControl: boolean}}
 */
var mapOptions = {
	center: userLocation.DEFAULT_LOCATION,
	zoom: 17,
    mapTypeControl: true,
	mapTypeId: google.maps.MapTypeId.SATELLITE,
	disableDefaultUI: true,
	zoomControl: true
};

/**
 * Initializes the map
 */
function initialize_Map() {
	userLocation.map = new google.maps.Map(document.getElementById(MAP_ELEMENT),
		mapOptions);
	userLocation.moveToCurrentLocationOrFallback();
	userLocation.trackLocation = true;
}<|endoftext|>


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

'use strict'

const _ = require('lodash')
const Bluebird = require('bluebird')
const EventEmitter = require('events')
const drivelist = Bluebird.promisifyAll(require('drivelist'))

/**
 * @summary BlockDeviceAdapter
 * @class
 */
class BlockDeviceAdapter extends EventEmitter {
  /**
   * @summary BlockDeviceAdapter constructor
   * @class
   * @example
   * const adapter = new BlockDeviceAdapter()
   */
  constructor () {
    super()

    /** @type {String} Adapter name */
    this.id = this.constructor.id

    this.devices = []
    this.on('devices', (devices) => {
      this.devices = devices
    })
  }

  /**
   * @summary Scan for block devices
   * @public
   *
   * @param {Object} [options] - options
   * @param {Object} [options.includeSystemDrives=false] - include system drives
   * @param {Function} [callback] - optional callback
   * @returns {BlockDeviceAdapter}
   *
   * @example
   * adapter.scan({
   *   includeSystemDrives: true
   * }, (error, devices) => {
   *   // ...
   * })
   */
  scan (options = {}, callback) {
    // eslint-disable-next-line lodash/prefer-lodash-method
    drivelist.listAsync().map((drive) => {
      drive.adapter = this.id

      // TODO: Find a better way to detect that a certain
      // block device is a compute module initialized
      // through usbboot.
      if (_.includes([ '0001', 'RPi-MSD- 0001', 'File-Stor Gadget', 'Linux File-Stor Gadget USB Device' ], drive.description)) {
        drive.description = 'Compute Module'
        drive.icon = 'raspberrypi'
        drive.isSystem = false
      }

      return drive
    }).catch((error) => {
      this.emit('error', error)
      callback && callback(error)
    }).filter((drive) => {
      return !drive.error && (options.includeSystemDrives || !drive.isSystem)
    }).map((drive) => {
      drive.displayName = drive.device
      if (/PhysicalDrive/i.test(drive.device) && drive.mountpoints.length) {
        drive.displayName = _.map(drive.mountpoints, 'path').join(', ')
      }
      return drive
    }).then((drives) => {
      this.emit('devices', drives)
      callback && callback(null, drives)
    })

    return this
  }
}

/**
 * @summary The name of this adapter
 * @public
 * @type {String}
 * @constant
 */
BlockDeviceAdapter.id = 'blockdevice'

// Exports
module.exports = BlockDeviceAdapter
<commit_msg>fix(adapters): Always ignore RAID attached devices<commit_after>/*
 * Copyright 2017 resin.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict'

const _ = require('lodash')
const Bluebird = require('bluebird')
const EventEmitter = require('events')
const drivelist = Bluebird.promisifyAll(require('drivelist'))

/**
 * @summary BlockDeviceAdapter
 * @class
 */
class BlockDeviceAdapter extends EventEmitter {
  /**
   * @summary BlockDeviceAdapter constructor
   * @class
   * @example
   * const adapter = new BlockDeviceAdapter()
   */
  constructor () {
    super()

    /** @type {String} Adapter name */
    this.id = this.constructor.id

    this.devices = []
    this.on('devices', (devices) => {
      this.devices = devices
    })
  }

  /**
   * @summary Scan for block devices
   * @public
   *
   * @param {Object} [options] - options
   * @param {Object} [options.includeSystemDrives=false] - include system drives
   * @param {Function} [callback] - optional callback
   * @returns {BlockDeviceAdapter}
   *
   * @example
   * adapter.scan({
   *   includeSystemDrives: true
   * }, (error, devices) => {
   *   // ...
   * })
   */
  scan (options = {}, callback) {
    // eslint-disable-next-line lodash/prefer-lodash-method
    drivelist.listAsync().map((drive) => {
      drive.adapter = this.id

      // TODO: Find a better way to detect that a certain
      // block device is a compute module initialized
      // through usbboot.
      if (_.includes([ '0001', 'RPi-MSD- 0001', 'File-Stor Gadget', 'Linux File-Stor Gadget USB Device' ], drive.description)) {
        drive.description = 'Compute Module'
        drive.icon = 'raspberrypi'
        drive.isSystem = false
      }

      return drive
    }).catch((error) => {
      this.emit('error', error)
      callback && callback(error)
    }).filter((drive) => {
      // Always ignore RAID attached devices, as they are in danger-country;
      // Even flashing RAIDs intentionally can have unintended effects
      if (drive.busType === 'RAID') {
        return false
      }
      return !drive.error && (options.includeSystemDrives || !drive.isSystem)
    }).map((drive) => {
      drive.displayName = drive.device
      if (/PhysicalDrive/i.test(drive.device) && drive.mountpoints.length) {
        drive.displayName = _.map(drive.mountpoints, 'path').join(', ')
      }
      return drive
    }).then((drives) => {
      this.emit('devices', drives)
      callback && callback(null, drives)
    })

    return this
  }
}

/**
 * @summary The name of this adapter
 * @public
 * @type {String}
 * @constant
 */
BlockDeviceAdapter.id = 'blockdevice'

// Exports
module.exports = BlockDeviceAdapter
<|endoftext|>