<commit_before>/*
 * grunt-protractor-runner
 * https://github.com/teerapap/grunt-protractor-runner
 *
 * Copyright (c) 2013 Teerapap Changwichukarn
 * Licensed under the MIT license.
 */

'use strict';

var util = require('util');
var path = require('path');
var fs = require('fs');
var split = require('split');
var through2 = require('through2');

module.exports = function(grunt) {

  grunt.registerMultiTask('protractor', 'A grunt task to run protractor.', function() {

    // '.../node_modules/protractor/lib/protractor.js'
    var protractorMainPath = require.resolve('protractor');
    // '.../node_modules/protractor/bin/protractor'
    var protractorBinPath = path.resolve(protractorMainPath, '../../bin/protractor');
    // '.../node_modules/protractor/referenceConf.js'
    var protractorRefConfPath = path.resolve(protractorMainPath, '../../referenceConf.js');

    // Merge task-specific and/or target-specific options with these defaults.
    var opts = this.options({
      configFile: protractorRefConfPath,
      keepAlive: false,
      noColor: false,
      debug: false,
      nodeBin: 'node',
      args: {},
      output: false
    });

    // configFile is a special property which need not to be in options{} object.
    if (!grunt.util._.isUndefined(this.data.configFile)) {
      opts.configFile = this.data.configFile;
    }

    grunt.verbose.writeln("Options: " + util.inspect(opts));

    var keepAlive = opts['keepAlive'];
    var strArgs = ["seleniumAddress", "seleniumServerJar", "seleniumPort", "baseUrl", "rootElement", "browser", "chromeDriver", "chromeOnly", "directConnect", "sauceUser", "sauceKey", "sauceSeleniumAddress", "framework", "suite"];
    var listArgs = ["specs", "exclude"];
    var boolArgs = ["includeStackTrace", "verbose"];
    var objectArgs = ["params", "capabilities", "cucumberOpts", "mochaOpts"];

    var args = process.execArgv.concat([protractorBinPath, opts.configFile]);
    if (opts.noColor){
      args.push('--no-jasmineNodeOpts.showColors');
    }
    if (!grunt.util._.isUndefined(opts.debug) && opts.debug === true){
      args.splice(1,0,'debug');
    }

    // Iterate over all supported arguments.
    strArgs.forEach(function(a) {
      if (a in opts.args || grunt.option(a)) {
        args.push('--'+a, grunt.option(a) || opts.args[a]);
      }
    });
    listArgs.forEach(function(a) {
      if (a in opts.args || grunt.option(a)) {
        args.push('--'+a,  grunt.option(a) || opts.args[a].join(","));
      }
    });
    boolArgs.forEach(function(a) {
      if (a in opts.args || grunt.option(a)) {
        args.push('--'+a);
      }
    });

    // Convert [object] to --[object].key1 val1 --[object].key2 val2 ....
    objectArgs.forEach(function(a) {
      (function convert(prefix, obj, args) {
        for (var key in obj) {
          var val = obj[key];
          var type = typeof obj[key];
          if (type === "object") {
            if (Array.isArray(val)) {
              // Add duplicates --[object].key val1 --[object].key val2 ...
              for (var i=0;i<val.length;i++) {
                args.push(prefix+"."+key, val[i]);
              }
            } else {
              // Dig deeper
              convert(prefix+"."+key, val, args);
            }
          } else if (type === "undefined" || type === "function") {
            // Skip these types
          } else if (type === "boolean") {
            // Add --[object].key
            args.push(prefix+"."+key);
          } else {
            // Add --[object].key value
            args.push(prefix+"."+key, val);
          }
        }
      })("--" + a, opts.args[a], args);
    });

    grunt.verbose.writeln("Spawn node with arguments: " + args.join(" "));

    // Spawn protractor command
    var done = this.async();
    var child = grunt.util.spawn({
        cmd: opts.nodeBin,
        args: args,
        opts: {
          stdio:'pipe'
        }
      },
      function(error, result, code) {
        if (error) {
          grunt.log.error(String(result));
          if(code === 1 && keepAlive) {
            // Test fails but do not want to stop the grunt process.
            grunt.log.oklns("Test failed but keep the grunt process alive.");
            done();
            done = null;
          } else {
            // Test fails and want to stop the grunt process,
            // or protractor exited with other reason.
            grunt.fail.fatal('protractor exited with code: '+code, 3);
          }
        } else {
          done();
          done = null;
        }
      }
    );
    process.stdin.pipe(child.stdin);
    child.stdout.pipe(process.stdout);
    child.stderr.pipe(process.stderr);

    // Write the result in the output file
    if (!grunt.util._.isUndefined(opts.output) && opts.output !== false) {

      grunt.log.writeln("Output test result to: " + opts.output);

      grunt.file.mkdir(path.dirname(opts.output));

      child.stdout
        .pipe(split())
        .pipe(through2(function (chunk, encoding, callback) {
          if ((/^Using the selenium server at/).test(chunk.toString())) {
            // skip
          }
          else {
            this.push(chunk + '\n');
          }
          callback();
        }))
        .pipe(fs.createWriteStream(opts.output));
    }
  });

};
<commit_msg>pass all grunt args to protractor<commit_after>/*
 * grunt-protractor-runner
 * https://github.com/teerapap/grunt-protractor-runner
 *
 * Copyright (c) 2013 Teerapap Changwichukarn
 * Licensed under the MIT license.
 */

'use strict';

var util = require('util');
var path = require('path');
var fs = require('fs');
var split = require('split');
var through2 = require('through2');

module.exports = function(grunt) {

  grunt.registerMultiTask('protractor', 'A grunt task to run protractor.', function() {

    // '.../node_modules/protractor/lib/protractor.js'
    var protractorMainPath = require.resolve('protractor');
    // '.../node_modules/protractor/bin/protractor'
    var protractorBinPath = path.resolve(protractorMainPath, '../../bin/protractor');
    // '.../node_modules/protractor/referenceConf.js'
    var protractorRefConfPath = path.resolve(protractorMainPath, '../../referenceConf.js');

    // Merge task-specific and/or target-specific options with these defaults.
    var opts = this.options({
      configFile: protractorRefConfPath,
      keepAlive: false,
      noColor: false,
      debug: false,
      nodeBin: 'node',
      args: {},
      output: false
    });

    // configFile is a special property which need not to be in options{} object.
    if (!grunt.util._.isUndefined(this.data.configFile)) {
      opts.configFile = this.data.configFile;
    }

    grunt.verbose.writeln("Options: " + util.inspect(opts));

    var keepAlive = opts['keepAlive'];
    var strArgs = ["seleniumAddress", "seleniumServerJar", "seleniumPort", "baseUrl", "rootElement", "browser", "chromeDriver", "chromeOnly", "directConnect", "sauceUser", "sauceKey", "sauceSeleniumAddress", "framework", "suite"];
    var listArgs = ["specs", "exclude"];
    var boolArgs = ["includeStackTrace", "verbose"];
    var objectArgs = ["params", "capabilities", "cucumberOpts", "mochaOpts"];

    var args = process.execArgv.concat([protractorBinPath, opts.configFile]);
    if (opts.noColor){
      args.push('--no-jasmineNodeOpts.showColors');
    }
    if (!grunt.util._.isUndefined(opts.debug) && opts.debug === true){
      args.splice(1,0,'debug');
    }

    var toAdd = process.argv.slice(3);
    for (var i = 0 ; i<toAdd.length ; i++ ){
      args.push(toAdd[i]);
    }
    console.log('arging the args', args);

    // Iterate over all supported arguments.
    strArgs.forEach(function(a) {
      if (a in opts.args || grunt.option(a)) {
        args.push('--'+a, grunt.option(a) || opts.args[a]);
      }
    });
    listArgs.forEach(function(a) {
      if (a in opts.args || grunt.option(a)) {
        args.push('--'+a,  grunt.option(a) || opts.args[a].join(","));
      }
    });
    boolArgs.forEach(function(a) {
      if (a in opts.args || grunt.option(a)) {
        args.push('--'+a);
      }
    });

    // Convert [object] to --[object].key1 val1 --[object].key2 val2 ....
    objectArgs.forEach(function(a) {
      (function convert(prefix, obj, args) {
        for (var key in obj) {
          var val = obj[key];
          var type = typeof obj[key];
          if (type === "object") {
            if (Array.isArray(val)) {
              // Add duplicates --[object].key val1 --[object].key val2 ...
              for (var i=0;i<val.length;i++) {
                args.push(prefix+"."+key, val[i]);
              }
            } else {
              // Dig deeper
              convert(prefix+"."+key, val, args);
            }
          } else if (type === "undefined" || type === "function") {
            // Skip these types
          } else if (type === "boolean") {
            // Add --[object].key
            args.push(prefix+"."+key);
          } else {
            // Add --[object].key value
            args.push(prefix+"."+key, val);
          }
        }
      })("--" + a, opts.args[a], args);
    });

    grunt.verbose.writeln("Spawn node with arguments: " + args.join(" "));

    // Spawn protractor command
    var done = this.async();
    var child = grunt.util.spawn({
        cmd: opts.nodeBin,
        args: args,
        opts: {
          stdio:'pipe'
        }
      },
      function(error, result, code) {
        if (error) {
          grunt.log.error(String(result));
          if(code === 1 && keepAlive) {
            // Test fails but do not want to stop the grunt process.
            grunt.log.oklns("Test failed but keep the grunt process alive.");
            done();
            done = null;
          } else {
            // Test fails and want to stop the grunt process,
            // or protractor exited with other reason.
            grunt.fail.fatal('protractor exited with code: '+code, 3);
          }
        } else {
          done();
          done = null;
        }
      }
    );
    process.stdin.pipe(child.stdin);
    child.stdout.pipe(process.stdout);
    child.stderr.pipe(process.stderr);

    // Write the result in the output file
    if (!grunt.util._.isUndefined(opts.output) && opts.output !== false) {

      grunt.log.writeln("Output test result to: " + opts.output);

      grunt.file.mkdir(path.dirname(opts.output));

      child.stdout
        .pipe(split())
        .pipe(through2(function (chunk, encoding, callback) {
          if ((/^Using the selenium server at/).test(chunk.toString())) {
            // skip
          }
          else {
            this.push(chunk + '\n');
          }
          callback();
        }))
        .pipe(fs.createWriteStream(opts.output));
    }
  });

};
<|endoftext|>


