<commit_before>/**
 * RenRen OAuth2 Lib
 * @author Tang Bo Hao
 */

// Local Require
var util = require('util'),
	OAuth2 = require('../support/oauth').OAuth2,
	ClientBase = require('./clientBase'),
	URL= require('url');

// export renrenClient
var renrenClient = module.exports = function renrenClient(appinfo, user) {
	ClientBase.call(this);
	this.name = 'renren';
	this.secret = appinfo.secret;

	// check token
	var	now = new Date();
	if(user){
		this.refresh = user.refresh;

		if( !user.expire || user.expire > now){
			this.token = user.token;
			this.expire = user.expire;
			return;
		}
	}
	// Create OAuth2 Object based on config
	this.oa2 = new OAuth2(
		appinfo.key, appinfo.secret,
		this.api.oauth_site, this.api.oauth_authorize, this.api.oauth_token /* oauth urls */
	);

};
util.inherits(renrenClient, ClientBase);

// Set API
renrenClient.prototype.api = require('./apiconfig').RenRenAPI;

/**
 * Authorization Part
 * @param {Request} req express request object
 * @param {Response} res express response object
 * @param {Function} callback Callback Function
 * @param {Object} context 'this' object of callback
 */
renrenClient.prototype.authorize = function (req, res, callback, context) {
	var self = this;
	// set access token callback
	var access_cbfunc = function(error, access_token, refresh_token, result) {
		//Finally call back
		if (error) return callback.call(context, error);

		// set expire date
		if(result['expires_in']){
			var expire_at = new Date();
			expire_at.setTime(expire_at.getTime()+result['expires_in']*1000);
		}

		// remove temp
		delete req.session.redirectURI;

		// store the access token in the session
		self.token = access_token;
		self.expire = expire_at;
		self.refresh = refresh_token;

		var user = {
			platform: self.name,
			token: access_token,
			refresh: refresh_token,
			expire: expire_at.getTime() };

		callback.call(context, null, user);
	};

	// if has token, directly return
	if(this.token){
		return callback.call(context, null, {
				platform: this.name,
				token: this.token,
				refresh: this.refresh,
				expire: this.expire
			});
	}

	// if has refresh token
	if(this.refresh){
		this.oa2.refreshAccessToken(this.refresh,{
			grant_type: 'refresh_token',
		}, access_cbfunc );
	}else{ // start new round
		var redirectURI;

		// This is get access token round
		if(req.param("code")){
			redirectURI = req.session.redirectURI;
			this.oa2.getOAuthAccessToken(
				req.param("code"),
				{
					redirect_uri: redirectURI,
					grant_type: 'authorization_code',
				}, access_cbfunc);
		}else{ // This is authorize round
			// set redirect_uri
			redirectURI = req.session.redirectURI = "http://"+req.header('Host') + req.url;

			var authorizeUrl = this.oa2.getAuthorizeUrl({
					response_type: 'code',
					redirect_uri: redirectURI,
				});

			res.redirect(authorizeUrl);
		}
	}// end refresh if
};

/* ==!====== API Method =========
   ================================== */
/**
 * Get Method
 * @param api API Target
 * @param param parameters
 * @param callback Template: function( err, data, response )
 */
renrenClient.prototype.get = function(api, param, callback, context) {
	if (!this.token) return callback.call(context, "not authorized");
	this.post(api, param, callback, context);
};

/**
 * Restful Post/Put Method
 * @param api API Target
 * @param body HTTP request content
 * @param callback Template: function( err, data, response )
 * @param {Object} context 'this' object of callback
 */
renrenClient.prototype.post = function post(api, body, callback, context) {
	if (!this.token) return callback.call(context, "not authorized");

	var param = {
		method: api,
		format: this.api.result_format,
		v: '1.0',
		access_token: this.token
	};
	// set body in param
	for(var key in body){
		param[key] = body[key];
	}
	// set sig
	var basestring = this._buildBaseString(param, true, true);
	param.sig = this._buildSignature(basestring, this.secret, 'md5');
	// do post
	this._performSecureRequest('POST', this.api.apiurl, param, null
	, function(err, data){
		if(err) return callback.call(context, err);

		if(data){
			data = JSON.parse(data);
		}
		callback.call(context, null, data);
	});
};

renrenClient.prototype.geneCommonUser = function (data) {
	if(!data.uid) return data;

	//organize data with common structure
	return {
  		id: data.uid,
  		name: data.name,
  		location:{
  			country:	data.hometown_location.country,
  			province: data.hometown_location.province,
  			city: 		data.hometown_location.city,
  		},
  		imageUrl: data.tinyurl,
  		imageUrl_large: data.mainurl,
  		gender:	data.sex == 1,
  		is_special:	Boolean(data.zidou == 1),
			specialtype: Number(data.vip),
  		lang: "zh-cn",
  	};
};

// override common api
renrenClient.prototype.account_info = function (param, callback, context) {
	param = param || {};
	param.fields = "uid,name,sex,star,zidou,vip,tinyurl,mainurl,hometown_location";

	ClientBase.prototype.account_info.call(this, param, function(err, data){
		if(data) data = data[0];
		callback.call(context, err, data);
	}, this);
};<commit_msg>fix renren Client bug. enable refresh token method<commit_after>/**
 * RenRen OAuth2 Lib
 * @author Tang Bo Hao
 */

// Local Require
var util = require('util'),
	OAuth2 = require('../support/oauth').OAuth2,
	ClientBase = require('./clientBase'),
	URL= require('url');

// export renrenClient
var renrenClient = module.exports = function renrenClient(appinfo, user) {
	ClientBase.call(this);
	this.name = 'renren';
	this.secret = appinfo.secret;

	// check token
	var	now = new Date();
	if(user){
		this.refresh = user.refresh;

		if( !user.expire || user.expire > now){
			this.token = user.token;
			this.expire = user.expire;
			return;
		}
	}
	// Create OAuth2 Object based on config
	this.oa2 = new OAuth2(
		appinfo.key, appinfo.secret,
		this.api.oauth_site, this.api.oauth_authorize, this.api.oauth_token /* oauth urls */
	);

};
util.inherits(renrenClient, ClientBase);

// Set API
renrenClient.prototype.api = require('./apiconfig').RenRenAPI;

/**
 * Authorization Part
 * @param {Request} req express request object
 * @param {Response} res express response object
 * @param {Function} callback Callback Function
 * @param {Object} context 'this' object of callback
 */
renrenClient.prototype.authorize = function (req, res, callback, context) {
	var self = this;
	// set access token callback
	var access_cbfunc = function(error, access_token, refresh_token, result) {
		//Finally call back
		if (error) return callback.call(context, error);

		// set expire date
		if(result['expires_in']){
			var expire_at = Date.now() + result['expires_in']*1000 ;
			var r_expire_at = Date.now() + result['expires_in']*1000*2 ;
		}

		// remove temp
		req.session.redirectURI && delete req.session.redirectURI;

		// store the access token in the session
		self.token = access_token;
		self.expire = expire_at;
		self.refresh = refresh_token;

		var user = {
			platform: self.name,
			token: access_token,
			refresh: refresh_token,
			expire: expire_at,
			r_expire: r_expire_at };

		callback.call(context, null, user);
	};

	// if has token, directly return
	if(this.token){
		return callback.call(context, null, {
				platform: this.name,
				token: this.token,
				refresh: this.refresh,
				expire: this.expire,
				r_expire: this.r_expire
			});
	}

	// if has refresh token
	if(this.refresh && this.r_expire && Date.now() < this.r_expire){
		this.oa2.refreshAccessToken(this.refresh,{
			grant_type: 'refresh_token',
		}, access_cbfunc );
	}else{ // start new round
		var redirectURI;

		// This is get access token round
		if(req.param("code")){
			if(req.session.redirectURI){
				redirectURI = req.session.redirectURI;
			}else{
				var i = req.url.indexOf("?");
				redirectURI = "http://"+req.header('Host') + (i>=0 ? req.url.substring(0,i) : req.url);
			}
			this.oa2.getOAuthAccessToken(
				req.param("code"),
				{
					redirect_uri: redirectURI,
					grant_type: 'authorization_code',
				}, access_cbfunc);
		}else{ // This is authorize round
			// set redirect_uri
			redirectURI = req.session.redirectURI = "http://"+req.header('Host') + req.url;

			var authorizeUrl = this.oa2.getAuthorizeUrl({
					response_type: 'code',
					redirect_uri: redirectURI,
				});

			res.redirect(authorizeUrl);
		}
	}// end refresh if
};

/* ==!====== API Method =========
   ================================== */
/**
 * Get Method
 * @param api API Target
 * @param param parameters
 * @param callback Template: function( err, data, response )
 */
renrenClient.prototype.get = function(api, param, callback, context) {
	if (!this.token) return callback.call(context, "not authorized");
	this.post(api, param, callback, context);
};

/**
 * Restful Post/Put Method
 * @param api API Target
 * @param body HTTP request content
 * @param callback Template: function( err, data, response )
 * @param {Object} context 'this' object of callback
 */
renrenClient.prototype.post = function post(api, body, callback, context) {
	if (!this.token) return callback.call(context, "not authorized");

	var param = {
		method: api,
		format: this.api.result_format,
		v: '1.0',
		access_token: this.token
	};
	// set body in param
	for(var key in body){
		param[key] = body[key];
	}
	// set sig
	var basestring = this._buildBaseString(param, true, true);
	param.sig = this._buildSignature(basestring, this.secret, 'md5');
	// do post
	this._performSecureRequest('POST', this.api.apiurl, param, null
	, function(err, data){
		if(err) return callback.call(context, err);

		if(data){
			data = JSON.parse(data);
		}
		callback.call(context, null, data);
	});
};

renrenClient.prototype.geneCommonUser = function (data) {
	if(!data.uid) return data;

	//organize data with common structure
	return {
  		id: data.uid,
  		name: data.name,
  		location:{
  			country:	data.hometown_location.country,
  			province: data.hometown_location.province,
  			city: 		data.hometown_location.city,
  		},
  		imageUrl: data.tinyurl,
  		imageUrl_large: data.mainurl,
  		gender:	data.sex == 1,
  		is_special:	Boolean(data.zidou == 1),
			specialtype: Number(data.vip),
  		lang: "zh-cn",
  	};
};

// override common api
renrenClient.prototype.account_info = function (param, callback, context) {
	param = param || {};
	param.fields = "uid,name,sex,star,zidou,vip,tinyurl,mainurl,hometown_location";

	ClientBase.prototype.account_info.call(this, param, function(err, data){
		if(data) data = data[0];
		callback.call(context, err, data);
	}, this);
};<|endoftext|>


<commit_before>var url = require('url')
var unirest = require('unirest')

function replaceHost(req, target) {
  req.url = url.parse(target)
  return req
}

