<commit_before>// Karma configuration
// Generated on Wed Mar 19 2014 12:00:53 GMT-0700 (PDT)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha', 'browserify'],

    // list of files / patterns to load in the browser
    files: [
      'lib/**/*.coffee',
      'test/**/*.coffee'
    ],

    sauceLabs: {
      username: process.env.SAUCE_USERNAME,
      accessKey: process.env.SAUCE_ACCESS_KEY,
      startConnect: true,
      testName: 'KD tests'
    },

    // define SauceLabs browsers
    customLaunchers: {

      sl_firefox_windows: {
        base: 'SauceLabs',
        browserName: 'firefox',
        platform: 'Windows 7'
      },

      sl_chrome_windows: {
        base: 'SauceLabs',
        browserName: 'chrome',
        platform: 'Windows 7'
      },

      sl_ie_9: {
        base: 'SauceLabs',
        browserName: 'internet explorer',
        platform: 'Windows 7',
        version: '9'
      },

      sl_ie_10: {
        base: 'SauceLabs',
        browserName: 'internet explorer',
        platform: 'Windows 7',
        version: '10'
      }
    },

    // list of files to exclude
    exclude: [
      'lib/index.coffee'
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'lib/**/*.coffee': ['browserify'],
      'test/**/*.coffee': ['browserify']
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress', 'coverage'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Chrome'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    plugins : [
      'karma-mocha',
      'karma-coverage',
      'karma-chrome-launcher',
      'karma-browserify'
    ],

    coverageReporter: {
      type : 'html',
      dir : 'coverage/'
    },

    browserify: {
      transform: ['coffeeify'],
      extensions: ['.coffee']
    }
  });
};
<commit_msg>Fix code coverage using browserify-istanbul<commit_after>// Karma configuration
// Generated on Wed Mar 19 2014 12:00:53 GMT-0700 (PDT)

var istanbul = require('browserify-istanbul');

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha', 'browserify'],

    // list of files / patterns to load in the browser
    files: [
      'lib/**/*.coffee',
      'test/**/*.coffee'
    ],

    sauceLabs: {
      username: process.env.SAUCE_USERNAME,
      accessKey: process.env.SAUCE_ACCESS_KEY,
      startConnect: true,
      testName: 'KD tests'
    },

    // define SauceLabs browsers
    customLaunchers: {

      sl_firefox_windows: {
        base: 'SauceLabs',
        browserName: 'firefox',
        platform: 'Windows 7'
      },

      sl_chrome_windows: {
        base: 'SauceLabs',
        browserName: 'chrome',
        platform: 'Windows 7'
      },

      sl_ie_9: {
        base: 'SauceLabs',
        browserName: 'internet explorer',
        platform: 'Windows 7',
        version: '9'
      },

      sl_ie_10: {
        base: 'SauceLabs',
        browserName: 'internet explorer',
        platform: 'Windows 7',
        version: '10'
      }
    },

    // list of files to exclude
    exclude: [
      'lib/index.coffee'
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'lib/**/*.coffee': ['browserify'],
      'test/**/*.coffee': ['browserify']
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress', 'coverage'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_ERROR,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Chrome'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    plugins : [
      'karma-mocha',
      'karma-coverage',
      'karma-chrome-launcher',
      'karma-browserify'
    ],

    coverageReporter: {
      dir : 'coverage/',
      reporters : [
        {"type": "text"},
        {"type": "html"}
      ]
    },

    browserify: {
      debug: true,
      transform: [
        'coffeeify',
        istanbul({
          instrumenterConfig: { embedSource: true }
        })
      ],
      extensions: ['.coffee']
    }
  });
};
<|endoftext|>


<commit_before>"use strict";
var decode = require('punycode').ucs2.decode;
var style = require('./lib/colors&spices');

var culinary = {
	style: function(string) { return new style(string, culinary._decode) } ,

	write: function(string) {
		process.stdout.write(string);
		return this;
	},

	up: function(integer){ return this.execute(integer + "A") },

	down: function(integer){ return this.execute(integer + "B") },

	back: function(integer){ return this.execute(integer + "D") },

	forth: function(integer){ return this.execute(integer + "C") },

	position: function(x,y) {
		// This allows dimensions object to be passed without parsing
		if(x.constructor === Object) {
			var temp = x;
			x = temp.columns;
			y = temp.rows;
		}
		return this.execute(y + ";" + x + "H")
	},

	dimensions: function() { return { columns: process.stdout.columns, rows: process.stdout.rows, width: process.stdout.columns, height: process.stdout.rows } },

	scrollUp: function(){ return this.execute("D", false) },
	scrollDown: function(){ return this.execute("M", false) },

	cursorTo: function(position) { process.stdout.cursorTo(position); return this; },
	nextLine: function(){ return this.execute("E", false) },

	save: function(){ return this.execute("s") },
	restore: function(){ return this.execute("u") },

	_cursor: function(hide){
		if(hide) return this.execute("?25h");
		else return this.execute("?25l");
	},

	_custom: function(character, prepend, append, hasAttributes){ return this.execute(prepend + character + append, hasAttributes) },

	bell: function(){ return this.write("\x07");  },

	clearScreen: function(direction){
		var directionCodes = {
			up: 1,
			down: 0,
			entire: 2
		}

		if(!direction) direction = "entire";

		return this.execute(directionCodes[direction] + "J");
	},

	eraseLine: function(direction){
		var directionCodes = {
			left: 1,
			right: 0,
			entire: 2
		}

		if(!direction) direction = "entire";

		return this.execute(directionCodes[direction] + "K");
	},

	execute: function(command, prepend){
		var prepend = (prepend == false)?"":this._bracket;
		// Creates new buffer and decodes command using punnycode
		return this.write(this._decode(prepend+command));;
	},

	_bracket: "[",

	_decode: function(string){
		// Decodes the string to ucs2 and returns the Buffer with escape code
		return new Buffer([ 0x1b ].concat(decode(string.toString())));
	}
}

// Aliases
culinary.removeLine = culinary.eraseLine;
culinary.cls = culinary.clearScreen;
culinary.next = culinary.nextLine;
culinary.endLine = culinary.nextLine;
culinary.size = culinary.dimensions;
culinary.left = culinary.back;
culinary.right = culinary.forth;

culinary.hideCursor = function() { culinary.cursor(true) };
culinary.showCursor = function() { culinary.cursor(false) };
//

module.exports = culinary;
<commit_msg>Bunch of updates to cursor handling<commit_after>"use strict";
var decode = require('punycode').ucs2.decode;
var style = require('./lib/colors&spices');

var culinary = {
	style: function(string) { return new style(string, culinary._decode) } ,

	write: function(string) {
		process.stdout.write(string);
		return this;
	},

	up: function(integer){ return this.execute(integer + "A") },

	down: function(integer){ return this.execute(integer + "B") },

	back: function(integer){ return this.execute(integer + "D") },

	forth: function(integer){ return this.execute(integer + "C") },

	position: function(x,y) {
		// This allows dimensions object to be passed without parsing
		if(x.constructor === Object) {
			var temp = x;
			x = temp.columns;
			y = temp.rows;
		}
		return this.execute(y + ";" + x + "H")
	},

	dimensions: function() { return { columns: process.stdout.columns, rows: process.stdout.rows, width: process.stdout.columns, height: process.stdout.rows } },

	scrollUp: function(){ return this.execute("D", false) },
	scrollDown: function(){ return this.execute("M", false) },

	cursorTo: function(position) { process.stdout.cursorTo(position); return this; },
	nextLine: function(){ return this.execute("E", false) },

	save: function(){ return this.execute("s") },
	restore: function(){ return this.execute("u") },

	cursor: function(show){
		if(show != false) return this.execute("?25h");
		else return this.execute("?25l");
	},

	_custom: function(character, prepend, append, hasAttributes){ return this.execute(prepend + character + append, hasAttributes) },

	bell: function(){ return this.write("\x07");  },

	clearScreen: function(direction){
		var directionCodes = {
			up: 1,
			down: 0,
			entire: 2
		}

		if(!direction) direction = "entire";

		return this.execute(directionCodes[direction] + "J");
	},

	eraseLine: function(direction){
		var directionCodes = {
			left: 1,
			right: 0,
			entire: 2
		}

		if(!direction) direction = "entire";

		return this.execute(directionCodes[direction] + "K");
	},

	execute: function(command, prepend){
		var prepend = (prepend == false)?"":this._bracket;
		// Creates new buffer and decodes command using punnycode
		return this.write(this._decode(prepend+command));;
	},

	_bracket: "[",

	_decode: function(string){
		// Decodes the string to ucs2 and returns the Buffer with escape code
		return new Buffer([ 0x1b ].concat(decode(string.toString())));
	}
}

// Aliases
culinary.removeLine = culinary.eraseLine;
culinary.cls = culinary.clearScreen;
culinary.next = culinary.nextLine;
culinary.endLine = culinary.nextLine;
culinary.size = culinary.dimensions;
culinary.left = culinary.back;
culinary.right = culinary.forth;

culinary.hideCursor = function() { return culinary.cursor(false) };
culinary.showCursor = function() { return culinary.cursor(true) };
//

module.exports = culinary;
<|endoftext|>


<commit_before>

