<commit_before>/**
 * ZURB FOUNDATION 5 MULTISELECT PLUGIN
 *
 * @author Andrea Mariani
 * @mail me@andreamariani.net
 * @twitter @andreamariani2k
 * @web http://www.andreamariani.net
 *
 * ** THIS PLUGIN IS IN DEVELOPMENT ** *
 */

(function($) {

        //toggle for click on zselect, close for click elsewhere, nothing for click on .zselect *
        $(document).mouseup(function (e){
            var container = $(".zselect ul");
            if ( container.parent().is(e.target) || ( container.is(':visible') && !container.parent().is(e.target) ) && ( container.has(e.target).length === 0 )  ) {
                container.toggle();
                //console.log(e.target);
            }
        });

        //escape key for close all zselect
        $(window).on('keydown', function(e){
            e = e || window.event;
            if (e.keyCode === 27) {
                $("li.zmsfilter input").val('').keyup(); //clean filter
                $(".zselect ul").hide();
            }
        });

        //click on label toggle input
        $(document).on('click', '.zselect li', function(e){
            if($(e.target).prop("tagName") !== "INPUT"){
                    $("input:checkbox[disabled!='disabled']",this).prop('checked', function( i, val ) { return !val; }).trigger('change');
            }

        });

        //select all and deselect all
        $(document).on('click','.selectall,.deselectall', function(){
           var state = ($(this).hasClass('selectall'))?true:false;
           $(this).parent().find("input:checkbox[disabled!='disabled']:visible").prop('checked', state).change();
        });

        //optgroup
        $(document).on('click','.optgroup', function(){
           $(this).parent().find(".optgroup_"+$(this).attr('data-optgroup')+" li input:checkbox[disabled!='disabled']").prop('checked', function( i, val ) { return !val; }).change();
        });

        //when resize window + init
        function onResize(reflow){
            $.each( $(".zselect"), function(k,v){
                //if( $(v).find("ul").attr('style') !== undefined && reflow !== true ) return false; //break if already set

                var w = $(v).outerWidth();

                $(v).find("ul").attr('style', 'width:'+w+'px!important;' );

                //var size = Math.max(Math.min(w / (1), parseFloat(20)), parseFloat(11));
                //console.log(size);
                //$(v).find('ul li').css('font-size', size);

                var w_li = $(v).find('ul li:eq(0)').width();
                //console.log(w_li);

            });

        }

        $( window ).resize(function() {
            onResize();
        });

        function refreshPlaceholder(rel, placeholder, selectedText) {
             selectedText = selectedText || "Selected %1 item%s1 of %2 item%s2";
             var checked=$("div#"+rel+" ul li input:checked").length;
             var tot=$("div#"+rel+" ul li input:checkbox").length;

             if(checked>0) {
                 var checkedS = checked > 1 ? "s" : "";
                 var totS = tot > 1 ? "s" : "";
                 var txt = selectedText.replace(/%1/g, checked)
                                       .replace(/%2/g, tot)
                                       .replace(/%s1/g, checkedS)
                                       .replace(/%s2/g, totS);
                 $(".zselect#"+rel+" span.zmshead").text(txt);
             } else {
                 $(".zselect#"+rel+" span.zmshead").html( (placeholder===undefined) ? ' ' : placeholder );
             }
        }

var methods = {
    init : function(options) {

        var id,checked,disabled="",disabledClass="";
        var optgroup=[];
        var optgroup_size,optgroup_id = 0;
        var optgroup_name = false;
        var optgroup_members = 0;

        $.each( $(this),function(k,v){

            id=Math.random().toString(36).substr(2, 9);
            $(v).hide().attr('rel',id);
            $(v).parent().append("

");

            if(options.selectAll!==false){
                var sAllText="Select All";
                var desAllText="Deselect All";
                if(options.selectAllText!==undefined){
                    sAllText=options.selectAllText[0];
                    desAllText=options.selectAllText[1];
                }

                $('#'+id+' ul').append("
"+sAllText+"
");
                $('#'+id+' ul').append("
"+desAllText+"
");
            }

            $.each(v, function(j,z){

                var appendTo;
                if( $(z).parent().attr("label") !== undefined && optgroup.indexOf($(z).parent().attr("label"))===-1 ){
                    optgroup_size = $(z).parent().find('option').size();
                    optgroup_members += optgroup_size;
                    optgroup_name = $(z).parent().attr("label");

                    $('#'+id+' ul').append("
"+$(z).parent().attr("label")+"
");
                    $('#'+id+' ul').append($("
").addClass('optgroup_'+optgroup_id));
                    optgroup.push($(z).parent().attr("label"));
                }
                //console.log( $(z).attr('value') + " " + $(z).text() + " " + $(z).is('[data-selected]') + " " + $(z).is(':selected'));
                //console.log(id);
                //console.log( '#'+id+' ul' );
                checked = ( $(z).is('[data-selected]') || $(z).is(':selected')) ? "checked='checked'" : "";
                dataZ = ( $(z).data("z") !== undefined ) ? 'data-z="' + $(z).data("z") + '"' : "";

                if( $(z).is('[data-disabled]') ){
                    disabled = "disabled='disabled'";
                    disabledClass = "class='disabled'";
                }
                else{
                    disabled = disabledClass = "";
                }

                if( optgroup_name === false ) appendTo = '#'+id+' ul';
                else                          appendTo = '#'+id+' ul div.optgroup_'+optgroup_id;

                $(appendTo).append("
<input value='"+$(z).val()+"' type='checkbox' "+checked+" "+disabled+" "+dataZ+" /> "+$(z).text()+"
");

                if(optgroup_members === j+1) {
                    optgroup_size = 0;
                    optgroup_id ++;
                    optgroup_name = false;
                }

            });
            $('#'+id+' span.zmshead').html( (options.placeholder===undefined) ? ' ' : options.placeholder );
        });

        if(options.filter === true){
            //defaults
            if (options.filterResult === undefined) options.filterResult = true;
            if (options.filterResultText === undefined) options.filterResultText = 'showed';
            var fplaholder = (options.filterPlaceholder !== undefined) ? options.filterPlaceholder : "Filter...";

            var rel = this.attr('rel');
            $("div#"+rel+" ul").prepend('
<input type="text" placeholder="'+fplaholder+'" />
');

            if(options.filterResult === true)
                $("div#"+rel+" ul").append('

');

            $("div#"+rel+" ul li.zmsfilter input").keyup(function(){
                    var value=$(this).val().toLowerCase();
                    var show=0,tot=$("div#"+rel+" ul li input:checkbox").length;
                    $("div#"+rel+" ul li input:checkbox").filter( function(i,v) {
                          //console.log($(v).val());
                          //console.log($(v).parent().text());
                          if( $(v).val().toLowerCase().indexOf(value) === -1 && $(v).parent().text().toLowerCase().indexOf(value) === -1 ){//and text() check...
                               $(v).parent().hide();

                          }
                          else {
                               $(v).parent().show();
                               show++;
                          }

                    });

                    if(options.filterResult === true)
                        $("div#"+rel+" ul li.filterResult").text(options.filterResultText + ' '+show+'/'+tot);

                });
        }//end filter

        if(options.live !== undefined){
            var rel = this.attr('rel');
            $(".zselect#"+rel).on('change','input:checkbox',function(e){
                $(options.live).val( methods.getValue($("select[rel='"+rel+"']")) );
            });
        }//end live

        if(options.get !== undefined){
            var query = window.location.search.substring(1);
            var vars = query.split("&");
            var need = false;
            for (var i=0;i<vars.length;i++) {
                var pair = vars[i].split("=");
                if (pair[0] == options.get) {

                  need = pair[1].replace(',','%2C').split('%2C');

                }
            }

            if(need){
                var rel = this.attr('rel');
                for(var i=0; i<need.length; i++){
                    //console.log(need[i]);
                    $(".zselect#"+rel+" ul li input:checkbox[value='"+need[i]+"']").trigger('click');

                }
                refreshPlaceholder(rel,options.placeholder,options.selectedText);
            }
        }

        // Updates original select after checkbox update
        $(".zselect").on('change', 'input:checkbox', function() {
            var container = $(this).closest('.zselect');
            var rel = container.attr('id');
            refreshPlaceholder(rel, options.placeholder, options.selectedText);

            var select = $('select[rel='+rel+']');
            $.each(container.find('input:checkbox'), function(k, v) {
                if($(v).val() !== undefined){
                    if($(v).prop('checked')) {
                        select.find("option[value='"+$(v).val()+"']").prop("selected", true);
                    } else {
                        select.find("option[value='"+$(v).val()+"']").prop("selected", false);
                    }
                }
            });
            select.trigger('change');
        });

        onResize();

    },

    getValue : function(selector) {
       if(selector===undefined) selector = this;
       var value = new Array();
       var rel   = $(selector).attr('rel');
       $.each( $("div#"+rel+" ul li input"), function(k,v){
          if( $(v).val() !== undefined ){
               if( $(v).prop('checked') )
               value.push($(v).val());
          }
       });
       return value;
    },

    open : function( ) {
        $("div#"+$(this).attr('rel')+" ul").show();
    },
    close : function( ) {
        $("div#"+$(this).attr('rel')+" ul").hide();
    },

    disable : function (val,state){ //console.log(state);
        if(val!==undefined){
            if(state) $("div#"+$(this).attr('rel')+" ul li input:checkbox[value='"+val+"']").attr('disabled','disabled');
            else      $("div#"+$(this).attr('rel')+" ul li input:checkbox[value='"+val+"']").removeAttr('disabled');
        }
        else{
            if(state) $("div#"+$(this).attr('rel')+" ul li input:checkbox").attr('disabled','disabled');
            else      $("div#"+$(this).attr('rel')+" ul li input:checkbox").removeAttr('disabled');
        }
    },
    set : function (val,checked){
        $("div#"+$(this).attr('rel')+" ul li input:checkbox[value='"+val+"']").prop('checked', checked).change();
    },
    uncheckall_inpage : function( ) {
        $(".zselect ul li input:checkbox").prop('checked', false).change();
    },
    checkall_inpage : function( ) {
        $(".zselect ul li input:checkbox").prop('checked', true).change();
    },
    checkall : function( ) {
        $("div#"+$(this).attr('rel')+" ul li input:checkbox").prop('checked', true).change();
    },
    uncheckall : function( ) {
        $("div#"+$(this).attr('rel')+" ul li input:checkbox").prop('checked', false).change();
    },
    destroy : function (val){
        $("div#"+$(this).attr('rel')+" ul li input:checkbox[value='"+val+"']").parent().remove();
    },
    reflow : function(){
        onResize(true);
    },

    add : function(option, pos){
        var position = pos || 'append';
        var checked='', disabled='', disabledClass='';

        if(option.checked)  checked=' checked="checked" ';
        if(option.disabled) {disabled=' disabled="disabled" '; disabledClass=' class="disabled" ';}

        if(position === 'append') $("div#"+$(this).attr('rel')+" ul").append("
<input value='"+option.value+"' type='checkbox' "+checked+" "+disabled+" /> "+option.text+"
");
        else {
            if(position === 'prepend'){
               $("
<input value='"+option.value+"' type='checkbox' "+checked+" "+disabled+" /> "+option.text+"
").insertAfter($("div#"+$(this).attr('rel')+" ul li.deselectall"));
            }
            else{
               $("
<input value='"+option.value+"' type='checkbox' "+checked+" "+disabled+" /> "+option.text+"
").insertAfter($("div#"+$(this).attr('rel')+" ul li input[value='"+position.substring(1)+"']").closest('li'));
            }
        }

    }

    //,update : function( content ) {  }
    };

$.fn.zmultiselect = function(methodOrOptions) {
    if ( methods[methodOrOptions] ) {
        return methods[ methodOrOptions ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof methodOrOptions === 'object' || ! methodOrOptions ) {
        return methods.init.apply( this, arguments );
    } else {
        $.error( 'Method ' +  methodOrOptions + ' does not exist on zmultiselect' );
    }
    };

})( jQuery );
<commit_msg>Update zurb5-multiselect.js<commit_after>/**
 * ZURB FOUNDATION 5 MULTISELECT PLUGIN
 *
 * @author Andrea Mariani
 * @mail me@andreamariani.net
 * @twitter @andreamariani2k
 * @web http://www.andreamariani.net
 *
 * ** THIS PLUGIN IS IN DEVELOPMENT ** *
 */

(function($) {

            //toggle for click on zselect, close for click elsewhere, nothing for click on .zselect *
        $(document).mouseup(function (e){
                    var container = $(".zselect ul");
            if ( container.parent().is(e.target) || ( container.is(':visible') && !container.parent().is(e.target) ) && ( container.has(e.target).length === 0 )  ) {
                container.toggle();
                //console.log(e.target);
            }
        });

        //escape key for close all zselect
        $(window).on('keydown', function(e){
            e = e || window.event;
            if (e.keyCode === 27) {
                $("li.zmsfilter input").val('').keyup(); //clean filter
                $(".zselect ul").hide();
            }
        });

        //click on label toggle input
        $(document).on('click', '.zselect li', function(e){
            if($(e.target).prop("tagName") !== "INPUT"){
                    $("input:checkbox[disabled!='disabled']",this).prop('checked', function( i, val ) { return !val; }).trigger('change');
            }

        });

        //select all and deselect all
        $(document).on('click','.selectall,.deselectall', function(){
           var state = ($(this).hasClass('selectall'))?true:false;
           $(this).parent().find("input:checkbox[disabled!='disabled']:visible").prop('checked', state).change();
        });

        //optgroup
        $(document).on('click','.optgroup', function(){
           $(this).parent().find(".optgroup_"+$(this).attr('data-optgroup')+" li input:checkbox[disabled!='disabled']").prop('checked', function( i, val ) { return !val; }).change();
        });

        //when resize window + init
        function onResize(reflow){
            $.each( $(".zselect"), function(k,v){
                //if( $(v).find("ul").attr('style') !== undefined && reflow !== true ) return false; //break if already set

                var w = $(v).outerWidth();

                $(v).find("ul").attr('style', 'width:'+w+'px!important;' );

                //var size = Math.max(Math.min(w / (1), parseFloat(20)), parseFloat(11));
                //console.log(size);
                //$(v).find('ul li').css('font-size', size);

                var w_li = $(v).find('ul li:eq(0)').width();
                //console.log(w_li);

            });

        }

        $( window ).resize(function() {
            onResize();
        });

        function refreshPlaceholder(rel, placeholder, selectedText) {
             selectedText = selectedText || "Selected %1 item%s1 of %2 item%s2";
             var checked=$("div#"+rel+" ul li input:checked").length;
             var tot=$("div#"+rel+" ul li input:checkbox").length;

             if(checked>0) {
                 var checkedS = checked > 1 ? "s" : "";
                 var totS = tot > 1 ? "s" : "";
                 var txt = selectedText.replace(/%1/g, checked)
                                       .replace(/%2/g, tot)
                                       .replace(/%s1/g, checkedS)
                                       .replace(/%s2/g, totS);
                 $(".zselect#"+rel+" span.zmshead").text(txt);
             } else {
                 $(".zselect#"+rel+" span.zmshead").html( (placeholder===undefined) ? ' ' : placeholder );
             }
        }

var methods = {
    init : function(options) {

        var id,checked,disabled="",disabledClass="";
        var optgroup=[];
        var optgroup_size,optgroup_id = 0;
        var optgroup_name = false;
        var optgroup_members = 0;

        $.each( $(this),function(k,v){

            id=Math.random().toString(36).substr(2, 9);
            $(v).hide().attr('rel',id);
            $(v).parent().append("

");

            if(options.selectAll!==false){
                var sAllText="Select All";
                var desAllText="Deselect All";
                if(options.selectAllText!==undefined){
                    sAllText=options.selectAllText[0];
                    desAllText=options.selectAllText[1];
                }

                $('#'+id+' ul').append("
"+sAllText+"
");
                $('#'+id+' ul').append("
"+desAllText+"
");
            }

            $.each(v, function(j,z){

                var appendTo;
                if( $(z).parent().attr("label") !== undefined && optgroup.indexOf($(z).parent().attr("label"))===-1 ){
                    optgroup_size = $(z).parent().find('option').size();
                    optgroup_members += optgroup_size;
                    optgroup_name = $(z).parent().attr("label");

                    $('#'+id+' ul').append("
"+$(z).parent().attr("label")+"
");
                    $('#'+id+' ul').append($("
").addClass('optgroup_'+optgroup_id));
                    optgroup.push($(z).parent().attr("label"));
                }
                //console.log( $(z).attr('value') + " " + $(z).text() + " " + $(z).is('[data-selected]') + " " + $(z).is(':selected'));
                //console.log(id);
                //console.log( '#'+id+' ul' );
                checked = ( $(z).is('[data-selected]') || $(z).is(':selected')) ? "checked='checked'" : "";
                dataZ = ( $(z).data("z") !== undefined ) ? 'data-z="' + $(z).data("z") + '"' : "";

                if( $(z).is('[data-disabled]') ){
                    disabled = "disabled='disabled'";
                    disabledClass = "class='disabled'";
                }
                else{
                    disabled = disabledClass = "";
                }

                if( optgroup_name === false ) appendTo = '#'+id+' ul';
                else                          appendTo = '#'+id+' ul div.optgroup_'+optgroup_id;

                $(appendTo).append("
<input value='"+$(z).val()+"' type='checkbox' "+checked+" "+disabled+" "+dataZ+" /> "+$(z).text()+"
");

                if(optgroup_members === j+1) {
                    optgroup_size = 0;
                    optgroup_id ++;
                    optgroup_name = false;
                }

            });
            $('#'+id+' span.zmshead').html( (options.placeholder===undefined) ? ' ' : options.placeholder );
        });

        if(options.filter === true){
            //defaults
            if (options.filterResult === undefined) options.filterResult = true;
            if (options.filterResultText === undefined) options.filterResultText = 'showed';
            var fplaholder = (options.filterPlaceholder !== undefined) ? options.filterPlaceholder : "Filter...";

            var rel = this.attr('rel');
            $("div#"+rel+" ul").prepend('
<input type="text" placeholder="'+fplaholder+'" />
');

            if(options.filterResult === true)
                $("div#"+rel+" ul").append('

');

            $("div#"+rel+" ul li.zmsfilter input").keyup(function(){
                    var value=$(this).val().toLowerCase();
                    var show=0,tot=$("div#"+rel+" ul li input:checkbox").length;
                    $("div#"+rel+" ul li input:checkbox").filter( function(i,v) {
                          //console.log($(v).val());
                          //console.log($(v).parent().text());
                          if( $(v).val().toLowerCase().indexOf(value) === -1 && $(v).parent().text().toLowerCase().indexOf(value) === -1 ){//and text() check...
                               $(v).parent().hide();

                          }
                          else {
                               $(v).parent().show();
                               show++;
                          }

                    });

                    if(options.filterResult === true)
                        $("div#"+rel+" ul li.filterResult").text(options.filterResultText + ' '+show+'/'+tot);

                });
        }//end filter

        if(options.live !== undefined){
            var rel = this.attr('rel');
            $(".zselect#"+rel).on('change','input:checkbox',function(e){
                $(options.live).val( methods.getValue($("select[rel='"+rel+"']")) );
            });
        }//end live

        if(options.get !== undefined){
            var query = window.location.search.substring(1);
            var vars = query.split("&");
            var need = false;
            for (var i=0;i<vars.length;i++) {
                var pair = vars[i].split("=");
                if (pair[0] == options.get) {

                  need = pair[1].replace(',','%2C').split('%2C');

                }
            }

            if(need){
                var rel = this.attr('rel');
                for(var i=0; i<need.length; i++){
                    //console.log(need[i]);
                    $(".zselect#"+rel+" ul li input:checkbox[value='"+need[i]+"']").trigger('click');

                }
                refreshPlaceholder(rel,options.placeholder,options.selectedText);
            }
        }

        // Updates original select after checkbox update
        $(".zselect").on('change', 'input:checkbox', function() {
            var container = $(this).closest('.zselect');
            var rel = container.attr('id');
            refreshPlaceholder(rel, options.placeholder, options.selectedText);

            var select = $('select[rel='+rel+']');
            $.each(container.find('input:checkbox'), function(k, v) {
                if($(v).val() !== undefined){
                    if($(v).prop('checked')) {
                        select.find("option[value='"+$(v).val()+"']").prop("selected", true);
                    } else {
                        select.find("option[value='"+$(v).val()+"']").prop("selected", false);
                    }
                }
            });
            select.trigger('change');
        });

        onResize();

    },

    getValue : function(selector) {
       if(selector===undefined) selector = this;
       var value = new Array();
       var rel   = $(selector).attr('rel');
       $.each( $("div#"+rel+" ul li input"), function(k,v){
          if( $(v).val() !== undefined ){
               if( $(v).prop('checked') )
               value.push($(v).val());
          }
       });
       return value;
    },

    open : function( ) {
        $("div#"+$(this).attr('rel')+" ul").show();
    },
    close : function( ) {
        $("div#"+$(this).attr('rel')+" ul").hide();
    },

    disable : function (val,state){ //console.log(state);
        if(val!==undefined){
            if(state) $("div#"+$(this).attr('rel')+" ul li input:checkbox[value='"+val+"']").attr('disabled','disabled');
            else      $("div#"+$(this).attr('rel')+" ul li input:checkbox[value='"+val+"']").removeAttr('disabled');
        }
        else{
            if(state) $("div#"+$(this).attr('rel')+" ul li input:checkbox").attr('disabled','disabled');
            else      $("div#"+$(this).attr('rel')+" ul li input:checkbox").removeAttr('disabled');
        }
    },
    set : function (val,checked){
        $("div#"+$(this).attr('rel')+" ul li input:checkbox[value='"+val+"']").prop('checked', checked).change();
    },
    uncheckall_inpage : function( ) {
        $(".zselect ul li input:checkbox").prop('checked', false).change();
    },
    checkall_inpage : function( ) {
        $(".zselect ul li input:checkbox").prop('checked', true).change();
    },
    checkall : function( ) {
        $("div#"+$(this).attr('rel')+" ul li input:checkbox").prop('checked', true).change();
    },
    uncheckall : function( ) {
        $("div#"+$(this).attr('rel')+" ul li input:checkbox").prop('checked', false).change();
    },
    destroy : function (val){
        $("div#"+$(this).attr('rel')+" ul li input:checkbox[value='"+val+"']").parent().remove();
    },
    reflow : function(){
        onResize(true);
    },

    add : function(option, pos){
        var position = pos || 'append';
        var checked='', disabled='', disabledClass='';

        if(option.checked)  checked=' checked="checked" ';
        if(option.disabled) {disabled=' disabled="disabled" '; disabledClass=' class="disabled" ';}

        if(position === 'append') $("div#"+$(this).attr('rel')+" ul").append("
<input value='"+option.value+"' type='checkbox' "+checked+" "+disabled+" /> "+option.text+"
");
        else {
            if(position === 'prepend'){
               $("
<input value='"+option.value+"' type='checkbox' "+checked+" "+disabled+" /> "+option.text+"
").insertAfter($("div#"+$(this).attr('rel')+" ul li.deselectall"));
            }
            else{
               $("
<input value='"+option.value+"' type='checkbox' "+checked+" "+disabled+" /> "+option.text+"
").insertAfter($("div#"+$(this).attr('rel')+" ul li input[value='"+position.substring(1)+"']").closest('li'));
            }
        }

    }

    //,update : function( content ) {  }
    };

$.fn.zmultiselect = function(methodOrOptions) {
    if ( methods[methodOrOptions] ) {
        return methods[ methodOrOptions ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof methodOrOptions === 'object' || ! methodOrOptions ) {
        return methods.init.apply( this, arguments );
    } else {
        $.error( 'Method ' +  methodOrOptions + ' does not exist on zmultiselect' );
    }
    };

})( jQuery );
<|endoftext|>


<commit_before>/*
 * moleculer
 * Copyright (c) 2017 Ice Services (https://github.com/ice-services/moleculer)
 * MIT Licensed
 */

"use strict";

const http 				= require("http");
const queryString 		= require("querystring");

const _ 				= require("lodash");
const bp 				= require("body-parser");
const serveStatic 		= require("serve-static");
const nanomatch  		= require("nanomatch");

const { CustomError } 	= require("../src/errors");

/**
 * Official API Gateway service for Moleculer
 *
 * TODO:
 * -----
 * 	- create context
 *  - generate requestID & response back to backend
 *  - prereq action to check the params & responseType
 *  - auth service call
 *  -
 *
 *
 */
module.exports = {

	// Service name
	name: "api-gw",

	// Version
	version: "1.0",

	// Service settings
	settings: {

		// Exposed port
		port: process.env.PORT || 4000,

		// Exposed IP
		ip: process.env.IP || "0.0.0.0",

		// Exposed path prefix
		path: "/api",

		// Whitelist of actions (array of string mask or regex)
		whitelist: [
			"posts.*",
			"users.get",
			"$node.*",
			/^math\.\w+$/
		],

		// Action aliases
		aliases: {
			"POST users": "users.create",
			"add": "math.add",
			"GET sub": "math.sub",
			"POST divide": "math.div",
			"health": "$node.health"
		},

		// Folder to server assets (static files)
		assets: {
			// Root folder of assets
			folder: "./assets",
			// Options to `server-static` module
			options: {}
		},

		// Use bodyparser module
		bodyParsers: {
			json: true,
			urlencoded: { extended: true }
		}
	},

	/**
	 * Service created lifecycle event handler
	 */
	created() {
		this.server = http.createServer(this.httpHandler);

		this.server.on("connection", socket => {
			// Disable Nagle algorithm https://nodejs.org/dist/latest-v6.x/docs/api/net.html#net_socket_setnodelay_nodelay
			socket.setNoDelay(true);
		});

		// Create static server middleware
		if (this.settings.assets) {
			this.serve = serveStatic(this.settings.assets.folder, _.defaultsDeep(this.settings.assets.options, {
				fallthrough: false
			}));
		}

		// Handle whitelist
		this.hasWhitelist = Array.isArray(this.settings.whitelist);

		// Handle aliases
		this.hasAliases = this.settings.aliases && Object.keys(this.settings.aliases).length > 0;

		// Handle body parsers
		if (this.settings.bodyParsers) {
			const bodyParsers = _.isObject(this.settings.bodyParsers) ? this.settings.bodyParsers : { json: true };
			const parsers = [];
			Object.keys(bodyParsers).forEach(key => {
				const opts = _.isObject(bodyParsers[key]) ? bodyParsers[key] : undefined;
				if (bodyParsers[key] !== false)
					parsers.push(bp[key](opts));
			});

			this.parsers = parsers;
		}

		// Create URL prefix regexp
		let path = this.settings.path || "/";
		this.urlRegex = new RegExp(path.replace("/", "\\/") + "\\/([\\w\\.\\~\\/]+)", "g");

		this.logger.info("API Gateway created!");
	},

	methods: {
		/**
		 * Send 404 response
		 *
		 * @param {HttpRequest} req
		 * @param {HttpResponse} res
		 */
		send404(req, res) {
			res.writeHead(404);
			res.end("Not found");
		},

		/**
		 * Main HTTP request handler
		 *
		 * @param {HttpRequest} req
		 * @param {HttpResponse} res
		 * @returns
		 */
		httpHandler(req, res) {
			this.logger.debug("");
			this.logger.debug(`${req.method} ${req.url}`);

			try {
				// Split URL & query params
				let url;
				let query;
				const questionIdx = req.url.indexOf("?", 1);
				if (questionIdx === -1) {
					url = req.url;
				} else {
					query = queryString.parse(req.url.substring(questionIdx + 1));
					url = req.url.substring(0, questionIdx);
				}

				// Trim trailing slash
				if (url.endsWith("/"))
					url = url.slice(0, -1);

				// Check the URL is an API request
				this.urlRegex.lastIndex = 0;
				const match = this.urlRegex.exec(url);
				if (match) {
					// Resolve action name
					let actionName = match[1].replace(/~/, "$").replace(/\//g, ".");

					return this.callAction(actionName, req, res, query);
				}

				// Serve assets static files
				if (this.serve) {
					this.serve(req, res, err => {
						this.logger.debug(err);
						this.send404(req, res);
					});
					return;
				}

				// 404
				this.send404(req, res);

			} catch(err) {
				// 500
				this.logger.error("Handler error!", err);

				res.writeHead(500);
				res.end("Server error! " + err.message);
			}
		},

		/**
		 * Call an action with broker
		 *
		 * @param {String} actionName 	Name of action
		 * @param {HttpRequest} req 	Request object
		 * @param {HttpResponse} res 	Response object
		 * @param {Object} query		Parsed query string
		 * @returns {Promise}
		 */
		callAction(actionName, req, res, query) {
			let params = {};

			return this.Promise.resolve()

			// Resolve aliases
			.then(() => {
				if (this.hasAliases) {
					const newActionName = this.resolveAlias(actionName, req.method);
					if (newActionName !== actionName) {
						this.logger.debug(`  Alias: ${req.method} ${actionName} -> ${newActionName}`);
						actionName = newActionName;
					}
				}
			})

			// Whitelist check
			.then(() => {
				if (this.hasWhitelist) {
					if (!this.checkWhitelist(actionName)) {
						this.logger.debug(`  The '${actionName}' action is not in the whitelist!`);
						return this.Promise.reject(new CustomError("Not found", 404));
					}
				}
			})

			// Parse body
			.then(() => {

				if (["POST", "PUT", "PATCH"].indexOf(req.method) !== -1 && this.parsers.length > 0) {
					return this.Promise.mapSeries(this.parsers, parser => {
						return new this.Promise((resolve, reject) => {
							parser(req, res, err => {
								if (err)
									return reject(err);

								resolve();
							});
						});
					});
				}
			})

			// Merge params
			.then(() => {
				params = Object.assign({}, query);
				if (_.isObject(req.body))
					params = Object.assign(params, req.body);
			})

			// Call the action
			.then(() => {
				this.logger.info(`  Call '${actionName}' action with params:`, params);

				return this.broker.call(actionName, params)
					.then(data => {
						// Return with the response
						res.writeHead(200, { "Content-type": "application/json"});
						res.end(JSON.stringify(data));
					});
			})

			// Error handling
			.catch(err => {
				// Return with the error
				this.logger.error(err);
				res.writeHead(err.code || 500, { "Content-type": "application/json"});
				const errObj = _.pick(err, ["name", "message", "code", "data"]);
				res.end(JSON.stringify(errObj, null, 2));
			});
		},

		/**
		 * Check the action name in whitelist
		 *
		 * @param {String} action
		 * @returns {Boolean}
		 */
		checkWhitelist(action) {
			return this.settings.whitelist.find(mask => {
				if (_.isString(mask))
					return nanomatch.isMatch(action, mask, { unixify: false,  });
				else if (_.isRegExp(mask))
					return mask.test(action);
			}) != null;
		},

		/**
		 * Resolve alias names
		 *
		 * @param {String} actionName
		 * @param {string} [method="GET"]
		 * @returns {String} Resolved actionName
		 */
		resolveAlias(actionName, method = "GET") {
			const match = method + " " + actionName;

			const res = this.settings.aliases[match] || this.settings.aliases[actionName];

			return res ? res : actionName;
		}

	},

	/**
	 * Service started lifecycle event handler
	 */
	started() {
		this.server.listen(this.settings.port, this.settings.ip, err => {
			if (err)
				return this.logger.error("API Gateway listen error!", err);

			const addr = this.server.address();
			this.logger.info(`API Gateway listening on http://${addr.address}:${addr.port}`);
		});
	},

	/**
	 * Service stopped lifecycle event handler
	 */
	stopped() {
		if (this.server.listening) {
			this.server.close(err => {
				if (err)
					return this.logger.error("API Gateway close error!", err);

				this.logger.info("API Gateway stopped!");
			});
		}
	}

};<commit_msg>fix assets path<commit_after>/*
 * moleculer
 * Copyright (c) 2017 Ice Services (https://github.com/ice-services/moleculer)
 * MIT Licensed
 */

"use strict";

const http 				= require("http");
const queryString 		= require("querystring");

const _ 				= require("lodash");
const bp 				= require("body-parser");
const serveStatic 		= require("serve-static");
const nanomatch  		= require("nanomatch");

const { CustomError } 	= require("../src/errors");

/**
 * Official API Gateway service for Moleculer
 *
 * TODO:
 * -----
 * 	- create context
 *  - generate requestID & response back to backend
 *  - prereq action to check the params & responseType
 *  - auth service call
 *  -
 *
 *
 */
module.exports = {

	// Service name
	name: "api-gw",

	// Version
	version: "1.0",

	// Service settings
	settings: {

		// Exposed port
		port: process.env.PORT || 4000,

		// Exposed IP
		ip: process.env.IP || "0.0.0.0",

		// Exposed path prefix
		path: "/api",

		// Whitelist of actions (array of string mask or regex)
		whitelist: [
			"posts.*",
			"users.get",
			"$node.*",
			/^math\.\w+$/
		],

		// Action aliases
		aliases: {
			"POST users": "users.create",
			"add": "math.add",
			"GET sub": "math.sub",
			"POST divide": "math.div",
			"health": "$node.health"
		},

		// Folder to server assets (static files)
		assets: {
			// Root folder of assets
			folder: "./examples/www/assets",
			// Options to `server-static` module
			options: {}
		},

		// Use bodyparser module
		bodyParsers: {
			json: true,
			urlencoded: { extended: true }
		}
	},

	/**
	 * Service created lifecycle event handler
	 */
	created() {
		this.server = http.createServer(this.httpHandler);

		this.server.on("connection", socket => {
			// Disable Nagle algorithm https://nodejs.org/dist/latest-v6.x/docs/api/net.html#net_socket_setnodelay_nodelay
			socket.setNoDelay(true);
		});

		// Create static server middleware
		if (this.settings.assets) {
			this.serve = serveStatic(this.settings.assets.folder, _.defaultsDeep(this.settings.assets.options, {
				fallthrough: false
			}));
		}

		// Handle whitelist
		this.hasWhitelist = Array.isArray(this.settings.whitelist);

		// Handle aliases
		this.hasAliases = this.settings.aliases && Object.keys(this.settings.aliases).length > 0;

		// Handle body parsers
		if (this.settings.bodyParsers) {
			const bodyParsers = _.isObject(this.settings.bodyParsers) ? this.settings.bodyParsers : { json: true };
			const parsers = [];
			Object.keys(bodyParsers).forEach(key => {
				const opts = _.isObject(bodyParsers[key]) ? bodyParsers[key] : undefined;
				if (bodyParsers[key] !== false)
					parsers.push(bp[key](opts));
			});

			this.parsers = parsers;
		}

		// Create URL prefix regexp
		let path = this.settings.path || "/";
		this.urlRegex = new RegExp(path.replace("/", "\\/") + "\\/([\\w\\.\\~\\/]+)", "g");

		this.logger.info("API Gateway created!");
	},

	methods: {
		/**
		 * Send 404 response
		 *
		 * @param {HttpRequest} req
		 * @param {HttpResponse} res
		 */
		send404(req, res) {
			res.writeHead(404);
			res.end("Not found");
		},

		/**
		 * Main HTTP request handler
		 *
		 * @param {HttpRequest} req
		 * @param {HttpResponse} res
		 * @returns
		 */
		httpHandler(req, res) {
			this.logger.debug("");
			this.logger.debug(`${req.method} ${req.url}`);

			try {
				// Split URL & query params
				let url;
				let query;
				const questionIdx = req.url.indexOf("?", 1);
				if (questionIdx === -1) {
					url = req.url;
				} else {
					query = queryString.parse(req.url.substring(questionIdx + 1));
					url = req.url.substring(0, questionIdx);
				}

				// Trim trailing slash
				if (url.endsWith("/"))
					url = url.slice(0, -1);

				// Check the URL is an API request
				this.urlRegex.lastIndex = 0;
				const match = this.urlRegex.exec(url);
				if (match) {
					// Resolve action name
					let actionName = match[1].replace(/~/, "$").replace(/\//g, ".");

					return this.callAction(actionName, req, res, query);
				}

				// Serve assets static files
				if (this.serve) {
					this.serve(req, res, err => {
						this.logger.debug(err);
						this.send404(req, res);
					});
					return;
				}

				// 404
				this.send404(req, res);

			} catch(err) {
				// 500
				this.logger.error("Handler error!", err);

				res.writeHead(500);
				res.end("Server error! " + err.message);
			}
		},

		/**
		 * Call an action with broker
		 *
		 * @param {String} actionName 	Name of action
		 * @param {HttpRequest} req 	Request object
		 * @param {HttpResponse} res 	Response object
		 * @param {Object} query		Parsed query string
		 * @returns {Promise}
		 */
		callAction(actionName, req, res, query) {
			let params = {};

			return this.Promise.resolve()

			// Resolve aliases
			.then(() => {
				if (this.hasAliases) {
					const newActionName = this.resolveAlias(actionName, req.method);
					if (newActionName !== actionName) {
						this.logger.debug(`  Alias: ${req.method} ${actionName} -> ${newActionName}`);
						actionName = newActionName;
					}
				}
			})

			// Whitelist check
			.then(() => {
				if (this.hasWhitelist) {
					if (!this.checkWhitelist(actionName)) {
						this.logger.debug(`  The '${actionName}' action is not in the whitelist!`);
						return this.Promise.reject(new CustomError("Not found", 404));
					}
				}
			})

			// Parse body
			.then(() => {

				if (["POST", "PUT", "PATCH"].indexOf(req.method) !== -1 && this.parsers.length > 0) {
					return this.Promise.mapSeries(this.parsers, parser => {
						return new this.Promise((resolve, reject) => {
							parser(req, res, err => {
								if (err)
									return reject(err);

								resolve();
							});
						});
					});
				}
			})

			// Merge params
			.then(() => {
				params = Object.assign({}, query);
				if (_.isObject(req.body))
					params = Object.assign(params, req.body);
			})

			// Call the action
			.then(() => {
				this.logger.info(`  Call '${actionName}' action with params:`, params);

				return this.broker.call(actionName, params)
					.then(data => {
						// Return with the response
						res.writeHead(200, { "Content-type": "application/json"});
						res.end(JSON.stringify(data));
					});
			})

			// Error handling
			.catch(err => {
				// Return with the error
				this.logger.error(err);
				res.writeHead(err.code || 500, { "Content-type": "application/json"});
				const errObj = _.pick(err, ["name", "message", "code", "data"]);
				res.end(JSON.stringify(errObj, null, 2));
			});
		},

		/**
		 * Check the action name in whitelist
		 *
		 * @param {String} action
		 * @returns {Boolean}
		 */
		checkWhitelist(action) {
			return this.settings.whitelist.find(mask => {
				if (_.isString(mask))
					return nanomatch.isMatch(action, mask, { unixify: false,  });
				else if (_.isRegExp(mask))
					return mask.test(action);
			}) != null;
		},

		/**
		 * Resolve alias names
		 *
		 * @param {String} actionName
		 * @param {string} [method="GET"]
		 * @returns {String} Resolved actionName
		 */
		resolveAlias(actionName, method = "GET") {
			const match = method + " " + actionName;

			const res = this.settings.aliases[match] || this.settings.aliases[actionName];

			return res ? res : actionName;
		}

	},

	/**
	 * Service started lifecycle event handler
	 */
	started() {
		this.server.listen(this.settings.port, this.settings.ip, err => {
			if (err)
				return this.logger.error("API Gateway listen error!", err);

			const addr = this.server.address();
			this.logger.info(`API Gateway listening on http://${addr.address}:${addr.port}`);
		});
	},

	/**
	 * Service stopped lifecycle event handler
	 */
	stopped() {
		if (this.server.listening) {
			this.server.close(err => {
				if (err)
					return this.logger.error("API Gateway close error!", err);

				this.logger.info("API Gateway stopped!");
			});
		}
	}

};<|endoftext|>


<commit_before>function OAuthConsumer(options) {
    if (arguments.length > 0) {
        this.init(options);
    }

    this.init = function(options) {
        this.debug = options.debug == true ? true : false;
        this.key = options.key || '';
        this.secret = options.secret || '';
        this.callback_url = options.callback_url || 'oob';
        this.token = options.token || '';
        this.token_secret = options.token_secret || '';
    };

    this.requestToken = function(){
        if (this.debug) {
            netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead UniversalBrowserWrite");
        }
        // create a header
        var request_params = {
            'oauth_callback': this.callback_url,
            'oauth_consumer_key': this.key,
            'oauth_token': this.token,
            'oauth_signature_method': SIGNATURE_METHOD,
            'oauth_timestamp': this.getTimestamp(),
            'oauth_nonce': this.getNonce(),
            'oauth_verifier': '',
            'oauth_signature': (
                new OAuthConsumer.signatureMethods[SIGNATURE_METHOD]
             ).sign(this.secret, this.token_secret),
            'oauth_version': VERSION
        };
        var request_header = [];
        var request = [];
        var header = '';
        var xhr;
        var url;

        for (var i in request_params) {
            if (request_params.hasOwnProperty(i)) {
                request_header.push(OAuthUtilities.urlEncode(i) + '="'
                    + OAuthUtilities.urlEncode(request_params[i]) + '"');
                request.push(OAuthUtilities.urlEncode(i) + '='
                    + OAuthUtilities.urlEncode(request_params[i]));
            }
        }

        header = 'OAuth realm="' + this.realm + '",' + request_header.join(',');
        url = this.requestTokenUrl;

        xhr = new XMLHttpRequest();
        xhr.open('POST', url, false);
        xhr.setRequestHeader('Authorization', header);
        xhr.send(request.join('&'));
        if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
            // oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03&
            var token_string_params = xhr.responseText.split('&');
            for (var i = 0; i < token_string_params.length; i++) {
                var param = token_string_params[i].split('=');
                if (param[0] == 'oauth_token') {
                    this.token = param[1];
                }
                if (param[0] == 'oauth_token_secret') {
                    this.token_secret = param[1];
                }
            }
        }

        return this;
    };

    this.authorize = function(){
        if (this.debug) {
            netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead UniversalBrowserWrite");
        }

        // create a header
        var request_params = {
            'oauth_callback': this.callback_url,
            'oauth_consumer_key': this.key,
            'oauth_token': this.token,
            'oauth_signature_method': SIGNATURE_METHOD,
            'oauth_timestamp': this.getTimestamp(),
            'oauth_nonce': this.getNonce(),
            'oauth_verifier': '',
            'oauth_signature': (
                new OAuthConsumer.signatureMethods[SIGNATURE_METHOD]
             ).sign(this.secret, this.token_secret),
            'oauth_version': VERSION
        };

        var request = [];
        var header = '';
        var url;

        for (var i in request_params) {
            if (request_params.hasOwnProperty(i)) {
                request.push(OAuthUtilities.urlEncode(i) + '='
                    + OAuthUtilities.urlEncode(request_params[i]));
            }
        }

        url = this.authorizationUrl + '?' + request.join('&');
        return url;
    };

    this.accessToken = function(oauth_verifier){
        if (this.debug) {
            netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead UniversalBrowserWrite");
        }

        // create a header
        var request_params = {
            //'oauth_callback': this.callback_url,
            'oauth_consumer_key': this.key,
            'oauth_token': this.token,
            'oauth_signature_method': SIGNATURE_METHOD,
            'oauth_timestamp': this.getTimestamp(),
            'oauth_nonce': this.getNonce(),
            'oauth_verifier': oauth_verifier,
            'oauth_signature': (
                new OAuthConsumer.signatureMethods[SIGNATURE_METHOD]
             ).sign(this.secret, this.token_secret),
            'oauth_version': VERSION
        };
        var request_header = [];
        var request = [];
        var header = '';
        var xhr;
        var url;

        for (var i in request_params) {
            if (request_params.hasOwnProperty(i)) {
                request_header.push(OAuthUtilities.urlEncode(i) + '="'
                    + OAuthUtilities.urlEncode(request_params[i]) + '"');
                request.push(OAuthUtilities.urlEncode(i) + '='
                    + OAuthUtilities.urlEncode(request_params[i]));
            }
        }

        header = 'OAuth realm="' + this.realm + '",' + request_header.join(',');
        url = this.accessTokenUrl;
        xhr = new XMLHttpRequest();
        xhr.open('POST', url, false);
        xhr.setRequestHeader('Authorization', header);
        xhr.send(request.join('&'));
        if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
            // oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03&
            var token_string_params = xhr.responseText.split('&');
            for (var i = 0; i < token_string_params.length; i++) {
                var param = token_string_params[i].split('=');
                if (param[0] == 'oauth_token') {
                    this.token = param[1];
                }
                if (param[0] == 'oauth_token_secret') {
                    this.token_secret = param[1];
                }
            }
        }

        return this;
    };

    this.getTimestamp = function() {
        return parseInt((new Date).getTime() / 1000) + '';
    };

    this.getNonce = function(key_length){
        key_length = key_length || 64;

        var key_bytes = key_length / 8;
        var value = '';
        var key_iter = key_bytes / 4;
        var key_remainder = key_bytes % 4;
        var chars = ['20', '21', '22', '23', '24', '25', '26', '27', '28', '29',
                     '2A', '2B', '2C', '2D', '2E', '2F', '30', '31', '32', '33',
                     '34', '35', '36', '37', '38', '39', '3A', '3B', '3C', '3D',
                     '3E', '3F', '40', '41', '42', '43', '44', '45', '46', '47',
                     '48', '49', '4A', '4B', '4C', '4D', '4E', '4F', '50', '51',
                     '52', '53', '54', '55', '56', '57', '58', '59', '5A', '5B',
                     '5C', '5D', '5E', '5F', '60', '61', '62', '63', '64', '65',
                     '66', '67', '68', '69', '6A', '6B', '6C', '6D', '6E', '6F',
                     '70', '71', '72', '73', '74', '75', '76', '77', '78', '79',
                     '7A', '7B', '7C', '7D', '7E'];

        for (var i = 0; i < key_iter; i++) {
            value += chars[rand()] + chars[rand()] + chars[rand()]+ chars[rand()];
        }

        // handle remaing bytes
        for (var i = 0; i < key_remainder; i++) {
            value += chars[rand()];
        }

        return value;

        function rand() {
            return Math.floor(Math.random() * chars.length);
        }
    };
}

OAuthConsumer.signatureMethods = {};
<commit_msg>added cookie support<commit_after>function OAuthConsumer(options) {
    if (arguments.length > 0) {
        this.init(options);
    }

    this.init = function(options) {
        // default to using cookies
        options.use_cookies = options.use_cookies || true;

        this.debug = options.debug == false ? false : true;
        this.key = options.key || '';
        this.secret = options.secret || '';
        this.callback_url = options.callback_url || 'oob';
        this.token = options.token || '';
        this.token_secret = options.token_secret || '';
        this.use_cookies = options.use_cookies;
        this.cookie;

        if (options.use_cookies) {
            this.cookie = new OAuthCookie('oauth_token');
            var values = this.cookie.getValue().split('|');
            if (values) {
                this.token = values[0];
                this.token_secret = values[1];
            }
        }
    };

    this.requestToken = function(){
        if (this.debug) {
            netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead UniversalBrowserWrite");
        }
        // create a header
        var request_params = {
            'oauth_callback': this.callback_url,
            'oauth_consumer_key': this.key,
            'oauth_token': this.token,
            'oauth_signature_method': this.signature_method,
            'oauth_timestamp': this.getTimestamp(),
            'oauth_nonce': this.getNonce(),
            'oauth_verifier': '',
            'oauth_signature': (
                new OAuthConsumer.signatureMethods[this.signature_method]
             ).sign(this.secret, this.token_secret),
            'oauth_version': VERSION
        };
        var request_header = [];
        var request = [];
        var header = '';
        var xhr;
        var url;

        for (var i in request_params) {
            if (request_params.hasOwnProperty(i)) {
                request_header.push(OAuthUtilities.urlEncode(i) + '="'
                    + OAuthUtilities.urlEncode(request_params[i]) + '"');
                request.push(OAuthUtilities.urlEncode(i) + '='
                    + OAuthUtilities.urlEncode(request_params[i]));
            }
        }

        header = 'OAuth realm="' + this.realm + '",' + request_header.join(',');
        url = this.requestTokenUrl;

        xhr = new XMLHttpRequest();
        xhr.open('POST', url, false);
        xhr.setRequestHeader('Authorization', header);
        xhr.send(request.join('&'));
        if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
            // oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03&
            var token_string_params = xhr.responseText.split('&');
            for (var i = 0; i < token_string_params.length; i++) {
                var param = token_string_params[i].split('=');
                if (param[0] == 'oauth_token') {
                    this.token = param[1];
                }
                if (param[0] == 'oauth_token_secret') {
                    this.token_secret = param[1];
                }
            }
            //this.cookie.setValue(this.token + '|' + this.token_secret);
        }

        return this;
    };

    this.authorize = function(){
        if (this.debug) {
            netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead UniversalBrowserWrite");
        }

        // create a header
        var request_params = {
            'oauth_callback': this.callback_url,
            'oauth_consumer_key': this.key,
            'oauth_token': this.token,
            'oauth_signature_method': SIGNATURE_METHOD,
            'oauth_timestamp': this.getTimestamp(),
            'oauth_nonce': this.getNonce(),
            'oauth_verifier': '',
            'oauth_signature': (
                new OAuthConsumer.signatureMethods[SIGNATURE_METHOD]
             ).sign(this.secret, this.token_secret),
            'oauth_version': VERSION
        };

        var request = [];
        var header = '';
        var url;

        for (var i in request_params) {
            if (request_params.hasOwnProperty(i)) {
                request.push(OAuthUtilities.urlEncode(i) + '='
                    + OAuthUtilities.urlEncode(request_params[i]));
            }
        }

        url = this.authorizationUrl + '?' + request.join('&');
        return url;
    };

    this.accessToken = function(oauth_verifier){
        if (this.debug) {
            netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead UniversalBrowserWrite");
        }

        // create a header
        var request_params = {
            //'oauth_callback': this.callback_url,
            'oauth_consumer_key': this.key,
            'oauth_token': this.token,
            'oauth_signature_method': SIGNATURE_METHOD,
            'oauth_timestamp': this.getTimestamp(),
            'oauth_nonce': this.getNonce(),
            'oauth_verifier': oauth_verifier,
            'oauth_signature': (
                new OAuthConsumer.signatureMethods[SIGNATURE_METHOD]
             ).sign(this.secret, this.token_secret),
            'oauth_version': VERSION
        };
        var request_header = [];
        var request = [];
        var header = '';
        var xhr;
        var url;

        for (var i in request_params) {
            if (request_params.hasOwnProperty(i)) {
                request_header.push(OAuthUtilities.urlEncode(i) + '="'
                    + OAuthUtilities.urlEncode(request_params[i]) + '"');
                request.push(OAuthUtilities.urlEncode(i) + '='
                    + OAuthUtilities.urlEncode(request_params[i]));
            }
        }

        header = 'OAuth realm="' + this.realm + '",' + request_header.join(',');
        url = this.accessTokenUrl;
        xhr = new XMLHttpRequest();
        xhr.open('POST', url, false);
        xhr.setRequestHeader('Authorization', header);
        xhr.send(request.join('&'));
        if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
            // oauth_token=hh5s93j4hdidpola&oauth_token_secret=hdhd0244k9j7ao03&
            var token_string_params = xhr.responseText.split('&');
            for (var i = 0; i < token_string_params.length; i++) {
                var param = token_string_params[i].split('=');
                if (param[0] == 'oauth_token') {
                    this.token = param[1];
                }
                if (param[0] == 'oauth_token_secret') {
                    this.token_secret = param[1];
                }
            }

            this.cookie.setValue(this.token + '|' + this.token_secret);
        }

        return this;
    };

    this.getTimestamp = function() {
        return parseInt((new Date).getTime() / 1000) + '';
    };

    this.getNonce = function(key_length){
        key_length = key_length || 64;

        var key_bytes = key_length / 8;
        var value = '';
        var key_iter = key_bytes / 4;
        var key_remainder = key_bytes % 4;
        var chars = ['20', '21', '22', '23', '24', '25', '26', '27', '28', '29',
                     '2A', '2B', '2C', '2D', '2E', '2F', '30', '31', '32', '33',
                     '34', '35', '36', '37', '38', '39', '3A', '3B', '3C', '3D',
                     '3E', '3F', '40', '41', '42', '43', '44', '45', '46', '47',
                     '48', '49', '4A', '4B', '4C', '4D', '4E', '4F', '50', '51',
                     '52', '53', '54', '55', '56', '57', '58', '59', '5A', '5B',
                     '5C', '5D', '5E', '5F', '60', '61', '62', '63', '64', '65',
                     '66', '67', '68', '69', '6A', '6B', '6C', '6D', '6E', '6F',
                     '70', '71', '72', '73', '74', '75', '76', '77', '78', '79',
                     '7A', '7B', '7C', '7D', '7E'];

        for (var i = 0; i < key_iter; i++) {
            value += chars[rand()] + chars[rand()] + chars[rand()]+ chars[rand()];
        }

        // handle remaing bytes
        for (var i = 0; i < key_remainder; i++) {
            value += chars[rand()];
        }

        return value;

        function rand() {
            return Math.floor(Math.random() * chars.length);
        }
    };
}

OAuthConsumer.signatureMethods = {};
<|endoftext|>


<commit_before>import React, { Component } from "react";
import DateTimeField from "react-bootstrap-datetimepicker";
import moment from "moment";

class ParentComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      date: "1990-06-05",
      format: "YYYY-MM-DD",
      inputFormat: "DD/MM/YYYY",
      mode: "date"
    };
  }

  handleChange = (newDate) => {
    console.log("newDate", newDate);
    return this.setState({date: newDate});
  }

  render() {
    const {date, format, mode, inputFormat} = this.state;
    return <DateTimeField
      dateTime={date}
      format={format}
      viewMode={mode}
      inputFormat={inputFormat}
      onChange={this.handleChange}
    />;
  }
}

class Basic extends Component {

	render() {
    return (

React Bootstrap DateTimePicker

								This project is a port of https://github.com/Eonasdan/bootstrap-datetimepicker for React.js

                Controlled Component example
                <ParentComponent />

                  {`class ParentComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      date: "1990-06-05",
      format: "YYYY-MM-DD",
      inputFormat: "DD/MM/YYYY",
      mode: "date"
    };
  }

  handleChange = (newDate) => {
    console.log("newDate", newDate);
    return this.setState({date: newDate});
  }

  render() {
    const {date, format, mode, inputFormat} = this.state;
    return <DateTimeField
      dateTime={date}
      format={format}
      viewMode={mode}
      inputFormat={inputFormat}
      onChange={this.handleChange}
    />;
  }
}`}

                  Example with default Text
                  <DateTimeField
                    defaultText="Please select a date"
                  />

 {'<DateTimeField defaultText="Please select a date" />'}

								Default Basic Example
								<DateTimeField />

 {'<DateTimeField />'}

								Example with default Text
								<DateTimeField
									defaultText="Please select a date"
								/>

 {'<DateTimeField defaultText="Please select a date" />'}

                ViewMode set to years view with custom inputFormat
                <DateTimeField
                  inputFormat='DD-MM-YYYY'
                  viewMode='years'
                />

 {'<DateTimeField viewMode="years" inputFormat="DD-MM-YYYY" />'}

                daysOfWeekDisabled
                <DateTimeField
                  daysOfWeekDisabled={[0, 1, 2]}
                />

 {'<DateTimeField daysOfWeekDisabled={[0,1,2]} />'}

                minDate and maxDate
                <DateTimeField
                  maxDate={moment().add(1, "days")}
                  minDate={moment().subtract(1, "days")}
                />

 {'<DateTimeField daysOfWeekDisabled={[0,1,2]} />'}

                  just time picker
                  <DateTimeField
                      mode="time"
                      />

 {'<DateTimeField mode="time" />'}

                  just date picker
                  <DateTimeField
                      mode="date"
                      />

 {'<DateTimeField mode="date" />'}

      );
   }
}

React.render(React.createFactory(Basic)(), document.getElementById("example"));
<commit_msg>fix minDate + maxDate examples<commit_after>import React, { Component } from "react";
import DateTimeField from "react-bootstrap-datetimepicker";
import moment from "moment";

class ParentComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      date: "1990-06-05",
      format: "YYYY-MM-DD",
      inputFormat: "DD/MM/YYYY",
      mode: "date"
    };
  }

  handleChange = (newDate) => {
    console.log("newDate", newDate);
    return this.setState({date: newDate});
  }

  render() {
    const {date, format, mode, inputFormat} = this.state;
    return <DateTimeField
      dateTime={date}
      format={format}
      viewMode={mode}
      inputFormat={inputFormat}
      onChange={this.handleChange}
    />;
  }
}

class Basic extends Component {

	render() {
    return (

React Bootstrap DateTimePicker

								This project is a port of https://github.com/Eonasdan/bootstrap-datetimepicker for React.js

                Controlled Component example
                <ParentComponent />

                  {`class ParentComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      date: "1990-06-05",
      format: "YYYY-MM-DD",
      inputFormat: "DD/MM/YYYY",
      mode: "date"
    };
  }

  handleChange = (newDate) => {
    console.log("newDate", newDate);
    return this.setState({date: newDate});
  }

  render() {
    const {date, format, mode, inputFormat} = this.state;
    return <DateTimeField
      dateTime={date}
      format={format}
      viewMode={mode}
      inputFormat={inputFormat}
      onChange={this.handleChange}
    />;
  }
}`}

                  Example with default Text
                  <DateTimeField
                    defaultText="Please select a date"
                  />

 {'<DateTimeField defaultText="Please select a date" />'}

								Default Basic Example
								<DateTimeField />

 {'<DateTimeField />'}

								Example with default Text
								<DateTimeField
									defaultText="Please select a date"
								/>

 {'<DateTimeField defaultText="Please select a date" />'}

                ViewMode set to years view with custom inputFormat
                <DateTimeField
                  inputFormat='DD-MM-YYYY'
                  viewMode='years'
                />

 {'<DateTimeField viewMode="years" inputFormat="DD-MM-YYYY" />'}

                daysOfWeekDisabled
                <DateTimeField
                  daysOfWeekDisabled={[0, 1, 2]}
                />

 {'<DateTimeField daysOfWeekDisabled={[0,1,2]} />'}

                minDate and maxDate
                <DateTimeField
                  minDate={moment()}
                  maxDate={moment().add(5, "days")}
                />

 {'<DateTimeField minDate={moment()} maxDate={moment().add(5, "days")} />'}

                  just time picker
                  <DateTimeField
                      mode="time"
                      />

 {'<DateTimeField mode="time" />'}

                  just date picker
                  <DateTimeField
                      mode="date"
                      />

 {'<DateTimeField mode="date" />'}

      );
   }
}

React.render(React.createFactory(Basic)(), document.getElementById("example"));
<|endoftext|>


<commit_before>/**
 * Builds full page project browser
 */
'use strict';

var Treebeard = require('treebeard');   // Uses treebeard, installed as plugin
var $ = require('jquery');  // jQuery
var m = require('mithril'); // exposes mithril methods, useful for redraw etc.
var ProjectOrganizer = require('js/project-organizer');
var $osf = require('js/osfHelpers');

var LinkObject = function (type, data, label, index) {
    this.type = type;
    this.data = data;
    this.label = label;
    this.index = index;  // For breadcrumbs to cut off when clicking parent level
};

var Breadcrumb = function (label, url, type) {
    this.label = label;
    this.url = url;
    this.type = 'breadcrumb' || type;
};

var Collection = function(label, path, pathQuery) {
    this.type = 'collection';
    this.label = label || 'New Collection';
    this.path = path;
    this.pathQuery = pathQuery;
};

var Filter = function (label, data, type) {
    this.label = label;
    this.data = data;
    this.type = 'name' || type;
};

/**
 * Initialize File Browser. Prepeares an option object within FileBrowser
 * @constructor
 */
var FileBrowser = {
    controller : function (options) {
        var self = this;
        self.isLoadedUrl = false;
        self.wrapperSelector = options.wrapperSelector;

        // VIEW STATES
        self.showInfo = m.prop(false);

        // DEFAULT DATA -- to be switched with server response
        self.collections = [
            new Collection('All My Projects', 'users/me/nodes/', { 'related_counts' : true }),
            new Collection('All My Registrations', 'registrations/', { 'related_counts' : true }),
            new Collection('Everything', 'users/me/nodes/', { 'related_counts' : true }),
        ];
        self.breadcrumbs = m.prop([
            new Breadcrumb('All My Projects','http://localhost:8000/v2/users/me/nodes/?related_counts=true', 'collection')
        ]);
        self.nameFilters = [
            new Filter('Caner Uguz', '8q36f')
        ];
        self.tagFilters = [
            new Filter('Something Else', 'something-else', 'tag')
        ];
        self.filesData = m.prop($osf.apiV2Url(
            self.collections[0].path,
            { query : self.collections[0].pathQuery }
        ));

        self.updateFilesData = function(linkObject) {
            linkObject.link = self.generateLinks(linkObject);
            if (linkObject.link !== self.filesData()) {
                self.filesData(linkObject.link);
                self.isLoadedUrl = false; // check if in fact changed
                self.updateBreadcrumbs(linkObject);
            }
        };

        // INFORMATION PANEL
        self.selected = m.prop([]);
        self.updateSelected = function(selectedList){
            selectedList.map(function(item){
                // get information

            });
            self.selected(selectedList);

        };

        // COLLECTIONS PANEL
        self.activeCollection = m.prop(1);
        self.updateCollection = function(coll) {
            self.activeCollection(coll.id);
            var linkObject = new LinkObject( 'collection', coll, coll.label);
            self.updateFilesData(linkObject);
        };

        // USER FILTER
        self.activeUser = m.prop(1);
        self.updateUserFilter = function(user) {
            self.activeUser(user.id);
            var linkObject = new LinkObject('user', user.data, user.label);
            self.updateFilesData(linkObject);
        };

        // Refresh the Grid
        self.updateList = function(element, isInit, context){
            if(!self.isLoadedUrl) {
                var el = element || $(self.wrapperSelector).find('.fb-main').get(0);
                m.mount(el,
                    m.component( ProjectOrganizer, {
                        filesData : self.filesData,
                        updateSelected : self.updateSelected,
                        updateFilesData : self.updateFilesData,
                        wrapperSelector : self.wrapperSelector
                        }
                    )
                );
                self.isLoadedUrl = true;
            }
        }.bind(self);

        // BREADCRUMBS
        self.updateBreadcrumbs = function(linkObject){
            var crumb = new Breadcrumb(linkObject.label, linkObject.link, linkObject.type);
            if (linkObject.type === 'collection' || linkObject.type === 'user'){
                self.breadcrumbs([crumb]);
                return;
            }
            if (linkObject.type === 'breadcrumb'){
                self.breadcrumbs().splice(linkObject.index+1, self.breadcrumbs().length-linkObject.index-1);
                return;
            }
            self.breadcrumbs().push(crumb);
        }.bind(self);

        self.generateLinks = function (linkObject) {
            if (linkObject.type === 'collection'){
                return $osf.apiV2Url(linkObject.data.path, {
                        query : linkObject.data.pathQuery
                    }
                );
            }
            else if (linkObject.type === 'breadcrumb') {
                return linkObject.data.url;
            }
            else if (linkObject.type === 'user') {
                return $osf.apiV2Url('users/' + linkObject.data + '/nodes', { query : {'related_counts' : true}});
            }
            else if (linkObject.type === 'node') {
                return $osf.apiV2Url('nodes/' + linkObject.data.uid + '/children', { query : { 'related_counts' : true }});
            }
            // If nothing
            throw new Error('Link could not be generated from linkObject data');
        };

    },
    view : function (ctrl) {
        var infoPanel = '';
        var poStyle = 'width : 80%';
        var infoClass = 'btn-default';
        if (ctrl.showInfo()){
            infoPanel = m('.fb-infobar', m.component(Information, { selected : ctrl.selected }));
            poStyle = 'width : 60%';
            infoClass = 'btn-primary';
        }
        return [
            m('.fb-header.m-b-xs', [
                m.component(Breadcrumbs, {
                    data : ctrl.breadcrumbs,
                    updateFilesData : ctrl.updateFilesData
                }),
                m('.fb-buttonRow', [
                    m('button.btn', {
                        'class' : infoClass,
                        onclick : function () {
                            ctrl.showInfo(!ctrl.showInfo());
                        }
                    }, m('.fa.fa-info'))
                ])
            ]),
            m('.fb-sidebar', [
                m.component(Collections, {
                    list : ctrl.collections,
                    activeCollection : ctrl.activeCollection,
                    updateCollection : ctrl.updateCollection
                }),
                m.component(Filters, {
                    activeUser : ctrl.activeUser,
                    updateUser : ctrl.updateUserFilter,
                    nameFilters : ctrl.nameFilters,
                    tagFilters : ctrl.tagFilters
                })
            ]),
            m('.fb-main', { config: ctrl.updateList, style : poStyle },
                m('#poOrganizer', m('.spinner-loading-wrapper', m('.logo-spin.logo-md')))
            ),
            infoPanel
        ];
    }
};

/**
 * Collections Module.
 * @constructor
 */
var Collections  = {
    view : function (ctrl, args) {
        var selectedCSS;
        return m('.fb-collections', m('ul', [
            args.list.map(function(item, index, array){
                selectedCSS = item.id === args.activeCollection() ? '.active' : '';
                return m('li', { className : selectedCSS},
                    m('a', { href : '#', onclick : args.updateCollection.bind(null, item) },  item.label)
                );
            })
        ]));
    }
};

/**
 * Breadcrumbs Module.
 * @constructor
 */

var Breadcrumbs = {
    view : function (ctrl, args) {
        return m('.fb-breadcrumbs', m('ul', [
            args.data().map(function(item, index, array){
                if(index === array.length-1){
                    return m('li',  item.label);
                }
                var linkObject = new LinkObject(item.type, item, item.label, index);

                return m('li',
                    m('a', { href : '#', onclick : args.updateFilesData.bind(null, linkObject)},  item.label),
                    m('i.fa.fa-chevron-right')
                );
            })

        ]));
    }
};

/**
 * Filters Module.
 * @constructor
 */
var Filters = {
    view : function (ctrl, args) {
        var selectedCSS;
        return m('.fb-filters.m-t-lg',
            [
                m('h4', 'Filters'),
                m('', 'Contributors'),
                m('ul', [
                    args.nameFilters.map(function(item){
                        selectedCSS = item.id === args.activeUser() ? '.active' : '';
                        return m('li' + selectedCSS,
                            m('a', { href : '#', onclick : args.updateUser.bind(null, item)}, item.label)
                        );
                    })
                ])

            ]
        );
    }
};

/**
 * Information Module.
 * @constructor
 */
var Information = {
    view : function (ctrl, args) {
        var template = '';
        if (args.selected().length === 1) {
            var item = args.selected()[0];
            template = m('', [
                m('h4', m('a', { href : item.data.links.html}, item.data.attributes.title)),
                m('p', [
                    m('span', 'Description: '),
                    m('span', item.data.attributes.description)
                ]),
                m('p', [
                    m('span', 'Category: '),
                    m('span', item.data.attributes.category)
                ]),
                m('p', [
                    m('', 'Tags'),
                    item.data.attributes.tags.map(function(tag){
                        return m('span.tag', tag);
                    })
                ]),
                m('p', [
                    m('span', 'Last Modified: '),
                    m('span', item.data.attributes.date_modified)
                ]),
                m('p', [
                    m('span', 'Visibility: '),
                    m('span', item.data.attributes.public ? 'Public' : 'Private')
                ]),

            ]);
        }
        if (args.selected().length > 1) {
            template = m('', [ 'There are multiple items: ', args.selected().map(function(item){
                    return m('p', item.data.attributes.title);
                })]);
        }
        return m('.fb-information', template);
    }
};

module.exports = FileBrowser;<commit_msg>Unify filter structure with ids and add tag links<commit_after>/**
 * Builds full page project browser
 */
'use strict';

var Treebeard = require('treebeard');   // Uses treebeard, installed as plugin
var $ = require('jquery');  // jQuery
var m = require('mithril'); // exposes mithril methods, useful for redraw etc.
var ProjectOrganizer = require('js/project-organizer');
var $osf = require('js/osfHelpers');

var LinkObject = function (type, data, label, index) {
    this.type = type;
    this.data = data;
    this.label = label;
    this.index = index;  // For breadcrumbs to cut off when clicking parent level
};

var Breadcrumb = function (label, url, type) {
    this.label = label;
    this.url = url;
    this.type = 'breadcrumb' || type;
};

var Collection = function(label, path, pathQuery) {
    this.id = getUID();
    this.type = 'collection';
    this.label = label || 'New Collection';
    this.path = path;
    this.pathQuery = pathQuery;
};

var Filter = function (label, data, type) {
    this.id = getUID();
    this.label = label;
    this.data = data;
    this.type = type;
};

if (!window.fileBrowserCounter) {
    window.fileBrowserCounter = 0;
}
function getUID() {
    window.fileBrowserCounter = window.fileBrowserCounter + 1;
    return window.treebeardCounter;
}

/**
 * Initialize File Browser. Prepeares an option object within FileBrowser
 * @constructor
 */
var FileBrowser = {
    controller : function (options) {
        var self = this;
        self.isLoadedUrl = false;
        self.wrapperSelector = options.wrapperSelector;

        // VIEW STATES
        self.showInfo = m.prop(false);

        // DEFAULT DATA -- to be switched with server response
        self.collections = [
            new Collection('All My Projects', 'users/me/nodes/', { 'related_counts' : true }),
            new Collection('All My Registrations', 'registrations/', { 'related_counts' : true }),
            new Collection('Everything', 'users/me/nodes/', { 'related_counts' : true })
        ];
        self.breadcrumbs = m.prop([
            new Breadcrumb('All My Projects','http://localhost:8000/v2/users/me/nodes/?related_counts=true', 'collection')
        ]);
        self.nameFilters = [
            new Filter('Caner Uguz', '8q36f', 'name')
        ];
        self.tagFilters = [
            new Filter('Something Else', 'something-else', 'tag')
        ];
        self.filesData = m.prop($osf.apiV2Url(
            self.collections[0].path,
            { query : self.collections[0].pathQuery }
        ));

        self.updateFilesData = function(linkObject) {
            linkObject.link = self.generateLinks(linkObject);
            if (linkObject.link !== self.filesData()) {
                self.filesData(linkObject.link);
                self.isLoadedUrl = false; // check if in fact changed
                self.updateBreadcrumbs(linkObject);
            }
        };

        // INFORMATION PANEL
        self.selected = m.prop([]);
        self.updateSelected = function(selectedList){
            selectedList.map(function(item){
                // get information

            });
            self.selected(selectedList);
        };

        // USER FILTER
        self.activeFilter = m.prop(1);
        self.updateFilter = function(filter) {
            self.activeFilter(filter.id);
            var linkObject = new LinkObject(filter.type, filter.data, filter.label);
            self.updateFilesData(linkObject);
        };

        // Refresh the Grid
        self.updateList = function(element){
            if(!self.isLoadedUrl) {
                var el = element || $(self.wrapperSelector).find('.fb-main').get(0);
                m.mount(el,
                    m.component( ProjectOrganizer, {
                        filesData : self.filesData,
                        updateSelected : self.updateSelected,
                        updateFilesData : self.updateFilesData,
                        wrapperSelector : self.wrapperSelector
                        }
                    )
                );
                self.isLoadedUrl = true;
            }
        }.bind(self);

        // BREADCRUMBS
        self.updateBreadcrumbs = function(linkObject){
            var crumb = new Breadcrumb(linkObject.label, linkObject.link, linkObject.type);
            if (linkObject.type === 'collection' || linkObject.type === 'user'){
                self.breadcrumbs([crumb]);
                return;
            }
            if (linkObject.type === 'breadcrumb'){
                self.breadcrumbs().splice(linkObject.index+1, self.breadcrumbs().length-linkObject.index-1);
                return;
            }
            self.breadcrumbs().push(crumb);
        }.bind(self);

        self.generateLinks = function (linkObject) {
            if (linkObject.type === 'collection'){
                return $osf.apiV2Url(linkObject.data.path, {
                        query : linkObject.data.pathQuery
                    }
                );
            }
            else if (linkObject.type === 'breadcrumb') {
                return linkObject.data.url;
            }
            else if (linkObject.type === 'name') {
                return $osf.apiV2Url('users/' + linkObject.data + '/nodes', { query : {'related_counts' : true}});
            }
            else if (linkObject.type === 'tag') {
                return $osf.apiV2Url('nodes/', { query : {'filter[tag]' : linkObject.data , 'related_counts' : true}});
            }
            else if (linkObject.type === 'node') {
                return $osf.apiV2Url('nodes/' + linkObject.data.uid + '/children', { query : { 'related_counts' : true }});
            }
            // If nothing
            throw new Error('Link could not be generated from linkObject data');
        };

    },
    view : function (ctrl) {
        var infoPanel = '';
        var poStyle = 'width : 80%';
        var infoClass = 'btn-default';
        if (ctrl.showInfo()){
            infoPanel = m('.fb-infobar', m.component(Information, { selected : ctrl.selected }));
            poStyle = 'width : 60%';
            infoClass = 'btn-primary';
        }
        return [
            m('.fb-header.m-b-xs', [
                m.component(Breadcrumbs, {
                    data : ctrl.breadcrumbs,
                    updateFilesData : ctrl.updateFilesData
                }),
                m('.fb-buttonRow', [
                    m('button.btn', {
                        'class' : infoClass,
                        onclick : function () {
                            ctrl.showInfo(!ctrl.showInfo());
                        }
                    }, m('.fa.fa-info'))
                ])
            ]),
            m('.fb-sidebar', [
                m.component(Collections, {
                    list : ctrl.collections,
                    activeFilter : ctrl.activeFilter,
                    updateFilter : ctrl.updateFilter
                }),
                m.component(Filters, {
                    activeFilter : ctrl.activeFilter,
                    updateFilter : ctrl.updateFilter,
                    nameFilters : ctrl.nameFilters,
                    tagFilters : ctrl.tagFilters
                })
            ]),
            m('.fb-main', { config: ctrl.updateList, style : poStyle },
                m('#poOrganizer', m('.spinner-loading-wrapper', m('.logo-spin.logo-md')))
            ),
            infoPanel
        ];
    }
};

/**
 * Collections Module.
 * @constructor
 */
var Collections  = {
    view : function (ctrl, args) {
        var selectedCSS;
        return m('.fb-collections', m('ul', [
            args.list.map(function(item){
                selectedCSS = item.id === args.activeFilter() ? '.active' : '';
                return m('li', { className : selectedCSS},
                    m('a', { href : '#', onclick : args.updateFilter.bind(null, item) },  item.label)
                );
            })
        ]));
    }
};

/**
 * Breadcrumbs Module.
 * @constructor
 */

var Breadcrumbs = {
    view : function (ctrl, args) {
        return m('.fb-breadcrumbs', m('ul', [
            args.data().map(function(item, index, array){
                if(index === array.length-1){
                    return m('li',  item.label);
                }
                var linkObject = new LinkObject(item.type, item, item.label, index);

                return m('li',
                    m('a', { href : '#', onclick : args.updateFilesData.bind(null, linkObject)},  item.label),
                    m('i.fa.fa-chevron-right')
                );
            })

        ]));
    }
};

/**
 * Filters Module.
 * @constructor
 */
var Filters = {
    view : function (ctrl, args) {
        var selectedCSS;
        return m('.fb-filters.m-t-lg',
            [
                m('h4', 'Filters'),
                m('', 'Contributors'),
                m('ul', [
                    args.nameFilters.map(function(item, index){
                        selectedCSS = item.id === args.activeFilter() ? '.active' : '';
                        return m('li' + selectedCSS,
                            m('a', { href : '#', onclick : args.updateFilter.bind(null, item)}, item.label)
                        );
                    })
                ]),
                m('', 'Tags'),
                m('ul', [
                    args.tagFilters.map(function(item){
                        selectedCSS = item.id === args.activeFilter() ? '.active' : '';
                        return m('li' + selectedCSS,
                            m('a', { href : '#', onclick : args.updateFilter.bind(null, item)}, item.label)
                        );
                    })
                ])
            ]
        );
    }
};

/**
 * Information Module.
 * @constructor
 */
var Information = {
    view : function (ctrl, args) {
        var template = '';
        if (args.selected().length === 1) {
            var item = args.selected()[0];
            template = m('', [
                m('h4', m('a', { href : item.data.links.html}, item.data.attributes.title)),
                m('p', [
                    m('span', 'Description: '),
                    m('span', item.data.attributes.description)
                ]),
                m('p', [
                    m('span', 'Category: '),
                    m('span', item.data.attributes.category)
                ]),
                m('p', [
                    m('', 'Tags'),
                    item.data.attributes.tags.map(function(tag){
                        return m('span.tag', tag);
                    })
                ]),
                m('p', [
                    m('span', 'Last Modified: '),
                    m('span', item.data.attributes.date_modified)
                ]),
                m('p', [
                    m('span', 'Visibility: '),
                    m('span', item.data.attributes.public ? 'Public' : 'Private')
                ])
            ]);
        }
        if (args.selected().length > 1) {
            template = m('', [ 'There are multiple items: ', args.selected().map(function(item){
                    return m('p', item.data.attributes.title);
                })]);
        }
        return m('.fb-information', template);
    }
};

module.exports = FileBrowser;<|endoftext|>


<commit_before>window.addEventListener('load', function () {
	document.getElementById('fireNetworkBtn').addEventListener('click', fireNetwork);
	document.getElementById('addNonCritReq').addEventListener('click', addNonCriticalRequestHandler);
	document.getElementById('displayRecords').addEventListener('click', getRecords);
	window.addEventListener('network-ready', updatePendingRequestCount);
	document.getElementById('clearHistory').addEventListener('click', clearHistory);
	document.getElementById('fireCriticalReq').addEventListener('click', fireCriticalRequestHandler);
	setInterval(updateChargingStatus, 100);
	updatePendingRequestCount();
	setInterval(updatePendingRequestCount, 100);
	setInterval(updateTotalRequests, 100);
});

var onChrome;

if (navigator.battery) {
	onChrome = false;
} else {
	onChrome = true;
}

function fireNetwork() {
	window.dispatchEvent(new Event('network-ready'));
}

function addNonCriticalRequestHandler() {
	var interval = document.getElementById('nonCritInterval').value;
	var totalTime = document.getElementById('nonCritIntervalLength').value;
	var numAdd = document.getElementById('numNonCritReqAdd').value;

	if (+interval === 0) {
		for (var i = 0; i < numAdd; ++i) {
			addNonCriticalRequest();
		}
	} else {
		var startTime = new Date().getTime();
		var interval = setInterval(function () {
			if (new Date().getTime() - startTime > totalTime * 60 * 1000) {
				clearInterval(interval);
				return;
			}
			addNonCriticalRequest();
		}, interval * 1000);
	}
}

function addNonCriticalRequest() {
	var urlString = document.getElementById('requestURL');
	AL.addNonCriticalRequest(urlString.value, null, function () {
	});
}

function updateChargingStatus() {
	var elem = document.getElementById('isCharging');
	if (elem) {
		if (!onChrome) {
			elem.innerHTML = navigator.battery.charging;
		} else {
			navigator.getBattery().then(function (battery) {
				elem.innerHTML = battery.charging;
			})
		}
	}
}

function fireCriticalRequestHandler() {
	var interval = document.getElementById('critInterval').value;
	var addNonCritBefore = document.getElementById('autoAddNonCritCheck');
	var numAdd = document.getElementById('numNonCritReqAdd').value;

	if (addNonCritBefore.checked === true) {
		for (var i = 0; i < numAdd; ++i) {
			addNonCriticalRequest();
		}
	}

	if (+interval === 0) {
		fireCriticalRequest();
	} else {
		setInterval(fireCriticalRequest, interval * 60 * 1000);
	}
}

function fireCriticalRequest() {
	var urlString = document.getElementById('requestURL');
	AL.ajax(urlString.value, null, function () {
	});
}

function updatePendingRequestCount() {
	var elem = document.getElementById('pendingRequestCount');
	if (elem) {
		elem.innerHTML = AL.getPendingRequests().length;
	}
}

function updateTotalRequests() {
	var elem = document.getElementById('totalRequestCount');
	if (elem) {
		AL.getNextID(function (ID) {
			elem.innerHTML = ID - 1;
		});

	}
}

function getRecords() {
	var elem = document.getElementById('recordsList');
	AL.getHistory(function (records) {
		function requestObject(begin, end, size, origin, id) {
			this.begin = begin;
			this.end = end;
			this.size = size;
			this.origin = origin;
			this.id = id;
		}
		records = [
			new requestObject(26, 14, 5, "1", 1),
			new requestObject(30, 15, 5, "1", 1),
			new requestObject(67, 30, 5, "1", 1),
			new requestObject(48, 24, 5, "1", 1),
			new requestObject(Date.now(), Date.now(), 5, "1", 1),
			new requestObject(Date.now(), Date.now(), 5, "1", 1),
			new requestObject(Date.now(), Date.now(), 5, "1", 1),
			new requestObject(Date.now(), Date.now(), 5, "1", 1),
			new requestObject(Date.now(), Date.now(), 5, "1", 1)
		];
		if (records) {
			var counter = 0;
			var string = [];
			for (var i = Math.max(records.length - 5, 0); i < Math.max(records.length, 0); ++i) {
				string[counter] = records[i].begin - records[i].end;
				++counter;
			}
			elem.innerHTML = string.toString();
		}
		else {
			console.log("Records is null");
		}
	});
}

function clearHistory() {
	AL.clearHistory();
}
<commit_msg>show last 5 latency record<commit_after>window.addEventListener('load', function () {
	document.getElementById('fireNetworkBtn').addEventListener('click', fireNetwork);
	document.getElementById('addNonCritReq').addEventListener('click', addNonCriticalRequestHandler);
	document.getElementById('displayRecords').addEventListener('click', getRecords);
	window.addEventListener('network-ready', updatePendingRequestCount);
	document.getElementById('clearHistory').addEventListener('click', clearHistory);
	document.getElementById('fireCriticalReq').addEventListener('click', fireCriticalRequestHandler);
	setInterval(updateChargingStatus, 100);
	updatePendingRequestCount();
	setInterval(updatePendingRequestCount, 100);
	setInterval(updateTotalRequests, 100);
});

var onChrome;

if (navigator.battery) {
	onChrome = false;
} else {
	onChrome = true;
}

function fireNetwork() {
	window.dispatchEvent(new Event('network-ready'));
}

function addNonCriticalRequestHandler() {
	var interval = document.getElementById('nonCritInterval').value;
	var totalTime = document.getElementById('nonCritIntervalLength').value;
	var numAdd = document.getElementById('numNonCritReqAdd').value;

	if (+interval === 0) {
		for (var i = 0; i < numAdd; ++i) {
			addNonCriticalRequest();
		}
	} else {
		var startTime = new Date().getTime();
		var interval = setInterval(function () {
			if (new Date().getTime() - startTime > totalTime * 60 * 1000) {
				clearInterval(interval);
				return;
			}
			addNonCriticalRequest();
		}, interval * 1000);
	}
}

function addNonCriticalRequest() {
	var urlString = document.getElementById('requestURL');
	AL.addNonCriticalRequest(urlString.value, null, function () {
	});
}

function updateChargingStatus() {
	var elem = document.getElementById('isCharging');
	if (elem) {
		if (!onChrome) {
			elem.innerHTML = navigator.battery.charging;
		} else {
			navigator.getBattery().then(function (battery) {
				elem.innerHTML = battery.charging;
			})
		}
	}
}

function fireCriticalRequestHandler() {
	var interval = document.getElementById('critInterval').value;
	var addNonCritBefore = document.getElementById('autoAddNonCritCheck');
	var numAdd = document.getElementById('numNonCritReqAdd').value;

	if (addNonCritBefore.checked === true) {
		for (var i = 0; i < numAdd; ++i) {
			addNonCriticalRequest();
		}
	}

	if (+interval === 0) {
		fireCriticalRequest();
	} else {
		setInterval(fireCriticalRequest, interval * 60 * 1000);
	}
}

function fireCriticalRequest() {
	var urlString = document.getElementById('requestURL');
	AL.ajax(urlString.value, null, function () {
	});
}

function updatePendingRequestCount() {
	var elem = document.getElementById('pendingRequestCount');
	if (elem) {
		elem.innerHTML = AL.getPendingRequests().length;
	}
}

function updateTotalRequests() {
	var elem = document.getElementById('totalRequestCount');
	if (elem) {
		AL.getNextID(function (ID) {
			elem.innerHTML = ID - 1;
		});

	}
}

function getRecords() {
	var elem = document.getElementById('recordsList');
	AL.getHistory(function (records) {
		if (records) {
			var counter = 0;
			var string = [];
			for (var i = Math.max(records.length - 5, 0); i < Math.max(records.length, 0); ++i) {
				string[counter] = records[i].end - records[i].begin;
				++counter;
			}
			elem.innerHTML = string.toString();
		}
		else {
			console.log("Records is null");
		}
	});
}

function clearHistory() {
	AL.clearHistory();
}

<|endoftext|>