<commit_before>(function($){
	// This function adds noise to the background-color attribute of an element
	$.fn.noisy = function(options) {
		return this.each(function() {
	 		var canvas = document.createElement('canvas'),
	 		    ctx = canvas.getContext("2d");

	 		var defaults = {
	 			// How many percent of the image that is filled with noise,
	 			//   represented by a number between 0 and 1 inclusive
	 			noise:              1,

	 			// The width and height of the background image in pixels
	 			tileSize:           200,

	 			// An empty string is transparent
	 			backgroundColor:    '',

	 			// The maximum noise particle opacity,
	 			//   represented by a number between 0 and 1 inclusive
	 			maxNoiseOpacity:    20/255,

	 			// A string linking to the image used if there's no canvas support
	 			fallbackImage:      undefined,

	 			// Specifies wheter the particles are grayscale or colorful
	 			monochromatic:      false
	 		};
	 		options = $.extend(defaults, options);

	 		// Use fallback image if canvas isn't supported
	 		if ((options.fallbackImage !== undefined) && !ctx) {
	 			$(this).css('background-image', options.fallbackImage);
	 			return;
	 		}

	 		canvas.width = canvas.height = options.tileSize;
	 		var imgData = ctx.createImageData(canvas.width, canvas.height);

	 		var rand = function(min, max) {
	 			return Math.floor(Math.random()*(max-min)+min);
	 		};

	 		// Add black and white pixels at random positions to the canvas
	 		for (var i = 0; i < options.noise * Math.pow(options.tileSize, 2); i++) {
	 			var x = rand(0, canvas.width),
	 			    y = rand(0, canvas.height),
	 			    index = (x + y * imgData.width) * 4;

	 			if (options.monochromatic) var randColorChannel = rand(0, 255);

	 			imgData.data[index  ] = randColorChannel;                                           // red
	 			imgData.data[index+1] = options.monochromatic ? randColorChannel : rand(0, 255);    // green
	 			imgData.data[index+2] = options.monochromatic ? randColorChannel : rand(0, 255);    // blue
	 			imgData.data[index+3] = rand(0, 255*options.maxNoiseOpacity);                       // alpha
	 		}

	 		ctx.putImageData(imgData, 0, 0);
	 		$(this).css('background', 'url(' + canvas.toDataURL('image/png') + ')' + options.backgroundColor);
		});
	};
})(jQuery);<commit_msg>Moved defaults out of the private variable<commit_after>(function($){
	// This function adds noise to the background-color attribute of an element
	$.fn.noisy = function(options) {
		return this.each(function() {
	 		var canvas = document.createElement('canvas'),
	 		    ctx = canvas.getContext("2d");

	 		options = $.extend({}, $.fn.noisy.defaults, options);

	 		// Use fallback image if canvas isn't supported
	 		if ((options.fallbackImage !== undefined) && !ctx) {
	 			$(this).css('background-image', options.fallbackImage);
	 			return;
	 		}

	 		canvas.width = canvas.height = options.tileSize;
	 		var imgData = ctx.createImageData(canvas.width, canvas.height);

	 		var rand = function(min, max) {
	 			return Math.floor(Math.random()*(max-min)+min);
	 		};

	 		// Add black and white pixels at random positions to the canvas
	 		for (var i = 0; i < options.noise * Math.pow(options.tileSize, 2); i++) {
	 			var x = rand(0, canvas.width),
	 			    y = rand(0, canvas.height),
	 			    index = (x + y * imgData.width) * 4;

	 			if (options.monochromatic) var randColorChannel = rand(0, 255);

	 			imgData.data[index  ] = randColorChannel;                                           // red
	 			imgData.data[index+1] = options.monochromatic ? randColorChannel : rand(0, 255);    // green
	 			imgData.data[index+2] = options.monochromatic ? randColorChannel : rand(0, 255);    // blue
	 			imgData.data[index+3] = rand(0, 255*options.maxNoiseOpacity);                       // alpha
	 		}

	 		ctx.putImageData(imgData, 0, 0);
	 		$(this).css('background', 'url(' + canvas.toDataURL('image/png') + ')' + options.backgroundColor);
		});
	};

	$.fn.noisy.defaults = {
		// How many percent of the image that is filled with noise,
		//   represented by a number between 0 and 1 inclusive
		noise:              1,

		// The width and height of the background image in pixels
		tileSize:           200,

		// An empty string is transparent
		backgroundColor:    '',

		// The maximum noise particle opacity,
		//   represented by a number between 0 and 1 inclusive
		maxNoiseOpacity:    20/255,

		// A string linking to the image used if there's no canvas support
		fallbackImage:      undefined,

		// Specifies wheter the particles are grayscale or colorful
		monochromatic:      false
	};
})(jQuery);<|endoftext|>


<commit_before>var csv_migrations_select2 = csv_migrations_select2 || {};

(function ($) {
    /**
     * Select2 Logic.
     */
    function Select2()
    {
        //
    }

    /**
     * Setup method.
     *
     * @return {undefined}
     */
    Select2.prototype.setup = function (options) {
        this.min_length = options.hasOwnProperty('min_length') ? options.min_length : 1;
        this.timeout = options.hasOwnProperty('timeout') ? options.timeout : 300;
        this.api_token = options.hasOwnProperty('token') ? options.token : null;
        this.limit = options.hasOwnProperty('limit') ? options.limit : 10;
        this.id = options.hasOwnProperty('id') ? options.id : null;
        this.magicValue = {id: '%%me%%', name: '<< me >>'};

        var that = this;
        // loop through select2 inputs
        $(this.id).each(function () {
            that.init(this);
        });

        // Observe document for added select2(s)
        dom_observer.added(document, function (nodes) {
            $(nodes).each(function () {
                $(this).find(that.id).each(function () {
                    that.init(this);
                });
            });
        });
    };

    /**
     * Initialize method.
     *
     * @return {undefined}
     */
    Select2.prototype.init = function (element) {
        var that = this;
        var value = $(element).val();

        // set select2 option label, if is empty and the option value is set
        if (value && !$(element).text()) {
            value = Array === value.constructor ? value : [value];
            value.forEach(function (val) {
                that._setDisplayValue(val, element);
            });
        }

        // enable select2 functionality
        this._enable(element);
    };

    /**
     * Method that enables select2 functionality on specified input.
     *
     * @param {string} input select2 input
     * @return {undefined}
     * {@link plugin: https://select2.github.io}
     */
    Select2.prototype._enable = function (input) {
        var that = this;
        var placeholder = $(input).attr('title');
        // enable select2
        $(input).select2({
            theme: 'bootstrap',
            width: '100%',
            placeholder: placeholder,
            allowClear: true,
            minimumInputLength: that.min_length,
            escapeMarkup: function (text) {
                return text;
            },
            ajax: {
                url: function() {

                    var connectedField = $(input).data('connected-field') ?? '';
                    var connectedTargetField = $(input).data('connected-target-field') ?? '';
                    var connectedFieldValue = '';
                    if (connectedField != '' && connectedTargetField != '') {
                        connectedFieldValue = '?' + connectedTargetField + '=' + $('#' + connectedField).val();
                    }

                    return $(input).data('url') + connectedFieldValue;
                },
                dataType: 'json',
                contentType: 'application/json',
                accepts: {
                    json: 'application/json'
                },
                delay: that.timeout,
                method: 'get',
                headers: {
                    'Authorization': 'Bearer ' + that.api_token
                },
                data: function (params) {
                    return {
                        query: params.term, // search term
                        page: params.page
                    };
                },
                processResults: function (data, params) {
                    var result = [];
                    $.each(data.data, function (k, v) {
                        result.push({
                            id: k,
                            name: v
                        });
                    });
                    params.page = params.page || 1;

                    if ($(input).data('magic-value')) {
                        result.unshift(that.magicValue);
                    }

                    return {
                        results: result,
                        pagination: {
                            more: (params.page * 10) < data.pagination.count
                        }
                    };
                },
                cache: true
            },
            templateResult: function (data) {
                if (data.loading) {
                    // don't show any text if minimum input legth is 0
                    if (0 === that.min_length) {
                        return;
                    }

                    return data.text;
                }

                return data.name;
            },
            templateSelection: function (data) {
                return data.name || data.text;
            }
        });

        // fix for select2 search not working within bootstrap modals
        // @link https://github.com/select2/select2/issues/1436#issuecomment-21028474
        $.fn.modal.Constructor.prototype.enforceFocus = function () {};
    };

    /**
     * Set and set select2 field label value, based on table's display field.
     *
     * @param {string} id Record id
     * @param {object} input Select2 input
     * @return {undefined}
     */
    Select2.prototype._setDisplayValue = function (id, input) {
        $(input).data('magic-value') && id === this.magicValue.id ?
            this._magicDisplayValue(id, input) :
            this._ajaxDisplayValue(id, input);
    };

    Select2.prototype._magicDisplayValue = function (id, input) {
        $(input).find('option[value="' + id + '"]').remove();

        var option = $('<option selected="selected">' + this.magicValue.name + '</option>').val(id);

        $(input).append(option).trigger('change');
        $(input).trigger('change');
    };

    Select2.prototype._ajaxDisplayValue = function (id, input) {
        var that = this;
        var url = $(input).data('url').replace('/lookup', '/view/' + id);
        $.ajax({
            url: url,
            type: 'get',
            data: { format: 'pretty' },
            dataType: 'json',
            contentType: 'application/json',
            headers: {
                'Authorization': 'Bearer ' + that.api_token
            },
            success: function (data) {
                if (!data.success) {
                    return;
                }
                var label = data.data[$(input).data('display-field')];
                $(input).find('option[value="' + id + '"]').remove();
                var option = $('<option selected="selected">' + label + '</option>').val(id);
                $(input).append(option).trigger('change');
                // set select2 display value
                $(input).trigger('change');
            },
            error: function (jqXHR, textStatus, errorThrown) {
                console.log(jqXHR);
                console.log(textStatus);
                console.log(errorThrown);
            }
        });
    };

    csv_migrations_select2 = new Select2();

})(jQuery);
<commit_msg>Pass selected field name to lookuplistener<commit_after>var csv_migrations_select2 = csv_migrations_select2 || {};

