<commit_before>/*jshint node: true, -W106 */
'use strict';

/*
* Name : page.js
* Module : Page
* Location : /lib/businessTier/page
*
* History :
*
* Version   Date         Programmer         Description
* =========================================================
* 0.0.1     2015-05-19   Matteo Furlan    Initial code
* =========================================================
*/

var PageModel=require('../../dataTier/page/pageModel.js');
var BarChart=require('../graph/barChart.js');
var LineChart=require('../graph/lineChart.js');
var MapChart=require('../graph/mapChart.js');
var Table=require('../graph/table.js');

function Page(params,networkHandler,norris){
	if(params===undefined || networkHandler===undefined || norris===undefined ||
		norris._app===undefined || norris._io===undefined ||
		norris._networkHandler===undefined || norris._pageListSocket===undefined ||
		norris._pageList===undefined){
		console.log('Error: 421');
		return;
	}
	var pageM = new PageModel(params);
	if(pageM._name === undefined) {
		console.log('Error: 421');
		return;
	}

	this._page = pageM;
	this._networkHandler = networkHandler;
	this._norris = norris;
	this._pageNamespace = '/' + this._networkHandler_norrisNamespace + '/' + params.ID;
	this._pageSocket = this._networkHandler.createSocket(this._pageNamespace);
	this._pageSocket.attachObject(this,'configPage');
	this._graphs = [];

	//add to routing
	this._networkHandler.addPageToRouting(this._pageNamespace);
}

Page.prototype.createBarChart = function(params) {
	if(params === undefined || params.ID === undefined) {
		return null;
	}

	for (var key in this._graphs) {
		if(this._graphs[key].getProperties().ID===params.ID){
			return null;
		}
	}
	var graphSocket=this._networkHandler.createSocket(this._pageNamespace+'/'+params.ID);
	var graph = new BarChart(params, this, graphSocket);
	if(graph._dataBarChart === undefined) {
		return null;
	}
	graphSocket.attachObject(graph, 'configGraph');

	this._graphs.push(graph);
	this._page.addGraph(graph._dataBarChart);
	var graphProp=graph.getProperties();

	var data={
		ID: this._page._ID,
		data: {
			ID: graphProp.ID,
			title: graphProp.title,
			type: 'BarChart',
			socketURL: this._networkHandler._routes._baseURL + '/' + this._pageNamespace + '/' + graphProp.ID
		}
	};
	//notify page
	this._pageSocket.sendMessage('insertGraph', data);

	//notify pagelist
	this._norris.pageChanged({eventType: 'insertGraph', params: data});

	this._networkHandler.addGraphToRouting(this._pageNamespace+'/'+params.ID);
	return graph;
};

Page.prototype.createLineChart = function(params) {
	if(params === undefined || params.ID === undefined) {
		return null;
	}

	for (var key in this._graphs) {
		if(this._graphs[key].getProperties().ID===params.ID){
			return null;
		}
	}
	var graphSocket=this._networkHandler.createSocket(this._pageNamespace+'/'+params.ID);
	var graph = new LineChart(params, this, graphSocket);
	if(graph._dataLineChart === undefined) {
		return null;
	}
	graphSocket.attachObject(graph, 'configGraph');

	this._graphs.push(graph);
	this._page.addGraph(graph._dataLineChart);
	var graphProp=graph.getProperties();

	var data={
		ID: this._page._ID,
		data: {
			ID: graphProp.ID,
			title: graphProp.title,
			type: 'LineChart',
			socketURL: this._networkHandler._routes._baseURL + '/' + this._pageNamespace + '/' + graphProp.ID
		}
	};
	//notify page
	this._pageSocket.sendMessage('insertGraph', data);

	//notify pagelist
	this._norris.pageChanged({eventType: 'insertGraph', params: data});

	this._networkHandler.addGraphToRouting(this._pageNamespace+'/'+params.ID);
	return graph;
};

Page.prototype.createMapChart = function(params) {
	if(params === undefined || params.ID === undefined) {
		return null;
	}

	for (var key in this._graphs) {
		if(this._graphs[key].getProperties().ID===params.ID){
			return null;
		}
	}
	var graphSocket=this._networkHandler.createSocket(this._pageNamespace+'/'+params.ID);
	var graph = new MapChart(params, this, graphSocket);
	if(graph._dataMapChart === undefined) {
		return null;
	}
	graphSocket.attachObject(graph, 'configGraph');

	this._graphs.push(graph);
	this._page.addGraph(graph._dataMapChart);
	var graphProp=graph.getProperties();

	var data={
		ID: this._page._ID,
		data: {
			ID: graphProp.ID,
			title: graphProp.title,
			type: 'MapChart',
			socketURL: this._networkHandler._routes._baseURL + '/' + this._pageNamespace + '/' + graphProp.ID
		}
	};
	//notify page
	this._pageSocket.sendMessage('insertGraph', data);

	//notify pagelist
	this._norris.pageChanged({eventType: 'insertGraph', params: data});

	this._networkHandler.addGraphToRouting(this._pageNamespace+'/'+params.ID);
	return graph;
};

Page.prototype.createTable = function(params) {
	if(params === undefined || params.ID === undefined) {
		return null;
	}

	for (var key in this._graphs) {
		if(this._graphs[key].getProperties().ID===params.ID){
			return null;
		}
	}
	var graphSocket=this._networkHandler.createSocket(this._pageNamespace+'/'+params.ID);
	var graph = new Table(params, this, graphSocket);
	if(graph._dataTable === undefined) {
		return null;
	}
	graphSocket.attachObject(graph, 'configGraph');

	this._graphs.push(graph);
	this._page.addGraph(graph._dataTable);
	var graphProp=graph.getProperties();

	var data={
		ID: this._page._ID,
		data: {
			ID: graphProp.ID,
			title: graphProp.title,
			type: 'Table',
			socketURL: this._networkHandler._routes._baseURL + '/' + this._pageNamespace + '/' + graphProp.ID
		}
	};
	//notify page
	this._pageSocket.sendMessage('insertGraph', data);

	//notify pagelist
	this._norris.pageChanged({eventType: 'insertGraph', params: data});

	this._networkHandler.addGraphToRouting(this._pageNamespace+'/'+params.ID);
	return graph;
};

Page.prototype.updateProperties = function(params) {

	if(params!==undefined && params!==null && typeof params==='object') {

		//call the updateProperties method in the Data Tier
		this._page.updateProperties(params);
		var data=params;
		data.ID=this._page._ID;
		//notify the page sockets
		this._pageSocket.sendMessage('updatePageProp', data);

		//notify norris about the page update
		if (params.description!==undefined || params.name!==undefined){
			this._norris.pageChanged({eventType: 'updatePage', params: data});
		}
	}
};

Page.prototype.getProperties = function() {
	return this._page.getProperties();
};

Page.prototype.getConfigJSON = function() {
	var ret = {
		properties: this._page.getProperties(),
		data: []
	};
	var PData = this._page.getData();
	for(var i=0; i < PData.length; i++) {
		ret.data.push({
			ID: PData[i].properties.ID,
			title: PData[i].properties.title,
			socketURL: this._networkHandler._routes._baseURL + this._pageNamespace + '/' + PData[i].properties.ID
		});
	}
	return ret;
};

Page.prototype.graphChanged = function(params) {
	if(params!==undefined && params.eventType!==undefined && params.params!== undefined &&
		(typeof params.eventType) === 'string' && params.eventType !== '' && typeof params.params === 'object') {
		//notify the page sockets
		this._pageSocket.sendMessage(params.eventType, params.params);
	}
	var norrisData={
		ID: this._page._ID,
		data: params
	};
	//notify norris about the graph update
	this._norris.pageChanged({eventType: 'updateGraph', params: norrisData});
};

module.exports = Page;<commit_msg>fix routing path<commit_after>/*jshint node: true, -W106 */
'use strict';

/*
* Name : page.js
* Module : Page
* Location : /lib/businessTier/page
*
* History :
*
* Version   Date         Programmer         Description
* =========================================================
* 0.0.1     2015-05-19   Matteo Furlan    Initial code
* =========================================================
*/

var PageModel=require('../../dataTier/page/pageModel.js');
var BarChart=require('../graph/barChart.js');
var LineChart=require('../graph/lineChart.js');
var MapChart=require('../graph/mapChart.js');
var Table=require('../graph/table.js');

function Page(params,networkHandler,norris){
	if(params===undefined || networkHandler===undefined || norris===undefined ||
		norris._app===undefined || norris._io===undefined ||
		norris._networkHandler===undefined || norris._pageListSocket===undefined ||
		norris._pageList===undefined){
		console.log('Error: 421');
		return;
	}
	var pageM = new PageModel(params);
	if(pageM._name === undefined) {
		console.log('Error: 421');
		return;
	}

	this._page = pageM;
	this._networkHandler = networkHandler;
	this._norris = norris;
	this._pageNamespace = '/' + this._networkHandler._norrisNamespace + '/' + params.ID;
	this._pageSocket = this._networkHandler.createSocket(this._pageNamespace);
	this._pageSocket.attachObject(this,'configPage');
	this._graphs = [];

	//add to routing
	this._networkHandler.addPageToRouting(this._pageNamespace);
}

Page.prototype.createBarChart = function(params) {
	if(params === undefined || params.ID === undefined) {
		return null;
	}

	for (var key in this._graphs) {
		if(this._graphs[key].getProperties().ID===params.ID){
			return null;
		}
	}
	var graphSocket=this._networkHandler.createSocket(this._pageNamespace+'/'+params.ID);
	var graph = new BarChart(params, this, graphSocket);
	if(graph._dataBarChart === undefined) {
		return null;
	}
	graphSocket.attachObject(graph, 'configGraph');

	this._graphs.push(graph);
	this._page.addGraph(graph._dataBarChart);
	var graphProp=graph.getProperties();

	var data={
		ID: this._page._ID,
		data: {
			ID: graphProp.ID,
			title: graphProp.title,
			type: 'BarChart',
			socketURL: this._networkHandler._routes._baseURL + '/' + this._pageNamespace + '/' + graphProp.ID
		}
	};
	//notify page
	this._pageSocket.sendMessage('insertGraph', data);

	//notify pagelist
	this._norris.pageChanged({eventType: 'insertGraph', params: data});

	this._networkHandler.addGraphToRouting(this._pageNamespace+'/'+params.ID);
	return graph;
};

Page.prototype.createLineChart = function(params) {
	if(params === undefined || params.ID === undefined) {
		return null;
	}

	for (var key in this._graphs) {
		if(this._graphs[key].getProperties().ID===params.ID){
			return null;
		}
	}
	var graphSocket=this._networkHandler.createSocket(this._pageNamespace+'/'+params.ID);
	var graph = new LineChart(params, this, graphSocket);
	if(graph._dataLineChart === undefined) {
		return null;
	}
	graphSocket.attachObject(graph, 'configGraph');

	this._graphs.push(graph);
	this._page.addGraph(graph._dataLineChart);
	var graphProp=graph.getProperties();

	var data={
		ID: this._page._ID,
		data: {
			ID: graphProp.ID,
			title: graphProp.title,
			type: 'LineChart',
			socketURL: this._networkHandler._routes._baseURL + '/' + this._pageNamespace + '/' + graphProp.ID
		}
	};
	//notify page
	this._pageSocket.sendMessage('insertGraph', data);

	//notify pagelist
	this._norris.pageChanged({eventType: 'insertGraph', params: data});

	this._networkHandler.addGraphToRouting(this._pageNamespace+'/'+params.ID);
	return graph;
};