var
	map = require('../src/map');

describe('map via reduce', function ()
{
	function square (x)
	{
		return x * x;
	}

	var testArray = [5, 4, 7];

	it('works like native map', function ()
	{
		expect(testArray.map(square)).toEqual(map(testArray, square));
	});

	function proj ()
	{
		return [].slice.call(arguments);
	}

	it('has identical result', function ()
	{
		var
			p1 = testArray.map(proj),
			p2 = map(testArray, proj);

		expect(p1).toEqual(p2);
	});

});
<commit_msg>fix tempo.<commit_after>

var
	map = require('../src/map');

describe('map via reduce', function ()
{

	function square (x)
	{
		return x * x;
	}

	var testArray = [5, 4, 7];

	it('works like native map', function ()
	{
		expect(testArray.map(square)).toEqual(map(testArray, square));
	});

	function proj ()
	{
		return [].slice.call(arguments);
	}

	it('has identical result', function ()
	{
		var
			p1 = testArray.map(proj),
			p2 = map(testArray, proj);

		expect(p1).toEqual(p2);
	});

});
<|endoftext|>


<commit_before>//
// Backbone-associations.js 0.2.0
//
// (c) 2012 Dhruva Ray, Jaynti Kanani
//
// Backbone-associations may be freely distributed under the MIT license; see the accompanying LICENSE.txt.
//
// Depends on [Backbone](https://github.com/documentcloud/backbone) (and thus on [Underscore](https://github.com/documentcloud/underscore/) as well)
//
// A complete [Test & Benchmark Suite](../test/test-suite.html) is included for your perusal.

// Initial Setup
// --------------
(function() {
    // The top-level namespace. All public Backbone classes and modules will be attached to this.
    // Exported for the browser and CommonJS.
    var _, Backbone;
    if ( typeof window === 'undefined' ) {
        _ = require( 'underscore' );
        Backbone = require( 'backbone' );
        exports = module.exports = Backbone;
    }
    else {
        _ = window._;
        Backbone = window.Backbone;
        exports = window;
    }
    // Backbone.AssociatedModel
    // --------------

    //Add `Many` and `One` relations to Backbone Object
    Backbone.Many  = "Many";
    Backbone.One  = "One";
    //Define `AssociatedModel` (Extends Backbone.Model)
    Backbone.AssociatedModel = Backbone.Model.extend({
        //Define relations with Associated Model
        relations: undefined,
        //Set a hash of model attributes on the object,
        //firing `"change"` unless you choose to silence it.
        //It maintains relations between models during the set operation. It also bubbles up child events to the parent.
        set: function( key, value, options ) {
            var attributes,processedRelations,tbp;
            // Duplicate backbone's behavior to allow separate key/value parameters, instead of a single 'attributes' object.
            if ( _.isObject( key ) || key == null ) {
                attributes = key;
                options = value;
            }
            else {
                attributes = {};
                attributes[ key ] = value;
            }
            // Extract attributes and options.
            options || (options = {});
            if(!attributes) return this;
            if (options.unset) for (attr in attributes) attributes[attr] = void 0;
            //Check for existence of relations in this model
            if(this.relations){
                //Iterate over `this.relations` and `set` model and collection values
                _.each(this.relations ,function(relation){
                    if (attributes[relation.key] != undefined ){
                        //Get value of attribute with relation key in `val`
                        var val = getValue(attributes,relation.key);
                        //Get class if relation is stored as a string
                        relation.relatedModel && _.isString(relation.relatedModel) && (relation.relatedModel = eval(relation.relatedModel));
                        relation.collectionType && _.isString(relation.collectionType) && (relation.collectionType = eval(relation.collectionType));
                        //Track reference change of associated model for `change:attribute` event
                        var refChanged = false;
                        //If `relation` defines model as associated collection...
                        if(relation.type === Backbone.Many){
                            //`relation.collectionType` should be instance of `Backbone.Collection`
                            if(relation.collectionType && !relation.collectionType.prototype instanceof Backbone.Collection){
                                throw new Error( 'collectionType must inherit from Backbone.Collection' );
                            }
                            //Create new `Backbone.Collection` with `collectionType`
                            if(!this.attributes[relation.key]){
                                this.attributes[relation.key] = relation.collectionType ? new relation.collectionType() : this._createCollection(relation.relatedModel);
                                refChanged = true;
                            }
                            // Get all models if `val` is already instanceof `Backbone.Collection`
                            if(val instanceof Backbone.Collection){
                                val = val.models;
                            }
                            //Resetting new Collection with new value and options
                            this.attributes[relation.key].reset(val,options);
                        }
                        //If `relation` defines model as associated model...
                        else if(relation.type == Backbone.One && relation.relatedModel){
                            //Create New `Backbone.Model` using `relation.relatedModel` if `attributes` is not null
                            if(!this.attributes[relation.key]){
                                //If `val` is already instance of  `AssociatedModel`, reserve `relation.key` for `Backbone.Model.prototype.set`
                                if(val instanceof Backbone.AssociatedModel) return this;
                                this.attributes[relation.key] = new relation.relatedModel();
                                refChanged = true;
                            }
                            //If the new attributes is a smaller subset, then use the default values for that attribute - if available.
                            else{
                                var opt = {};
                                var defaults = getValue(this.attributes[relation.key], 'defaults');
                                _.each(this.attributes[relation.key].attributes,function(value,key){
                                    !_.has(val,key) && (opt[key] = (defaults ? defaults[key] : void 0));
                                });
                                this.attributes[relation.key].set(opt,{silent:true});
                            }
                            //Set `val` to model with options
                            this.attributes[relation.key].set(val,options);
                        }
                        //Add proxy events to respective parents
                        this.attributes[relation.key].off("all");
                        this.attributes[relation.key].on("all",function(){return this.trigger.apply(this,arguments);},this);
                        //If reference has changed, trigger `change:attribute` event
                        refChanged && this.trigger('change:'+relation.key,options);
                        //Create a local `processedRelations` array to store the relation key which has been processed.
                        //We cannot use `this.relations` because if there is no value defined for `relation.key`, it will not get processed by either Backbone `set` or the `AssociatedModel` set
                        !processedRelations && (processedRelations=[]);
                        if(_.indexOf(processedRelations,relation.key)===-1){
                            processedRelations.push(relation.key);
                        }
                    }
                },this);
            };
            if(processedRelations){
                //Find attributes yet to be processed - `tbp`
                tbp = {};
                for(var key in attributes){
                    if(_.indexOf(processedRelations,key)===-1){
                        tbp[key] = attributes[key];
                    }
                }
            }
            //Set all `attributes` to `tbp`
            else{
                tbp = attributes;
            }
            //Returns results for `Backbone.Model.prototype.set`
            return Backbone.Model.prototype.set.call( this, tbp , options);
        },
        //Returns New `collection` of type `relation.relatedModel`
        _createCollection: function(type) {
            var collection;
            if ( type && type.prototype instanceof Backbone.AssociatedModel ) {
                //Creates new `Backbone.Collection` and defines model class
                collection = new Backbone.Collection();
                collection.model = type;
            }
            else{
                throw new Error( 'type must inherit from Backbone.AssociatedModel' );
            }
            return collection;
        },
        // `trigger` the event for `Associated Model`
        trigger : function(){
            //Check & Add `visited` tag to prevent event of cycle
            if(!this.visited){
                // mark as `visited`
                this.visited = true;
                Backbone.Model.prototype.trigger.apply(this,arguments);
                //delete `visited` tag to allow trigger for next `set` operation
                delete this.visited;
            }
            return this;
        },
        //The JSON representation of the model.
        toJSON : function(){
            var json;
            if(!this.visited){
                this.visited = true;
                //Get json representation from `Backbone.Model.prototype.toJSON`
                json = Backbone.Model.prototype.toJSON.apply( this, arguments );
                //If `this.relations` is defined, iterate through each `relation` and added it's json representation to parents' json representation
                if(this.relations){
                    _.each(this.relations ,function(relation){
                        var attr = this.attributes[relation.key];
                        if(attr){
                            aJson = attr.toJSON();
                            json[relation.key] = _.isArray(aJson)?_.compact(aJson):aJson;
                        }
                    },this);
                }
                delete this.visited;
            }
            return json;
        },
        //deep `clone` the model.
        clone : function(){
            var cloneObj;
            if(!this.visited){
                this.visited = true;
                //Get shallow clone from `Backbone.Model.prototype.clone`
                cloneObj = Backbone.Model.prototype.clone.apply( this, arguments );
                //If `this.relations` is defined, iterate through each `relation` and `clone`
                if(this.relations){
                    _.each(this.relations ,function(relation){
                        if(this.attributes[relation.key]){
                            var sourceObj = cloneObj.attributes[relation.key];
                            if(sourceObj instanceof Backbone.Collection){
                                //Creates new `collection` using `relation`
                                var newCollection = relation.collectionType ? new relation.collectionType() : this._createCollection(relation.relatedModel);
                                //Added each `clone` model to `newCollection`
                                sourceObj.each(function(model){
                                    var mClone = model.clone()
                                    mClone && newCollection.add(mClone);
                                });
                                cloneObj.attributes[relation.key] = newCollection;
                            }
                            else if(sourceObj instanceof Backbone.Model){
                                cloneObj.attributes[relation.key] = sourceObj.clone();
                            }
                        }
                    },this);
                }
                delete this.visited;
            }
            return cloneObj;
        }
    });
    // Duplicate Backbone's behavior. To get a value from a Backbone object as a property
    // or as a function.
    var getValue = function(object, prop) {
        if (!(object && object[prop])) return null;
        return _.isFunction(object[prop]) ? object[prop]() : object[prop];
    };
})();
<commit_msg>Pass relation-specific options to set/reset<commit_after>//
// Backbone-associations.js 0.2.0
//
// (c) 2012 Dhruva Ray, Jaynti Kanani
//
// Backbone-associations may be freely distributed under the MIT license; see the accompanying LICENSE.txt.
//
// Depends on [Backbone](https://github.com/documentcloud/backbone) (and thus on [Underscore](https://github.com/documentcloud/underscore/) as well)
//
// A complete [Test & Benchmark Suite](../test/test-suite.html) is included for your perusal.

