<commit_before>/*
 * Copyright (C) 2012 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * Custom configuration object for AttributeList configuration
 * @author Roy Braam
 */
Ext.define("viewer.components.CustomConfiguration",{
    extend: "viewer.components.SelectionWindowConfig",
    panel: null,
    panelHeight: 120,
    searchconfigs: [],
    nextId: 1,
    constructor: function (parentId,configObject){
        viewer.components.CustomConfiguration.superclass.constructor.call(this, parentId,configObject);
        this.initSearchconfigs(configObject);
    },
    initSearchconfigs: function(config) {
        var me = this;
        me.panel = Ext.create('Ext.panel.Panel', {
		    width: me.formWidth,
            margin: '15 0 0 0',
		    height: 250,
		    layout: 'auto',
            autoScroll: true,
		    items: [],
		    renderTo: 'config',
            tbar: [
                "->",
                {
                    xtype:'button',
                    iconCls: 'addbutton-icon',
                    text: 'Zoekingang toevoegen',
                    listeners: {
                        click: function() {
                            me.appendSearchField();
                        }
                    }
                }
            ]
		});

        if(config != null) {
            if(config.nextSearchConfigId != null) {
                me.nextId = config.nextSearchConfigId;
            }
            if(config.searchconfigs != null) {
                Ext.Array.each(config.searchconfigs, function(searchconfig) {
                    me.appendSearchField(searchconfig);
                });
            }
        }
    },
    appendSearchField: function(config) {
        var me = this;
        var nextId = me.nextId;
        var newconfig = config || {
            id: 'search' + nextId,
            name: 'Zoekingang ' + nextId,
            url: ''
        };
        me.searchconfigs.push(newconfig);
        var collapsed = true;
        if(nextId == 1) collapsed = false;
        me.panel.add(me.newSearchField(newconfig, collapsed));
        me.nextId++;
    },
    newSearchField: function(config, collapsed) {
        var me = this;
        return {
            xtype: 'panel',
            id: config.id,
            layout: 'anchor',
            anchor: '100%',
            width: '100%',
            title: config.name,
            animCollapse: false,
            collapsible: true,
            collapsed: collapsed,
            titleCollapse: true,
            hideCollapseTool: true,
            items: [
                {
                    xtype: 'fieldset',
                    defaultType: 'textfield',
                    border: 0,
                    padding: 10,
                    style: {
                        border: '0px none',
                        marginBottom: '0px'
                    },
                    items: [
                        { fieldLabel: 'Naam', name: 'name', value: config.name, id: 'name'+config.id },
                        { fieldLabel: 'URL', name: 'url', value: config.url, id: 'url'+config.id },
                        {
                            xtype:'button',
                            iconCls: 'savebutton-icon',
                            text: 'Zoekingang opslaan',
                            listeners: {
                                click: function(button) {
                                    me.saveConfig(config.id);
                                }
                            }
                        }
                    ]
                }
            ],
            tbar: ["->", {
                xtype:'button',
                iconCls: 'removebutton-icon',
                text: 'Zoekingang verwijderen',
                listeners: {
                    click: function() {
                        me.removeConfig(config.id);
                    }
                }
            }],
            listeners: {
                beforeexpand: function(){
                    Ext.Array.each(me.panel.items.items, function(item) {
                        item.collapse();
                    });
                }
            }
        };
    },
    saveConfig: function(configid) {
        var me = this;
        var panel = Ext.getCmp(configid);
        var newname = Ext.getCmp('name' + configid).getValue();
        var newurl = Ext.getCmp('url' + configid).getValue();
        panel.setTitle(newname);
        var newSearchconfigs = [];
        Ext.Array.each(me.searchconfigs, function(searchconfig) {
            if(searchconfig.id == configid) {
                searchconfig.name = newname;
                searchconfig.url = newurl;
            }
            newSearchconfigs.push(searchconfig);
        });
        me.searchconfigs = newSearchconfigs;
    },
    removeConfig: function(configid) {
        var me = this;
        me.panel.remove(configid);
        var newSearchconfigs = [];
        Ext.Array.each(me.searchconfigs, function(searchconfig) {
            if(searchconfig.id != configid) {
                newSearchconfigs.push(searchconfig);
            }
        });
        me.searchconfigs = newSearchconfigs;
    },
    getConfiguration: function(){
        var me = this;
        var config = viewer.components.CustomConfiguration.superclass.getConfiguration.call(this);
        config['searchconfigs'] = me.searchconfigs;
        config['nextSearchConfigId'] = me.nextId;
        return config;
    }
});

<commit_msg>Wrench icon added to search<commit_after>/*
 * Copyright (C) 2012 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * Custom configuration object for AttributeList configuration
 * @author Roy Braam
 */
Ext.define("viewer.components.CustomConfiguration",{
    extend: "viewer.components.SelectionWindowConfig",
    panel: null,
    panelHeight: 120,
    searchconfigs: [],
    nextId: 1,
    constructor: function (parentId,configObject){
        viewer.components.CustomConfiguration.superclass.constructor.call(this, parentId,configObject);
        this.initSearchconfigs(configObject);
    },
    initSearchconfigs: function(config) {
        var me = this;
        me.panel = Ext.create('Ext.panel.Panel', {
		    width: me.formWidth,
            margin: '15 0 0 0',
		    height: 250,
		    layout: 'auto',
            autoScroll: true,
		    items: [],
		    renderTo: 'config',
            tbar: [
                "->",
                {
                    xtype:'button',
                    iconCls: 'addbutton-icon',
                    text: 'Zoekingang toevoegen',
                    listeners: {
                        click: function() {
                            me.appendSearchField();
                        }
                    }
                }
            ]
		});

        if(config != null) {
            if(config.nextSearchConfigId != null) {
                me.nextId = config.nextSearchConfigId;
            }
            if(config.searchconfigs != null) {
                Ext.Array.each(config.searchconfigs, function(searchconfig) {
                    me.appendSearchField(searchconfig);
                });
            }
        }
    },
    appendSearchField: function(config) {
        var me = this;
        var nextId = me.nextId;
        var newconfig = config || {
            id: 'search' + nextId,
            name: 'Zoekingang ' + nextId,
            url: ''
        };
        me.searchconfigs.push(newconfig);
        var collapsed = true;
        if(nextId == 1) collapsed = false;
        me.panel.add(me.newSearchField(newconfig, collapsed));
        me.nextId++;
    },
    newSearchField: function(config, collapsed) {
        var me = this;
        return {
            xtype: 'panel',
            id: config.id,
            layout: 'anchor',
            anchor: '100%',
            width: '100%',
            title: config.name,
            animCollapse: false,
            collapsible: true,
            collapsed: collapsed,
            iconCls: "edit-icon-bw",
            titleCollapse: true,
            hideCollapseTool: true,
            items: [
                {
                    xtype: 'fieldset',
                    defaultType: 'textfield',
                    border: 0,
                    padding: 10,
                    style: {
                        border: '0px none',
                        marginBottom: '0px'
                    },
                    items: [
                        { fieldLabel: 'Naam', name: 'name', value: config.name, id: 'name'+config.id },
                        { fieldLabel: 'URL', name: 'url', value: config.url, id: 'url'+config.id },
                        {
                            xtype:'button',
                            iconCls: 'savebutton-icon',
                            text: 'Zoekingang opslaan',
                            listeners: {
                                click: function(button) {
                                    me.saveConfig(config.id);
                                }
                            }
                        }
                    ]
                }
            ],
            tbar: ["->", {
                xtype:'button',
                iconCls: 'removebutton-icon',
                text: 'Zoekingang verwijderen',
                listeners: {
                    click: function() {
                        me.removeConfig(config.id);
                    }
                }
            }],
            listeners: {
                beforeexpand: function(){
                    Ext.Array.each(me.panel.items.items, function(item) {
                        item.collapse();
                    });
                }
            }
        };
    },
    saveConfig: function(configid) {
        var me = this;
        var panel = Ext.getCmp(configid);
        var newname = Ext.getCmp('name' + configid).getValue();
        var newurl = Ext.getCmp('url' + configid).getValue();
        panel.setTitle(newname);
        var newSearchconfigs = [];
        Ext.Array.each(me.searchconfigs, function(searchconfig) {
            if(searchconfig.id == configid) {
                searchconfig.name = newname;
                searchconfig.url = newurl;
            }
            newSearchconfigs.push(searchconfig);
        });
        me.searchconfigs = newSearchconfigs;
    },
    removeConfig: function(configid) {
        var me = this;
        me.panel.remove(configid);
        var newSearchconfigs = [];
        Ext.Array.each(me.searchconfigs, function(searchconfig) {
            if(searchconfig.id != configid) {
                newSearchconfigs.push(searchconfig);
            }
        });
        me.searchconfigs = newSearchconfigs;
    },
    getConfiguration: function(){
        var me = this;
        var config = viewer.components.CustomConfiguration.superclass.getConfiguration.call(this);
        config['searchconfigs'] = me.searchconfigs;
        config['nextSearchConfigId'] = me.nextId;
        return config;
    }
});

<|endoftext|>


<commit_before>define(['app', "directives/stats-display/amchart3","directives/stats-display/results-list",'authentication'], function() { 'use strict'; //"directives/stats-display/stats-display",

    return ['$scope',  '$http', '$timeout', '$filter',
     function($scope,  $http, $timeout, $filter ) {

        $scope.schema="resourcemobilization";
        $scope.chartData=[];

        $http.get("/api/v2013/thesaurus/domains/countries/terms", {cache: true}).then(function(o) {
            $scope.countries = $filter('orderBy')(o.data, 'title');
          return;
        });
        $timeout(function(){
          $http.get("api/v2015/rm-stats/chart-data", {cache: true}).then(function(o) {

              $scope.chartData= o.data;
            return;
          });
        });

        $http.get("api/v2015/rm-stats/source-docs", {cache: true}).then(function(o) {
            $scope.documents= o.data;
          return;
        });

    }];
});
<commit_msg>again - bug wrong path<commit_after>define(['app', "directives/stats-display/amchart3","directives/stats-display/results-list",'authentication'], function() { 'use strict'; //"directives/stats-display/stats-display",

    return ['$scope',  '$http', '$timeout', '$filter',
     function($scope,  $http, $timeout, $filter ) {

        $scope.schema="resourcemobilization";
        $scope.chartData=[];

        $http.get("/api/v2013/thesaurus/domains/countries/terms", {cache: true}).then(function(o) {
            $scope.countries = $filter('orderBy')(o.data, 'title');
          return;
        });
        $timeout(function(){
          $http.get("/api/v2015/rm-stats/chart-data", {cache: true}).then(function(o) {

              $scope.chartData= o.data;
            return;
          });
        });

        $http.get("/api/v2015/rm-stats/source-docs", {cache: true}).then(function(o) {
            $scope.documents= o.data;
          return;
        });

    }];
});
<|endoftext|>


<commit_before>const Discord = require("discord.js");
const config = require("./../../config.json");
const MSS = require("./../../functions/");
const request = require("request");