Page.prototype.createMapChart = function(params) {
	if(params === undefined || params.ID === undefined) {
		return null;
	}

	for (var key in this._graphs) {
		if(this._graphs[key].getProperties().ID===params.ID){
			return null;
		}
	}
	var graphSocket=this._networkHandler.createSocket(this._pageNamespace+'/'+params.ID);
	var graph = new MapChart(params, this, graphSocket);
	if(graph._dataMapChart === undefined) {
		return null;
	}
	graphSocket.attachObject(graph, 'configGraph');

	this._graphs.push(graph);
	this._page.addGraph(graph._dataMapChart);
	var graphProp=graph.getProperties();

	var data={
		ID: this._page._ID,
		data: {
			ID: graphProp.ID,
			title: graphProp.title,
			type: 'MapChart',
			socketURL: this._networkHandler._routes._baseURL + '/' + this._pageNamespace + '/' + graphProp.ID
		}
	};
	//notify page
	this._pageSocket.sendMessage('insertGraph', data);

	//notify pagelist
	this._norris.pageChanged({eventType: 'insertGraph', params: data});

	this._networkHandler.addGraphToRouting(this._pageNamespace+'/'+params.ID);
	return graph;
};

Page.prototype.createTable = function(params) {
	if(params === undefined || params.ID === undefined) {
		return null;
	}

	for (var key in this._graphs) {
		if(this._graphs[key].getProperties().ID===params.ID){
			return null;
		}
	}
	var graphSocket=this._networkHandler.createSocket(this._pageNamespace+'/'+params.ID);
	var graph = new Table(params, this, graphSocket);
	if(graph._dataTable === undefined) {
		return null;
	}
	graphSocket.attachObject(graph, 'configGraph');

	this._graphs.push(graph);
	this._page.addGraph(graph._dataTable);
	var graphProp=graph.getProperties();

	var data={
		ID: this._page._ID,
		data: {
			ID: graphProp.ID,
			title: graphProp.title,
			type: 'Table',
			socketURL: this._networkHandler._routes._baseURL + '/' + this._pageNamespace + '/' + graphProp.ID
		}
	};
	//notify page
	this._pageSocket.sendMessage('insertGraph', data);

	//notify pagelist
	this._norris.pageChanged({eventType: 'insertGraph', params: data});

	this._networkHandler.addGraphToRouting(this._pageNamespace+'/'+params.ID);
	return graph;
};

Page.prototype.updateProperties = function(params) {

	if(params!==undefined && params!==null && typeof params==='object') {

		//call the updateProperties method in the Data Tier
		this._page.updateProperties(params);
		var data=params;
		data.ID=this._page._ID;
		//notify the page sockets
		this._pageSocket.sendMessage('updatePageProp', data);

		//notify norris about the page update
		if (params.description!==undefined || params.name!==undefined){
			this._norris.pageChanged({eventType: 'updatePage', params: data});
		}
	}
};

Page.prototype.getProperties = function() {
	return this._page.getProperties();
};

Page.prototype.getConfigJSON = function() {
	var ret = {
		properties: this._page.getProperties(),
		data: []
	};
	var PData = this._page.getData();
	for(var i=0; i < PData.length; i++) {
		ret.data.push({
			ID: PData[i].properties.ID,
			title: PData[i].properties.title,
			socketURL: this._networkHandler._routes._baseURL + this._pageNamespace + '/' + PData[i].properties.ID
		});
	}
	return ret;
};

Page.prototype.graphChanged = function(params) {
	if(params!==undefined && params.eventType!==undefined && params.params!== undefined &&
		(typeof params.eventType) === 'string' && params.eventType !== '' && typeof params.params === 'object') {
		//notify the page sockets
		this._pageSocket.sendMessage(params.eventType, params.params);
	}
	var norrisData={
		ID: this._page._ID,
		data: params
	};
	//notify norris about the graph update
	this._norris.pageChanged({eventType: 'updateGraph', params: norrisData});
};

module.exports = Page;<|endoftext|>


<commit_before>/* All things javascript specific for the classic page change list */

/* 25b6: black right-pointing triangle, 25bc: black down-pointing triangle,
   25b7: white right-pointing triangle, 25BD: white down-pointing triangle */
var expand_sym = '\u25B7';
var collapse_sym = '\u25BD';

var feincms_page_open_list;

var page = function(item_id) { return tree_structure[item_id]; }

var recolor_lines = function()
{
    $('tbody tr').removeClass('row1').removeClass('row2');
    $('tbody tr:visible:even').addClass('row1');
    $('tbody tr:visible:odd').addClass('row2');
}

/* show all immediate children, then open all children that are marked as open */
var open_subtree = function(item_id)
{
    p = page(item_id)
    if(p.children.length == 0)
        return;

    p.ptr.html(collapse_sym);
    $.each(p.children, function(i, id)
           {
           pp = page(id)
           if(pp.ptr)
               {
               pp.row.show();
               if(pp.open)
                    open_subtree(id);
               }
           });
}

/* hide all descendants */
var close_subtree = function(item_id)
{
    p = page(item_id)
    if(p.descendants.length == 0)
        return;
    p.ptr.html(expand_sym);
    $.each(p.descendants, function(i, id)
           {
           pp = page(id);
           if(pp.ptr)
                pp.row.hide()
           });
}

/* Click handler */
var page_tree_handler = function(item_id)
{
    p = page(item_id);

    if(p.children.length == 0)
        return false;

    open = p.open;
    p.open = !open;

    if(open)
        {
        close_subtree(item_id);
        feincms_page_open_list = feincms_page_open_list.filter(function(o) { return o != item_id });
        }
    else
        {
        open_subtree(item_id);
        feincms_page_open_list.push(item_id);
        }

    /* Do I really want that? */
    recolor_lines();

    return false;
}

/* Clean out tree_structure: Remove non existant parents, children, descendants */
var tree_structure_clean = function()
{
    feincms_page_open_list = $.cookie('feincms_page_open_list');

    /* Keep a list of open pages to save state across reloads */
    if(feincms_page_open_list) {
        lst = feincms_page_open_list.split(',');
        feincms_page_open_list = [];
        for(var i=0; i<lst.length; i++)
            feincms_page_open_list.push(parseInt(lst[i]));
    } else
        feincms_page_open_list = [];

    $(window).unload(function(){
        $.cookie('feincms_page_open_list', feincms_page_open_list.join(','));
    });

    for(k in tree_structure)
        {
            p = page(k);
            /* Precompute object links for no object-id lookups later */
            m = $('#page_marker-' + k);
            if(m.length)
                {
                    p.ptr = m;
                    p.row = m.parents('tr:first');
                }
            else /* row not present in changelist, throw node away */
                {
                    tree_structure[k] = { }
                }
        }

    /* Clean out tree_structure: Remove non existant parents, children, descendants */
    for(k in tree_structure)
        {
            p = page(k);
            if(p.parent && !page(p.parent).ptr)
                p.parent = null

                if(p.descendants)
                    p.descendants = $.grep(p.descendants, function(o) { return page(o).ptr; });

            if(p.children)
                {
                    p.children = $.grep(p.children, function(o) { return page(o).ptr; });
                    if(p.children.length)
                        p.ptr.html(expand_sym);
                }
        }
    for(i in feincms_page_open_list)
        {
            item_id = feincms_page_open_list[i];
            page(item_id).open = true;
        }
}

/* Cut/Copy/Paste support */
// FIXME: This changes the site structure and would need to refresh the tree_structure at least (if not more, eg. page filter).
var cut_item_pk = null;
function cut_item(pk, elem) {
    var row = $(elem.parentNode.parentNode);

    if(row.hasClass('cut')) {
        cut_item_pk = null;
        $('a.paste_target').hide();
        row.removeClass('cut');
    } else {
        cut_item_pk = pk;
        $('a.paste_target').show();
        $('tr').removeClass('cut');
        row.addClass('cut').find('a.paste_target').hide();
    }

    return false;
}

function paste_item(pk, position) {
    if(!cut_item_pk)
        return false;

    $.post('.', {
           '__cmd': 'move_node',
           'position': position,
           'cut_item': cut_item_pk,
           'pasted_on': pk
           }, function(data) {
           if(data == 'OK')
           window.location.reload();
           else
           alert(data);
           });

    return false;
}

<commit_msg>Make javascript code not fail when pages have been deleted<commit_after>/* All things javascript specific for the classic page change list */

/* 25b6: black right-pointing triangle, 25bc: black down-pointing triangle,
   25b7: white right-pointing triangle, 25BD: white down-pointing triangle */
var expand_sym = '\u25B7';
var collapse_sym = '\u25BD';

var feincms_page_open_list;

var page = function(item_id) { return tree_structure[item_id]; }

var recolor_lines = function()
{
    $('tbody tr').removeClass('row1').removeClass('row2');
    $('tbody tr:visible:even').addClass('row1');
    $('tbody tr:visible:odd').addClass('row2');
}

/* show all immediate children, then open all children that are marked as open */
var open_subtree = function(item_id)
{
    p = page(item_id)
    if(p.children.length == 0)
        return;

    p.ptr.html(collapse_sym);
    $.each(p.children, function(i, id)
           {
           pp = page(id)
           if(pp.ptr)
               {
               pp.row.show();
               if(pp.open)
                    open_subtree(id);
               }
           });
}

/* hide all descendants */
var close_subtree = function(item_id)
{
    p = page(item_id)
    if(p.descendants.length == 0)
        return;
    p.ptr.html(expand_sym);
    $.each(p.descendants, function(i, id)
           {
           pp = page(id);
           if(pp.ptr)
                pp.row.hide()
           });
}

/* Click handler */
var page_tree_handler = function(item_id)
{
    p = page(item_id);

    if(p.children.length == 0)
        return false;

    open = p.open;
    p.open = !open;

    if(open)
        {
        close_subtree(item_id);
        feincms_page_open_list = feincms_page_open_list.filter(function(o) { return o != item_id });
        }
    else
        {
        open_subtree(item_id);
        feincms_page_open_list.push(item_id);
        }

    /* Do I really want that? */
    recolor_lines();

    return false;
}

/* Clean out tree_structure: Remove non existant parents, children, descendants */
var tree_structure_clean = function()
{
    feincms_page_open_list = $.cookie('feincms_page_open_list');

    /* Keep a list of open pages to save state across reloads */
    if(feincms_page_open_list) {
        lst = feincms_page_open_list.split(',');
        feincms_page_open_list = [];
        for(var i=0; i<lst.length; i++)
            feincms_page_open_list.push(parseInt(lst[i]));
    } else
        feincms_page_open_list = [];

    $(window).unload(function(){
        $.cookie('feincms_page_open_list', feincms_page_open_list.join(','));
    });

    for(k in tree_structure)
        {
            p = page(k);
            /* Precompute object links for no object-id lookups later */
            m = $('#page_marker-' + k);
            if(m.length)
                {
                    p.ptr = m;
                    p.row = m.parents('tr:first');
                }
            else /* row not present in changelist, throw node away */
                {
                    tree_structure[k] = { }
                }
        }

    /* Clean out tree_structure: Remove non existant parents, children, descendants */
    for(k in tree_structure)
        {
            p = page(k);
            if(p.parent && !page(p.parent).ptr)
                p.parent = null

                if(p.descendants)
                    p.descendants = $.grep(p.descendants, function(o) { return page(o).ptr; });

            if(p.children)
                {
                    p.children = $.grep(p.children, function(o) { return page(o).ptr; });
                    if(p.children.length)
                        p.ptr.html(expand_sym);
                }
        }
    for(i in feincms_page_open_list)
        {
            item_id = feincms_page_open_list[i];
            var p = page(item_id);
            // pages could have been deleted
            if(p) p.open = true;
        }
}