function handler(error, response, body) {
  if (error) {
    return console.error('An error has occured:', error);
  }
  console.log('Request sent, status code: ' + response.statusCode)
}

// Create function
function requestFork(req, targets) {

  // Send to all forks
  targets.map(function(target){
    unirest.request(replaceHost(req, target), handler)
  })

}

var req = {
  url: 'https://api.github.com/repos/request/request',
  headers: {
    'User-Agent': 'request'
  }
}

var targets = [
  "http://mockbin.com/bin/8bbc56c6-eeb3-4d3e-b916-5a41a1e170ca",
  "http://mockbin.com/bin/356aaac4-2db1-4fb6-9e37-a44780f9f0d3"
]

requestFork(req, targets)<commit_msg>Add callback<commit_after>var url = require('url')
var unirest = require('unirest')

function replaceHost(req, target) {
  req.url = url.parse(target)
  return req
}

module.exports = function requestFork(req, targets, cb) {
  var responses = []
  var errors = []

  function handler(error, response, body) {
    if (error) {
      errors.push(error)
    }
    responses.push(response)
    if (responses.length + errors.length === targets.length) {
      cb(responses, errors)
    }
  }

  targets.map(function(target){
    unirest.request(replaceHost(req, target), handler)
  })
}
<|endoftext|>


<commit_before>'use strict'

const _VIA_NAME = 'VGG Image Annotator';
const _VIA_NAME_SHORT = 'VIA';
const _VIA_VERSION = '3.0.9';
const _VIA_URL_CODE_REPO = 'https://gitlab.com/vgg/via';
const _VIA_URL_PROJECT_PAGE = 'http://www.robots.ox.ac.uk/~vgg/software/via/';

const _VIA_CONFIG = { MSG_TIMEOUT:3000 };
const _VIA_REMOTE_STORE = 'http://zeus.robots.ox.ac.uk/via/store/3.x.y/'; // to host your own server, see https://gitlab.com/vgg/vps
const _VIA_REMOTE_TIMEOUT = 6000; // in milliseconds
//const _VIA_REMOTE_STORE = 'http://localhost:9669/'; // for debug

const _VIA_DEFAULT_ATTRIBUTE_ANCHOR_ID = '';

var _VIA_FLOAT_FIXED_POINT = 3; // floats are stored as 3 decimal places
var _VIA_SPATIAL_REGION_MOVE_DELTA = 10; // in pixels
var _VIA_SPATIAL_REGION_LABEL_MAXLENGTH = 12; // in characters
var _VIA_SPATIAL_REGION_LABEL_FONT = '12px Sans';
<commit_msg>added https:// url for VIA shared project server<commit_after>'use strict'

const _VIA_NAME = 'VGG Image Annotator';
const _VIA_NAME_SHORT = 'VIA';
const _VIA_VERSION = '3.0.10';
const _VIA_URL_CODE_REPO = 'https://gitlab.com/vgg/via';
const _VIA_URL_PROJECT_PAGE = 'https://www.robots.ox.ac.uk/~vgg/software/via/';

const _VIA_CONFIG = { MSG_TIMEOUT:3000 };

// VIA Project Server (VPS)
// Use the https://zeus.robots.ox.ac.uk/via/store/3.x.y/ by default
// For older versions, the http://zeus.robots.ox.ac.uk/via/store/3.x.y/ remains available
// to host your own server, see https://gitlab.com/vgg/vps
const _VIA_REMOTE_STORE = 'https://zeus.robots.ox.ac.uk/via/store/3.x.y/';
//const _VIA_REMOTE_STORE = 'http://zeus.robots.ox.ac.uk/via/store/3.x.y/'; // use if http:// only access is required
const _VIA_REMOTE_TIMEOUT = 6000; // in milliseconds
//const _VIA_REMOTE_STORE = 'http://localhost:9669/'; // for debug

const _VIA_DEFAULT_ATTRIBUTE_ANCHOR_ID = '';

var _VIA_FLOAT_FIXED_POINT = 3; // floats are stored as 3 decimal places
var _VIA_SPATIAL_REGION_MOVE_DELTA = 10; // in pixels
var _VIA_SPATIAL_REGION_LABEL_MAXLENGTH = 12; // in characters
var _VIA_SPATIAL_REGION_LABEL_FONT = '12px Sans';
<|endoftext|>


<commit_before>
/**
 * @class t10
 * @singleton
 *
 * t10 class provides basic translation functionalities in Browsers.
 */
window.t10 = (function (window) {
    'use strict';

    var $ = window.jQuery;

    var exports = function () {};

    var self = new exports();

    var t10Pt = exports.prototype;

    /**
     * Set the translation resource
     *
     * @param {Object} resource The mapping from key to translated string
     * @return {t10} The t10 object itself
     */
    t10Pt.setResource = function (resource) {
        self.resource = resource;

        return self;
    };

    t10Pt.getResource = function () {
        return self.resource;
    };

    /**
     * Translate a key
     *
     * @param {String} key The key to translate
     * @return {String} The translated string
     */
    t10Pt.t = function (key) {
        var value = self.resource[key];

        if (value != null) {
            return value;
        }

        return key;
    };

    /**
     * Scan <t> tags and .t-text and .t-attr class elements and translate its contents
     *
     * @return object
     * @subreturn {Number} object['t-tag'] the count of translated <t> tags
     * @subreturn {Number} object['t-text'] the count of translated .t-text tags
     * @subreturn {Number} object['t-attr'] the count of translated .t-attr tags' attributes
     */
    t10Pt.scan = function (dom) {
        var t = self.scanTTag(dom);
        var tText = self.scanTText(dom);
        var tAttr = self.scanTAttr(dom);

        return {
            't-tag': t,
            't-text': tText,
            't-attr': tAttr
        };
    };

    /**
     * remove <t> tag and insert string for key
     *
     * @return translated key count
     */
    t10Pt.scanTTag = function (dom) {

        var list = $('t', dom).each(function () {

            var t = $(this);

            t.after(self.t(t.text())).remove();

        });

        return list.length;

    };

    /**
     * scan .t-text class and replace text with translated string
     *
     * @return translated key count
     */
    t10Pt.scanTText = function (dom) {

        var count = 0;

        $('.t-text', dom).each(function () {

            var elm = $(this);

            // replace text with translated string
            elm.text(self.t(elm.text()));

            elm.removeClass('t-text').addClass('t-text-done');

            // increment translation count
            count ++;
        });

        return count;
    };

    var T_ATTR_REGEXP = /^t:/; // translatable attribute starts with 't:'

    /**
     * scan .t-attr class and translate its attr starts with 't:' prefix
     *
     * @return translated key count
     */
    t10Pt.scanTAttr = function (dom) {

        var count = 0;

        $('.t-attr', dom).each(function () {

            $.each(this.attributes, function (i, attr) {
                var label = attr.value;

                if (T_ATTR_REGEXP.test(label)) {
                    label = label.replace(T_ATTR_REGEXP, '');

                    // replace attribute value with translated string
                    attr.value = self.t(label);

                    // increment translation count
                    count ++;
                }

            });

            $(this).removeClass('t-attr').addClass('t-attr-done');

        });

        return count;
    };

    t10Pt.setAvailableLanguages = function (array) {
        self.availables = array;

        self.defaultLanguage = array[0];

        return self;
    };

    t10Pt.setLanguage = function (language) {
        self.language = language;

        return self;
    };

    t10Pt.getBestLanguage = function (language) {
        language = language || self.language;

        if (language == null) {
            return self.defaultLanguage;
        }

        var select = null;

        for (var i = 0; i < self.availables.length; i++) {
            var available = self.availables[i];

            var foundPos = language.indexOf(available);

            if (foundPos === 0) {
                if (select == null || select.length < available.length) {
                    select = available;
                }
            }
        }

        if (select == null) {
            return self.defaultLanguage;
        }

        return select;

    };

    t10Pt.loadScript = function (urlPattern) {
        return $.getScript(urlPattern.replace('{LANGUAGE}', self.getBestLanguage()));
    };

    t10Pt.loadJson = function (urlPattern) {
        return $.getJSON(urlPattern.replace('{LANGUAGE}', self.getBestLanguage())).pipe(function (resource) {
            self.setResources(resource);
        });
    };

    return new exports();

}(window));
<commit_msg>Refactor whole structure<commit_after>
/**
 * @class t10
 * @singleton
 *
 * t10 class provides basic translation functionalities in Browsers.
 */
window.t10 = (function (window, $) {
    'use strict';

    var exports = {};

    var resource = {};

    var available = [];

    var defaultLanguage = null;

    /**
     * Sets the translation resource
     *
     * @param {Object} resource The mapping from key to translated string
     * @return {t10} The t10 object itself
     */
    exports.setResource = function (resource) {
        resource = resource;

        return exports;
    };

    exports.getResource = function () {
        return resource;
    };

    /**
     * Translates a key
     *
     * @param {String} key The key to translate
     * @return {String} The translated string
     */
    exports.t = function (key) {
        var value = resource[key];

        if (value != null) {
            return value;
        }

        return key;
    };

    /**
     * Scan <t> tags and .t-text and .t-attr class elements and translate its contents
     *
     * @return object
     * @subreturn {Number} object['t-tag'] the count of translated <t> tags
     * @subreturn {Number} object['t-text'] the count of translated .t-text tags
     * @subreturn {Number} object['t-attr'] the count of translated .t-attr tags' attributes
     */
    exports.scan = function (dom) {

        return {
            't-tag': exports.scanTTag(dom),
            't-text': exports.scanTText(dom),
            't-attr': exports.scanTAttr(dom)
        };

    };

    /**
     * remove <t> tag and insert string for key
     *
     * @return translated key count
     */
    exports.scanTTag = function (dom) {

        var list = $('t', dom).each(function () {

            var elm = $(this);

            elm.after(exports.t(elm.text())).remove();

        });

        return list.length;

    };

    /**
     * scan .t-text class and replace text with translated string
     *
     * @return translated key count
     */
    exports.scanTText = function (dom) {

        var count = 0;

        $('.t-text', dom).each(function () {

            var elm = $(this);

            // replace text with translated string
            elm.text(exports.t(elm.text()));

            elm.removeClass('t-text').addClass('t-text-done');

            // increment translation count
            count ++;
        });

        return count;
    };

    var T_ATTR_REGEXP = /^t:/; // translatable attribute starts with 't:'

    /**
     * scan .t-attr class and translate its attr starts with 't:' prefix
     *
     * @return translated key count
     */
    exports.scanTAttr = function (dom) {

        var count = 0;

        $('.t-attr', dom).each(function () {

            $.each(this.attributes, function (i, attr) {
                var label = attr.value;

                if (T_ATTR_REGEXP.test(label)) {
                    label = label.replace(T_ATTR_REGEXP, '');

                    // replace attribute value with translated string
                    attr.value = exports.t(label);

                    // increment translation count
                    count ++;
                }

            });

            $(this).removeClass('t-attr').addClass('t-attr-done');

        });

        return count;
    };

    exports.setAvailableLanguages = function (array) {
        availables = array;

        defaultLanguage = array[0];

        return exports;
    };

    /**
     * Returns the best match language among the available languages
     *
     */
    exports.getBestLanguage = function (language) {

        if (language == null) {
            return defaultLanguage;
        }

        var select = null;

        for (var i = 0; i < availables.length; i++) {
            var available = availables[i];

            var foundPos = language.indexOf(available);

            if (foundPos === 0) {
                if (select == null || select.length < available.length) {
                    select = available;
                }
            }
        }

        if (select == null) {
            return defaultLanguage;
        }

        return select;

    };

    exports.loadScript = function (urlPattern) {
        return $.getScript(urlPattern.replace('{LANGUAGE}', exports.getBestLanguage()));
    };

    exports.loadJson = function (urlPattern) {
        return $.getJSON(urlPattern.replace('{LANGUAGE}', exports.getBestLanguage())).pipe(function (resource) {
            exports.setResources(resource);
        });
    };

    return exports;

}(window, window.jQuery));
<|endoftext|>