// Initial Setup
// --------------
(function() {
    // The top-level namespace. All public Backbone classes and modules will be attached to this.
    // Exported for the browser and CommonJS.
    var _, Backbone;
    if ( typeof window === 'undefined' ) {
        _ = require( 'underscore' );
        Backbone = require( 'backbone' );
        exports = module.exports = Backbone;
    }
    else {
        _ = window._;
        Backbone = window.Backbone;
        exports = window;
    }
    // Backbone.AssociatedModel
    // --------------

    //Add `Many` and `One` relations to Backbone Object
    Backbone.Many  = "Many";
    Backbone.One  = "One";
    //Define `AssociatedModel` (Extends Backbone.Model)
    Backbone.AssociatedModel = Backbone.Model.extend({
        //Define relations with Associated Model
        relations: undefined,
        //Set a hash of model attributes on the object,
        //firing `"change"` unless you choose to silence it.
        //It maintains relations between models during the set operation. It also bubbles up child events to the parent.
        set: function( key, value, options ) {
            var attributes,processedRelations,tbp;
            // Duplicate backbone's behavior to allow separate key/value parameters, instead of a single 'attributes' object.
            if ( _.isObject( key ) || key == null ) {
                attributes = key;
                options = value;
            }
            else {
                attributes = {};
                attributes[ key ] = value;
            }
            // Extract attributes and options.
            options || (options = {});
            if(!attributes) return this;
            if (options.unset) for (attr in attributes) attributes[attr] = void 0;
            //Check for existence of relations in this model
            if(this.relations){
                //Iterate over `this.relations` and `set` model and collection values
                _.each(this.relations ,function(relation){
                    if (attributes[relation.key] != undefined ){
                        //Get value of attribute with relation key in `val`
                        var val = getValue(attributes,relation.key);
                        //Get class if relation is stored as a string
                        relation.relatedModel && _.isString(relation.relatedModel) && (relation.relatedModel = eval(relation.relatedModel));
                        relation.collectionType && _.isString(relation.collectionType) && (relation.collectionType = eval(relation.collectionType));
                        //Track reference change of associated model for `change:attribute` event
                        var refChanged = false;
                        //Merge in options specific to this relation
                        var relationOptions = options;
                        if (relation.options != undefined) _.extend(relationOptions,relation.options);
                        //If `relation` defines model as associated collection...
                        if(relation.type === Backbone.Many){
                            //`relation.collectionType` should be instance of `Backbone.Collection`
                            if(relation.collectionType && !relation.collectionType.prototype instanceof Backbone.Collection){
                                throw new Error( 'collectionType must inherit from Backbone.Collection' );
                            }
                            //Create new `Backbone.Collection` with `collectionType`
                            if(!this.attributes[relation.key]){
                                this.attributes[relation.key] = relation.collectionType ? new relation.collectionType() : this._createCollection(relation.relatedModel);
                                refChanged = true;
                            }
                            // Get all models if `val` is already instanceof `Backbone.Collection`
                            if(val instanceof Backbone.Collection){
                                val = val.models;
                            }
                            //Resetting new Collection with new value and options
                            this.attributes[relation.key].reset(val,relationOptions);
                        }
                        //If `relation` defines model as associated model...
                        else if(relation.type == Backbone.One && relation.relatedModel){
                            //Create New `Backbone.Model` using `relation.relatedModel` if `attributes` is not null
                            if(!this.attributes[relation.key]){
                                //If `val` is already instance of  `AssociatedModel`, reserve `relation.key` for `Backbone.Model.prototype.set`
                                if(val instanceof Backbone.AssociatedModel) return this;
                                this.attributes[relation.key] = new relation.relatedModel();
                                refChanged = true;
                            }
                            //If the new attributes is a smaller subset, then use the default values for that attribute - if available.
                            else{
                                var opt = {};
                                var defaults = getValue(this.attributes[relation.key], 'defaults');
                                _.each(this.attributes[relation.key].attributes,function(value,key){
                                    !_.has(val,key) && (opt[key] = (defaults ? defaults[key] : void 0));
                                });
                                this.attributes[relation.key].set(opt,{silent:true});
                            }
                            //Set `val` to model with options
                            this.attributes[relation.key].set(val,relationOptions);
                        }
                        //Add proxy events to respective parents
                        this.attributes[relation.key].off("all");
                        this.attributes[relation.key].on("all",function(){return this.trigger.apply(this,arguments);},this);
                        //If reference has changed, trigger `change:attribute` event
                        refChanged && this.trigger('change:'+relation.key);
                        //Create a local `processedRelations` array to store the relation key which has been processed.
                        //We cannot use `this.relations` because if there is no value defined for `relation.key`, it will not get processed by either Backbone `set` or the `AssociatedModel` set
                        !processedRelations && (processedRelations=[]);
                        if(_.indexOf(processedRelations,relation.key)===-1){
                            processedRelations.push(relation.key);
                        }
                    }
                },this);
            };
            if(processedRelations){
                //Find attributes yet to be processed - `tbp`
                tbp = {};
                for(var key in attributes){
                    if(_.indexOf(processedRelations,key)===-1){
                        tbp[key] = attributes[key];
                    }
                }
            }
            //Set all `attributes` to `tbp`
            else{
                tbp = attributes;
            }
            //Returns results for `Backbone.Model.prototype.set`
            return Backbone.Model.prototype.set.call( this, tbp , options);
        },
        //Returns New `collection` of type `relation.relatedModel`
        _createCollection: function(type) {
            var collection;
            if ( type && type.prototype instanceof Backbone.AssociatedModel ) {
                //Creates new `Backbone.Collection` and defines model class
                collection = new Backbone.Collection();
                collection.model = type;
            }
            else{
                throw new Error( 'type must inherit from Backbone.AssociatedModel' );
            }
            return collection;
        },
        // `trigger` the event for `Associated Model`
        trigger : function(){
            //Check & Add `visited` tag to prevent event of cycle
            if(!this.visited){
                // mark as `visited`
                this.visited = true;
                Backbone.Model.prototype.trigger.apply(this,arguments);
                //delete `visited` tag to allow trigger for next `set` operation
                delete this.visited;
            }
            return this;
        },
        //The JSON representation of the model.
        toJSON : function(){
            var json;
            if(!this.visited){
                this.visited = true;
                //Get json representation from `Backbone.Model.prototype.toJSON`
                json = Backbone.Model.prototype.toJSON.apply( this, arguments );
                //If `this.relations` is defined, iterate through each `relation` and added it's json representation to parents' json representation
                if(this.relations){
                    _.each(this.relations ,function(relation){
                        var attr = this.attributes[relation.key];
                        if(attr){
                            aJson = attr.toJSON();
                            json[relation.key] = _.isArray(aJson)?_.compact(aJson):aJson;
                        }
                    },this);
                }
                delete this.visited;
            }
            return json;
        },
        //deep `clone` the model.
        clone : function(){
            var cloneObj;
            if(!this.visited){
                this.visited = true;
                //Get shallow clone from `Backbone.Model.prototype.clone`
                cloneObj = Backbone.Model.prototype.clone.apply( this, arguments );
                //If `this.relations` is defined, iterate through each `relation` and `clone`
                if(this.relations){
                    _.each(this.relations ,function(relation){
                        if(this.attributes[relation.key]){
                            var sourceObj = cloneObj.attributes[relation.key];
                            if(sourceObj instanceof Backbone.Collection){
                                //Creates new `collection` using `relation`
                                var newCollection = relation.collectionType ? new relation.collectionType() : this._createCollection(relation.relatedModel);
                                //Added each `clone` model to `newCollection`
                                sourceObj.each(function(model){
                                    var mClone = model.clone()
                                    mClone && newCollection.add(mClone);
                                });
                                cloneObj.attributes[relation.key] = newCollection;
                            }
                            else if(sourceObj instanceof Backbone.Model){
                                cloneObj.attributes[relation.key] = sourceObj.clone();
                            }
                        }
                    },this);
                }
                delete this.visited;
            }
            return cloneObj;
        }
    });
    // Duplicate Backbone's behavior. To get a value from a Backbone object as a property
    // or as a function.
    var getValue = function(object, prop) {
        if (!(object && object[prop])) return null;
        return _.isFunction(object[prop]) ? object[prop]() : object[prop];
    };
})();
<|endoftext|>


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