(function ($) {
    /**
     * Select2 Logic.
     */
    function Select2()
    {
        //
    }

    /**
     * Setup method.
     *
     * @return {undefined}
     */
    Select2.prototype.setup = function (options) {
        this.min_length = options.hasOwnProperty('min_length') ? options.min_length : 1;
        this.timeout = options.hasOwnProperty('timeout') ? options.timeout : 300;
        this.api_token = options.hasOwnProperty('token') ? options.token : null;
        this.limit = options.hasOwnProperty('limit') ? options.limit : 10;
        this.id = options.hasOwnProperty('id') ? options.id : null;
        this.magicValue = {id: '%%me%%', name: '<< me >>'};

        var that = this;
        // loop through select2 inputs
        $(this.id).each(function () {
            that.init(this);
        });

        // Observe document for added select2(s)
        dom_observer.added(document, function (nodes) {
            $(nodes).each(function () {
                $(this).find(that.id).each(function () {
                    that.init(this);
                });
            });
        });
    };

    /**
     * Initialize method.
     *
     * @return {undefined}
     */
    Select2.prototype.init = function (element) {
        var that = this;
        var value = $(element).val();

        // set select2 option label, if is empty and the option value is set
        if (value && !$(element).text()) {
            value = Array === value.constructor ? value : [value];
            value.forEach(function (val) {
                that._setDisplayValue(val, element);
            });
        }

        // enable select2 functionality
        this._enable(element);
    };

    /**
     * Method that enables select2 functionality on specified input.
     *
     * @param {string} input select2 input
     * @return {undefined}
     * {@link plugin: https://select2.github.io}
     */
    Select2.prototype._enable = function (input) {
        var that = this;
        var placeholder = $(input).attr('title');
        // enable select2
        $(input).select2({
            theme: 'bootstrap',
            width: '100%',
            placeholder: placeholder,
            allowClear: true,
            minimumInputLength: that.min_length,
            escapeMarkup: function (text) {
                return text;
            },
            ajax: {
                url: function() {

                    var currentFieldName = $(input).attr('field-name');
                    var connectedField = $(input).data('connected-field') ?? '';
                    var connectedTargetField = $(input).data('connected-target-field') ?? '';
                    var connectedFieldValue = '';
                    if (connectedField != '' && connectedTargetField != '') {
                        connectedFieldValue = '?' + connectedTargetField + '=' + $('#' + connectedField).val();
                    }

                    if (connectedFieldValue != '' && currentFieldName != '') {
                        currentFieldName = '&field=' + currentFieldName;
                    } else {
                        currentFieldName = '?field=' + currentFieldName;
                    }

                    return $(input).data('url') + connectedFieldValue + currentFieldName;
                },
                dataType: 'json',
                contentType: 'application/json',
                accepts: {
                    json: 'application/json'
                },
                delay: that.timeout,
                method: 'get',
                headers: {
                    'Authorization': 'Bearer ' + that.api_token
                },
                data: function (params) {
                    return {
                        query: params.term, // search term
                        page: params.page
                    };
                },
                processResults: function (data, params) {
                    var result = [];
                    $.each(data.data, function (k, v) {
                        result.push({
                            id: k,
                            name: v
                        });
                    });
                    params.page = params.page || 1;

                    if ($(input).data('magic-value')) {
                        result.unshift(that.magicValue);
                    }

                    return {
                        results: result,
                        pagination: {
                            more: (params.page * 10) < data.pagination.count
                        }
                    };
                },
                cache: true
            },
            templateResult: function (data) {
                if (data.loading) {
                    // don't show any text if minimum input legth is 0
                    if (0 === that.min_length) {
                        return;
                    }

                    return data.text;
                }

                return data.name;
            },
            templateSelection: function (data) {
                return data.name || data.text;
            }
        });

        // fix for select2 search not working within bootstrap modals
        // @link https://github.com/select2/select2/issues/1436#issuecomment-21028474
        $.fn.modal.Constructor.prototype.enforceFocus = function () {};
    };

    /**
     * Set and set select2 field label value, based on table's display field.
     *
     * @param {string} id Record id
     * @param {object} input Select2 input
     * @return {undefined}
     */
    Select2.prototype._setDisplayValue = function (id, input) {
        $(input).data('magic-value') && id === this.magicValue.id ?
            this._magicDisplayValue(id, input) :
            this._ajaxDisplayValue(id, input);
    };

    Select2.prototype._magicDisplayValue = function (id, input) {
        $(input).find('option[value="' + id + '"]').remove();

        var option = $('<option selected="selected">' + this.magicValue.name + '</option>').val(id);

        $(input).append(option).trigger('change');
        $(input).trigger('change');
    };

    Select2.prototype._ajaxDisplayValue = function (id, input) {
        var that = this;
        var url = $(input).data('url').replace('/lookup', '/view/' + id);
        $.ajax({
            url: url,
            type: 'get',
            data: { format: 'pretty' },
            dataType: 'json',
            contentType: 'application/json',
            headers: {
                'Authorization': 'Bearer ' + that.api_token
            },
            success: function (data) {
                if (!data.success) {
                    return;
                }
                var label = data.data[$(input).data('display-field')];
                $(input).find('option[value="' + id + '"]').remove();
                var option = $('<option selected="selected">' + label + '</option>').val(id);
                $(input).append(option).trigger('change');
                // set select2 display value
                $(input).trigger('change');
            },
            error: function (jqXHR, textStatus, errorThrown) {
                console.log(jqXHR);
                console.log(textStatus);
                console.log(errorThrown);
            }
        });
    };

    csv_migrations_select2 = new Select2();

})(jQuery);
<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Button from 'components/Button';
import Loading from 'components/Loading';
import SearchInput from 'components/Texts/SearchInput';
import Input from 'components/Texts/Input';
import { addEmoji, stringIsEmpty } from 'helpers/stringHelpers';
import { borderRadius, Color, mobileMaxWidth } from 'constants/css';
import { css } from 'emotion';

export default class SectionPanel extends Component {
  static propTypes = {
    canEdit: PropTypes.bool,
    title: PropTypes.string,
    button: PropTypes.node,
    emptyMessage: PropTypes.string,
    inverted: PropTypes.bool,
    isEmpty: PropTypes.bool,
    isSearching: PropTypes.bool,
    headerTheme: PropTypes.object,
    loaded: PropTypes.bool,
    loadMore: PropTypes.func,
    children: PropTypes.node,
    loadMoreButtonShown: PropTypes.bool,
    onEditTitle: PropTypes.func,
    onSearch: PropTypes.func,
    placeholder: PropTypes.string,
    searchPlaceholder: PropTypes.string,
    searchQuery: PropTypes.string,
    style: PropTypes.object
  };

  constructor({ title }) {
    super();
    this.state = {
      loading: false,
      onEdit: false,
      editedTitle: title
    };
  }