<commit_before>define(['xaml!sprd/view/svg/PatternRenderer'], function(PatternRenderer) {

    return PatternRenderer.inherit("sprd.view.svg.DesignConfigurationRendererClass", {

        defaults: {
            tagName: "g",
            maskId: null,
            "data-mask-id": "{configuration.afterEffect.id}",
            isSpecialFlex: "{isSpecialFlex()}",
            isFlock: "{isFlock()}",
            largeSize: "{largeSize()}",
            filter: "{filter()}",
            loadedLayers: {},
            viewer: null,
            loading: "{configuration.loading}"
        },

        $classAttributes: ["x", "y", "width", "height"],

        url: function() {

            if (this.$.imageService && this.$.configuration && this.$.configuration.$.design && this.$.configuration.$.printColors) {

                var maxSize = Math.min(this.$._width, 600),
                    options = {},
                    design = this.$.configuration.$.design;

                if (this.$.width >= this.$.height) {
                    options.width = maxSize;
                } else {
                    options.height = maxSize;
                }

                options.printColors = this.$.configuration.getPrintColorsAsRGB();
                options.version = design.$.version;

                if (!design.isVectorDesign()) {
                    return this.$.configuration.$.processedImage || design.$.localImage || this.$.imageService.designImageFromCache(design.$.wtfMbsId, options);
                }

            }
            return null;
        }.onChange("design", "_width", "_height", "configuration.processedImage").on(["configuration.printColors", "reset"]),

        maskUrl: function(layerIndex) {

            if (this.$.imageService && this.$.configuration && this.$.configuration.$.design) {

                var maxSize = Math.min(this.$._width, 600),
                    options = {},
                    design = this.$.configuration.$.design;

                if (this.$.width >= this.$.height) {
                    options.width = maxSize;
                } else {
                    options.height = maxSize;
                }

                var colors = this.$.configuration.$.printColors.size(),
                    printColors = [];
                for (var i = 0; i < colors; i++) {
                    printColors.push("none");
                }

                printColors[layerIndex] = "FFFFFF";

                options.printColors = printColors;
                options.version = design.$.version;
                options.layerIndex = layerIndex;

                if (!design.isVectorDesign()) {
                    return this.$.configuration.$.processedImage || design.$.localImage || this.$.imageService.designImageFromCache(design.$.wtfMbsId, options);
                } else {
                    return this.$.imageService.designImageFromCache(design.$.wtfMbsId, options);
                }

            }

            return null;
        }.onChange("design", "_width", "_height").on(["configuration.printColors", "reset"]),

        handleLoad: function(index) {
            var loadedLayers = this.get("loadedLayers") || {};
            loadedLayers[index] = true;
            this.set("loadedLayers", loadedLayers, {update: true, force: true});
        },

        allLayersLoaded: function() {
            var loadedLayers = this.get("loadedLayers");
            var length = Object.keys(loadedLayers).length;

            return length == this.get("configuration.printColors.length");
        }.onChange("loadedLayers").on(["configuration.printColors", "reset"]),

        fillUrl: function(layerIndex) {
            //there are some designs where the layer order needs to be switched
            var fixedLayerIndex = this.get("configuration.design.colors.$items")[layerIndex].$.layer;

            if (this.isSpecialColor(fixedLayerIndex)) {
                return "url(#p" + this.$.maskId + "-" + fixedLayerIndex + ")";
            }

            var printColors = this.get("configuration.printColors.$items");
            return printColors[fixedLayerIndex].color().toString();
        },

        loaderSize: function() {
            return Math.min(this.$.height, this.$.width) * 0.5;
        }.onChange("width", "height"),

        loaderPos: function() {
            var s = this.loaderSize() * 0.5;
            return {
                x: this.$.width * 0.5 - s,
                y: this.$.height * 0.5 - s
            }
        }.onChange("width", "height")

    })
});<commit_msg>preventing LoadedLayers from ending up in dom<commit_after>define(['xaml!sprd/view/svg/PatternRenderer'], function(PatternRenderer) {

    return PatternRenderer.inherit("sprd.view.svg.DesignConfigurationRendererClass", {

        defaults: {
            tagName: "g",
            maskId: null,
            "data-mask-id": "{configuration.afterEffect.id}",
            isSpecialFlex: "{isSpecialFlex()}",
            isFlock: "{isFlock()}",
            largeSize: "{largeSize()}",
            filter: "{filter()}",
            loadedLayers: {},
            viewer: null,
            loading: "{configuration.loading}"
        },

        $classAttributes: ["x", "y", "width", "height", "loadedLayers"],

        url: function() {

            if (this.$.imageService && this.$.configuration && this.$.configuration.$.design && this.$.configuration.$.printColors) {

                var maxSize = Math.min(this.$._width, 600),
                    options = {},
                    design = this.$.configuration.$.design;

                if (this.$.width >= this.$.height) {
                    options.width = maxSize;
                } else {
                    options.height = maxSize;
                }

                options.printColors = this.$.configuration.getPrintColorsAsRGB();
                options.version = design.$.version;

                if (!design.isVectorDesign()) {
                    return this.$.configuration.$.processedImage || design.$.localImage || this.$.imageService.designImageFromCache(design.$.wtfMbsId, options);
                }

            }
            return null;
        }.onChange("design", "_width", "_height", "configuration.processedImage").on(["configuration.printColors", "reset"]),

        maskUrl: function(layerIndex) {

            if (this.$.imageService && this.$.configuration && this.$.configuration.$.design) {

                var maxSize = Math.min(this.$._width, 600),
                    options = {},
                    design = this.$.configuration.$.design;

                if (this.$.width >= this.$.height) {
                    options.width = maxSize;
                } else {
                    options.height = maxSize;
                }

                var colors = this.$.configuration.$.printColors.size(),
                    printColors = [];
                for (var i = 0; i < colors; i++) {
                    printColors.push("none");
                }

                printColors[layerIndex] = "FFFFFF";

                options.printColors = printColors;
                options.version = design.$.version;
                options.layerIndex = layerIndex;

                if (!design.isVectorDesign()) {
                    return this.$.configuration.$.processedImage || design.$.localImage || this.$.imageService.designImageFromCache(design.$.wtfMbsId, options);
                } else {
                    return this.$.imageService.designImageFromCache(design.$.wtfMbsId, options);
                }

            }

            return null;
        }.onChange("design", "_width", "_height").on(["configuration.printColors", "reset"]),

        handleLoad: function(index) {
            var loadedLayers = this.get("loadedLayers") || {};
            loadedLayers[index] = true;
            this.set("loadedLayers", loadedLayers, {update: true, force: true});
        },

        allLayersLoaded: function() {
            var loadedLayers = this.get("loadedLayers");
            var length = Object.keys(loadedLayers).length;

            return length == this.get("configuration.printColors.length");
        }.onChange("loadedLayers").on(["configuration.printColors", "reset"]),

        fillUrl: function(layerIndex) {
            //there are some designs where the layer order needs to be switched
            var fixedLayerIndex = this.get("configuration.design.colors.$items")[layerIndex].$.layer;

            if (this.isSpecialColor(fixedLayerIndex)) {
                return "url(#p" + this.$.maskId + "-" + fixedLayerIndex + ")";
            }

            var printColors = this.get("configuration.printColors.$items");
            return printColors[fixedLayerIndex].color().toString();
        },

        loaderSize: function() {
            return Math.min(this.$.height, this.$.width) * 0.5;
        }.onChange("width", "height"),

        loaderPos: function() {
            var s = this.loaderSize() * 0.5;
            return {
                x: this.$.width * 0.5 - s,
                y: this.$.height * 0.5 - s
            }
        }.onChange("width", "height")

    })
});<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import { Animated, Text, TextInput, View } from 'react-native-universal'
import matchMedia from 'react-native-match-media'
import Uranium from 'uranium'
import Color from 'color'
import ps from 'react-native-ps'

import connectTheme from './connectTheme'
import { Animations, Colors, Type } from './styles'
import { Breakpoints } from './styles/Grid'
import Divider from './Divider'
import Error from './Error'

const AnimatedDivider = Animated.createAnimatedComponent(Divider)

class Input extends Component {
  constructor(props) {
    super(props)

    this.handleFocus = this.handleFocus.bind(this)
    this.handleBlur = this.handleBlur.bind(this)
    this.focusInput = this.focusInput.bind(this)

    this.state = {
      // If the component starts with a value, start the
      // placeholder in its focused state
      labelAV: new Animated.Value(this.props.value ? 1 : 0),
      colorAV: new Animated.Value(0),
    }
  }

  componentDidMount() {
  }

  get styles() {
    return styles(this.props.theme)
  }

  handleFocus() {
    if (this.props.disabled) {
      this.refs.input.blur()
      return
    }
    Animated.timing(
      this.state.labelAV,
      { ...Animations.default, toValue: 1 }
    ).start()
    Animated.timing(
      this.state.colorAV,
      { ...Animations.default, toValue: 1 }
    ).start()
  }

  handleBlur() {
    Animated.timing(
      this.state.colorAV,
      { ...Animations.default, toValue: 0 }
    ).start()

    // Only return color to its original state if the input
    // has a value
    if (this.props.value) return

    Animated.timing(
      this.state.labelAV,
      { ...Animations.default, toValue: 0 }
    ).start()
  }

  focusInput() {
    this.refs.input.focus()
  }

