<commit_before>"use strict";

/**
* Represents an command framework command
* @prop {Object} subcommands Object mapping subcommand labels to Command objects
*/
class Command {
    /**
    * Register a command
    * @arg {String} label The command label
    * @arg {Function | String | Array<Function | String>} generator A response string, array of functions or strings, or function that generates a string or array of strings when called.
    * If a function is passed, the function will be passed a Message object and an array of command arguments. The Message object will have an additional property `prefix`, which is the prefix used in the command.
    *
generator(msg, args)

    * @arg {Object} [options] Command options
    * @arg {Array<String>} [options.aliases] An array of command aliases
    * @arg {Boolean} [options.caseInsensitive=false] Whether the command label (and aliases) is case insensitive or not
    * @arg {Boolean} [options.deleteCommand=false] Whether to delete the user command message or not
    * @arg {Boolean} [options.guildOnly=false] Whether to prevent the command from being used in Direct Messages or not
    * @arg {Boolean} [options.dmOnly=false] Whether to prevent the command from being used in guilds or not
    * @arg {String} [options.description="No description"] A short description of the command to show in the default help command
    * @arg {String} [options.fullDescription="No full description"] A detailed description of the command to show in the default help command
    * @arg {String} [options.usage] Details on how to call the command to show in the default help command
    * @arg {Object} [options.requirements] A set of factors that limit who can call the command
    * @arg {Array<String>} [options.requirements.userIDs] An array of user IDs representing users that can call the command
    * @arg {Object} [options.requirements.permissions] An object containing permission keys the user must match to use the command
    * i.e.:
    * ```
    * {
    *   "administrator": false,
    *   "manageMessages": true
    * }```
    * In the above example, the user must not have administrator permissions, but must have manageMessages to use the command
    * @arg {Array<String>} [options.requirements.roleIDs] An array of role IDs that would allow a user to use the command
    * @arg {Array<String>} [options.requirements.roleNames] An array of role names that would allow a user to use the command
    * @arg {Number} [cooldown] The cooldown between command usage in milliseconds
    */
    constructor(label, generator, options) {
        this.label = label;
        this.description = options.description || "No description";
        this.fullDescription = options.fullDescription || "No full description";
        this.usage = options.usage || "";
        this.aliases = options.aliases || [];
        this.caseInsensitive = !!options.caseInsensitive;
        this.requirements = options.requirements || {};
        if(!this.requirements.userIDs) {
            this.requirements.userIDs = [];
        }
        if(!this.requirements.permissions) {
            this.requirements.permissions = {};
        }
        if(!this.requirements.roleIDs) {
            this.requirements.roleIDs = [];
        }
        if(!this.requirements.roleNames) {
            this.requirements.roleNames = [];
        }
        this.deleteCommand = !!options.deleteCommand;
        this.guildOnly = !!options.guildOnly;
        this.dmOnly = !!options.dmOnly;
        this.cooldown = options.cooldown || 0;
        if(this.cooldown !== 0) {
            this.usersOnCooldown = new Set();
        }
        if(typeof generator === "string") {
            this.response = generator;
            this.execute = () => this.response;
        } else if(Array.isArray(generator)) {
            this.responses = generator.map((item, index) => {
                if(typeof generator === "string") {
                    return () => generator;
                } else if(typeof generator === "function") {
                    return generator;
                } else {
                    throw new Error("Invalid command response generator (index " + index + ")");
                }
            });
            this.execute = () => this.responses[Math.floor(Math.random() * this.responses.length)];
        } else if(typeof generator === "function") {
            this.execute = generator;
        } else {
            throw new Error("Invalid command response generator");
        }

        this.subcommands = {};
        this.subcommandAliases = {};
    }

    permissionCheck(msg) {
        var req = false;
        if(this.requirements.userIDs.length > 0) {
            req = true;
            if(~this.requirements.userIDs.indexOf(msg.author.id)) {
                return true;
            }
        }
        if(!msg.channel.guild) {
            return !this.guildOnly && !req;
        } else if(this.dmOnly) {
            return false;
        }
        var keys = Object.keys(this.requirements.permissions);
        if(keys.length > 0) {
            req = true;
            var permissions = msg.channel.permissionsOf(msg.author.id).json;
            for(var key of keys) {
                if(this.requirements.permissions[key] !== permissions[key]) {
                    req = false;
                    break;
                }
            }
            if(req) {
                return true;
            }
            req = true;
        }
        if(msg.member && msg.member.roles.length > 0) {
            var roles = msg.member.roles;
            if(this.requirements.roleIDs.length > 0) {
                req = true;
                for(var roleID of this.requirements.roleIDs) {
                    if(~roles.indexOf(roleID)) {
                        return true;
                    }
                }
            }
            if(this.requirements.roleNames.length > 0) {
                req = true;
                roles = roles.map((roleID) => msg.channel.guild.roles.get(roleID).name);
                for(var roleName of this.requirements.roleNames) {
                    if(~roles.indexOf(roleName)) {
                        return true;
                    }
                }
            }
        }
        return !req;
    }

    cooldownCheck(userID) {
        if(this.usersOnCooldown.has(userID)) {
            return false;
        }
        this.usersOnCooldown.add(userID);
        setTimeout(() => {
            this.usersOnCooldown.delete(userID);
        }, this.cooldown);
        return true;
    }

    process(args, msg) {
        if(!this.permissionCheck(msg)) {
            return;
        }
        if(args.length === 0) {
            if(this.cooldown !== 0 && !this.cooldownCheck(msg.author.id)) {
                return;
            }
            return this.execute(msg, args);
        }
        var label = this.subcommandAliases[args[0]] || args[0];
        var subcommand;
        if((subcommand = this.subcommands[label]) !== undefined || ((subcommand = this.subcommands[label.toLowerCase()]) !== undefined && subcommand.caseInsensitive)) {
            return subcommand.process(args.slice(1), msg);
        } else {
            if(this.cooldown !== 0 && !this.cooldownCheck(msg.author.id)) {
                return;
            }
            return this.execute(msg, args);
        }
    }

    /**
    * Register an alias for a subcommand
    * @arg {String} alias The alias
    * @arg {String} label The original subcommand label
    */
    registerSubcommandAlias(alias, label) {
        if(!this.subcommands[label]) {
            throw new Error("No subcommand registered for " + label);
        }
        if(this.subcommandAliases[alias]) {
            throw new Error(`Alias ${label} already registered`);
        }
        this.subcommandAliases[alias] = label;
        this.subcommands[label].aliases.push(alias);
    }

    /**
    * Register a subcommand
    * @arg {String} label The subcommand label
    * @arg {Function | String | Array<Function | String>} generator A response string, array of functions or strings, or function that generates a string or array of strings when called.
    * If a function is passed, the function will be passed a Message object and an array of subcommand arguments. The Message object will have an additional property `prefix`, which is the prefix used in the subcommand.
    *
generator(msg, args)

    * @arg {Object} [options] Command options
    * @arg {Array<String>} [options.aliases] An array of subcommand aliases
    * @arg {Boolean} [options.caseInsensitive=false] Whether the subcommand label (and aliases) is case insensitive or not
    * @arg {Boolean} [options.deleteCommand=false] Whether to delete the user subcommand message or not
    * @arg {Boolean} [options.guildOnly=false] Whether to prevent the subcommand from being used in Direct Messages or not
    * @arg {Boolean} [options.dmOnly=false] Whether to prevent the subcommand from being used in guilds or not
    * @arg {String} [options.description="No description"] A short description of the subcommand to show in the default help subcommand
    * @arg {String} [options.fullDescription="No full description"] A detailed description of the subcommand to show in the default help subcommand
    * @arg {String} [options.usage] Details on how to call the subcommand to show in the default help subcommand
    * @arg {Object} [options.requirements] A set of factors that limit who can call the subcommand
    * @arg {Array<String>} [options.requirements.userIDs] An array of user IDs representing users that can call the subcommand
    * @arg {Object} [options.requirements.permissions] An object containing permission keys the user must match to use the subcommand
    * i.e.:
    * ```
    * {
    *   "administrator": false,
    *   "manageMessages": true
    * }```
    * In the above example, the user must not have administrator permissions, but must have manageMessages to use the subcommand
    * @arg {Array<String>} [options.requirements.roleIDs] An array of role IDs that would allow a user to use the subcommand
    * @arg {Array<String>} [options.requirements.roleNames] An array of role names that would allow a user to use the subcommand
    * @arg {Number} [cooldown] The cooldown between command usage in milliseconds
    * @returns {Command}
    */
    registerSubcommand(label, generator, options) {
        if(label.includes(" ")) {
            throw new Error("Subcommand label may not have spaces");
        }
        if(this.subcommands[label]) {
            throw new Error("You have already registered a subcommand for " + label);
        }
        options = options || {};
        this.subcommands[label] = new Command(label, generator, options);
        if(options.aliases) {
            options.aliases.forEach((alias) => {
                this.subcommandAliases[alias] = label;
            });
        }
        return this.subcommands[label];
    }