'use strict';

let Sequelize = require('sequelize');
let db = syzoj.db;

let User = syzoj.model('user');
let Problem = syzoj.model('problem');
let Contest = syzoj.model('contest');

let model = db.define('judge_state', {
  id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },
  code: { type: Sequelize.TEXT('medium') },
  language: { type: Sequelize.STRING(20) },

  status: { type: Sequelize.STRING(50) },
  score: { type: Sequelize.INTEGER },
  total_time: { type: Sequelize.INTEGER },
  pending: { type: Sequelize.BOOLEAN },
  max_memory: { type: Sequelize.INTEGER },

  result: { type: Sequelize.TEXT('medium'), json: true },

  user_id: { type: Sequelize.INTEGER },

  problem_id: { type: Sequelize.INTEGER },

  submit_time: { type: Sequelize.INTEGER },
  /*
   * "type" indicate it's contest's submission(type = 1) or normal submission(type = 0)
   * type = 2: this is a test submission
   * if it's contest's submission (type = 1), the type_info is contest_id
   * use this way represent because it's easy to expand
   */
  type: { type: Sequelize.INTEGER },
  type_info: { type: Sequelize.INTEGER }
}, {
  timestamps: false,
  tableName: 'judge_state',
  indexes: [
    {
      fields: ['status'],
    },
    {
      fields: ['score'],
    },
    {
      fields: ['user_id'],
    },
    {
      fields: ['problem_id'],
    }
  ]
});

let Model = require('./common');
class JudgeState extends Model {
  static async create(val) {
    return JudgeState.fromRecord(JudgeState.model.build(Object.assign({
      code: '',
      language: '',
      user_id: 0,
      problem_id: 0,
      submit_time: parseInt((new Date()).getTime() / 1000),

      type: 0,
      type_info: '',

      pending: true,

      score: 0,
      total_time: 0,
      max_memory: 0,
      status: 'Waiting',
      result: '{ "status": "Waiting", "total_time": 0, "max_memory": 0, "score": 0, "case_num": 0, "compiler_output": "", "pending": true }'
    }, val)));
  }

  async loadRelationships() {
    this.user = await User.fromID(this.user_id);
    if (this.problem_id) this.problem = await Problem.fromID(this.problem_id);
  }

  async isAllowedVisitBy(user) {
    await this.loadRelationships();

    if (user && user.id === this.problem.user_id) return true;
    else if (this.type === 0 || this.type == 2) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
    else if (this.type === 1) {
      return user && (user.is_admin || user.id === this.user_id);
    }
  }

  async isAllowedSeeCodeBy(user) {
    await this.loadRelationships();

    if (user && user.id === this.problem.user_id) return true;
    else if (this.type === 0 || this.type === 2) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
    else if (this.type === 1) {
      let contest = await Contest.fromID(this.type_info);
      if (await contest.isRunning()) {
        return (user && this.user_id === user.id) || (user && user.is_admin);
      } else {
        return true;
      }
    }
  }

  async isAllowedSeeCaseBy(user) {
    await this.loadRelationships();

    if (user && user.id === this.problem.user_id) return true;
    else if (this.type === 0 || this.type === 2) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
    else if (this.type === 1) {
      let contest = await Contest.fromID(this.type_info);
      if (await contest.isRunning()) {
        return contest.type === 'ioi' || (user && user.is_admin);
      } else {
        return true;
      }
    }
  }

  async isAllowedSeeDataBy(user) {
    await this.loadRelationships();

    if (user && user.id === this.problem.user_id) return true;
    else if (this.type === 0 || this.type === 2) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
    else if (this.type === 1) {
      let contest = await Contest.fromID(this.type_info);
      if (await contest.isRunning()) {
        return user && user.is_admin;
      } else {
        return true;
      }
    }
  }

  async updateResult(result) {
    this.score = result.score;
    this.pending = result.pending;
    this.status = result.status;
    this.total_time = result.total_time;
    this.max_memory = result.max_memory;
    this.result = result;
  }

  async updateRelatedInfo(newSubmission) {
    if (this.type === 0 || this.type === 2) {
      if (newSubmission) {
        await this.loadRelationships();
        await this.user.refreshSubmitInfo();
        this.problem.submit_num++;
        await this.user.save();
        await this.problem.save();
      } else if (this.status === 'Accepted') {
        await this.loadRelationships();
        await this.user.refreshSubmitInfo();
        this.problem.ac_num++;
        await this.user.save();
        await this.problem.save();
      }
    } else if (this.type === 1) {
      let contest = await Contest.fromID(this.type_info);
      await contest.newSubmission(this);
    } else if (this.type === 2) {
      if (newSubmission || this.status === 'Accepted') {
        await this.loadRelationships();
        await this.user.refreshSubmitInfo();
        await this.user.save();
      }
    }
  }

  async rejudge() {
    await syzoj.utils.lock(['JudgeState::rejudge', this.id], async () => {
      await this.loadRelationships();

      let oldStatus = this.status;

      this.status = 'Waiting';
      this.score = 0;
      this.total_time = 0;
      this.max_memory = 0;
      this.pending = true;
      this.result = { status: "Waiting", total_time: 0, max_memory: 0, score: 0, case_num: 0, compiler_output: "", pending: true };
      await this.save();

      let WaitingJudge = syzoj.model('waiting_judge');
      let waiting_judge = await WaitingJudge.create({
        judge_id: this.id
      });

      await waiting_judge.save();

      if (oldStatus === 'Accepted') {
        await this.user.refreshSubmitInfo();
        await this.user.save();
      }

      if (this.type === 0 || this.type === 2) {
        if (oldStatus === 'Accepted') {
          this.problem.ac_num--;
          await this.problem.save();
        }
      } else if (this.type === 1) {
        let contest = await Contest.fromID(this.type_info);
        await contest.newSubmission(this);
      }
    });
  }

  getModel() { return model; }
}

JudgeState.model = model;

module.exports = JudgeState;
<commit_msg>Fix can't see submission after contest<commit_after>/*
 *  This file is part of SYZOJ.
 *
 *  Copyright (c) 2016 Menci <huanghaorui301@gmail.com>
 *
 *  SYZOJ is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  SYZOJ is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public
 *  License along with SYZOJ. If not, see <http://www.gnu.org/licenses/>.
 */

'use strict';

let Sequelize = require('sequelize');
let db = syzoj.db;

let User = syzoj.model('user');
let Problem = syzoj.model('problem');
let Contest = syzoj.model('contest');

let model = db.define('judge_state', {
  id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },
  code: { type: Sequelize.TEXT('medium') },
  language: { type: Sequelize.STRING(20) },

  status: { type: Sequelize.STRING(50) },
  score: { type: Sequelize.INTEGER },
  total_time: { type: Sequelize.INTEGER },
  pending: { type: Sequelize.BOOLEAN },
  max_memory: { type: Sequelize.INTEGER },

  result: { type: Sequelize.TEXT('medium'), json: true },

  user_id: { type: Sequelize.INTEGER },

  problem_id: { type: Sequelize.INTEGER },

  submit_time: { type: Sequelize.INTEGER },
  /*
   * "type" indicate it's contest's submission(type = 1) or normal submission(type = 0)
   * type = 2: this is a test submission
   * if it's contest's submission (type = 1), the type_info is contest_id
   * use this way represent because it's easy to expand
   */
  type: { type: Sequelize.INTEGER },
  type_info: { type: Sequelize.INTEGER }
}, {
  timestamps: false,
  tableName: 'judge_state',
  indexes: [
    {
      fields: ['status'],
    },
    {
      fields: ['score'],
    },
    {
      fields: ['user_id'],
    },
    {
      fields: ['problem_id'],
    }
  ]
});

let Model = require('./common');
class JudgeState extends Model {
  static async create(val) {
    return JudgeState.fromRecord(JudgeState.model.build(Object.assign({
      code: '',
      language: '',
      user_id: 0,
      problem_id: 0,
      submit_time: parseInt((new Date()).getTime() / 1000),

      type: 0,
      type_info: '',

      pending: true,

      score: 0,
      total_time: 0,
      max_memory: 0,
      status: 'Waiting',
      result: '{ "status": "Waiting", "total_time": 0, "max_memory": 0, "score": 0, "case_num": 0, "compiler_output": "", "pending": true }'
    }, val)));
  }

  async loadRelationships() {
    this.user = await User.fromID(this.user_id);
    if (this.problem_id) this.problem = await Problem.fromID(this.problem_id);
  }

  async isAllowedVisitBy(user) {
    await this.loadRelationships();

    if (user && user.id === this.problem.user_id) return true;
    else if (this.type === 0 || this.type == 2) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
    else if (this.type === 1) {
      let contest = await Contest.fromID(this.type_info);
      if (await contest.isRunning()) {
        return (user && this.user_id === user.id) || (user && user.is_admin);
      } else {
        return true;
      }
    }
  }

  async isAllowedSeeCodeBy(user) {
    await this.loadRelationships();

    if (user && user.id === this.problem.user_id) return true;
    else if (this.type === 0 || this.type === 2) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
    else if (this.type === 1) {
      let contest = await Contest.fromID(this.type_info);
      if (await contest.isRunning()) {
        return (user && this.user_id === user.id) || (user && user.is_admin);
      } else {
        return true;
      }
    }
  }