module.exports = function place(message) {
	let input = message.content.replace (/\n/g, "").split(" ");
	var user = encodeURI(input[1]);

	request('http://moustacheminer.com/place/searchapi.php?username=' + user, function(error, response, body) {
		if(error) {
			message.reply("An error occured while retrieving the data: " + error);
		}

		var data = JSON.parse(body);
		var reply;
		var colour = [];

		for (i=0; i<16; i++) {
			colour[i] = 0;
		}

		if(!data.info) {
			reply += "The user has not placed any dots down, or does not exist.";
		} else {
			data.info.forEach(function(element) {
				colour[element.colour]++
			});

			reply = `Info for ` + user + `
\`\`\`
White      | ` + colour[0]  + ` | ` + ((colour[0]  / data.info.length)*100).toFixed(2) + `%
Light Grey | ` + colour[1]  + ` | ` + ((colour[1]  / data.info.length)*100).toFixed(2) + `%
Grey       | ` + colour[2]  + ` | ` + ((colour[2]  / data.info.length)*100).toFixed(2) + `%
Black      | ` + colour[3]  + ` | ` + ((colour[3]  / data.info.length)*100).toFixed(2) + `%
Pink       | ` + colour[4]  + ` | ` + ((colour[4]  / data.info.length)*100).toFixed(2) + `%
Red        | ` + colour[5]  + ` | ` + ((colour[5]  / data.info.length)*100).toFixed(2) + `%
Orange     | ` + colour[6]  + ` | ` + ((colour[6]  / data.info.length)*100).toFixed(2) + `%
Brown      | ` + colour[7]  + ` | ` + ((colour[7]  / data.info.length)*100).toFixed(2) + `%
Yellow     | ` + colour[8]  + ` | ` + ((colour[8]  / data.info.length)*100).toFixed(2) + `%
Lime       | ` + colour[9]  + ` | ` + ((colour[9]  / data.info.length)*100).toFixed(2) + `%
Green      | ` + colour[10] + ` | ` + ((colour[10] / data.info.length)*100).toFixed(2) + `%
Cyan       | ` + colour[11] + ` | ` + ((colour[11] / data.info.length)*100).toFixed(2) + `%
Blue       | ` + colour[12] + ` | ` + ((colour[12] / data.info.length)*100).toFixed(2) + `%
Dark Blue  | ` + colour[13] + ` | ` + ((colour[13] / data.info.length)*100).toFixed(2) + `%
Magenta    | ` + colour[14] + ` | ` + ((colour[14] / data.info.length)*100).toFixed(2) + `%
Purple     | ` + colour[15] + ` | ` + ((colour[15] / data.info.length)*100).toFixed(2) + `%
-------------------------()*100
Total      | ` + data.info.length + `\`\`\``;
		}

		//Yes, false is a string. I'm so sorry
		if(data.error != "false") {
			message.reply(data.error);
		} else {
			var embed = new Discord.RichEmbed()
				.setTitle(input[1])
				.setAuthor("/r/place info for " + input[1], "http://moustacheminer.com/mss.png")
				.setColor("#00AE86")
				.setDescription(reply)
				.setFooter("MSS-Discord, " + config.MSS.version, "")
				.setTimestamp()
				.setURL("http://moustacheminer.com/place/?username=" + user)
				.addField("Powered by /r/PlaceDevs", "Please go to this URL to view the rest of the log. http://moustacheminer.com/place/?username=" + user);

			message.channel.sendEmbed(embed, "", { disableEveryone: true });
		}
	});
}
<commit_msg>Remove extra ()*100<commit_after>const Discord = require("discord.js");
const config = require("./../../config.json");
const MSS = require("./../../functions/");
const request = require("request");

module.exports = function place(message) {
	let input = message.content.replace (/\n/g, "").split(" ");
	var user = encodeURI(input[1]);

	request('http://moustacheminer.com/place/searchapi.php?username=' + user, function(error, response, body) {
		if(error) {
			message.reply("An error occured while retrieving the data: " + error);
		}

		var data = JSON.parse(body);
		var reply;
		var colour = [];

		for (i=0; i<16; i++) {
			colour[i] = 0;
		}

		if(!data.info) {
			reply += "The user has not placed any dots down, or does not exist.";
		} else {
			data.info.forEach(function(element) {
				colour[element.colour]++
			});

			reply = `Info for ` + user + `
\`\`\`
White      | ` + colour[0]  + ` | ` + ((colour[0]  / data.info.length)*100).toFixed(2) + `%
Light Grey | ` + colour[1]  + ` | ` + ((colour[1]  / data.info.length)*100).toFixed(2) + `%
Grey       | ` + colour[2]  + ` | ` + ((colour[2]  / data.info.length)*100).toFixed(2) + `%
Black      | ` + colour[3]  + ` | ` + ((colour[3]  / data.info.length)*100).toFixed(2) + `%
Pink       | ` + colour[4]  + ` | ` + ((colour[4]  / data.info.length)*100).toFixed(2) + `%
Red        | ` + colour[5]  + ` | ` + ((colour[5]  / data.info.length)*100).toFixed(2) + `%
Orange     | ` + colour[6]  + ` | ` + ((colour[6]  / data.info.length)*100).toFixed(2) + `%
Brown      | ` + colour[7]  + ` | ` + ((colour[7]  / data.info.length)*100).toFixed(2) + `%
Yellow     | ` + colour[8]  + ` | ` + ((colour[8]  / data.info.length)*100).toFixed(2) + `%
Lime       | ` + colour[9]  + ` | ` + ((colour[9]  / data.info.length)*100).toFixed(2) + `%
Green      | ` + colour[10] + ` | ` + ((colour[10] / data.info.length)*100).toFixed(2) + `%
Cyan       | ` + colour[11] + ` | ` + ((colour[11] / data.info.length)*100).toFixed(2) + `%
Blue       | ` + colour[12] + ` | ` + ((colour[12] / data.info.length)*100).toFixed(2) + `%
Dark Blue  | ` + colour[13] + ` | ` + ((colour[13] / data.info.length)*100).toFixed(2) + `%
Magenta    | ` + colour[14] + ` | ` + ((colour[14] / data.info.length)*100).toFixed(2) + `%
Purple     | ` + colour[15] + ` | ` + ((colour[15] / data.info.length)*100).toFixed(2) + `%
-----------------------------
Total      | ` + data.info.length + `\`\`\``;
		}

		//Yes, false is a string. I'm so sorry
		if(data.error != "false") {
			message.reply(data.error);
		} else {
			var embed = new Discord.RichEmbed()
				.setTitle(input[1])
				.setAuthor("/r/place info for " + input[1], "http://moustacheminer.com/mss.png")
				.setColor("#00AE86")
				.setDescription(reply)
				.setFooter("MSS-Discord, " + config.MSS.version, "")
				.setTimestamp()
				.setURL("http://moustacheminer.com/place/?username=" + user)
				.addField("Powered by /r/PlaceDevs", "Please go to this URL to view the rest of the log. http://moustacheminer.com/place/?username=" + user);

			message.channel.sendEmbed(embed, "", { disableEveryone: true });
		}
	});
}
<|endoftext|>


<commit_before>(function(jQuery) {
"use strict";

var $ = jQuery;

/**
 * @class Echo.StreamServer.Controls.Stream.Item.Plugins.Like
 * Adds extra Like/Unlike buttons to each item in the Echo Stream
 * control for authenticated users.
 *
 * 	new Echo.StreamServer.Controls.Stream({
 * 		"target": document.getElementById("echo-stream"),
 * 		"appkey": "echo.jssdk.demo.aboutecho.com",
 * 		"plugins": [{
 * 			"name": "Like"
 * 		}]
 * 	});
 *
 * More information regarding the plugins installation can be found
 * in the [“How to initialize Echo components”](#!/guide/how_to_initialize_components-section-initializing-plugins) guide.
 *
 * @extends Echo.Plugin
 *
 * @package streamserver/plugins.pack.js
 * @package streamserver.pack.js
 */
var plugin = Echo.Plugin.manifest("LikeCardUI", "Echo.StreamServer.Controls.Stream.Item");

if (Echo.Plugin.isDefined(plugin)) return;

plugin.init = function() {
	this.extendTemplate("insertAsFirstChild", "footer", plugin.templates.main);
	this.component.addButtonSpec("LikeCardUI", this._assembleButton("Like"));
	this.component.addButtonSpec("LikeCardUI", this._assembleButton("Unlike"));
};

plugin.config = {
	/**
	 * @cfg {Boolean} asyncFacePileRendering
	 * This parameter is used to enable FacePile control rendering in async mode.
	 */
	"asyncFacePileRendering": false
};

plugin.labels = {
	/**
	 * @echo_label
	 */
	"likeThis": " like this.",
	/**
	 * @echo_label
	 */
	"likesThis": " likes this.",
	/**
	 * @echo_label
	 */
	"likeControl": "Like",
	/**
	 * @echo_label
	 */
	"unlikeControl": "Unlike",
	/**
	 * @echo_label
	 */
	"likeProcessing": "Liking...",
	/**
	 * @echo_label
	 */
	"unlikeProcessing": "Unliking..."
};

plugin.dependencies = [{
	"control": "Echo.StreamServer.Controls.FacePile",
	"url": "{config:cdnBaseURL.sdk}/streamserver.pack.js"
}];

plugin.events = {
	"Echo.StreamServer.Controls.FacePile.Item.Plugins.LikeCardUI.onUnlike": function(topic, args) {
		this._sendActivity("Unlike", this.component, args.actor);
		return {"stop": ["bubble"]};
	}
};

/**
 * @echo_template
 */
plugin.templates.main =
	'
' +
		'

' +
		'

' +
		'

' +
		'

' +
	'
';

/**
 * @echo_renderer
 */
plugin.renderers.likedBy = function(element) {
	var plugin = this;
	var item = this.component;
	if (!item.get("data.object.likes").length) {
		return element.hide();
	}
	var likesPerPage = 5;
	var visibleUsersCount = plugin.get("facePile")
		? plugin.get("facePile").getVisibleUsersCount()
		: likesPerPage;
	var youLike = false;
	var userId = item.user.get("identityUrl");
	var users = item.get("data.object.likes");
	$.each(users, function(i, like) {
		if (like.actor.id === userId) {
			youLike = true;
			return false; // break
		}
	});
	var config = plugin.config.assemble({
		"target": element.get(0),
		"data": {
			"itemsPerPage": likesPerPage,
			"entries": users
		},
		"initialUsersCount": visibleUsersCount,
		"totalUsersCount": item.get("data.object.accumulators.likesCount"),
		"item": {
			"avatar": true,
			"text": false
		}
	});
	config.plugins.push({"name": "LikeCardUI"});
	if (item.user.is("admin")) {
		element.addClass(plugin.cssPrefix + "highlight");
	}
	if (this.config.get("asyncFacePileRendering")) {
		setTimeout($.proxy(this._initFacePile, this, config), 0);
	} else {
		this._initFacePile(config);
	}
	return element.show();
};

plugin.renderers.likeIcon = function(element) {
	this.component.set("likeIcon", element);
	return !!this._getLikesCount()
		? element : element.hide();
};

plugin.renderers.likers = function(element) {
	var likesCount = this._getLikesCount();
	var counter = this.get("counter");
	if (!counter) {
		counter = new Echo.Apps.Conversations.RollingCounter({
			"target": element,
			"count": likesCount,
			"speed": 200
		});
	}
	this.set("counter", counter);
	return counter.roll(element, likesCount);
};

plugin.methods._getLikesCount = function() {
	return this.component.get("data.object.accumulators.likesCount");
};

plugin.methods._initFacePile = function(config) {
	this.set("facePile", new Echo.StreamServer.Controls.FacePile(config));
};

plugin.methods._sendRequest = function(data, callback, errorCallback) {
	Echo.StreamServer.API.request({
		"endpoint": "submit",
		"secure": this.config.get("useSecureAPI", false, true),
		"submissionProxyURL": this.component.config.get("submissionProxyURL"),
		"onData": callback,
		"onError": errorCallback,
		"data": data
	}).send();
};

plugin.methods._sendActivity = function(name, item, actor) {
	var plugin = this;
	var activity = {
		"verbs": ["http://activitystrea.ms/schema/1.0/" + name.toLowerCase()],
		"targets": [{"id": item.get("data.object.id")}]
	};
	if (actor && actor.id) {
		activity.author = actor.id;
	}

	this._sendRequest({
		"content": activity,
		"appkey": item.config.get("appkey"),
		"sessionID": item.user.get("sessionID"),
		"target-query": item.config.get("parent.query")
	}, function(response) {
		/**
		 * @echo_event Echo.StreamServer.Controls.Stream.Item.Plugins.Like.onLikeComplete
		 * Triggered when the Like operation is finished.
		 */
		/**
		 * @echo_event Echo.StreamServer.Controls.Stream.Item.Plugins.Like.onUnlikeComplete
		 * Triggered when the reverse Like operation is finished.
		 */
		plugin._publishEventComplete({
			"name": name,
			"state": "Complete",
			"response": response
		});
		plugin.requestDataRefresh();
	}, function(response) {
		/**
		 * @echo_event Echo.StreamServer.Controls.Stream.Item.Plugins.Like.onLikeError
		 * Triggered when the Like operation failed.
		 */
		/**
		 * @echo_event Echo.StreamServer.Controls.Stream.Item.Plugins.Like.onUnlikeError
		 * Triggered when the reverse Like operation failed.
		 */
		plugin._publishEventComplete({
			"name": name,
			"state": "Error",
			"response": response
		});
	});
};

plugin.methods._publishEventComplete = function(args) {
	var item = this.component;
	this.events.publish({
		"topic": "on" + args.name + args.state,
		"data": {
			"item": {
				"data": item.get("data"),
				"target": item.config.get("target")
			},
			"response": args.response
		}
	});
};

plugin.methods._assembleButton = function(name) {
	var self = this;
	var callback = function() {
		var item = this;
		var buttonNode = item.get("buttons." + self.name + "." + name + ".element");
		$("." + item.cssPrefix + "buttonCaption", buttonNode)
			.empty()
			.append(self.labels.get(name.toLowerCase() + "Processing"));
		self._sendActivity(name, item);
	};
	return function() {
		var item = this;
		var action =
			($.map(item.get("data.object.likes"), function(entry) {
				if (item.user.has("identity", entry.actor.id)) return entry;
			})).length > 0 ? "Unlike" : "Like";
		return {
			"name": name,
			"icon": "{%= baseURL %}/images/like.png",
			"label": self.labels.get(name.toLowerCase() + "Control"),
			"visible": item.user.is("logged") && action === name,
			"once": true,
			"callback": callback
		};
	};
};

plugin.css =
	'.{plugin.class:likesArea} { float: right; }' +
	'.{plugin.class:likeIcon} { float: left; height: 20px; width: 20px; opacity: 0.3; margin-right: 7px; background: url({%= baseURL %}/images/like.png) no-repeat 0px 1px; }' +
	'.{plugin.class:likedBy} { float: left; height: 20px; margin-right: 5px; vertical-align: text-top;}' +
	'.{plugin.class:likers} { float: left; position: relative; border: 1px solid #808080; border-radius: 50%; color: #808080; display: inline-block; font-size: 10px; height: 20px; line-height: 22px; text-align: center; vertical-align: text-top; width: 20px; overflow: hidden; }' +
	'.{plugin.class:highlight} { line-height: 23px; }' +
	'.{plugin.class:likedBy} .echo-streamserver-controls-facepile-item-avatar { border-radius: 50%; }' +
	'.{plugin.class:likedBy} .echo-streamserver-controls-facepile-item-avatar img { border-radius: 50%; height: 20px; width: 20px; }' +
	'.{plugin.class:likedBy} echo-streamserver-controls-facepile-and { display: none; }';

Echo.Plugin.create(plugin);

})(Echo.jQuery);