    /**
    * Unregister a subcommand
    * @arg {String} label The subcommand label
    */
    unregisterSubcommand(label) {
        var original = this.subcommandAliases[label];
        if(original) {
            this.subcommands[original].aliases.splice(this.subcommands[original].aliases.indexOf(label), 1);
            this.subcommandAliases[label] = undefined;
        } else {
            this.subcommands[label] = undefined;
        }
    }
}

module.exports = Command;
<commit_msg>Fix array-based command generators<commit_after>"use strict";

/**
* Represents an command framework command
* @prop {Object} subcommands Object mapping subcommand labels to Command objects
*/
class Command {
    /**
    * Register a command
    * @arg {String} label The command label
    * @arg {Function | String | Array<Function | String>} generator A response string, array of functions or strings, or function that generates a string or array of strings when called.
    * If a function is passed, the function will be passed a Message object and an array of command arguments. The Message object will have an additional property `prefix`, which is the prefix used in the command.
    *
generator(msg, args)

    * @arg {Object} [options] Command options
    * @arg {Array<String>} [options.aliases] An array of command aliases
    * @arg {Boolean} [options.caseInsensitive=false] Whether the command label (and aliases) is case insensitive or not
    * @arg {Boolean} [options.deleteCommand=false] Whether to delete the user command message or not
    * @arg {Boolean} [options.guildOnly=false] Whether to prevent the command from being used in Direct Messages or not
    * @arg {Boolean} [options.dmOnly=false] Whether to prevent the command from being used in guilds or not
    * @arg {String} [options.description="No description"] A short description of the command to show in the default help command
    * @arg {String} [options.fullDescription="No full description"] A detailed description of the command to show in the default help command
    * @arg {String} [options.usage] Details on how to call the command to show in the default help command
    * @arg {Object} [options.requirements] A set of factors that limit who can call the command
    * @arg {Array<String>} [options.requirements.userIDs] An array of user IDs representing users that can call the command
    * @arg {Object} [options.requirements.permissions] An object containing permission keys the user must match to use the command
    * i.e.:
    * ```
    * {
    *   "administrator": false,
    *   "manageMessages": true
    * }```
    * In the above example, the user must not have administrator permissions, but must have manageMessages to use the command
    * @arg {Array<String>} [options.requirements.roleIDs] An array of role IDs that would allow a user to use the command
    * @arg {Array<String>} [options.requirements.roleNames] An array of role names that would allow a user to use the command
    * @arg {Number} [cooldown] The cooldown between command usage in milliseconds
    */
    constructor(label, generator, options) {
        this.label = label;
        this.description = options.description || "No description";
        this.fullDescription = options.fullDescription || "No full description";
        this.usage = options.usage || "";
        this.aliases = options.aliases || [];
        this.caseInsensitive = !!options.caseInsensitive;
        this.requirements = options.requirements || {};
        if(!this.requirements.userIDs) {
            this.requirements.userIDs = [];
        }
        if(!this.requirements.permissions) {
            this.requirements.permissions = {};
        }
        if(!this.requirements.roleIDs) {
            this.requirements.roleIDs = [];
        }
        if(!this.requirements.roleNames) {
            this.requirements.roleNames = [];
        }
        this.deleteCommand = !!options.deleteCommand;
        this.guildOnly = !!options.guildOnly;
        this.dmOnly = !!options.dmOnly;
        this.cooldown = options.cooldown || 0;
        if(this.cooldown !== 0) {
            this.usersOnCooldown = new Set();
        }
        if(typeof generator === "string") {
            this.response = generator;
            this.execute = () => this.response;
        } else if(Array.isArray(generator)) {
            this.responses = generator.map((item) => {
                if(typeof item === "string") {
                    return () => item;
                } else if(typeof item === "function") {
                    return item;
                } else {
                    throw new Error("Invalid command response generator (index " + index + ")");
                }
            });
            this.execute = () => this.responses[Math.floor(Math.random() * this.responses.length)];
        } else if(typeof generator === "function") {
            this.execute = generator;
        } else {
            throw new Error("Invalid command response generator");
        }

        this.subcommands = {};
        this.subcommandAliases = {};
    }

    permissionCheck(msg) {
        var req = false;
        if(this.requirements.userIDs.length > 0) {
            req = true;
            if(~this.requirements.userIDs.indexOf(msg.author.id)) {
                return true;
            }
        }
        if(!msg.channel.guild) {
            return !this.guildOnly && !req;
        } else if(this.dmOnly) {
            return false;
        }
        var keys = Object.keys(this.requirements.permissions);
        if(keys.length > 0) {
            req = true;
            var permissions = msg.channel.permissionsOf(msg.author.id).json;
            for(var key of keys) {
                if(this.requirements.permissions[key] !== permissions[key]) {
                    req = false;
                    break;
                }
            }
            if(req) {
                return true;
            }
            req = true;
        }
        if(msg.member && msg.member.roles.length > 0) {
            var roles = msg.member.roles;
            if(this.requirements.roleIDs.length > 0) {
                req = true;
                for(var roleID of this.requirements.roleIDs) {
                    if(~roles.indexOf(roleID)) {
                        return true;
                    }
                }
            }
            if(this.requirements.roleNames.length > 0) {
                req = true;
                roles = roles.map((roleID) => msg.channel.guild.roles.get(roleID).name);
                for(var roleName of this.requirements.roleNames) {
                    if(~roles.indexOf(roleName)) {
                        return true;
                    }
                }
            }
        }
        return !req;
    }

    cooldownCheck(userID) {
        if(this.usersOnCooldown.has(userID)) {
            return false;
        }
        this.usersOnCooldown.add(userID);
        setTimeout(() => {
            this.usersOnCooldown.delete(userID);
        }, this.cooldown);
        return true;
    }

    process(args, msg) {
        if(!this.permissionCheck(msg)) {
            return;
        }
        if(args.length === 0) {
            if(this.cooldown !== 0 && !this.cooldownCheck(msg.author.id)) {
                return;
            }
            return this.execute(msg, args);
        }
        var label = this.subcommandAliases[args[0]] || args[0];
        var subcommand;
        if((subcommand = this.subcommands[label]) !== undefined || ((subcommand = this.subcommands[label.toLowerCase()]) !== undefined && subcommand.caseInsensitive)) {
            return subcommand.process(args.slice(1), msg);
        } else {
            if(this.cooldown !== 0 && !this.cooldownCheck(msg.author.id)) {
                return;
            }
            return this.execute(msg, args);
        }
    }

    /**
    * Register an alias for a subcommand
    * @arg {String} alias The alias
    * @arg {String} label The original subcommand label
    */
    registerSubcommandAlias(alias, label) {
        if(!this.subcommands[label]) {
            throw new Error("No subcommand registered for " + label);
        }
        if(this.subcommandAliases[alias]) {
            throw new Error(`Alias ${label} already registered`);
        }
        this.subcommandAliases[alias] = label;
        this.subcommands[label].aliases.push(alias);
    }