  async isAllowedSeeCaseBy(user) {
    await this.loadRelationships();

    if (user && user.id === this.problem.user_id) return true;
    else if (this.type === 0 || this.type === 2) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
    else if (this.type === 1) {
      let contest = await Contest.fromID(this.type_info);
      if (await contest.isRunning()) {
        return contest.type === 'ioi' || (user && user.is_admin);
      } else {
        return true;
      }
    }
  }

  async isAllowedSeeDataBy(user) {
    await this.loadRelationships();

    if (user && user.id === this.problem.user_id) return true;
    else if (this.type === 0 || this.type === 2) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
    else if (this.type === 1) {
      let contest = await Contest.fromID(this.type_info);
      if (await contest.isRunning()) {
        return user && user.is_admin;
      } else {
        return true;
      }
    }
  }

  async updateResult(result) {
    this.score = result.score;
    this.pending = result.pending;
    this.status = result.status;
    this.total_time = result.total_time;
    this.max_memory = result.max_memory;
    this.result = result;
  }

  async updateRelatedInfo(newSubmission) {
    if (this.type === 0 || this.type === 2) {
      if (newSubmission) {
        await this.loadRelationships();
        await this.user.refreshSubmitInfo();
        this.problem.submit_num++;
        await this.user.save();
        await this.problem.save();
      } else if (this.status === 'Accepted') {
        await this.loadRelationships();
        await this.user.refreshSubmitInfo();
        this.problem.ac_num++;
        await this.user.save();
        await this.problem.save();
      }
    } else if (this.type === 1) {
      let contest = await Contest.fromID(this.type_info);
      await contest.newSubmission(this);
    } else if (this.type === 2) {
      if (newSubmission || this.status === 'Accepted') {
        await this.loadRelationships();
        await this.user.refreshSubmitInfo();
        await this.user.save();
      }
    }
  }

  async rejudge() {
    await syzoj.utils.lock(['JudgeState::rejudge', this.id], async () => {
      await this.loadRelationships();

      let oldStatus = this.status;

      this.status = 'Waiting';
      this.score = 0;
      this.total_time = 0;
      this.max_memory = 0;
      this.pending = true;
      this.result = { status: "Waiting", total_time: 0, max_memory: 0, score: 0, case_num: 0, compiler_output: "", pending: true };
      await this.save();

      let WaitingJudge = syzoj.model('waiting_judge');
      let waiting_judge = await WaitingJudge.create({
        judge_id: this.id
      });

      await waiting_judge.save();

      if (oldStatus === 'Accepted') {
        await this.user.refreshSubmitInfo();
        await this.user.save();
      }

      if (this.type === 0 || this.type === 2) {
        if (oldStatus === 'Accepted') {
          this.problem.ac_num--;
          await this.problem.save();
        }
      } else if (this.type === 1) {
        let contest = await Contest.fromID(this.type_info);
        await contest.newSubmission(this);
      }
    });
  }

  getModel() { return model; }
}

JudgeState.model = model;

module.exports = JudgeState;
<|endoftext|>


<commit_before>import Component from '@glimmer/component';
import ConfirmCreateModal from './edit-newsletter/confirm-create';
import ConfirmNewsletterEmailModal from './edit-newsletter/confirm-newsletter-email';
import {action} from '@ember/object';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency';
import {tracked} from '@glimmer/tracking';

export default class EditNewsletterModal extends Component {
    @service modals;
    @service store;

    static modalOptions = {
        className: 'fullscreen-modal-full-overlay fullscreen-modal-portal-settings'
    };

    @tracked tab = 'settings';
    @tracked optInExisting = this.args.data.newsletter.isNew;

    get activeNewsletterSlugs() {
        const activeNewsletters = this.store.peekAll('newsletter').filter((n) => {
            return n.status === 'active' && !n.isNew && !n.isDestroyed;
        });

        return activeNewsletters.map(n => n.slug);
    }

    willDestroy() {
        super.willDestroy(...arguments);
        this.args.data.newsletter.rollbackAttributes();
    }

    @action
    changeTab(tab) {
        this.tab = tab;
    }

    @action
    saveViaKeyboard(event, responder) {
        responder.stopPropagation();
        event.preventDefault();

        this.saveTask.perform();
    }

    @action
    setOptInExisting(value) {
        this.optInExisting = value;
    }

    @task
    *saveTask() {
        try {
            yield this.args.data.newsletter.validate({});

            const {optInExisting} = this;

            const shouldCreate = yield this.modals.open(ConfirmCreateModal, {
                optInExisting,
                newsletter: this.args.data.newsletter,
                activeNewsletterSlugs: this.activeNewsletterSlugs
            });

            if (!shouldCreate) {
                // ensure task button returns to idle state
                return 'canceled';
            }

            const newEmail = this.args.data.newsletter.senderEmail;

            const result = yield this.args.data.newsletter.save({
                adapterOptions: {optInExisting}
            });

            if (result._meta?.sent_email_verification) {
                yield this.modals.open(ConfirmNewsletterEmailModal, {
                    newEmail,
                    currentEmail: this.args.data.newsletter.senderEmail
                });
            }

            this.args.data.afterSave?.(result);

            return result;
        } catch (e) {
            if (e === undefined) {
                // ensure task button shows failed state
                throw new Error('Validation failed');
            }

            throw e;
        }
    }
}
<commit_msg>Fixed create newsletter confirmation showing when editing existing newsletter<commit_after>import Component from '@glimmer/component';
import ConfirmCreateModal from './edit-newsletter/confirm-create';
import ConfirmNewsletterEmailModal from './edit-newsletter/confirm-newsletter-email';
import {action} from '@ember/object';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency';
import {tracked} from '@glimmer/tracking';

export default class EditNewsletterModal extends Component {
    @service modals;
    @service store;

    static modalOptions = {
        className: 'fullscreen-modal-full-overlay fullscreen-modal-portal-settings'
    };

    @tracked tab = 'settings';
    @tracked optInExisting = this.args.data.newsletter.isNew;

    get activeNewsletterSlugs() {
        const activeNewsletters = this.store.peekAll('newsletter').filter((n) => {
            return n.status === 'active' && !n.isNew && !n.isDestroyed;
        });

        return activeNewsletters.map(n => n.slug);
    }

    willDestroy() {
        super.willDestroy(...arguments);
        this.args.data.newsletter.rollbackAttributes();
    }

    @action
    changeTab(tab) {
        this.tab = tab;
    }

    @action
    saveViaKeyboard(event, responder) {
        responder.stopPropagation();
        event.preventDefault();

        this.saveTask.perform();
    }

    @action
    setOptInExisting(value) {
        this.optInExisting = value;
    }

    @task
    *saveTask() {
        try {
            yield this.args.data.newsletter.validate({});

            const {optInExisting} = this;

            if (this.args.data.newsletter.isNew) {
                const shouldCreate = yield this.modals.open(ConfirmCreateModal, {
                    optInExisting,
                    newsletter: this.args.data.newsletter,
                    activeNewsletterSlugs: this.activeNewsletterSlugs
                });

                if (!shouldCreate) {
                    // ensure task button returns to idle state
                    return 'canceled';
                }
            }

            const newEmail = this.args.data.newsletter.senderEmail;

            const result = yield this.args.data.newsletter.save({
                adapterOptions: {optInExisting}
            });

            if (result._meta?.sent_email_verification) {
                yield this.modals.open(ConfirmNewsletterEmailModal, {
                    newEmail,
                    currentEmail: this.args.data.newsletter.senderEmail
                });
            }

            this.args.data.afterSave?.(result);

            return result;
        } catch (e) {
            if (e === undefined) {
                // ensure task button shows failed state
                throw new Error('Validation failed');
            }

            throw e;
        }
    }
}
<|endoftext|>


<commit_before>'use strict'

var fs = require('fs')
var rollup = require('rollup')
var uglify = require('uglify-js')
var babel = require('rollup-plugin-babel')
var execSync = require('child_process').execSync

bundle({
  minified: 'dist/jspdf.customfonts.min.js',
  debug: 'dist/jspdf.customfonts.debug.js'
})

// Monkey patching adler32 and filesaver
function monkeyPatch() {
  return {
    transform: (code, id) => {
      var file = id.split('/').pop()
      if (file === 'adler32cs.js') {
        code = code.replace(/this, function/g, 'jsPDF, function')
        code = code.replace(/require\('buffer'\)/g, '{}')
      }
      return code
    }
  }
}

// Rollup removes local variables unless used within a module.
// This plugin makes sure specified local variables are preserved
// and kept local. This plugin wouldn't be necessary if es2015
// modules would be used.
function rawjs(opts) {
  opts = opts || {}
  return {
    transform: (code, id) => {
      var variable = opts[id.split('/').pop()]
      if (!variable) return code

      var keepStr = '/*rollup-keeper-start*/window.tmp=' + variable +
        ';/*rollup-keeper-end*/'
      return code + keepStr
    },
    transformBundle: (code) => {
      for (var file in opts) {
        var r = new RegExp(opts[file] + '\\$\\d+', 'g')
        code = code.replace(r, opts[file])
      }
      var re = /\/\*rollup-keeper-start\*\/.*\/\*rollup-keeper-end\*\//g
      return code.replace(re, '')
    }
  }
}