  render() {
    const { placeholder, style, theme, disabled, error, ...other } = this.props
    const { colorAV, labelAV, focused } = this.state
    return (
      <View style={[this.styles.base, style]}>
        <TextInput
          ref="input"
          css={[
            this.styles.textInput,
            disabled && this.styles.disabled,
          ]}
          selectionColor={Color(theme.accent).alpha(0.87).rgbString()}
          underlineColorAndroid="transparent"
          {...other}
          onFocus={this.handleFocus}
          onBlur={this.handleBlur} />
        <Animated.Text
          css={[
            this.styles.placeholder,
            focused && this.styles.placeholderFocus,
            disabled && this.styles.disabled,
          ]}
          style={{
            top: labelAV.interpolate({
              inputRange: [0, 1],
              outputRange: !matchMedia(Breakpoints.ml.split('@media ')[1]).matches ?
                [
                  this.styles.placeholder.top,
                  this.styles.placeholderFocus.top,
                ] :
                [
                  this.styles.placeholder[Breakpoints.ml].top,
                  this.styles.placeholderFocus[Breakpoints.ml].top,
                ],
            }),
            color: colorAV.interpolate({
              inputRange: [0, 1],
              outputRange: [
                this.styles.placeholder.color,
                this.styles.placeholderFocus.color,
              ],
            }),
            fontSize: labelAV.interpolate({
              inputRange: [0, 1],
              outputRange: [
                this.styles.placeholder.fontSize,
                this.styles.placeholderFocus.fontSize,
              ],
            }),
          }}
          onPress={this.focusInput}>
          {placeholder}
        </Animated.Text>
        <AnimatedDivider
          color={colorAV.interpolate({
            inputRange: [0, 1],
            outputRange: [
              theme.divider,
              Color(theme.accent).alpha(0.87).rgbString(),
            ],
          })}
          type={disabled && 'dotted'}
          css={this.styles.divider} />
        {error &&
          <Error css={this.styles.error}>{error}</Error>
        }
      </View>
    )
  }
}

Input.propTypes = {
  style: PropTypes.object,
  placeholder: PropTypes.string,
  value: PropTypes.string,
  disabled: PropTypes.bool,
  error: PropTypes.string,

  theme: PropTypes.object.isRequired,
}

Input.defaultProps = {
  style: {},
  placeholder: '',
  disabled: false,
}

const styles = theme => ps({
  base: {
    alignSelf: 'stretch',
  },

  textInput: {
    height: 16,
    marginTop: 40,

    ...Type.subheading,
    lineHeight: 16,

    [Breakpoints.ml]: {
      marginTop: 32,

      ...Type.subheading[Breakpoints.ml],
    },
  },

  // Applies to both input and placeholder
  disabled: {
    color: Colors.blackHint,
  },

  placeholder: {
    position: 'absolute',
    top: 40,

    ...Type.subheading,
    color: Colors.blackHint,
    lineHeight: 16,

    [Breakpoints.ml]: {
      top: 32,

      ...Type.subheading[Breakpoints.ml],
    },
  },

  placeholderFocus: {
    top: 16,
    ...Type.caption,
    color: Color(theme.accent).alpha(0.87).rgbString(),

    [Breakpoints.ml]: {
      top: 12,
    },
  },

  divider: {
    marginTop: 8,
    marginBottom: 8,

    [Breakpoints.ml]: {
      marginBottom: 4,
    },
  },

  error: {
    marginBottom: 8,

    [Breakpoints.ml]: {
      marginBottom: 4,
    },
  },

  web: {
    disabled: {
      cursor: 'default',
      userSelect: 'none',
    },
  },
})

export default connectTheme(Uranium(Input))
<commit_msg>Get Input working universally<commit_after>import React, { Component, PropTypes } from 'react'
import { Animated, Text, TextInput, View } from 'react-native-universal'
import matchMedia from 'react-native-match-media'
import Uranium from 'uranium'
import Color from 'color'
import ps from 'react-native-ps'

import connectTheme from './connectTheme'
import { Animations, Colors, Type } from './styles'
import { Breakpoints } from './styles/Grid'
import Divider from './Divider'
import Error from './Error'

const AnimatedDivider = Animated.createAnimatedComponent(Divider)

class Input extends Component {
  constructor(props) {
    super(props)

    this.handleFocus = this.handleFocus.bind(this)
    this.handleBlur = this.handleBlur.bind(this)
    this.focusInput = this.focusInput.bind(this)

    this.state = {
      // If the component starts with a value, start the
      // placeholder in its focused state
      labelAV: new Animated.Value(this.props.value ? 1 : 0),
      colorAV: new Animated.Value(0),
    }
  }

  componentDidMount() {
  }

  get styles() {
    return styles(this.props.theme)
  }

  handleFocus() {
    if (this.props.disabled) {
      this.refs.input.blur()
      return
    }
    Animated.timing(
      this.state.labelAV,
      { ...Animations.default, toValue: 1 }
    ).start()
    Animated.timing(
      this.state.colorAV,
      { ...Animations.default, toValue: 1 }
    ).start()
  }

  handleBlur() {
    Animated.timing(
      this.state.colorAV,
      { ...Animations.default, toValue: 0 }
    ).start()

    // Only return color to its original state if the input
    // has a value
    if (this.props.value) return

    Animated.timing(
      this.state.labelAV,
      { ...Animations.default, toValue: 0 }
    ).start()
  }

  focusInput() {
    this.refs.input.focus()
  }

  render() {
    const { placeholder, style, theme, disabled, error, ...other } = this.props
    const { colorAV, labelAV, focused } = this.state
    return (
      <View style={[this.styles.base, style]}>
        <TextInput
          ref="input"
          css={[
            this.styles.textInput,
            disabled && this.styles.disabled,
          ]}
          selectionColor={Color(theme.accent).alpha(0.87).rgbString()}
          underlineColorAndroid="transparent"
          {...other}
          onFocus={this.handleFocus}
          onBlur={this.handleBlur} />
        <Animated.Text
          css={[
            this.styles.placeholder,
            focused && this.styles.placeholderFocus,
            disabled && this.styles.disabled,
          ]}
          style={{
            top: labelAV.interpolate({
              inputRange: [0, 1],
              outputRange: !matchMedia(Breakpoints.ml.split('@media ')[1]).matches ?
                [
                  this.styles.placeholder.top,
                  this.styles.placeholderFocus.top,
                ] :
                [
                  this.styles.placeholder[Breakpoints.ml].top,
                  this.styles.placeholderFocus[Breakpoints.ml].top,
                ],
            }),
            color: colorAV.interpolate({
              inputRange: [0, 1],
              outputRange: [
                this.styles.placeholder.color,
                this.styles.placeholderFocus.color,
              ],
            }),
            fontSize: labelAV.interpolate({
              inputRange: [0, 1],
              outputRange: [
                this.styles.placeholder.fontSize,
                this.styles.placeholderFocus.fontSize,
              ],
            }),
          }}
          onPress={this.focusInput}>
          {placeholder}
        </Animated.Text>
        <AnimatedDivider
          color={colorAV.interpolate({
            inputRange: [0, 1],
            outputRange: [
              theme.divider,
              Color(theme.accent).alpha(0.87).rgbString(),
            ],
          })}
          type={disabled && 'dotted'}
          css={this.styles.divider} />
        {error &&
          <Error css={this.styles.error}>{error}</Error>
        }
      </View>
    )
  }
}

Input.propTypes = {
  style: PropTypes.object,
  placeholder: PropTypes.string,
  value: PropTypes.string,
  disabled: PropTypes.bool,
  error: PropTypes.string,

  theme: PropTypes.object.isRequired,
}

Input.defaultProps = {
  style: {},
  placeholder: '',
  disabled: false,
}

const styles = theme => ps({
  base: {
    alignSelf: 'stretch',
  },

  textInput: {
    height: 32,
    paddingHorizontal: 0,
    paddingVertical: 4,
    marginTop: 32,

    ...Type.subheading,

    [Breakpoints.ml]: {
      marginTop: 28,

      ...Type.subheading[Breakpoints.ml],
    },
  },

  // Applies to both input and placeholder
  disabled: {
    color: Colors.blackHint,
  },

  placeholder: {
    position: 'absolute',
    top: 36,

    ...Type.subheading,
    color: Colors.blackHint,

    [Breakpoints.ml]: {
      top: 32,

      ...Type.subheading[Breakpoints.ml],
    },
  },

  placeholderFocus: {
    top: 16,
    ...Type.caption,
    color: Color(theme.accent).alpha(0.87).rgbString(),

    [Breakpoints.ml]: {
      top: 12,
    },
  },

  divider: {
    marginBottom: 8,

    [Breakpoints.ml]: {
      marginBottom: 4,
    },
  },

  error: {
    marginBottom: 8,

    [Breakpoints.ml]: {
      marginBottom: 4,
    },
  },

  web: {
    disabled: {
      cursor: 'default',
      userSelect: 'none',
    },
  },
})

export default connectTheme(Uranium(Input))
<|endoftext|>


<commit_before>var s = require('shared');

var remoteUpgrader = {
    once: function() {
        // a function to run once per reset
    },
    loop: function() {
        // a function to run once per loop.
    },
    run: function(creep) {
        var err = OK;
        const m = creep.memory;
        const myController = Game.getObjectById(m.controller);
        const path = {visualizePathStyle: {plainCost: 1, swampCost: 1, stroke: '#ffaa00', opacity: 1.0}};
        if (myController) {
            err = creep.moveTo(myController, path);
        }

        let thisRoom = creep.room.name;
        if (Memory.rooms[room].ticksTravelTime === undefined) {
            Memory.rooms[room].ticksTravelTime = 1500 - creep.ticksToLive;
        }
        if (room == Memory.attack) {
            // creep.moveTo(creep.room.controller);
            // if (Memory.rooms[room].ticksTravelTime === undefined) {
            //     Memory.rooms[room] = {ticksTravelTime: 1500 - creep.ticksToLive};
            // }
            // Memory.attack = 'E22S83';
            //err = creep.signController(creep.room.controller, 'Planned Expansion');
            err = creep.moveTo(creep.room.controller, path);
            if(creep.pos.getRangeTo(creep.room.controller) < 2) {
                Memory.rooms[room].ticksTravelTimeToController = 1500 - creep.ticksToLive;
            }
            if(creep.getActiveBodyparts(CLAIM) > 0) {
                if (Game.gcl.level > 1) {
                    err = creep.claimController(creep.room.controller);
                } else {
                    err = creep.reserveController(creep.room.controller);
                }
            } else {
                creep.memory.role = 'builder';
            }
        } else {
            err = creep.moveTo(destination, path);
        }

        switch (err) {
            case ERR_FULL:
            case ERR_NOT_ENOUGH_ENERGY:
        //    case ERR_NOT_ENOUGH_RESOURCES:
        case ERR_TIRED:
        case OK:
        break;
        case ERR_NOT_IN_RANGE:
        creep.moveTo(creep.room.controller, path);
        break;
        default:
        s.creepErr(creep, err);
        break;
    }
    return OK;
}
};