/* Cut/Copy/Paste support */
// FIXME: This changes the site structure and would need to refresh the tree_structure at least (if not more, eg. page filter).
var cut_item_pk = null;
function cut_item(pk, elem) {
    var row = $(elem.parentNode.parentNode);

    if(row.hasClass('cut')) {
        cut_item_pk = null;
        $('a.paste_target').hide();
        row.removeClass('cut');
    } else {
        cut_item_pk = pk;
        $('a.paste_target').show();
        $('tr').removeClass('cut');
        row.addClass('cut').find('a.paste_target').hide();
    }

    return false;
}

function paste_item(pk, position) {
    if(!cut_item_pk)
        return false;

    $.post('.', {
           '__cmd': 'move_node',
           'position': position,
           'cut_item': cut_item_pk,
           'pasted_on': pk
           }, function(data) {
           if(data == 'OK')
           window.location.reload();
           else
           alert(data);
           });

    return false;
}

<|endoftext|>


<commit_before>'use strict'

// ===================================================================

var Bluebird = require('bluebird')
var Collection = require('xo-collection').default
var forEach = require('lodash.foreach')
var Index = require('xo-collection/index')
var isString = require('lodash.isstring')
var startsWith = require('lodash.startswith')
var UniqueIndex = require('xo-collection/unique-index')

var Api = require('./api')
var BackOff = require('./back-off')
var ConnectionError = require('./connection-error')
var SessionError = require('./session-error')

// ===================================================================

function makeStandaloneDeferred () {
  var resolve, reject

  var promise = new Bluebird(function (resolve_, reject_) {
    resolve = resolve_
    reject = reject_
  })
  promise.resolve = resolve
  promise.reject = reject

  return promise
}

function noop () {}

// -------------------------------------------------------------------

var defineProperty = Object.defineProperty

var LINK_RE = /^(.*)\$link\$$/

function createAutoLinks (collection, object) {
  forEach(object, function resolveObject (value, key, object) {
    var matches = key.match(LINK_RE)
    if (!matches) {
      return
    }

    defineProperty(object, matches[1], {
      get: function () {
        return collection[value]
      }
    })
  })
}

function setMultiple (collection, items) {
  forEach(items, function (item) {
    createAutoLinks(item)

    collection.set(item)
  })
}

function unsetMultiple (collection, items) {
  forEach(items, function (item) {
    if (collection.has(item)) {
      collection.remove(item)
    }
  })
}

// ===================================================================

function Xo (opts) {
  if (!opts) {
    opts = {}
  } else if (isString(opts)) {
    opts = {
      url: opts
    }
  }

  // -----------------------------------------------------------------

  var api = new Api(opts.url)

  api.on('connected', function () {
    this._backOff.reset()
    this.status = 'connected'

    this._tryToOpenSession()
  }.bind(this))

  api.on('disconnected', function () {
    this._closeSession()
    this._connect()
  }.bind(this))

  api.on('notification', function (notification) {
    if (notification.method !== 'all') {
      return
    }

    var method = notification.params.type === 'exit' ?
      unsetMultiple :
      setMultiple

    method(this.objects, notification.params.items)
  }.bind(this))

  // -----------------------------------------------------------------

  var objects = this.objects = new Collection()
  objects.getKey = function (item) {
    return item.UUID || item.ref || 'undefined'
  }
  objects.createIndex('ref', new UniqueIndex('ref'))
  objects.createIndex('type', new Index('type'))

  this.status = 'disconnected'
  this.user = null

  this._api = api
  this._backOff = new BackOff()
  this._credentials = opts.creadentials
  this._session = makeStandaloneDeferred()
  this._signIn = null

  // -----------------------------------------------------------------

  this._connect()
}

Xo.prototype.call = function (method, params) {
  // Prevent session.*() from being because it may interfere
  // with this class session management.
  if (startsWith(method, 'session.')) {
    return Bluebird.reject(
      new Error('session.*() methods are disabled from this interface')
    )
  }

  return this._session.bind(this).then(function () {
    return this._api.call(method, params)
  }).catch(ConnectionError, SessionError, function () {
    // Automatically requeue this call.
    return this.call(method, params)
  })
}

Xo.prototype.signIn = function (credentials) {
  this.signOut()

  this._credentials = credentials
  this._signIn = makeStandaloneDeferred()

  this._tryToOpenSession()

  return this._signIn
}

Xo.prototype.signOut = function () {
  this._closeSession()
  this._credentials = null

  var signIn = this._signIn
  if (signIn && signIn.isPending()) {
    signIn.reject(new SessionError('sign in aborted'))
  }

  return this.status === 'connected' ?

    // Attempt to sign out and ignore any return values and errors.
    this._api.call('session.signOut').then(noop, noop) :

    // Always return a promise.
    Bluebird.resolve()
}

Xo.prototype._connect = function _connect () {
  this.status = 'connecting'

  return this._api.connect().bind(this).catch(function (error) {
    console.warn('could not connect:', error)

    return this._backOff.wait().bind(this).then(_connect)
  })
}

Xo.prototype._closeSession = function () {
  if (!this._session.isPending()) {
    this._session = makeStandaloneDeferred()
  }

  this.user = null
}

Xo.prototype._tryToOpenSession = function () {
  var credentials = this._credentials
  if (!credentials || this.status !== 'connected') {
    return
  }

  this._api.call(
    credentials.token ?
      'session.signInWithToken' :
      'session.signInWithPassword',
    credentials
  ).bind(this).then(
    function (user) {
      this.user = user

      this._api.call('xo.getAllObjects').bind(this).then(function (objects) {
        this.objects.clear()
        setMultiple(this.objects, objects)
      })

      // Validate the sign in.
      var signIn = this._signIn
      if (signIn) {
        signIn.resolve()
      }

      // Open the session.
      this._session.resolve()
    },

    function (error) {
      // Reject the sign in.
      var signIn = this._signIn
      if (signIn) {
        signIn.reject(error)
      }
    }
  )
}

// ===================================================================

module.exports = Xo
<commit_msg>Fix objects removal.<commit_after>'use strict'

// ===================================================================

var Bluebird = require('bluebird')
var Collection = require('xo-collection').default
var forEach = require('lodash.foreach')
var Index = require('xo-collection/index')
var isString = require('lodash.isstring')
var startsWith = require('lodash.startswith')
var UniqueIndex = require('xo-collection/unique-index')

var Api = require('./api')
var BackOff = require('./back-off')
var ConnectionError = require('./connection-error')
var SessionError = require('./session-error')

// ===================================================================

function makeStandaloneDeferred () {
  var resolve, reject

  var promise = new Bluebird(function (resolve_, reject_) {
    resolve = resolve_
    reject = reject_
  })
  promise.resolve = resolve
  promise.reject = reject

  return promise
}

function noop () {}

// -------------------------------------------------------------------

var defineProperty = Object.defineProperty

var LINK_RE = /^(.*)\$link\$$/

function createAutoLinks (collection, object) {
  forEach(object, function resolveObject (value, key, object) {
    var matches = key.match(LINK_RE)
    if (!matches) {
      return
    }

    defineProperty(object, matches[1], {
      get: function () {
        return collection[value]
      }
    })
  })
}

function setMultiple (collection, items) {
  const getKey = collection.getKey

  forEach(items, function (item) {
    const key = getKey(item)
    if (!key) {
      return
    }

    createAutoLinks(item)

    collection.set(key, item)
  })
}

function unsetMultiple (collection, items) {
  const getKey = collection.getKey

  forEach(items, function (item) {
    const key = getKey(item)
    if (!key) {
      return
    }

    if (collection.has(key)) {
      collection.remove(key)
    }
  })
}

// ===================================================================

function Xo (opts) {
  if (!opts) {
    opts = {}
  } else if (isString(opts)) {
    opts = {
      url: opts
    }
  }

  // -----------------------------------------------------------------

  var api = new Api(opts.url)

  api.on('connected', function () {
    this._backOff.reset()
    this.status = 'connected'

    this._tryToOpenSession()
  }.bind(this))

  api.on('disconnected', function () {
    this._closeSession()
    this._connect()
  }.bind(this))

  api.on('notification', function (notification) {
    if (notification.method !== 'all') {
      return
    }

    var method = notification.params.type === 'exit' ?
      unsetMultiple :
      setMultiple

    method(this.objects, notification.params.items)
  }.bind(this))

  // -----------------------------------------------------------------

  var objects = this.objects = new Collection()
  objects.getKey = function (item) {
    return item.UUID || item.ref || 'undefined'
  }
  objects.createIndex('ref', new UniqueIndex('ref'))
  objects.createIndex('type', new Index('type'))

  this.status = 'disconnected'
  this.user = null

  this._api = api
  this._backOff = new BackOff()
  this._credentials = opts.creadentials
  this._session = makeStandaloneDeferred()
  this._signIn = null

  // -----------------------------------------------------------------

  this._connect()
}

Xo.prototype.call = function (method, params) {
  // Prevent session.*() from being because it may interfere
  // with this class session management.
  if (startsWith(method, 'session.')) {
    return Bluebird.reject(
      new Error('session.*() methods are disabled from this interface')
    )
  }

  return this._session.bind(this).then(function () {
    return this._api.call(method, params)
  }).catch(ConnectionError, SessionError, function () {
    // Automatically requeue this call.
    return this.call(method, params)
  })
}

Xo.prototype.signIn = function (credentials) {
  this.signOut()

  this._credentials = credentials
  this._signIn = makeStandaloneDeferred()

  this._tryToOpenSession()

  return this._signIn
}

Xo.prototype.signOut = function () {
  this._closeSession()
  this._credentials = null

  var signIn = this._signIn
  if (signIn && signIn.isPending()) {
    signIn.reject(new SessionError('sign in aborted'))
  }

  return this.status === 'connected' ?

    // Attempt to sign out and ignore any return values and errors.
    this._api.call('session.signOut').then(noop, noop) :

    // Always return a promise.
    Bluebird.resolve()
}

Xo.prototype._connect = function _connect () {
  this.status = 'connecting'

  return this._api.connect().bind(this).catch(function (error) {
    console.warn('could not connect:', error)

    return this._backOff.wait().bind(this).then(_connect)
  })
}

Xo.prototype._closeSession = function () {
  if (!this._session.isPending()) {
    this._session = makeStandaloneDeferred()
  }

  this.user = null
}

Xo.prototype._tryToOpenSession = function () {
  var credentials = this._credentials
  if (!credentials || this.status !== 'connected') {
    return
  }

  this._api.call(
    credentials.token ?
      'session.signInWithToken' :
      'session.signInWithPassword',
    credentials
  ).bind(this).then(
    function (user) {
      this.user = user

      this._api.call('xo.getAllObjects').bind(this).then(function (objects) {
        this.objects.clear()
        setMultiple(this.objects, objects)
      })

      // Validate the sign in.
      var signIn = this._signIn
      if (signIn) {
        signIn.resolve()
      }

      // Open the session.
      this._session.resolve()
    },

    function (error) {
      // Reject the sign in.
      var signIn = this._signIn
      if (signIn) {
        signIn.reject(error)
      }
    }
  )
}

// ===================================================================

module.exports = Xo
<|endoftext|>


<commit_before>/**
 * Creates a new instance of Matrix
 *
 * @param {Number} xcount The width of the array
 * @param {Number} ycount The height of the array
 * @classDescription The Matrix class represents a zero-indexed 2d matrix.
 */
function Matrix(xcount, ycount) {
  this.xs = UTIL.fillArray(null, xcount, function(index) {
    return new UTIL.Dictionary();
  });
  this.ys = UTIL.fillArray(null, ycount, function(index) {
    return new UTIL.Dictionary();
  });
};