function bundle(paths) {
  rollup.rollup({
    entry: './main.js',
    plugins: [
      monkeyPatch(),
      rawjs({
        'jspdf.js': 'jsPDF',
        'filesaver.tmp.js': 'saveAs',
        'deflate.js': 'Deflater',
        'zlib.js': 'FlateStream',
        'css_colors.js': 'CssColors',
        'html2pdf.js': 'html2pdf'
      }),
      babel({
        presets: ['es2015-rollup'],
        exclude: ['node_modules/**', 'libs/**']
      })
    ]
  }).then((bundle) => {
    return bundle.generate({
      format: 'umd',
      moduleName: 'jspdf'
    })
  }).then(output => {
    let code = output.code
    code = code.replace(
      /Permission\s+is\s+hereby\s+granted[\S\s]+?IN\s+THE\s+SOFTWARE\./,
      'Licensed under the MIT License'
    )
    code = code.replace(
      /Permission\s+is\s+hereby\s+granted[\S\s]+?IN\s+THE\s+SOFTWARE\./g,
      ''
    )
    fs.writeFileSync(paths.debug, renew(code))

    var minified = uglify.minify(code, {
      output: {
        comments: /@preserve|@license|copyright/i
      }
    })
    fs.writeFileSync(paths.minified, renew(minified.code))
  }).catch((err) => {
    console.error(err)
  })
}

function renew(code) {
  var date = new Date().toISOString()
  var version = require('./package.json').version
  var whoami = execSync('whoami').toString().trim()
  var commit = execSync('git rev-parse --short=10 HEAD').toString().trim()
  code = code.replace('${versionID}', version + ' Built on ' + date)
  code = code.replace('${commitID}', commit)
  code = code.replace(/1\.0\.0-trunk/, version + ' ' + date + ':' + whoami)

  return code
}<commit_msg>fix build error<commit_after>'use strict'

var fs = require('fs')
var rollup = require('rollup')
var uglify = require('uglify-js')
var babel = require('rollup-plugin-babel')
var execSync = require('child_process').execSync

bundle({
  minified: 'dist/jspdf.customfonts.min.js',
  debug: 'dist/jspdf.customfonts.debug.js'
})

// Monkey patching adler32 and filesaver
function monkeyPatch() {
  return {
    transform: (code, id) => {
      var file = id.split('/').pop()

      if (file === 'adler32cs.js') {
        // Make library assign itself to the jsPDF instance instead
        // of window to avoid polluting global scope
        code = code.replace(/this, function/g, 'jsPDF, function')

        // Remove call to require('buffer') since it is not used and
        // might import a large arbitrary buffer library if a user is
        // using a commonjs module bundler
        code = code.replace(/require\('buffer'\)/g, '{}')
      }

      // Only one define call per module is allowed by requirejs so
      // we have to remove calls that other libraries make
      if (file === 'adler32cs.js') {
        code = code.replace(/typeof define/g, '0')
      } else if (file === 'FileSaver.js') {
        code = code.replace(/define !== null\) && \(define.amd != null/g, '0')
      } else if (file === 'html2canvas.js') {
        code = code.replace(/&&\s+define.amd/g, '&& define.amd && false')
      }

      return code
    }
  }
}

// Rollup removes local variables unless used within a module.
// This plugin makes sure specified local variables are preserved
// and kept local. This plugin wouldn't be necessary if es2015
// modules would be used.
function rawjs(opts) {
  opts = opts || {}
  return {
    transform: (code, id) => {
      var variable = opts[id.split('/').pop()]
      if (!variable) return code

      var keepStr = '/*rollup-keeper-start*/window.tmp=' + variable +
        ';/*rollup-keeper-end*/'
      return code + keepStr
    },
    transformBundle: (code) => {
      for (var file in opts) {
        var r = new RegExp(opts[file] + '\\$\\d+', 'g')
        code = code.replace(r, opts[file])
      }
      var re = /\/\*rollup-keeper-start\*\/.*\/\*rollup-keeper-end\*\//g
      return code.replace(re, '')
    }
  }
}

function bundle(paths) {
  rollup.rollup({
    entry: './main.js',
    context: 'window',
    plugins: [
      monkeyPatch(),
      rawjs({
        'jspdf.js': 'jsPDF',
        'filesaver.tmp.js': 'saveAs',
        'deflate.js': 'Deflater',
        'zlib.js': 'FlateStream',
        'css_colors.js': 'CssColors',
        'html2pdf.js': 'html2pdf'
      }),
      babel({
        presets: ['es2015-rollup'],
        exclude: ['node_modules/**', 'libs/**']
      })
    ]
  }).then((bundle) => {
    return bundle.generate({
      format: 'umd',
      name: 'jsPDF'
    })
  }).then(output => {
    let code = output.code
    code = code.replace(
      /Permission\s+is\s+hereby\s+granted[\S\s]+?IN\s+THE\s+SOFTWARE\./,
      'Licensed under the MIT License'
    )
    code = code.replace(
      /Permission\s+is\s+hereby\s+granted[\S\s]+?IN\s+THE\s+SOFTWARE\./g,
      ''
    )
    fs.writeFileSync(paths.debug, renew(code))

    var minified = uglify.minify(code, {
      output: {
        comments: /@preserve|@license|copyright/i
      }
    })
    fs.writeFileSync(paths.minified, renew(minified.code))
  }).catch((err) => {
    console.error(err)
  })
}

function renew(code) {
  var date = new Date().toISOString()
  var version = require('./package.json').version
  var whoami = execSync('whoami').toString().trim()
  var commit = execSync('git rev-parse --short=10 HEAD').toString().trim()
  code = code.replace('${versionID}', version + ' Built on ' + date)
  code = code.replace('${commitID}', commit)
  code = code.replace(/1\.0\.0-trunk/, version + ' ' + date + ':' + whoami)

  return code
}<|endoftext|>


<commit_before>var request = require('request'),
  Faker = require('faker'),
  debug = require('debug')('person:rapportive'),
  url = require('url');

var RAPPORTIVE_BASE_URL = 'https://rapportive.com',
  RAPPORTIVE_PROFILES_BASE_URL = 'https://profiles.rapportive.com',
  BETWEEN_ATTEMPTS = 60000,
  RATE_LIMIT_MAX = 599;

module.exports = Rapportive;

function Rapportive(opt) {
  this._init(opt);
}

var fn = Rapportive.prototype;

fn._init = function (opt) {
  opt = opt || {};
  this.endpoint = opt.endpoint || RAPPORTIVE_BASE_URL;
  this.profiles_endpoint = opt.profiles_endpoint || RAPPORTIVE_PROFILES_BASE_URL;
  this.sessions = [];
};

fn._request = function (req, cb) {
  req.uri = url.resolve(
    (req.endpoint = 'profiles' ? this.profiles_endpoint : this.endpoint), req.uri);
  req.json = true;
  return request(req, cb);
};

fn.login = function (person, cb) {
  var self = this;
  self._request({uri: '/login_status?user_email=' + person.email}, function (e, r, b) {
    if (!e && r.statusCode === 200) {
      debug('+ ' + b.session_token + ' (' + person.email + ')');
      self.sessions.push({
        email: person.email,
        first_name: person.first_name,
        last_name: person.last_name,
        session_token: b.session_token,
        rate_limit_uses: 0,
        last_use: Date.now() - BETWEEN_ATTEMPTS // one minute
      });
      return cb();
    }
    cb(new Error('Login failed with status code ' + r.statusCode));
  });
};

fn.get_profile = function (email, session_token, cb) {
  var self = this;
  debug('... looking up ' + email);
  self._request({
    endpoint: 'profiles',
    uri: '/contacts/email/' + email,
    headers : {'X-Session-Token' : session_token}
  }, function (e, r, b) {
    if (!e && r.statusCode === 200) {
      var contact = b.contact;
      return cb({
        email: email,
        ok: true,
        rapportive: contact
      });
    }
    cb({ error: (e && e.message || 'status code was ' + r.statusCode) });
  });
};

fn.get_profile_no_rate_limit = function (email, cb) {
  var self = this;
  var i = Math.floor(Math.random() * self.sessions.length);
  var session = self.sessions[i];

  if(session && session.session_token && session.rate_limit_uses !== RATE_LIMIT_MAX &&
    Date.now() - session.last_use > BETWEEN_ATTEMPTS) {
    debug('> ' + session.session_token + ' (' + session.rate_limit_uses +
      ', ' + session.email + ')');
    self.get_profile(email, session.session_token, cb);
  } else {
    if(session && session.rate_limit_uses === RATE_LIMIT_MAX) {
      debug('- ' + session.session_token);
      delete self.sessions[i];
    }

    var fakePerson = {
      first_name: Faker.Name.firstName().replace(/\W+/g, ''),
      last_name: Faker.Name.lastName().replace(/\W+/g, ''),
    };

    fakePerson.email = (fakePerson.first_name + '.' + fakePerson.last_name +
      '@gmail.com').toLowerCase();

    debug('login attempt with ' + fakePerson.email);
    self.login(fakePerson, function (err) {
      if(err) {
        debug(err);
        return cb(err);
      }
      self.get_profile_no_rate_limit(email, cb);
    });
  }
};