(function(jQuery) {
"use strict";

/**
 * @class Echo.StreamServer.Controls.FacePile.Item.Plugins.Like
 * Adds extra controls to items in the Echo FacePile control.
 *
 * @extends Echo.Plugin
 * @private
 */
var plugin = Echo.Plugin.manifest("LikeCardUI", "Echo.StreamServer.Controls.FacePile.Item");

if (Echo.Plugin.isDefined(plugin)) return;

plugin.init = function() {
	this.extendTemplate("insertAsLastChild", "container", plugin.templates.main);
};

plugin.labels = {
	/**
	 * @echo_label
	 */
	"unlikeOnBehalf": "Unlike on behalf of this user"
};

/**
 * @echo_template
 */
plugin.templates.main = '';

/**
 * @echo_renderer
 */
plugin.component.renderers.container = function(element) {
	this.parentRenderer("container", arguments);
	if (this.component.user.is("admin")) {
		element.addClass(this.cssPrefix + "highlight");
	}
};

/**
 * @echo_renderer
 */
plugin.renderers.adminUnlike = function(element) {
	var plugin = this;
	var item = this.component;
	if (!item.user.is("admin")) {
		return element.remove();
	}
	return element.one("click", function() {
		item.view.get("container").css("opacity", 0.3);
		/**
		 * @echo_event Echo.StreamServer.Controls.FacePile.Item.Plugins.Like.onUnlike
		 * Triggered when the item is "unliked" by admin on behalf of a user.
		 */
		plugin.events.publish({
			"topic": "onUnlike",
			"data": {
				"actor": item.get("data"),
				"target": item.config.get("parent.target").get(0)
			},
			"global": false,
			"propagation": false
		});
	});
};

plugin.css =
	'.{plugin.class:adminUnlike} { cursor: pointer; margin-left: 3px; }' +
	'.{plugin.class:highlight} { display: inline-block; line-height: 16px; background-color: #EEEEEE; padding: 1px 3px; border: 1px solid #D2D2D2; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; margin: 0px 2px; }';

Echo.Plugin.create(plugin);

})(Echo.jQuery);
<commit_msg>Fixed the color of likes counter<commit_after>(function(jQuery) {
"use strict";

var $ = jQuery;

/**
 * @class Echo.StreamServer.Controls.Stream.Item.Plugins.Like
 * Adds extra Like/Unlike buttons to each item in the Echo Stream
 * control for authenticated users.
 *
 * 	new Echo.StreamServer.Controls.Stream({
 * 		"target": document.getElementById("echo-stream"),
 * 		"appkey": "echo.jssdk.demo.aboutecho.com",
 * 		"plugins": [{
 * 			"name": "Like"
 * 		}]
 * 	});
 *
 * More information regarding the plugins installation can be found
 * in the [“How to initialize Echo components”](#!/guide/how_to_initialize_components-section-initializing-plugins) guide.
 *
 * @extends Echo.Plugin
 *
 * @package streamserver/plugins.pack.js
 * @package streamserver.pack.js
 */
var plugin = Echo.Plugin.manifest("LikeCardUI", "Echo.StreamServer.Controls.Stream.Item");

if (Echo.Plugin.isDefined(plugin)) return;

plugin.init = function() {
	this.extendTemplate("insertAsFirstChild", "footer", plugin.templates.main);
	this.component.addButtonSpec("LikeCardUI", this._assembleButton("Like"));
	this.component.addButtonSpec("LikeCardUI", this._assembleButton("Unlike"));
};

plugin.config = {
	/**
	 * @cfg {Boolean} asyncFacePileRendering
	 * This parameter is used to enable FacePile control rendering in async mode.
	 */
	"asyncFacePileRendering": false
};

plugin.labels = {
	/**
	 * @echo_label
	 */
	"likeThis": " like this.",
	/**
	 * @echo_label
	 */
	"likesThis": " likes this.",
	/**
	 * @echo_label
	 */
	"likeControl": "Like",
	/**
	 * @echo_label
	 */
	"unlikeControl": "Unlike",
	/**
	 * @echo_label
	 */
	"likeProcessing": "Liking...",
	/**
	 * @echo_label
	 */
	"unlikeProcessing": "Unliking..."
};

plugin.dependencies = [{
	"control": "Echo.StreamServer.Controls.FacePile",
	"url": "{config:cdnBaseURL.sdk}/streamserver.pack.js"
}];

plugin.events = {
	"Echo.StreamServer.Controls.FacePile.Item.Plugins.LikeCardUI.onUnlike": function(topic, args) {
		this._sendActivity("Unlike", this.component, args.actor);
		return {"stop": ["bubble"]};
	}
};

/**
 * @echo_template
 */
plugin.templates.main =
	'
' +
		'

' +
		'

' +
		'

' +
		'

' +
	'
';

/**
 * @echo_renderer
 */
plugin.renderers.likedBy = function(element) {
	var plugin = this;
	var item = this.component;
	if (!item.get("data.object.likes").length) {
		return element.hide();
	}
	var likesPerPage = 5;
	var visibleUsersCount = plugin.get("facePile")
		? plugin.get("facePile").getVisibleUsersCount()
		: likesPerPage;
	var youLike = false;
	var userId = item.user.get("identityUrl");
	var users = item.get("data.object.likes");
	$.each(users, function(i, like) {
		if (like.actor.id === userId) {
			youLike = true;
			return false; // break
		}
	});
	var config = plugin.config.assemble({
		"target": element.get(0),
		"data": {
			"itemsPerPage": likesPerPage,
			"entries": users
		},
		"initialUsersCount": visibleUsersCount,
		"totalUsersCount": item.get("data.object.accumulators.likesCount"),
		"item": {
			"avatar": true,
			"text": false
		}
	});
	config.plugins.push({"name": "LikeCardUI"});
	if (item.user.is("admin")) {
		element.addClass(plugin.cssPrefix + "highlight");
	}
	if (this.config.get("asyncFacePileRendering")) {
		setTimeout($.proxy(this._initFacePile, this, config), 0);
	} else {
		this._initFacePile(config);
	}
	return element.show();
};

plugin.renderers.likeIcon = function(element) {
	this.component.set("likeIcon", element);
	return !!this._getLikesCount()
		? element : element.hide();
};

plugin.renderers.likers = function(element) {
	var likesCount = this._getLikesCount();
	var counter = this.get("counter");
	if (!counter) {
		counter = new Echo.Apps.Conversations.RollingCounter({
			"target": element,
			"count": likesCount,
			"speed": 200
		});
	}
	this.set("counter", counter);
	return counter.roll(element, likesCount);
};

plugin.methods._getLikesCount = function() {
	return this.component.get("data.object.accumulators.likesCount");
};

plugin.methods._initFacePile = function(config) {
	this.set("facePile", new Echo.StreamServer.Controls.FacePile(config));
};

plugin.methods._sendRequest = function(data, callback, errorCallback) {
	Echo.StreamServer.API.request({
		"endpoint": "submit",
		"secure": this.config.get("useSecureAPI", false, true),
		"submissionProxyURL": this.component.config.get("submissionProxyURL"),
		"onData": callback,
		"onError": errorCallback,
		"data": data
	}).send();
};

plugin.methods._sendActivity = function(name, item, actor) {
	var plugin = this;
	var activity = {
		"verbs": ["http://activitystrea.ms/schema/1.0/" + name.toLowerCase()],
		"targets": [{"id": item.get("data.object.id")}]
	};
	if (actor && actor.id) {
		activity.author = actor.id;
	}

	this._sendRequest({
		"content": activity,
		"appkey": item.config.get("appkey"),
		"sessionID": item.user.get("sessionID"),
		"target-query": item.config.get("parent.query")
	}, function(response) {
		/**
		 * @echo_event Echo.StreamServer.Controls.Stream.Item.Plugins.Like.onLikeComplete
		 * Triggered when the Like operation is finished.
		 */
		/**
		 * @echo_event Echo.StreamServer.Controls.Stream.Item.Plugins.Like.onUnlikeComplete
		 * Triggered when the reverse Like operation is finished.
		 */
		plugin._publishEventComplete({
			"name": name,
			"state": "Complete",
			"response": response
		});
		plugin.requestDataRefresh();
	}, function(response) {
		/**
		 * @echo_event Echo.StreamServer.Controls.Stream.Item.Plugins.Like.onLikeError
		 * Triggered when the Like operation failed.
		 */
		/**
		 * @echo_event Echo.StreamServer.Controls.Stream.Item.Plugins.Like.onUnlikeError
		 * Triggered when the reverse Like operation failed.
		 */
		plugin._publishEventComplete({
			"name": name,
			"state": "Error",
			"response": response
		});
	});
};

plugin.methods._publishEventComplete = function(args) {
	var item = this.component;
	this.events.publish({
		"topic": "on" + args.name + args.state,
		"data": {
			"item": {
				"data": item.get("data"),
				"target": item.config.get("target")
			},
			"response": args.response
		}
	});
};

plugin.methods._assembleButton = function(name) {
	var self = this;
	var callback = function() {
		var item = this;
		var buttonNode = item.get("buttons." + self.name + "." + name + ".element");
		$("." + item.cssPrefix + "buttonCaption", buttonNode)
			.empty()
			.append(self.labels.get(name.toLowerCase() + "Processing"));
		self._sendActivity(name, item);
	};
	return function() {
		var item = this;
		var action =
			($.map(item.get("data.object.likes"), function(entry) {
				if (item.user.has("identity", entry.actor.id)) return entry;
			})).length > 0 ? "Unlike" : "Like";
		return {
			"name": name,
			"icon": "{%= baseURL %}/images/like.png",
			"label": self.labels.get(name.toLowerCase() + "Control"),
			"visible": item.user.is("logged") && action === name,
			"once": true,
			"callback": callback
		};
	};
};

plugin.css =
	'.{plugin.class:likesArea} { float: right; }' +
	'.{plugin.class:likeIcon} { float: left; height: 20px; width: 20px; opacity: 0.3; margin-right: 7px; background: url({%= baseURL %}/images/like.png) no-repeat 0px 1px; }' +
	'.{plugin.class:likedBy} { float: left; height: 20px; margin-right: 5px; vertical-align: text-top;}' +
	'.{plugin.class:likers} { float: left; position: relative; border: 1px solid #c6c6c6; border-radius: 50%; color: #c6c6c6; display: inline-block; font-size: 10px; height: 20px; line-height: 22px; text-align: center; vertical-align: text-top; width: 20px; overflow: hidden; }' +
	'.{plugin.class:highlight} { line-height: 23px; }' +
	'.{plugin.class:likedBy} .echo-streamserver-controls-facepile-item-avatar { border-radius: 50%; }' +
	'.{plugin.class:likedBy} .echo-streamserver-controls-facepile-item-avatar img { border-radius: 50%; height: 20px; width: 20px; }' +
	'.{plugin.class:likedBy} echo-streamserver-controls-facepile-and { display: none; }';

Echo.Plugin.create(plugin);

})(Echo.jQuery);