/**
 * @property {Error} An exception meaning the element accessed was out of the
 * matrix bounds
 */
Matrix.prototype.OutOfBoundsException = new Error("Out of matrix bounds!");

/**
 * Sets a value in the matrix
 *
 * @param {Number} x The x coordinate of the parameter to set
 * @param {Number} y The y coordinate of the parameter to set
 * @param {Object, String, Number, Boolean} The value to set at the specified
 * location
 * @exception {Matrix.prototype.OutofBoundsException} An exception meaning the
 * element accessed was outside of the bounds of the matrix.
 */
Matrix.prototype.setValue = function(x, y, value) {
  if(x < xs.length && y < ys.length) {
    this.xs[x].store(y, value);
    this.ys[y].store(x, value);
  }
  else
    throw Matrix.prototype.OutOfBoundsException;
};

/**
 * Removes/unsets a value in the matrix
 *
 * @param {Number} x The x coordinate of the parameter to remove
 * @param {Number} y The y coordinate of the parameter to remove
 * @exception {Matrix.prototype.OutofBoundsException} An exception meaning the
 * element accessed was outside of the bounds of the matrix.
 */
Matrix.prototype.removeValue = function(x, y) {
  if(x < xs.length && y < ys.length) {
    this.xs[x].remove(y);
    this.ys[y].remove(x);
  }
  else
    throw Matrix.prototype.OutOfBoundsException
};

/**
 * Checks to see if a property is set in this matrix
 *
 * @param {Number} x The x coordinate of the parameter to check
 * @param {Number} y The y coordinate of the parameter to check
 * @return {Boolean} True if set, false otherwise
 */
Matrix.prototype.isSet = function(x, y) {
  return this.xs[x].contains(y);
};

/**
 * Counts the values in an X row
 * @param {Number} x The x number of the row to check
 * @return {Number} The number of set values
 */
Matrix.prototype.countXVals = function(x) {
  return this.xs[x].count;
};

/**
 * Counts the values in an y column
 * @param {Number} y The y number of the column to check
 * @return {Number} The number of set values
 */
Matrix.prototype.countYVals = function(y) {
  return this.ys[y].count
}

Matrix.prototype.getXVals = function(x) {
  var ret = [];
  UTIL.forEachIn(this.xs[x].values, function(key, value) {
    ret.push(key);
  });
  return ret;
}<commit_msg>Modified Matrix constructor and added to namespace<commit_after>var Staffing = Staffing || {};

/**
 * Creates a new instance of Matrix
 *
 * @param {Number} xcount The width of the array
 * @param {Number} ycount The height of the array
 * @param {Array} [initialValues] An Array of length xcount containing Arrays of
 * length ycount which contains values upon which the array should be
 * initialized. If this parameter is provided, emptyVal must also be provided.
 * @param [emptyVal] A value to compare each value to using ==. If the
 * comparison returns true, this value will not be stored in the matrix.
 * @classDescription The Matrix class represents a zero-indexed 2d matrix.
 */
Staffing.Matrix = function Matrix(xcount, ycount, initialValues, emptyVal) {
  var args = arguments;
  this.xs = UTIL.fillArray(null, xcount, function(index) {
    var ret = new UTIL.Dictionary();
    if(args.length > 2) {
      for(var y = 0; y < ycount; y++) {
        if(initialValues[index][y] != emptyVal)
          ret.store(y, initialValues[index][y]);
      }
    }
    return ret;
  });
  this.ys = UTIL.fillArray(null, ycount, function(index) {
    var ret = new UTIL.Dictionary();
    if(args.length > 2) {
      for(var x = 0; x < xcount; x++) {
        if(initialValues[x][index] != emptyVal)
          ret.store(x, initialValues[x][index]);
      }
    }
    return ret;
  });
};

/**
 * @property {Error} An exception meaning the element accessed was out of the
 * matrix bounds
 */
Staffing.Matrix.prototype.OutOfBoundsException = new Error("Out of matrix bounds!");

/**
 * Sets a value in the matrix
 *
 * @param {Number} x The x coordinate of the parameter to set
 * @param {Number} y The y coordinate of the parameter to set
 * @param {Object, String, Number, Boolean} The value to set at the specified
 * location
 * @exception {Matrix.prototype.OutofBoundsException} An exception meaning the
 * element accessed was outside of the bounds of the matrix.
 */
Staffing.Matrix.prototype.setValue = function(x, y, value) {
  if(x < xs.length && y < ys.length) {
    this.xs[x].store(y, value);
    this.ys[y].store(x, value);
  }
  else
    throw Matrix.prototype.OutOfBoundsException;
};

/**
 * Removes/unsets a value in the matrix
 *
 * @param {Number} x The x coordinate of the parameter to remove
 * @param {Number} y The y coordinate of the parameter to remove
 * @exception {Matrix.prototype.OutofBoundsException} An exception meaning the
 * element accessed was outside of the bounds of the matrix.
 */
Staffing.Matrix.prototype.removeValue = function(x, y) {
  if(x < xs.length && y < ys.length) {
    this.xs[x].remove(y);
    this.ys[y].remove(x);
  }
  else
    throw Matrix.prototype.OutOfBoundsException
};

/**
 * Checks to see if a property is set in this matrix
 *
 * @param {Number} x The x coordinate of the parameter to check
 * @param {Number} y The y coordinate of the parameter to check
 * @return {Boolean} True if set, false otherwise
 */
Staffing.Matrix.prototype.isSet = function(x, y) {
  return this.xs[x].contains(y);
};

/**
 * Counts the values in an X row
 * @param {Number} x The x number of the row to check
 * @return {Number} The number of set values
 */
Staffing.Matrix.prototype.countXVals = function(x) {
  return this.xs[x].count;
};

/**
 * Counts the values in an y column
 * @param {Number} y The y number of the column to check
 * @return {Number} The number of set values
 */
Staffing.Matrix.prototype.countYVals = function(y) {
  return this.ys[y].count
}

Staffing.Matrix.prototype.getXVals = function(x) {
  var ret = [];
  UTIL.forEachIn(this.xs[x].values, function(key, value) {
    ret.push(key);
  });
  return ret;
}
<|endoftext|>


<commit_before>import assert from 'assert';
import {
  assertThat,
  everyItem,
  hasProperty,
  endsWith,
  hasSize,
  promiseThat, is, fulfilled, fulfilledWith,
  allOf, truthy
} from 'hamjest';

import fs from 'fs';
import path from 'path';

function convertOneFile(fileName, destFileName) {
  const fileReadPromise = new Promise(resolve => {
    fs.readFile(fileName, 'utf8', (error, content) => {
      if (!error) resolve(content);
    });
  });
  return fileReadPromise.then(fileContent => {
    return new Promise(resolve => {
      fs.writeFile(destFileName, minifyJson(fileContent), 'utf8', resolve);
    });
  });
}

function minifyJson(content) {
  return content;
  return JSON.stringify(JSON.parse(content));
}

describe('converting `stars.json`', () => {

  const destFile = path.join(__dirname, '../../dist/data/stars.json');
  const sourceFile = path.join(__dirname, '../../data/stars.json');
  let promise;

  beforeEach(() => {
    if (fs.existsSync(destFile)) fs.unlinkSync(destFile);
    promise = convertOneFile(sourceFile, destFile);
  });

  it('fulfills', () => {
    return promiseThat(promise, is(fulfilled()));
  });

  it('writes the destination file', () => {
    return promiseThat(promise,
      allOf(
        fulfilled(),
        truthy(fs.existsSync(destFile))
      )
    );
  });

});
<commit_msg>Make the test really work. (Learning how to do promises right with hamcrest)<commit_after>import assert from 'assert';
import {
  assertThat,
  everyItem,
  hasProperty,
  endsWith,
  hasSize,
  promiseThat, is, fulfilled, fulfilledWith,
  allOf, truthy
} from 'hamjest';

import fs from 'fs';
import path from 'path';

function convertOneFile(fileName, destFileName) {
  const fileReadPromise = new Promise(resolve => {
    fs.readFile(fileName, 'utf8', (error, content) => {
      if (!error) resolve(content);
    });
  });
  return fileReadPromise.then(fileContent => {
    return new Promise(resolve => {
      fs.writeFile(destFileName, minifyJson(fileContent), 'utf8', resolve);
    });
  });
}

function minifyJson(content) {
  return content;
  return JSON.stringify(JSON.parse(content));
}

describe('converting `stars.json`', () => {

  const destFile = path.join(__dirname, '../../dist/data/stars.json');
  const sourceFile = path.join(__dirname, '../../data/stars.json');
  let promise;

  beforeEach(() => {
    if (fs.existsSync(destFile)) fs.unlinkSync(destFile);
    promise = convertOneFile(sourceFile, destFile);
  });

  it('fulfills', () => {
    return promiseThat(promise, is(fulfilled()));
  });

  it('writes the destination file', () => {
    return promise.then(() => assert(fs.existsSync(destFile), 'Destination file missing.'));
  });

});
<|endoftext|>


<commit_before>describe('ZendeskWidgetProvider', function() {
  'use strict';

  var subject, mockService, $window;

  beforeEach(module('zendeskWidget'));
  beforeEach(inject(function(_$window_, _ZendeskWidget_) {
    subject    = _ZendeskWidget_;
    $window    = _$window_;
  }));

  describe('a set of API methods', function() {
    beforeEach(function() {
      var apiMethods = ['setLocale', 'identify', 'hide', 'show', 'activate'];
      // Stub out $window.zE() wrapper and all apiMethods
      mockService = $window.zE = function(fn) { fn(); };
      for (var apiMethod of apiMethods) {
        $window.zE[apiMethod] = function() {};
        spyOn($window.zE, apiMethod).and.callThrough();
      }
    });

    it("delegates to Zendesk's Web Widget API", function() {
      var anyArgs = ['foo', 'bar', 'baz'];

      subject.identify(anyArgs);
      subject.hide(anyArgs);
      subject.show(anyArgs);
      subject.activate(anyArgs);
      subject.setLocale(anyArgs);

      expect(mockService.identify).toHaveBeenCalledWith(anyArgs);
      expect(mockService.hide).toHaveBeenCalledWith(anyArgs);
      expect(mockService.show).toHaveBeenCalledWith(anyArgs);
      expect(mockService.activate).toHaveBeenCalledWith(anyArgs);
      expect(mockService.setLocale).toHaveBeenCalledWith(anyArgs);
    });
  });
})
<commit_msg>test: Use old-school looping since travis stuck on ancient Chromium:<commit_after>describe('ZendeskWidgetProvider', function() {
  'use strict';

  var subject, mockService, $window;

  beforeEach(module('zendeskWidget'));
  beforeEach(inject(function(_$window_, _ZendeskWidget_) {
    subject    = _ZendeskWidget_;
    $window    = _$window_;
  }));

  describe('a set of API methods', function() {
    beforeEach(function() {
      var apiMethods = ['setLocale', 'identify', 'hide', 'show', 'activate'];
      // Stub out $window.zE() wrapper and all apiMethods
      mockService = $window.zE = function(fn) { fn(); };
      for (var i = 0; i < apiMethods.length; i++) {
        var apiMethod = apiMethods[i];
        $window.zE[apiMethod] = function() {};
        spyOn($window.zE, apiMethod).and.callThrough();
      }
    });

    it("delegates to Zendesk's Web Widget API", function() {
      var anyArgs = ['foo', 'bar', 'baz'];

      subject.identify(anyArgs);
      subject.hide(anyArgs);
      subject.show(anyArgs);
      subject.activate(anyArgs);
      subject.setLocale(anyArgs);

      expect(mockService.identify).toHaveBeenCalledWith(anyArgs);
      expect(mockService.hide).toHaveBeenCalledWith(anyArgs);
      expect(mockService.show).toHaveBeenCalledWith(anyArgs);
      expect(mockService.activate).toHaveBeenCalledWith(anyArgs);
      expect(mockService.setLocale).toHaveBeenCalledWith(anyArgs);
    });
  });
})
<|endoftext|>