    /**
    * Register a subcommand
    * @arg {String} label The subcommand label
    * @arg {Function | String | Array<Function | String>} generator A response string, array of functions or strings, or function that generates a string or array of strings when called.
    * If a function is passed, the function will be passed a Message object and an array of subcommand arguments. The Message object will have an additional property `prefix`, which is the prefix used in the subcommand.
    *
generator(msg, args)

    * @arg {Object} [options] Command options
    * @arg {Array<String>} [options.aliases] An array of subcommand aliases
    * @arg {Boolean} [options.caseInsensitive=false] Whether the subcommand label (and aliases) is case insensitive or not
    * @arg {Boolean} [options.deleteCommand=false] Whether to delete the user subcommand message or not
    * @arg {Boolean} [options.guildOnly=false] Whether to prevent the subcommand from being used in Direct Messages or not
    * @arg {Boolean} [options.dmOnly=false] Whether to prevent the subcommand from being used in guilds or not
    * @arg {String} [options.description="No description"] A short description of the subcommand to show in the default help subcommand
    * @arg {String} [options.fullDescription="No full description"] A detailed description of the subcommand to show in the default help subcommand
    * @arg {String} [options.usage] Details on how to call the subcommand to show in the default help subcommand
    * @arg {Object} [options.requirements] A set of factors that limit who can call the subcommand
    * @arg {Array<String>} [options.requirements.userIDs] An array of user IDs representing users that can call the subcommand
    * @arg {Object} [options.requirements.permissions] An object containing permission keys the user must match to use the subcommand
    * i.e.:
    * ```
    * {
    *   "administrator": false,
    *   "manageMessages": true
    * }```
    * In the above example, the user must not have administrator permissions, but must have manageMessages to use the subcommand
    * @arg {Array<String>} [options.requirements.roleIDs] An array of role IDs that would allow a user to use the subcommand
    * @arg {Array<String>} [options.requirements.roleNames] An array of role names that would allow a user to use the subcommand
    * @arg {Number} [cooldown] The cooldown between command usage in milliseconds
    * @returns {Command}
    */
    registerSubcommand(label, generator, options) {
        if(label.includes(" ")) {
            throw new Error("Subcommand label may not have spaces");
        }
        if(this.subcommands[label]) {
            throw new Error("You have already registered a subcommand for " + label);
        }
        options = options || {};
        this.subcommands[label] = new Command(label, generator, options);
        if(options.aliases) {
            options.aliases.forEach((alias) => {
                this.subcommandAliases[alias] = label;
            });
        }
        return this.subcommands[label];
    }

    /**
    * Unregister a subcommand
    * @arg {String} label The subcommand label
    */
    unregisterSubcommand(label) {
        var original = this.subcommandAliases[label];
        if(original) {
            this.subcommands[original].aliases.splice(this.subcommands[original].aliases.indexOf(label), 1);
            this.subcommandAliases[label] = undefined;
        } else {
            this.subcommands[label] = undefined;
        }
    }
}

module.exports = Command;
<|endoftext|>


<commit_before>/**
 *  \details © 2011  Open Ximdex Evolution SL [http://www.ximdex.org]
 *
 *  Ximdex a Semantic Content Management System (CMS)
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 *  See the Affero GNU General Public License for more details.
 *  You should have received a copy of the Affero GNU General Public License
 *  version 3 along with Ximdex (see LICENSE file).
 *
 *  If not, visit http://gnu.org/licenses/agpl-3.0.html.
 *
 *  @author Ximdex DevTeam <dev@ximdex.com>
 *  @version $Revision$
 */
angular.module('ximdex.common.directive')
    .directive('ximUploader', function () {
        return {
            replace: true,
            restrict: 'E',
            templateUrl : 'inc/js/angular/templates/ximUploader.html',
            controller: ['$scope', '$element', '$attrs', 'xUrlHelper', 'xTranslate', function($scope, $element, $attrs, xUrlHelper, xTranslate){

            	$scope.nodeId = $attrs.ximNodeId;

            	$scope.targetUrl = xUrlHelper.getAction({
    	            action: 'fileupload_common_multiple',
    	            type: 'common',
    	            method: 'uploadFlowFile',
    	            id: $scope.nodeId,
    	        });

                $scope.options = angular.fromJson($attrs.ximUploaderOptions);
    	    	if ($scope.options.metaFields) {
                    $scope.globalMeta = {};
                }

    	    	$scope.$on('flow::fileAdded', function (event, $flow, file) {
                    if ($scope.options.allowedExtensions && $scope.options.allowedExtensions.indexOf(file.getExtension()) === -1) {
                        //Prevent adding file if is not accepted
                        event.preventDefault();
                    };
                    file.isImage = (file.file.type.indexOf("image") === -1) ? false : true;
    	    	});

    	    	$scope.$on('flow::fileError', function (event, $flow, file, jsonMessage) {
    	    		var message = angular.fromJson(jsonMessage);
                    if (message && message.msg) {
                        file.errorMsg = message.msg;
                    }
    	    	});

    	    	$scope.$on('flow::fileSuccess', function (event, $flow, file, jsonMessage) {
    	    		var message = angular.fromJson(jsonMessage);
                    if (message && message.msg) {
                        file.successMsg = message.msg;
                    }
    	    	});

    	    	$scope.$on('flow::Complete', function () {
    	    		console.log("nodeModified", $scope.nodeId)
                    $scope.$emit('nodeModified', $scope.nodeId);
    	    	});

    	    	$scope.uploadFiles = function() {
                    if ($scope.allowUpload()) {
                		$scope.$flow.opts.target = $scope.targetUrl;
                        $scope.$flow.opts.query = function(file, chunk) {
                            var query = {
                                meta: angular.toJson(file.meta || $scope.globalMeta),
                                overwrite: file.overwrite || false,
                                ximFilename: file.ximFilename
                            };
                            return query;
        	            };
        	    		$scope.$flow.opts.testChunks = false;
        	            $scope.$flow.opts.progressCallbacksInterval = 0;
        	    		$scope.$flow.upload();
                        console.log("UPLOAD, ", $scope.$flow.files);
                    }
    	    	}

                $scope.allowUpload = function(){
                    if (!$scope.totalFiles() > 0 && $scope.invalidFiles === $scope.totalFiles()) {
                        return false;
                    } else if(!!$scope.options.metaFields && $scope.options.globalMetaOnly){
                        for (field in $scope.options.metaFields) {
                            if ($scope.options.metaFields[field].required) {
                                if (!$scope.globalMeta || !$scope.globalMeta[field]) {
                                    return false
                                }
                            }
                        }
                    }
                    if ($scope.invalidFiles === $scope.$flow.files.length) return false;
                    return true;
                }

                $scope.uploadButtonLabel = function(){
                    //TODO: Adapt xTranslate to deal with replacement arguments
                    var label = xTranslate('widgets.fileUploader.upload')+' '+( $scope.totalFiles() - $scope.invalidFiles())+' '+xTranslate('widgets.fileUploader.files');
                    return label;
                }

                $scope.invalidFiles = function(){
                    var count = 0;
                    for (var i = $scope.$flow.files.length - 1; i >= 0; i--) {
                        if ($scope.$flow.files[i].invalid) {
                            count ++
                        }
                    };
                    return count;
                }
                $scope.totalFiles = function(){
                    var count = 0;
                    for (var i = $scope.$flow.files.length - 1; i >= 0; i--) {
                        if (!$scope.$flow.files[i].isComplete() && !$scope.$flow.files[i].error) {
                            count ++
                        }
                    };
                    return count;
                }
            }]
        }
    });<commit_msg>Minor issue<commit_after>/**
 *  \details © 2011  Open Ximdex Evolution SL [http://www.ximdex.org]
 *
 *  Ximdex a Semantic Content Management System (CMS)
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 *  See the Affero GNU General Public License for more details.
 *  You should have received a copy of the Affero GNU General Public License
 *  version 3 along with Ximdex (see LICENSE file).
 *
 *  If not, visit http://gnu.org/licenses/agpl-3.0.html.
 *
 *  @author Ximdex DevTeam <dev@ximdex.com>
 *  @version $Revision$
 */