(function(jQuery) {
"use strict";

/**
 * @class Echo.StreamServer.Controls.FacePile.Item.Plugins.Like
 * Adds extra controls to items in the Echo FacePile control.
 *
 * @extends Echo.Plugin
 * @private
 */
var plugin = Echo.Plugin.manifest("LikeCardUI", "Echo.StreamServer.Controls.FacePile.Item");

if (Echo.Plugin.isDefined(plugin)) return;

plugin.init = function() {
	this.extendTemplate("insertAsLastChild", "container", plugin.templates.main);
};

plugin.labels = {
	/**
	 * @echo_label
	 */
	"unlikeOnBehalf": "Unlike on behalf of this user"
};

/**
 * @echo_template
 */
plugin.templates.main = '';

/**
 * @echo_renderer
 */
plugin.component.renderers.container = function(element) {
	this.parentRenderer("container", arguments);
	if (this.component.user.is("admin")) {
		element.addClass(this.cssPrefix + "highlight");
	}
};

/**
 * @echo_renderer
 */
plugin.renderers.adminUnlike = function(element) {
	var plugin = this;
	var item = this.component;
	if (!item.user.is("admin")) {
		return element.remove();
	}
	return element.one("click", function() {
		item.view.get("container").css("opacity", 0.3);
		/**
		 * @echo_event Echo.StreamServer.Controls.FacePile.Item.Plugins.Like.onUnlike
		 * Triggered when the item is "unliked" by admin on behalf of a user.
		 */
		plugin.events.publish({
			"topic": "onUnlike",
			"data": {
				"actor": item.get("data"),
				"target": item.config.get("parent.target").get(0)
			},
			"global": false,
			"propagation": false
		});
	});
};

plugin.css =
	'.{plugin.class:adminUnlike} { cursor: pointer; margin-left: 3px; }' +
	'.{plugin.class:highlight} { display: inline-block; line-height: 16px; background-color: #EEEEEE; padding: 1px 3px; border: 1px solid #D2D2D2; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; margin: 0px 2px; }';

Echo.Plugin.create(plugin);

})(Echo.jQuery);
<|endoftext|>