<commit_before>import { expect } from 'chai';

import reducer from '../../../src/js/user-profile/reducers/profile.js';
import { UPDATE_LOGGEDIN_STATUS } from '../../../src/js/login/actions';

import {
  CREATE_MHV_ACCOUNT_SUCCESS,
  FETCH_MHV_ACCOUNT_SUCCESS,
  PROFILE_LOADING_FINISHED
} from '../../../src/js/user-profile/actions';

describe('Profile reducer', () => {
  it('should set loading to false when profile is done loading', () => {
    const state = reducer({}, { type: PROFILE_LOADING_FINISHED });
    expect(state.loading).to.be.false;
  });

  it('should set loading to false when logged in status changes', () => {
    const state = reducer({}, { type: UPDATE_LOGGEDIN_STATUS });
    expect(state.loading).to.be.false;
  });

  it('should set MHV account state after it is fetched', () => {
    const state = reducer({
      mhv: {
        account: {
          state: 'unknown'
        }
      }
    }, {
      type: FETCH_MHV_ACCOUNT_SUCCESS,
      data: {
        attributes: {
          accountState: 'upgraded'
        }
      }
    });

    expect(state.mhv.account.state).to.eq('upgraded');
  });

  it('should start polling after MHV account creation', () => {
    const state = reducer({
      mhv: {
        account: {
          state: 'unknown'
        }
      }
    }, { type: CREATE_MHV_ACCOUNT_SUCCESS });
    expect(state.mhv.account.polling).to.be.true;
    expect(state.mhv.account.polledTimes).to.eq(0);
  });

  it('should continue polling for MHV account state', () => {
    const state = reducer({
      mhv: {
        account: {
          polling: true,
          polledTimes: 0,
          state: 'registered'
        }
      }
    }, {
      type: FETCH_MHV_ACCOUNT_SUCCESS,
      data: {
        attributes: {
          accountState: 'registered'
        }
      }
    });

    expect(state.mhv.account.polling).to.be.true;
    expect(state.mhv.account.polledTimes).to.eq(1);
  });

  it('should stop polling for MHV account state once upgraded', () => {
    const state = reducer({
      mhv: {
        account: {
          polling: true,
          polledTimes: 2,
          state: 'registered'
        }
      }
    }, {
      type: FETCH_MHV_ACCOUNT_SUCCESS,
      data: {
        attributes: {
          accountState: 'upgraded'
        }
      }
    });

    expect(state.mhv.account.polling).to.be.false;
    expect(state.mhv.account.polledTimes).to.eq(0);
  });

  it('should stop polling for MHV account state upon reaching the limit for polling', () => {
    const state = reducer({
      mhv: {
        account: {
          polling: true,
          polledTimes: 10,
          state: 'registered'
        }
      }
    }, {
      type: FETCH_MHV_ACCOUNT_SUCCESS,
      data: {
        attributes: {
          accountState: 'registered'
        }
      }
    });

    expect(state.mhv.account.polling).to.be.false;
    expect(state.mhv.account.polledTimes).to.eq(0);
  });
});
<commit_msg>Updated spec for returned account state from create account action.<commit_after>import { expect } from 'chai';

import reducer from '../../../src/js/user-profile/reducers/profile.js';
import { UPDATE_LOGGEDIN_STATUS } from '../../../src/js/login/actions';

import {
  CREATE_MHV_ACCOUNT_SUCCESS,
  FETCH_MHV_ACCOUNT_SUCCESS,
  PROFILE_LOADING_FINISHED
} from '../../../src/js/user-profile/actions';

describe('Profile reducer', () => {
  it('should set loading to false when profile is done loading', () => {
    const state = reducer({}, { type: PROFILE_LOADING_FINISHED });
    expect(state.loading).to.be.false;
  });

  it('should set loading to false when logged in status changes', () => {
    const state = reducer({}, { type: UPDATE_LOGGEDIN_STATUS });
    expect(state.loading).to.be.false;
  });

  it('should set MHV account state after it is fetched', () => {
    const state = reducer({
      mhv: {
        account: {
          state: 'unknown'
        }
      }
    }, {
      type: FETCH_MHV_ACCOUNT_SUCCESS,
      data: {
        attributes: {
          accountState: 'upgraded'
        }
      }
    });

    expect(state.mhv.account.state).to.eq('upgraded');
  });

  it('should poll after MHV account creation if not yet upgraded', () => {
    const state = reducer({
      mhv: {
        account: {
          state: 'unknown'
        }
      }
    }, {
      type: CREATE_MHV_ACCOUNT_SUCCESS,
      data: {
        attributes: {
          accountState: 'unknown'
        }
      }
    });
    expect(state.mhv.account.polling).to.be.true;
    expect(state.mhv.account.polledTimes).to.eq(0);
    expect(state.mhv.account.state).to.eq('unknown');
  });

  it('should not poll after MHV account creation if upgraded', () => {
    const state = reducer({
      mhv: {
        account: {
          state: 'unknown'
        }
      }
    }, {
      type: CREATE_MHV_ACCOUNT_SUCCESS,
      data: {
        attributes: {
          accountState: 'upgraded'
        }
      }
    });
    expect(state.mhv.account.polling).to.be.false;
    expect(state.mhv.account.polledTimes).to.eq(0);
    expect(state.mhv.account.state).to.eq('upgraded');
  });

  it('should continue polling for MHV account state', () => {
    const state = reducer({
      mhv: {
        account: {
          polling: true,
          polledTimes: 0,
          state: 'registered'
        }
      }
    }, {
      type: FETCH_MHV_ACCOUNT_SUCCESS,
      data: {
        attributes: {
          accountState: 'registered'
        }
      }
    });

    expect(state.mhv.account.polling).to.be.true;
    expect(state.mhv.account.polledTimes).to.eq(1);
  });

  it('should stop polling for MHV account state once upgraded', () => {
    const state = reducer({
      mhv: {
        account: {
          polling: true,
          polledTimes: 2,
          state: 'registered'
        }
      }
    }, {
      type: FETCH_MHV_ACCOUNT_SUCCESS,
      data: {
        attributes: {
          accountState: 'upgraded'
        }
      }
    });

    expect(state.mhv.account.polling).to.be.false;
    expect(state.mhv.account.polledTimes).to.eq(0);
  });

  it('should stop polling for MHV account state upon reaching the limit for polling', () => {
    const state = reducer({
      mhv: {
        account: {
          polling: true,
          polledTimes: 10,
          state: 'registered'
        }
      }
    }, {
      type: FETCH_MHV_ACCOUNT_SUCCESS,
      data: {
        attributes: {
          accountState: 'registered'
        }
      }
    });

    expect(state.mhv.account.polling).to.be.false;
    expect(state.mhv.account.polledTimes).to.eq(0);
  });
});
<|endoftext|>


<commit_before>/**
 * For parsing strings like :
 * click ( '12', 14, true, blur(2, 4, hello( false).foo())). bar(12345)
 */
(function() {
    if (typeof require !== 'undefined')
        elenpi = require('../index.js');

    var r = elenpi.r,
        Parser = elenpi.Parser;

    var rules = {
        doublestring: r().regExp(/^"([^"]*)"/, false, function(descriptor, cap) {
            descriptor.value = cap[1];
        }),
        singlestring: r().regExp(/^'([^']*)'/, false, function(descriptor, cap) {
            descriptor.value = cap[1];
        }),
        "float": r().regExp(/^[0-9]*\.[0-9]+/, false, function(descriptor, cap) {
            descriptor.value = parseFloat(cap[0], 10);
        }),
        integer: r().regExp(/^[0-9]+/, false, function(descriptor, cap) {
            descriptor.value = parseInt(cap[0], 10);
        }),
        bool: r().regExp(/^(true|false)/, false, function(descriptor, cap) {
            descriptor.value = (cap[1] === 'true') ? true : false;
        }),
        //_____________________________________
        calls: r()
            .space()
            .zeroOrMore('calls',
                'call',
                r().regExp(/^\s*\.\s*/)
            ),

        call: r()
            .regExp(/^([\w-_]+)\s*/, false, function(descriptor, cap) {
                descriptor.method = cap[1];
            })
            .zeroOrOne(
                r()
                .regExp(/^\(\s*/)
                .zeroOrMore('arguments',
                    r().oneOf(['integer', 'bool', 'singlestring', 'doublestring', 'calls']),
                    r().regExp(/^\s*,\s*/)
                )
                .regExp(/^\s*\)/)
            )
    };
    var parser = new Parser(rules, 'calls');
    if (typeof module !== 'undefined' && module.exports)
        module.exports = parser;
    else
        this.chainedMethodParser = parser;
})()
<commit_msg>place chained method parser in elenpi at exports<commit_after>/**
 * For parsing strings like :
 * click ( '12', 14, true, blur(2, 4, hello( false).foo())). bar(12345)
 */
(function() {
    if (typeof require !== 'undefined')
        elenpi = require('../index.js');

    var r = elenpi.r,
        Parser = elenpi.Parser;

    var rules = {
        doublestring: r().regExp(/^"([^"]*)"/, false, function(descriptor, cap) {
            descriptor.value = cap[1];
        }),
        singlestring: r().regExp(/^'([^']*)'/, false, function(descriptor, cap) {
            descriptor.value = cap[1];
        }),
        "float": r().regExp(/^[0-9]*\.[0-9]+/, false, function(descriptor, cap) {
            descriptor.value = parseFloat(cap[0], 10);
        }),
        integer: r().regExp(/^[0-9]+/, false, function(descriptor, cap) {
            descriptor.value = parseInt(cap[0], 10);
        }),
        bool: r().regExp(/^(true|false)/, false, function(descriptor, cap) {
            descriptor.value = (cap[1] === 'true') ? true : false;
        }),
        //_____________________________________
        calls: r()
            .space()
            .zeroOrMore('calls',
                'call',
                r().regExp(/^\s*\.\s*/)
            ),

        call: r()
            .regExp(/^([\w-_]+)\s*/, false, function(descriptor, cap) {
                descriptor.method = cap[1];
            })
            .zeroOrOne(
                r()
                .regExp(/^\(\s*/)
                .zeroOrMore('arguments',
                    r().oneOf(['integer', 'bool', 'singlestring', 'doublestring', 'calls']),
                    r().regExp(/^\s*,\s*/)
                )
                .regExp(/^\s*\)/)
            )
    };
    var parser = new Parser(rules, 'calls');
    if (typeof module !== 'undefined' && module.exports)
        module.exports = parser;
    else
        elenpi.chainedMethodParser = parser;
})();
<|endoftext|>


<commit_before>'use strict';

/* eslint-env mocha */

const assert = require('assert');
const Request = require('../src/Request');