angular.module('ximdex.common.directive')
    .directive('ximUploader', function () {
        return {
            replace: true,
            restrict: 'E',
            templateUrl : 'inc/js/angular/templates/ximUploader.html',
            controller: ['$scope', '$element', '$attrs', 'xUrlHelper', 'xTranslate', function($scope, $element, $attrs, xUrlHelper, xTranslate){

            	$scope.nodeId = $attrs.ximNodeId;

            	$scope.targetUrl = xUrlHelper.getAction({
    	            action: 'fileupload_common_multiple',
    	            type: 'common',
    	            method: 'uploadFlowFile',
    	            id: $scope.nodeId,
    	        });

                $scope.options = angular.fromJson($attrs.ximUploaderOptions);
    	    	if ($scope.options.metaFields) {
                    $scope.globalMeta = {};
                }

    	    	$scope.$on('flow::fileAdded', function (event, $flow, file) {
                    if ($scope.options.allowedExtensions && $scope.options.allowedExtensions.indexOf(file.getExtension()) === -1) {
                        //Prevent adding file if is not accepted
                        event.preventDefault();
                    };
                    file.isImage = (file.file.type.indexOf("image") === -1) ? false : true;
    	    	});

    	    	$scope.$on('flow::fileError', function (event, $flow, file, jsonMessage) {
    	    		var message = (jsonMessage) ? angular.fromJson(jsonMessage) : null;
                    if (message && message.msg) {
                        file.errorMsg = message.msg;
                    }
    	    	});

    	    	$scope.$on('flow::fileSuccess', function (event, $flow, file, jsonMessage) {
    	    		var message = (jsonMessage) ? angular.fromJson(jsonMessage) : null;
                    if (message && message.msg) {
                        file.successMsg = message.msg;
                    }
    	    	});

    	    	$scope.$on('flow::Complete', function () {
    	    		console.log("nodeModified", $scope.nodeId)
                    $scope.$emit('nodeModified', $scope.nodeId);
    	    	});

    	    	$scope.uploadFiles = function() {
                    if ($scope.allowUpload()) {
                		$scope.$flow.opts.target = $scope.targetUrl;
                        $scope.$flow.opts.query = function(file, chunk) {
                            var query = {
                                meta: angular.toJson(file.meta || $scope.globalMeta),
                                overwrite: file.overwrite || false,
                                ximFilename: file.ximFilename
                            };
                            return query;
        	            };
        	    		$scope.$flow.opts.testChunks = false;
        	            $scope.$flow.opts.progressCallbacksInterval = 0;
        	    		$scope.$flow.upload();
                        console.log("UPLOAD, ", $scope.$flow.files);
                    }
    	    	}

                $scope.allowUpload = function(){
                    if (!$scope.totalFiles() > 0 && $scope.invalidFiles === $scope.totalFiles()) {
                        return false;
                    } else if(!!$scope.options.metaFields && $scope.options.globalMetaOnly){
                        for (field in $scope.options.metaFields) {
                            if ($scope.options.metaFields[field].required) {
                                if (!$scope.globalMeta || !$scope.globalMeta[field]) {
                                    return false
                                }
                            }
                        }
                    }
                    if ($scope.invalidFiles === $scope.$flow.files.length) return false;
                    return true;
                }

                $scope.uploadButtonLabel = function(){
                    //TODO: Adapt xTranslate to deal with replacement arguments
                    var label = xTranslate('widgets.fileUploader.upload')+' '+( $scope.totalFiles() - $scope.invalidFiles())+' '+xTranslate('widgets.fileUploader.files');
                    return label;
                }

                $scope.invalidFiles = function(){
                    var count = 0;
                    for (var i = $scope.$flow.files.length - 1; i >= 0; i--) {
                        if ($scope.$flow.files[i].invalid) {
                            count ++
                        }
                    };
                    return count;
                }
                $scope.totalFiles = function(){
                    var count = 0;
                    for (var i = $scope.$flow.files.length - 1; i >= 0; i--) {
                        if (!$scope.$flow.files[i].isComplete() && !$scope.$flow.files[i].error) {
                            count ++
                        }
                    };
                    return count;
                }
            }]
        }
    });<|endoftext|>


<commit_before>'use strict';

var install         = module.exports = {};

var node_path       = require('path');
var async           = require('async');
var fs              = require('fs-sync');

// Attension: there will no arguments checking
// @param {Object} options:
// - modules: {Array.<string>} modules to install, ['a@1.0.1', 'b@0.0.2'], notice that the version of each module must be specified:
//    'a' should be 'a@latest', or there will be an failure
// - save: {boolean} save cortexDependencies
// - cwd: {string}
// - desc: {string} private property, which will never called by command-line
// - recursive: {boolean} if false, cortex will not install dependencies

// @param {function()} callback
install.run = function(options, callback){
    var modules = options.modules;
    var should_save = options.save;
    var cwd = options.cwd;

    var MODULE_ROOT = install.context.profile.get('cache_root');

    async.waterfall([
        function(done) {
            var command_description = options.desc || 'installing';

            install.logger.info('{{cyan ' + command_description + '}}', '["' + modules.join('", "') + '"]');

            // suppose:
            // 1. modules -> ['a@~0.0.1', 'b@0.0.2']
            // 2. dependencies of 'b@0.0.2' -> ['~a@0.1.2']
            install.context.neuropil.install({
                modules: modules,
                dir: MODULE_ROOT,
                recursive: options.recursive,
                dependency_key: 'cortex.exactDependencies'

            }, done);
        },

        // @type {Object} all versions including dependencies
        // {
        //     'a': {
        //         '0.0.2': {...}
        //         '0.1.2': {...}
        //     },
        //     'b': {
        //         '0.0.2': {...}
        //     }
        // }
        // X data,

        // @type {Object} the direct version of the module to be installed
        // {'a': '0.0.1' }
        // X installed_map_without_deps

        // {
        //     origins: {
        //         'a': ['~0.0.1'],
        //         'b': ['0.0.2']
        //     },

        //     packages: {
        //         'a': {
        //             '0.0.7': <pkg>,
        //             '0.1.3': <pkg>
        //         },

        //         'b': {
        //             '0.0.2': <pkg>
        //         }
        //     },

        //     // according to `options.dependency_key`
        //     dependencies: {
        //         'a': {
        //             '0.0.7': {}, // no deps
        //             '0.1.3': {}
        //         },

        //         'b': {
        //             '0.0.2': {
        //                 'a': '~0.1.2'
        //             }
        //         }
        //     },

        //     ranges: {
        //         'a': {
        //             '~0.0.1': '0.0.7',
        //             '~0.1.2': '0.1.3'
        //         }
        //     }
        // }

        function(data, done) {
            // build modules
            var series = [];
            var commander = install.context.commander;

            install.iterate_packages(data.packages, function (name, version) {
                series.push(function(sub_done) {

                    // mock process.argv
                    var argv = [
                        '', '',
                        'build',
                        '--cwd',
                        node_path.join(MODULE_ROOT, name, version, 'package')
                    ];

                    var parsed = commander.parse(argv, function(err, result, details){
                        if ( err ) {
                            return sub_done(err);
                        }

                        // exec cortex.commands.build method
                        commander.run('build', result.opt, function(err) {
                            sub_done(err);
                        });
                    });
                });
            });

            async.parallel(series, function(err) {
                if(err){
                    return done(err);
                }

                done(null, data);
            });
        }

    ], function(err, data) {
        if(err){
            return callback(err);
        }

        // save to package.json
        if(should_save){
            var package_file = node_path.join(cwd, 'package.json');
            var pkg = fs.readJSON(package_file);
            var ctx = pkg.cortex || (pkg.cortex = {});

            var deps = ctx.dependencies || (ctx.dependencies = {});
            var exact_deps = ctx.exactDependencies || (ctx.exactDependencies = {});

            Object.keys(data.origins).forEach(function(name) {
                var versions = data.origins[name];
                var ranges = data.ranges[name] || {};

                versions.forEach(function (version) {
                    var exact_version = ranges[version] || version;

                    deps[name] = '~' + exact_version;
                    exact_deps[name] = exact_version;
                });
            });

            fs.write( package_file, JSON.stringify(pkg, null, 4) );
        }

        callback(null, data);
    });
};

// @param {Object} packages
// @param {function(name, version)} callback
install.iterate_packages = function (packages, callback) {
    var name;
    var versions;
    var version;

    for(name in packages){
        versions = packages[name];

        for(version in versions){
            callback(name, version);
        }
    }
};

<commit_msg>fixes #130: Abandon "cortex.exactDependencies"; related to #117<commit_after>'use strict';