<commit_before>module.exports = function (grunt) {
	var _ = grunt.utils._;
	var outFiles = {
		edge : '<%= meta.out %>/edge/**/*.js',
		latest : '<%= meta.out %>/<%= pkg.version %>/**/*.js'
	};
	var withExclude = _.extend({
		_options : {
			exclude : [/steal\//, /\.min\./, /qunit\.js/]
		}
	}, outFiles);

	grunt.initConfig({
		pkg : '<json:package.json>',
		meta : {
			out : "dist/",
			beautifier : {
				options : {
					indentSize : 1,
					indentChar : "\t"
				},
				exclude : [/\.min\./, /qunit\.js/]
			},
			banner : '/*!\n* <%= pkg.title || pkg.name %> - <%= pkg.version %> ' +
				'(<%= grunt.template.today("yyyy-mm-dd") %>)\n' +
				'<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' +
				'* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>\n' +
				'* Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n*/'
		},
		beautifier : {
			codebase : '<config:meta.beautifier>',
			dist : '<config:meta.beautifier>'
		},
		beautify : {
			codebase : [
				'dom/**/*.js',
				'event/**/*.js',
				'lang/**/*.js'
			],
			dist : '<%= meta.out %>/**/*.js'
		},
		build : {
			edge : {
				src : "jquery/build/build.js",
				out : 'jquery/<%= meta.out %>'
			},
			latest : {
				src : "jquery/build/build.js",
				version : '<%= pkg.version %>',
				out : 'jquery/<%= meta.out %>'
			}
		},
		shell : {
			makeSteal: 'rm -rf mkdir <%= meta.out %>/<%= pkg.version %>/steal && mkdir <%= meta.out %>/<%= pkg.version %>/steal && git archive HEAD | tar -x -C <%= meta.out %>/<%= pkg.version %>/steal',
			bundleLatest : 'cd <%= meta.out %> && zip -r jquerypp.<%= pkg.version %>.zip <%= pkg.version %>/',
			getGhPages : 'git clone -b gh-pages <%= pkg.repository.url %> build/gh-pages',
			copyLatest : 'rm -rf build/gh-pages/release/<%= pkg.version %> && ' +
				'cp -R <%= meta.out %>/<%= pkg.version %> build/gh-pages/release/<%= pkg.version %> && ' +
				'cp <%= meta.out %>/jquerypp.<%= pkg.version %>.zip build/gh-pages/downloads/ &&' +
				'rm -rf build/gh-pages/release/latest && ' +
				'cp -R <%= meta.out %>/<%= pkg.version %> build/gh-pages/release/latest',
			copyEdge : 'rm -rf build/gh-pages/release/edge && ' +
				'cp -R <%= meta.out %>/edge build/gh-pages/release/edge',
			updateGhPages : 'cd build/gh-pages && git add . --all && git commit -m "Updating release (latest: <%= pkg.version %>)" && ' +
				'git push origin',
			cleanup : 'rm -rf build/gh-pages',
			_options : {
				stdout : true,
				failOnError : true
			}
		},
		bannerize : outFiles,
		docco : {
			edge : {
				src : '<%= meta.out %>/edge/raw/**/*.js',
				docco : {
					output : '<%= meta.out %>/edge/docs'
				}
			},
			latest : {
				src : '<%= meta.out %>/<%= pkg.version %>/**/*.js',
				docco : {
					output : '<%= meta.out %>/<%= pkg.version %>/docs'
				}
			},
			_options : {
				exclude : [/\.min\./, /steal\//, /amd\//]
			}
		},
		strip : withExclude
	});

	grunt.loadTasks("../build/tasks");
	grunt.registerTask('edge', 'build:edge strip:edge beautify:dist bannerize:edge');
	grunt.registerTask('latest', 'build:latest strip:latest beautify:dist bannerize:latest shell:makeSteal docco:latest');
	grunt.registerTask("ghpages", "shell:cleanup shell:getGhPages shell:copyLatest shell:updateGhPages shell:cleanup");
};
<commit_msg>Adding zips to grunt task. Adding deploy as well.<commit_after>module.exports = function (grunt) {
	var _ = grunt.utils._;
	var outFiles = {
		edge : '<%= meta.out %>/edge/**/*.js',
		latest : '<%= meta.out %>/<%= pkg.version %>/**/*.js'
	};
	var withExclude = _.extend({
		_options : {
			exclude : [/steal\//, /\.min\./, /qunit\.js/]
		}
	}, outFiles);

	grunt.initConfig({
		pkg : '<json:package.json>',
		meta : {
			out : "dist/",
			beautifier : {
				options : {
					indentSize : 1,
					indentChar : "\t"
				},
				exclude : [/\.min\./, /qunit\.js/]
			},
			banner : '/*!\n* <%= pkg.title || pkg.name %> - <%= pkg.version %> ' +
				'(<%= grunt.template.today("yyyy-mm-dd") %>)\n' +
				'<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' +
				'* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>\n' +
				'* Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n*/'
		},
		beautifier : {
			codebase : '<config:meta.beautifier>',
			dist : '<config:meta.beautifier>'
		},
		beautify : {
			codebase : [
				'dom/**/*.js',
				'event/**/*.js',
				'lang/**/*.js'
			],
			dist : '<%= meta.out %>/**/*.js'
		},
		build : {
			edge : {
				src : "jquery/build/build.js",
				out : 'jquery/<%= meta.out %>'
			},
			latest : {
				src : "jquery/build/build.js",
				version : '<%= pkg.version %>',
				out : 'jquery/<%= meta.out %>'
			}
		},
		shell : {
			makeSteal: 'rm -rf mkdir <%= meta.out %>/<%= pkg.version %>/steal && mkdir <%= meta.out %>/<%= pkg.version %>/steal && git archive HEAD | tar -x -C <%= meta.out %>/<%= pkg.version %>/steal',
			bundleLatest : 'cd <%= meta.out %> && zip -r jquerypp-<%= pkg.version %>.zip <%= pkg.version %>/',
			getGhPages : 'git clone -b gh-pages <%= pkg.repository.url %> build/gh-pages',
			copyLatest : 'rm -rf build/gh-pages/release/<%= pkg.version %> && ' +
				'cp -R <%= meta.out %>/<%= pkg.version %> build/gh-pages/release/<%= pkg.version %> && ' +
				'cp <%= meta.out %>/jquerypp-<%= pkg.version %>.zip build/gh-pages/downloads/ &&' +
				'rm -rf build/gh-pages/release/latest && ' +
				'cp -R <%= meta.out %>/<%= pkg.version %> build/gh-pages/release/latest',
			copyEdge : 'rm -rf build/gh-pages/release/edge && ' +
				'cp -R <%= meta.out %>/edge build/gh-pages/release/edge',
			updateGhPages : 'cd build/gh-pages && git add . --all && git commit -m "Updating release (latest: <%= pkg.version %>)" && ' +
				'git push origin',
			cleanup : 'rm -rf build/gh-pages',
			_options : {
				stdout : true,
				failOnError : true
			}
		},
		bannerize : outFiles,
		docco : {
			edge : {
				src : '<%= meta.out %>/edge/raw/**/*.js',
				docco : {
					output : '<%= meta.out %>/edge/docs'
				}
			},
			latest : {
				src : '<%= meta.out %>/<%= pkg.version %>/**/*.js',
				docco : {
					output : '<%= meta.out %>/<%= pkg.version %>/docs'
				}
			},
			_options : {
				exclude : [/\.min\./, /steal\//, /amd\//]
			}
		},
		strip : withExclude
	});

	grunt.loadTasks("../build/tasks");
	grunt.registerTask('edge', 'build:edge strip:edge beautify:dist bannerize:edge');
	grunt.registerTask('latest', 'build:latest strip:latest beautify:dist bannerize:latest shell:makeSteal shell:bundleLatest docco:latest');
	grunt.registerTask("ghpages", "shell:cleanup shell:getGhPages shell:copyLatest shell:updateGhPages shell:cleanup");
	grunt.registerTask('deploy', 'latest ghpages');
};
<|endoftext|>


<commit_before>// Module dependencies
var crypto      = require('crypto'),
    express     = require('express'),
    hbs         = require('express-hbs'),
    compress    = require('compression'),
    fs          = require('fs'),
    uuid        = require('node-uuid'),
    Polyglot    = require('node-polyglot'),
    semver      = require('semver'),
    _           = require('lodash'),
    when        = require('when'),

    api         = require('./api'),
    config      = require('./config'),
    errors      = require('./errors'),
    helpers     = require('./helpers'),
    mailer      = require('./mail'),
    middleware  = require('./middleware'),
    models      = require('./models'),
    permissions = require('./permissions'),
    apps        = require('./apps'),
    routes      = require('./routes'),
    packageInfo = require('../../package.json'),

// Variables
    httpServer,
    dbHash;

// If we're in development mode, require "when/console/monitor"
// for help in seeing swallowed promise errors, and log any
// stderr messages from bluebird promises.
if (process.env.NODE_ENV === 'development') {
    require('when/monitor/console');
}

function doFirstRun() {
    var firstRunMessage = [
        'Welcome to Ghost.',
        'You\'re running under the ',
        process.env.NODE_ENV,
        'environment.',

        'Your URL is set to',
        '' + config().url + '.',
        'See http://docs.ghost.org for instructions.'
    ];

    return api.notifications.add({
        type: 'info',
        message: firstRunMessage.join(' ')
    });
}

function initDbHashAndFirstRun() {
    return api.settings.read({key: 'dbHash', context: {internal: true}}).then(function (response) {
        var hash = response.settings[0].value,
            initHash;

        dbHash = hash;

        if (dbHash === null) {
            initHash = uuid.v4();
            return api.settings.edit({settings: [{key: 'dbHash', value: initHash}]}, {context: {internal: true}})
                .then(function (response) {
                    dbHash = response.settings[0].value;
                    return dbHash;
                }).then(doFirstRun);
        }

        return dbHash;
    });
}

// Checks for the existence of the "built" javascript files from grunt concat.
// Returns a promise that will be resolved if all files exist or rejected if
// any are missing.
function builtFilesExist() {
    var deferreds = [],
        location = config().paths.builtScriptPath,

        fileNames = process.env.NODE_ENV === 'production' ?
                helpers.scriptFiles.production : helpers.scriptFiles.development;

    function checkExist(fileName) {
        var deferred = when.defer(),
            errorMessage = "Javascript files have not been built.",
            errorHelp = "\nPlease read the getting started instructions at:" +
                        "\nhttps://github.com/TryGhost/Ghost#getting-started-guide-for-developers";

        fs.exists(fileName, function (exists) {
            if (exists) {
                deferred.resolve(true);
            } else {
                var err = new Error(errorMessage);

                err.help = errorHelp;
                deferred.reject(err);
            }
        });

        return deferred.promise;
    }

    fileNames.forEach(function (fileName) {
        deferreds.push(checkExist(location + fileName));
    });

    return when.all(deferreds);
}

function ghostStartMessages() {
    // Tell users if their node version is not supported, and exit
    if (!semver.satisfies(process.versions.node, packageInfo.engines.node)) {
        console.log(
            "\nERROR: Unsupported version of Node".red,
            "\nGhost needs Node version".red,
            packageInfo.engines.node.yellow,
            "you are using version".red,
            process.versions.node.yellow,
            "\nPlease go to http://nodejs.org to get a supported version".green
        );

        process.exit(0);
    }

    // Startup & Shutdown messages
    if (process.env.NODE_ENV === 'production') {
        console.log(
            "Ghost is running...".green,
            "\nYour blog is now available on",
            config().url,
            "\nCtrl+C to shut down".grey
        );

        // ensure that Ghost exits correctly on Ctrl+C
        process.on('SIGINT', function () {
            console.log(
                "\nGhost has shut down".red,
                "\nYour blog is now offline"
            );
            process.exit(0);
        });
    } else {
        console.log(
            ("Ghost is running in " + process.env.NODE_ENV + "...").green,
            "\nListening on",
                config.getSocket() || config().server.host + ':' + config().server.port,
            "\nUrl configured as:",
            config().url,
            "\nCtrl+C to shut down".grey
        );
        // ensure that Ghost exits correctly on Ctrl+C
        process.on('SIGINT', function () {
            console.log(
                "\nGhost has shutdown".red,
                "\nGhost was running for",
                Math.round(process.uptime()),
                "seconds"
            );
            process.exit(0);
        });
    }
}

// ## Initializes the ghost application.
// Sets up the express server instance.
// Instantiates the ghost singleton, helpers, routes, middleware, and apps.
// Finally it starts the http server.
function init(server) {
    // create a hash for cache busting assets
    var assetHash = (crypto.createHash('md5').update(packageInfo.version + Date.now()).digest('hex')).substring(0, 10);

    // If no express instance is passed in
    // then create our own
    if (!server) {
        server = express();
    }

    // Set up Polygot instance on the require module
    Polyglot.instance = new Polyglot();

    // ### Initialisation
    // The server and its dependencies require a populated config
    // It returns a promise that is resolved when the application
    // has finished starting up.

    // Make sure javascript files have been built via grunt concat
    return builtFilesExist().then(function () {
        // Initialise the models
        return models.init();
    }).then(function () {
        // Populate any missing default settings
        return models.Settings.populateDefaults();
    }).then(function () {
        // Initialize the settings cache
        return api.init();
    }).then(function () {
        // Initialize the permissions actions and objects
        // NOTE: Must be done before the config.theme.update and initDbHashAndFirstRun calls
        return permissions.init();
    }).then(function () {
        // We must pass the api.settings object
        // into this method due to circular dependencies.
        return config.theme.update(api.settings, config().url);
    }).then(function () {
        return when.join(
            // Check for or initialise a dbHash.
            initDbHashAndFirstRun(),
            // Initialize mail
            mailer.init(),
            // Initialize apps
            apps.init()
        );
    }).then(function () {
        var adminHbs = hbs.create(),
            deferred = when.defer();

        // ##Configuration

        // return the correct mime type for woff filess
        express['static'].mime.define({'application/font-woff': ['woff']});

        // enabled gzip compression by default
        if (config().server.compress !== false) {
            server.use(compress());
        }

        // ## View engine
        // set the view engine
        server.set('view engine', 'hbs');

        // Create a hbs instance for admin and init view engine
        server.set('admin view engine', adminHbs.express3({partialsDir: config().paths.adminViews + 'partials'}));

        // Load helpers
        helpers.loadCoreHelpers(adminHbs, assetHash);

        // ## Middleware
        middleware(server, dbHash);

        // ## Routing

        // Set up API routes
        routes.api(server);

        // Set up Admin routes
        routes.admin(server);

        // Set up Frontend routes
        routes.frontend(server);

        // Log all theme errors and warnings
        _.each(config().paths.availableThemes._messages.errors, function (error) {
            errors.logError(error.message, error.context, error.help);
        });

        _.each(config().paths.availableThemes._messages.warns, function (warn) {
            errors.logWarn(warn.message, warn.context, warn.help);
        });

        // ## Start Ghost App
        if (config.getSocket()) {
            // Make sure the socket is gone before trying to create another
            try {
                fs.unlinkSync(config.getSocket());
            } catch (e) {
                // We can ignore this.
            }

            httpServer = server.listen(
                config.getSocket()
            );
            fs.chmod(config.getSocket(), '0660');

        } else {
            httpServer = server.listen(
                config().server.port,
                config().server.host
            );
        }

        httpServer.on('listening', function () {
            ghostStartMessages();
            deferred.resolve(httpServer);
        });

        return deferred.promise;
    });
}

module.exports = init;
<commit_msg>Clear any existing SIGINT listeners during startup<commit_after>// Module dependencies
var crypto      = require('crypto'),
    express     = require('express'),
    hbs         = require('express-hbs'),
    compress    = require('compression'),
    fs          = require('fs'),
    uuid        = require('node-uuid'),
    Polyglot    = require('node-polyglot'),
    semver      = require('semver'),
    _           = require('lodash'),
    when        = require('when'),

    api         = require('./api'),
    config      = require('./config'),
    errors      = require('./errors'),
    helpers     = require('./helpers'),
    mailer      = require('./mail'),
    middleware  = require('./middleware'),
    models      = require('./models'),
    permissions = require('./permissions'),
    apps        = require('./apps'),
    routes      = require('./routes'),
    packageInfo = require('../../package.json'),

// Variables
    httpServer,
    dbHash;

// If we're in development mode, require "when/console/monitor"
// for help in seeing swallowed promise errors, and log any
// stderr messages from bluebird promises.
if (process.env.NODE_ENV === 'development') {
    require('when/monitor/console');
}

function doFirstRun() {
    var firstRunMessage = [
        'Welcome to Ghost.',
        'You\'re running under the ',
        process.env.NODE_ENV,
        'environment.',

        'Your URL is set to',
        '' + config().url + '.',
        'See http://docs.ghost.org for instructions.'
    ];

    return api.notifications.add({
        type: 'info',
        message: firstRunMessage.join(' ')
    });
}

function initDbHashAndFirstRun() {
    return api.settings.read({key: 'dbHash', context: {internal: true}}).then(function (response) {
        var hash = response.settings[0].value,
            initHash;

        dbHash = hash;

        if (dbHash === null) {
            initHash = uuid.v4();
            return api.settings.edit({settings: [{key: 'dbHash', value: initHash}]}, {context: {internal: true}})
                .then(function (response) {
                    dbHash = response.settings[0].value;
                    return dbHash;
                }).then(doFirstRun);
        }

        return dbHash;
    });
}

// Checks for the existence of the "built" javascript files from grunt concat.
// Returns a promise that will be resolved if all files exist or rejected if
// any are missing.
function builtFilesExist() {
    var deferreds = [],
        location = config().paths.builtScriptPath,

        fileNames = process.env.NODE_ENV === 'production' ?
                helpers.scriptFiles.production : helpers.scriptFiles.development;

    function checkExist(fileName) {
        var deferred = when.defer(),
            errorMessage = "Javascript files have not been built.",
            errorHelp = "\nPlease read the getting started instructions at:" +
                        "\nhttps://github.com/TryGhost/Ghost#getting-started-guide-for-developers";

        fs.exists(fileName, function (exists) {
            if (exists) {
                deferred.resolve(true);
            } else {
                var err = new Error(errorMessage);

                err.help = errorHelp;
                deferred.reject(err);
            }
        });

        return deferred.promise;
    }

    fileNames.forEach(function (fileName) {
        deferreds.push(checkExist(location + fileName));
    });

    return when.all(deferreds);
}

function ghostStartMessages() {
    // Tell users if their node version is not supported, and exit
    if (!semver.satisfies(process.versions.node, packageInfo.engines.node)) {
        console.log(
            "\nERROR: Unsupported version of Node".red,
            "\nGhost needs Node version".red,
            packageInfo.engines.node.yellow,
            "you are using version".red,
            process.versions.node.yellow,
            "\nPlease go to http://nodejs.org to get a supported version".green
        );

        process.exit(0);
    }

    // Startup & Shutdown messages
    if (process.env.NODE_ENV === 'production') {
        console.log(
            "Ghost is running...".green,
            "\nYour blog is now available on",
            config().url,
            "\nCtrl+C to shut down".grey
        );

        // ensure that Ghost exits correctly on Ctrl+C
        process.removeAllListeners('SIGINT').on('SIGINT', function () {
            console.log(
                "\nGhost has shut down".red,
                "\nYour blog is now offline"
            );
            process.exit(0);
        });
    } else {
        console.log(
            ("Ghost is running in " + process.env.NODE_ENV + "...").green,
            "\nListening on",
                config.getSocket() || config().server.host + ':' + config().server.port,
            "\nUrl configured as:",
            config().url,
            "\nCtrl+C to shut down".grey
        );
        // ensure that Ghost exits correctly on Ctrl+C
        process.removeAllListeners('SIGINT').on('SIGINT', function () {
            console.log(
                "\nGhost has shutdown".red,
                "\nGhost was running for",
                Math.round(process.uptime()),
                "seconds"
            );
            process.exit(0);
        });
    }
}

// ## Initializes the ghost application.
// Sets up the express server instance.
// Instantiates the ghost singleton, helpers, routes, middleware, and apps.
// Finally it starts the http server.
function init(server) {
    // create a hash for cache busting assets
    var assetHash = (crypto.createHash('md5').update(packageInfo.version + Date.now()).digest('hex')).substring(0, 10);

    // If no express instance is passed in
    // then create our own
    if (!server) {
        server = express();
    }

    // Set up Polygot instance on the require module
    Polyglot.instance = new Polyglot();

    // ### Initialisation
    // The server and its dependencies require a populated config
    // It returns a promise that is resolved when the application
    // has finished starting up.

    // Make sure javascript files have been built via grunt concat
    return builtFilesExist().then(function () {
        // Initialise the models
        return models.init();
    }).then(function () {
        // Populate any missing default settings
        return models.Settings.populateDefaults();
    }).then(function () {
        // Initialize the settings cache
        return api.init();
    }).then(function () {
        // Initialize the permissions actions and objects
        // NOTE: Must be done before the config.theme.update and initDbHashAndFirstRun calls
        return permissions.init();
    }).then(function () {
        // We must pass the api.settings object
        // into this method due to circular dependencies.
        return config.theme.update(api.settings, config().url);
    }).then(function () {
        return when.join(
            // Check for or initialise a dbHash.
            initDbHashAndFirstRun(),
            // Initialize mail
            mailer.init(),
            // Initialize apps
            apps.init()
        );
    }).then(function () {
        var adminHbs = hbs.create(),
            deferred = when.defer();

        // ##Configuration

        // return the correct mime type for woff filess
        express['static'].mime.define({'application/font-woff': ['woff']});

        // enabled gzip compression by default
        if (config().server.compress !== false) {
            server.use(compress());
        }

        // ## View engine
        // set the view engine
        server.set('view engine', 'hbs');

        // Create a hbs instance for admin and init view engine
        server.set('admin view engine', adminHbs.express3({partialsDir: config().paths.adminViews + 'partials'}));

        // Load helpers
        helpers.loadCoreHelpers(adminHbs, assetHash);

        // ## Middleware
        middleware(server, dbHash);

        // ## Routing

        // Set up API routes
        routes.api(server);

        // Set up Admin routes
        routes.admin(server);

        // Set up Frontend routes
        routes.frontend(server);

        // Log all theme errors and warnings
        _.each(config().paths.availableThemes._messages.errors, function (error) {
            errors.logError(error.message, error.context, error.help);
        });

        _.each(config().paths.availableThemes._messages.warns, function (warn) {
            errors.logWarn(warn.message, warn.context, warn.help);
        });

        // ## Start Ghost App
        if (config.getSocket()) {
            // Make sure the socket is gone before trying to create another
            try {
                fs.unlinkSync(config.getSocket());
            } catch (e) {
                // We can ignore this.
            }

            httpServer = server.listen(
                config.getSocket()
            );
            fs.chmod(config.getSocket(), '0660');

        } else {
            httpServer = server.listen(
                config().server.port,
                config().server.host
            );
        }

        httpServer.on('listening', function () {
            ghostStartMessages();
            deferred.resolve(httpServer);
        });

        return deferred.promise;
    });
}

module.exports = init;
<|endoftext|>


<commit_before>/*global module:false*/
module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {
      banner: '// ==========================================================================\n' +
              '// Project:   <%= pkg.title || pkg.name %>\n' +
              '// Copyright: ©<%= grunt.template.today("yyyy") %> <%= pkg.author.name %>\n' +
              '//            See https://raw.github.com/everydayhero/csvjs/master/LICENSE\n' +
              '// =========================================================================='
    },
    lint: {
      files: ['grunt.js', 'src/*.js']
    },
    qunit: {
      files: ['test/*.html']
    },
    concat: {
      dist: {
        src: ['<banner:meta.banner>', '<file_strip_banner:src/<%= pkg.name %>.js>'],
        dest: 'dist/<%= pkg.name %>.js'
      }
    },
    min: {
      dist: {
        src: ['<banner:meta.banner>', '<config:concat.dist.dest>'],
        dest: 'dist/<%= pkg.name %>.min.js'
      }
    },
    watch: {
      files: '<config:lint.files>',
      tasks: 'lint qunit'
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true
      },
      globals: {}
    }
  });

  // Default task.
  grunt.registerTask('default', 'lint qunit concat min');

};
<commit_msg>Added version to banner<commit_after>/*global module:false*/
module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {
      banner: '// ==========================================================================\n' +
              '// Project:   <%= pkg.title || pkg.name %> <%= pkg.version %>\n' +
              '// Copyright: ©<%= grunt.template.today("yyyy") %> <%= pkg.author.name %>\n' +
              '//            See https://raw.github.com/everydayhero/csvjs/master/LICENSE\n' +
              '// =========================================================================='
    },
    lint: {
      files: ['grunt.js', 'src/*.js']
    },
    qunit: {
      files: ['test/*.html']
    },
    concat: {
      dist: {
        src: ['<banner:meta.banner>', '<file_strip_banner:src/<%= pkg.name %>.js>'],
        dest: 'dist/<%= pkg.name %>.js'
      }
    },
    min: {
      dist: {
        src: ['<banner:meta.banner>', '<config:concat.dist.dest>'],
        dest: 'dist/<%= pkg.name %>.min.js'
      }
    },
    watch: {
      files: '<config:lint.files>',
      tasks: 'lint qunit'
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true
      },
      globals: {}
    }
  });

  // Default task.
  grunt.registerTask('default', 'lint qunit concat min');

};
<|endoftext|>