describe('Request.js', () => {
  it('should be empty if nothing is set', () => {
    const actual =
      new Request()
        .getOptions();
    const expected = {};
    assert.deepEqual(expected, actual);
  });

  it('should be able to handle one simple options', () => {
    const actual =
      new Request()
        .addOptions({
          url: 'http://google.de',
        })
        .getOptions();
    const expected = { url: 'http://google.de' };
    assert.deepEqual(expected, actual);
  });

  it('should be able to handle url object options', () => {
    const actual =
      new Request()
        .addOptions({
          url: {
            hostname: 'google.de',
            protocol: 'http',
          },
        })
        .getOptions();
    const expected = { url: 'http://google.de' };
    assert.deepEqual(expected, actual);
  });

  it('should be able to handle object options', () => {
    const actual =
      new Request()
        .addOptions({
          toRequestOptions: () => ({
            url: 'http://google.de',
          }),
        })
        .getOptions();
    const expected = { url: 'http://google.de' };
    assert.deepEqual(expected, actual);
  });

  it('should merge options with different attributes', () => {
    const actual =
      new Request()
        .addOptions({
          method: 'post',
        })
        .addOptions({
          url: 'http://google.de',
        })
        .getOptions();
    const expected = { method: 'post', url: 'http://google.de' };
    assert.deepEqual(expected, actual);
  });

  it('should overwrite options with the same attributes and number values', () => {
    const actual =
      new Request()
        .addOptions({
          number: 1,
        })
        .addOptions({
          number: 2,
        })
        .getOptions();
    const expected = { number: 2 };
    assert.deepEqual(expected, actual);
  });

  it('should overwrite options with the same attributes and string values', () => {
    const actual =
      new Request()
        .addOptions({
          string: 'a',
        })
        .addOptions({
          string: 'b',
        })
        .getOptions();
    const expected = { string: 'b' };
    assert.deepEqual(expected, actual);
  });

  it('should concatenate options with the same attributes and array values', () => {
    const actual =
      new Request()
        .addOptions({})
        .addOptions({
          array: ['a'],
        })
        .addOptions({
          array: ['b'],
        })
        .getOptions();
    const expected = { array: ['a', 'b'] };
    assert.deepEqual(expected, actual);
  });
});
<commit_msg>Add some more tests for the added features<commit_after>'use strict';

/* eslint-env mocha */

const assert = require('assert');
const Request = require('../src/Request');

describe('Request.js', () => {
  it('should be empty if nothing is set', () => {
    const actual =
      new Request()
        .getOptions();
    const expected = {};
    assert.deepEqual(expected, actual);
  });

  it('should be able to handle one simple options', () => {
    const actual =
      new Request()
        .addOptions({
          url: 'http://google.de',
        })
        .getOptions();
    const expected = { url: 'http://google.de' };
    assert.deepEqual(expected, actual);
  });

  it('should be able to handle simple url object options', () => {
    const actual =
      new Request()
        .addOptions({
          url: {
            hostname: 'google.de',
            protocol: 'http',
          },
        })
        .getOptions();
    const expected = { url: 'http://google.de' };
    assert.deepEqual(expected, actual);
  });

  it('should be able to handle complex url object options with queries', () => {
    const actual =
      new Request()
        .addOptions({
          url: {
            hostname: 'google.de',
            protocol: 'http',
            query: {
              'a[]': ['b', 'c'],
              d: ['e'],
            }
          },
        })
        .getOptions();
    const expected = { url: 'http://google.de?a%5B%5D=b&a%5B%5D=c&d=e' };
    assert.deepEqual(expected, actual);
  });

  it('should be able to handle complex url object options with searchs', () => {
    const actual =
      new Request()
        .addOptions({
          url: {
            hostname: 'google.de',
            protocol: 'http',
            search: {
              'a[]': ['b', 'c'],
              d: ['e'],
            }
          },
        })
        .getOptions();
    const expected = { url: 'http://google.de?a%5B%5D=b&a%5B%5D=c&d=e' };
    assert.deepEqual(expected, actual);
  });

  it('should be able to handle object options', () => {
    const actual =
      new Request()
        .addOptions({
          toRequestOptions: () => ({
            url: 'http://google.de',
          }),
        })
        .getOptions();
    const expected = { url: 'http://google.de' };
    assert.deepEqual(expected, actual);
  });

  it('should merge options with different attributes', () => {
    const actual =
      new Request()
        .addOptions({
          method: 'post',
        })
        .addOptions({
          url: 'http://google.de',
        })
        .getOptions();
    const expected = { method: 'post', url: 'http://google.de' };
    assert.deepEqual(expected, actual);
  });

  it('should overwrite options with the same attributes and number values', () => {
    const actual =
      new Request()
        .addOptions({
          number: 1,
        })
        .addOptions({
          number: 2,
        })
        .getOptions();
    const expected = { number: 2 };
    assert.deepEqual(expected, actual);
  });

  it('should overwrite options with the same attributes and string values', () => {
    const actual =
      new Request()
        .addOptions({
          string: 'a',
        })
        .addOptions({
          string: 'b',
        })
        .getOptions();
    const expected = { string: 'b' };
    assert.deepEqual(expected, actual);
  });

  it('should concatenate options with the same attributes and array values', () => {
    const actual =
      new Request()
        .addOptions({})
        .addOptions({
          array: ['a'],
        })
        .addOptions({
          array: ['b'],
        })
        .getOptions();
    const expected = { array: ['a', 'b'] };
    assert.deepEqual(expected, actual);
  });

  it('should accept also an array of options', () => {
    const actual =
      new Request()
        .addOptions([
          {
            method: 'post',
          },
          {
            url: 'http://google.de',
          },
        ])
        .getOptions();
    const expected = { method: 'post', url: 'http://google.de' };
    assert.deepEqual(expected, actual);
  });
});
<|endoftext|>


<commit_before>angular.module('bolt.createProfile', [])

.controller('CreateProfileController', function($location, $scope, Profile, $window) {
  $scope.createProfile = function(first, last, email, phone, distance) {
    $location.path('/');

    var newData = {
      firstName: first,
      lastName: last,
      email: email,
      phone: phone.toString(),
      preferredDistance: distance
    };

    $window.localStorage.setItem('firstName', first);
    $window.localStorage.setItem('lastName', last);
    $window.localStorage.setItem('phone', phone);
    $window.localStorage.setItem('email', email);
    $window.localStorage.setItem('preferredDistance', distance);

    Profile.getUser()
    .then(function(currentUser) {
      Profile.updateUser(newData, currentUser)
      .catch(function (err) {
        console.error(err);
      });
    });
  };
})

<commit_msg>Fix and ungodly number of linter errors<commit_after>angular.module('bolt.createProfile', [])

.controller('CreateProfileController', function ($location, $scope, Profile, $window) {
  $scope.createProfile = function (first, last, email, phone, distance) {
    $location.path('/');

    var newData = {
      firstName: first,
      lastName: last,
      email: email,
      phone: phone.toString(),
      preferredDistance: distance
    };

    $window.localStorage.setItem('firstName', first);
    $window.localStorage.setItem('lastName', last);
    $window.localStorage.setItem('phone', phone);
    $window.localStorage.setItem('email', email);
    $window.localStorage.setItem('preferredDistance', distance);

    Profile.getUser()
    .then(function (currentUser) {
      Profile.updateUser(newData, currentUser)
      .catch(function (err) {
        console.error(err);
      });
    });
  };
});
<|endoftext|>


<commit_before>var AWS = require('aws-sdk'),
    cloudwatchlogs,
    _ = require('lodash'),
    logEvents = [],
    logGroupName = '',
    logStreamName = '',
    messageAsJSON,
    intervalId;

module.exports.init = function(awsLogGroupName, awsLogStreamName, awsAccessKeyId, awsSecretKey, awsRegion, jsonMessage) {
  if (awsAccessKeyId && awsSecretKey && awsRegion) {
    cloudwatchlogs = new AWS.CloudWatchLogs({accessKeyId: awsAccessKeyId, secretAccessKey: awsSecretKey, region: awsRegion});
  } else if (awsRegion && !awsAccessKeyId && !awsSecretKey) {
    // Amazon SDK will automatically pull access credentials from IAM Role when running on EC2 but region still needs to be configured
    cloudwatchlogs = new AWS.CloudWatchLogs({region: awsRegion});
  } else {
    cloudwatchlogs = new AWS.CloudWatchLogs();
  }
  logGroupName = awsLogGroupName;
  logStreamName = awsLogStreamName;
  messageAsJSON = jsonMessage;
};

module.exports.add = function(log) {
  logEvents.push({
    message: messageAsJSON ? JSON.stringify(log, null, '  ') : [log.level, log.msg, JSON.stringify(log.meta, null, '  ')].join(' - '),
    timestamp: new Date().getTime()
  });

  var lastFree = new Date().getTime();
  function upload() {
    if (new Date().getTime() - 2000 > lastFree) {
      token(function(err, sequenceToken) {
        if (err) {
          return console.log(err, err.stack);
        }

        if (logEvents.length <= 0) {
          return;
        }

        var payload = {
          logGroupName: logGroupName,
          logStreamName: logStreamName,
          logEvents: logEvents.splice(0, 20)
        };
        if (sequenceToken) payload.sequenceToken = sequenceToken;

        cloudwatchlogs.putLogEvents(payload, function(err, data) {
          if (err) return console.log(err, err.stack);
          lastFree = new Date().getTime();
        });
      });
    }
  }
  if (!intervalId) {
    intervalId = setInterval(upload, 1000);
  }
};

function findLogStream(logGroupName, logStreamName, cb) {
  function next(token) {
    var params = {
      logStreamNamePrefix: logStreamName,
      logGroupName: logGroupName
    };
    cloudwatchlogs.describeLogStreams(params, function(err, data) {
      if (err) return cb(err);
      var matches = _.find(data.logStreams, function(logStream) {
        return (logStream.logStreamName === logStreamName);
      });
      if (matches) {
        cb(null, matches);
      } else if (!data.nextToken) {
        cb(new Error('Stream not found'));
      } else {
        next(data.nextToken);
      }
    });
  }
  next();
}

function token(cb) {
  findLogStream(logGroupName, logStreamName, function(err, logStream) {
    if (err) {
      if(err.message === 'Stream not found'){
        return createLogStream(logGroupName, logStreamName, cb);
      }
      return cb(err);
    }
    cb(null, logStream.uploadSequenceToken);
  });
}

function createLogStream(logGroupName, logStreamName, cb){
  cloudwatchlogs.createLogStream({
    logGroupName: logGroupName,
    logStreamName: logStreamName
  }, function(err, data){
      if(err) cb(err);
      else token(cb);
  });
}
<commit_msg>Closes #23: retry on non existing resources<commit_after>var AWS = require('aws-sdk'),
    cloudwatchlogs,
    _ = require('lodash'),
    logEvents = [],
    logGroupName = '',
    logStreamName = '',
    messageAsJSON,
    intervalId;

module.exports.init = function(awsLogGroupName, awsLogStreamName, awsAccessKeyId, awsSecretKey, awsRegion, jsonMessage) {
  if (awsAccessKeyId && awsSecretKey && awsRegion) {
    cloudwatchlogs = new AWS.CloudWatchLogs({accessKeyId: awsAccessKeyId, secretAccessKey: awsSecretKey, region: awsRegion});
  } else if (awsRegion && !awsAccessKeyId && !awsSecretKey) {
    // Amazon SDK will automatically pull access credentials from IAM Role when running on EC2 but region still needs to be configured
    cloudwatchlogs = new AWS.CloudWatchLogs({region: awsRegion});
  } else {
    cloudwatchlogs = new AWS.CloudWatchLogs();
  }
  logGroupName = awsLogGroupName;
  logStreamName = awsLogStreamName;
  messageAsJSON = jsonMessage;
};