var install         = module.exports = {};

var node_path       = require('path');
var async           = require('async');
var fs              = require('fs-sync');

// Attension: there will no arguments checking
// @param {Object} options:
// - modules: {Array.<string>} modules to install, ['a@1.0.1', 'b@0.0.2'], notice that the version of each module must be specified:
//    'a' should be 'a@latest', or there will be an failure
// - save: {boolean} save cortexDependencies
// - cwd: {string}
// - desc: {string} private property, which will never called by command-line
// - recursive: {boolean} if false, cortex will not install dependencies

// @param {function()} callback
install.run = function(options, callback){
    var modules = options.modules;
    var should_save = options.save;
    var cwd = options.cwd;

    var MODULE_ROOT = install.context.profile.get('cache_root');

    async.waterfall([
        function(done) {
            var command_description = options.desc || 'installing';

            install.logger.info('{{cyan ' + command_description + '}}', '["' + modules.join('", "') + '"]');

            // suppose:
            // 1. modules -> ['a@~0.0.1', 'b@0.0.2']
            // 2. dependencies of 'b@0.0.2' -> ['~a@0.1.2']
            install.context.neuropil.install({
                modules: modules,
                dir: MODULE_ROOT,
                recursive: options.recursive,
                dependency_key: 'cortex.exactDependencies'

            }, done);
        },

        // @type {Object} all versions including dependencies
        // {
        //     'a': {
        //         '0.0.2': {...}
        //         '0.1.2': {...}
        //     },
        //     'b': {
        //         '0.0.2': {...}
        //     }
        // }
        // X data,

        // @type {Object} the direct version of the module to be installed
        // {'a': '0.0.1' }
        // X installed_map_without_deps

        // {
        //     origins: {
        //         'a': ['~0.0.1'],
        //         'b': ['0.0.2']
        //     },

        //     packages: {
        //         'a': {
        //             '0.0.7': <pkg>,
        //             '0.1.3': <pkg>
        //         },

        //         'b': {
        //             '0.0.2': <pkg>
        //         }
        //     },

        //     // according to `options.dependency_key`
        //     dependencies: {
        //         'a': {
        //             '0.0.7': {}, // no deps
        //             '0.1.3': {}
        //         },

        //         'b': {
        //             '0.0.2': {
        //                 'a': '~0.1.2'
        //             }
        //         }
        //     },

        //     ranges: {
        //         'a': {
        //             '~0.0.1': '0.0.7',
        //             '~0.1.2': '0.1.3'
        //         }
        //     }
        // }

        function(data, done) {
            // build modules
            var series = [];
            var commander = install.context.commander;

            install.iterate_packages(data.packages, function (name, version) {
                series.push(function(sub_done) {

                    // mock process.argv
                    var argv = [
                        '', '',
                        'build',
                        '--cwd',
                        node_path.join(MODULE_ROOT, name, version, 'package')
                    ];

                    var parsed = commander.parse(argv, function(err, result, details){
                        if ( err ) {
                            return sub_done(err);
                        }

                        // exec cortex.commands.build method
                        commander.run('build', result.opt, function(err) {
                            sub_done(err);
                        });
                    });
                });
            });

            async.parallel(series, function(err) {
                if(err){
                    return done(err);
                }

                done(null, data);
            });
        }

    ], function(err, data) {
        if(err){
            return callback(err);
        }

        // save to package.json
        if(should_save){
            var package_file = node_path.join(cwd, 'package.json');
            var pkg = fs.readJSON(package_file);
            var ctx = pkg.cortex || (pkg.cortex = {});

            var deps = ctx.dependencies || (ctx.dependencies = {});
            // var exact_deps = ctx.exactDependencies || (ctx.exactDependencies = {});

            Object.keys(data.origins).forEach(function(name) {
                var versions = data.origins[name];
                var ranges = data.ranges[name] || {};

                versions.forEach(function (version) {
                    var exact_version = ranges[version] || version;

                    deps[name] = '~' + exact_version;
                    // exact_deps[name] = exact_version;
                });
            });

            fs.write( package_file, JSON.stringify(pkg, null, 4) );
        }

        callback(null, data);
    });
};

// @param {Object} packages
// @param {function(name, version)} callback
install.iterate_packages = function (packages, callback) {
    var name;
    var versions;
    var version;

    for(name in packages){
        versions = packages[name].versions || {};

        for(version in versions){
            callback(name, version);
        }
    }
};

<|endoftext|>


<commit_before>'use strict';
const Command = require('../command');
const options = require('../tasks/configure/options');

class ConfigCommand extends Command {
    static configureSubcommands(commandName, commandArgs, extensions) {
        return commandArgs.command({
            command: 'get <key>',
            describe: 'Get a specific value from the configuration file',
            handler: argv => this._run(`${commandName} get`, argv, extensions)
        }).command({
            command: 'set <key> <value>',
            describe: 'Set a specific value in the configuration file',
            handler: argv => this._run(`${commandName} set`, argv, extensions)
        });
    }

    constructor(ui, system) {
        super(ui, system);

        this.instance = this.system.getInstance();
    }

    async run(argv) {
        const {key, value} = argv;

        this.instance.checkEnvironment();

        if (key && !value) {
            // getter
            if (this.instance.config.has(key)) {
                this.ui.log(this.instance.config.get(key));
            }

            return;
        } else if (key) {
            // setter
            this.instance.config.set(key, value).save();
            this.ui.log(`Successfully set '${key}' to '${value}'`, 'green');
            return;
        }

        const configure = require('../tasks/configure');
        await configure(this.ui, this.instance.config, argv, this.system.environment, false);
    }
}

ConfigCommand.description = 'View or edit Ghost configuration';
ConfigCommand.longDescription = '$0 config [key] [value]\n View or modify the configuration for a Ghost instance.';
ConfigCommand.params = '[key] [value]';
ConfigCommand.options = options;
ConfigCommand.allowRoot = true;