<commit_before>/*global module:false*/
module.exports = function (grunt) {
  'use strict';

  var bannerRegex = /\/\*[\s\S]*?\*\//,
      sauceLabsKey = process.env.SAUCE_LABS_KEY;

  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {
      banner: {
        widget: grunt.file.read('lib/jquery.ui.widget.js').match(bannerRegex)[0],
        source: grunt.file.read('src/jquery.marcopolo.js').match(bannerRegex)[0]
      }
    },
    lint: {
      files: ['grunt.js', 'src/*.js']
    },
    min: {
      widget: {
        src: ['<banner:meta.banner.widget>', 'lib/jquery.ui.widget.js'],
        dest: 'build/parts/jquery.ui.widget.min.js'
      },
      source: {
        src: ['<banner:meta.banner.source>', 'src/jquery.marcopolo.js'],
        dest: 'build/parts/jquery.marcopolo.min.js'
      }
    },
    concat: {
      widget: {
        src: 'lib/jquery.ui.widget.js',
        dest: 'build/parts/jquery.ui.widget.js'
      },
      source: {
        src: ['<banner:meta.banner.source>', '<file_strip_banner:src/jquery.marcopolo.js:block>'],
        dest: 'build/parts/jquery.marcopolo.js',
        separator: ''
      },
      unmin: {
        src: ['<config:concat.widget.dest>', '<config:concat.source.dest>'],
        dest: 'build/jquery.marcopolo.js'
      },
      min: {
        src: ['<config:min.widget.dest>', '<config:min.source.dest>'],
        dest: 'build/jquery.marcopolo.min.js',
        separator: '\n\n'
      }
    },
    watch: {
      files: '<config:lint.files>',
      tasks: 'lint'
    },
    component: {
      main: './build/jquery.marcopolo.min.js',
      dependencies: {
        'jquery': '>=1.4.3'
      }
    },
    jasmine: {
      all: 'http://localhost:8000/test/runner.html'
    },
    jshint: {
      options: {
        // Enforcing
        bitwise: true,
        camelcase: true,
        curly: true,
        eqeqeq: true,
        forin: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        noempty: true,
        nonew: true,
        quotmark: 'single',
        regexp: true,
        undef: true,
        unused: true,
        strict: true,
        trailing: true,
        maxlen: 120,
        // Relaxing
        boss: true,
        eqnull: true,
        sub: true,
        // Environment
        browser: true,
        jquery: true
      },
      globals: {
        define: true,
        process: true
      }
    },
    'saucelabs-jasmine': {
      all: {
        username: 'justinstayton',
        key: sauceLabsKey,
        testname: 'jquery-marcopolo',
        tags: ['master'],
        urls: ['<config:jasmine.all>'],
        browsers: [{
          browserName: 'internet explorer'
        }]
      }
    },
    server: {
      port: 8000,
      base: '.'
    },
    uglify: {}
  });

  var testTasks = ['lint', 'server', 'jasmine'];

  if (sauceLabsKey) {
    testTasks.push('saucelabs-jasmine');
  }

  grunt.registerTask('test', testTasks.join(' '));
  grunt.registerTask('default', 'test min concat component');

  grunt.loadNpmTasks('grunt-bump');
  grunt.loadNpmTasks('grunt-jasmine-task');
  grunt.loadNpmTasks('grunt-pkg-to-component');
  grunt.loadNpmTasks('grunt-saucelabs');
};
<commit_msg>Added all browsers to test against with Sauce Labs.<commit_after>/*global module:false*/
module.exports = function (grunt) {
  'use strict';

  var bannerRegex = /\/\*[\s\S]*?\*\//,
      sauceLabsKey = process.env.SAUCE_LABS_KEY;

  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {
      banner: {
        widget: grunt.file.read('lib/jquery.ui.widget.js').match(bannerRegex)[0],
        source: grunt.file.read('src/jquery.marcopolo.js').match(bannerRegex)[0]
      }
    },
    lint: {
      files: ['grunt.js', 'src/*.js']
    },
    min: {
      widget: {
        src: ['<banner:meta.banner.widget>', 'lib/jquery.ui.widget.js'],
        dest: 'build/parts/jquery.ui.widget.min.js'
      },
      source: {
        src: ['<banner:meta.banner.source>', 'src/jquery.marcopolo.js'],
        dest: 'build/parts/jquery.marcopolo.min.js'
      }
    },
    concat: {
      widget: {
        src: 'lib/jquery.ui.widget.js',
        dest: 'build/parts/jquery.ui.widget.js'
      },
      source: {
        src: ['<banner:meta.banner.source>', '<file_strip_banner:src/jquery.marcopolo.js:block>'],
        dest: 'build/parts/jquery.marcopolo.js',
        separator: ''
      },
      unmin: {
        src: ['<config:concat.widget.dest>', '<config:concat.source.dest>'],
        dest: 'build/jquery.marcopolo.js'
      },
      min: {
        src: ['<config:min.widget.dest>', '<config:min.source.dest>'],
        dest: 'build/jquery.marcopolo.min.js',
        separator: '\n\n'
      }
    },
    watch: {
      files: '<config:lint.files>',
      tasks: 'lint'
    },
    component: {
      main: './build/jquery.marcopolo.min.js',
      dependencies: {
        'jquery': '>=1.4.3'
      }
    },
    jasmine: {
      all: 'http://localhost:8000/test/runner.html'
    },
    jshint: {
      options: {
        // Enforcing
        bitwise: true,
        camelcase: true,
        curly: true,
        eqeqeq: true,
        forin: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        noempty: true,
        nonew: true,
        quotmark: 'single',
        regexp: true,
        undef: true,
        unused: true,
        strict: true,
        trailing: true,
        maxlen: 120,
        // Relaxing
        boss: true,
        eqnull: true,
        sub: true,
        // Environment
        browser: true,
        jquery: true
      },
      globals: {
        define: true,
        process: true
      }
    },
    'saucelabs-jasmine': {
      all: {
        username: 'justinstayton',
        key: sauceLabsKey,
        testname: 'jquery-marcopolo',
        tags: ['master'],
        urls: ['<config:jasmine.all>'],
        browsers: (function () {
          var compact = {
                'chrome': {
                  '*': ['Windows 2008', 'Mac 10.8', 'Linux']
                },
                'firefox': {
                  '3.6': 'Windows 2012',
                  '*': ['Windows 2012', 'Mac 10.6', 'Linux']
                },
                'internet explorer': {
                  '6': 'Windows 2003',
                  '7': 'Windows 2003',
                  '8': 'Windows 2003',
                  '9': 'Windows 2008',
                  '10': 'Windows 2012'
                },
                'ipad': {
                  '5.1': 'Mac 10.8',
                  '6': 'Mac 10.8'
                },
                'iphone': {
                  '5.1': 'Mac 10.8',
                  '6': 'Mac 10.8'
                },
                'opera': {
                  '11': 'Windows 2008',
                  '12': ['Windows 2008', 'Linux']
                },
                'safari': {
                  '5': ['Windows 2008', 'Mac 10.6'],
                  '6': 'Mac 10.8'
                }
              },
              expanded = [];

          Object.keys(compact).forEach(function (browserName) {
            Object.keys(compact[browserName]).forEach(function (version) {
              var platforms = compact[browserName][version];

              if (!Array.isArray(platforms)) {
                platforms = [platforms];
              }

              platforms.forEach(function (platform) {
                var options = {
                      browserName: browserName
                    };

                if (version !== '*') {
                  options.version = version;
                }

                if (platform) {
                  options.platform = platform;
                }

                expanded.push(options);
              });
            });
          });

          return expanded;
        })()
      }
    },
    server: {
      port: 8000,
      base: '.'
    },
    uglify: {}
  });

  var testTasks = ['lint', 'server', 'jasmine'];

  if (sauceLabsKey) {
    grunt.loadNpmTasks('grunt-saucelabs');

    testTasks.push('saucelabs-jasmine');
  }

  grunt.registerTask('test', testTasks.join(' '));
  grunt.registerTask('default', 'test min concat component');

  grunt.loadNpmTasks('grunt-bump');
  grunt.loadNpmTasks('grunt-jasmine-task');
  grunt.loadNpmTasks('grunt-pkg-to-component');
};
<|endoftext|>