module.exports.add = function(log) {
  logEvents.push({
    message: messageAsJSON ? JSON.stringify(log, null, '  ') : [log.level, log.msg, JSON.stringify(log.meta, null, '  ')].join(' - '),
    timestamp: new Date().getTime()
  });

  var lastFree = new Date().getTime();
  function upload() {
    if (new Date().getTime() - 2000 > lastFree) {
      token(function(err, sequenceToken) {
        if (err) {
          return console.log(err, err.stack);
        }

        if (logEvents.length <= 0) {
          return;
        }

        var payload = {
          logGroupName: logGroupName,
          logStreamName: logStreamName,
          logEvents: logEvents.splice(0, 20)
        };
        if (sequenceToken) payload.sequenceToken = sequenceToken;

        cloudwatchlogs.putLogEvents(payload, function(err, data) {
          if (err) return console.log(err, err.stack);
          lastFree = new Date().getTime();
        });
      });
    }
  }
  if (!intervalId) {
    intervalId = setInterval(upload, 1000);
  }
};

function findLogStream(logGroupName, logStreamName, cb) {
  function next(token) {
    var params = {
      logStreamNamePrefix: logStreamName,
      logGroupName: logGroupName
    };
    cloudwatchlogs.describeLogStreams(params, function(err, data) {
      if (err) {
        if(err.code === 'ResourceNotFoundException'){
          return createLogGroup(logGroupName, cb);
        }
        return cb(err);
      }

      var matches = _.find(data.logStreams, function(logStream) {
        return (logStream.logStreamName === logStreamName);
      });
      if (matches) {
        cb(null, matches);
      } else if (!data.nextToken) {
        cb(new Error('Stream not found'));
      } else {
        next(data.nextToken);
      }
    });
  }
  next();
}

function token(cb) {
  findLogStream(logGroupName, logStreamName, function(err, logStream) {
    if (err) {
      if(err.message === 'Stream not found'){
        return createLogStream(logGroupName, logStreamName, cb);
      }
      return cb(err);
    }
    cb(null, logStream.uploadSequenceToken);
  });
}

function createLogStream(logGroupName, logStreamName, cb){
  cloudwatchlogs.createLogStream({
    logGroupName: logGroupName,
    logStreamName: logStreamName
  }, function(err, data){
      if(err) cb(err);
      else token(cb);
  });
}

function createLogGroup(logGroupName, cb){
  cloudwatchlogs.createLogGroup({
    logGroupName: logGroupName
  }, function(err, data){
      if(err) cb(err);
      else findLogStream(logGroupName, logStreamName, cb);
  });
}
<|endoftext|>


<commit_before>/*jshint multistr: true */
'use strict';

angular.module('observatory3App')
.controller('ProjectsProfileCtrl', function ($scope, $http, $stateParams, $location, $uibModal, Auth, Upload, Project, notify) {
    $scope.imgPrefix = '/uploads/';
    $scope.userOnProject = false;
    $scope.project = {};
    var updateProject = function(){
        Project.getProject($stateParams.username, $stateParams.project).then(function(result) {
            $scope.project = result.data;
            initializeSlides($scope.project.photos);
            getAuthors();
            Auth.isLoggedInAsync(function(loggedIn){
                if (loggedIn){
                    var user = Auth.getCurrentUser();
                    $scope.user = user;
                    $scope.checkUserProject();
                }
            });
        },function(){
          $location.path('/projects');
        });
    };
    updateProject();

    $scope.selectImage = function() {
      angular.element('#uploadImage').trigger('click');
    };
    $scope.editProject = function() {
      $scope.editedProject = angular.copy($scope.project);

      var modalInstance = $uibModal.open({
        templateUrl: 'components/editProject/editProject.html',
        controller: 'projectEditController',

        resolve: {
          editProject: function () {
            return  $scope.editedProject;
          },
        }
      });

      modalInstance.result.then(function (projectAdded) {
        // $window.location.reload();
        var redirectUsername = projectAdded.githubUsername;
        var redirectProjectName = projectAdded.githubProjectName;
        if (redirectUsername === $stateParams.username && redirectProjectName === $stateParams.project){
          $scope.project=projectAdded;
          updateProject();
        }
        else{
          $location.path( 'projects/' + redirectUsername + '/' + redirectProjectName + '/profile');
        }

      }, function(){

      });
    };

    var getAuthors = function() {
        var project = $scope.project;
        $http.get('/api/projects/' + project._id + '/authors')
            .success(function(authors){
                $scope.authors = authors;
            })
    }

    $scope.getPic = function(user) {
        if (! ('avatar' in user)){
            user.avatar = "//www.gravatar.com/avatar/00000000000000000000000000000000?d=monsterid";
            $http.get('/api/users/' + user._id + '/avatar').success(function(avatar){
                user.avatar = avatar;
            });
        } else {
        }
        return user.avatar
    }

    var initializeSlides = function(photos) {
        var slides = [];
        if(photos.length > 0) {
          for (var i = 0; i < photos.length; i++){
              slides.push({
                  id: i,
                  active: false,
                  image: $scope.imgPrefix + photos[i],
                  src: photos[i]
              });
              if (i === 0) {
                  slides[0].active = true;
              }
          }
        }
        else {
          slides.push({
            id: 0,
            active: true,
            placeholder: true,
            image: '../../assets/images/projectplaceholder.png',
            src: '../../assets/images/projectplaceholder.png'
          });
        }
        $scope.slides = slides;
    }

    var getAuthors = function() {
        var project = $scope.project;
        $http.get('/api/projects/' + project._id + '/authors')
        .success(function(authors){
            $scope.authors = authors;
        });
    };

    $scope.isLoggedIn = Auth.isLoggedIn;
    $scope.isAdmin = Auth.isAdmin;
    $scope.isMentor = Auth.isMentor;

    $scope.joinProject = function(){
        $http.put('/api/users/' + $scope.user._id + '/project',{
            'project': $scope.project._id
        }).success(function(){
            notify({ message: "You are now on this project!"  });
            $scope.userOnProject = true;
            $scope.user.projects.push($scope.project._id);
            getAuthors();
        }).error(function(){
            notify({message: 'Error adding user to project!', classes: ["alert-danger"]});
        });
    };

    $scope.leaveProject = function(){
        var loggedInUser = Auth.getCurrentUser();
        $http.delete('/api/users/' + loggedInUser._id + '/project',
        {
            'project': $scope.project._id
        }).success(function(){
            notify({message: "You are now off this project!", classes: []});
            $scope.user.projects.splice($scope.user.projects.indexOf($scope.project._id), 1);
            $scope.userOnProject = false;
            getAuthors();
        }).error(function(){
            notify({message: 'Error removing user from project!', classes: ["alert-danger"]});
        });
    };

    $scope.markPast = function(){
        $http.put('api/projects/'+$scope.project._id+'/markPast').success(function(){
            notify("Project marked as past project");
            updateProject();
        }).error(function(){
            notify("Project not marked as a past project")
        });
    };

    $scope.markActive =  function(){
        $http.put('api/projects/'+$scope.project._id+'/markActive').success(function(){
            notify("Project marked as a current project");
            updateProject();
        }).error(function(){
            notify("ERROR: Project not marked as a current project")
        });
    };

    $scope.markDefault = function(){
        $http.put('api/projects/'+$scope.project._id+'/markdefault').success(function(){
            notify("Project marked as default");
            updateProject();
        }).error(function(){
            notify("Could not mark project as default!");
        });
    };

    $scope.unmarkDefault = function(){
        $http.put('api/projects/'+$scope.project._id+'/unmarkdefault').success(function(){
            notify("Project unmarked as default");
            updateProject();
        }).error(function(){
            notify("Could not unmark project as default!");
        });
    };

    $scope.checkUserProject = function() {
        $scope.userOnProject = $scope.user.projects.indexOf($scope.project._id) !== -1;
    };

    $scope.upload = function($file) {
      if ($file) {
        if($file.$error == "maxSize") {
          notify({ message: "Error: This image is too large, please upload a smaller image.", classes: ["alert-danger"] });
          return;
        }
        Upload.upload({
            url: 'api/projects/'+$stateParams.username+'/'+$stateParams.project+'/upload',
            data: {file: $file}
        }).success(function (data) {
            location.reload();
        }).error(function (data, status) {
            console.log('error status: ' + status);
        });
      }
    };

    $scope.deletePhoto = function(){
        var username = $scope.project.githubUsername;
        var projectName = $scope.project.githubProjectName;
        var activePhoto = $scope.slides[$scope.active];
        if (activePhoto){
            $http.delete('/api/projects/' +  username + '/' + projectName + '/' + activePhoto.src)
            .success(function(){
                location.reload();
            });
        }
    };
//tech bubble code
	$scope.isMentor = Auth.isMentor;
	$scope.addTechBubble = function(){
        if($scope.insertTechContent){
          $http.put('/api/projects/addTechBubble/' + $scope.project._id + '/' + $scope.insertTechContent).success(function(){
              $scope.project.tech.push($scope.insertTechContent);
              $scope.insertTechContent = '';
          }).error(function(){
              notify({message: "Could not add tech!", classes: ["alert-danger"]});
          });
        }
      };
   $scope.removeTech = function(tech){
          $http.put('/api/projects/' + $scope.project._id + '/' + tech + '/removeTech').success(function(){
				$scope.project.tech.splice($scope.project.tech.indexOf(tech),1);
          }).error(function(){
              notify({message: "Could not remove tech!", classes: ["alert-danger"]});
          });
      };

//end tech bubble code
});
<commit_msg>Syntax fixing on page<commit_after>/*jshint multistr: true */
'use strict';