module.exports = ConfigCommand;
<commit_msg>feat(config): remind user to restart ghost after making changes (#1382)<commit_after>'use strict';
const Command = require('../command');
const options = require('../tasks/configure/options');

class ConfigCommand extends Command {
    static configureSubcommands(commandName, commandArgs, extensions) {
        return commandArgs.command({
            command: 'get <key>',
            describe: 'Get a specific value from the configuration file',
            handler: argv => this._run(`${commandName} get`, argv, extensions)
        }).command({
            command: 'set <key> <value>',
            describe: 'Set a specific value in the configuration file',
            handler: argv => this._run(`${commandName} set`, argv, extensions)
        });
    }

    constructor(ui, system) {
        super(ui, system);

        this.instance = this.system.getInstance();
    }

    async run(argv) {
        const {key, value} = argv;

        this.instance.checkEnvironment();

        if (key && !value) {
            // getter
            if (this.instance.config.has(key)) {
                this.ui.log(this.instance.config.get(key));
            }

            return;
        } else if (key) {
            // setter
            this.instance.config.set(key, value).save();
            this.ui.log(`Successfully set '${key}' to '${value}'`, 'green');

            // If the instance is running, we want to remind the user to restart
            // it so the new config can take effect. The isRunning check is only
            // a nicety, so if it fails, swallow the error for better UX.
            try {
                if (await this.instance.isRunning()) {
                    const chalk = require('chalk');
                    this.ui.log(
                        `Ghost is running. Don't forget to run ${chalk.cyan('ghost restart')} to reload the config!`
                    );
                }
            } catch (_) {} // eslint-disable-line no-empty

            return;
        }

        const configure = require('../tasks/configure');
        await configure(this.ui, this.instance.config, argv, this.system.environment, false);
    }
}

ConfigCommand.description = 'View or edit Ghost configuration';
ConfigCommand.longDescription = '$0 config [key] [value]\n View or modify the configuration for a Ghost instance.';
ConfigCommand.params = '[key] [value]';
ConfigCommand.options = options;
ConfigCommand.allowRoot = true;

module.exports = ConfigCommand;
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var path = require('path'),
    async = require('async'),
    rimraf = require('rimraf'),
    install = require('./install'),
    tree = require('../tree'),
    project = require('../project'),
    logger = require('../logger'),
    clean = require('./clean'),
    argParse = require('../args').parse;

/**
 * Usage information and docs
 */

exports.summary = 'Removes a package from the package directory';

exports.usage = '' +
'jam remove PACKAGE [MORE...]\n' +
'\n' +
'Parameters:\n' +
'  PACKAGE    The package to remove\n' +
'\n' +
'Options:\n' +
'  -d, --package-dir  Package directory (defaults to "./jam")';

/* TODO
'  --clean        Runs clean command after removing the package, to remove\n' +
'                 any unused dependencies';
*/

/**
 * Run function called when "jam remove" command is used
 *
 * @param {Object} settings - the values from .jamrc files
 * @param {Array} args - command-line arguments
 */

exports.run = function (settings, args) {
    var a = argParse(args, {
        'target_dir': {match: ['-d', '--package-dir'], value: true},
        'recursive': {match: ['-R', '--recursive']} // runs clean afterwards
    });

    if (a.positional.length < 1) {
        console.log(exports.usage);
        logger.clean_exit = true;
        return;
    }

    var opt = a.options;
    opt.target_dir = opt.target_dir || settings.package_dir;

    var cwd = process.cwd();
    install.initDir(settings, cwd, opt, function (err, opt, cfg) {
        if (err) {
            return callback(err);
        }
        var names = a.positional;
        exports.checkDependants(settings, cfg, opt, names, function (err) {
            if (err) {
                return logger.error(err);
            }
            async.series({
                remove: async.apply(
                    async.forEach, names, async.apply(exports.remove, cfg, opt)
                ),
                tree: async.apply(exports.buildLocalTree, settings, cfg, opt)
            },
            function (err, results) {
                if (err) {
                    return logger.error(err);
                }
                var packages = results.tree;
                async.series([
                    async.apply(exports.reportUnused, packages, opt),

                    // TODO: write changes to package.json if --save option
                    // provided
                    //async.apply(project.writeMeta, opt.target_dir, cfg),

                    async.apply(
                        project.updateRequireConfig,
                        opt.target_dir,
                        opt.baseurl
                    ),
                    async.apply(exports.cleanUp, opt)
                ],
                function (err) {
                     if (err) {
                         return logger.error(err);
                     }
                     logger.end();
                });
            });
        });
    });
};

exports.checkDependants = function (settings, cfg, opt, names, callback) {
    exports.buildLocalTree(settings, cfg, opt, function (err, packages) {
        if (err) {
            return callback(err);
        }
        var has_dependants = false;
        for (var i = 0; i < names.length; i++) {
            var name = names[i];
            var pkg = packages[name];
            if (pkg) {
                var ranges = packages[name].ranges;
                var dependants = Object.keys(ranges).filter(function (d) {
                    return d !== '_root' && names.indexOf(d) === -1;
                });
                if (dependants.length) {
                    for (var j = 0; j < dependants.length; j++) {
                        var d = dependants[j];
                        logger.error(
                            d + ' depends on ' + name + ' ' + ranges[d]
                        );
                    };
                    has_dependants = true;
                }
            }
        };
        if (has_dependants) {
            return callback('Cannot remove package with dependants');
        }
        return callback();
    });
};

exports.remove = function (cfg, opt, name, callback) {
    logger.info('removing', name);
    delete cfg.dependencies[name];
    rimraf(path.resolve(opt.target_dir, name), callback);
};

exports.buildLocalTree = function (settings, cfg, opt, callback) {
    var local_sources = [
        install.dirSource(opt.target_dir),
        install.repoSource(settings.repositories, cfg)
    ];
    var newcfg = utils.convertToRootCfg(cfg);
    var pkg = {
        config: newcfg,
        source: 'root'
    };
    logger.info('Building local version tree...');
    tree.build(pkg, local_sources, callback);
};

exports.reportUnused = function (packages, opt, callback) {
    if (!opt.recursive) {
        exports.checkUnused(packages, opt, callback);
    }
    else {
        callback();
    }
};

exports.cleanUp = function (opt, callback) {
    if (opt.recursive) {
        clean.clean({
            target_dir: opt.target_dir,
            force: true
        }, callback);
    }
    else {
        callback();
    }
};

/**
 * Checks the packages directory for packages not in the provided version
 * tree.
 *
 * @param {Object} packages - the version tree to compare against
 * @param {Object} opt - the options object
 * @param {Function} callback
 */

exports.checkUnused = function (packages, opt, callback) {
    clean.unusedDirsTree(packages, opt, function (err, dirs) {
        if (err) {
            return callback(err);
        }
        if (dirs.length) {
            var names = dirs.map(function (d) {
                return path.relative('.', d);
            });
            console.log(
                '\n' +
                'The following packages are no longer required, ' +
                'and can be removed\nby running "jam clean":\n' +
                '    ' + names.join('\n    ') +
                '\n'
            );
        }
        return callback(null, packages);
    });
};
<commit_msg>updated remove command to work with package.json and no longer warn about unused packages<commit_after>/**
 * Module dependencies
 */

var path = require('path'),
    async = require('async'),
    rimraf = require('rimraf'),
    install = require('./install'),
    tree = require('../tree'),
    utils = require('../utils'),
    project = require('../project'),
    logger = require('../logger'),
    clean = require('./clean'),
    argParse = require('../args').parse;

/**
 * Usage information and docs
 */

exports.summary = 'Removes a package from the package directory';

exports.usage = '' +
'jam remove PACKAGE [MORE...]\n' +
'\n' +
'Parameters:\n' +
'  PACKAGE    The package to remove\n' +
'\n' +
'Options:\n' +
'  -d, --package-dir  Package directory (defaults to "./jam")';

/* TODO
'  --clean        Runs clean command after removing the package, to remove\n' +
'                 any unused dependencies';
*/

/**
 * Run function called when "jam remove" command is used
 *
 * @param {Object} settings - the values from .jamrc files
 * @param {Array} args - command-line arguments
 */

exports.run = function (settings, args) {
    var a = argParse(args, {
        'target_dir': {match: ['-d', '--package-dir'], value: true}
    });

    if (a.positional.length < 1) {
        console.log(exports.usage);
        logger.clean_exit = true;
        return;
    }

    var opt = a.options;
    var cwd = process.cwd();

    install.initDir(settings, cwd, opt, function (err, opt, cfg, proj_dir) {
        if (err) {
            return logger.error(err);
        }

        if (!opt.target_dir) {
            if (cfg.jam && cfg.jam.packageDir) {
                opt.target_dir = path.resolve(proj_dir, cfg.jam.packageDir);
            }
            else {
                opt.target_dir = path.resolve(proj_dir, settings.package_dir);
            }
        }
        if (!opt.baseurl) {
            if (cfg.jam && cfg.jam.baseUrl) {
                opt.baseurl = path.resolve(proj_dir, cfg.jam.baseUrl);
            }
            else {
                opt.baseurl = path.resolve(proj_dir, settings.baseUrl);
            }
        }

        var names = a.positional;
        exports.checkDependants(settings, cfg, opt, names, function (err) {
            if (err) {
                return logger.error(err);
            }
            async.series([
                async.apply(
                    async.forEach, names, async.apply(exports.remove, cfg, opt)
                ),
                async.apply(exports.buildLocalTree, settings, cfg, opt),
                async.apply(
                    project.updateRequireConfig, opt.target_dir, opt.baseurl
                )
            ],
            function (err) {
                if (err) {
                    return logger.error(err);
                }
                logger.end();
            });
        });
    });
};

exports.checkDependants = function (settings, cfg, opt, names, callback) {
    exports.buildLocalTree(settings, cfg, opt, function (err, packages) {
        if (err) {
            return callback(err);
        }
        var has_dependants = false;
        for (var i = 0; i < names.length; i++) {
            var name = names[i];
            var pkg = packages[name];
            if (pkg) {
                var ranges = packages[name].ranges;
                var dependants = Object.keys(ranges).filter(function (d) {
                    return d !== '_root' && names.indexOf(d) === -1;
                });
                if (dependants.length) {
                    for (var j = 0; j < dependants.length; j++) {
                        var d = dependants[j];
                        logger.error(
                            d + ' depends on ' + name + ' ' + ranges[d]
                        );
                    };
                    has_dependants = true;
                }
            }
        };
        if (has_dependants) {
            return callback('Cannot remove package with dependants');
        }
        return callback();
    });
};

exports.remove = function (cfg, opt, name, callback) {
    logger.info('removing', name);
    delete cfg.dependencies[name];
    rimraf(path.resolve(opt.target_dir, name), callback);
};

exports.buildLocalTree = function (settings, cfg, opt, callback) {
    var local_sources = [
        install.dirSource(opt.target_dir),
        install.repoSource(settings.repositories, cfg)
    ];
    var newcfg = utils.convertToRootCfg(cfg);
    var pkg = {
        config: newcfg,
        source: 'root'
    };
    logger.info('Building local version tree...');
    tree.build(pkg, local_sources, callback);
};
<|endoftext|>


<commit_before>'use babel';

import resolver from '../utils/tree-path-resolver';
import path from 'safe-win-path';
import rootPath from '../utils/root-path-finder';
import n from '../utils/notifications';
import fs from 'fs-plus';
import View from '../views/modal-text';
import swPath from '../utils/statwolf-path';

const open = function(statwolfPath) {

  statwolfPath = statwolfPath.split('.');
  statwolfPath.push(statwolfPath[statwolfPath.length -1]);
  statwolfPath = statwolfPath.join(path.sep);
  statwolfPath = path.join(rootPath(), statwolfPath);

  var exists = ['.js', '.json', '.r', '.py', '.csx'].some(function(suffix) {
    if(!fs.isFileSync(statwolfPath + suffix)) return false;

    statwolfPath = statwolfPath + suffix;
    return true;
  });

  if(!exists) {
    n.error('Statwolf path', 'Wrong path provided.');
    return;
  }

  atom.workspace.open(statwolfPath);

};

export default function(d) {

  const onPath = atom.commands.add('atom-workspace', {
    'statwolf:copyPath': function(event) {
      const relativePath = resolver(event.target, true);

      if(relativePath === null) {
        n.error('Statwolf path', 'Not a Statwolf module', true);
        return;
      }

      atom.clipboard.write(relativePath.replace(new RegExp('\\' + path.sep, 'g'), '.'));
      n.info('Statwolf path', 'Path copied into clipboard');
    },
    'statwolf:openPath': function(event) {
      const view = new View('Insert a Statwolf path');
      const panel = atom.workspace.addModalPanel({ item: view });

      view.on('exit', function() {
        panel.destroy();
      });

      view.on('confirm', function(statwolfPath) {
        view.emit('exit');

        open(statwolfPath);
      });
    }
  });
  d.add(onPath);

  const clickHandler = atom.workspace.observeTextEditors(function(editor) {
    const view = editor.element;

    view.addEventListener('dblclick', function(event) {

      if(!event.ctrlKey) {
        return;
      }

      const row = editor.getCursorBufferPosition().row;
      const text = editor.getTextInRange([ [ row, 0 ], [ row, Infinity ] ]).match(/Statwolf\.([a-zA-Z0-9\_\-]+\.?)*/);

      if(!text) {
        return;
      }

      open(text[0]);
    });

  });
  d.add(clickHandler);

  const componentHandler = atom.workspace.observeTextEditors(function(editor) {
    let filePath = editor.getPath();

    if(!filePath) {
      return;
    }

    filePath = path.sanitize(filePath);

    if(!filePath.startsWith(rootPath())) {
      return;
    }

    const view = editor.element;
    let customPath;

    view.addEventListener('keydown', function(event) {

      if(!event.ctrlKey || !event.altKey) {
        return;
      }

      switch(event.code) {
        case 'Digit8':
          customPath = swPath.resolvePath(filePath).concat([ 'js' ]).join('.');
          break;
        case 'Digit9':
          customPath = swPath.resolvePath(filePath).concat([ 'test', 'js' ]).join('.');
          break;
        case 'Digit0':
          customPath = swPath.resolvePath(filePath).concat([ 'deps', 'json' ]).join('.');
          break;
        default:
          return;
      }

      if(!fs.existsSync(customPath)) {
        return;
      }

      atom.workspace.open(customPath);
    });

  });
  d.add(componentHandler);

  console.log('Statwolf paths ready.');
};
<commit_msg>fixed bug ATOM-16<commit_after>'use babel';

import resolver from '../utils/tree-path-resolver';
import path from 'safe-win-path';
import rootPath from '../utils/root-path-finder';
import n from '../utils/notifications';
import fs from 'fs-plus';
import View from '../views/modal-text';
import swPath from '../utils/statwolf-path';

const open = function(statwolfPath) {

  statwolfPath = statwolfPath.split('.');
  statwolfPath.push(statwolfPath[statwolfPath.length -1]);
  statwolfPath = statwolfPath.join(path.sep);
  statwolfPath = path.join(rootPath(), statwolfPath);

  var exists = ['.js', '.json', '.r', '.py', '.csx'].some(function(suffix) {
    if(!fs.isFileSync(statwolfPath + suffix)) return false;

    statwolfPath = statwolfPath + suffix;
    return true;
  });

  if(!exists) {
    n.error('Statwolf path', 'Wrong path provided.');
    return;
  }

  atom.workspace.open(statwolfPath);

};

export default function(d) {

  const onPath = atom.commands.add('atom-workspace', {
    'statwolf:copyPath': function(event) {
      const relativePath = resolver(event.target, true);

      if(relativePath === null) {
        n.error('Statwolf path', 'Not a Statwolf module', true);
        return;
      }

      atom.clipboard.write(relativePath.replace(new RegExp('\\' + path.sep, 'g'), '.'));
      n.info('Statwolf path', 'Path copied into clipboard');
    },
    'statwolf:openPath': function(event) {
      const view = new View('Insert a Statwolf path');
      const panel = atom.workspace.addModalPanel({ item: view });

      view.on('exit', function() {
        panel.destroy();
      });

      view.on('confirm', function(statwolfPath) {
        view.emit('exit');

        open(statwolfPath);
      });
    }
  });
  d.add(onPath);

  const clickHandler = atom.workspace.observeTextEditors(function(editor) {
    const view = editor.element;

    view.addEventListener('dblclick', function(event) {

      if(!event.ctrlKey) {
        return;
      }

      const cursor = editor.getCursorBufferPosition();
      const row = editor.getTextInRange([ [ cursor.row, 0 ], [ cursor.row, Infinity ] ]);
      const text = row.match(/Statwolf\.([a-zA-Z0-9\_\-]+\.?)*/g);

      if(!text) {
        return;
      }

      let distance = Infinity;
      let currentPath;
      text.forEach(function(match) {
        const d = cursor.column - row.indexOf(match);
        if(d < 0 || d >= distance) {
          return;
        }

        distance = d;
        currentPath = match;
      });

      console.log(`Opening ${ currentPath }`);
      open(currentPath);
    });

  });
  d.add(clickHandler);

  const componentHandler = atom.workspace.observeTextEditors(function(editor) {
    let filePath = editor.getPath();

    if(!filePath) {
      return;
    }

    filePath = path.sanitize(filePath);

    if(!filePath.startsWith(rootPath())) {
      return;
    }

    const view = editor.element;
    let customPath;

    view.addEventListener('keydown', function(event) {

      if(!event.ctrlKey || !event.altKey) {
        return;
      }

      switch(event.code) {
        case 'Digit8':
          customPath = swPath.resolvePath(filePath).concat([ 'js' ]).join('.');
          break;
        case 'Digit9':
          customPath = swPath.resolvePath(filePath).concat([ 'test', 'js' ]).join('.');
          break;
        case 'Digit0':
          customPath = swPath.resolvePath(filePath).concat([ 'deps', 'json' ]).join('.');
          break;
        default:
          return;
      }

      if(!fs.existsSync(customPath)) {
        return;
      }

      atom.workspace.open(customPath);
    });

  });
  d.add(componentHandler);

  console.log('Statwolf paths ready.');
};
<|endoftext|>


<commit_before>NewController = BaseController.extend({
  template: 'new_post',
  data: function() {
    return {

      categoryList: function() {
        return Categories.find({}, {sort: {name: 1}});
      },

      feelingList: function() {
        return Feelings.find({},{sort: {enum: 1}})
      },

      userPicture: function(){
          return UsersXP.findOne({user_id: Meteor.userId()}).picture;
      }
    }
  }
});

if(Meteor.isClient) {
  Template.new_post.onRendered(function () {
      $(document).on("click", "#feelJoy", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-0').data('enum', enumD);
      });
      $(document).on("click", "#feelTrust", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-7').data('enum', enumD);
      });
      $(document).on("click", "#feelFear", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-6').data('enum', enumD);
      });
      $(document).on("click", "#feelSurprise", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-5').data('enum', enumD);
      });
      $(document).on("click", "#feelSadness", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-4').data('enum', enumD);
      });
      $(document).on("click", "#feelDisgust", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-3').data('enum', enumD);
      });
      $(document).on("click", "#feelAnger", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-2').data('enum', enumD);
      });
      $(document).on("click", "#feelAnticipation", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-1').data('enum', enumD);
      });
      $(document).on("submit", "#exp_form", function(e) {
        var title = $('#exp_title').val();
        var description =  $('#exp_description').val();
        var category = $('#exp_category').val();
        var isAnnon = $('#exp_annon').is(":checked");
        var feel = $('#exp_form').data('enum');
        if(!!title || !!description || !!category || !!feel) {
          var currentUser = Meteor.user();

          Experiences.insert({
            Title: title,
            Description: description,
            CategoryId: category,
            Feeling: feel,
            Rating: {
    		      TotalPoints: 0,
    	        UserRates: [
                {UserId: currentUser._id, Rate: 0, RatedOn: new Date()}
              ]
            },
      			UserId: currentUser._id,
            asAnnonymous: isAnnon,
      	    Keywords: [],
            CreatedOn: new Date()
          });

          //the total amount of experiences
          var addedExperiences = Experiences.find({},{_id:1}).count();

          //get matched badges with the total of posts
          Badges.find({ reach: {post: addedExperiences } })
            .forEach(function(badge){
                var userXP = UsersXP.findOne({ user_id: Meteor.userId() }),
                    badges = userXP.badges;
                badges.push(badge);

                UsersXP.update({_id:userXP._id}, {
                    $set: {
                        badges:badges,

                        total_badges: (userXP.total_badges + 1 )
                    }
                });
          });

        }
      });
  });
}
<commit_msg>Fix for new experience page.<commit_after>NewController = BaseController.extend({
  template: 'new_post',
  data: function() {
    return {

      categoryList: function() {
        return Categories.find({}, {sort: {name: 1}});
      },

      feelingList: function() {
        return Feelings.find({},{sort: {enum: 1}})
      },

      userPicture: function(){
          var currentUser = UsersXP.findOne({user_id: Meteor.userId()});
          return currentUser ? currentUser.picture : "";
      }
    }
  }
});