module.exports = remoteUpgrader;<commit_msg>clean out remote role prototype<commit_after>var s = require('shared');
const moveOpts =  {visualizePathStyle: {stroke: '#ffaa00', opacity: 0.8}};

const errResponse = function errResponse(err, creep, goal, destination) {
    var mem = goal.id;
    switch (err) {
        case ERR_NOT_IN_RANGE:
        if (!destination) {
            err = creep.moveTo(goal, moveOpts);
        } else {
            err = cree.moveTo(destination, moveOpts);
        }
        break;
        case OK:
        case ERR_FULL:
        case ERR_NOT_ENOUGH_ENERGY:
        case ERR_TIRED:
        case ERR_BUSY:
        case ERR_NOT_FOUND:
        mem = undefined;
        break;
        default:
        creep.say('?');
        break;
    }
    return mem;
};

var remoteMiner = {
    run: function(creep) {
        var err = OK;
        const m = creep.memory;
        const energy = creep.carry.energy;
        const carried = _.sum(creep.carry);
        var goal;
        var last;
        var destination = getDestination(creep);
        var extracting = !m.depositing;
        var key = 'target';
        var getGoal = getTarget;

        if (extracting) {
            if (carried == creep.carryCapacity) {
                extracting = false;
            }
        } else {
            if (carried === 0) {
                extracting = true;
            }
        }

        m.depositing = !extracting;

        if (extracting) {
            last = Game.getObjectById(m.target);
            key = 'source';
            getGoal = getSource;
        } else {
            last = Game.getObjectById(m.source);
            // getGoal = getTarget;
        }

        if (m[key]) {
            goal = Game.getObjectById(m[key]);
        }
        if (!goal) {
            goal = getGoal(creep, last);
            m[key] = undefined;
        }
        if (goal) {
            err = extract(creep, goal);
            m[key] = errResponse(err, creep, goal, destination);
        }

        return OK;
    }
};

module.exports = remoteMiner;<|endoftext|>


<commit_before>// @flow

import React from 'react';
import renderer from 'react-test-renderer';
// import { mount } from 'enzyme';
import { Provider } from 'unstated';
import ItemContainer, { resetNextUuid } from '../ItemContainer/ItemContainer';
import AccordionContainer from '../AccordionContainer/AccordionContainer';
import AccordionItemBody from './accordion-item-body';

describe('AccordionItemBody', () => {
    let accordionStore;
    let itemStore;
    let onChange;

    beforeEach(() => {
        onChange = jest.fn();

        const itemContainer = new ItemContainer();
        resetNextUuid();
        const accordionContainer = new AccordionContainer();
        accordionContainer.setAccordion(true);
        accordionContainer.setOnChange(onChange);
        accordionStore = accordionContainer;
        itemStore = itemContainer;

        accordionStore.addItem({
            uuid: 0, // because `nextUuid` in ItemContainer starts at zero.
            expanded: false,
            disabled: false,
        });
    });

    it('renders correctly with min params', () => {
        const tree = renderer
            .create(
                <Provider inject={[accordionStore, itemStore]}>
                    <AccordionItemBody>

Fake body

                    </AccordionItemBody>
                </Provider>,
            )
            .toJSON();
        expect(tree).toMatchSnapshot();
    });

    // it('renders correctly with different className', () => {
    //     const className = 'className';
    //     const wrapper = mount(
    //         <Provider accordionStore={accordionStore} uuid={uuid}>
    //             <AccordionItemBody className={className} />
    //         </Provider>,
    //     );
    //     expect(wrapper.find('div').hasClass(className)).toEqual(true);
    // });

    // it('renders correctly with different hideBodyClassName', () => {
    //     const hideBodyClassName = 'hideBodyClassName';
    //     const wrapper = mount(
    //         <Provider accordionStore={accordionStore} uuid={uuid}>
    //             <AccordionItemBody hideBodyClassName={hideBodyClassName} />
    //         </Provider>,
    //     );
    //     expect(wrapper.find('div').hasClass(hideBodyClassName)).toEqual(true);
    // });

    // it('renders null if an associated AccordionItem is not registered in accordionStore', () => {
    //     const className = 'className';
    //     const wrapper = mount(
    //         <Provider accordionStore={accordionStore} uuid="foo">
    //             <AccordionItemBody className={className}>
    //
Fake body

    //             </AccordionItemBody>
    //         </Provider>,
    //     );

    //     expect(
    //         wrapper.findWhere(item => item.className === className).length,
    //     ).toEqual(0);
    // });

    // it('respects arbitrary user-defined props', () => {
    //     const wrapper = mount(
    //         <Provider accordionStore={accordionStore} uuid={uuid}>
    //             <AccordionItemBody lang="en" />
    //         </Provider>,
    //     );
    //     expect(wrapper.find('div').instance().lang).toEqual('en');
    // });
});
<commit_msg>Re-enable and fix all tests in accordion-item-body.spec<commit_after>// @flow

import React from 'react';
import renderer from 'react-test-renderer';
import { mount } from 'enzyme';
import { Provider } from 'unstated';
import ItemContainer, { resetNextUuid } from '../ItemContainer/ItemContainer';
import AccordionContainer from '../AccordionContainer/AccordionContainer';
import AccordionItemBody from './accordion-item-body';

describe('AccordionItemBody', () => {
    let accordionStore;
    let itemStore;
    let onChange;

    beforeEach(() => {
        onChange = jest.fn();

        const itemContainer = new ItemContainer();
        resetNextUuid();
        const accordionContainer = new AccordionContainer();
        accordionContainer.setAccordion(true);
        accordionContainer.setOnChange(onChange);
        accordionStore = accordionContainer;
        itemStore = itemContainer;

        accordionStore.addItem({
            uuid: 0, // because `nextUuid` in ItemContainer starts at zero.
            expanded: false,
            disabled: false,
        });
    });

    it('renders correctly with min params', () => {
        const tree = renderer
            .create(
                <Provider inject={[accordionStore, itemStore]}>
                    <AccordionItemBody>

Fake body

                    </AccordionItemBody>
                </Provider>,
            )
            .toJSON();
        expect(tree).toMatchSnapshot();
    });

    it('renders correctly with different className', () => {
        const className = 'className';
        const wrapper = mount(
            <Provider inject={[accordionStore, itemStore]}>
                <AccordionItemBody className={className} />
            </Provider>,
        );
        expect(wrapper.find('div').hasClass(className)).toEqual(true);
    });

    it('renders correctly with different hideBodyClassName', () => {
        const hideBodyClassName = 'hideBodyClassName';
        const wrapper = mount(
            <Provider inject={[accordionStore, itemStore]}>
                <AccordionItemBody hideBodyClassName={hideBodyClassName} />
            </Provider>,
        );
        expect(wrapper.find('div').hasClass(hideBodyClassName)).toEqual(true);
    });

    it('renders null if an associated AccordionItem is not registered in accordionStore', () => {
        const className = 'className';
        const wrapper = mount(
            <Provider inject={[accordionStore, itemStore]}>
                <AccordionItemBody className={className}>

Fake body

                </AccordionItemBody>
            </Provider>,
        );

        expect(
            wrapper.findWhere(item => item.className === className).length,
        ).toEqual(0);
    });

    it('respects arbitrary user-defined props', () => {
        const wrapper = mount(
            <Provider inject={[accordionStore, itemStore]}>
                <AccordionItemBody lang="en" />
            </Provider>,
        );
        expect(wrapper.find('div').instance().lang).toEqual('en');
    });
});
<|endoftext|>