<commit_before>import Sigil from "../Sigil";

const GatewayImage = ({
  error = false,
  patp = false,
  image = false,
  size = 100,
}) => {
  if (error) {
    return (

        <svg
          width={size}
          height={size}
          viewBox="0 0 100 100"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
        >
          <rect width="100" height="100" rx="10" fill="#24201E" />
          <path
            d="M28.8906 27.9844C28.5019 28.0215 28.1699 28.2833 28.043 28.6524C27.914 29.0235 28.0137 29.4336 28.2969 29.7032L70.2969 71.7032C70.4844 71.8965 70.7402 72.0059 71.0098 72.0059C71.2773 72.0079 71.5352 71.9004 71.7246 71.709C71.9141 71.5176 72.0176 71.2598 72.0137 70.9903C72.0098 70.7227 71.8984 70.4668 71.7031 70.2813L66.2501 64.8283C69.8204 60.9181 72.0001 55.7073 72.0001 50.0003C72.0001 37.8618 62.1386 28.0003 50.0001 28.0003C44.2931 28.0003 39.0976 30.1956 35.1876 33.7658L29.7031 28.2813C29.4922 28.0645 29.1934 27.9551 28.8906 27.9844L28.8906 27.9844ZM50.0001 30C61.0566 30 70.0001 38.9435 70.0001 50C70.0001 55.17 68.0411 59.8575 64.8281 63.406L36.5936 35.1715C40.1405 31.9606 44.8336 29.9995 49.9996 29.9995L50.0001 30ZM32.1721 37.8125C31.842 37.8321 31.5452 38.0137 31.3752 38.2969C29.2424 41.6856 28.0002 45.7029 28.0002 49.9999C28.0002 62.1384 37.8617 71.9999 50.0002 71.9999C54.2951 71.9999 58.3147 70.7558 61.7032 68.6249C62.1739 68.3319 62.3165 67.7128 62.0235 67.2421C61.7305 66.7714 61.1114 66.6288 60.6407 66.9218C57.5587 68.8593 53.9122 69.9999 50.0002 69.9999C38.9437 69.9999 30.0002 61.0564 30.0002 49.9999C30.0002 46.0878 31.1233 42.4414 33.0627 39.3594C33.2697 39.043 33.2815 38.6387 33.092 38.3125C32.9045 37.9844 32.5491 37.7929 32.1721 37.8125L32.1721 37.8125Z"
            fill="white"
          />
        </svg>

    );
  }

  if (patp) {
    return (

        <Sigil patp={patp} size={size} />

    );
  }

  return image ? (

  ) : (

  );
};

export default GatewayImage;
<commit_msg>GatewayImage: allow for background colours<commit_after>import Sigil from "../Sigil";

const GatewayImage = ({
  error = false,
  patp = false,
  image = false,
  size = 100,
}) => {
  if (error) {
    return (

        <svg
          width={size}
          height={size}
          viewBox="0 0 100 100"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
        >
          <rect width="100" height="100" rx="10" fill="#24201E" />
          <path
            d="M28.8906 27.9844C28.5019 28.0215 28.1699 28.2833 28.043 28.6524C27.914 29.0235 28.0137 29.4336 28.2969 29.7032L70.2969 71.7032C70.4844 71.8965 70.7402 72.0059 71.0098 72.0059C71.2773 72.0079 71.5352 71.9004 71.7246 71.709C71.9141 71.5176 72.0176 71.2598 72.0137 70.9903C72.0098 70.7227 71.8984 70.4668 71.7031 70.2813L66.2501 64.8283C69.8204 60.9181 72.0001 55.7073 72.0001 50.0003C72.0001 37.8618 62.1386 28.0003 50.0001 28.0003C44.2931 28.0003 39.0976 30.1956 35.1876 33.7658L29.7031 28.2813C29.4922 28.0645 29.1934 27.9551 28.8906 27.9844L28.8906 27.9844ZM50.0001 30C61.0566 30 70.0001 38.9435 70.0001 50C70.0001 55.17 68.0411 59.8575 64.8281 63.406L36.5936 35.1715C40.1405 31.9606 44.8336 29.9995 49.9996 29.9995L50.0001 30ZM32.1721 37.8125C31.842 37.8321 31.5452 38.0137 31.3752 38.2969C29.2424 41.6856 28.0002 45.7029 28.0002 49.9999C28.0002 62.1384 37.8617 71.9999 50.0002 71.9999C54.2951 71.9999 58.3147 70.7558 61.7032 68.6249C62.1739 68.3319 62.3165 67.7128 62.0235 67.2421C61.7305 66.7714 61.1114 66.6288 60.6407 66.9218C57.5587 68.8593 53.9122 69.9999 50.0002 69.9999C38.9437 69.9999 30.0002 61.0564 30.0002 49.9999C30.0002 46.0878 31.1233 42.4414 33.0627 39.3594C33.2697 39.043 33.2815 38.6387 33.092 38.3125C32.9045 37.9844 32.5491 37.7929 32.1721 37.8125L32.1721 37.8125Z"
            fill="white"
          />
        </svg>

    );
  }

  if (patp) {
    return (

        <Sigil patp={patp} size={size} />

    );
  }

  if (image?.startsWith("#")) {
    return (

    );
  }

  return image ? (

  ) : (

  );
};

export default GatewayImage;
<|endoftext|>


<commit_before>import requestToQualifiedRelationQuoted from '../query/requestToQualifiedRelationQuoted';
import requestToWhereClause from '../query/requestToWhereClause';
import pgEscape from 'pg-escape';
import sql, {join as joinSql, raw as rawSql} from '../sqlTemplate';
import prepareSqlValue from '../prepareSqlValue';

export default function requestToUpdateStatement(req) {
    const qualifiedRelationQuoted = rawSql(requestToQualifiedRelationQuoted(req));
    if (!req.body)
        throw new Error('PATCH request must have a body');

    const assignmentsQuoted = joinSql(Object.keys(req.body)
        .map(key => sql `${rawSql(pgEscape.ident(key))} = ${prepareSqlValue(req.body[key])}`)
    );
    if (!assignmentsQuoted.text.length)
        return new Error('PATCH request body must set at least one field');

    const whereClause = requestToWhereClause(req);

    const bodyExpression = req.flags.preferSingular ? sql `
        coalesce(string_agg(row_to_json(t)::text, ','), '')::character varying
    ` : sql `
        coalesce(array_to_json(array_agg(row_to_json(t))), '[]')::character varying
    `;

    const returning = rawSql(
        req.flags.preferRepresentation !== 'headersOnly' ? ' RETURNING *' : ''
    );

    const updateSubquery = sql
        `UPDATE ${qualifiedRelationQuoted} SET ${assignmentsQuoted} ${whereClause} ${returning}`;

    return req.flags.preferRepresentation !== 'full' ?
        updateSubquery
        : sql `
            WITH t AS (${updateSubquery})
            SELECT ${bodyExpression} as body from t
        `;
}
<commit_msg>s/return/throw in requestToUpdateStatement<commit_after>import requestToQualifiedRelationQuoted from '../query/requestToQualifiedRelationQuoted';
import requestToWhereClause from '../query/requestToWhereClause';
import pgEscape from 'pg-escape';
import sql, {join as joinSql, raw as rawSql} from '../sqlTemplate';
import prepareSqlValue from '../prepareSqlValue';