if(Meteor.isClient) {
  Template.new_post.onRendered(function () {
      $(document).on("click", "#feelJoy", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-0').data('enum', enumD);
      });
      $(document).on("click", "#feelTrust", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-7').data('enum', enumD);
      });
      $(document).on("click", "#feelFear", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-6').data('enum', enumD);
      });
      $(document).on("click", "#feelSurprise", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-5').data('enum', enumD);
      });
      $(document).on("click", "#feelSadness", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-4').data('enum', enumD);
      });
      $(document).on("click", "#feelDisgust", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-3').data('enum', enumD);
      });
      $(document).on("click", "#feelAnger", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-2').data('enum', enumD);
      });
      $(document).on("click", "#feelAnticipation", function(e) {
        var enumD = $(e.currentTarget).data('enum');
        $('#exp_form').removeClass().addClass('new-post-container feeling-id-1').data('enum', enumD);
      });
      $(document).on("submit", "#exp_form", function(e) {
        var title = $('#exp_title').val();
        var description =  $('#exp_description').val();
        var category = $('#exp_category').val();
        var isAnnon = $('#exp_annon').is(":checked");
        var feel = $('#exp_form').data('enum');
        if(!!title || !!description || !!category || !!feel) {
          var currentUser = Meteor.user();

          Experiences.insert({
            Title: title,
            Description: description,
            CategoryId: category,
            Feeling: feel,
            Rating: {
    		      TotalPoints: 0,
    	        UserRates: [
                {UserId: currentUser._id, Rate: 0, RatedOn: new Date()}
              ]
            },
      			UserId: currentUser._id,
            asAnnonymous: isAnnon,
      	    Keywords: [],
            CreatedOn: new Date()
          });

          //the total amount of experiences
          var addedExperiences = Experiences.find({},{_id:1}).count();

          //get matched badges with the total of posts
          Badges.find({ reach: {post: addedExperiences } })
            .forEach(function(badge){
                var userXP = UsersXP.findOne({ user_id: Meteor.userId() }),
                    badges = userXP.badges;
                badges.push(badge);

                UsersXP.update({_id:userXP._id}, {
                    $set: {
                        badges:badges,

                        total_badges: (userXP.total_badges + 1 )
                    }
                });
          });

        }
      });
  });
}
<|endoftext|>