  render() {
    const {
      canEdit,
      headerTheme = { color: '#fff', background: Color.logoBlue() },
      inverted,
      title,
      button,
      loadMoreButtonShown,
      onEditTitle,
      onSearch,
      placeholder = 'Enter Title',
      searchPlaceholder,
      searchQuery = '',
      style = {}
    } = this.props;
    const { loading, onEdit, editedTitle } = this.state;
    return (

 header {
            display: grid;
            width: 100%;
            grid-template-areas: 'title search buttons';
            grid-template-columns: auto ${onSearch ? '40%' : 'auto'} auto;
            background: ${inverted
              ? headerTheme.color
              : headerTheme.background};
            color: ${inverted ? headerTheme.background : headerTheme.color};
            border-top-left-radius: ${borderRadius};
            border-top-right-radius: ${borderRadius};
            padding: ${inverted ? '2rem' : '1rem'};
            font-weight: ${inverted ? 'bold' : ''};
            font-size: 2.5rem;
            align-items: center;
          }
          > main {
            position: relative;
            display: flex;
            flex-direction: column;
            padding: 1rem;
            width: 100%;
            justify-content: center;
            min-height: 15rem;
          }
          @media (max-width: ${mobileMaxWidth}) {
            border-radius: 0;
            border: 0;
            > header {
              border-radius: 0;
            }
          }
        `}
      >

            {onEdit ? (
              <Input
                maxLength={100}
                placeholder={placeholder}
                autoFocus
                onChange={text =>
                  this.setState({ editedTitle: addEmoji(text) })
                }
                onKeyPress={event => {
                  if (!stringIsEmpty(editedTitle) && event.key === 'Enter') {
                    this.onChangeTitle(editedTitle);
                  }
                }}
                value={editedTitle}
              />
            ) : (

{title}

            )}
            {canEdit && onEditTitle ? (
              <div
                className={css`
                  &:hover {
                    text-decoration: underline;
                  }
                `}
                style={{
                  color: Color.gray(),
                  fontSize: '1.5rem',
                  marginLeft: onEdit ? '1rem' : '1.5rem',
                  cursor: 'pointer',
                  display: 'flex',
                  fontWeight: 'normal',
                  lineHeight: '1.7rem',
                  alignItems: 'flex-end'
                }}
                onClick={() =>
                  this.setState({ onEdit: !onEdit, editedTitle: title })
                }
              >
                {onEdit ? 'Cancel' : 'Edit'}

            ) : (
              ''
            )}

          {onSearch && (
            <SearchInput
              style={{
                color: Color.black(),
                gridArea: 'search',
                width: '100%',
                justifySelf: 'center',
                zIndex: 0
              }}
              onChange={this.onSearch}
              placeholder={searchPlaceholder}
              value={searchQuery}
            />
          )}

            {button}

          {this.renderContent()}
          {loadMoreButtonShown && (

              <Button
                transparent
                disabled={loading}
                onClick={this.onLoadMore}
                style={{ fontSize: '2rem' }}
              >
                Load More
              </Button>

          )}

    );
  }

  onChangeTitle = async title => {
    const { onEditTitle } = this.props;
    await onEditTitle(title);
    this.setState({ onEdit: false });
  };

  onSearch = text => {
    const { onSearch } = this.props;
    onSearch(text);
  };

  onLoadMore = async() => {
    const { loadMore } = this.props;
    const { loading } = this.state;
    if (!loading) {
      this.setState({ loading: true });
      await loadMore();
      this.setState({ loading: false });
    }
  };

  renderContent = () => {
    const {
      children,
      emptyMessage,
      isEmpty,
      isSearching,
      loaded,
      searchQuery
    } = this.props;
    return loaded ? (
      (!stringIsEmpty(searchQuery) && isSearching) || isEmpty ? (

          {searchQuery && isSearching
            ? 'Searching...'
            : searchQuery
              ? 'No Results'
              : emptyMessage}

      ) : (
        children
      )
    ) : (
      <Loading />
    );
  };

  statusMsg = css`
    font-size: 3rem;
    font-weight: bold;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    position: absolute;
    display: flex;
    justify-content: center;
    align-items: center;
  `;
}
<commit_msg>minor change<commit_after>import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Button from 'components/Button';
import Loading from 'components/Loading';
import SearchInput from 'components/Texts/SearchInput';
import Input from 'components/Texts/Input';
import { addEmoji, stringIsEmpty } from 'helpers/stringHelpers';
import { borderRadius, Color, mobileMaxWidth } from 'constants/css';
import { css } from 'emotion';

export default class SectionPanel extends Component {
  static propTypes = {
    canEdit: PropTypes.bool,
    title: PropTypes.string,
    button: PropTypes.node,
    emptyMessage: PropTypes.string,
    inverted: PropTypes.bool,
    isEmpty: PropTypes.bool,
    isSearching: PropTypes.bool,
    headerTheme: PropTypes.object,
    loaded: PropTypes.bool,
    loadMore: PropTypes.func,
    children: PropTypes.node,
    loadMoreButtonShown: PropTypes.bool,
    onEditTitle: PropTypes.func,
    onSearch: PropTypes.func,
    placeholder: PropTypes.string,
    searchPlaceholder: PropTypes.string,
    searchQuery: PropTypes.string,
    style: PropTypes.object
  };

  constructor({ title }) {
    super();
    this.state = {
      loading: false,
      onEdit: false,
      editedTitle: title
    };
  }

  render() {
    const {
      canEdit,
      headerTheme = { color: '#fff', background: Color.logoBlue() },
      inverted,
      title,
      button,
      loadMoreButtonShown,
      onEditTitle,
      onSearch,
      placeholder = 'Enter Title',
      searchPlaceholder,
      searchQuery = '',
      style = {}
    } = this.props;
    const { loading, onEdit, editedTitle } = this.state;
    return (

 header {
            display: grid;
            width: 100%;
            grid-template-areas: 'title search buttons';
            grid-template-columns: auto ${onSearch ? '40%' : 'auto'} auto;
            background: ${inverted
              ? headerTheme.color
              : headerTheme.background};
            color: ${inverted ? headerTheme.background : headerTheme.color};
            border-top-left-radius: ${borderRadius};
            border-top-right-radius: ${borderRadius};
            padding: 1rem;
            padding-top: ${inverted ? '1.7rem' : '1rem'};
            font-weight: ${inverted ? 'bold' : ''};
            font-size: 2.5rem;
            align-items: center;
          }
          > main {
            position: relative;
            display: flex;
            flex-direction: column;
            padding: 1rem;
            width: 100%;
            justify-content: center;
            min-height: 15rem;
          }
          @media (max-width: ${mobileMaxWidth}) {
            border-radius: 0;
            border: 0;
            > header {
              border-radius: 0;
            }
          }
        `}
      >

            {onEdit ? (
              <Input
                maxLength={100}
                placeholder={placeholder}
                autoFocus
                onChange={text =>
                  this.setState({ editedTitle: addEmoji(text) })
                }
                onKeyPress={event => {
                  if (!stringIsEmpty(editedTitle) && event.key === 'Enter') {
                    this.onChangeTitle(editedTitle);
                  }
                }}
                value={editedTitle}
              />
            ) : (

{title}

            )}
            {canEdit && onEditTitle ? (
              <div
                className={css`
                  &:hover {
                    text-decoration: underline;
                  }
                `}
                style={{
                  color: Color.gray(),
                  fontSize: '1.5rem',
                  marginLeft: onEdit ? '1rem' : '1.5rem',
                  cursor: 'pointer',
                  display: 'flex',
                  fontWeight: 'normal',
                  lineHeight: '1.7rem',
                  alignItems: 'flex-end'
                }}
                onClick={() =>
                  this.setState({ onEdit: !onEdit, editedTitle: title })
                }
              >
                {onEdit ? 'Cancel' : 'Edit'}

            ) : (
              ''
            )}

          {onSearch && (
            <SearchInput
              style={{
                color: Color.black(),
                gridArea: 'search',
                width: '100%',
                justifySelf: 'center',
                zIndex: 0
              }}
              onChange={this.onSearch}
              placeholder={searchPlaceholder}
              value={searchQuery}
            />
          )}

            {button}

          {this.renderContent()}
          {loadMoreButtonShown && (

              <Button
                transparent
                disabled={loading}
                onClick={this.onLoadMore}
                style={{ fontSize: '2rem' }}
              >
                Load More
              </Button>

          )}

    );
  }

  onChangeTitle = async title => {
    const { onEditTitle } = this.props;
    await onEditTitle(title);
    this.setState({ onEdit: false });
  };

  onSearch = text => {
    const { onSearch } = this.props;
    onSearch(text);
  };

  onLoadMore = async() => {
    const { loadMore } = this.props;
    const { loading } = this.state;
    if (!loading) {
      this.setState({ loading: true });
      await loadMore();
      this.setState({ loading: false });
    }
  };

  renderContent = () => {
    const {
      children,
      emptyMessage,
      isEmpty,
      isSearching,
      loaded,
      searchQuery
    } = this.props;
    return loaded ? (
      (!stringIsEmpty(searchQuery) && isSearching) || isEmpty ? (

          {searchQuery && isSearching
            ? 'Searching...'
            : searchQuery
              ? 'No Results'
              : emptyMessage}

      ) : (
        children
      )
    ) : (
      <Loading />
    );
  };

  statusMsg = css`
    font-size: 3rem;
    font-weight: bold;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    position: absolute;
    display: flex;
    justify-content: center;
    align-items: center;
  `;
}
<|endoftext|>


<commit_before>'use strict';
module.exports = function (grunt) {
    grunt.config.merge({
        copy: {
            source: {
                files: [{
                    expand: true,
                    src: [
                        'apps/**/*',
                        'lib/**/*',
                        'conf/**/*',
                        'grunt/tasks/*',
                        'i18n/**/*',
                        'lib/**/*',
                        'Gruntfile.js',
                        '.jshintrc',
                        'bower.json',
                        'package.json'
                    ],
                    dot: true,
                    dest: 'dist/<%= pkg.name %>-<%= pkg.version %>/'
                }]
            },
            dependencies: {
                files: [{
                    expand: true,
                    src: [
                        'node_modules/**/*',
                        'bower_components/**/*'
                    ],
                    dest: 'dist/<%= pkg.name %>-<%= pkg.version %>/'
                }]
            },
            packaging_rpm: {
                files: [{
                    expand: true,
                    src: ['<%= pkg.name %>.spec'],
                    dest: 'dist/'
                }]
            },
            packaging_deb: {
                files: [{
                    expand: true,
                    src: ['debian/**/*'],
                    dest: 'dist/<%= pkg.name %>-<%= pkg.version %>/'
                }]
            }
        }
    });

    grunt.config.merge({
        clean: {
            dist_source: ['dist/<%= pkg.name %>-<%= pkg.version %>/']
        }
    });

    grunt.registerTask('dist:source', 'create a source tarball of the module', function () {
        grunt.task.run('clean:dist_source');
        grunt.util.runPrefixedSubtasksFor('copy', 'source')();
        if (grunt.option('include-dependencies')) {
            grunt.task.run(['checkDependencies:build', 'bower:install']);
            grunt.util.runPrefixedSubtasksFor('copy', 'dependencies')();
        }
        if (grunt.isPeerDependencyInstalled('grunt-contrib-compress') && !grunt.option('no-compress')) {
            grunt.task.run('compress:source');
        } else if (grunt.option('compress') === undefined) {
            grunt.log.warn('grunt-contrib-compress module not installed, will not compress sources');
        } else if (grunt.option('compress') === true) {
            grunt.fail.fatal('grunt-contrib-compress module not installed');
        }
    });

    grunt.registerTask('dist:dependencies', 'create a source tarball of the dependencies of the module', function () {
        grunt.task.run(['clean:dist_source', 'checkDependencies:build', 'bower:install']);
        grunt.util.runPrefixedSubtasksFor('copy', 'dependencies')();
        if (grunt.isPeerDependencyInstalled('grunt-contrib-compress') && !grunt.option('no-compress')) {
            grunt.util.runPrefixedSubtasksFor('compress', 'dependencies')();
        } else if (grunt.option('compress') === undefined) {
            grunt.log.warn('grunt-contrib-compress module not installed, will not compress dependencies');
        } else if (grunt.option('compress') === true) {
            grunt.fail.fatal('grunt-contrib-compress module not installed');
        }
    });

    grunt.config.merge({
        exec: {
            dpkg_source: {
                cmd: 'dpkg-source -Zgzip -b <%= pkg.name %>-<%= pkg.version %>/',
                cwd: 'dist/'
            }
        }
    });

    grunt.registerTask('dist:dpkg-source', 'run dpkg-source to create debian specific packaging information', function () {
        grunt.task.run(['copy:packaging_deb', 'exec:dpkg_source']);
    });

    grunt.registerTask('dist:rpm', 'put everything to build an rpm into dist directory', function () {
        grunt.task.run('copy:packaging_rpm');
    });

    grunt.util.registerDummyTask('exec', 'grunt-exec');
    if (grunt.isPeerDependencyInstalled('grunt-exec')) {
        grunt.loadNpmTasks('grunt-exec');
    }
};
<commit_msg>use bower task directly<commit_after>'use strict';
module.exports = function (grunt) {
    grunt.config.merge({
        copy: {
            source: {
                files: [{
                    expand: true,
                    src: [
                        'apps/**/*',
                        'lib/**/*',
                        'conf/**/*',
                        'grunt/tasks/*',
                        'i18n/**/*',
                        'lib/**/*',
                        'Gruntfile.js',
                        '.jshintrc',
                        'bower.json',
                        'package.json'
                    ],
                    dot: true,
                    dest: 'dist/<%= pkg.name %>-<%= pkg.version %>/'
                }]
            },
            dependencies: {
                files: [{
                    expand: true,
                    src: [
                        'node_modules/**/*',
                        'bower_components/**/*'
                    ],
                    dest: 'dist/<%= pkg.name %>-<%= pkg.version %>/'
                }]
            },
            packaging_rpm: {
                files: [{
                    expand: true,
                    src: ['<%= pkg.name %>.spec'],
                    dest: 'dist/'
                }]
            },
            packaging_deb: {
                files: [{
                    expand: true,
                    src: ['debian/**/*'],
                    dest: 'dist/<%= pkg.name %>-<%= pkg.version %>/'
                }]
            }
        }
    });

    grunt.config.merge({
        clean: {
            dist_source: ['dist/<%= pkg.name %>-<%= pkg.version %>/']
        }
    });

    grunt.registerTask('dist:source', 'create a source tarball of the module', function () {
        grunt.task.run('clean:dist_source');
        grunt.util.runPrefixedSubtasksFor('copy', 'source')();
        if (grunt.option('include-dependencies')) {
            grunt.task.run(['checkDependencies:build', 'checkDependencies:bower']);
            grunt.util.runPrefixedSubtasksFor('copy', 'dependencies')();
        }
        if (grunt.isPeerDependencyInstalled('grunt-contrib-compress') && !grunt.option('no-compress')) {
            grunt.task.run('compress:source');
        } else if (grunt.option('compress') === undefined) {
            grunt.log.warn('grunt-contrib-compress module not installed, will not compress sources');
        } else if (grunt.option('compress') === true) {
            grunt.fail.fatal('grunt-contrib-compress module not installed');
        }
    });

    grunt.registerTask('dist:dependencies', 'create a source tarball of the dependencies of the module', function () {
        grunt.task.run(['clean:dist_source', 'checkDependencies:build', 'bower:install']);
        grunt.util.runPrefixedSubtasksFor('copy', 'dependencies')();
        if (grunt.isPeerDependencyInstalled('grunt-contrib-compress') && !grunt.option('no-compress')) {
            grunt.util.runPrefixedSubtasksFor('compress', 'dependencies')();
        } else if (grunt.option('compress') === undefined) {
            grunt.log.warn('grunt-contrib-compress module not installed, will not compress dependencies');
        } else if (grunt.option('compress') === true) {
            grunt.fail.fatal('grunt-contrib-compress module not installed');
        }
    });

    grunt.config.merge({
        exec: {
            dpkg_source: {
                cmd: 'dpkg-source -Zgzip -b <%= pkg.name %>-<%= pkg.version %>/',
                cwd: 'dist/'
            }
        }
    });

    grunt.registerTask('dist:dpkg-source', 'run dpkg-source to create debian specific packaging information', function () {
        grunt.task.run(['copy:packaging_deb', 'exec:dpkg_source']);
    });

    grunt.registerTask('dist:rpm', 'put everything to build an rpm into dist directory', function () {
        grunt.task.run('copy:packaging_rpm');
    });

    grunt.util.registerDummyTask('exec', 'grunt-exec');
    if (grunt.isPeerDependencyInstalled('grunt-exec')) {
        grunt.loadNpmTasks('grunt-exec');
    }
};
<|endoftext|>