<commit_msg>[fix] Actually increment the session uses.<commit_after>var request = require('request'),
  Faker = require('faker'),
  debug = require('debug')('person:rapportive'),
  url = require('url');

var RAPPORTIVE_BASE_URL = 'https://rapportive.com',
  RAPPORTIVE_PROFILES_BASE_URL = 'https://profiles.rapportive.com',
  BETWEEN_ATTEMPTS = 60000,
  RATE_LIMIT_MAX = 599;

module.exports = Rapportive;

function Rapportive(opt) {
  this._init(opt);
}

var fn = Rapportive.prototype;

fn._init = function (opt) {
  opt = opt || {};
  this.endpoint = opt.endpoint || RAPPORTIVE_BASE_URL;
  this.profiles_endpoint = opt.profiles_endpoint || RAPPORTIVE_PROFILES_BASE_URL;
  this.sessions = [];
};

fn._request = function (req, cb) {
  req.uri = url.resolve(
    (req.endpoint = 'profiles' ? this.profiles_endpoint : this.endpoint), req.uri);
  req.json = true;
  return request(req, cb);
};

fn.login = function (person, cb) {
  var self = this;
  self._request({uri: '/login_status?user_email=' + person.email}, function (e, r, b) {
    if (!e && r.statusCode === 200) {
      debug('+ ' + b.session_token + ' (' + person.email + ')');
      var session = {
        email: person.email,
        first_name: person.first_name,
        last_name: person.last_name,
        session_token: b.session_token,
        rate_limit_uses: 0,
        last_use: Date.now() - BETWEEN_ATTEMPTS // one minute
      };

      self.sessions.push(session);
      return cb(null, session);
    }

    cb(new Error('Login failed with status code ' + r.statusCode));
  });
};

fn.get_profile = function (email, session, cb) {
  var self = this;
  debug('... looking up ' + email);
  session.rate_limit_uses++;
  self._request({
    endpoint: 'profiles',
    uri: '/contacts/email/' + email,
    headers : {'X-Session-Token' : session.session_token}
  }, function (e, r, b) {
    if (!e && r.statusCode === 200) {
      var contact = b.contact;
      return cb({
        email: email,
        ok: true,
        rapportive: contact
      });
    }
    else if (r.statusCode === 403) {
      //
      // Remark: This is probably IP address rate-limiting so maybe return the error?
      // https://github.com/jordan-wright/rapportive/issues/11
      //
      self.sessions.splice(self.sessions.indexOf(session), 1);
      return self.get_profile_no_rate_limit(email, cb);
    }

    cb({ error: (e && e.message || 'status code was ' + r.statusCode) });
  });
};

fn.get_profile_no_rate_limit = function (email, cb) {
  var i = Math.floor(Math.random() * this.sessions.length),
      session = this.sessions[i],
      self = this;

  if (session && session.session_token && session.rate_limit_uses !== RATE_LIMIT_MAX &&
    Date.now() - session.last_use > BETWEEN_ATTEMPTS) {
    debug('> ' + session.session_token + ' (' + session.rate_limit_uses + ', ' + session.email + ')');
    self.get_profile(email, session, cb);
  }
  else {
    if (session && session.rate_limit_uses === RATE_LIMIT_MAX) {
      debug('- ' + session.session_token);
      delete self.sessions[i];
    }

    var fakePerson = {
      first_name: Faker.Name.firstName().replace(/\W+/g, ''),
      last_name: Faker.Name.lastName().replace(/\W+/g, ''),
    };

    fakePerson.email = (fakePerson.first_name + '.' + fakePerson.last_name + '@gmail.com').toLowerCase();

    debug('login attempt with ' + fakePerson.email);
    self.login(fakePerson, function (err, session_) {
      if (err) {
        debug(err);
        return cb(err);
      }

      self.get_profile(email, session_, cb);
    });
  }
};

<|endoftext|>


<commit_before>import React from 'react';
import {connectToStores} from 'fluxible-addons-react';
import DeckViewStore from '../../../../../stores/DeckViewStore';
import Thumbnail from '../../../../common/Thumbnail';
import CustomDate from '../../../util/CustomDate';
import ISO6391 from 'iso-639-1';
import cheerio from 'cheerio';
import lodash from 'lodash';
import {Microservices} from '../../../../../configs/microservices';
import {NavLink} from 'fluxible-router';

import { Dropdown, Menu, Flag } from 'semantic-ui-react';

import {navigateAction} from 'fluxible-router';

import ContentLikeStore from '../../../../../stores/ContentLikeStore';
import UserProfileStore from '../../../../../stores/UserProfileStore';
import TranslationStore from '../../../../../stores/TranslationStore';
import ContentStore from '../../../../../stores/ContentStore';
import loadLikes from '../../../../../actions/activityfeed/loadLikes';

import TranslationPanel from '../../../TranslationPanel/TranslationPanel.js';

class DeckViewPanel extends React.Component {
    getTextFromHtml(html) {
        let text = cheerio.load(html).text();
        if (text.length > 25) {
            text = text.substr(0, 21) + '...';
        }
        return text;
    }

    render() {
        const heightStyle = {
            //height: this.props.DeckViewStore.deckViewPanelHeight + 'px',
            minHeight: this.props.DeckViewStore.deckViewPanelHeight,
            overflowY: 'auto',
            overflowX: 'auto'
        };
        const deckData = this.props.DeckViewStore.deckData;
        let slidesArr = [];
        if (this.props.DeckViewStore.slidesData && this.props.DeckViewStore.slidesData.children) {
            slidesArr = this.props.DeckViewStore.slidesData.children;
        }
        let tags = [];
        if (deckData && deckData.tags){
            tags = deckData.tags;
        }
        let currentRevision = 1;
        if(deckData.revisions){
            currentRevision = deckData.revisions.length === 1 ? deckData.revisions[0] : deckData.revisions.find((rev) => {
                return rev.id === deckData.active;
            });
        }

        const forkCount = deckData.forkCount;
        const shareCount = deckData.shareCount;
        const downloadCount = deckData.downloadCount;

        //const deckTheme = lodash.get(deckData, 'theme', 'Simple');
        let deckTheme = currentRevision.theme;
        switch (deckTheme) {
            case 'default':
                deckTheme = 'White - Default';
                break;
            case 'beige':
                deckTheme = 'Cream';
                break;
            case 'black':
                deckTheme = 'Black';
                break;
            case 'league':
                deckTheme = 'Black';
                break;
            case 'sky':
                deckTheme = 'sky';
                break;
            case 'solarized':
                deckTheme = 'Beige';
                break;
            case 'moon':
                deckTheme = 'Dark Slate Blue';
                break;
            case 'night':
                deckTheme = 'High Contrast 1';
                break;
            case 'blood':
                deckTheme = 'High Contrast 2';
                break;
            case 'serif':
                deckTheme = 'Serif';
                break;
            case 'simple':
                deckTheme = 'Simple';
                break;
            case 'openuniversity':
                deckTheme = 'Open University';
                break;
            case 'odimadrid':
                deckTheme = 'ODI Madrid';
                break;
            case 'oeg':
                deckTheme = 'OEG';
                break;
            default:
        }
        const deckLicense = deckData.license;
        const deckTitle = currentRevision.title;
        const deckDate = CustomDate.format(deckData.timestamp, 'Do MMMM YYYY');
        const deckDescription = lodash.get(deckData, 'description', '');
        const deckCreator = this.props.DeckViewStore.creatorData.username;
        const deckOwner = this.props.DeckViewStore.ownerData.username;
        const originCreator = this.props.DeckViewStore.originCreatorData.username;

        let deckLanguageCode = deckData.language === undefined ? 'en' : deckData.language;
        let deckLanguage = deckLanguageCode === undefined ? '' : ISO6391.getName(deckLanguageCode);
        // default English
        deckLanguage = (deckLanguage === '' ? 'English' : deckLanguage);
        //const deckLanguageCode = lodash.get(deckData, 'language', undefined);
        //const deckLanguage = deckLanguageCode === undefined ? 'English' : ISO6391.getName(deckLanguageCode.substr(0, 2));
        // // TODO when flag code is available, remove the hard coded flag and update the respective JSX.
        // //const countryFlag = 'gb';
        //let translations = this.props.TranslationStore.translations;
        const totalSlides = lodash.get(this.props.DeckViewStore.slidesData, 'children.length', undefined);
        const maxSlideThumbnails = 3;

        const totalLikes = this.props.ContentLikeStore.usersWhoLikedDeck.length;

        const deckURL = '/deck/' + this.props.selector.id;
        const creatorProfileURL = '/user/' + deckCreator;
        const ownerProfileURL = '/user/' + deckOwner;

        const user = this.props.UserProfileStore.userid;

        let originInfo = deckData.origin != null ?
Origin:
                <NavLink href={'/deck/' + deckData.origin.id + '-' + deckData.origin.revision}>{deckData.origin.title}</NavLink> by {originCreator}

 : '';

        return (

                        {(this.props.TranslationStore.inProgress) ?

Translating

 : ''}

                            {(deckTitle === undefined) ?

Loading

 : ''}

{deckTitle}

Creator:
                                            {deckCreator}

                                        {originInfo}

Date: {deckDate}

                                        {deckDescription &&

Description:

{deckDescription}

                                        }

                                            {deckLanguage}

                                        {/* <TranslationPanel/>*/}

                                            {totalSlides}

                                            {forkCount}

                                            {totalLikes}

                                            {shareCount}

                                            {downloadCount}

                                {tags.length > 0 ?

 : ''}

                                    {tags.map((tag, index) => {
                                        return {tag};
                                    })}

                        {/* Read https://slidewiki.atlassian.net/wiki/display/SWIK/How+To+Use+Slide+Thumbnail to know the details */}
                        {slidesArr.map((slide, index) => {
                            let thumbnailURL = `${Microservices.file.uri}/thumbnail/slide/${slide.id}`;
                            if (slide.theme) {
                                thumbnailURL += '/' + slide.theme;
                            }
                            if (index < maxSlideThumbnails) {
                                return (

                                                    <Thumbnail key={index}
                                                        url={thumbnailURL}
                                                        slideId={slide.id} alt={''} abIndex={-1}/>

                                                {this.getTextFromHtml(slide.title)}

Slide {index + 1} of {totalSlides}

                                );
                            }
                        })}

        );
    }
}