export default function requestToUpdateStatement(req) {
    const qualifiedRelationQuoted = rawSql(requestToQualifiedRelationQuoted(req));
    if (!req.body)
        throw new Error('PATCH request must have a body');

    const assignmentsQuoted = joinSql(Object.keys(req.body)
        .map(key => sql `${rawSql(pgEscape.ident(key))} = ${prepareSqlValue(req.body[key])}`)
    );
    if (!assignmentsQuoted.text.length)
        throw new Error('PATCH request body must set at least one field');

    const whereClause = requestToWhereClause(req);

    const bodyExpression = req.flags.preferSingular ? sql `
        coalesce(string_agg(row_to_json(t)::text, ','), '')::character varying
    ` : sql `
        coalesce(array_to_json(array_agg(row_to_json(t))), '[]')::character varying
    `;

    const returning = rawSql(
        req.flags.preferRepresentation !== 'headersOnly' ? ' RETURNING *' : ''
    );

    const updateSubquery = sql
        `UPDATE ${qualifiedRelationQuoted} SET ${assignmentsQuoted} ${whereClause} ${returning}`;

    return req.flags.preferRepresentation !== 'full' ?
        updateSubquery
        : sql `
            WITH t AS (${updateSubquery})
            SELECT ${bodyExpression} as body from t
        `;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License.
 */
const express = require("express");
const msal = require('@azure/msal-node');
const { promises: fs } = require("fs");

const SERVER_PORT = process.env.PORT || 3000;

const readFromStorage = () => {
    return fs.readFile("./data/cache.json", "utf-8");
};

const writeToStorage = (getMergedState) => {
    return readFromStorage().then(oldFile =>{
        const mergedState = getMergedState(oldFile);
        return fs.writeFile("./data/cacheAfterWrite.json", mergedState);
    })
};

const cachePlugin = {
    readFromStorage,
    writeToStorage
};

const publicClientConfig = {
    auth: {
        clientId: "99cab759-2aab-420b-91d8-5e3d8d4f063b",
        authority: "https://login.microsoftonline.com/90b8faa8-cc95-460e-a618-ee770bee1759",
        redirectUri: "http://localhost:3000/redirect",
    },
    cache: {
        cachePlugin
    },
};
const pca = new msal.PublicClientApplication(publicClientConfig);
const msalCacheManager = pca.getCacheManager();

// Create Express App and Routes
const app = express();

app.get('/', (req, res) => {
    const authCodeUrlParameters = {
        scopes: ["user.read"],
        redirectUri: ["http://localhost:3000/redirect"],
    };

    // get url to sign user in and consent to scopes needed for application
    pca.getAuthCodeUrl(authCodeUrlParameters).then((response) => {
        console.log(response);
        res.redirect(response);
    }).catch((error) => console.log(JSON.stringify(error)));
});

app.get('/redirect', (req, res) => {
    const tokenRequest = {
        code: req.query.code,
        redirectUri: "http://localhost:3000/redirect",
        scopes: ["user.read"],
    };

    pca.acquireTokenByCode(tokenRequest).then((response) => {
        console.log("\nResponse: \n:", response);
        res.send(200);
        return msalCacheManager.writeToPersistence();
    }).catch((error) => {
        console.log(error);
        res.status(500).send(error);
    });
});

msalCacheManager.readFromPersistence().then(() => {
    app.listen(SERVER_PORT, () => console.log(`Msal Node Auth Code Sample app listening on port ${SERVER_PORT}!`))
    console.log("Accounts: \n", msalCacheManager.getAllAccounts());
});

<commit_msg>Add logger example to msal-node-auth-code sample<commit_after>/*
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License.
 */
const express = require("express");
const msal = require('@azure/msal-node');
const { promises: fs } = require("fs");

const SERVER_PORT = process.env.PORT || 3000;

const readFromStorage = () => {
    return fs.readFile("./data/cache.json", "utf-8");
};

const writeToStorage = (getMergedState) => {
    return readFromStorage().then(oldFile =>{
        const mergedState = getMergedState(oldFile);
        return fs.writeFile("./data/cacheAfterWrite.json", mergedState);
    })
};

const cachePlugin = {
    readFromStorage,
    writeToStorage
};

const publicClientConfig = {
    auth: {
        clientId: "99cab759-2aab-420b-91d8-5e3d8d4f063b",
        authority: "https://login.microsoftonline.com/90b8faa8-cc95-460e-a618-ee770bee1759",
        redirectUri: "http://localhost:3000/redirect",
    },
    cache: {
        cachePlugin
    },
    system: {
        loggerOptions: {
            loggerCallback(loglevel, message, containsPii) {
                console.log(message);
            },
            piiLoggingEnabled: false,
            logLevel: msal.LogLevel.Verbose,
        }
    }
};
const pca = new msal.PublicClientApplication(publicClientConfig);
const msalCacheManager = pca.getCacheManager();

// Create Express App and Routes
const app = express();

app.get('/', (req, res) => {
    const authCodeUrlParameters = {
        scopes: ["user.read"],
        redirectUri: ["http://localhost:3000/redirect"],
    };

    // get url to sign user in and consent to scopes needed for application
    pca.getAuthCodeUrl(authCodeUrlParameters).then((response) => {
        console.log(response);
        res.redirect(response);
    }).catch((error) => console.log(JSON.stringify(error)));
});

app.get('/redirect', (req, res) => {
    const tokenRequest = {
        code: req.query.code,
        redirectUri: "http://localhost:3000/redirect",
        scopes: ["user.read"],
    };

    pca.acquireTokenByCode(tokenRequest).then((response) => {
        console.log("\nResponse: \n:", response);
        res.send(200);
        return msalCacheManager.writeToPersistence();
    }).catch((error) => {
        console.log(error);
        res.status(500).send(error);
    });
});

msalCacheManager.readFromPersistence().then(() => {
    app.listen(SERVER_PORT, () => console.log(`Msal Node Auth Code Sample app listening on port ${SERVER_PORT}!`))
    console.log("Accounts: \n", msalCacheManager.getAllAccounts());
});

<|endoftext|>


<commit_before>import axios from '../utils/axiosWrapper'
import { browserHistory } from 'react-router'

// action types
export const CLIENTS_FETCH = "CLIENTS_FETCH"
export const CLIENTS_FETCH_SUCCESS = "CLIENTS_FETCH_SUCCESS"
export const CLIENTS_FETCH_ERROR = "CLIENTS_FETCH_ERROR"

export const CLIENT_FETCH = "CLIENT_FETCH"
export const CLIENT_FETCH_SUCCESS = "CLIENT_FETCH_SUCCESS"
export const CLIENT_FETCH_ERROR = "CLIENT_FETCH_ERROR"

export const CLIENT_RESET = "CLIENT_RESET"
export const CLIENT_UPDATE_FIELD = "CLIENT_UPDATE_FIELD"

export const CLIENT_UPDATE = "CLIENT_UPDATE"
export const CLIENT_UPDATE_SUCCESS = "CLIENT_UPDATE_SUCCESS"
export const CLIENT_UPDATE_ERROR = "CLIENT_UPDATE_ERROR"

export const CLIENT_CREATE = "CLIENT_CREATE"
export const CLIENT_CREATE_SUCCESS = "CLIENT_CREATE_SUCCESS"
export const CLIENT_CREATE_ERROR = "CLIENT_CREATE_ERROR"

export const CLIENT_DELETE = "CLIENT_DELETE"
export const CLIENT_DELETE_SUCCESS = "CLIENT_DELETE_SUCCESS"
export const CLIENT_DELETE_ERROR = "CLIENT_DELETE_ERROR"

// gets error message from server response
const errorHandler = err => err.message || err.response.data.message
const endpoint = "/company"

// action creators

// receives pagination params
// and dispatches actions to fetch the list of clients
export function fetchClients(params) {
  return (dispatch) => {
    dispatch({ type: CLIENTS_FETCH });
    axios.get(endpoint, {params})
    .then(res => dispatch({ type: CLIENTS_FETCH_SUCCESS, clients: res.data }))
    .catch(err => dispatch({ type: CLIENTS_FETCH_ERROR, error: errorHandler(err) }))
  }
}

// receives project id
// and dispatches actions to fetch the client
export function fetchSingleClient(id) {
  return {
    type: CLIENT_FETCH,
    payload: axios.get(`${endpoint}/id/${id}`).then(res => res.data)
  }
}

// resets active client back to null
// useful for creating a new client
export function resetClient() {
  return { type: CLIENT_RESET }
}

// updates form field when user types
export function updateClientField(name, value) {
  return { name, value, type: CLIENT_UPDATE_FIELD }
}

// receives client, sends data to backend,
// and dispatch the related actions
export function editClient(client, isEditMode) {
  const promise = axios({
    method: isEditMode ? 'put' : 'post',
    url: isEditMode ? `${endpoint}/id/${client.id}` : endpoint,
    data: client
  }).then(res => res.data)
  promise.then(() => browserHistory.push('/clients'))
  return {
    type: isEditMode ? CLIENT_UPDATE : CLIENT_CREATE,
    payload: promise
  }
}
export const saveClient = client => editClient(client, true)
export const createClient = client => editClient(client, false)

// receives client, deletes data in backend,
// and dispatch the related actions
export function deleteClient(client) {
  return {
    type: CLIENT_DELETE,
    payload: axios.delete(`${endpoint}/id/${client.id}`).then(res => res.data)
  }
}

const initialState = {currentPage: []}

// computes a slice of the state for the CLIENT_UPDATE_SUCCESS action
const updateSuccess = (state, action) => {
  const clients = state.currentPage.map(client => {
    return client.id === action.client.id ?
      action.client :
      client;
  });
  return {
    ...state,
    currentPage: clients,
    activeClient: action.client,
    loading: false
  }
}

// computes a slice of the state for the CLIENT_CREATE_SUCCESS action
const createSuccess = (state, action) => {
  const clients = state.currentPage.concat(action.client);
  return {
    ...state,
    currentPage: clients,
    activeClient: null,
    loading: false
  }
}

// reducer
export default (state = initialState, action) => {
  switch (action.type) {
    case CLIENTS_FETCH:
    case CLIENT_FETCH:
    case CLIENT_UPDATE:
    case CLIENT_CREATE:
    case CLIENT_DELETE:
      return {
        ...state,
        loading: true
      }
    case CLIENTS_FETCH_SUCCESS:
      return {
        ...state,
        currentPage: action.clients.content,
        loading: false
      }
    case CLIENT_FETCH_SUCCESS:
      return {
        ...state,
        activeClient: action.client,
        loading: false
      }
    case CLIENT_UPDATE_SUCCESS:
      return updateSuccess(state, action)
    case CLIENT_CREATE_SUCCESS:
      return createSuccess(state, action)
    case CLIENT_DELETE_SUCCESS:
      return {
        ...state,
        loading: false,
        currentPage: state.currentPage
          .filter(client => client.id !== action.client.id)
      }
    case CLIENT_RESET:
      return {
        ...state,
        activeClient: null
      }
    case CLIENT_UPDATE_FIELD:
      return {
        ...state,
        activeClient: {
          ...state.activeClient,
          [action.name]: action.value
        }
      }
    case CLIENTS_FETCH_ERROR:
    case CLIENT_FETCH_ERROR:
    case CLIENT_UPDATE_ERROR:
    case CLIENT_CREATE_ERROR:
    case CLIENT_DELETE_ERROR:
      return {
        ...state,
        error: action.error,
        loading: false
      }
    default:
      return state;
  }
}
<commit_msg>refactor: client reducer with pagination and normalization<commit_after>import axios from '../utils/axiosWrapper'
import { browserHistory } from 'react-router'
import createPaginator from './createPaginator'
import { combineReducers } from 'redux'

const endpoint = "/company"
const paginator = createPaginator(endpoint)

// SELECTORS
export const getClientsPage = state => paginator.selectors.pageSelector(
  state.clients.pagination,
  state.clients.entities
)
export const getClientByID = (state, id) => state.clients.entities[id] || {missing: true}

// ACTION TYPES
export const CLIENTS_FETCH = paginator.types.FETCH_PAGE
export const CLIENT_FETCH = "CLIENT_FETCH"
export const CLIENT_UPDATE = "CLIENT_UPDATE"
export const CLIENT_CREATE = "CLIENT_CREATE"
export const CLIENT_DELETE = "CLIENT_DELETE"

// ACTIONS CREATORS

// receives pagination params
// and dispatches actions to fetch the list of clients
export const fetchClientsPage = paginator.actions.fetchPage

// receives project id
// and dispatches actions to fetch the client
export function fetchSingleClient(id) {
  return {
    type: CLIENT_FETCH,
    payload: axios.get(`${endpoint}/id/${id}`).then(res => res.data)
  }
}

// resets active client back to null
// useful for creating a new client
export function resetClient() {
  return { type: CLIENT_RESET }
}

// updates form field when user types
export function updateClientField(name, value) {
  return { name, value, type: CLIENT_UPDATE_FIELD }
}

// receives client, sends data to backend,
// and dispatch the related actions
export function editClient(client, isEditMode) {
  const promise = axios({
    method: isEditMode ? 'put' : 'post',
    url: isEditMode ? `${endpoint}/id/${client.id}` : endpoint,
    data: client
  }).then(res => res.data)
  promise.then(() => browserHistory.push('/clients'))
  return {
    type: isEditMode ? CLIENT_UPDATE : CLIENT_CREATE,
    payload: promise
  }
}
export const saveClient = client => editClient(client, true)
export const createClient = client => editClient(client, false)

// receives client, deletes data in backend,
// and dispatch the related actions
export function deleteClient(client) {
  return {
    type: CLIENT_DELETE,
    payload: axios.delete(`${endpoint}/id/${client.id}`).then(res => res.data)
  }
}

// REDUCER
const clientsReducer = (state = {}, action = {}) => {
  const {type, payload = {}} = action
  switch (type) {
    case `${CLIENT_FETCH}_LOADING`:
    case `${CLIENT_UPDATE}_LOADING`:
    case `${CLIENT_CREATE}_LOADING`:
    case `${CLIENT_DELETE}_LOADING`:
      return {
        ...state,
        [payload.id]: {loading: true}
      }
    case `${CLIENT_FETCH}_SUCCESS`:
    case `${CLIENT_UPDATE}_SUCCESS`:
    case `${CLIENT_CREATE}_SUCCESS`:
      return {
        ...state,
        [payload.id]: payload
      }
    case `${CLIENT_DELETE}_SUCCESS`:
      const copy = {...state}
      delete copy[payload.id]
      return copy
    case `${CLIENT_FETCH}_ERROR`:
    case `${CLIENT_UPDATE}_ERROR`:
    case `${CLIENT_CREATE}_ERROR`:
    case `${CLIENT_DELETE}_ERROR`:
      return {
        ...state,
        [payload.id]: {loading: false, error: payload}
      }
    default:
      return paginator.reducers.items(state, action)
  }
}

export default combineReducers({
  entities: clientsReducer,
  pagination: paginator.reducers.pagination
})
<|endoftext|>