angular.module('observatory3App')
.controller('ProjectsProfileCtrl', function ($scope, $http, $stateParams, $location, $uibModal, Auth, Upload, Project, notify) {
  $scope.imgPrefix = '/uploads/';
  $scope.userOnProject = false;
  $scope.project = {};

  $scope.selectImage = function() {
    angular.element('#uploadImage').trigger('click');
  };
  $scope.editProject = function() {
    $scope.editedProject = angular.copy($scope.project);

    var modalInstance = $uibModal.open({
      templateUrl: 'components/editProject/editProject.html',
      controller: 'projectEditController',

      resolve: {
        editProject: function () {
          return  $scope.editedProject;
        },
      }
    });

    modalInstance.result.then(function (projectAdded) {
      // $window.location.reload();
      var redirectUsername = projectAdded.githubUsername;
      var redirectProjectName = projectAdded.githubProjectName;
      if (redirectUsername === $stateParams.username && redirectProjectName === $stateParams.project){
        $scope.project=projectAdded;
        updateProject();
      }
      else{
        $location.path( 'projects/' + redirectUsername + '/' + redirectProjectName + '/profile');
      }
    }, function(){});
  };

  var getAuthors = function() {
    var project = $scope.project;
    $http.get('/api/projects/' + project._id + '/authors')
      .success(function(authors){
        $scope.authors = authors;
      });
  };

  $scope.getPic = function(user) {
    if (! ('avatar' in user)){
      user.avatar = '//www.gravatar.com/avatar/00000000000000000000000000000000?d=monsterid';
      $http.get('/api/users/' + user._id + '/avatar').success(function(avatar){
        user.avatar = avatar;
      });
    } else {
    }
    return user.avatar;
  };

  var initializeSlides = function(photos) {
    var slides = [];
    if(photos.length > 0) {
      for (var i = 0; i < photos.length; i++){
        slides.push({
          id: i,
          active: false,
          image: $scope.imgPrefix + photos[i],
          src: photos[i]
        });
        if (i === 0) {
          slides[0].active = true;
        }
      }
    }
    else {
      slides.push({
        id: 0,
        active: true,
        placeholder: true,
        image: '../../assets/images/projectplaceholder.png',
        src: '../../assets/images/projectplaceholder.png'
      });
    }
    $scope.slides = slides;
  };

  $scope.isLoggedIn = Auth.isLoggedIn;
  $scope.isAdmin = Auth.isAdmin;
  $scope.isMentor = Auth.isMentor;

  $scope.joinProject = function(){
    $http.put('/api/users/' + $scope.user._id + '/project',{
      'project': $scope.project._id
    }).success(function(){
      notify({ message: 'You are now on this project!'});
      $scope.userOnProject = true;
      $scope.user.projects.push($scope.project._id);
      getAuthors();
    }).error(function(){
      notify({message: 'Error adding user to project!', classes: ['alert-danger']});
    });
  };

  $scope.leaveProject = function(){
    var loggedInUser = Auth.getCurrentUser();
    $http.delete('/api/users/' + loggedInUser._id + '/project',
        {
          'project': $scope.project._id
        }).success(function(){
      notify({message: 'You are now off this project!', classes: []});
      $scope.user.projects.splice($scope.user.projects.indexOf($scope.project._id), 1);
      $scope.userOnProject = false;
      getAuthors();
    }).error(function(){
          notify({message: 'Error removing user from project!', classes: ['alert-danger']});
        });
  };

  $scope.markPast = function(){
    $http.put('api/projects/'+$scope.project._id+'/markPast').success(function(){
      notify('Project marked as past project');
      updateProject();
    }).error(function(){
      notify('Project not marked as a past project');
    });
  };

  $scope.markActive =  function(){
    $http.put('api/projects/'+$scope.project._id+'/markActive').success(function(){
      notify('Project marked as a current project');
      updateProject();
    }).error(function(){
      notify('ERROR: Project not marked as a current project');
    });
  };

  $scope.markDefault = function(){
    $http.put('api/projects/'+$scope.project._id+'/markdefault').success(function(){
      notify('Project marked as default');
      updateProject();
    }).error(function(){
      notify('Could not mark project as default!');
    });
  };

  $scope.unmarkDefault = function(){
    $http.put('api/projects/'+$scope.project._id+'/unmarkdefault').success(function(){
      notify('Project unmarked as default');
      updateProject();
    }).error(function(){
      notify('Could not unmark project as default!');
    });
  };

  $scope.checkUserProject = function() {
    $scope.userOnProject = $scope.user.projects.indexOf($scope.project._id) !== -1;
  };

  $scope.upload = function($file) {
    if ($file) {
      if($file.$error === 'maxSize') {
        notify({ message: 'Error: This image is too large, please upload a smaller image.', classes: ['alert-danger'] });
        return;
      }
      Upload.upload({
        url: 'api/projects/'+$stateParams.username+'/'+$stateParams.project+'/upload',
        data: {file: $file}
      }).success(function () {
        location.reload();
      }).error(function (data, status) {
        console.log('error status: ' + status);
      });
    }
  };

  $scope.deletePhoto = function(){
    var username = $scope.project.githubUsername;
    var projectName = $scope.project.githubProjectName;
    var activePhoto = $scope.slides[$scope.active];
    if (activePhoto){
      $http.delete('/api/projects/' +  username + '/' + projectName + '/' + activePhoto.src)
        .success(function(){
          location.reload();
        });
    }
  };
  //tech bubble code
  $scope.isMentor = Auth.isMentor;
  $scope.addTechBubble = function(){
    if($scope.insertTechContent){
      $http.put('/api/projects/addTechBubble/' + $scope.project._id + '/' + $scope.insertTechContent).success(function(){
        $scope.project.tech.push($scope.insertTechContent);
        $scope.insertTechContent = '';
      }).error(function(){
        notify({message: 'Could not add tech!', classes: ['alert-danger']});
      });
    }
  };
  $scope.removeTech = function(tech){
    $http.put('/api/projects/' + $scope.project._id + '/' + tech + '/removeTech').success(function(){
      $scope.project.tech.splice($scope.project.tech.indexOf(tech),1);
    }).error(function(){
      notify({message: 'Could not remove tech!', classes: ['alert-danger']});
    });
  };

  //end tech bubble code

  var updateProject = function(){
    Project.getProject($stateParams.username, $stateParams.project).then(function(result) {
      $scope.project = result.data;
      initializeSlides($scope.project.photos);
      getAuthors();
      Auth.isLoggedInAsync(function(loggedIn){
        if (loggedIn){
          var user = Auth.getCurrentUser();
          $scope.user = user;
          $scope.checkUserProject();
        }
      });
    },function(){
      $location.path('/projects');
    });
  };
  updateProject();

});
<|endoftext|>


<commit_before>'use strict';

const Promise = require('bluebird');
const makeLogs = require('./storage/logs');
const messageModule = require('./services/messaging');
const _ = require('lodash');

module.exports = function (context) {
    const events = context.apis.foundation.getSystemEvents();
    const logger = context.apis.foundation.makeLogger({ module: 'cluster_master' });
    const clusterConfig = context.sysconfig.teraslice;
    const parseError = require('error_parser');

    // Initialize the HTTP service for handling incoming requests.
    const app = require('express')();
    const server = app.listen(clusterConfig.port);
    logger.info(`listening on port ${clusterConfig.port}`);

    const messaging = messageModule(context, logger);
    context.messaging = messaging;
    context.services = {};

    const assetServiceOnline = assetServicelistener();

    // ignore process calls, this is handled by ipc messages from node master
    messaging.register({ event: 'process:SIGTERM', callback: () => {} });
    messaging.register({ event: 'process:SIGINT', callback: () => {} });

    // event is fired from terafoundation when an error occurs during instantiation of a client
    events.on('getClient:config_error', terminalShutdown);

    function terminalShutdown(errEV) {
        logger.error(`Terminal error: ${errEV.err}`);
        messaging.send({ to: 'node_master', message: 'cluster:error:terminal' });
    }

    messaging.register({
        event: 'worker:shutdown',
        callback: () => {
            logger.info('cluster_master is shutting down');
            Promise.all(_.map(context.services, service => service.shutdown()))
                .then(() => logger.flush())
                .then(() => process.exit())
                .catch((err) => {
                    const errMsg = parseError(err);
                    logger.error(`Error while cluster_master shutting down, error: ${errMsg}`);
                    setTimeout(() => {
                        process.exit(0);
                    }, 10);
                });
        }
    });

    function assetServicelistener() {
        let assetsServiceIsReady = false;
        let assetsServiceError = false;

        messaging.register({
            event: 'assets:service:available',
            callback: (assetServiceResponse) => {
                if (assetServiceResponse.error) {
                    assetsServiceError = true;
                } else {
                    assetsServiceIsReady = true;
                }
            }
        });
        return () => new Promise(((resolve, reject) => {
            if (assetsServiceIsReady) {
                resolve(true);
            } else {
                const assetReady = setInterval(() => {
                    if (assetsServiceIsReady) {
                        clearInterval(assetReady);
                        resolve(true);
                    }
                    if (assetsServiceError) {
                        clearInterval(assetReady);
                        reject('An error occurred while instantiating the assets service');
                    }
                }, 100);
            }
        }));
    }
    require('./services/execution.js')(context)
        .then((clusterService) => {
            messaging.initialize({ server });
            logger.trace('cluster_service has instantiated');
            context.services.execution = clusterService;
            return require('./services/jobs')(context);
        })
        .then((jobsService) => {
            logger.trace('jobs_service has instantiated');
            context.services.jobs = jobsService;
            return assetServiceOnline();
        })
        .then(() => require('./services/api')(context, app))
        .then((apiService) => {
            logger.trace('api_service has instantiated');
            context.services.api = apiService;
            return makeLogs(context);
        })
        .then(() => logger.info('Ready'))
        .catch((err) => {
            const errMsg = parseError(err);
            logger.error('error during service initialization', errMsg);
            messaging.send({ to: 'node_master', message: 'cluster:error:terminal' });
        });
};
<commit_msg>changed express timeout to 5mins resolves #621 (#630)<commit_after>'use strict';

const Promise = require('bluebird');
const makeLogs = require('./storage/logs');
const messageModule = require('./services/messaging');
const _ = require('lodash');

module.exports = function (context) {
    const events = context.apis.foundation.getSystemEvents();
    const logger = context.apis.foundation.makeLogger({ module: 'cluster_master' });
    const clusterConfig = context.sysconfig.teraslice;
    const parseError = require('error_parser');

    // Initialize the HTTP service for handling incoming requests.
    const app = require('express')();
    const server = app.listen(clusterConfig.port);
    // setting request timeout to 5 minutes
    server.timeout = 300000;
    logger.info(`listening on port ${clusterConfig.port}`);

    const messaging = messageModule(context, logger);
    context.messaging = messaging;
    context.services = {};

    const assetServiceOnline = assetServicelistener();

    // ignore process calls, this is handled by ipc messages from node master
    messaging.register({ event: 'process:SIGTERM', callback: () => {} });
    messaging.register({ event: 'process:SIGINT', callback: () => {} });

    // event is fired from terafoundation when an error occurs during instantiation of a client
    events.on('getClient:config_error', terminalShutdown);

    function terminalShutdown(errEV) {
        logger.error(`Terminal error: ${errEV.err}`);
        messaging.send({ to: 'node_master', message: 'cluster:error:terminal' });
    }

    messaging.register({
        event: 'worker:shutdown',
        callback: () => {
            logger.info('cluster_master is shutting down');
            Promise.all(_.map(context.services, service => service.shutdown()))
                .then(() => logger.flush())
                .then(() => process.exit())
                .catch((err) => {
                    const errMsg = parseError(err);
                    logger.error(`Error while cluster_master shutting down, error: ${errMsg}`);
                    setTimeout(() => {
                        process.exit(0);
                    }, 10);
                });
        }
    });

    function assetServicelistener() {
        let assetsServiceIsReady = false;
        let assetsServiceError = false;

        messaging.register({
            event: 'assets:service:available',
            callback: (assetServiceResponse) => {
                if (assetServiceResponse.error) {
                    assetsServiceError = true;
                } else {
                    assetsServiceIsReady = true;
                }
            }
        });
        return () => new Promise(((resolve, reject) => {
            if (assetsServiceIsReady) {
                resolve(true);
            } else {
                const assetReady = setInterval(() => {
                    if (assetsServiceIsReady) {
                        clearInterval(assetReady);
                        resolve(true);
                    }
                    if (assetsServiceError) {
                        clearInterval(assetReady);
                        reject('An error occurred while instantiating the assets service');
                    }
                }, 100);
            }
        }));
    }
    require('./services/execution.js')(context)
        .then((clusterService) => {
            messaging.initialize({ server });
            logger.trace('cluster_service has instantiated');
            context.services.execution = clusterService;
            return require('./services/jobs')(context);
        })
        .then((jobsService) => {
            logger.trace('jobs_service has instantiated');
            context.services.jobs = jobsService;
            return assetServiceOnline();
        })
        .then(() => require('./services/api')(context, app))
        .then((apiService) => {
            logger.trace('api_service has instantiated');
            context.services.api = apiService;
            return makeLogs(context);
        })
        .then(() => logger.info('Ready'))
        .catch((err) => {
            const errMsg = parseError(err);
            logger.error('error during service initialization', errMsg);
            messaging.send({ to: 'node_master', message: 'cluster:error:terminal' });
        });
};
<|endoftext|>


<commit_before>(function(){
  'use strict';

  angular.module('topFive.search',[])
    .component('resultsCompnent', {
      templateUrl: '/app/search/components/resultsComponentTemplate.html',
      bindings: { onResults: '&'},
      controller: 'resultsComponentController',
      controllerAs: 'vm'
  });

}());
<commit_msg>change binding for results component<commit_after>(function(){
  'use strict';

  angular.module('topFive.search',[])
    .component('resultsCompnent', {
      templateUrl: '/app/search/components/resultsComponentTemplate.html',
      bindings: { results: '<'},
      controller: 'resultsComponentController',
      controllerAs: 'vm'
  });

}());
<|endoftext|>