<commit_before>(function(ns)
{

  var JSONC = {},
      _nCode = -1,
      toString = {}.toString;

  if ( !Array.prototype.contains )
  {
    Array.prototype.contains = function ( v )
    {
      var i;
      for ( i = 0; i < this.length; i++ )
      {
        if ( this[i][1] === v )
        {
          return true;
        }
      }
      return false;
    };
  }
  if ( !Array.prototype.unique )
  {
    Array.prototype.unique = function () {
      var i,
          arr = [];
      for ( i = 0; i < this.length; i++)
      {
        if ( !arr.contains( this[i][1] ) ) {
          arr.push( this[i] );
        }
      }
      return arr;
    };
  }
  if(!RegExp.escape)
  {
    RegExp.escape = function( text )
    {
      return text.replace( /[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&" );
    };
  }
  function _isObject ( obj )
  {
    return toString.call( obj ) === "[object Object]";
  }
  function _isArray ( obj )
  {
    return toString.call( obj ) === "[object Array]";
  }
  function biDimensionalArrayToObject( aArr )
  {
    var obj = {},
        nIndex,
        nLen = aArr.length,
        oItem;
    for( nIndex = 0; nIndex < nLen; nIndex++ )
    {
      oItem = aArr[nIndex];
      obj[oItem[0]] = oItem[1];
    }
    return obj;
  }
  function _numberToKey ( index, totalChar, offset ){
    totalChar = totalChar || 26;
    offset = offset || 65;
    var aArr = [];
    var currentChar = index;
    while( currentChar >= totalChar )
    {
      aArr.push( (currentChar % totalChar) + offset );
      currentChar = Math.floor( currentChar / totalChar - 1 );
    }
    aArr.push(currentChar + offset);
    return aArr.reverse();
  }
  function _getSpecialKey ( aKeys )
  {
    return String.fromCharCode.apply(String, aKeys);
  }
  function _getKeys ( json, aKeys )
  {
    var aKey,
      sKey,
      oItem;

    for ( sKey in json )
    {

      if ( json.hasOwnProperty( sKey ) )
      {
        oItem = json[sKey];
        if ( _isObject( oItem ) || _isArray( oItem ) )
        {
          aKeys = aKeys.concat( _getKeys( oItem, aKeys).unique() );
        }
        if ( isNaN( Number( sKey ) ) )
        {
          if ( !aKeys.contains( sKey ) )
          {
            _nCode += 1;
            aKey = [];
            aKey.push( _getSpecialKey( _numberToKey( _nCode ) ), sKey );
            aKeys.push( aKey );
          }
        }
      }
    }
    return aKeys;
  }
  JSONC.compress = function ( json, optKeys )
  {
    if(!optKeys)
    {
      _nCode = -1;
    }
    var aKeys = optKeys || [],
      oKeys,
      aKey,
      obj,
      str,
      nIndex,
      nLenKeys;
    if ( _isArray( json ) )
    {
      for ( nIndex = 0, nLenKeys = json.length; nIndex < nLenKeys; nIndex++ )
      {
        json[nIndex] = this.compress( json[nIndex], aKeys );
      }
    }
    else
    {
      aKeys = _getKeys( json, aKeys );
      aKeys = aKeys.unique();
      oKeys = biDimensionalArrayToObject( aKeys );

      str = JSON.stringify( json );
      nLenKeys = aKeys.length;

      for ( nIndex = 0; nIndex < nLenKeys; nIndex++ )
      {
        aKey = aKeys[nIndex];
        str = str.replace( new RegExp( RegExp.escape( '"' + aKey[1] + '"' ), "g" ), '"' + aKey[0] + '"' );
      }

      obj = JSON.parse( str );
      obj._ = oKeys;
    }
    return obj || json;
  };
  JSONC.decompress = function ( json )
  {
    var nIndex,
      oKeys,
      str,
      sKey,
      nLenKeys,
      jsonCopy = JSON.parse( JSON.stringify( json ) );
    if ( _isArray( json ) )
    {
      for ( nIndex = 0, nLenKeys = json.length; nIndex < nLenKeys; nIndex++ )
      {
        json[nIndex] = this.decompress( json[nIndex] );
      }
    }
    else
    {
      oKeys = JSON.parse( JSON.stringify( jsonCopy._ ) );
      delete jsonCopy._;
      str = JSON.stringify( jsonCopy );
      for( sKey in oKeys)
      {
        if(oKeys.hasOwnProperty(sKey))
        {
          str = str.replace( new RegExp( '"' + sKey + '"', "g" ), '"' +  oKeys[sKey] + '"' );
        }
      }
    }
    return str ? JSON.parse(str): json ;
  };

  ns.JSONC = JSONC;
}((window.Namespace = {})));<commit_msg>Reduce complexity in compress method<commit_after>(function(ns)
{

  var JSONC = {},
      _nCode = -1,
      toString = {}.toString;

  if ( !Array.prototype.contains )
  {
    Array.prototype.contains = function ( v )
    {
      var i;
      for ( i = 0; i < this.length; i++ )
      {
        if ( this[i][1] === v )
        {
          return true;
        }
      }
      return false;
    };
  }
  if ( !Array.prototype.unique )
  {
    Array.prototype.unique = function () {
      var i,
          arr = [];
      for ( i = 0; i < this.length; i++)
      {
        if ( !arr.contains( this[i][1] ) ) {
          arr.push( this[i] );
        }
      }
      return arr;
    };
  }
  if(!RegExp.escape)
  {
    RegExp.escape = function( text )
    {
      return text.replace( /[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&" );
    };
  }
  function _isObject ( obj )
  {
    return toString.call( obj ) === "[object Object]";
  }
  function _isArray ( obj )
  {
    return toString.call( obj ) === "[object Array]";
  }
  function biDimensionalArrayToObject( aArr )
  {
    var obj = {},
        nIndex,
        nLen = aArr.length,
        oItem;
    for( nIndex = 0; nIndex < nLen; nIndex++ )
    {
      oItem = aArr[nIndex];
      obj[oItem[0]] = oItem[1];
    }
    return obj;
  }
  function _numberToKey ( index, totalChar, offset ){
    totalChar = totalChar || 26;
    offset = offset || 65;
    var aArr = [];
    var currentChar = index;
    while( currentChar >= totalChar )
    {
      aArr.push( (currentChar % totalChar) + offset );
      currentChar = Math.floor( currentChar / totalChar - 1 );
    }
    aArr.push(currentChar + offset);
    return aArr.reverse();
  }
  function _getSpecialKey ( aKeys )
  {
    return String.fromCharCode.apply(String, aKeys);
  }
  function _getKeys ( json, aKeys )
  {
    var aKey,
      sKey,
      oItem;

    for ( sKey in json )
    {

      if ( json.hasOwnProperty( sKey ) )
      {
        oItem = json[sKey];
        if ( _isObject( oItem ) || _isArray( oItem ) )
        {
          aKeys = aKeys.concat( _getKeys( oItem, aKeys).unique() );
        }
        if ( isNaN( Number( sKey ) ) )
        {
          if ( !aKeys.contains( sKey ) )
          {
            _nCode += 1;
            aKey = [];
            aKey.push( _getSpecialKey( _numberToKey( _nCode ) ), sKey );
            aKeys.push( aKey );
          }
        }
      }
    }
    return aKeys;
  }
  function compressArray ( json, aKeys )
  {
    var nIndex,
        nLenKeys;

    for ( nIndex = 0, nLenKeys = json.length; nIndex < nLenKeys; nIndex++ )
    {
      json[nIndex] = JSONC.compress( json[nIndex], aKeys );
    }
  }
  function compressOther ( json, aKeys )
  {
    var oKeys,
        aKey,
        str,
        nLenKeys,
        nIndex,
        obj;
    aKeys = _getKeys( json, aKeys );
    aKeys = aKeys.unique();
    oKeys = biDimensionalArrayToObject( aKeys );

    str = JSON.stringify( json );
    nLenKeys = aKeys.length;

    for ( nIndex = 0; nIndex < nLenKeys; nIndex++ )
    {
      aKey = aKeys[nIndex];
      str = str.replace( new RegExp( RegExp.escape( '"' + aKey[1] + '"' ), "g" ), '"' + aKey[0] + '"' );
    }

    obj = JSON.parse( str );
    obj._ = oKeys;
    return obj;
  }
  JSONC.compress = function ( json, optKeys )
  {
    if(!optKeys)
    {
      _nCode = -1;
    }
    var aKeys = optKeys || [],
      obj;
    if ( _isArray( json ) )
    {
      compressArray( json, aKeys );
    }
    else
    {
      obj = compressOther ( json, aKeys );
    }
    return obj || json;
  };
  JSONC.decompress = function ( json )
  {
    var nIndex,
      oKeys,
      str,
      sKey,
      nLenKeys,
      jsonCopy = JSON.parse( JSON.stringify( json ) );
    if ( _isArray( json ) )
    {
      for ( nIndex = 0, nLenKeys = json.length; nIndex < nLenKeys; nIndex++ )
      {
        json[nIndex] = this.decompress( json[nIndex] );
      }
    }
    else
    {
      oKeys = JSON.parse( JSON.stringify( jsonCopy._ ) );
      delete jsonCopy._;
      str = JSON.stringify( jsonCopy );
      for( sKey in oKeys)
      {
        if(oKeys.hasOwnProperty(sKey))
        {
          str = str.replace( new RegExp( '"' + sKey + '"', "g" ), '"' +  oKeys[sKey] + '"' );
        }
      }
    }
    return str ? JSON.parse(str): json ;
  };

  ns.JSONC = JSONC;
}((window.Namespace = {})));<|endoftext|>


<commit_before>/* globals: ga_track_event */
hqDefine('app_manager/js/releases.js', function () {
    function SavedApp(app_data, releasesMain) {
        var self = ko.mapping.fromJS(app_data);
        $.each(['comment_user_name', '_deleteState'], function (i, attr) {
            self[attr] = self[attr] || ko.observable();
        });
        if (!self.include_media) {
            self.include_media = ko.observable(self.doc_type() !== "RemoteApp");
        }
        if(!self.generating_url){
            self.generating_url = ko.observable(false);
        }
        self.include_media.subscribe(function() {
            // If we've generated an app code ensure that we update it when we toggle media
            if (self.app_code()) {
                self.get_app_code();
            }
        });
        self.num_errors = ko.observable(app_data.num_errors || 0);
        self.app_code = ko.observable(null);
        self.failed_url_generation = ko.observable(false);
        self.build_profile = ko.observable('');
        self.base_url = function() {
            return '/a/' + self.domain() + '/apps/odk/' + self.id() + '/';
        };
        self.build_profiles = function() {
            var profiles = [{'label': gettext('(Default)'), 'value': ''}];
            _.each(app_data.build_profiles, function(value, key) {
                profiles.push({'label': value['name'], 'value': key});
            });
            return profiles;
        };

        self.track_deploy_type = function(type) {
            ga_track_event('App Manager', 'Deploy Type', type);
        };

        self.changeAppCode = function () {
            self.app_code(null);
            self.failed_url_generation(false);
            self.generating_url(false);
        };

        self.onSMSPanelClick = function() {
            self.track_deploy_type('Send to phone via SMS');
            self.generate_short_url('short_url');
        };

        self.build_profile.subscribe(self.changeAppCode);

        self.should_generate_url = function(url_type) {
            var types = _.values(SavedApp.URL_TYPES);
            return (types.indexOf(url_type) !== 1 &&
                !ko.utils.unwrapObservable(self[url_type]));
        };

        self.generate_short_url = function(url_type) {
            //accepted_url_types = ['short_odk_url', 'short_odk_media_url', 'short_url']
            url_type = url_type || SavedApp.URL_TYPES.SHORT_ODK_URL;
            var base_url = self.base_url(),
                should_generate_url = self.should_generate_url();

            if (should_generate_url && !self.generating_url()){
                self.generating_url(true);
                $.ajax({
                    url: base_url + url_type + '/?profile=' + self.build_profile(),
                }).done(function(data){
                    var bitly_code = self.parse_bitly_url(data);
                    if (!self.build_profile()) {
                        self[url_type](data);
                    }

                    self.failed_url_generation(!bitly_code);
                    self.app_code(bitly_code);

                }).fail(function() {
                    self.app_code(null);
                    self.failed_url_generation(true);
                }).always(function(){
                    self.generating_url(false);
                });
            }
        };

        self.get_short_odk_url = function() {
            var url_type;
            if (self.include_media()) {
                url_type = SavedApp.URL_TYPES.SHORT_ODK_MEDIA_URL;
            } else {
                url_type = SavedApp.URL_TYPES.SHORT_ODK_URL;
            }
            if (!(ko.utils.unwrapObservable(self[url_type])) || self.build_profile()) {
                return self.generate_short_url(url_type);
            } else {
                return ko.utils.unwrapObservable(self[url_type]);
            }
        };

        self.parse_bitly_url = function(url) {
            // Matches "foo" in "http://bit.ly/foo" and "https://is.gd/X/foo/" ("*" is not greedy)
            var re = /^http.*\/(\w+)\/?/;
            var match = url.match(re);
            if (match) {
                return match[1];
            }
            return null;
        };

        self.click_app_code = function() {
            self.get_app_code();
            ga_track_event('App Manager', 'Initiate Install', 'Get App Code');
            analytics.workflow('Initiate Installation Method');
        };

        self.get_app_code = function() {
            var short_odk_url = self.get_short_odk_url();
            if (short_odk_url) {
                self.app_code(self.parse_bitly_url(short_odk_url));
            }
        };

        self.allow_media_install = ko.computed(function(){
            return self.doc_type() !== "RemoteApp";  // remote apps don't support multimedia
        });

        self.mm_supported = function() {
            // This is added to fix legacy issues with incorrectly formatted media_profile.ccpr files.
            // Files that were generated prior to 10/16/2013 are affected, so don't support remote mm for build made before then.
            var supported_date = new Date(2013, 9, 16);
            var date_built = new Date(self.built_on());
            return date_built.getTime() > supported_date.getTime();
        };

        self.get_odk_install_url = ko.computed(function() {
            var slug = self.include_media() ? 'odk_media' : 'odk';
            return releasesMain.url(slug, self.id());
        });

        self.full_odk_install_url = ko.computed(function() {
            return self.get_odk_install_url() + '?profile=' + self.build_profile();
        });

        self.sms_url = function(index) {
            if (index === 0) { // sending to sms
                return self.short_url();
            } else { // sending to odk
                if (self.include_media() && self.short_odk_media_url()) {
                    return self.short_odk_media_url();
                } else {
                    return self.short_odk_url();
                }
            }
        };

        self.download_application_zip = function (multimedia_only, build_profile) {
            releasesMain.download_application_zip(self.id(), multimedia_only, build_profile);
        };

        self.clickDeploy = function () {
            ga_track_event('App Manager', 'Deploy Button', self.id());
            analytics.workflow('Clicked Deploy');
            $.post(releasesMain.options.urls.hubspot_click_deploy);
        };

        self.clickScan = function() {
            self.handleScanModal();
            self.trackScan();
        };

        self.handleScanModal = function() {

            // Hide the main deploy modal, then re-open
            // it when the scan barcode modal is closed
            var $deployModal = $('.modal.fade.in');
            $deployModal.modal('hide');
            $('body').one("hide.bs.modal", function() {
                $deployModal.modal({ show: true });
            });
        };

        self.trackScan = function() {
            ga_track_event('App Manager', 'Initiate Install', 'Show Bar Code');
            analytics.workflow('Initiate Installation Method');
        };

        self.reveal_java_download = function(){
            return this.j2me_enabled();
        };
        return self;
    }

    function ReleasesMain(o) {
        /* {fetchUrl, deleteUrl} */
        var AsyncDownloader = hqImport('app_manager/js/download_async_modal.js').AsyncDownloader;
        var self = this;
        self.options = o;
        self.recipients = self.options.recipient_contacts;
        self.savedApps = ko.observableArray();
        self.doneFetching = ko.observable(false);
        self.buildState = ko.observable('');
        self.fetchState = ko.observable('');
        self.nextVersionToFetch = null;
        self.fetchLimit = o.fetchLimit || 5;
        self.deployAnyway = {};
        self.currentAppVersion = ko.observable(self.options.currentAppVersion);
        self.lastAppVersion = ko.observable();
        self.selectingVersion = ko.observable("");

        self.download_modal = $(self.options.download_modal_id);
        self.async_downloader = new AsyncDownloader(self.download_modal);

        self.download_application_zip = function(appId, multimedia_only, build_profile) {
            var url_slug = multimedia_only ? 'download_multimedia' : 'download_zip';
            var url = self.url(url_slug, appId);
            var params = {};
            params.message = "Your application download is ready";
            if (build_profile) {
                params.profile = build_profile;
            }
            self.async_downloader.generateDownload(url, params);
            // Not so nice... Hide the open modal so we don't get bootstrap recursion errors
            // http://stackoverflow.com/questions/13649459/twitter-bootstrap-multiple-modal-error
            $('.modal.fade.in').modal('hide');
            self.download_modal.modal({show: true});
        };

        self.buildButtonEnabled = ko.computed(function () {
            if (self.buildState() === 'pending' || self.fetchState() === 'pending') {
                return false;
            } else {
                return true;
            }
        });
        self.brokenBuilds = ko.computed(function () {
            var apps = self.savedApps();
            return _.some(apps, function (app) {
                return app.build_broken();
            });
        });
        self.savedApps.subscribe(function () {
            var lastApp = self.savedApps()[0];
            self.lastAppVersion(lastApp ? lastApp.version() : -1);
        });
        self.url = function (name) {
            var template = self.options.urls[name];
            for (var i = 1; i < arguments.length; i++) {
                template = template.replace('___', ko.utils.unwrapObservable(arguments[i]));
            }
            return template;
        };
        self.latestReleaseId = ko.computed(function () {
            for (var i = 0; i < self.savedApps().length; i++) {
                var savedApp = self.savedApps()[i];
                if (savedApp.is_released()) {
                    return savedApp.id();
                }
            }
        });

        self.addSavedApp = function (savedApp, toBeginning) {
            if (toBeginning) {
                self.savedApps.unshift(savedApp);
            } else {
                self.savedApps.push(savedApp);
            }
            self.deployAnyway[savedApp.id()] = ko.observable(false);
        };

        self.addSavedApps = function (savedApps) {
            var i, savedApp;
            for (i = 0; i < savedApps.length; i++) {
                savedApp = SavedApp(savedApps[i], self);
                self.addSavedApp(savedApp);
            }
            if (i) {
                self.nextVersionToFetch = savedApps[i - 1].version - 1;
            }
            if (savedApps.length < self.fetchLimit) {
                self.doneFetching(true);
            } else {
                self.doneFetching(false);
            }
        };

        self.getMoreSavedApps = function (scroll) {
            self.fetchState('pending');
            $.ajax({
                url: self.url('fetch'),
                dataType: 'json',
                data: {
                    start_build: self.nextVersionToFetch,
                    limit: self.fetchLimit
                },
                success: function (savedApps) {
                    self.addSavedApps(savedApps);
                    self.fetchState('');
                    if (scroll) {
                        // Scroll so the bottom of main content (and the "View More" button) aligns with the bottom of the window
                        var $content = $("#hq-content");
                        window.scrollTo(0, $content.position().top + $content.height() - window.innerHeight);
                    }
                },
                error: function () {
                    self.fetchState('error');
                }
            });
        };

        self.toggleRelease = function (savedApp) {
            var is_released = savedApp.is_released();
            var saved_app_id = savedApp.id();
            if (savedApp.is_released() !== 'pending') {
                var url = self.url('release', saved_app_id);
                var that = this;
                $.ajax({
                    url: url,
                    type: 'post',
                    dataType: 'json',
                    data: {ajax: true, is_released: !is_released},
                    beforeSend: function (jqXHR, settings) {
                        savedApp.is_released('pending');
                        if ($.ajaxSettings.beforeSend) {
                            $.ajaxSettings.beforeSend(jqXHR, settings);
                        }
                    },
                    success: function (data) {
                        savedApp.is_released(data.is_released);
                    },
                    error: function () {
                        savedApp.is_released('error');
                    }
                });
            }
        };
        self.reload_message = "Sorry, that didn't go through. " +
                "Please reload your page and try again";
        self.deleteSavedApp = function (savedApp) {
            savedApp._deleteState('pending');
            $.post({
                url: self.url('delete'),
                data: {saved_app: savedApp.id()},
                success: function () {
                    self.savedApps.remove(savedApp);
                    savedApp._deleteState(false);
                },
                error: function () {
                    savedApp._deleteState('error');
                    alert(self.reload_message);
                },
            });
        };
        self.revertSavedApp = function (savedApp) {
            $.postGo(self.url('revertBuild'), {saved_app: savedApp.id()});
        };
        self.makeNewBuild = function () {
            if (self.buildState() === 'pending') {
                return false;
            }

            var url = self.url('currentVersion');
            self.fetchState('pending');
            $.get({
                url: self.url('currentVersion'),
                success: function(data) {
                    self.fetchState('');
                    self.currentAppVersion(data.currentVersion);
                    if (!data.latestRelease) {
                        self.actuallyMakeBuild();
                    } else if (data.latestRelease !== self.lastAppVersion()) {
                        window.alert("The versions list has changed since you loaded the page.");
                        self.reloadApps();
                    } else if (self.lastAppVersion() !== self.currentAppVersion()) {
                        self.actuallyMakeBuild();
                    } else {
                        window.alert("No new changes to deploy!");
                    }
                },
                error: function () {
                    self.fetchState('error');
                    window.alert(self.reload_message);
                },
            });
        };
        self.reloadApps = function () {
            self.savedApps([]);
            self.nextVersionToFetch = null;
            self.getMoreSavedApps(false);
        };
        self.actuallyMakeBuild = function () {
            self.buildState('pending');
            $.post({
                url: self.url('newBuild'),
                success: function(data) {
                    $('#build-errors-wrapper').html(data.error_html);
                    if (data.saved_app) {
                        var app = SavedApp(data.saved_app, self);
                        self.addSavedApp(app, true);
                    }
                    self.buildState('');
                },
                error: function () {
                    self.buildState('error');
                },
            });
        };
    }

    SavedApp.URL_TYPES = {
        SHORT_ODK_URL: 'short_odk_url',
        SHORT_ODK_MEDIA_URL: 'short_odk_media_url',
        SHORT_URL: 'short_url'
    };

    return {
        ReleasesMain: ReleasesMain,
        SavedApp: SavedApp
    };
});
<commit_msg>get rid of useless diff<commit_after>/* globals: ga_track_event */
hqDefine('app_manager/js/releases.js', function () {
    function SavedApp(app_data, releasesMain) {
        var self = ko.mapping.fromJS(app_data);
        $.each(['comment_user_name', '_deleteState'], function (i, attr) {
            self[attr] = self[attr] || ko.observable();
        });
        if (!self.include_media) {
            self.include_media = ko.observable(self.doc_type() !== "RemoteApp");
        }
        if(!self.generating_url){
            self.generating_url = ko.observable(false);
        }
        self.include_media.subscribe(function() {
            // If we've generated an app code ensure that we update it when we toggle media
            if (self.app_code()) {
                self.get_app_code();
            }
        });
        self.num_errors = ko.observable(app_data.num_errors || 0);
        self.app_code = ko.observable(null);
        self.failed_url_generation = ko.observable(false);
        self.build_profile = ko.observable('');
        self.base_url = function() {
            return '/a/' + self.domain() + '/apps/odk/' + self.id() + '/';
        };
        self.build_profiles = function() {
            var profiles = [{'label': gettext('(Default)'), 'value': ''}];
            _.each(app_data.build_profiles, function(value, key) {
                profiles.push({'label': value['name'], 'value': key});
            });
            return profiles;
        };

        self.track_deploy_type = function(type) {
            ga_track_event('App Manager', 'Deploy Type', type);
        };

        self.changeAppCode = function () {
            self.app_code(null);
            self.failed_url_generation(false);
            self.generating_url(false);
        };

        self.onSMSPanelClick = function() {
            self.track_deploy_type('Send to phone via SMS');
            self.generate_short_url('short_url');
        };

        self.build_profile.subscribe(self.changeAppCode);

        self.should_generate_url = function(url_type) {
            var types = _.values(SavedApp.URL_TYPES);
            return (types.indexOf(url_type) !== 1 &&
                !ko.utils.unwrapObservable(self[url_type]));
        };

        self.generate_short_url = function(url_type) {
            //accepted_url_types = ['short_odk_url', 'short_odk_media_url', 'short_url']
            url_type = url_type || SavedApp.URL_TYPES.SHORT_ODK_URL;
            var base_url = self.base_url(),
                should_generate_url = self.should_generate_url();

            if (should_generate_url && !self.generating_url()){
                self.generating_url(true);
                $.ajax({
                    url: base_url + url_type + '/?profile=' + self.build_profile(),
                }).done(function(data){
                    var bitly_code = self.parse_bitly_url(data);
                    if (!self.build_profile()) {
                        self[url_type](data);
                    }

                    self.failed_url_generation(!bitly_code);
                    self.app_code(bitly_code);

                }).fail(function() {
                    self.app_code(null);
                    self.failed_url_generation(true);
                }).always(function(){
                    self.generating_url(false);
                });
            }
        };

        self.get_short_odk_url = function() {
            var url_type;
            if (self.include_media()) {
                url_type = SavedApp.URL_TYPES.SHORT_ODK_MEDIA_URL;
            } else {
                url_type = SavedApp.URL_TYPES.SHORT_ODK_URL;
            }
            if (!(ko.utils.unwrapObservable(self[url_type])) || self.build_profile()) {
                return self.generate_short_url(url_type);
            } else {
                return ko.utils.unwrapObservable(self[url_type]);
            }
        };

        self.parse_bitly_url = function(url) {
            // Matches "foo" in "http://bit.ly/foo" and "https://is.gd/X/foo/" ("*" is not greedy)
            var re = /^http.*\/(\w+)\/?/;
            var match = url.match(re);
            if (match) {
                return match[1];
            }
            return null;
        };

        self.click_app_code = function() {
            self.get_app_code();
            ga_track_event('App Manager', 'Initiate Install', 'Get App Code');
            analytics.workflow('Initiate Installation Method');
        };

        self.get_app_code = function() {
            var short_odk_url = self.get_short_odk_url();
            if (short_odk_url) {
                self.app_code(self.parse_bitly_url(short_odk_url));
            }
        };

        self.allow_media_install = ko.computed(function(){
            return self.doc_type() !== "RemoteApp";  // remote apps don't support multimedia
        });

        self.mm_supported = function() {
            // This is added to fix legacy issues with incorrectly formatted media_profile.ccpr files.
            // Files that were generated prior to 10/16/2013 are affected, so don't support remote mm for build made before then.
            var supported_date = new Date(2013, 9, 16);
            var date_built = new Date(self.built_on());
            return date_built.getTime() > supported_date.getTime();
        };

        self.get_odk_install_url = ko.computed(function() {
            var slug = self.include_media() ? 'odk_media' : 'odk';
            return releasesMain.url(slug, self.id());
        });

        self.full_odk_install_url = ko.computed(function() {
            return self.get_odk_install_url() + '?profile=' + self.build_profile();
        });

        self.sms_url = function(index) {
            if (index === 0) { // sending to sms
                return self.short_url();
            } else { // sending to odk
                if (self.include_media() && self.short_odk_media_url()) {
                    return self.short_odk_media_url();
                } else {
                    return self.short_odk_url();
                }
            }
        };

        self.download_application_zip = function (multimedia_only, build_profile) {
            releasesMain.download_application_zip(self.id(), multimedia_only, build_profile);
        };

        self.clickDeploy = function () {
            ga_track_event('App Manager', 'Deploy Button', self.id());
            analytics.workflow('Clicked Deploy');
            $.post(releasesMain.options.urls.hubspot_click_deploy);
        };

        self.clickScan = function() {
            self.handleScanModal();
            self.trackScan();
        };

        self.handleScanModal = function() {

            // Hide the main deploy modal, then re-open
            // it when the scan barcode modal is closed
            var $deployModal = $('.modal.fade.in');
            $deployModal.modal('hide');
            $('body').one("hide.bs.modal", function() {
                $deployModal.modal({ show: true });
            });
        };

        self.trackScan = function() {
            ga_track_event('App Manager', 'Initiate Install', 'Show Bar Code');
            analytics.workflow('Initiate Installation Method');
        };

        self.reveal_java_download = function(){
            return this.j2me_enabled();
        };
        return self;
    }

    function ReleasesMain(o) {
        /* {fetchUrl, deleteUrl} */
        var AsyncDownloader = hqImport('app_manager/js/download_async_modal.js').AsyncDownloader;
        var self = this;
        self.options = o;
        self.recipients = self.options.recipient_contacts;
        self.savedApps = ko.observableArray();
        self.doneFetching = ko.observable(false);
        self.buildState = ko.observable('');
        self.fetchState = ko.observable('');
        self.nextVersionToFetch = null;
        self.fetchLimit = o.fetchLimit || 5;
        self.deployAnyway = {};
        self.currentAppVersion = ko.observable(self.options.currentAppVersion);
        self.lastAppVersion = ko.observable();
        self.selectingVersion = ko.observable("");

        self.download_modal = $(self.options.download_modal_id);
        self.async_downloader = new AsyncDownloader(self.download_modal);

        self.download_application_zip = function(appId, multimedia_only, build_profile) {
            var url_slug = multimedia_only ? 'download_multimedia' : 'download_zip';
            var url = self.url(url_slug, appId);
            var params = {};
            params.message = "Your application download is ready";
            if (build_profile) {
                params.profile = build_profile;
            }
            self.async_downloader.generateDownload(url, params);
            // Not so nice... Hide the open modal so we don't get bootstrap recursion errors
            // http://stackoverflow.com/questions/13649459/twitter-bootstrap-multiple-modal-error
            $('.modal.fade.in').modal('hide');
            self.download_modal.modal({show: true});
        };

        self.buildButtonEnabled = ko.computed(function () {
            if (self.buildState() === 'pending' || self.fetchState() === 'pending') {
                return false;
            } else {
                return true;
            }
        });
        self.brokenBuilds = ko.computed(function () {
            var apps = self.savedApps();
            return _.some(apps, function (app) {
                return app.build_broken();
            });
        });
        self.savedApps.subscribe(function () {
            var lastApp = self.savedApps()[0];
            self.lastAppVersion(lastApp ? lastApp.version() : -1);
        });
        self.url = function (name) {
            var template = self.options.urls[name];
            for (var i = 1; i < arguments.length; i++) {
                template = template.replace('___', ko.utils.unwrapObservable(arguments[i]));
            }
            return template;
        };
        self.latestReleaseId = ko.computed(function () {
            for (var i = 0; i < self.savedApps().length; i++) {
                var savedApp = self.savedApps()[i];
                if (savedApp.is_released()) {
                    return savedApp.id();
                }
            }
        });

        self.addSavedApp = function (savedApp, toBeginning) {
            if (toBeginning) {
                self.savedApps.unshift(savedApp);
            } else {
                self.savedApps.push(savedApp);
            }
            self.deployAnyway[savedApp.id()] = ko.observable(false);
        };

        self.addSavedApps = function (savedApps) {
            var i, savedApp;
            for (i = 0; i < savedApps.length; i++) {
                savedApp = SavedApp(savedApps[i], self);
                self.addSavedApp(savedApp);
            }
            if (i) {
                self.nextVersionToFetch = savedApps[i - 1].version - 1;
            }
            if (savedApps.length < self.fetchLimit) {
                self.doneFetching(true);
            } else {
                self.doneFetching(false);
            }
        };

        self.getMoreSavedApps = function (scroll) {
            self.fetchState('pending');
            $.ajax({
                url: self.url('fetch'),
                dataType: 'json',
                data: {
                    start_build: self.nextVersionToFetch,
                    limit: self.fetchLimit
                },
                success: function (savedApps) {
                    self.addSavedApps(savedApps);
                    self.fetchState('');
                    if (scroll) {
                        // Scroll so the bottom of main content (and the "View More" button) aligns with the bottom of the window
                        var $content = $("#hq-content");
                        window.scrollTo(0, $content.position().top + $content.height() - window.innerHeight);
                    }
                },
                error: function () {
                    self.fetchState('error');
                }
            });
        };

        self.toggleRelease = function (savedApp) {
            var is_released = savedApp.is_released();
            var saved_app_id = savedApp.id();
            if (savedApp.is_released() !== 'pending') {
                var url = self.url('release', saved_app_id);
                var that = this;
                $.ajax({
                    url: url,
                    type: 'post',
                    dataType: 'json',
                    data: {ajax: true, is_released: !is_released},
                    beforeSend: function (jqXHR, settings) {
                        savedApp.is_released('pending');
                        if ($.ajaxSettings.beforeSend) {
                            $.ajaxSettings.beforeSend(jqXHR, settings);
                        }
                    },
                    success: function (data) {
                        savedApp.is_released(data.is_released);
                    },
                    error: function () {
                        savedApp.is_released('error');
                    }
                });
            }
        };
        self.reload_message = "Sorry, that didn't go through. " +
                "Please reload your page and try again";
        self.deleteSavedApp = function (savedApp) {
            savedApp._deleteState('pending');
            $.post({
                url: self.url('delete'),
                data: {saved_app: savedApp.id()},
                success: function () {
                    self.savedApps.remove(savedApp);
                    savedApp._deleteState(false);
                },
                error: function () {
                    savedApp._deleteState('error');
                    alert(self.reload_message);
                },
            });
        };
        self.revertSavedApp = function (savedApp) {
            $.postGo(self.url('revertBuild'), {saved_app: savedApp.id()});
        };
        self.makeNewBuild = function () {
            if (self.buildState() === 'pending') {
                return false;
            }

            var url = self.url('currentVersion');
            self.fetchState('pending');
            $.get({
                url: self.url('currentVersion'),
                success: function(data) {
                    self.fetchState('');
                    self.currentAppVersion(data.currentVersion);
                    if (!data.latestRelease) {
                        self.actuallyMakeBuild();
                    } else if (data.latestRelease !== self.lastAppVersion()) {
                        window.alert("The versions list has changed since you loaded the page.");
                        self.reloadApps();
                    } else if (self.lastAppVersion() !== self.currentAppVersion()) {
                        self.actuallyMakeBuild();
                    } else {
                        window.alert("No new changes to deploy!");
                    }
                },
                error: function () {
                    self.fetchState('error');
                    window.alert(self.reload_message);
                },
            });
        };
        self.reloadApps = function () {
            self.savedApps([]);
            self.nextVersionToFetch = null;
            self.getMoreSavedApps(false);
        };
        self.actuallyMakeBuild = function () {
            self.buildState('pending');
            $.post({
                url: self.url('newBuild'),
                success: function(data) {
                    $('#build-errors-wrapper').html(data.error_html);
                    if (data.saved_app) {
                        var app = SavedApp(data.saved_app, self);
                        self.addSavedApp(app, true);
                    }
                    self.buildState('');
                },
                error: function() {
                    self.buildState('error');
                },
            });
        };
    }

    SavedApp.URL_TYPES = {
        SHORT_ODK_URL: 'short_odk_url',
        SHORT_ODK_MEDIA_URL: 'short_odk_media_url',
        SHORT_URL: 'short_url'
    };

    return {
        ReleasesMain: ReleasesMain,
        SavedApp: SavedApp
    };
});
<|endoftext|>