<commit_before>/**
 * FoodCoopShop - The open source software for your foodcoop
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @since         FoodCoopShop 2.5.0
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 * @author        Mario Rothauer <office@foodcoopshop.com>
 * @copyright     Copyright (c) Mario Rothauer, https://www.rothauer-it.com
 * @link          https://www.foodcoopshop.com
 */
foodcoopshop.SelfService = {

    autoLogoutTimer : 180,
    currentLogoutTimer : 0,

    init : function() {
        foodcoopshop.Helper.initLogoutButton(document.location.href);
  	    this.initWindowResize();
        this.initAutoLogout();
        this.initSearchForm();
        this.initDepositPayment();
    },

    initLoginForm : function() {

        var barcodeInputField = $('#barcode');
        barcodeInputField.on('keyup focus', function (e) {
            $(this).prop('type', 'password'); // to avoid autocomplete
        });

        var loginForm = $('#LoginForm');
        formIsSubmitted = false;
        loginForm.on('submit', function(e) {
            if (formIsSubmitted) {
                return false;
            }
            formIsSubmitted = true;
        });

        barcodeInputField.on('keypress', foodcoopshop.Helper.debounce(
            function() {
                foodcoopshop.SelfService.submitForm(loginForm, 'fa-sign-in-alt');
            }, 1000)
        );

        barcodeInputField.focus();

    },

    initDepositPayment : function() {

        foodcoopshop.Helper.changeInputNumberToTextForEdge();

        $('.btn-add-deposit').featherlight(
            foodcoopshop.AppFeatherlight.initLightboxForForms(
                foodcoopshop.Helper.addPaymentFormSave,
                null,
                foodcoopshop.AppFeatherlight.closeLightbox,
                $('#add-payment-deposit-form')
            )
        );

    },

    initSearchForm : function() {

        var searchForm = $('#product-search');

        formIsSubmitted = false;
        searchForm.on('submit', function(e) {
            if (formIsSubmitted) {
                return false;
            }
            formIsSubmitted = true;
        });

        if (!foodcoopshop.Helper.isMobile()) {
            foodcoopshop.Helper.initBootstrapSelect(searchForm);
        }
        searchForm.find('select, input[type="text"]').on('change', function() {
            foodcoopshop.SelfService.submitSearchForm(searchForm);
        });
        searchForm.find('select, input[type="text"]').on('keypress', foodcoopshop.Helper.debounce(
            function() {
                foodcoopshop.SelfService.submitForm(searchForm, 'fa-search');
            }, 1000)
        );

        searchForm.find('input[type="text"]').focus();
    },

    submitForm : function(searchForm, icon) {
        var submitButton = searchForm.find('.btn[type="submit"]');
        foodcoopshop.Helper.addSpinnerToButton(submitButton, icon);
        foodcoopshop.Helper.disableButton(submitButton);
        searchForm.submit();
    },

    initHighlightedProductId: function(productId) {
        var rowId = '#product-wrapper-' + productId;
        $.scrollTo(rowId, 1000, {
            offset: {
                top: -100
            }
        });
        $(rowId).css('background-color', '#f3515c');
        $(rowId).css('color', 'white');
        $(rowId).one('mouseover', function () {
            $(this).removeAttr('style');
        });
        $(rowId).find('.quantity-in-units-input-field-wrapper input').focus();
    },

    initCartErrors: function (cartErrors) {
        cartErrors = $.parseJSON(cartErrors);
        for (var key in cartErrors) {
            var productContainer = $('#cart .product.' + key);
            productContainer.addClass('error');
            productContainer.after('

' + cartErrors[key].join('

') + '

');
        }
    },

    initWindowResize: function () {
        $(window).on('resize', function () {
            foodcoopshop.SelfService.onWindowResize();
        });
        foodcoopshop.SelfService.onWindowResize();
    },

    setFocusToSearchInputField : function() {
        $('#product-search input[name="keyword"]').focus();
    },

    onWindowResize : function() {
        $('.right-box').css('max-height', parseInt($(window).height()));
    },

    initAutoLogout : function() {

        this.resetTimer();
        this.renderTimer();

        $(document).idle({
            startAtIdle : true,
            onActive: function(){
                foodcoopshop.SelfService.resetTimer();
                foodcoopshop.SelfService.renderTimer();
            },
            onIdle: function() {
                foodcoopshop.SelfService.currentLogoutTimer--;
                foodcoopshop.SelfService.renderTimer();
                if (foodcoopshop.SelfService.currentLogoutTimer == 0) {
                    document.location.href = '/' + foodcoopshop.LocalizedJs.helper.routeLogout + '?redirect=' + document.location.href;
                }
            },
            recurIdleCall : true,
            idle: 1000
        });

    },

    resetTimer : function() {
        this.currentLogoutTimer = this.autoLogoutTimer;
    },

    renderTimer : function() {
        $('.auto-logout-timer').html(this.currentLogoutTimer);
    }

};<commit_msg>fixed submit dropdown<commit_after>/**
 * FoodCoopShop - The open source software for your foodcoop
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @since         FoodCoopShop 2.5.0
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 * @author        Mario Rothauer <office@foodcoopshop.com>
 * @copyright     Copyright (c) Mario Rothauer, https://www.rothauer-it.com
 * @link          https://www.foodcoopshop.com
 */
foodcoopshop.SelfService = {

    autoLogoutTimer : 180,
    currentLogoutTimer : 0,

    init : function() {
        foodcoopshop.Helper.initLogoutButton(document.location.href);
  	    this.initWindowResize();
        this.initAutoLogout();
        this.initSearchForm();
        this.initDepositPayment();
    },

    initLoginForm : function() {

        var barcodeInputField = $('#barcode');
        barcodeInputField.on('keyup focus', function (e) {
            $(this).prop('type', 'password'); // to avoid autocomplete
        });

        var loginForm = $('#LoginForm');
        formIsSubmitted = false;
        loginForm.on('submit', function(e) {
            if (formIsSubmitted) {
                return false;
            }
            formIsSubmitted = true;
        });

        barcodeInputField.on('keypress', foodcoopshop.Helper.debounce(
            function() {
                foodcoopshop.SelfService.submitForm(loginForm, 'fa-sign-in-alt');
            }, 1000)
        );

        barcodeInputField.focus();

    },

    initDepositPayment : function() {

        foodcoopshop.Helper.changeInputNumberToTextForEdge();

        $('.btn-add-deposit').featherlight(
            foodcoopshop.AppFeatherlight.initLightboxForForms(
                foodcoopshop.Helper.addPaymentFormSave,
                null,
                foodcoopshop.AppFeatherlight.closeLightbox,
                $('#add-payment-deposit-form')
            )
        );

    },

    initSearchForm : function() {

        var searchForm = $('#product-search');

        formIsSubmitted = false;
        searchForm.on('submit', function(e) {
            if (formIsSubmitted) {
                return false;
            }
            formIsSubmitted = true;
        });

        if (!foodcoopshop.Helper.isMobile()) {
            foodcoopshop.Helper.initBootstrapSelect(searchForm);
        }
        searchForm.find('select, input[type="text"]').on('change', function() {
            foodcoopshop.SelfService.submitForm(searchForm, 'fa-search');
        });
        searchForm.find('select, input[type="text"]').on('keypress', foodcoopshop.Helper.debounce(
            function() {
                foodcoopshop.SelfService.submitForm(searchForm, 'fa-search');
            }, 1000)
        );

        searchForm.find('input[type="text"]').focus();
    },

    submitForm : function(searchForm, icon) {
        var submitButton = searchForm.find('.btn[type="submit"]');
        foodcoopshop.Helper.addSpinnerToButton(submitButton, icon);
        foodcoopshop.Helper.disableButton(submitButton);
        searchForm.submit();
    },

    initHighlightedProductId: function(productId) {
        var rowId = '#product-wrapper-' + productId;
        $.scrollTo(rowId, 1000, {
            offset: {
                top: -100
            }
        });
        $(rowId).css('background-color', '#f3515c');
        $(rowId).css('color', 'white');
        $(rowId).one('mouseover', function () {
            $(this).removeAttr('style');
        });
        $(rowId).find('.quantity-in-units-input-field-wrapper input').focus();
    },

    initCartErrors: function (cartErrors) {
        cartErrors = $.parseJSON(cartErrors);
        for (var key in cartErrors) {
            var productContainer = $('#cart .product.' + key);
            productContainer.addClass('error');
            productContainer.after('

' + cartErrors[key].join('

') + '

');
        }
    },

    initWindowResize: function () {
        $(window).on('resize', function () {
            foodcoopshop.SelfService.onWindowResize();
        });
        foodcoopshop.SelfService.onWindowResize();
    },

    setFocusToSearchInputField : function() {
        $('#product-search input[name="keyword"]').focus();
    },

    onWindowResize : function() {
        $('.right-box').css('max-height', parseInt($(window).height()));
    },

    initAutoLogout : function() {

        this.resetTimer();
        this.renderTimer();

        $(document).idle({
            startAtIdle : true,
            onActive: function(){
                foodcoopshop.SelfService.resetTimer();
                foodcoopshop.SelfService.renderTimer();
            },
            onIdle: function() {
                foodcoopshop.SelfService.currentLogoutTimer--;
                foodcoopshop.SelfService.renderTimer();
                if (foodcoopshop.SelfService.currentLogoutTimer == 0) {
                    document.location.href = '/' + foodcoopshop.LocalizedJs.helper.routeLogout + '?redirect=' + document.location.href;
                }
            },
            recurIdleCall : true,
            idle: 1000
        });

    },

    resetTimer : function() {
        this.currentLogoutTimer = this.autoLogoutTimer;
    },

    renderTimer : function() {
        $('.auto-logout-timer').html(this.currentLogoutTimer);
    }

};<|endoftext|>


<commit_before>'use strict';

var path = require('path');

module.exports = function(grunt) {
  grunt.registerMultiTask('vjslanguages', 'A Grunt plugin for compiling VideoJS language assets.', function() {

    this.files.forEach(function(f) {
      var languageName = path.basename(f.src, '.json');
      var languageData = grunt.file.readJSON(f.src);
      var jsTemplate = 'videojs.addLanguage("' + languageName + '",' + JSON.stringify(languageData) + ');';
      var jsFilePath = path.join(f.dest, languageName + '.js');
      grunt.file.write(jsFilePath, jsTemplate);
      grunt.log.writeln('- [' + languageName +'] Language Built. File "' + jsFilePath + '" created.');
    });
  });
};
<commit_msg>update for pretty printed scripts<commit_after>'use strict';

var path = require('path');

module.exports = function(grunt) {
  grunt.registerMultiTask('vjslanguages', 'A Grunt plugin for compiling VideoJS language assets.', function() {

    this.files.forEach(function(f) {
      var languageName = path.basename(f.src, '.json');
      var languageData = grunt.file.readJSON(f.src);
      var jsTemplate = 'videojs.addLanguage("' + languageName + '",' + JSON.stringify(languageData,null,' ') + ');';
      var jsFilePath = path.join(f.dest, languageName + '.js');
      grunt.file.write(jsFilePath, jsTemplate);
      grunt.log.writeln('- [' + languageName +'] Language Built. File "' + jsFilePath + '" created.');
    });
  });
};
<|endoftext|>


<commit_before>//

// Pseudocode

// Initial Solution

// Refactored Solution

/*
// Reflect

What concepts did you solidify in working on this challenge?

What was the most difficult part of this challenge?

Did you solve the problem in a new way this time?

Was your pseudocode different from the Ruby version? What was the same and what was different?

*/<commit_msg>9.2 solution<commit_after>/*
//JavaScript Grocery List

// User Stories
A) Create a new list

B) Add an item with a quantity to the list

C) Remove an item from the list

D) Update quantities for items in your list

E) Print the list in nice format

F) Return the list

// Pseudocode
A) Construct a new grocery list object.

B) Create a list prototype function that takes an "item" property and "quantity" value as arguments, and assigns them to the list object.

C) Create a list prototype function that takes "item" as input and deletes it from the list object.

D) Create a list prototype function that takes item and quantity as input.
IF the list object already contains the item property
  Set item quantity value to user's quantity value.
ELSE
  Throw an error stating that the item does not currently exist in the list.

E) FOR loop through list object and print to console.

F) Create a list prototype function that returns the list object.

*/

// Initial Solution
function GroceryList() {}

GroceryList.prototype.addItem = function (item, quantity) {
  this[item] = quantity;
  console.log(quantity + " of " + item + " has been added.");
}

GroceryList.prototype.removeItem = function (item) {
  delete this[item];
  console.log(item + " has been removed from the list.");
}

GroceryList.prototype.updateQuantity = function (item, quantity) {
  if (this.hasOwnProperty(item)) {
    this[item] = quantity;
    console.log("The amount of " + item + " is now updated to " + quantity + ".");
  } else {
    throw "Unable to update! This list does not contain any " + item + ". Please add it first.";
  }
}

GroceryList.prototype.print = function () {
  console.log("This list contains:");
  for (var item in this) {
    if (typeof this[item] != 'function') {
      console.log("- " + this[item] + " of " + item);
    }
  }
}

GroceryList.prototype.getList = function () {
  var list = {};
  for (var item in this) {
    if (typeof this[item] != 'function') {
      list[item] = this[item];
    }
  }
  return list;
}

// Driver Code
var list = new GroceryList();

list.addItem("greek yogurt", 2);
list.addItem("honey", 1);
list.addItem("granola", 1);
list.addItem("avocado", 3);
list.addItem("Cinnamon Toast Crunch", 1);
list.addItem("milk", 1);
list.addItem("strawberries", 1);

list.removeItem("granola");

list.updateQuantity("honey", 2);

// Error handling allows the remaining program to run even if an exception is encountered.
try {
  list.updateQuantity("granola", 2)
}
catch(errorMsg) {
  console.log(errorMsg)
}

list.print();

console.log(list.getList());

// Refactored Solution

function GroceryList() {
  this.list = {};
}

GroceryList.prototype.addItem = function (item, quantity) {
  this.list[item] = quantity;
  console.log(quantity + " of " + item + " has been added.");
}

GroceryList.prototype.removeItem = function (item) {
  delete this.list[item];
  console.log(item + " has been removed from the list.");
}

GroceryList.prototype.updateQuantity = function (item, quantity) {
  if (this.list.hasOwnProperty(item)) {
    this.list[item] = quantity;
    console.log("The amount of " + item + " is now updated to " + quantity + ".");
  } else {
    throw "Unable to update! This list does not contain any " + item + ". Please add it first.";
  }
}

GroceryList.prototype.print = function () {
  console.log("This list contains:");
  for (var item in this.list) {
    console.log("- " + this.list[item] + " of " + item);
  }
}

GroceryList.prototype.getList = function () {
  return this.list;
}

/*
// Reflect

What concepts did you solidify in working on this challenge? (reviewing the passing of information, objects, constructors, etc.)
Constructor functions, prototypes, data types, error handling, and property manipulation.

What was the most difficult part of this challenge?
I forgot about the prototype of an object, making it extremely difficult to create functions to manipulate new instances of the object.

Did an array or object make more sense to use and why?
Objects made more sense simply because we're dealing with 2 pieces of information per grocery list item (item and quantity).

*/
<|endoftext|>


<commit_before>"use strict";
/*!
 * Module dependencies.
 */

var dummy
  , path = require('path')
  , hotplate = require('hotplate')
  , hotCoreStoreRegistry = require('hotCoreStoreRegistry')
;

hotplate.hotEvents.on('pageElements', 'hotCoreStoreVars', hotplate.cachable( function( done ){

  var storesVarsData = {};

  hotCoreStoreRegistry.getAllStores( function( err, allStores ){

    Object.keys( allStores ).forEach( function( storeName ){
      var store = allStores[ storeName ];

      if( store.publicURL && store.hotExpose ){
        var url = path.join( hotplate.config.get( 'hotCoreStoreExposer.storesUrlsPrefix' ), store.publicURL );
        storesVarsData[ store.storeName ] = {
          target: url,
          sortParam: 'sortBy',
          alsoNotify: store.alsoNotify,
          enabledField: store.enabledField,
          defaultNewToStart: store.defaultNewToStart,
          alwaysRefreshOnChange: store.alwaysRefreshOnChange,
          type: store.type ? store.type : 'cached',
        };
      }
    });
  });

  done( null, { vars: [
    { name: 'stores', value: storesVarsData } ]
  } );

}));

<commit_msg>Exposing preserveCacheOnReset, PLUS Update to new EventEmitterCollector API<commit_after>"use strict";
/*!
 * Module dependencies.
 */

var dummy
  , path = require('path')
  , hotplate = require('hotplate')
  , hotCoreStoreRegistry = require('hotCoreStoreRegistry')
;

hotplate.hotEvents.onCollect('pageElements', 'hotCoreStoreVars', hotplate.cachable( function( done ){

  var storesVarsData = {};

  hotCoreStoreRegistry.getAllStores( function( err, allStores ){

    Object.keys( allStores ).forEach( function( storeName ){
      var store = allStores[ storeName ];

      if( store.publicURL && store.hotExpose ){
        var url = path.join( hotplate.config.get( 'hotCoreStoreExposer.storesUrlsPrefix' ), store.publicURL );
        storesVarsData[ store.storeName ] = {
          target: url,
          sortParam: 'sortBy',
          alsoNotify: store.alsoNotify,
          enabledField: store.enabledField,
          defaultNewToStart: store.defaultNewToStart,
          preserveCacheOnReset: !!store.preserveCacheOnReset,
          alwaysRefreshOnChange: store.alwaysRefreshOnChange,
          type: store.type ? store.type : 'cached',
        };
      }
    });
  });

  done( null, { vars: [
    { name: 'stores', value: storesVarsData } ]
  } );

}));

<|endoftext|>


<commit_before>import r from 'ramda';
import products from '../mock-data/products.json';

const getBrands = r.compose(r.uniq, r.map(r.prop('brand')));
const brands = getBrands(products);

console.log(brands);<commit_msg>Add functions for sorting and finding featured products<commit_after>import r from 'ramda';
import products from '../mock-data/products.json';

const getBrands = r.compose(r.uniq, r.map(r.prop('brand')));
const sortByPriceAsc = r.sortBy(r.prop('price'));
const sortByPriceDesc = r.compose(r.reverse, sortByPriceAsc);
const isFeatured = r.propEq('featured', true);
const getFeatured = r.filter(isFeatured);

const featured = getFeatured(products);

console.log(featured);
<|endoftext|>


<commit_before>import React from 'react';
import {render} from 'react-dom';
import HelloWorld from './HelloWorld';

render(<HelloWorld />, document.getElementById('app'));<commit_msg>initial commit<commit_after>import React from 'react';
import {render} from 'react-dom';
import ReactWeather from './ReactWeather';

render(<ReactWeather />, document.getElementById('app'));<|endoftext|>


<commit_before>/*
 * Copyright 2012 Sakai Foundation (SF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://www.osedu.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

var _ = require('underscore');
var assert = require('assert');

var OaeUtil = require('oae-util/lib/util');
var RestAPI = require('oae-rest');
var RestContext = require('oae-rest/lib/model').RestContext;
var TestsUtil = require('oae-tests');

var ActivityTestsUtil = require('oae-activity/lib/test/util');

describe('Notifications', function() {

    // Rest context that can be used for anonymous requests on the cambridge tenant
    var anonymousCamRestContext = null;

    // Rest context that can be used every time we need to make a request as a tenant admin
    var camAdminRestContext = null;

    // Rest context that can be used every time we need to make a request as a global admin
    var globalAdminRestContext = null;

    /*!
     * Create a default activity configuration object, overridden with the given `overlay` object.
     *
     * @param   {Object}    overlay     Configuration properties with which to overide the default.
     * @return  {Object}                An object that represents the default configuration for unit tests, overridden by the overlay.
     */
    var createDefaultConfig = function(overlay) {
        return _.extend({'collectionPollingFrequency': -1}, overlay);
    };

    /**
     * Function that will fill up the tenant admin and anymous rest context
     */
    before(function(callback) {
        anonymousCamRestContext = TestsUtil.createTenantRestContext(global.oaeTests.tenants.cam.host);
        camAdminRestContext = TestsUtil.createTenantAdminRestContext(global.oaeTests.tenants.cam.host);
        globalAdminRestContext = TestsUtil.createGlobalAdminRestContext();
        callback();
    });

    describe('Notification Stream', function() {

        /**
         * Test that verifies notifications are not sent to the actor of an activity.
         */
        it('verifies a notification is never sent to the actor of an activity', function(callback) {
            TestsUtil.generateTestUsers(camAdminRestContext, 2, function(err, createdUsers) {
                assert.ok(!err);
                var mrvisser = createdUsers[_.keys(createdUsers)[0]];
                var simong = createdUsers[_.keys(createdUsers)[1]];

                // Create content with simong as a user
                RestAPI.Content.createLink(mrvisser.restContext, 'Google', 'Google', 'private', 'http://www.google.ca', [], [simong.user.id], function(err, content) {
                    assert.ok(!err);

                    // Sanity check that the content is in simong's notification stream
                    ActivityTestsUtil.collectAndGetNotificationStream(simong.restContext, null, function(err, notificationStream) {
                        assert.ok(!err);
                        assert.equal(notificationStream.items.length, 1);
                        assert.equal(notificationStream.items[0].actor['oae:id'], mrvisser.user.id);
                        assert.equal(notificationStream.items[0].object['oae:id'], content.id);

                        // Verify that no notification was routed to mrvisser, as they performed the action and this would be super annoying
                        ActivityTestsUtil.collectAndGetNotificationStream(mrvisser.restContext, null, function(err, notificationStream) {
                            assert.ok(!err);
                            assert.equal(notificationStream.items.length, 0);
                            callback();
                        });
                    });
                });
            });
        });

        /**
         * Test that verifies a notification is sent to users when a content item is created with them as a member
         */
        it('verifies a notification is sent when creating content with a user member', function(callback) {
            TestsUtil.generateTestUsers(camAdminRestContext, 2, function(err, createdUsers) {
                assert.ok(!err);
                var mrvisser = createdUsers[_.keys(createdUsers)[0]];
                var simong = createdUsers[_.keys(createdUsers)[1]];

                // Create content with simong as a user and verify it winds up in the notification stream
                RestAPI.Content.createLink(mrvisser.restContext, 'Google', 'Google', 'private', 'http://www.google.ca', [], [simong.user.id], function(err, content) {
                    assert.ok(!err);

                    ActivityTestsUtil.collectAndGetNotificationStream(simong.restContext, null, function(err, notificationStream) {
                        assert.ok(!err);
                        assert.equal(notificationStream.items.length, 1);
                        assert.equal(notificationStream.items[0].actor['oae:id'], mrvisser.user.id);
                        assert.equal(notificationStream.items[0].object['oae:id'], content.id);
                        callback();
                    });
                });
            });
        });

        /**
         * Ensure that receiving 2 activities who do not get aggregated result in an increment of +2.
         */
        it('verify that n non-aggregated activities result in a +n increment of the notification count', function(callback) {
            TestsUtil.generateTestUsers(camAdminRestContext, 2, function(err, createdUsers) {
                assert.ok(!err);
                var mrvisser = createdUsers[_.keys(createdUsers)[0]];
                var simong = createdUsers[_.keys(createdUsers)[1]];

                // Generate 2 non-aggregatable activities
                RestAPI.Content.createLink(mrvisser.restContext, 'Google', 'Google', 'private', 'http://www.google.ca', [], [simong.user.id], function(err, content) {
                    assert.ok(!err);
                    RestAPI.Group.createGroup(mrvisser.restContext, 'some group', 'Group title', 'Group description', 'private', 'request', [], [simong.user.id], function(err, newGroup) {
                        assert.ok(!err);

                        // Simon should have 2 notifications
                        ActivityTestsUtil.collectAndGetNotificationStream(simong.restContext, null, function(err, notificationStream) {
                            assert.ok(!err);
                            assert.equal(notificationStream.items.length, 2);

                            // Verify the count.
                            RestAPI.User.getMe(simong.restContext, function(err, meData) {
                                assert.ok(!err);
                                assert.strictEqual(meData.notificationsUnread, 2);
                                callback();
                            });
                        });
                    });
                });
            });
        });
    });

    describe('Mark Notifications Read', function() {

        /**
         * Test that verifies marking notifications as read and counts work.
         */
        it('verifies toggling of notifications read', function(callback) {
            TestsUtil.generateTestUsers(camAdminRestContext, 2, function(err, createdUsers) {
                assert.ok(!err);
                var mrvisser = createdUsers[_.keys(createdUsers)[0]];
                var simong = createdUsers[_.keys(createdUsers)[1]];

                RestAPI.User.getMe(simong.restContext, function(err, me) {
                    assert.ok(!err);
                    assert.ok(!me.notificationsUnread);
                    assert.ok(!me.notificationsLastRead);

                    // Create content with simong as a member
                    RestAPI.Content.createLink(mrvisser.restContext, 'Google', 'Google', 'private', 'http://www.google.ca', [], [simong.user.id], function(err, content) {
                        assert.ok(!err);

                        // Ensure the notification gets delivered
                        ActivityTestsUtil.collectAndGetNotificationStream(simong.restContext, null, function(err, notificationStream) {
                            assert.ok(!err);
                            assert.equal(notificationStream.items.length, 1);
                            assert.equal(notificationStream.items[0].actor['oae:id'], mrvisser.user.id);
                            assert.equal(notificationStream.items[0].object['oae:id'], content.id);

                            // Verify the notificationsUnread status
                            RestAPI.User.getMe(simong.restContext, function(err, me) {
                                assert.ok(!err);

                                // We now have unread notifications, but still no "lastRead" status
                                assert.strictEqual(me.notificationsUnread, 1);
                                assert.strictEqual(me.notificationsLastRead, undefined);

                                RestAPI.Activity.markNotificationsRead(simong.restContext, function(err, result) {
                                    var lastReadTime = result.lastReadTime;

                                    assert.strictEqual(lastReadTime, OaeUtil.getNumberParam(lastReadTime));

                                    // Verify the notificationsLastRead status
                                    RestAPI.User.getMe(simong.restContext, function(err, me) {
                                        assert.ok(!err);

                                        // We now have no unread notifications, and a lastRead status
                                        assert.strictEqual(me.notificationsUnread, 0);
                                        assert.strictEqual(me.notificationsLastRead, lastReadTime);

                                        // Create 2 content items again with simong as a member
                                        RestAPI.Content.createLink(mrvisser.restContext, 'Google', 'Google', 'private', 'http://www.google.ca', [], [simong.user.id], function(err, content) {
                                            assert.ok(!err);

                                            RestAPI.Content.createLink(mrvisser.restContext, 'Google', 'Google', 'private', 'http://www.google.ca', [], [simong.user.id], function(err, content) {
                                                assert.ok(!err);

                                                // Ensure the notification gets delivered and aggregated
                                                ActivityTestsUtil.collectAndGetNotificationStream(simong.restContext, null, function(err, notificationStream) {
                                                    assert.ok(!err);
                                                    assert.equal(notificationStream.items.length, 1);
                                                    assert.equal(notificationStream.items[0].actor['oae:id'], mrvisser.user.id);
                                                    assert.equal(notificationStream.items[0].object['oae:collection'].length, 3);

                                                    // Verify the notificationsUnread is incremented and notificationsLastRead status
                                                    RestAPI.User.getMe(simong.restContext, function(err, me) {
                                                        assert.ok(!err);

                                                        // We now have unread notifications, and a lastRead status
                                                        assert.strictEqual(me.notificationsUnread, 2);
                                                        assert.equal(me.notificationsLastRead, lastReadTime);

                                                        callback();
                                                    });
                                                });
                                            });
                                        });
                                    });
                                });
                            });
                        });
                    });
                });
            });
        });
    });
});
<commit_msg>Updating docs<commit_after>/*
 * Copyright 2012 Sakai Foundation (SF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://www.osedu.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

var _ = require('underscore');
var assert = require('assert');

var OaeUtil = require('oae-util/lib/util');
var RestAPI = require('oae-rest');
var RestContext = require('oae-rest/lib/model').RestContext;
var TestsUtil = require('oae-tests');

var ActivityTestsUtil = require('oae-activity/lib/test/util');

describe('Notifications', function() {

    // Rest context that can be used for anonymous requests on the cambridge tenant
    var anonymousCamRestContext = null;

    // Rest context that can be used every time we need to make a request as a tenant admin
    var camAdminRestContext = null;

    // Rest context that can be used every time we need to make a request as a global admin
    var globalAdminRestContext = null;

    /*!
     * Create a default activity configuration object, overridden with the given `overlay` object.
     *
     * @param   {Object}    overlay     Configuration properties with which to overide the default.
     * @return  {Object}                An object that represents the default configuration for unit tests, overridden by the overlay.
     */
    var createDefaultConfig = function(overlay) {
        return _.extend({'collectionPollingFrequency': -1}, overlay);
    };

    /**
     * Function that will fill up the tenant admin and anymous rest context
     */
    before(function(callback) {
        anonymousCamRestContext = TestsUtil.createTenantRestContext(global.oaeTests.tenants.cam.host);
        camAdminRestContext = TestsUtil.createTenantAdminRestContext(global.oaeTests.tenants.cam.host);
        globalAdminRestContext = TestsUtil.createGlobalAdminRestContext();
        callback();
    });

    describe('Notification Stream', function() {

        /**
         * Test that verifies notifications are not sent to the actor of an activity.
         */
        it('verifies a notification is never sent to the actor of an activity', function(callback) {
            TestsUtil.generateTestUsers(camAdminRestContext, 2, function(err, createdUsers) {
                assert.ok(!err);
                var mrvisser = createdUsers[_.keys(createdUsers)[0]];
                var simong = createdUsers[_.keys(createdUsers)[1]];

                // Create content with simong as a user
                RestAPI.Content.createLink(mrvisser.restContext, 'Google', 'Google', 'private', 'http://www.google.ca', [], [simong.user.id], function(err, content) {
                    assert.ok(!err);

                    // Sanity check that the content is in simong's notification stream
                    ActivityTestsUtil.collectAndGetNotificationStream(simong.restContext, null, function(err, notificationStream) {
                        assert.ok(!err);
                        assert.equal(notificationStream.items.length, 1);
                        assert.equal(notificationStream.items[0].actor['oae:id'], mrvisser.user.id);
                        assert.equal(notificationStream.items[0].object['oae:id'], content.id);

                        // Verify that no notification was routed to mrvisser, as they performed the action and this would be super annoying
                        ActivityTestsUtil.collectAndGetNotificationStream(mrvisser.restContext, null, function(err, notificationStream) {
                            assert.ok(!err);
                            assert.equal(notificationStream.items.length, 0);
                            callback();
                        });
                    });
                });
            });
        });

        /**
         * Test that verifies a notification is sent to users when a content item is created with them as a member
         */
        it('verifies a notification is sent when creating content with a user member', function(callback) {
            TestsUtil.generateTestUsers(camAdminRestContext, 2, function(err, createdUsers) {
                assert.ok(!err);
                var mrvisser = createdUsers[_.keys(createdUsers)[0]];
                var simong = createdUsers[_.keys(createdUsers)[1]];

                // Create content with simong as a user and verify it winds up in the notification stream
                RestAPI.Content.createLink(mrvisser.restContext, 'Google', 'Google', 'private', 'http://www.google.ca', [], [simong.user.id], function(err, content) {
                    assert.ok(!err);

                    ActivityTestsUtil.collectAndGetNotificationStream(simong.restContext, null, function(err, notificationStream) {
                        assert.ok(!err);
                        assert.equal(notificationStream.items.length, 1);
                        assert.equal(notificationStream.items[0].actor['oae:id'], mrvisser.user.id);
                        assert.equal(notificationStream.items[0].object['oae:id'], content.id);
                        callback();
                    });
                });
            });
        });

        /**
         * Test that verifies that receiving non-aggregating notifications will appropriately update the unreadNotificationsCount
         */
        it('verify unread notifications count', function(callback) {
            TestsUtil.generateTestUsers(camAdminRestContext, 2, function(err, createdUsers) {
                assert.ok(!err);
                var mrvisser = createdUsers[_.keys(createdUsers)[0]];
                var simong = createdUsers[_.keys(createdUsers)[1]];

                // Generate 2 non-aggregating activities
                RestAPI.Content.createLink(mrvisser.restContext, 'Google', 'Google', 'private', 'http://www.google.ca', [], [simong.user.id], function(err, content) {
                    assert.ok(!err);
                    RestAPI.Group.createGroup(mrvisser.restContext, 'some group', 'Group title', 'Group description', 'private', 'request', [], [simong.user.id], function(err, newGroup) {
                        assert.ok(!err);

                        // Simon should have 2 notifications
                        ActivityTestsUtil.collectAndGetNotificationStream(simong.restContext, null, function(err, notificationStream) {
                            assert.ok(!err);
                            assert.equal(notificationStream.items.length, 2);

                            // Verify the notificationsUnread count on the me feed
                            RestAPI.User.getMe(simong.restContext, function(err, meData) {
                                assert.ok(!err);
                                assert.strictEqual(meData.notificationsUnread, 2);
                                callback();
                            });
                        });
                    });
                });
            });
        });
    });

    describe('Mark Notifications Read', function() {

        /**
         * Test that verifies marking notifications as read and counts work.
         */
        it('verifies toggling of notifications read', function(callback) {
            TestsUtil.generateTestUsers(camAdminRestContext, 2, function(err, createdUsers) {
                assert.ok(!err);
                var mrvisser = createdUsers[_.keys(createdUsers)[0]];
                var simong = createdUsers[_.keys(createdUsers)[1]];

                RestAPI.User.getMe(simong.restContext, function(err, me) {
                    assert.ok(!err);
                    assert.ok(!me.notificationsUnread);
                    assert.ok(!me.notificationsLastRead);

                    // Create content with simong as a member
                    RestAPI.Content.createLink(mrvisser.restContext, 'Google', 'Google', 'private', 'http://www.google.ca', [], [simong.user.id], function(err, content) {
                        assert.ok(!err);

                        // Ensure the notification gets delivered
                        ActivityTestsUtil.collectAndGetNotificationStream(simong.restContext, null, function(err, notificationStream) {
                            assert.ok(!err);
                            assert.equal(notificationStream.items.length, 1);
                            assert.equal(notificationStream.items[0].actor['oae:id'], mrvisser.user.id);
                            assert.equal(notificationStream.items[0].object['oae:id'], content.id);

                            // Verify the notificationsUnread status
                            RestAPI.User.getMe(simong.restContext, function(err, me) {
                                assert.ok(!err);

                                // We now have unread notifications, but still no "lastRead" status
                                assert.strictEqual(me.notificationsUnread, 1);
                                assert.strictEqual(me.notificationsLastRead, undefined);

                                RestAPI.Activity.markNotificationsRead(simong.restContext, function(err, result) {
                                    var lastReadTime = result.lastReadTime;

                                    assert.strictEqual(lastReadTime, OaeUtil.getNumberParam(lastReadTime));

                                    // Verify the notificationsLastRead status
                                    RestAPI.User.getMe(simong.restContext, function(err, me) {
                                        assert.ok(!err);

                                        // We now have no unread notifications, and a lastRead status
                                        assert.strictEqual(me.notificationsUnread, 0);
                                        assert.strictEqual(me.notificationsLastRead, lastReadTime);

                                        // Create 2 content items again with simong as a member
                                        RestAPI.Content.createLink(mrvisser.restContext, 'Google', 'Google', 'private', 'http://www.google.ca', [], [simong.user.id], function(err, content) {
                                            assert.ok(!err);

                                            RestAPI.Content.createLink(mrvisser.restContext, 'Google', 'Google', 'private', 'http://www.google.ca', [], [simong.user.id], function(err, content) {
                                                assert.ok(!err);

                                                // Ensure the notification gets delivered and aggregated
                                                ActivityTestsUtil.collectAndGetNotificationStream(simong.restContext, null, function(err, notificationStream) {
                                                    assert.ok(!err);
                                                    assert.equal(notificationStream.items.length, 1);
                                                    assert.equal(notificationStream.items[0].actor['oae:id'], mrvisser.user.id);
                                                    assert.equal(notificationStream.items[0].object['oae:collection'].length, 3);

                                                    // Verify the notificationsUnread is incremented and notificationsLastRead status
                                                    RestAPI.User.getMe(simong.restContext, function(err, me) {
                                                        assert.ok(!err);

                                                        // We now have unread notifications, and a lastRead status
                                                        assert.strictEqual(me.notificationsUnread, 2);
                                                        assert.equal(me.notificationsLastRead, lastReadTime);

                                                        callback();
                                                    });
                                                });
                                            });
                                        });
                                    });
                                });
                            });
                        });
                    });
                });
            });
        });
    });
});
<|endoftext|>


