<commit_before>(function(factory){
    "use strict";
    if (typeof define === 'function' && define.amd) {
        define(['jquery','bootstrap-colorpicker'], factory);
    } else if (window.jQuery && !window.jQuery.fn.colorpickerplus) {
        factory(window.jQuery);
    }
}(function($){
	var panelColors = ["#5B0F00","#660000","#783F04","#7F6000","#274E13","#0C343D","#1C4587","#073763","#20124D","#4C1130",
		"#5B0F00","#660000","#783F04","#7F6000","#274E13","#0C343D","#1C4587","#073763","#20124D","#4C1130",
		"#85200C","#990000","#B45F06","#BF9000","#38761D","#134F5C","#1155CC","#0B5394","#351C75","#741B47",
		"#A61C00","#CC0000","#E69138","#F1C232","#6AA84F","#45818E","#3C78D8","#3D85C6","#674EA7","#A64D79",
		"#CC4125","#E06666","#F6B26B","#FFD966","#93C47D","#76A5AF","#6D9EEB","#6FA8DC","#8E7CC3","#C27BA0",
		"#DD7E6B","#EA9999","#F9CB9C","#FFE599","#B6D7A8","#A2C4C9","#A4C2F4","#9FC5E8","#B4A7D6","#D5A6BD",
		"#E6B8AF","#F4CCCC","#FCE5CD","#FFF2CC","#D9EAD3","#D0E0E3","#C9DAF8","#CFE2F3","#D9D2E9","#EAD1DC",
		"#980000","#FF0000","#FF9900","#FFFF00","#00FF00","#00FFFF","#4A86E8","#0000FF","#9900FF","#FF00FF",
		"#000000","#222222","#444444","#666666","#888888","#AAAAAA","#CCCCCC","#DDDDDD","#EEEEEE","#FFFFFF"];
    var storage = window.localStorage;
    var customColors = [];
    if(!!storage) {
        if(!storage.getItem("colorpickerplus_custom_colors")) {
            storage.setItem("colorpickerplus_custom_colors",customColors.join('$'));
        }
        customColors = storage.getItem("colorpickerplus_custom_colors").split('$');
    }
	var ROWS = 9;
	var CELLS = 10;
    var createColorCell = function(color, cell) {
        if(!cell) {
          cell = $('

');
		}
        if(!!color) {
          cell.data('color', color);
          cell.css('background-color', color);
        } else {
          cell.addClass('colorpicker-color');//alpha
        }
        return cell;
    };
    var ColorpickerEmbed = function(element) {
        var container = $(element);
        var customRows = Math.max(Math.ceil(customColors.length/CELLS), 1);
        var row = null;
        for(var i=0;i<customRows;i++) {
            if(i===customRows-1) {
                row = $('

');
            } else {
                row = $('

');
			}
            for(var j=0;j<CELLS;j++) {
                var cInd = i*CELLS+j;
                var cell = null;
                if(cInd===0) {
                  cell = createColorCell();
                } else {
                    if(cInd<customColors.length) {
                        var c = customColors[cInd];
                        cell = createColorCell(c);
                    } else {
                        cell = $('

');
                    }
                }
                cell.appendTo(row);
            }
            row.appendTo(container);
        }
        for(i=0;i<ROWS;i++) {
            row = null;
            if(i<ROWS-2) {
                row = $('

');
            } else {
			  if(i===ROWS-2) {
			    $('

').appendTo(container);
			  }
                row = $('

');
			}
            for(var jj=0;jj<CELLS;jj++) {
                var cc = panelColors[i*CELLS+jj];
                createColorCell(cc).appendTo(row);
            }
            row.appendTo(container);
        }
        var inputGrp = $('
<input type="text" class="form-control"/><button class="btn btn-default" type="button" title="Custom Color">C</button>
');
        var colorInput = $('input', inputGrp);
        inputGrp.appendTo(container);
        container.on('click.colorpickerplus-container', '.colorcell', $.proxy(this.select, this));
        inputGrp.on('click.colorpickerplus-container', 'button', $.proxy(this.custom, this));
        colorInput.on('changeColor.colorpickerplus-container', $.proxy(this.change, this));
        container.on('click', $.proxy(this.stopPropagation, this));
        colorInput.colorpicker();
        //colorInput.data('colorpicker').picker.on('click touchstart', $.proxy(this.stopPropagation, this));
        this.element = element;
        this.colorInput = colorInput[0];
    };
    ColorpickerEmbed.prototype = {
        constructor: ColorpickerEmbed,
        custom: function() {
			var $element = $(this.element);
            var color = $(this.colorInput).val();
            customColors[customColors.length] = color;
            var cells = $('.nonecell', $element);
            var cell = createColorCell(color, cells.first());
            cell.removeClass('nonecell');
            cell.addClass('colorcell');
            storage.setItem("colorpickerplus_custom_colors",customColors.join('$'));
        },
        select: function(e) {
			var $element = $(this.element);
            var c = $(e.target).data('color');
            if(c==null) {
              $element.trigger('changeColor',[c]);
            } else {
			  var colorInput = $(this.colorInput);
              colorInput.val(c);
              colorInput.colorpicker('setValue', c);
              this.update(c);
            }
            $element.trigger('select',[c]);
            $(this.colorInput).colorpicker('hide');
        },
        change: function(e) {
			var $element = $(this.element);
            e.stopPropagation();
            $element.trigger('changeColor',[e.color.toHex()]);
        },
        update: function(color) {
			var $element = $(this.element);
            var cells = $('.colorcell', $element);
            cells.removeClass('selected');
            if(color!=null) {
			  var colorInput = $(this.colorInput);
              colorInput.val(color);
            }
            cells.each(function(){
                var c = $(this).data('color');
                if(color!=null&&c===color.toUpperCase()) {
                    $(this).addClass('selected');
                    return false;
                }
            });
        },
        stopPropagation:function(e) {
            // if (!e.pageX && !e.pageY && e.originalEvent) {
            //     e.pageX = e.originalEvent.touches[0].pageX;
            //     e.pageY = e.originalEvent.touches[0].pageY;
            // }
			var target = $(e.target);
            if(!target.is('.colorcell')) {
              e.stopPropagation();
              //e.preventDefault();
			}
        }
    };
    $.colorpickerembed = ColorpickerEmbed;

    $.fn.colorpickerembed = function(option) {
        var pickerArgs = arguments;

        return this.each(function() {
            var $this = $(this),
            inst = $this.data('colorpickerembed'),
            options = ((typeof option === 'object') ? option : {});
            if ((!inst) && (typeof option !== 'string')) {
                $this.data('colorpickerembed', new ColorpickerEmbed(this, options));
            } else {
                if (typeof option === 'string') {
                    inst[option].apply(inst, Array.prototype.slice.call(pickerArgs, 1));
                }
            }
        });
    };
    $.fn.colorpickerembed.constructor = ColorpickerEmbed;
    //singleton
    var colorpickerplus;
    var _container;
    var currPicker;
    $(function(){
    	colorpickerplus = $('.colorpickerplus');
    	if(colorpickerplus.length<=0) {
          colorpickerplus = $('

');
    	  colorpickerplus.appendTo($('body'));
    	  //console.log('append singleton to body');
    	}
        _container = $('

').appendTo(colorpickerplus);
        _container.colorpickerembed();
        currPicker = null;
        _container.on('changeColor', function(e, val){
    	  //console.log('color:'+val);
            if(!!currPicker) {
    	  //console.log('color:'+val);
                currPicker.setValue(val);
            }
        });
        _container.on('select', function(){
            if(!!currPicker) {
                // currPicker.setValue(c);
                hide();
            }
        });

    });
    //var embed = _container.data('colorpickerembed');
	/*
    colorpickerplus.on('mouseup.colorpickerplus', function(e) {
		var target = $(e.target);
        if(!target.is('input')) {
			e.stopPropagation();
		}
    });
	*/
    var show = function(picker) {
        _container.data('colorpickerembed').update(picker.getValue());
        currPicker = picker;
        colorpickerplus.show();
        //console.log('show');
    };
    var hide = function() {
        //colorpickerplus.offset({top:0, left:0});
        colorpickerplus.hide();
        currPicker = null;
    };
    var reposition = function(picker) {
	  var $element = $(picker.element);
        var offset = $element.offset();
        //var mx = offset.left+picker.element.outerHeight();
        //var my = offset.top;
        //console.log(picker.element.outerHeight());
        offset.top +=$element.outerHeight();
        colorpickerplus.css(offset);
    };
    var defaults = {};
    var ColorpickerPlus = function(element, options) {
        var $element = $(element);
        this.options = $.extend({}, defaults, $element.data(), options);
        var input = $element.is('input') ? $element : (this.options.input ?
            $element.find(this.options.input) : false);
        if (input && (input.length === 0)) {
            input = false;
        }
        if (input !== false) {
            $element.on('focus', $.proxy(this.show, this));
			this.input = input[0];
            // $element.on({
            //     'focusout.colorpickerplus': $.proxy(this.hide, this)
            // });
        }

        if ((input === false)) {
            $element.on('click', $.proxy(this.show, this));
        }
		this.element = element;
        // $($.proxy(function() {
        //     $element.trigger('create');
        // }, this));
    };
    ColorpickerPlus.version = '0.1.0';
    ColorpickerPlus.prototype = {
        constructor: ColorpickerPlus,
        destroy: function() {
			var $element = $(this.element);
            $element.removeData('colorpickerplus').off('.colorpickerplus');
            if (this.input !== false) {
                $(this.input).off('.colorpickerplus');
            }
            $element.trigger('destroy');
        },
        reposition: function() {
        	reposition(this);
        },
        show: function() {
			var $element = $(this.element);
            this.reposition();
            $(window).on('resize.colorpickerplus', $.proxy(this.reposition, this));
            $(window.document.body).on('mouseup.colorpickerplus', $.proxy(this.hide, this));
            show(this);
            $element.trigger('showPicker',[this.getValue()]);
        },
        hide: function(e) {
			var $element = $(this.element);
			var target = $(e.target);
            var p = target.closest('.colorpicker, .colorpickerplus');
            if(p.length>0||target.is('input')) {return;}
            hide();
            $(window).off('resize.colorpickerplus');
            $(window.document.body).off('mouseup.colorpickerplus');
            $element.trigger('hidePicker',[this.getValue()]);
        },
        setValue: function(val) {
			var $element = $(this.element);
            if(!!val) {
              $element.data('cpp-color', val);
            } else {
              $element.removeData('cpp-color');
            }
            $element.trigger('changeColor',[val]);
        },
        getValue: function(defaultValue) {
			var $element = $(this.element);
            defaultValue = (defaultValue === undefined) ? '#000000' : defaultValue;
            var val;
            if (this.hasInput()) {
                val = $(this.input).val();
            } else {
                val = $element.data('cpp-color');
            }
            if ((val === undefined) || (val === '') || (val === null)) {
                // if not defined or empty, return default
                val = defaultValue;
            }
            return (typeof val==='string')?val.toUpperCase():val;
        },
        hasInput: function() {
            return (this.input !== false);
        }
    };

    $.colorpickerplus = ColorpickerPlus;

    $.fn.colorpickerplus = function(option) {
        var pickerArgs = arguments;

        return this.each(function() {
            var $this = $(this),
            inst = $this.data('colorpickerplus'),
            options = ((typeof option === 'object') ? option : {});
            if ((!inst) && (typeof option !== 'string')) {
                $this.data('colorpickerplus', new ColorpickerPlus(this, options));
            } else {
                if (typeof option === 'string') {
                    inst[option].apply(inst, Array.prototype.slice.call(pickerArgs, 1));
                }
            }
        });
    };

    $.fn.colorpickerplus.constructor = ColorpickerPlus;
}));
<commit_msg>fix colorpicker triggered by non-input<commit_after>(function(factory){
    "use strict";
    if (typeof define === 'function' && define.amd) {
        define(['jquery','bootstrap-colorpicker'], factory);
    } else if (window.jQuery && !window.jQuery.fn.colorpickerplus) {
        factory(window.jQuery);
    }
}(function($){
	var panelColors = ["#5B0F00","#660000","#783F04","#7F6000","#274E13","#0C343D","#1C4587","#073763","#20124D","#4C1130",
		"#5B0F00","#660000","#783F04","#7F6000","#274E13","#0C343D","#1C4587","#073763","#20124D","#4C1130",
		"#85200C","#990000","#B45F06","#BF9000","#38761D","#134F5C","#1155CC","#0B5394","#351C75","#741B47",
		"#A61C00","#CC0000","#E69138","#F1C232","#6AA84F","#45818E","#3C78D8","#3D85C6","#674EA7","#A64D79",
		"#CC4125","#E06666","#F6B26B","#FFD966","#93C47D","#76A5AF","#6D9EEB","#6FA8DC","#8E7CC3","#C27BA0",
		"#DD7E6B","#EA9999","#F9CB9C","#FFE599","#B6D7A8","#A2C4C9","#A4C2F4","#9FC5E8","#B4A7D6","#D5A6BD",
		"#E6B8AF","#F4CCCC","#FCE5CD","#FFF2CC","#D9EAD3","#D0E0E3","#C9DAF8","#CFE2F3","#D9D2E9","#EAD1DC",
		"#980000","#FF0000","#FF9900","#FFFF00","#00FF00","#00FFFF","#4A86E8","#0000FF","#9900FF","#FF00FF",
		"#000000","#222222","#444444","#666666","#888888","#AAAAAA","#CCCCCC","#DDDDDD","#EEEEEE","#FFFFFF"];
    var storage = window.localStorage;
    var customColors = [];
    if(!!storage) {
        if(!storage.getItem("colorpickerplus_custom_colors")) {
            storage.setItem("colorpickerplus_custom_colors",customColors.join('$'));
        }
        customColors = storage.getItem("colorpickerplus_custom_colors").split('$');
    }
	var ROWS = 9;
	var CELLS = 10;
    var createColorCell = function(color, cell) {
        if(!cell) {
          cell = $('

');
		}
        if(!!color) {
          cell.data('color', color);
          cell.css('background-color', color);
        } else {
          cell.addClass('colorpicker-color');//alpha
        }
        return cell;
    };
    var ColorpickerEmbed = function(element) {
        var container = $(element);
        var customRows = Math.max(Math.ceil(customColors.length/CELLS), 1);
        var row = null;
        for(var i=0;i<customRows;i++) {
            if(i===customRows-1) {
                row = $('

');
            } else {
                row = $('

');
			}
            for(var j=0;j<CELLS;j++) {
                var cInd = i*CELLS+j;
                var cell = null;
                if(cInd===0) {
                  cell = createColorCell();
                } else {
                    if(cInd<customColors.length) {
                        var c = customColors[cInd];
                        cell = createColorCell(c);
                    } else {
                        cell = $('

');
                    }
                }
                cell.appendTo(row);
            }
            row.appendTo(container);
        }
        for(i=0;i<ROWS;i++) {
            row = null;
            if(i<ROWS-2) {
                row = $('

');
            } else {
			  if(i===ROWS-2) {
			    $('

').appendTo(container);
			  }
                row = $('

');
			}
            for(var jj=0;jj<CELLS;jj++) {
                var cc = panelColors[i*CELLS+jj];
                createColorCell(cc).appendTo(row);
            }
            row.appendTo(container);
        }
        var inputGrp = $('
<input type="text" class="form-control"/><button class="btn btn-default" type="button" title="Custom Color">C</button>
');
        var colorInput = $('input', inputGrp);
        inputGrp.appendTo(container);
        container.on('click.colorpickerplus-container', '.colorcell', $.proxy(this.select, this));
        inputGrp.on('click.colorpickerplus-container', 'button', $.proxy(this.custom, this));
        colorInput.on('changeColor.colorpickerplus-container', $.proxy(this.change, this));
        container.on('click', $.proxy(this.stopPropagation, this));
        colorInput.colorpicker();
        //colorInput.data('colorpicker').picker.on('click touchstart', $.proxy(this.stopPropagation, this));
        this.element = element;
        this.colorInput = colorInput[0];
    };
    ColorpickerEmbed.prototype = {
        constructor: ColorpickerEmbed,
        custom: function() {
			var $element = $(this.element);
            var color = $(this.colorInput).val();
            customColors[customColors.length] = color;
            var cells = $('.nonecell', $element);
            var cell = createColorCell(color, cells.first());
            cell.removeClass('nonecell');
            cell.addClass('colorcell');
            storage.setItem("colorpickerplus_custom_colors",customColors.join('$'));
        },
        select: function(e) {
			var $element = $(this.element);
            var c = $(e.target).data('color');
            if(c==null) {
              $element.trigger('changeColor',[c]);
            } else {
			  var colorInput = $(this.colorInput);
              colorInput.val(c);
              colorInput.colorpicker('setValue', c);
              this.update(c);
            }
            $element.trigger('select',[c]);
            $(this.colorInput).colorpicker('hide');
        },
        change: function(e) {
			var $element = $(this.element);
            e.stopPropagation();
            $element.trigger('changeColor',[e.color.toHex()]);
        },
        update: function(color) {
			var $element = $(this.element);
            var cells = $('.colorcell', $element);
            cells.removeClass('selected');
            if(color!=null) {
			  var colorInput = $(this.colorInput);
              colorInput.val(color);
            }
            cells.each(function(){
                var c = $(this).data('color');
                if(color!=null&&c===color.toUpperCase()) {
                    $(this).addClass('selected');
                    return false;
                }
            });
        },
        stopPropagation:function(e) {
            // if (!e.pageX && !e.pageY && e.originalEvent) {
            //     e.pageX = e.originalEvent.touches[0].pageX;
            //     e.pageY = e.originalEvent.touches[0].pageY;
            // }
			var target = $(e.target);
            if(!target.is('.colorcell')) {
              e.stopPropagation();
              //e.preventDefault();
			}
        }
    };
    $.colorpickerembed = ColorpickerEmbed;

    $.fn.colorpickerembed = function(option) {
        var pickerArgs = arguments;

        return this.each(function() {
            var $this = $(this),
            inst = $this.data('colorpickerembed'),
            options = ((typeof option === 'object') ? option : {});
            if ((!inst) && (typeof option !== 'string')) {
                $this.data('colorpickerembed', new ColorpickerEmbed(this, options));
            } else {
                if (typeof option === 'string') {
                    inst[option].apply(inst, Array.prototype.slice.call(pickerArgs, 1));
                }
            }
        });
    };
    $.fn.colorpickerembed.constructor = ColorpickerEmbed;
    //singleton
    var colorpickerplus;
    var _container;
    var currPicker;
    $(function(){
    	colorpickerplus = $('.colorpickerplus');
    	if(colorpickerplus.length<=0) {
          colorpickerplus = $('

');
    	  colorpickerplus.appendTo($('body'));
    	  //console.log('append singleton to body');
    	}
        _container = $('

').appendTo(colorpickerplus);
        _container.colorpickerembed();
        currPicker = null;
        _container.on('changeColor', function(e, val){
    	  //console.log('color:'+val);
            if(!!currPicker) {
    	  //console.log('color:'+val);
                currPicker.setValue(val);
            }
        });
        _container.on('select', function(){
            if(!!currPicker) {
                // currPicker.setValue(c);
                hide();
            }
        });

    });
    //var embed = _container.data('colorpickerembed');
	/*
    colorpickerplus.on('mouseup.colorpickerplus', function(e) {
		var target = $(e.target);
        if(!target.is('input')) {
			e.stopPropagation();
		}
    });
	*/
    var show = function(picker) {
        _container.data('colorpickerembed').update(picker.getValue());
        currPicker = picker;
        colorpickerplus.show();
        //console.log('show');
    };
    var hide = function() {
        //colorpickerplus.offset({top:0, left:0});
        colorpickerplus.hide();
        currPicker = null;
    };
    var reposition = function(picker) {
	  var $element = $(picker.element);
        var offset = $element.offset();
        //var mx = offset.left+picker.element.outerHeight();
        //var my = offset.top;
        //console.log(picker.element.outerHeight());
        offset.top +=$element.outerHeight();
        colorpickerplus.css(offset);
    };
    var defaults = {};
    var ColorpickerPlus = function(element, options) {
        var $element = $(element);
        this.options = $.extend({}, defaults, $element.data(), options);
        var input = $element.is('input') ? $element : (this.options.input ?
            $element.find(this.options.input) : false);
        if (input && (input.length === 0)) {
            input = false;
        }
        if (input !== false) {
            $element.on('focus', $.proxy(this.show, this));
			this.input = input[0];
            // $element.on({
            //     'focusout.colorpickerplus': $.proxy(this.hide, this)
            // });
        }

        if ((input === false)) {
            $element.on('click', $.proxy(this.show, this));
            this.input = false
        }
		this.element = element;
        // $($.proxy(function() {
        //     $element.trigger('create');
        // }, this));
    };
    ColorpickerPlus.version = '0.1.0';
    ColorpickerPlus.prototype = {
        constructor: ColorpickerPlus,
        destroy: function() {
			var $element = $(this.element);
            $element.removeData('colorpickerplus').off('.colorpickerplus');
            if (this.input !== false) {
                $(this.input).off('.colorpickerplus');
            }
            $element.trigger('destroy');
        },
        reposition: function() {
        	reposition(this);
        },
        show: function() {
			var $element = $(this.element);
            this.reposition();
            $(window).on('resize.colorpickerplus', $.proxy(this.reposition, this));
            $(window.document.body).on('mouseup.colorpickerplus', $.proxy(this.hide, this));
            show(this);
            $element.trigger('showPicker',[this.getValue()]);
        },
        hide: function(e) {
			var $element = $(this.element);
			var target = $(e.target);
            var p = target.closest('.colorpicker, .colorpickerplus');
            if(p.length>0||target.is('input')) {return;}
            hide();
            $(window).off('resize.colorpickerplus');
            $(window.document.body).off('mouseup.colorpickerplus');
            $element.trigger('hidePicker',[this.getValue()]);
        },
        setValue: function(val) {
			var $element = $(this.element);
            if(!!val) {
              $element.data('cpp-color', val);
            } else {
              $element.removeData('cpp-color');
            }
            $element.trigger('changeColor',[val]);
        },
        getValue: function(defaultValue) {
			var $element = $(this.element);
            defaultValue = (defaultValue === undefined) ? '#000000' : defaultValue;
            var val;
            if (this.hasInput()) {
                val = $(this.input).val();
            } else {
                val = $element.data('cpp-color');
            }
            if ((val === undefined) || (val === '') || (val === null)) {
                // if not defined or empty, return default
                val = defaultValue;
            }
            return (typeof val==='string')?val.toUpperCase():val;
        },
        hasInput: function() {
            return (this.input !== false);
        }
    };

    $.colorpickerplus = ColorpickerPlus;

    $.fn.colorpickerplus = function(option) {
        var pickerArgs = arguments;

        return this.each(function() {
            var $this = $(this),
            inst = $this.data('colorpickerplus'),
            options = ((typeof option === 'object') ? option : {});
            if ((!inst) && (typeof option !== 'string')) {
                $this.data('colorpickerplus', new ColorpickerPlus(this, options));
            } else {
                if (typeof option === 'string') {
                    inst[option].apply(inst, Array.prototype.slice.call(pickerArgs, 1));
                }
            }
        });
    };

    $.fn.colorpickerplus.constructor = ColorpickerPlus;
}));
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012-2013 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Part of DataSelection and Filter component
 * Creates a dialog where filter and selection settings can be set.
 * A dataselectionfilter contains 1..n filters, a filter contains 1..n attributefilters.
 * @author Meine Toonen
 */
/**
 * A filter has 1..n attribute filters, which can be added/removed via the gui.
 */
Ext.define ("viewer.components.Filter",{
    extend: "viewer.components.Component",
    attributeCombobox: null,
    attributeStore:null,
    attributeFilters : null,
    id: null,
    container : null,
	leftWidth: 150,
    uniqueList: null,
    config: {
        attributes:null,
        logicOperator:null,
		parentMainContainer:null,
        showList:true,
        parentComponent: null,

    },
    constructor: function(config){
        this.initConfig(config);
        this.id = Ext.id();
		this.attributeFilters = [];
        this.attributeStore = Ext.create('Ext.data.Store', {
            fields: ['id', 'title', 'value'],
            data : this.attributes
        });
        this.attributeCombobox = Ext.create('viewer.components.FlamingoCombobox', {
            fieldLabel: '',
            store: this.attributeStore,
            queryMode: 'local',
            displayField: 'title',
            valueField: 'value',
			width: this.leftWidth,
            listeners: {
                change:{
                    scope: this,
                    fn: this.attributeComboboxChanged
                }
            }
        });
		var attribuutFilter = Ext.create("viewer.components.AttributeFilter",{
            first: true,
            id: this.id,
            number: 1
        });
        this.attributeFilters.push(attribuutFilter);
        var attributeFilterUI = attribuutFilter.getUI();
        attributeFilterUI.add({
			xtype: 'button',
			text : '+',
			width: 20,
			listeners: {
				click:{
					scope: this,
					fn: this.addAttributeFilter
				}
			}
		});
        var firstContainer =  Ext.create('Ext.container.Container', {
			width: 400,
			height: MobileManager.isMobile() ? 30 : 25,
			layout: {
				type: 'hbox',
				align:'stretch'
			},
			items:  [
				this.attributeCombobox,
				attributeFilterUI
			]
		});
		this.container = Ext.create("Ext.container.Container", {
			width: '100%',
			items: [ firstContainer ]
        });
        return this;
    },
    // Called when a new layer is chosen from the upper combobox
    setNewAttributeList : function (list){
        this.attributeStore.loadData(list,false);
        this.attributeCombobox.clearValue();
        this.attributes = list;
    },
    attributeComboboxChanged: function(el,val,prevVal){
        this.uniqueList=[];
        this.setUniqueListOnAttributeFilters([]);
        if (val!=null){
            var applayerAttribute = this.getAppLayerAttributeByName(val);
            if (applayerAttribute && applayerAttribute.defaultValue==="filterList"){
                this.getAttributeUniques(val,applayerAttribute.featureType);
            }
        }
    },
    /**
     * Get the attribute from the selected AppLayer by name.
     */
    getAppLayerAttributeByName: function (name){
        var appLayer = this.parentComponent.appLayer;
        if(appLayer && appLayer.attributes){
            for (var i=0; i < appLayer.attributes.length; i++){
                var attribute = appLayer.attributes[i]
                if (attribute.name===name){
                    return attribute;
                }
            }
        }
        return null;
    },
    getAttributeUniques : function (attributeName,ft){
        var appLayer = this.parentComponent.layerSelector.getValue();
        if(attributeName){
            this.parentMainContainer.setLoading("Laad unieke waardes...");
            Ext.Ajax.request({
                url: actionBeans.unique,
                timeout: 240000,
                scope:this,
                params: {
                    attributes: [attributeName],
                    applicationLayer: appLayer.id,
                    featureType: ft
                },
                success: function ( result, request ) {
                    var res = Ext.JSON.decode(result.responseText);
                    if(res.success){
                        var values = res.uniqueValues;
                        if(res.msg){
                            Ext.MessageBox.alert('Info', res.msg);
                        }
                        this.handleUniqueValues(values);
                    }else{
                        Ext.MessageBox.alert('Foutmelding', "Kan geen unieke waardes ophalen: " + res.msg);
                    }
                },
                failure: function ( result, request) {
                    Ext.MessageBox.alert('Foutmelding', "Kan geen unieke waardes ophalen: " + result.responseText);
                }
            });
        }
    },
    /**
     * Handle the response of the Uniguevalues request.
     */
    handleUniqueValues : function (values){
        values =  this.transformUniqueValuesToStore(values);
        this.uniqueList=values;
        this.setUniqueListOnAttributeFilters(values);
        this.parentMainContainer.setLoading(false);
    },
    /**
     *
     */
    setUniqueListOnAttributeFilters: function(values){
        for (var i=0; i < this.attributeFilters.length; i++){
            this.attributeFilters[i].setUniqueList(values);
        }
    },

    /**
     * Transform the uniquelist response of a object with arrays of strings
     * that points to the string. So it will work for Ext Stores (and comboboxes)
     * @param valueArray A array of values
     */
    transformUniqueValuesToStore : function(values){
        var newValues=[];
        for (var attribute in values){
            for (var i =0; i < values[attribute].length; i++){
                newValues.push({value: values[attribute][i]});
            }
        }
        return newValues;
    },
    //Add a new attributefilter (to expand this filter)
    addAttributeFilter : function (){
        var me = this;
		var filterContainer = Ext.create('Ext.container.Container', {
			width: 400,
			height: MobileManager.isMobile() ? 30 : 25,
			layout: {
				type: 'hbox',
				align:'stretch'
			},
			items:  [
				// left = leftwidth - 50 (or/and combobox of attributefilter)
				{ xtype: 'container', width: (this.leftWidth - 50) }
			]
		});
		var attributeFilter = Ext.create("viewer.components.AttributeFilter",{
            first: false,
            id: this.id,
            number: this.attributeFilters.length + 1
        });
        var attributeFilterUI = attributeFilter.getUI();
        attributeFilterUI.add({
            xtype: 'button',
			text : '-',
			width: 20,
			listeners: {
				click: function() {
					me.removeAttributeFilter(attributeFilter, filterContainer)
				}
			}
        });
		filterContainer.add(attributeFilterUI);
		filterContainer.doLayout();
        this.container.add(filterContainer);
        this.attributeFilters.push(attributeFilter);
        attributeFilter.setUniqueList(this.uniqueList);
        if(this.parentMainContainer) this.parentMainContainer.doLayout();
    },
    removeAttributeFilter : function (attributeFilter, filterContainer){
        for ( var i = 0 ; i < this.attributeFilters.length;i++){
            var af = this.attributeFilters[i];
            if(af == attributeFilter){
                this.attributeFilters.splice(i,1);
            }
        }
		// We have to remove all items from the attribute filter due to some weird Ext bug
		attributeFilter.removeItems();
		this.container.remove(filterContainer.getId());
    },
    getUI : function (){
        return this.container;
    },
    /*
     * Get the cql(like) filter for this filter
     */
    getCQL : function (){
        var cql ="";
        if(this.logicOperator != null){
            cql += " " + this.logicOperator.getValue() + " ";
        }
        cql += "(";
		var attribute = this.attributeCombobox.getValue();
		if(attribute === null) return "";
        for(var i = 0 ; i < this.attributeFilters.length;i++){
            var af = this.attributeFilters[i];
            var type = this.getAttributeType(attribute);
            af.attribute = attribute;
            af.attributeType = type;
            cql += af.getCQL();
        }
        cql+= ")";

        return cql;
    },
    getAttributeType : function (name){
        for(var i = 0 ; i < this.attributes.length ;i++){
            var attr = this.attributes[i];
            if(attr.value == name){
                return attr.type;
            }
        }
        return null;
    },
    getExtComponents: function() {
        return [ this.container.getId() ];
    }
});
<commit_msg>Removed trailing comma<commit_after>/*
 * Copyright (C) 2012-2013 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Part of DataSelection and Filter component
 * Creates a dialog where filter and selection settings can be set.
 * A dataselectionfilter contains 1..n filters, a filter contains 1..n attributefilters.
 * @author Meine Toonen
 */
/**
 * A filter has 1..n attribute filters, which can be added/removed via the gui.
 */
Ext.define ("viewer.components.Filter",{
    extend: "viewer.components.Component",
    attributeCombobox: null,
    attributeStore:null,
    attributeFilters : null,
    id: null,
    container : null,
	leftWidth: 150,
    uniqueList: null,
    config: {
        attributes:null,
        logicOperator:null,
	parentMainContainer:null,
        showList:true,
        parentComponent: null

    },
    constructor: function(config){
        this.initConfig(config);
        this.id = Ext.id();
		this.attributeFilters = [];
        this.attributeStore = Ext.create('Ext.data.Store', {
            fields: ['id', 'title', 'value'],
            data : this.attributes
        });
        this.attributeCombobox = Ext.create('viewer.components.FlamingoCombobox', {
            fieldLabel: '',
            store: this.attributeStore,
            queryMode: 'local',
            displayField: 'title',
            valueField: 'value',
			width: this.leftWidth,
            listeners: {
                change:{
                    scope: this,
                    fn: this.attributeComboboxChanged
                }
            }
        });
		var attribuutFilter = Ext.create("viewer.components.AttributeFilter",{
            first: true,
            id: this.id,
            number: 1
        });
        this.attributeFilters.push(attribuutFilter);
        var attributeFilterUI = attribuutFilter.getUI();
        attributeFilterUI.add({
			xtype: 'button',
			text : '+',
			width: 20,
			listeners: {
				click:{
					scope: this,
					fn: this.addAttributeFilter
				}
			}
		});
        var firstContainer =  Ext.create('Ext.container.Container', {
			width: 400,
			height: MobileManager.isMobile() ? 30 : 25,
			layout: {
				type: 'hbox',
				align:'stretch'
			},
			items:  [
				this.attributeCombobox,
				attributeFilterUI
			]
		});
		this.container = Ext.create("Ext.container.Container", {
			width: '100%',
			items: [ firstContainer ]
        });
        return this;
    },
    // Called when a new layer is chosen from the upper combobox
    setNewAttributeList : function (list){
        this.attributeStore.loadData(list,false);
        this.attributeCombobox.clearValue();
        this.attributes = list;
    },
    attributeComboboxChanged: function(el,val,prevVal){
        this.uniqueList=[];
        this.setUniqueListOnAttributeFilters([]);
        if (val!=null){
            var applayerAttribute = this.getAppLayerAttributeByName(val);
            if (applayerAttribute && applayerAttribute.defaultValue==="filterList"){
                this.getAttributeUniques(val,applayerAttribute.featureType);
            }
        }
    },
    /**
     * Get the attribute from the selected AppLayer by name.
     */
    getAppLayerAttributeByName: function (name){
        var appLayer = this.parentComponent.appLayer;
        if(appLayer && appLayer.attributes){
            for (var i=0; i < appLayer.attributes.length; i++){
                var attribute = appLayer.attributes[i]
                if (attribute.name===name){
                    return attribute;
                }
            }
        }
        return null;
    },
    getAttributeUniques : function (attributeName,ft){
        var appLayer = this.parentComponent.layerSelector.getValue();
        if(attributeName){
            this.parentMainContainer.setLoading("Laad unieke waardes...");
            Ext.Ajax.request({
                url: actionBeans.unique,
                timeout: 240000,
                scope:this,
                params: {
                    attributes: [attributeName],
                    applicationLayer: appLayer.id,
                    featureType: ft
                },
                success: function ( result, request ) {
                    var res = Ext.JSON.decode(result.responseText);
                    if(res.success){
                        var values = res.uniqueValues;
                        if(res.msg){
                            Ext.MessageBox.alert('Info', res.msg);
                        }
                        this.handleUniqueValues(values);
                    }else{
                        Ext.MessageBox.alert('Foutmelding', "Kan geen unieke waardes ophalen: " + res.msg);
                    }
                },
                failure: function ( result, request) {
                    Ext.MessageBox.alert('Foutmelding', "Kan geen unieke waardes ophalen: " + result.responseText);
                }
            });
        }
    },
    /**
     * Handle the response of the Uniguevalues request.
     */
    handleUniqueValues : function (values){
        values =  this.transformUniqueValuesToStore(values);
        this.uniqueList=values;
        this.setUniqueListOnAttributeFilters(values);
        this.parentMainContainer.setLoading(false);
    },
    /**
     *
     */
    setUniqueListOnAttributeFilters: function(values){
        for (var i=0; i < this.attributeFilters.length; i++){
            this.attributeFilters[i].setUniqueList(values);
        }
    },

    /**
     * Transform the uniquelist response of a object with arrays of strings
     * that points to the string. So it will work for Ext Stores (and comboboxes)
     * @param valueArray A array of values
     */
    transformUniqueValuesToStore : function(values){
        var newValues=[];
        for (var attribute in values){
            for (var i =0; i < values[attribute].length; i++){
                newValues.push({value: values[attribute][i]});
            }
        }
        return newValues;
    },
    //Add a new attributefilter (to expand this filter)
    addAttributeFilter : function (){
        var me = this;
		var filterContainer = Ext.create('Ext.container.Container', {
			width: 400,
			height: MobileManager.isMobile() ? 30 : 25,
			layout: {
				type: 'hbox',
				align:'stretch'
			},
			items:  [
				// left = leftwidth - 50 (or/and combobox of attributefilter)
				{ xtype: 'container', width: (this.leftWidth - 50) }
			]
		});
		var attributeFilter = Ext.create("viewer.components.AttributeFilter",{
            first: false,
            id: this.id,
            number: this.attributeFilters.length + 1
        });
        var attributeFilterUI = attributeFilter.getUI();
        attributeFilterUI.add({
            xtype: 'button',
			text : '-',
			width: 20,
			listeners: {
				click: function() {
					me.removeAttributeFilter(attributeFilter, filterContainer)
				}
			}
        });
		filterContainer.add(attributeFilterUI);
		filterContainer.doLayout();
        this.container.add(filterContainer);
        this.attributeFilters.push(attributeFilter);
        attributeFilter.setUniqueList(this.uniqueList);
        if(this.parentMainContainer) this.parentMainContainer.doLayout();
    },
    removeAttributeFilter : function (attributeFilter, filterContainer){
        for ( var i = 0 ; i < this.attributeFilters.length;i++){
            var af = this.attributeFilters[i];
            if(af == attributeFilter){
                this.attributeFilters.splice(i,1);
            }
        }
		// We have to remove all items from the attribute filter due to some weird Ext bug
		attributeFilter.removeItems();
		this.container.remove(filterContainer.getId());
    },
    getUI : function (){
        return this.container;
    },
    /*
     * Get the cql(like) filter for this filter
     */
    getCQL : function (){
        var cql ="";
        if(this.logicOperator != null){
            cql += " " + this.logicOperator.getValue() + " ";
        }
        cql += "(";
		var attribute = this.attributeCombobox.getValue();
		if(attribute === null) return "";
        for(var i = 0 ; i < this.attributeFilters.length;i++){
            var af = this.attributeFilters[i];
            var type = this.getAttributeType(attribute);
            af.attribute = attribute;
            af.attributeType = type;
            cql += af.getCQL();
        }
        cql+= ")";

        return cql;
    },
    getAttributeType : function (name){
        for(var i = 0 ; i < this.attributes.length ;i++){
            var attr = this.attributes[i];
            if(attr.value == name){
                return attr.type;
            }
        }
        return null;
    },
    getExtComponents: function() {
        return [ this.container.getId() ];
    }
});
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import { Link } from 'react-router';
import MainStore from '../stores/main-store.js'
import CookieNotice from './cookie-notice.js';
import BrowserCookies from 'browser-cookies';

class Main extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {};

    this.bindedOnChange = this.onChange.bind(this);
  }

  componentWillMount() {
    MainStore.addChangeListener(this.bindedOnChange);
  }

  componentWillUnmount() {
    MainStore.removeChangeListener(this.bindedOnChange);
  }

  componentDidMount() {
    this.checkAuth();
    this.checkCookieAdviceCookie();
  }

  onChange() {
    this.setState(MainStore.getState());
  }

  displayMenu() {
    return !['/', 'auth'].includes(this.props.location.pathname);
  }

  togglePanel() {
    MainStore.togglePanel();
  }

  async checkAuth() {
    const url = '/api/auth/check';

    const response = await fetch(url, {credentials: 'same-origin'});
    const json = await response.json();

    if (json.username) {
      MainStore.setUser(json.username);
    }
  }

  checkCookieAdviceCookie() {
    if (!BrowserCookies.get('cookie-advice-accepted')) {
      MainStore.showCookieAdvice();
    }
  }

  onAcceptCookie() {
    BrowserCookies.set('cookie-advice-accepted', "yes", {expires: 365});
    MainStore.hideCookieAdvice();
  }

  render() {
    console.log("render main");
    return (

              <Link to="/" className="c-nav__item c-text--loud">

                  {" citylines.co "}
              </Link>
              { this.state.username ?
               {this.state.username}  :
              <Link to="/auth" className="c-nav__item c-nav__item--right"> Ingresar</Link> }

            {this.props.children}

          {this.state.showCookieAdvice && <CookieNotice
            onAccept={this.onAcceptCookie}
            />}

      )
  }
}

export default Main
<commit_msg>Removes console.log<commit_after>import React, {Component} from 'react';
import { Link } from 'react-router';
import MainStore from '../stores/main-store.js'
import CookieNotice from './cookie-notice.js';
import BrowserCookies from 'browser-cookies';

class Main extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {};

    this.bindedOnChange = this.onChange.bind(this);
  }

  componentWillMount() {
    MainStore.addChangeListener(this.bindedOnChange);
  }

  componentWillUnmount() {
    MainStore.removeChangeListener(this.bindedOnChange);
  }

  componentDidMount() {
    this.checkAuth();
    this.checkCookieAdviceCookie();
  }

  onChange() {
    this.setState(MainStore.getState());
  }

  displayMenu() {
    return !['/', 'auth'].includes(this.props.location.pathname);
  }

  togglePanel() {
    MainStore.togglePanel();
  }

  async checkAuth() {
    const url = '/api/auth/check';

    const response = await fetch(url, {credentials: 'same-origin'});
    const json = await response.json();

    if (json.username) {
      MainStore.setUser(json.username);
    }
  }

  checkCookieAdviceCookie() {
    if (!BrowserCookies.get('cookie-advice-accepted')) {
      MainStore.showCookieAdvice();
    }
  }

  onAcceptCookie() {
    BrowserCookies.set('cookie-advice-accepted', "yes", {expires: 365});
    MainStore.hideCookieAdvice();
  }

  render() {
    return (

              <Link to="/" className="c-nav__item c-text--loud">

                  {" citylines.co "}
              </Link>
              { this.state.username ?
               {this.state.username}  :
              <Link to="/auth" className="c-nav__item c-nav__item--right"> Ingresar</Link> }

            {this.props.children}

          {this.state.showCookieAdvice && <CookieNotice
            onAccept={this.onAcceptCookie}
            />}

      )
  }
}

export default Main
<|endoftext|>


<commit_before>/* eslint "require-jsdoc": 0 */
((PWASSEMBLE) => {
  console.log(PWASSEMBLE.TEMPLATE_PREFIX, 'Template loaded:',
      PWASSEMBLE.instance.template);

  function getFeed(url) {
    return fetch(`./feeds?url=${encodeURIComponent(url)}`)
    .then((response) => {
      if (!response.ok) {
        throw Error('Feed fetch error');
      }
      return response.text()
      // Rewrite non-http links and proxy them locally
      .then((raw) => JSON.parse(raw.replace(
          /src=(\\["'])(http:\/\/.*?)(?:\\["'])/g,
          (_, p1, p2) => {
            return `src=${p1}./proxy?url=${encodeURIComponent(p2)}${p1}`;
          })));
    })
    .catch((fetchError) => {
      throw fetchError;
    });
  }

  function getHtml(entries) {
    // Helper function to proxy unsecure HTTP URLs over HTTPS
    const proxyHttps = (url) => /^http:\/\//.test(url) ?
        `./proxy?url=${encodeURIComponent(url)}` : url;
    return Promise.resolve(`
        ${entries.map((entry) => {
          let videos = [];
          return `
              <article ${entry.meta.language ?
                  `lang="${entry.meta.language}"` : ''}>

${entry.title}

                ${entry.enclosures.length ?
                    (entry.enclosures.map((enc) => {
                      if (/^image/.test(enc.type)) {
                        return `

`;
                      } else if (/^video/.test(enc.type)) {
                        videos.push(
                            `<source src="${proxyHttps(enc.url)}"></source>`);
                      }
                      return 0;
                    }).join('') + (videos.length ?
                        `<p><video controls>${videos.join('\n')}</video></p>` :
                        '')
                    ) :
                    ''}
                ${entry.image && entry.image.url ?
                    `<p><img alt="" src="${proxyHttps(entry.image.url)}"></p>` :
                    ''}
                ${entry.description ? // eslint-disable-line no-nested-ternary
                    `<section>${entry.description}</section>` :
                    (entry.summary ?
                        `<section>${entry.summary}</section>` :
                        '')}

Posted on
                    <time datetime="${new Date(entry.date).toISOString()}">
                      ${new Date(entry.date).toLocaleString()}
                    </time>
                    ${entry.author ? `by ${entry.author}` : ''}

`;
        }).join('\n')}`);
  }

  getFeed(PWASSEMBLE.instance.rssFeed)
  .then((entries) => getHtml(entries))
  .then((html) => {
    const container = document.querySelector('#container');
    container.querySelector('main').innerHTML = html;
    const showFallbackImage = (imgErrorEvent) => {
      imgErrorEvent.target.src = `${location.origin}/static/offline.svg`;
    };
    for (let img of container.querySelectorAll('img')) {
      img.addEventListener('error', showFallbackImage);
    }
  })
  .catch((error) => {
    console.log(PWASSEMBLE.TEMPLATE_PREFIX, error);
  });

  if ('PushManager' in window) {
    document.querySelector('nav').appendChild(
        document.querySelector('#pushNotificationsToggle'));
  }
})(window.PWASSEMBLE || {});
<commit_msg>Corrected article HTML in case of feed issues.<commit_after>/* eslint "require-jsdoc": 0 */
((PWASSEMBLE) => {
  console.log(PWASSEMBLE.TEMPLATE_PREFIX, 'Template loaded:',
      PWASSEMBLE.instance.template);

  function getFeed(url) {
    return fetch(`./feeds?url=${encodeURIComponent(url)}`)
    .then((response) => {
      if (!response.ok) {
        throw Error('Feed fetch error');
      }
      return response.text()
      // Rewrite non-http links and proxy them locally
      .then((raw) => JSON.parse(raw.replace(
          /src=(\\["'])(http:\/\/.*?)(?:\\["'])/g,
          (_, p1, p2) => {
            return `src=${p1}./proxy?url=${encodeURIComponent(p2)}${p1}`;
          })));
    })
    .catch((fetchError) => {
      throw fetchError;
    });
  }

  function getHtml(entries) {
    // Helper function to proxy unsecure HTTP URLs over HTTPS
    const proxyHttps = (url) => /^http:\/\//.test(url) ?
        `./proxy?url=${encodeURIComponent(url)}` : url;
    return Promise.resolve(`
        ${entries.map((entry) => {
          let videos = [];
          return `
              <article ${entry.meta.language ?
                  `lang="${entry.meta.language}"` : ''}>

${entry.title}

                ${entry.enclosures.length ?
                    (entry.enclosures.map((enc) => {
                      if (/^image/.test(enc.type)) {
                        return `

`;
                      } else if (/^video/.test(enc.type)) {
                        videos.push(
                            `<source src="${proxyHttps(enc.url)}"></source>`);
                      }
                    }).join('') + (videos.length ?
                        `<p><video controls>${videos.join('\n')}</video></p>` :
                        '')
                    ) :
                    ''}
                ${entry.image && entry.image.url ?
                    `<p><img alt="" src="${proxyHttps(entry.image.url)}"></p>` :
                    ''}
                ${entry.description ? // eslint-disable-line no-nested-ternary
                    `<section>${entry.description}</section>` :
                    (entry.summary ?
                        `<section>${entry.summary}</section>` :
                        '')}

Posted on
                    <time datetime="${new Date(entry.date).toISOString()}">
                      ${new Date(entry.date).toLocaleString()}
                    </time>
                    ${entry.author ? `by ${entry.author}` : ''}

`;
        }).join('\n')}`);
  }

  getFeed(PWASSEMBLE.instance.rssFeed)
  .then((entries) => getHtml(entries))
  .then((html) => {
    const container = document.querySelector('#container');
    container.querySelector('main').innerHTML = html;
    const showFallbackImage = (imgErrorEvent) => {
      imgErrorEvent.target.src = `${location.origin}/static/offline.svg`;
    };
    for (let img of container.querySelectorAll('img')) {
      img.addEventListener('error', showFallbackImage);
    }
  })
  .catch((error) => {
    console.log(PWASSEMBLE.TEMPLATE_PREFIX, error);
  });

  if ('PushManager' in window) {
    document.querySelector('nav').appendChild(
        document.querySelector('#pushNotificationsToggle'));
  }
})(window.PWASSEMBLE || {});
<|endoftext|>


<commit_before>const fs = require('fs');
const imageSize = require('image-size');
const requestImageSize = require('request-image-size');
const covert = require('../../../covert.js');
const cloudinary = require('cloudinary');
cloudinary.config(covert.cloudinary);

/**
* Uploads an image to cloudinary CDN
*
* @param {String} image - Path to image file on server, or direct URL to online image
* @param {Boolean} imageIsLocal - True if `image` is a path on the server, false if `image` is a URL to an online image
*
* @returns {Promise} - URL of image on cloudinary CDN
*/
module.exports = function(image, imageIsLocal){return new Promise((resolve, reject) => {

	let sizeOf = imageIsLocal ? imageSize : requestImageSize;

	let uploadSettings = {
		crop: 'fit',
		format: 'png'
	}

	if(!imageIsLocal && image.includes('res.cloudinary.com/stickers-for-discord/')){
		resolve(image);
		return;
	}

	sizeOf(image, (err, size) => {

		if(err){
			reject(err);
			return;
		}

		if(size.width > 300) uploadSettings.width = 300;
		if(size.height > 300) uploadSettings.height = 300;

		cloudinary.uploader.upload(image, (res, err) => {
			if(err){
				reject(err);
				return;
			}

			resolve(res.secure_url);
			if(imageIsLocal) fs.unlink(image);

		}, uploadSettings);

	});

})}<commit_msg>Fix issue where Node 8.0.0+ wouldn't delete sticker cache files<commit_after>const fs = require('fs');
const imageSize = require('image-size');
const requestImageSize = require('request-image-size');
const covert = require('../../../covert.js');
const cloudinary = require('cloudinary');
cloudinary.config(covert.cloudinary);

/**
* Uploads an image to cloudinary CDN
*
* @param {String} image - Path to image file on server, or direct URL to online image
* @param {Boolean} imageIsLocal - True if `image` is a path on the server, false if `image` is a URL to an online image
*
* @returns {Promise} - URL of image on cloudinary CDN
*/
module.exports = function(image, imageIsLocal){return new Promise((resolve, reject) => {

	let sizeOf = imageIsLocal ? imageSize : requestImageSize;

	let uploadSettings = {
		crop: 'fit',
		format: 'png'
	}

	if(!imageIsLocal && image.includes('res.cloudinary.com/stickers-for-discord/')){
		resolve(image);
		return;
	}

	sizeOf(image, (err, size) => {

		if(err){
			reject(err);
			return;
		}

		if(size.width > 300) uploadSettings.width = 300;
		if(size.height > 300) uploadSettings.height = 300;

		cloudinary.uploader.upload(image, (res, err) => {
			if(err){
				reject(err);
				return;
			}

			resolve(res.secure_url);
			if(imageIsLocal) fs.unlink(image, () => {});

		}, uploadSettings);

	});

})}<|endoftext|>


<commit_before>/* eslint-env jest */

import ReactGA from 'react-ga'

afterEach(() => {
  jest.clearAllMocks()
})

describe('google-analytics tests', () => {
  test('initializes on module load', () => {
    const GA = require('../google-analytics')
    expect(ReactGA.initialize).toHaveBeenCalledWith('UA-24159386-1')
  })
})
<commit_msg>Add more GA tests<commit_after>/* eslint-env jest */

jest.mock('react-ga')

afterEach(() => {
  jest.clearAllMocks()
  jest.resetModules()
})

describe('google-analytics tests', () => {
  test('initializes on module load', () => {
    const ReactGA = require('react-ga').default
    require('../google-analytics').default // eslint-disable-line no-unused-expressions
    expect(ReactGA.initialize).toHaveBeenCalledWith('UA-24159386-1')
  })

  test('does not throw error if ReactGA fails to initialize', () => {
    const ReactGA = require('react-ga').default
    ReactGA.initialize.mockImplementationOnce(() => {
      throw new Error('Bad stuff!')
    })

    // Suppress an expected console error
    jest.spyOn(global.console, 'error')
      .mockImplementationOnce(() => {})

    // This would throw an error if not handled appropriately
    require('../google-analytics').default // eslint-disable-line no-unused-expressions
  })

  test('does not throw error if ReactGA.pageview throws an error', () => {
    const ReactGA = require('react-ga').default
    ReactGA.pageview.mockImplementationOnce(() => {
      throw new Error('Bad pageview stuff!')
    })

    // Suppress an expected console error
    jest.spyOn(global.console, 'error')
      .mockImplementationOnce(() => {})

    // This would throw an error if not handled appropriately
    const GA = require('../google-analytics').default
    GA.pageview()
  })

  test('does not throw error if ReactGA.event throws an error', () => {
    const ReactGA = require('react-ga').default
    ReactGA.event.mockImplementationOnce(() => {
      throw new Error('Bad event stuff!')
    })

    // Suppress an expected console error
    jest.spyOn(global.console, 'error')
      .mockImplementationOnce(() => {})

    // This would throw an error if not handled appropriately
    const GA = require('../google-analytics').default
    GA.event()
  })

  test('a pageview calls ReactGA as expected', () => {
    const ReactGA = require('react-ga').default

    const GA = require('../google-analytics').default
    GA.pageview()

    expect(ReactGA.pageview).toHaveBeenCalled()
  })

  test('an event calls ReactGA as expected', () => {
    const ReactGA = require('react-ga').default

    const GA = require('../google-analytics').default
    GA.event({
      foo: 'bar'
    })

    expect(ReactGA.event).toHaveBeenCalledWith({
      foo: 'bar'
    })
  })
})
<|endoftext|>


<commit_before>'use strict';

define(['angular', 'jquery', 'require'], function(angular, $, require) {

  var app = angular.module('my-app.marketplace.controllers', []);

  app.controller('marketplaceCommonFunctions', ['googleCustomSearchService', 'miscSearchService', 'layoutService', 'marketplaceService',
    'miscService', 'MISC_URLS', '$sessionStorage', '$localStorage','$rootScope', '$scope', '$routeParams', '$timeout', '$location',
    function(googleCustomSearchService, miscSearchService, layoutService, marketplaceService, miscService, MISC_URLS, $sessionStorage,
             $localStorage, $rootScope, $scope, $routeParams, $timeout, $location) {

      var currentThemePrimary = $sessionStorage.portal.theme.materialTheme ? $sessionStorage.portal.theme.materialTheme.primary['500'] : {value: ['0', '0', '0']};
      $scope.primaryColorRgb = 'rgb('+ currentThemePrimary.value[0] + ',' + currentThemePrimary.value[1] + ',' + currentThemePrimary.value[2] + ')';

      $scope.navToDetails = function(marktetplaceEntry, location) {
        marketplaceService.setFromInfo(location, $scope.searchTerm);
        $location.path("apps/details/"+ marktetplaceEntry.fname);
      };

      $scope.isStatic = function(portlet) {
        return portlet.maxUrl.indexOf('portal') !== -1 //max url is a portal hit
          && portlet.portletName // there is a portletName
          && portlet.portletName.indexOf('cms') != -1; //the portlet is static content portlet
      };

      $scope.getLaunchURL = function(marketplaceEntry) {
        var layoutObj = marketplaceEntry.layoutObject;
        if($rootScope.GuestMode && !marketplaceEntry.hasInLayout) {
          return $scope.loginToAuthPage + '/web/apps/details/'+ marketplaceEntry.fname
        } else if(layoutObj.altMaxUrl == false && (layoutObj.renderOnWeb || $localStorage.webPortletRender)) {
          return 'exclusive/' + layoutObj.fname;
        } else if(layoutObj.altMaxUrl == false && $scope.isStatic(marketplaceEntry)) {
          return 'static/' + layoutObj.fname;
        } else {
          return marketplaceEntry.maxUrl;
        }
      };

      $scope.addToHome = function addToHome(portlet) {
        var fname = portlet.fname;
        var ret = layoutService.addToHome(portlet);
        ret.success(function (request, text){
          $('.fname-'+fname).html(' Added Successfully').prop('disabled',true).removeClass('btn-add').addClass('btn-added');
          $scope.$apply(function(){
            var marketplaceEntries = $.grep($sessionStorage.marketplace, function(e) { return e.fname === portlet.fname});
            if(marketplaceEntries.length > 0) {
              marketplaceEntries[0].hasInLayout = true;
            }
            $rootScope.layout = null; //reset layout due to modifications
            $sessionStorage.layout = null;
          });
        })
          .error(function(request, text, error) {
            $('.fname-'+fname).parent().append('Issue adding to home, please try again later');
          });
      };

      $scope.searchTermFilter = function(portlet) {
        return marketplaceService.portletMatchesSearchTerm(portlet, $scope.searchTerm, {
          searchDescription: true,
          searchKeywords: true,
          defaultReturn : true
        });
      };

      $scope.selectFilter = function (filter,category) {
        $scope.sortParameter = filter;
        $scope.categoryToShow = category;
        $scope.showCategories = false;
        if (filter === 'popular') {
          $scope.selectedFilter = 'popular';
          $scope.sortParameter = ['-rating','-userRated'];
        }
        if (filter === 'az') {
          $scope.selectedFilter = 'az';
          $scope.sortParameter = 'name';
        }
        if (filter === 'category') {
          $scope.selectedFilter = 'category';
          $scope.sortParameter = 'name';
          $scope.showCategories = true;
        }

        miscService.pushGAEvent('Marketplace','Tab Select',filter);

      };

      $scope.slideTabs = function(direction) {
        $scope.tabsPosition = 'start';
        if (direction === 'right') {
          $scope.tabsPosition = 'end';
        }
      };

      $scope.toggleShowAll = function() {
        $scope.showAll = !$scope.showAll;
      };

      this.setupSearchTerm = function() {
        var tempFilterText = '', filterTextTimeout;
        $scope.searchTerm = marketplaceService.getInitialFilter();
        if($routeParams.initFilter !== null && ($scope.searchTerm === null || $scope.searchTerm === "")) {
          $scope.searchTerm = $routeParams.initFilter;
        } else {
          marketplaceService.initialFilter("");
        }
        $scope.searchText = $scope.searchTerm;
        var initFilter = false;
        //delay on the filter
        $scope.$watch('searchText', function (val) {
          if (filterTextTimeout) $timeout.cancel(filterTextTimeout);

          tempFilterText = val;
          filterTextTimeout = $timeout(function() {
            $scope.searchTerm = tempFilterText;
            if(initFilter && $scope.searchTerm) {
              miscService.pushGAEvent('Search','Filter',$scope.searchTerm);
            } else {
              initFilter = true;
            }
          }, 250); // delay 250 ms
        });
      };

      this.initializeConstants = function() {
        //initialize constants
        googleCustomSearchService.getPublicWebSearchURL().then(function(webSearchURL){
          $scope.webSearchUrl = webSearchURL;
        });
        googleCustomSearchService.getDomainResultsLabel().then(function(domainResultsLabel){
          $scope.domainResultsLabel = domainResultsLabel;
        });
        miscSearchService.getKBSearchURL().then(function(kbSearchURL){
          $scope.kbSearchUrl = kbSearchURL;
        });
        miscSearchService.getEventSearchURL().then(function(eventsSearchURL){
          $scope.eventsSearchUrl = eventsSearchURL;
        });
        miscSearchService.getHelpDeskHelpURL().then(function(helpdeskURL){
          $scope.helpdeskUrl = helpdeskURL;
        });
        $scope.directorySearchUrl = MISC_URLS.directorySearchURL;
        $scope.feedbackUrl = MISC_URLS.feedbackURL;
        $scope.loginToAuthPage = MISC_URLS.myuwHome;
      }
    }
  ]);

  var currentPage = 'market';
  var currentCategory = '';

  app.controller('MarketplaceController', [
    '$rootScope','$scope', '$controller', 'marketplaceService',
    function($rootScope, $scope, $controller, marketplaceService) {

      var base = $controller('marketplaceCommonFunctions', { $scope : $scope });

      var init = function(){
        //init variables
        $scope.portlets = [];
        marketplaceService.getPortlets().then(function(data) {
          $scope.portlets = data.portlets;
          $scope.categories = data.categories;
        });

        base.setupSearchTerm();

        //initialize variables

        $scope.searchResultLimit = 20;
        $scope.showAll = $rootScope.GuestMode || false;
        if(currentPage === 'details') {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = "";
          // Default filter is to sort by category for marketplaceDetails back to marketplace
          $scope.selectedFilter = 'category';
          // To sort by category, angular will use name to filter
          $scope.sortParameter = 'name';
          // Show category selection div by default
          $scope.showCategories = true;

          currentPage = 'market';
          if(currentCategory !== '')
            $scope.categoryToShow = currentCategory;
          else
            $scope.categoryToShow = '';
        } else {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = "";
          // Default filter is to sort by popularity
          $scope.selectedFilter = 'popular';
          // To sort by popularity, angular will use portlet.rating to filter
          $scope.sortParameter = ['-rating','-userRated'];
          // Hide category selection div by default
          $scope.showCategories = false;
        }

        base.initializeConstants();
      };

      //run functions
      init();
    } ]);

  app.controller('MarketplaceDetailsController', [
      '$controller', '$scope', '$routeParams', '$mdDialog', 'marketplaceService',
      'SERVICE_LOC',
      function($controller, $scope, $routeParams, $mdDialog, marketplaceService,
               SERVICE_LOC) {

        $controller('marketplaceCommonFunctions', { $scope : $scope });

        $scope.specifyCategory = function(category) {
          currentCategory=category;
          currentPage='details';
        };

        var figureOutBackStuff = function() {
          var fromInfo = marketplaceService.getFromInfo();
          if(fromInfo.term) {
            //from somewhere
            if("Search" === fromInfo.searchOrBrowse && fromInfo.term) {
              //if from search and term is populated, return to search
              $scope.backText = "Search Results for " + fromInfo.term;
              $scope.backURL = "apps/search/" + fromInfo.term;
            } else {
              //assuming from browse
              $scope.backText = "Browse";
              $scope.backURL = "apps/browse/" + fromInfo.term;
            }

            //reset services
            marketplaceService.setFromInfo(undefined,undefined);
          } else {
            //direct hit, will go back to browse
            $scope.backURL="apps";
            $scope.backText="Browse";
          }
        };

        $scope.clickRatingReviewAdmin = function() {
          $mdDialog.show({
            controller: 'MarketplaceRatingReviewAdminController',
            templateUrl: require.toUrl('./partials/rating-review-admin.html'),
            parent: angular.element(document.body),
            scope: $scope,
            preserveScope : true,
            clickOutsideToClose:true,
            fullscreen: false
          });
        };

        // init
        var init = function() {
          $scope.loading = true;
          figureOutBackStuff();
          $scope.obj = [];
          $scope.ratingPrefix = SERVICE_LOC.base +
            SERVICE_LOC.marketplace.base;
          $scope.errorMessage = 'There was an issue loading details, please click back to apps.';
          marketplaceService.getPortlet($routeParams.fname).then(function(result) {
            $scope.loading = false;
            if(!result) {
              $scope.error = true;
              $scope.portlet = null;
            } else {
              $scope.portlet = result;
              $scope.error = false;
            }
          }, function(reason){
            $scope.loading = false;
            $scope.error = true;
          });
        };
        init();
      }]
  );

  app.controller('MarketplaceRatingReviewAdminController', [
    '$scope', 'marketplaceService',
    function($scope, marketplaceService) {
      var init = function(){
        $scope.ratings = [];
        marketplaceService.getAllRatings($scope.portlet.fname).then(function(ratings){
          if(!ratings){
            return;
          }
          $scope.ratings = ratings;
          $scope.average =0;
          $scope.totalReviews = 0;
          angular.forEach(ratings, function(value, key){
            $scope.average+= value.rating;
            if(value.review) {
              $scope.totalReviews += 1;
            }
          });
          $scope.average = Math.round($scope.average / ratings.length);
        })
      };

      init();
    }]);

  return app;

});<commit_msg>Fix spelling error<commit_after>'use strict';

define(['angular', 'jquery', 'require'], function(angular, $, require) {

  var app = angular.module('my-app.marketplace.controllers', []);

  app.controller('marketplaceCommonFunctions', ['googleCustomSearchService', 'miscSearchService', 'layoutService', 'marketplaceService',
    'miscService', 'MISC_URLS', '$sessionStorage', '$localStorage','$rootScope', '$scope', '$routeParams', '$timeout', '$location',
    function(googleCustomSearchService, miscSearchService, layoutService, marketplaceService, miscService, MISC_URLS, $sessionStorage,
             $localStorage, $rootScope, $scope, $routeParams, $timeout, $location) {

      var currentThemePrimary = $sessionStorage.portal.theme.materialTheme ? $sessionStorage.portal.theme.materialTheme.primary['500'] : {value: ['0', '0', '0']};
      $scope.primaryColorRgb = 'rgb('+ currentThemePrimary.value[0] + ',' + currentThemePrimary.value[1] + ',' + currentThemePrimary.value[2] + ')';

      $scope.navToDetails = function(marketplaceEntry, location) {
        marketplaceService.setFromInfo(location, $scope.searchTerm);
        $location.path("apps/details/"+ marketplaceEntry.fname);
      };

      $scope.isStatic = function(portlet) {
        return portlet.maxUrl.indexOf('portal') !== -1 //max url is a portal hit
          && portlet.portletName // there is a portletName
          && portlet.portletName.indexOf('cms') != -1; //the portlet is static content portlet
      };

      $scope.getLaunchURL = function(marketplaceEntry) {
        var layoutObj = marketplaceEntry.layoutObject;
        if($rootScope.GuestMode && !marketplaceEntry.hasInLayout) {
          return $scope.loginToAuthPage + '/web/apps/details/'+ marketplaceEntry.fname
        } else if(layoutObj.altMaxUrl == false && (layoutObj.renderOnWeb || $localStorage.webPortletRender)) {
          return 'exclusive/' + layoutObj.fname;
        } else if(layoutObj.altMaxUrl == false && $scope.isStatic(marketplaceEntry)) {
          return 'static/' + layoutObj.fname;
        } else {
          return marketplaceEntry.maxUrl;
        }
      };

      $scope.addToHome = function addToHome(portlet) {
        var fname = portlet.fname;
        var ret = layoutService.addToHome(portlet);
        ret.success(function (request, text){
          $('.fname-'+fname).html(' Added Successfully').prop('disabled',true).removeClass('btn-add').addClass('btn-added');
          $scope.$apply(function(){
            var marketplaceEntries = $.grep($sessionStorage.marketplace, function(e) { return e.fname === portlet.fname});
            if(marketplaceEntries.length > 0) {
              marketplaceEntries[0].hasInLayout = true;
            }
            $rootScope.layout = null; //reset layout due to modifications
            $sessionStorage.layout = null;
          });
        })
          .error(function(request, text, error) {
            $('.fname-'+fname).parent().append('Issue adding to home, please try again later');
          });
      };

      $scope.searchTermFilter = function(portlet) {
        return marketplaceService.portletMatchesSearchTerm(portlet, $scope.searchTerm, {
          searchDescription: true,
          searchKeywords: true,
          defaultReturn : true
        });
      };

      $scope.selectFilter = function (filter,category) {
        $scope.sortParameter = filter;
        $scope.categoryToShow = category;
        $scope.showCategories = false;
        if (filter === 'popular') {
          $scope.selectedFilter = 'popular';
          $scope.sortParameter = ['-rating','-userRated'];
        }
        if (filter === 'az') {
          $scope.selectedFilter = 'az';
          $scope.sortParameter = 'name';
        }
        if (filter === 'category') {
          $scope.selectedFilter = 'category';
          $scope.sortParameter = 'name';
          $scope.showCategories = true;
        }

        miscService.pushGAEvent('Marketplace','Tab Select',filter);

      };

      $scope.slideTabs = function(direction) {
        $scope.tabsPosition = 'start';
        if (direction === 'right') {
          $scope.tabsPosition = 'end';
        }
      };

      $scope.toggleShowAll = function() {
        $scope.showAll = !$scope.showAll;
      };

      this.setupSearchTerm = function() {
        var tempFilterText = '', filterTextTimeout;
        $scope.searchTerm = marketplaceService.getInitialFilter();
        if($routeParams.initFilter !== null && ($scope.searchTerm === null || $scope.searchTerm === "")) {
          $scope.searchTerm = $routeParams.initFilter;
        } else {
          marketplaceService.initialFilter("");
        }
        $scope.searchText = $scope.searchTerm;
        var initFilter = false;
        //delay on the filter
        $scope.$watch('searchText', function (val) {
          if (filterTextTimeout) $timeout.cancel(filterTextTimeout);

          tempFilterText = val;
          filterTextTimeout = $timeout(function() {
            $scope.searchTerm = tempFilterText;
            if(initFilter && $scope.searchTerm) {
              miscService.pushGAEvent('Search','Filter',$scope.searchTerm);
            } else {
              initFilter = true;
            }
          }, 250); // delay 250 ms
        });
      };

      this.initializeConstants = function() {
        //initialize constants
        googleCustomSearchService.getPublicWebSearchURL().then(function(webSearchURL){
          $scope.webSearchUrl = webSearchURL;
        });
        googleCustomSearchService.getDomainResultsLabel().then(function(domainResultsLabel){
          $scope.domainResultsLabel = domainResultsLabel;
        });
        miscSearchService.getKBSearchURL().then(function(kbSearchURL){
          $scope.kbSearchUrl = kbSearchURL;
        });
        miscSearchService.getEventSearchURL().then(function(eventsSearchURL){
          $scope.eventsSearchUrl = eventsSearchURL;
        });
        miscSearchService.getHelpDeskHelpURL().then(function(helpdeskURL){
          $scope.helpdeskUrl = helpdeskURL;
        });
        $scope.directorySearchUrl = MISC_URLS.directorySearchURL;
        $scope.feedbackUrl = MISC_URLS.feedbackURL;
        $scope.loginToAuthPage = MISC_URLS.myuwHome;
      }
    }
  ]);

  var currentPage = 'market';
  var currentCategory = '';

  app.controller('MarketplaceController', [
    '$rootScope','$scope', '$controller', 'marketplaceService',
    function($rootScope, $scope, $controller, marketplaceService) {

      var base = $controller('marketplaceCommonFunctions', { $scope : $scope });

      var init = function(){
        //init variables
        $scope.portlets = [];
        marketplaceService.getPortlets().then(function(data) {
          $scope.portlets = data.portlets;
          $scope.categories = data.categories;
        });

        base.setupSearchTerm();

        //initialize variables

        $scope.searchResultLimit = 20;
        $scope.showAll = $rootScope.GuestMode || false;
        if(currentPage === 'details') {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = "";
          // Default filter is to sort by category for marketplaceDetails back to marketplace
          $scope.selectedFilter = 'category';
          // To sort by category, angular will use name to filter
          $scope.sortParameter = 'name';
          // Show category selection div by default
          $scope.showCategories = true;

          currentPage = 'market';
          if(currentCategory !== '')
            $scope.categoryToShow = currentCategory;
          else
            $scope.categoryToShow = '';
        } else {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = "";
          // Default filter is to sort by popularity
          $scope.selectedFilter = 'popular';
          // To sort by popularity, angular will use portlet.rating to filter
          $scope.sortParameter = ['-rating','-userRated'];
          // Hide category selection div by default
          $scope.showCategories = false;
        }

        base.initializeConstants();
      };

      //run functions
      init();
    } ]);

  app.controller('MarketplaceDetailsController', [
      '$controller', '$scope', '$routeParams', '$mdDialog', 'marketplaceService',
      'SERVICE_LOC',
      function($controller, $scope, $routeParams, $mdDialog, marketplaceService,
               SERVICE_LOC) {

        $controller('marketplaceCommonFunctions', { $scope : $scope });

        $scope.specifyCategory = function(category) {
          currentCategory=category;
          currentPage='details';
        };

        var figureOutBackStuff = function() {
          var fromInfo = marketplaceService.getFromInfo();
          if(fromInfo.term) {
            //from somewhere
            if("Search" === fromInfo.searchOrBrowse && fromInfo.term) {
              //if from search and term is populated, return to search
              $scope.backText = "Search Results for " + fromInfo.term;
              $scope.backURL = "apps/search/" + fromInfo.term;
            } else {
              //assuming from browse
              $scope.backText = "Browse";
              $scope.backURL = "apps/browse/" + fromInfo.term;
            }

            //reset services
            marketplaceService.setFromInfo(undefined,undefined);
          } else {
            //direct hit, will go back to browse
            $scope.backURL="apps";
            $scope.backText="Browse";
          }
        };

        $scope.clickRatingReviewAdmin = function() {
          $mdDialog.show({
            controller: 'MarketplaceRatingReviewAdminController',
            templateUrl: require.toUrl('./partials/rating-review-admin.html'),
            parent: angular.element(document.body),
            scope: $scope,
            preserveScope : true,
            clickOutsideToClose:true,
            fullscreen: false
          });
        };

        // init
        var init = function() {
          $scope.loading = true;
          figureOutBackStuff();
          $scope.obj = [];
          $scope.ratingPrefix = SERVICE_LOC.base +
            SERVICE_LOC.marketplace.base;
          $scope.errorMessage = 'There was an issue loading details, please click back to apps.';
          marketplaceService.getPortlet($routeParams.fname).then(function(result) {
            $scope.loading = false;
            if(!result) {
              $scope.error = true;
              $scope.portlet = null;
            } else {
              $scope.portlet = result;
              $scope.error = false;
            }
          }, function(reason){
            $scope.loading = false;
            $scope.error = true;
          });
        };
        init();
      }]
  );

  app.controller('MarketplaceRatingReviewAdminController', [
    '$scope', 'marketplaceService',
    function($scope, marketplaceService) {
      var init = function(){
        $scope.ratings = [];
        marketplaceService.getAllRatings($scope.portlet.fname).then(function(ratings){
          if(!ratings){
            return;
          }
          $scope.ratings = ratings;
          $scope.average =0;
          $scope.totalReviews = 0;
          angular.forEach(ratings, function(value, key){
            $scope.average+= value.rating;
            if(value.review) {
              $scope.totalReviews += 1;
            }
          });
          $scope.average = Math.round($scope.average / ratings.length);
        })
      };

      init();
    }]);

  return app;

});<|endoftext|>


<commit_before>// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: {
      dir: require('path').join(__dirname, '../coverage/budgetbutler'),
      reports: ['html', 'lcovonly', 'text-summary'],
      fixWebpackSourcePaths: true
    },
    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};
<commit_msg>added no sandbox for travis<commit_after>// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: {
      dir: require('path').join(__dirname, '../coverage/budgetbutler'),
      reports: ['html', 'lcovonly', 'text-summary'],
      fixWebpackSourcePaths: true
    },
	customLaunchers: {
	    'ChromeHeadless': {
	        base: 'Chrome',
	        flags: [
	            '--headless',
	            '--disable-gpu',
	        ],
	    }
	},
	autoWatch: false,
	browsers: ['ChromeHeadless'],

    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};
<|endoftext|>


<commit_before>define([
        '../Core/defined',
        '../Core/GroundPolylineGeometry',
        '../Scene/GroundPolylinePrimitive'
    ], function(
        defined,
        GroundPolylineGeometry,
        GroundPolylinePrimitive) {
    'use strict';

    function createGroundPolylineGeometry(groundPolylineGeometry, offset) {
        return GroundPolylinePrimitive.initializeTerrainHeights()
            .then(function() {
                if (defined(offset)) {
                    groundPolylineGeometry = GroundPolylineGeometry.unpack(groundPolylineGeometry, offset);
                }
                return GroundPolylineGeometry.createGeometry(groundPolylineGeometry);
            });
    }

    return createGroundPolylineGeometry;
});
<commit_msg>Remove GroundPolylinePrimitive from createGroundPolylineGeometry.<commit_after>define([
        '../Core/ApproximateTerrainHeights',
        '../Core/defined',
        '../Core/GroundPolylineGeometry'
    ], function(
        ApproximateTerrainHeights,
        defined,
        GroundPolylineGeometry) {
    'use strict';

    function createGroundPolylineGeometry(groundPolylineGeometry, offset) {
        return ApproximateTerrainHeights.initialize()
            .then(function() {
                if (defined(offset)) {
                    groundPolylineGeometry = GroundPolylineGeometry.unpack(groundPolylineGeometry, offset);
                }
                return GroundPolylineGeometry.createGeometry(groundPolylineGeometry);
            });
    }

    return createGroundPolylineGeometry;
});
<|endoftext|>


<commit_before>function drawPie(tweets){

  content = [];

  tweets.forEach(function(e) {
    content.push({
      "label": e[0],
      "value": e[1],
      "color": '#'+(Math.random()*0xFFFFFF<<0).toString(16)
    });
  });

  var pie = new d3pie("pieChart", {
    "header": {
      "title": {
        "text": "",
        "fontSize": 24,
        "font": "helvetica"
      },
      "subtitle": {
        "color": "#999999",
        "fontSize": 12,
        "font": "open sans"
      },
      "titleSubtitlePadding": 9
    },
    "footer": {
      "color": "#999999",
      "fontSize": 10,
      "font": "open sans",
      "location": "bottom-left"
    },
    "size": {
      "canvasWidth": 590
    },
    "data": {
      "sortOrder": "value-desc",
      "content": content
    },
    "labels": {
      "outer": {
        "pieDistance": 32
      },
      "inner": {
        "hideWhenLessThanPercentage": 3
      },
      "mainLabel": {
        "fontSize": 11
      },
      "percentage": {
        "color": "#ffffff",
        "decimalPlaces": 0
      },
      "value": {
        "color": "#adadad",
        "fontSize": 11
      },
      "lines": {
        "enabled": true
      }
    },
    "effects": {
      "pullOutSegmentOnClick": {
        "effect": "linear",
        "speed": 400,
        "size": 8
      }
    },
    "misc": {
      "gradient": {
        "enabled": true,
        "percentage": 100
      }
    },
    "callbacks": {}
  });
}<commit_msg>refine pie JS to allow for clickable events<commit_after>function drawPie(tweets){

  content = [];

  tweets.forEach(function(e) {
    content.push({
      "label": e[0],
      "value": e[1],
      "color": '#'+(Math.random()*0xFFFFFF<<0).toString(16)
    });
  });

  var pie = new d3pie("pieChart", {
    "header": {
      "title": {
        "text": "",
        "fontSize": 24,
        "font": "helvetica"
      },
      "subtitle": {
        "color": "#999999",
        "fontSize": 12,
        "font": "open sans"
      },
      "titleSubtitlePadding": 9
    },
    "footer": {
      "color": "#999999",
      "fontSize": 10,
      "font": "open sans",
      "location": "bottom-left"
    },
    "size": {
      "canvasHeight": 700,
      "canvasWidth": 700
    },
    "data": {
      "sortOrder": "value-desc",
      "content": content
    },
    "labels": {
    "outer": {
      "hideWhenLessThanPercentage": 1,
      "pieDistance": 32
    },
    "inner": {
      "hideWhenLessThanPercentage": 3
    },
    "mainLabel": {
      "fontSize": 11
    },
    "percentage": {
      "color": "#ffffff",
      "decimalPlaces": 0
    },
    "value": {
      "color": "#adadad",
      "fontSize": 11
    },
    "lines": {
      "enabled": true
    }
  },
  "effects": {
    "pullOutSegmentOnClick": {
      "effect": "linear",
      "speed": 400,
      "size": 8
    }
  },
  "misc": {
    "gradient": {
      "enabled": true,
      "percentage": 100
    }
  },
  "callbacks": {
    "onClickSegment": function(e){
      window.location.replace('/word/' + e.data.label);
    }
  }
});
}<|endoftext|>


<commit_before>import dotenv from 'dotenv';

dotenv.load();
const CONFIG = {
	keyFile: require.resolve(process.env.GOOGLE_KEYFILE_PATH),
	userId: process.env.USER_ID,
	serviceAcctId: process.env.SERVICE_ACCT_ID,
	calendarUrl: process.env.CALENDAR_URL,
	calendarId: JSON.parse(process.env.CALENDAR_ID),
	telegramBotToken: process.env.TELEGRAM_BOT_TOKEN
};
const ROOM_CONFIG = {
	roomsOpenForBooking: {
		'fg': { 'command': '/book_fgd', 'text': 'Focus Group Room' },
		'qc': { 'command': '/book_queen_combined', 'text': 'Queen Room Combined' },
		'q1': { 'command': '/book_queen_video', 'text': 'Queen (Video)' },
		'q2': { 'command': '/book_queen_projector', 'text': 'Queen (Projector)' }
	},
	roomsListing: {						// used for insert, reading & displaying event room info
		'primary': { name: 'Open Space', id: 'primary' },
		'fg': { name: 'Focus Group Room', id: 'fg', colour: 5 },
		'q1': { name: 'Queen (Video)', id: 'q1', colour: 6 },
		'q2': { name: 'Queen (Projector)', id: 'q2', colour: 10 },
		'qc': { name: 'Queen (Combined)', id: 'qc', children: ['q1', 'q2'], colour: 11 },
		'dr': { name: 'Drone', id: 'dr', colour: 7 },
		'bb': { name: 'Bumblebee', id: 'bb', colour: 3 }
	}
};
const SESSION_LENGTH = 1000 * 60 * 3;
const BOOKING_DURATION_OPTIONS = {		// for displaying selected duration options during booking
	1: '30 mins',
	2: '1 hour',
	3: '1.5 hours',
	4: '2 hours',
	5: '2.5 hours',
	6: '3 hours',
	7: '3.5 hours',
	8: '4 hours'
};

export { CONFIG as default, ROOM_CONFIG, SESSION_LENGTH, BOOKING_DURATION_OPTIONS };
<commit_msg>Removed unused USER_ID var in config<commit_after>import dotenv from 'dotenv';

dotenv.load();
const CONFIG = {
	keyFile: require.resolve(process.env.GOOGLE_KEYFILE_PATH),
	serviceAcctId: process.env.SERVICE_ACCT_ID,
	calendarUrl: process.env.CALENDAR_URL,
	calendarId: JSON.parse(process.env.CALENDAR_ID),
	telegramBotToken: process.env.TELEGRAM_BOT_TOKEN
};
const ROOM_CONFIG = {
	roomsOpenForBooking: {
		'fg': { 'command': '/book_fgd', 'text': 'Focus Group Room' },
		'qc': { 'command': '/book_queen_combined', 'text': 'Queen Room Combined' },
		'q1': { 'command': '/book_queen_video', 'text': 'Queen (Video)' },
		'q2': { 'command': '/book_queen_projector', 'text': 'Queen (Projector)' }
	},
	roomsListing: {						// used for insert, reading & displaying event room info
		'primary': { name: 'Open Space', id: 'primary' },
		'fg': { name: 'Focus Group Room', id: 'fg', colour: 5 },
		'q1': { name: 'Queen (Video)', id: 'q1', colour: 6 },
		'q2': { name: 'Queen (Projector)', id: 'q2', colour: 10 },
		'qc': { name: 'Queen (Combined)', id: 'qc', children: ['q1', 'q2'], colour: 11 },
		'dr': { name: 'Drone', id: 'dr', colour: 7 },
		'bb': { name: 'Bumblebee', id: 'bb', colour: 3 }
	}
};
const SESSION_LENGTH = 1000 * 60 * 3;
const BOOKING_DURATION_OPTIONS = {		// for displaying selected duration options during booking
	1: '30 mins',
	2: '1 hour',
	3: '1.5 hours',
	4: '2 hours',
	5: '2.5 hours',
	6: '3 hours',
	7: '3.5 hours',
	8: '4 hours'
};

export { CONFIG as default, ROOM_CONFIG, SESSION_LENGTH, BOOKING_DURATION_OPTIONS };
<|endoftext|>