DeckViewPanel.contextTypes = {
    executeAction: React.PropTypes.func.isRequired
};

DeckViewPanel = connectToStores(DeckViewPanel, [DeckViewStore, ContentLikeStore, UserProfileStore, ContentStore, TranslationStore], (context, props) => {
    return {
        DeckViewStore: context.getStore(DeckViewStore).getState(),
        ContentLikeStore: context.getStore(ContentLikeStore).getState(),
        UserProfileStore: context.getStore(UserProfileStore).getState(),
        ContentStore: context.getStore(ContentStore).getState(),
        TranslationStore: context.getStore(TranslationStore).getState(),
    };
});
export default DeckViewPanel;
<commit_msg>clean up metadata<commit_after>import React from 'react';
import {connectToStores} from 'fluxible-addons-react';
import DeckViewStore from '../../../../../stores/DeckViewStore';
import Thumbnail from '../../../../common/Thumbnail';
import CustomDate from '../../../util/CustomDate';
import ISO6391 from 'iso-639-1';
import cheerio from 'cheerio';
import lodash from 'lodash';
import {Microservices} from '../../../../../configs/microservices';
import {NavLink} from 'fluxible-router';

import { Dropdown, Menu, Flag } from 'semantic-ui-react';

import {navigateAction} from 'fluxible-router';

import ContentLikeStore from '../../../../../stores/ContentLikeStore';
import UserProfileStore from '../../../../../stores/UserProfileStore';
import TranslationStore from '../../../../../stores/TranslationStore';
import ContentStore from '../../../../../stores/ContentStore';
import loadLikes from '../../../../../actions/activityfeed/loadLikes';

import TranslationPanel from '../../../TranslationPanel/TranslationPanel.js';

class DeckViewPanel extends React.Component {
    getTextFromHtml(html) {
        let text = cheerio.load(html).text();
        if (text.length > 25) {
            text = text.substr(0, 21) + '...';
        }
        return text;
    }

    render() {
        const heightStyle = {
            //height: this.props.DeckViewStore.deckViewPanelHeight + 'px',
            minHeight: this.props.DeckViewStore.deckViewPanelHeight,
            overflowY: 'auto',
            overflowX: 'auto'
        };
        const deckData = this.props.DeckViewStore.deckData;
        let slidesArr = [];
        if (this.props.DeckViewStore.slidesData && this.props.DeckViewStore.slidesData.children) {
            slidesArr = this.props.DeckViewStore.slidesData.children;
        }
        let tags = [];
        if (deckData && deckData.tags){
            tags = deckData.tags;
        }
        let currentRevision = 1;
        if(deckData.revisions){
            currentRevision = deckData.revisions.length === 1 ? deckData.revisions[0] : deckData.revisions.find((rev) => {
                return rev.id === deckData.active;
            });
        }

        const forkCount = deckData.forkCount;
        const shareCount = deckData.shareCount;
        const downloadCount = deckData.downloadCount;

        //const deckTheme = lodash.get(deckData, 'theme', 'Simple');
        let deckTheme = currentRevision.theme;
        switch (deckTheme) {
            case 'default':
                deckTheme = 'White - Default';
                break;
            case 'beige':
                deckTheme = 'Cream';
                break;
            case 'black':
                deckTheme = 'Black';
                break;
            case 'league':
                deckTheme = 'Black';
                break;
            case 'sky':
                deckTheme = 'sky';
                break;
            case 'solarized':
                deckTheme = 'Beige';
                break;
            case 'moon':
                deckTheme = 'Dark Slate Blue';
                break;
            case 'night':
                deckTheme = 'High Contrast 1';
                break;
            case 'blood':
                deckTheme = 'High Contrast 2';
                break;
            case 'serif':
                deckTheme = 'Serif';
                break;
            case 'simple':
                deckTheme = 'Simple';
                break;
            case 'openuniversity':
                deckTheme = 'Open University';
                break;
            case 'odimadrid':
                deckTheme = 'ODI Madrid';
                break;
            case 'oeg':
                deckTheme = 'OEG';
                break;
            default:
        }
        const deckLicense = deckData.license;
        const deckTitle = currentRevision.title;
        const deckDate = CustomDate.format(deckData.timestamp, 'Do MMMM YYYY');
        const deckDescription = lodash.get(deckData, 'description', '');
        const deckCreator = this.props.DeckViewStore.creatorData.username;
        const deckOwner = this.props.DeckViewStore.ownerData.username;
        const originCreator = this.props.DeckViewStore.originCreatorData.username;

        let deckLanguageCode = deckData.language === undefined ? 'en' : deckData.language;
        let deckLanguage = deckLanguageCode === undefined ? '' : ISO6391.getName(deckLanguageCode);
        // default English
        deckLanguage = (deckLanguage === '' ? 'English' : deckLanguage);
        //const deckLanguageCode = lodash.get(deckData, 'language', undefined);
        //const deckLanguage = deckLanguageCode === undefined ? 'English' : ISO6391.getName(deckLanguageCode.substr(0, 2));
        // // TODO when flag code is available, remove the hard coded flag and update the respective JSX.
        // //const countryFlag = 'gb';
        //let translations = this.props.TranslationStore.translations;
        const totalSlides = lodash.get(this.props.DeckViewStore.slidesData, 'children.length', undefined);
        const maxSlideThumbnails = 3;

        const totalLikes = this.props.ContentLikeStore.usersWhoLikedDeck.length;

        const deckURL = '/deck/' + this.props.selector.id;
        const creatorProfileURL = '/user/' + deckCreator;
        const ownerProfileURL = '/user/' + deckOwner;

        const user = this.props.UserProfileStore.userid;

        let originInfo = deckData.origin != null ?
Origin:
                <NavLink href={'/deck/' + deckData.origin.id + '-' + deckData.origin.revision}>{deckData.origin.title}</NavLink> by {originCreator}

 : '';

        return (

                        {(this.props.TranslationStore.inProgress) ?

Translating

 : ''}

                            {(deckTitle === undefined) ?

Loading

 : ''}

{deckTitle}

Creator:
                                            {deckCreator}

                                        {originInfo}

Date: {deckDate}

                                        {deckDescription &&

Description:

{deckDescription}

                                        }

                                            {deckLanguage}

                                        {/* <TranslationPanel/>*/}

                                            {totalSlides}

                                            {forkCount}

                                            {totalLikes}

                                            {shareCount}

                                            {downloadCount}

                                {tags.length > 0 ?

 : ''}

                                    {tags.map((tag, index) => {
                                        return {tag};
                                    })}

                                {/* Read https://slidewiki.atlassian.net/wiki/display/SWIK/How+To+Use+Slide+Thumbnail to know the details */}
                                {slidesArr.map((slide, index) => {
                                    let thumbnailURL = `${Microservices.file.uri}/thumbnail/slide/${slide.id}`;
                                    if (slide.theme) {
                                        thumbnailURL += '/' + slide.theme;
                                    }
                                    if (index < maxSlideThumbnails) {
                                        return (

                                                            <Thumbnail key={index}
                                                                url={thumbnailURL}
                                                                slideId={slide.id} alt={''} tabIndex={-1}/>

                                                        {this.getTextFromHtml(slide.title)}

Slide {index + 1} of {totalSlides}

                                        );
                                    }
                                })}

        );
    }
}

DeckViewPanel.contextTypes = {
    executeAction: React.PropTypes.func.isRequired
};

DeckViewPanel = connectToStores(DeckViewPanel, [DeckViewStore, ContentLikeStore, UserProfileStore, ContentStore, TranslationStore], (context, props) => {
    return {
        DeckViewStore: context.getStore(DeckViewStore).getState(),
        ContentLikeStore: context.getStore(ContentLikeStore).getState(),
        UserProfileStore: context.getStore(UserProfileStore).getState(),
        ContentStore: context.getStore(ContentStore).getState(),
        TranslationStore: context.getStore(TranslationStore).getState(),
    };
});
export default DeckViewPanel;
<|endoftext|>