<commit_before>import { warn } from '../util/debug'

export function wheelMixin(BScroll) {
  BScroll.prototype.wheelTo = function (index) {
    if (this.options.wheel) {
      this.y = -index * this.itemHeight
      this.scrollTo(0, this.y)
    }
  }

  BScroll.prototype.getSelectedIndex = function () {
    return this.options.wheel && this.selectedIndex
  }

  BScroll.prototype._initWheel = function () {
    const wheel = this.options.wheel
    if (!wheel.wheelWrapperClass || !wheel.wheelItemClass) {
      if (!wheel.wheelWrapperClass) {
        wheel.wheelWrapperClass = 'wheel-scroll'
      }
      if (!wheel.wheelItemClass) {
        wheel.wheelItemClass = 'wheel-item'
      }
      warn('wheelWrapperClass & wheelItemClass of wheel options use the default setting.')
    }
    if (wheel.selectedIndex === undefined) {
      wheel.selectedIndex = 0
      warn('wheel option selectedIndex is required!')
    }
  }
}<commit_msg>feat(wheel): 去掉warning<commit_after>import { warn } from '../util/debug'

export function wheelMixin(BScroll) {
  BScroll.prototype.wheelTo = function (index) {
    if (this.options.wheel) {
      this.y = -index * this.itemHeight
      this.scrollTo(0, this.y)
    }
  }

  BScroll.prototype.getSelectedIndex = function () {
    return this.options.wheel && this.selectedIndex
  }

  BScroll.prototype._initWheel = function () {
    const wheel = this.options.wheel
    if (!wheel.wheelWrapperClass) {
      wheel.wheelWrapperClass = 'wheel-scroll'
    }
    if (!wheel.wheelItemClass) {
      wheel.wheelItemClass = 'wheel-item'
    }
    if (wheel.selectedIndex === undefined) {
      wheel.selectedIndex = 0
      warn('wheel option selectedIndex is required!')
    }
  }
}<|endoftext|>