<commit_before>var fs      = require('fs');
var ini     = require('ini');
var p       = require('path');
var svnInfo = require('svn-info');

/**
 * Configuration generator for local repositories.
 *
 * @param {String} dir directory where the local repositories are located
 * @class
 */
function Local(dir) {
  this.dir = dir;
}

/**
 * Generate Repoman configuration from local repositories.
 * Only supports vanilla git clone (using git config),
 * and subversion checkouts (using svn info).
 *
 * @param {Function} cb standard cb(err, result) callback
 */
Local.prototype.generate = function (cb) {

  var self   = this;
  var config = {};
  var repos  = fs.readdirSync(this.dir);

  repos.forEach(function (repo) {

    var gitConfig  = p.join(repo, '.git', 'config');
    var svnEntries = p.join(repo, '.svn', 'entries');

    if (fs.existsSync(gitConfig)) {
      self._git(gitConfig, repo, config);

    } else if (fs.existsSync(svnEntries)) {
      self._svn(svnEntries, repo, config);
    }

  });

  cb(null, config);
};

Local.prototype._git = function (gitConfig, repo, config) {

  var info = ini.parse(fs.readFileSync(gitConfig, 'utf-8'));
  var url  = info['remote "origin"'].url;

  config[repo] = { type: 'git', url: url };
};

Local.prototype._svn = function (svnEntries, repo, config) {

  var info = svnInfo.sync(repo);
  var url  = info.repositoryRoot;

  config[repo] = { type: 'svn', url: url };
};

module.exports = Local;
<commit_msg>Fix #30: repoman config --local crashes with TypeError<commit_after>var fs      = require('fs');
var ini     = require('ini');
var p       = require('path');
var svnInfo = require('svn-info');

/**
 * Configuration generator for local repositories.
 *
 * @param {String} dir directory where the local repositories are located
 * @class
 */
function Local(dir) {
  this.dir = dir;
}

/**
 * Generate Repoman configuration from local repositories.
 * Only supports vanilla git clone (using git config),
 * and subversion checkouts (using svn info).
 *
 * @param {Function} cb standard cb(err, result) callback
 */
Local.prototype.generate = function (cb) {

  var self   = this;
  var config = {};
  var repos  = fs.readdirSync(this.dir);

  repos.forEach(function (repo) {

    var gitConfig  = p.join(repo, '.git', 'config');
    var svnEntries = p.join(repo, '.svn', 'entries');

    if (fs.existsSync(gitConfig)) {
      self._git(gitConfig, repo, config);

    } else if (fs.existsSync(svnEntries)) {
      self._svn(svnEntries, repo, config);
    }

  });

  cb(null, config);
};

Local.prototype._git = function (gitConfig, repo, config) {

  var info = ini.parse(fs.readFileSync(gitConfig, 'utf-8'));

  if (info['remote "origin"'])
    config[repo] = { type: 'git', url: info['remote "origin"'].url };
};

Local.prototype._svn = function (svnEntries, repo, config) {

  var info = svnInfo.sync(repo);
  var url  = info.repositoryRoot;

  config[repo] = { type: 'svn', url: url };
};

module.exports = Local;
<|endoftext|>