<commit_before>//
// Linkedin
//
(function(hello){

function formatError(o){
	if(o && "errorCode" in o){
		o.error = {
			code : o.status,
			message : o.message
		};
	}
}

function formatUser(o){
	if(o.error){
		return;
	}
	o.first_name = o.firstName;
	o.last_name = o.lastName;
	o.name = o.formattedName || (o.first_name + ' ' + o.last_name);
	o.thumbnail = o.pictureUrl;
}

function formatFriends(o){
	formatError(o);
	paging(o);
	if(o.values){
		o.data = o.values;
		for(var i=0;i<o.data.length;i++){
			formatUser(o.data[i]);
		}
		delete o.values;
	}
	return o;
}

function paging(res){
	if( "_count" in res && "_start" in res && (res._count + res._start) < res._total ){
		res['paging'] = {
			next : "?start="+(res._start+res._count)+"&count="+res._count
		};
	}
}

function empty(o,headers){
	if(JSON.stringify(o) === '{}'&&headers.statusCode === 200){
		o.success = true;
	}
}

hello.init({
	'linkedin' : {

		oauth : {
			version : 2,
			response_type : 'code',
			auth	: "https://www.linkedin.com/uas/oauth2/authorization",
			grant	: "https://www.linkedin.com/uas/oauth2/accessToken"
		},

		// Refresh the access_token once expired
		refresh : true,

		scope : {
			basic	: 'r_fullprofile',
			email	: 'r_emailaddress',
			friends : 'r_network',
			publish : 'rw_nus'
		},
		scope_delim : ' ',

		base	: "https://api.linkedin.com/v1/",

		get : {
			"me"			: 'people/~:(picture-url,first-name,last-name,id,formatted-name)',
			"me/friends"	: 'people/~/connections?count=@{limit|500}',
			"me/followers"	: 'people/~/connections?count=@{limit|500}',
			"me/following"	: 'people/~/connections?count=@{limit|500}',

			// http://developer.linkedin.com/documents/get-network-updates-and-statistics-api
			"me/share"		: "people/~/network/updates?count=@{limit|250}"
		},

		post : {

			// https://developer.linkedin.com/documents/api-requests-json
			"me/share"		: function(p, callback){
				var data =  {
					"visibility": {
						"code": "anyone"
					}
				};

				if(p.data.id){

					data["attribution"] = {
						"share": {
							"id": p.data.id
						}
					};

				}
				else{
					data["comment"] = p.data.message;
					data["content"] = {
						"submitted-url": p.data.link,
						"submitted-image-url": p.data.picture
					};
				}

				p.data = JSON.stringify(data);

				callback('people/~/shares?format=json');
			},

			"me/like" : like
		},

		del :{
			"me/like" : like
		},

		wrap : {
			me : function(o){
				formatError(o);
				formatUser(o);
				return o;
			},
			"me/friends" : formatFriends,
			"me/following" : formatFriends,
			"me/followers" : formatFriends,
			"me/share" : function(o){
				formatError(o);
				paging(o);
				if(o.values){
					o.data = o.values;
					delete o.values;
					for(var i=0;i<o.data.length;i++){
						var d = o.data[i];
						formatUser(d);
						d.message = d.headline;
					}
				}
				return o;
			},
			"default" : function(o,headers){
				formatError(o);
				empty(o,headers);
				paging(o);
			}
		},
		jsonp : function(p,qs){
			formatQuery(qs);
			if(p.method==='get'){
				qs.format = 'jsonp';
				qs['error-callback'] = p.callbackID;
			}
		},
		xhr : function(p,qs){
			if(p.method !== 'get'){
				formatQuery(qs);
				p.headers['Content-Type'] = 'application/json';
				// x-li-format ensures error responses are not returned in XML
				p.headers['x-li-format'] = 'json';
				p.proxy = true;
				return true;
			}
			return false;
		}
	}
});

function formatQuery(qs){
	// Linkedin signs requests with the parameter 'oauth2_access_token'... yeah anotherone who thinks they should be different!
	if(qs.access_token){
		qs.oauth2_access_token = qs.access_token;
		delete qs.access_token;
	}
}

function like(p, callback){
	p.headers["x-li-format"] = "json";
	var id = p.data.id;
	p.data = (p.method !== 'delete').toString();
	p.method = 'put';
	callback('people/~/network/updates/key=' + id + '/is-liked');
}

})(hello);
<commit_msg>Moved changes from hello.all.js and hello.all.min.js to linkedin.js per request of MrSwitch.<commit_after>//
// Linkedin
//
(function(hello){

function formatError(o){
	if(o && "errorCode" in o){
		o.error = {
			code : o.status,
			message : o.message
		};
	}
}

function formatUser(o){
	if(o.error){
		return;
	}
	o.first_name = o.firstName;
	o.last_name = o.lastName;
	o.name = o.formattedName || (o.first_name + ' ' + o.last_name);
	o.thumbnail = o.pictureUrl;
	o.email = o.emailAddress;
}

function formatFriends(o){
	formatError(o);
	paging(o);
	if(o.values){
		o.data = o.values;
		for(var i=0;i<o.data.length;i++){
			formatUser(o.data[i]);
		}
		delete o.values;
	}
	return o;
}

function paging(res){
	if( "_count" in res && "_start" in res && (res._count + res._start) < res._total ){
		res['paging'] = {
			next : "?start="+(res._start+res._count)+"&count="+res._count
		};
	}
}

function empty(o,headers){
	if(JSON.stringify(o) === '{}'&&headers.statusCode === 200){
		o.success = true;
	}
}

hello.init({
	'linkedin' : {

		oauth : {
			version : 2,
			response_type : 'code',
			auth	: "https://www.linkedin.com/uas/oauth2/authorization",
			grant	: "https://www.linkedin.com/uas/oauth2/accessToken"
		},

		// Refresh the access_token once expired
		refresh : true,

		scope : {
			basic	: 'r_fullprofile',
			email	: 'r_emailaddress',
			friends : 'r_network',
			publish : 'rw_nus'
		},
		scope_delim : ' ',

		base	: "https://api.linkedin.com/v1/",

		get : {
			"me"			: 'people/~:(picture-url,first-name,last-name,id,formatted-name,email-address)',
			"me/friends"	: 'people/~/connections?count=@{limit|500}',
			"me/followers"	: 'people/~/connections?count=@{limit|500}',
			"me/following"	: 'people/~/connections?count=@{limit|500}',

			// http://developer.linkedin.com/documents/get-network-updates-and-statistics-api
			"me/share"		: "people/~/network/updates?count=@{limit|250}"
		},

		post : {

			// https://developer.linkedin.com/documents/api-requests-json
			"me/share"		: function(p, callback){
				var data =  {
					"visibility": {
						"code": "anyone"
					}
				};

				if(p.data.id){

					data["attribution"] = {
						"share": {
							"id": p.data.id
						}
					};

				}
				else{
					data["comment"] = p.data.message;
					data["content"] = {
						"submitted-url": p.data.link,
						"submitted-image-url": p.data.picture
					};
				}

				p.data = JSON.stringify(data);

				callback('people/~/shares?format=json');
			},

			"me/like" : like
		},

		del :{
			"me/like" : like
		},

		wrap : {
			me : function(o){
				formatError(o);
				formatUser(o);
				return o;
			},
			"me/friends" : formatFriends,
			"me/following" : formatFriends,
			"me/followers" : formatFriends,
			"me/share" : function(o){
				formatError(o);
				paging(o);
				if(o.values){
					o.data = o.values;
					delete o.values;
					for(var i=0;i<o.data.length;i++){
						var d = o.data[i];
						formatUser(d);
						d.message = d.headline;
					}
				}
				return o;
			},
			"default" : function(o,headers){
				formatError(o);
				empty(o,headers);
				paging(o);
			}
		},
		jsonp : function(p,qs){
			formatQuery(qs);
			if(p.method==='get'){
				qs.format = 'jsonp';
				qs['error-callback'] = p.callbackID;
			}
		},
		xhr : function(p,qs){
			if(p.method !== 'get'){
				formatQuery(qs);
				p.headers['Content-Type'] = 'application/json';
				// x-li-format ensures error responses are not returned in XML
				p.headers['x-li-format'] = 'json';
				p.proxy = true;
				return true;
			}
			return false;
		}
	}
});

function formatQuery(qs){
	// Linkedin signs requests with the parameter 'oauth2_access_token'... yeah anotherone who thinks they should be different!
	if(qs.access_token){
		qs.oauth2_access_token = qs.access_token;
		delete qs.access_token;
	}
}

function like(p, callback){
	p.headers["x-li-format"] = "json";
	var id = p.data.id;
	p.data = (p.method !== 'delete').toString();
	p.method = 'put';
	callback('people/~/network/updates/key=' + id + '/is-liked');
}

})(hello);
<|endoftext|>


<commit_before>import * as Element from '../helpers/element'
import Base from './base'
import Toggler from './toggler'
import Action from './action'
import Class from './class'

export default Base.extend({
	directive: 'selector',

	modules: {
		actions: Action,
		classes: Class,
		items: Toggler.extend({directive: 'item'})
	},

	defaults: {
		selected: 0,
		interval: 0,
		classSelected: 'is-selected'
	},

	events: {

		init: function()
		{
			const Module = this.constructor

			this.select(this.$settings.selected | 0, false)

			if(this.$settings.interval > 0)
			{
				this.play()
			}
			else
			{
				this.stop()
			}
		}
	},

	methods: {

		select: function(index, transition = true)
		{
			const oldSelected = this.selected
			const newSelected = index | 0

			if(oldSelected !== newSelected)
			{
				this.selected = newSelected

				for(let i = 0; i < this.$owns.items.length; i++)
				{
					let item = this.$owns.items[i]

					item.toggle(i === newSelected, transition)
					item.$element.classList.toggle(this.$settings.classSelected, i === newSelected)
				}

				this.trigger('change', {
					property: 'selected',
					oldValue: oldSelected,
					newValue: newSelected
				})
			}
		},

		go: function(count = 0, transition = true)
		{
			const total = this.$owns.items.length
			let selected = (this.selected + count) % total

			if(selected < 0)
			{
				selected += total
			}

			this.select(selected, transition)
		},

		next: function(transition = true)
		{
			this.go(1, transition)
		},

		previous: function(transition = true)
		{
			this.go(-1, transition)
		},

		play: function(interval = this.$settings.interval)
		{
			this._interval = setInterval(() => this.next(), interval | 0)
		},

		stop: function()
		{
			clearInterval(this._interval)
			this._interval = false
		},

		isSelected: function(index)
		{
			return this.selected === index
		},

		isFirst: function()
		{
			return this.isSelected(0)
		},

		isLast: function()
		{
			return this.isSelected(this.$owns.items.length - 1)
		},

		isPlaying: function()
		{
			return this._interval !== false
		}
	}
})
<commit_msg>Added change events when playing/stopping<commit_after>import * as Element from '../helpers/element'
import Base from './base'
import Toggler from './toggler'
import Action from './action'
import Class from './class'

export default Base.extend({
	directive: 'selector',

	modules: {
		actions: Action,
		classes: Class,
		items: Toggler.extend({directive: 'item'})
	},

	defaults: {
		selected: 0,
		interval: 0,
		classSelected: 'is-selected'
	},

	events: {

		init: function()
		{
			const Module = this.constructor

			this.select(this.$settings.selected | 0, false)

			if(this.$settings.interval > 0)
			{
				this.play()
			}
			else
			{
				this.stop()
			}
		}
	},

	methods: {

		select: function(index, transition = true)
		{
			const oldSelected = this.selected
			const newSelected = index | 0

			if(oldSelected !== newSelected)
			{
				this.selected = newSelected

				for(let i = 0; i < this.$owns.items.length; i++)
				{
					let item = this.$owns.items[i]

					item.toggle(i === newSelected, transition)
					item.$element.classList.toggle(this.$settings.classSelected, i === newSelected)
				}

				this.trigger('change', {
					property: 'selected',
					oldValue: oldSelected,
					newValue: newSelected
				})
			}
		},

		go: function(count = 0, transition = true)
		{
			const total = this.$owns.items.length
			let selected = (this.selected + count) % total

			if(selected < 0)
			{
				selected += total
			}

			this.select(selected, transition)
		},

		next: function(transition = true)
		{
			this.go(1, transition)
		},

		previous: function(transition = true)
		{
			this.go(-1, transition)
		},

		play: function(interval = this.$settings.interval)
		{
			this._interval = setInterval(() => this.next(), interval | 0)

			this.trigger('change', {
				property: 'interval',
				oldValue: false,
				newValue: true
			})
		},

		stop: function()
		{
			clearInterval(this._interval)
			this._interval = false

			this.trigger('change', {
				property: 'interval',
				oldValue: true,
				newValue: false
			})
		},

		isSelected: function(index)
		{
			return this.selected === index
		},

		isFirst: function()
		{
			return this.isSelected(0)
		},

		isLast: function()
		{
			return this.isSelected(this.$owns.items.length - 1)
		},

		isPlaying: function()
		{
			return this._interval !== false
		}
	}
})
<|endoftext|>


<commit_before>(function ($) {
    'use strict';

    $.extend(true, $.trumbowyg, {
        langs: {
            // jshint camelcase:false
            en: {
                fontsize: 'Font size',
                fontsizes: {
                    'x-small': 'Extra small',
                    'small': 'Small',
                    'medium': 'Regular',
                    'large': 'Large',
                    'x-large': 'Extra large',
                    'custom': 'Custom'
                }
            },
            fr: {
                fontsize: 'Taille de la police',
                fontsizes: {
                    'x-small': 'Très petit',
                    'small': 'Petit',
                    'medium': 'Normal',
                    'large': 'Grand',
                    'x-large': 'Très grand',
                    'custom': 'Douane'
                }
            },
            nl: {
                fontsize: 'Lettergrootte',
                fontsizes: {
                    'x-small': 'Extra klein',
                    'small': 'Klein',
                    'medium': 'Normaal',
                    'large': 'Groot',
                    'x-large': 'Extra groot',
                    'custom': 'Tilpasset'
                }
            },
            tr: {
                fontsize: 'Yazı Boyutu',
                fontsizes: {
                    'x-small': 'Çok Küçük',
                    'small': 'Küçük',
                    'medium': 'Normal',
                    'large': 'Büyük',
                    'x-large': 'Çok Büyük',
                    'custom': 'Görenek'
                }
            }
        }
    });
    // jshint camelcase:true

    // Add dropdown with font sizes
    $.extend(true, $.trumbowyg, {
        plugins: {
            fontsize: {
                init: function (trumbowyg) {
                    trumbowyg.addBtnDef('fontsize', {
                        dropdown: buildDropdown(trumbowyg)
                    });
                }
            }
        }
    });

    function buildDropdown(trumbowyg) {
        var dropdown = [];
        var sizes = ['x-small', 'small', 'medium', 'large', 'x-large'];

        $.each(sizes, function (index, size) {
            trumbowyg.addBtnDef('fontsize_' + size, {
                text: '' + trumbowyg.lang.fontsizes[size] + '',
                hasIcon: false,
                fn: function () {
                    trumbowyg.execCmd('fontSize', index + 1, true);
                }
            });
            dropdown.push('fontsize_' + size);
        });

        var freeSizeButtonName = 'fontsize_custom',
            freeSizeBtnDef = {
                fn: function () {
                    trumbowyg.openModalInsert('Custom Font Size',
                        {
                            size: {
                                label: 'Font Size',
                                value: '48px'
                            }
                        },
                        function (values) {
                            var text = trumbowyg.range.startContainer.parentElement;
                            var selectedText = trumbowyg.getRangeText();
                            if ($(text).html() === selectedText) {
                                $(text).css('font-size', values.size);
                            } else {
                                trumbowyg.range.deleteContents();
                                var html = '' + selectedText + '';
                                var node = $(html)[0];
                                trumbowyg.range.insertNode(node);
                            }
                            trumbowyg.saveRange();
                            return true;
                        }
                    );
                },
                text: '' + trumbowyg.lang.fontsizes.custom + '',
                hasIcon: false
            };
        trumbowyg.addBtnDef(freeSizeButtonName, freeSizeBtnDef);
        dropdown.push(freeSizeButtonName);

        return dropdown;
    }
})(jQuery);
<commit_msg>Add german translation<commit_after>(function ($) {
    'use strict';

    $.extend(true, $.trumbowyg, {
        langs: {
            // jshint camelcase:false
            en: {
                fontsize: 'Font size',
                fontsizes: {
                    'x-small': 'Extra small',
                    'small': 'Small',
                    'medium': 'Regular',
                    'large': 'Large',
                    'x-large': 'Extra large',
                    'custom': 'Custom'
                }
            },
            fr: {
                fontsize: 'Taille de la police',
                fontsizes: {
                    'x-small': 'Très petit',
                    'small': 'Petit',
                    'medium': 'Normal',
                    'large': 'Grand',
                    'x-large': 'Très grand',
                    'custom': 'Douane'
                }
            },
            de: {
                fontsize: 'Font size',
                fontsizes: {
                    'x-small': 'Sehr klein',
                    'small': 'Klein',
                    'medium': 'Normal',
                    'large': 'Groß',
                    'x-large': 'Sehr groß',
                    'custom': 'Benutzerdefiniert'
                }
            },
            nl: {
                fontsize: 'Lettergrootte',
                fontsizes: {
                    'x-small': 'Extra klein',
                    'small': 'Klein',
                    'medium': 'Normaal',
                    'large': 'Groot',
                    'x-large': 'Extra groot',
                    'custom': 'Tilpasset'
                }
            },
            tr: {
                fontsize: 'Yazı Boyutu',
                fontsizes: {
                    'x-small': 'Çok Küçük',
                    'small': 'Küçük',
                    'medium': 'Normal',
                    'large': 'Büyük',
                    'x-large': 'Çok Büyük',
                    'custom': 'Görenek'
                }
            }
        }
    });
    // jshint camelcase:true

    // Add dropdown with font sizes
    $.extend(true, $.trumbowyg, {
        plugins: {
            fontsize: {
                init: function (trumbowyg) {
                    trumbowyg.addBtnDef('fontsize', {
                        dropdown: buildDropdown(trumbowyg)
                    });
                }
            }
        }
    });

    function buildDropdown(trumbowyg) {
        var dropdown = [];
        var sizes = ['x-small', 'small', 'medium', 'large', 'x-large'];

        $.each(sizes, function (index, size) {
            trumbowyg.addBtnDef('fontsize_' + size, {
                text: '' + trumbowyg.lang.fontsizes[size] + '',
                hasIcon: false,
                fn: function () {
                    trumbowyg.execCmd('fontSize', index + 1, true);
                }
            });
            dropdown.push('fontsize_' + size);
        });

        var freeSizeButtonName = 'fontsize_custom',
            freeSizeBtnDef = {
                fn: function () {
                    trumbowyg.openModalInsert('Custom Font Size',
                        {
                            size: {
                                label: 'Font Size',
                                value: '48px'
                            }
                        },
                        function (values) {
                            var text = trumbowyg.range.startContainer.parentElement;
                            var selectedText = trumbowyg.getRangeText();
                            if ($(text).html() === selectedText) {
                                $(text).css('font-size', values.size);
                            } else {
                                trumbowyg.range.deleteContents();
                                var html = '' + selectedText + '';
                                var node = $(html)[0];
                                trumbowyg.range.insertNode(node);
                            }
                            trumbowyg.saveRange();
                            return true;
                        }
                    );
                },
                text: '' + trumbowyg.lang.fontsizes.custom + '',
                hasIcon: false
            };
        trumbowyg.addBtnDef(freeSizeButtonName, freeSizeBtnDef);
        dropdown.push(freeSizeButtonName);

        return dropdown;
    }
})(jQuery);
<|endoftext|>


<commit_before>/* Initialize VR ------------------------------------------------------------ */

var FriendVR = {
	// Declare some variables used in the functions
	canvas: null,
	scene: null,
	camera: null,
	crosshair: null,
	room: {},
	renderer: null,
	controls: null,
	raycaster: null,
	initialized: null,
	logo: null,
	rot: null,
	rooms: [],
	currentRoom: 0,
	zPhase: 0.0,
	intersected: null,

	// Initialize the engine
	init: function()
	{
		if( this.initialized ) return;

		var self = this;

		// Make sure we're ready!
		if( !document.body || document.body && !document.body.classList.contains( 'Inside' ) )
			return setTimeout( function(){ FriendVR.init() }, 5 );

		vrInitialized = true;

		if( WEBVR.isAvailable() === false )
		{
			var mess = WEBVR.getMessage();
			mess.style.zIndex = 2147483647;
			document.body.appendChild( mess );
		}

		// Setup the scene
		this.canvas = document.createElement( 'div' );
		document.body.appendChild( this.canvas );
		this.canvas.style.zIndex = 2147483646;

		this.scene = new THREE.Scene();
		this.camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 10 );
		this.scene.add( this.camera );

		// 3d crosshair that shows your where you are pointing
		this.crosshair = new THREE.Mesh(
			new THREE.RingGeometry( 0.02, 0.04, 32 ),
			new THREE.MeshBasicMaterial( {
				color: 0xffffff,
				opacity: 0.5,
				transparent: true
			} )
		);
		this.crosshair.position.z = - 2;
		this.camera.add( this.crosshair );

		// Set up the current room space itself
		this.room.mesh = new THREE.Mesh(
			new THREE.BoxGeometry( 6, 2, 6, 1, 1, 1 ),
			new THREE.MeshBasicMaterial( { color: 0x0B2640, side: THREE.DoubleSide } )
		);
		this.room.mesh.receiveShadow = true;
		this.scene.add( this.room.mesh );

		// Floor of room
		this.room.floorPlane = new THREE.Mesh(
			new THREE.PlaneGeometry( 6, 6, 1 ),
			new THREE.MeshBasicMaterial( { color: 0xffffff, side: THREE.DoubleSide } )
		);
		this.room.floorPlane.rotation.x = 90 / 180 * Math.PI;
		this.room.floorPlane.position.y = -0.7;
		this.room.floorPlane.receiveShadow = true;
		this.scene.add( this.room.floorPlane );

		// Ceiling of room
		this.room.ceilingPlane = new THREE.Mesh(
			new THREE.PlaneGeometry( 6, 6, 1 ),
			new THREE.MeshBasicMaterial( { color: 0x505050, side: THREE.DoubleSide } )
		);
		this.room.ceilingPlane.rotation.x = 90 / 180 * Math.PI;
		this.room.ceilingPlane.position.y = 0.7;
		this.scene.add( this.room.ceilingPlane );

		//vrScene.add( new THREE.HemisphereLight( 0x606060, 0x404040 ) );

		this.room.light = new THREE.DirectionalLight( 0xffffff );
		this.room.light.position.set( 1, 1, 1 ).normalize();
		this.room.light.castShadow = true;
		this.room.light.shadowDarkness = 0.7;
		this.room.light.shadowCameraVisible = true;
		this.scene.add( this.room.light );

		// Friend logo
		var l = new THREE.ObjectLoader();
		l.load( './art_original/FriendLogo.json', function( obj )
		{
			self.logo = obj;
			self.logo.scale.set( 0.2, 0.2, 0.2 );
			self.logo.position.x = 0;
			self.logo.position.y = 0.7;
			self.logo.position.z = -1;
			self.logo.rotation.x = 90 / 180 * Math.PI;
			self.logo.rotation.x = 90 / 180 * Math.PI;
			self.logo.castShadow = true;
			self.logo.receiveShadow = true;
			self.scene.add( self.logo );
		} );

		// Software packages
		var m = new Module( 'system' );
		m.onExecuted = function( e, d )
		{
			if( e != 'ok' ) return;
			var list = JSON.parse( d );
			var start = -0.9;
			var ypos = 0.3;
			var margin = 0.1;
			var count = 0;
			var row = 0;
			for( var a = 0; a < list.length; a++ )
			{
				var pln = new THREE.Mesh(
					new THREE.PlaneGeometry( 0.5, 0.5, 1 ),
					new THREE.MeshBasicMaterial( { color: 0xAD3524, side: THREE.DoubleSide } )
				);
				pln.position.x = start + ( count * ( 0.5 + margin ) );
				pln.position.y = ypos;
				pln.position.z = -2;
				pln.castShadow = true;
				pln.receiveShadow = true;
				self.scene.add( pln );
				if( count++ >= 3 )
				{
					count = 0;
					ypos -= 0.5 + margin;
					row++;
					if( row >= 2 )
					{
						break;
					}
				}
			}
		}
		m.execute( 'listuserapplications' );

		// Setup the rendering
		this.raycaster = new THREE.Raycaster();
		this.renderer = new THREE.WebGLRenderer( { antialias: true } );
		this.renderer.shadowMapType = THREE.PCFSoftShadowMap;
		this.renderer.setClearColor( 0x202050 );
		this.renderer.setPixelRatio( window.devicePixelRatio );
		this.renderer.setSize( window.innerWidth, window.innerHeight );
		this.renderer.sortObjects = false;
		this.canvas.appendChild( this.renderer.domElement );
		this.controls = new THREE.VRControls( this.camera );
		this.effect = new THREE.VREffect( this.renderer );

		WEBVR.getVRDisplay( function ( display )
		{
			var btn = WEBVR.getButton( display, self.renderer.domElement );
			btn.style.zIndex = 2147483647;
			document.body.appendChild( btn );
		} );

		// TODO: Reenable these later..
		/*vrRenderer.domElement.addEventListener( 'mousedown', onMouseDown, false );
		vrRenderer.domElement.addEventListener( 'mouseup', onMouseUp, false );
		vrRenderer.domElement.addEventListener( 'touchstart', onMouseDown, false );
		vrRenderer.domElement.addEventListener( 'touchend', onMouseUp, false );*/
		//window.addEventListener( 'resize', onWindowResize, false );

		// Set up the animation/rendering
		this.animate();
	},
	// Just setup how to animate / render
	animate: function()
	{
		FriendVR.effect.requestAnimationFrame( FriendVR.animate );
		FriendVR.render();
	},
	// Do the actual rendering
	render: function()
	{
		// Find intersections (collisions with camera)
		this.raycaster.setFromCamera( { x: 0, y: 0 }, this.camera );
		/*var intersects = vrRaycaster.intersectObjects( this.room.mesh.children );
		if( intersects.length > 0 )
		{
			if( INTERSECTED != intersects[ 0 ].object )
			{
				if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );

				INTERSECTED = intersects[ 0 ].object;
				INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
				INTERSECTED.material.emissive.setHex( 0x000000 );
			}

		}
		else
		{
			if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
			INTERSECTED = undefined;
		}*/

		// Rotate the logo
		if( this.logo ) this.logo.rotation.z = this.rot / 180 * Math.PI;
		this.rot += 0.5;

		// Update controls and render
		this.controls.update();
		this.effect.render( this.scene, this.camera );
	}
}

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

/* Initialize VR ------------------------------------------------------------ */

var FriendVR = {
	// Declare some variables used in the functions
	canvas: null,
	scene: null,
	camera: null,
	crosshair: null,
	room: {},
	renderer: null,
	controls: null,
	raycaster: null,
	initialized: null,
	logo: null,
	rot: null,
	rooms: [],
	currentRoom: 0,
	zPhase: 0.0,
	intersected: null,

	// Initialize the engine
	init: function()
	{
		if( this.initialized ) return;

		var self = this;

		// Make sure we're ready!
		if( !document.body || document.body && !document.body.classList.contains( 'Inside' ) )
			return setTimeout( function(){ FriendVR.init() }, 5 );

		vrInitialized = true;

		if( WEBVR.isAvailable() === false )
		{
			var mess = WEBVR.getMessage();
			mess.style.zIndex = 2147483647;
			document.body.appendChild( mess );
		}

		// Setup the scene
		this.canvas = document.createElement( 'div' );
		document.body.appendChild( this.canvas );
		this.canvas.style.zIndex = 2147483646;

		this.scene = new THREE.Scene();
		this.camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 10 );
		this.scene.add( this.camera );

		// 3d crosshair that shows your where you are pointing
		this.crosshair = new THREE.Mesh(
			new THREE.RingGeometry( 0.02, 0.04, 32 ),
			new THREE.MeshBasicMaterial( {
				color: 0xffffff,
				opacity: 0.5,
				transparent: true
			} )
		);
		this.crosshair.position.z = - 2;
		this.camera.add( this.crosshair );

		// Set up the current room space itself
		this.room.mesh = new THREE.Mesh(
			new THREE.BoxGeometry( 6, 2, 6, 1, 1, 1 ),
			new THREE.MeshBasicMaterial( { color: 0x0B2640, side: THREE.DoubleSide } )
		);
		this.room.mesh.receiveShadow = true;
		this.scene.add( this.room.mesh );

		// Floor of room
		this.room.floorPlane = new THREE.Mesh(
			new THREE.PlaneGeometry( 6, 6, 1 ),
			new THREE.MeshBasicMaterial( { color: 0xffffff, side: THREE.DoubleSide } )
		);
		this.room.floorPlane.rotation.x = 90 / 180 * Math.PI;
		this.room.floorPlane.position.y = -0.7;
		this.room.floorPlane.receiveShadow = true;
		this.scene.add( this.room.floorPlane );

		// Ceiling of room
		this.room.ceilingPlane = new THREE.Mesh(
			new THREE.PlaneGeometry( 6, 6, 1 ),
			new THREE.MeshBasicMaterial( { color: 0x505050, side: THREE.DoubleSide } )
		);
		this.room.ceilingPlane.rotation.x = 90 / 180 * Math.PI;
		this.room.ceilingPlane.position.y = 0.7;
		this.scene.add( this.room.ceilingPlane );

		//vrScene.add( new THREE.HemisphereLight( 0x606060, 0x404040 ) );

		this.room.light = new THREE.DirectionalLight( 0xffffff );
		this.room.light.position.set( 1, 1, 1 ).normalize();
		this.room.light.castShadow = true;
		this.room.light.shadowDarkness = 0.7;
		this.room.light.shadowCameraVisible = true;
		this.scene.add( this.room.light );

		// Friend logo
		var l = new THREE.ObjectLoader();
		l.load( './art_original/FriendLogo.json', function( obj )
		{
			self.logo = obj;
			self.logo.scale.set( 0.2, 0.2, 0.2 );
			self.logo.position.x = 0;
			self.logo.position.y = 0.7;
			self.logo.position.z = -1;
			self.logo.rotation.x = 90 / 180 * Math.PI;
			self.logo.rotation.x = 90 / 180 * Math.PI;
			self.logo.castShadow = true;
			self.logo.receiveShadow = true;
			self.scene.add( self.logo );
		} );

		// Software packages
		var m = new Module( 'system' );
		m.onExecuted = function( e, d )
		{
			if( e != 'ok' ) return;
			var list = JSON.parse( d );
			var start = -0.9;
			var ypos = 0.3;
			var margin = 0.1;
			var count = 0;
			var row = 0;
			for( var a = 0; a < list.length; a++ )
			{
				var pln = new THREE.Mesh(
					new THREE.PlaneGeometry( 0.5, 0.5, 1 ),
					new THREE.MeshBasicMaterial( { color: 0xAD3524, side: THREE.DoubleSide } )
				);
				pln.position.x = start + ( count * ( 0.5 + margin ) );
				pln.position.y = ypos;
				pln.position.z = -2;
				pln.castShadow = true;
				pln.receiveShadow = true;
				self.scene.add( pln );
				if( count++ >= 3 )
				{
					count = 0;
					ypos -= 0.5 + margin;
					row++;
					if( row >= 2 )
					{
						break;
					}
				}
			}
		}
		m.execute( 'listuserapplications' );

		// Setup the rendering
		this.raycaster = new THREE.Raycaster();
		this.renderer = new THREE.WebGLRenderer( { antialias: true } );
		this.renderer.shadowMapType = THREE.PCFSoftShadowMap;
		this.renderer.setClearColor( 0x202050 );
		this.renderer.setPixelRatio( window.devicePixelRatio );
		this.renderer.setSize( window.innerWidth, window.innerHeight );
		this.renderer.sortObjects = false;
		this.canvas.appendChild( this.renderer.domElement );
		this.controls = new THREE.VRControls( this.camera );
		this.effect = new THREE.VREffect( this.renderer );

		WEBVR.getVRDisplay( function ( display )
		{
			var btn = WEBVR.getButton( display, self.renderer.domElement );
			btn.style.zIndex = 2147483647;
			document.body.appendChild( btn );
		} );

		// TODO: Reenable these later..
		/*vrRenderer.domElement.addEventListener( 'mousedown', onMouseDown, false );
		vrRenderer.domElement.addEventListener( 'mouseup', onMouseUp, false );
		vrRenderer.domElement.addEventListener( 'touchstart', onMouseDown, false );
		vrRenderer.domElement.addEventListener( 'touchend', onMouseUp, false );*/
		//window.addEventListener( 'resize', onWindowResize, false );

		// Set up the animation/rendering
		this.animate();
	},
	// Just setup how to animate / render
	animate: function()
	{
		FriendVR.effect.requestAnimationFrame( FriendVR.animate );
		FriendVR.render();
	},
	// Do the actual rendering
	render: function()
	{
		// Find intersections (collisions with camera)
		this.raycaster.setFromCamera( { x: 0, y: 0 }, this.camera );
		/*var intersects = vrRaycaster.intersectObjects( this.room.mesh.children );
		if( intersects.length > 0 )
		{
			if( INTERSECTED != intersects[ 0 ].object )
			{
				if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );

				INTERSECTED = intersects[ 0 ].object;
				INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
				INTERSECTED.material.emissive.setHex( 0x000000 );
			}

		}
		else
		{
			if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
			INTERSECTED = undefined;
		}*/

		// Rotate the logo
		if( this.logo ) this.logo.rotation.z = this.rot / 180 * Math.PI;
		this.rot += 0.5;

		// Update controls and render
		this.controls.update();
		this.effect.render( this.scene, this.camera );
	}
}

<|endoftext|>


<commit_before><commit_msg>jQuery v1.8.2.<commit_after><|endoftext|>


<commit_before>/**
 * Copyright 2017 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import {StateChangeType} from './navigation-state';

/**
 * @typedef {!Object<string, *>}
 */
export let StoryVariableDef;

/** @enum {string} */
const Variable = {
  STORY_PAGE_ID: 'storyPageId',
  STORY_PAGE_INDEX: 'storyPageIndex',
  STORY_PAGE_COUNT: 'storyPageCount',
  STORY_IS_MUTED: 'storyIsMuted',
  STORY_PROGRESS: 'storyProgress',
};

/**
 * Variable service for amp-story.
 * Used for URL replacement service. See usage in src/url-replacements-impl.
 */
export class AmpStoryVariableService {
  constructor() {
    /** @private {!StoryVariableDef} */
    this.variables_ = {
      [Variable.STORY_PAGE_INDEX]: null,
      [Variable.STORY_PAGE_ID]: null,
      [Variable.STORY_PAGE_COUNT]: null,
      [Variable.STORY_PROGRESS]: null,
      [Variable.STORY_IS_MUTED]: null,
    };

    /** @private {boolean} */
    this.isInitialized_ = false;
  }

  /**
   * @param {!./navigation-state.StateChangeEventDef} stateChangeEvent
   */
  onNavigationStateChange(stateChangeEvent) {
    switch (stateChangeEvent.type) {
      case StateChangeType.ACTIVE_PAGE:
        const {pageIndex, pageId, storyProgress, totalPages} =
            stateChangeEvent.value;
        this.variables_[Variable.STORY_PAGE_INDEX] = pageIndex;
        this.variables_[Variable.STORY_PAGE_ID] = pageId;
        this.variables_[Variable.STORY_PROGRESS] = storyProgress;
        this.variables_[Variable.STORY_PAGE_COUNT] = totalPages;
        break;
    }
  }

  /**
   * @param {boolean} isMuted
   */
  onMutedStateChange(isMuted) {
    this.variables_[Variable.STORY_IS_MUTED] = isMuted;
  }

  /**
   * @return {!StoryVariableDef}
   */
  get() {
    // TODO(newmius): You should probably Object.freeze this in development.
    return this.variables_;
  }
}
<commit_msg>Cleanup AmpStoryVariableService private field (#14810)<commit_after>/**
 * Copyright 2017 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import {StateChangeType} from './navigation-state';

/**
 * @typedef {!Object<string, *>}
 */
export let StoryVariableDef;

/** @enum {string} */
const Variable = {
  STORY_PAGE_ID: 'storyPageId',
  STORY_PAGE_INDEX: 'storyPageIndex',
  STORY_PAGE_COUNT: 'storyPageCount',
  STORY_IS_MUTED: 'storyIsMuted',
  STORY_PROGRESS: 'storyProgress',
};

/**
 * Variable service for amp-story.
 * Used for URL replacement service. See usage in src/url-replacements-impl.
 */
export class AmpStoryVariableService {
  constructor() {
    /** @private {!StoryVariableDef} */
    this.variables_ = {
      [Variable.STORY_PAGE_INDEX]: null,
      [Variable.STORY_PAGE_ID]: null,
      [Variable.STORY_PAGE_COUNT]: null,
      [Variable.STORY_PROGRESS]: null,
      [Variable.STORY_IS_MUTED]: null,
    };
  }

  /**
   * @param {!./navigation-state.StateChangeEventDef} stateChangeEvent
   */
  onNavigationStateChange(stateChangeEvent) {
    switch (stateChangeEvent.type) {
      case StateChangeType.ACTIVE_PAGE:
        const {pageIndex, pageId, storyProgress, totalPages} =
            stateChangeEvent.value;
        this.variables_[Variable.STORY_PAGE_INDEX] = pageIndex;
        this.variables_[Variable.STORY_PAGE_ID] = pageId;
        this.variables_[Variable.STORY_PROGRESS] = storyProgress;
        this.variables_[Variable.STORY_PAGE_COUNT] = totalPages;
        break;
    }
  }

  /**
   * @param {boolean} isMuted
   */
  onMutedStateChange(isMuted) {
    this.variables_[Variable.STORY_IS_MUTED] = isMuted;
  }

  /**
   * @return {!StoryVariableDef}
   */
  get() {
    // TODO(newmius): You should probably Object.freeze this in development.
    return this.variables_;
  }
}
<|endoftext|>


<commit_before>var Bro = require("brototype"),
    intersperse = require("intersperse"),
    q = require("q");

var Table = function (table_name, connection_method) {
    var _self = this,
        deferred = q.defer(),
        mysql = connection_method.mysql,
        config = connection_method.config;

    _self.Query_Promise = function () {
        this.commafied_keys = function (data_to_commafy) {
            if (typeof data_to_commafy !== 'object') {
                throw Error("ARGUMENT_MUST_BE_AN_OBJECT");
            } else if (Bro(data_to_commafy).giveMeProps().length === 0) {
                throw Error("ARGUMENT_CANNOT_BE_EMPTY");
            }

            // Could this operation be performed more functionally?
            var keys = Bro(data_to_commafy).giveMeProps(),
                commafied_keys = intersperse(keys, ', '),
                output_string = "";

            for (var iter = 0; iter < commafied_keys.length; iter ++) {
                output_string = output_string + commafied_keys[iter];
            }

            return output_string;
        };

        this.equalized_keyvals = function(data_to_equalize) {
            if (typeof data_to_equalize !== 'object') {
                throw Error("ARGUMENT_MUST_BE_AN_OBJECT");
            } else if (Bro(data_to_equalize).giveMeProps().length === 0) {
                throw Error("ARGUMENT_CANNOT_BE_EMPTY");
            }
        };

        return this;
    };

    var table_description_connection = mysql.createConnection(config);
    table_description_connection.query(("DESCRIBE " + table_name), function (err, rows, fields) {
        if (err) {
            table_description_connection.end();
            deferred.reject(Bro(_self).comeAtMe({
                err: err
            }));
        } else {
            _self.data_structure = {};
            rows.map(function (row) {
                _self.data_structure[row.Field] = {
                    Type: row.Type,
                    Null: row.Null,
                    Key: row.Key,
                    Default: row.Default,
                    Extra: row.Extra
                };
            });

            table_description_connection.end();
            deferred.resolve(_self);
        }
    });

    return deferred.promise;
};

module.exports = Table;<commit_msg>Implements mysql-crud-Table.Query_Promise().equalized_keyvals()<commit_after>var Bro = require("brototype"),
    intersperse = require("intersperse"),
    q = require("q");

var Table = function (table_name, connection_method) {
    var _self = this,
        deferred = q.defer(),
        mysql = connection_method.mysql,
        config = connection_method.config;

    _self.Query_Promise = function () {
        this.commafied_keys = function (data_to_commafy) {
            if (typeof data_to_commafy !== 'object') {
                throw Error("ARGUMENT_MUST_BE_AN_OBJECT");
            } else if (Bro(data_to_commafy).giveMeProps().length === 0) {
                throw Error("ARGUMENT_CANNOT_BE_EMPTY");
            }

            // Could this operation be performed more functionally?
            var keys = Bro(data_to_commafy).giveMeProps(),
                commafied_keys = intersperse(keys, ', '),
                output_string = "";

            for (var iter = 0; iter < commafied_keys.length; iter ++) {
                output_string = output_string + commafied_keys[iter];
            }

            return output_string;
        };

        this.equalized_keyvals = function(data_to_equalize) {
            if (typeof data_to_equalize !== 'object') {
                throw Error("ARGUMENT_MUST_BE_AN_OBJECT");
            } else if (Bro(data_to_equalize).giveMeProps().length === 0) {
                throw Error("ARGUMENT_CANNOT_BE_EMPTY");
            }

            var keys = Bro(data_to_equalize).giveMeProps(),
                output_string = keys[0] + "=" + data_to_equalize[keys[0]];

            for (var iter = 1; iter < keys.length; iter ++) {
                output_string = output_string + ", " + keys[iter] + "=" + data_to_equalize[keys[iter]];
            }

            return output_string;
        };

        return this;
    };

    var table_description_connection = mysql.createConnection(config);
    table_description_connection.query(("DESCRIBE " + table_name), function (err, rows, fields) {
        if (err) {
            table_description_connection.end();
            deferred.reject(Bro(_self).comeAtMe({
                err: err
            }));
        } else {
            _self.data_structure = {};
            rows.map(function (row) {
                _self.data_structure[row.Field] = {
                    Type: row.Type,
                    Null: row.Null,
                    Key: row.Key,
                    Default: row.Default,
                    Extra: row.Extra
                };
            });

            table_description_connection.end();
            deferred.resolve(_self);
        }
    });

    return deferred.promise;
};

module.exports = Table;<|endoftext|>


<commit_before>var _ = require('lodash');

/**
 * Constructs a new MySQL model, i.e. a class representing a table.
 * @param {Database} db a mysql database instance.
 * @param {String} table the name of the table on database.
 * @constructor
 */
function Model(db, table) {
  this.db = db;
  this.table = table;
}

/**
 * Parses the given selector and returns a parameterized where clause.
 * @param {Boolean|Number|String|Date|Object|Array} selector the selector.
 * @returns {Object} with two properties: "sql" and "params".
 * @private
 */
Model.prototype._parseSelector = function (selector) {
  var self = this, sql, params;

  if (_.isArray(selector)) {
    sql = [];
    params = [];

    selector.forEach(function (e) {
      var result = self._parseSelector(e);

      sql.push(result.sql);
      params.push.apply(params, result.params);
    });

    return {sql: sql.join(' OR '), params: params};

  } else if (_.isPlainObject(selector)) {
    sql = [];
    params = [];

    _.forOwn(selector, function (v, k) {
      sql.push('`' + k + '` = ?');
      params.push(v);
    });

    return {sql: sql.join(' AND '), params: params};

  } else { // boolean, number, string, date
    sql = '`id` = ?';
    params = [selector];

    return {sql: sql, params: params};
  }
};

/**
 * Retrieves the designated record(s) from database.
 * @param {Boolean|Number|String|Date|Object|Array} selector a selector to match the record(s) in database.
 * @param {Function} callback a callback function i.e. function(error, data).
 */
Model.prototype.get = function (selector, callback) {
  var sql, params, result;

  if (typeof selector === 'function') {
    callback = selector;
    selector = null;
  }

  sql = 'SELECT * FROM ??';
  params = [this.table];

  if (selector) {
    result = this._parseSelector(selector);

    if (! _.isEmpty(result.sql)) {
      sql += ' WHERE ' + result.sql;
      params.push.apply(params, result.params);
    }
  }

  sql += ';';

  this.db.query(sql, params, callback);
};

/**
 * Counts the designated record(s) in database.
 * @param {Boolean|Number|String|Date|Object|Array} [selector] a selector to match the record(s) in database.
 * @param {Function} callback a callback function i.e. function(error, data).
 */
Model.prototype.count = function (selector, callback) {
  var sql, params, result;

  if (typeof selector === 'function') {
    callback = selector;
    selector = null;
  }

  sql = 'SELECT COUNT(*) AS `count` FROM ??';
  params = [this.table];

  if (selector) {
    result = this._parseSelector(selector);

    if (! _.isEmpty(result.sql)) {
      sql += ' WHERE ' + result.sql;
      params.push.apply(params, result.params);
    }
  }

  sql += ';';

  this.db.query(sql, params, function (error, records) {
    var count;

    if (error) return callback(error);
    count = records[0].count;

    callback(null, count);
  });
};

/**
 * Creates or updates the specified record in database.
 * @param {Object} properties the record's properties to be set in the database.
 * @param {Function} callback a callback function i.e. function(error, data).
 */
Model.prototype.set = function (properties, callback) {
  var sql, params;

  sql = 'INSERT INTO ?? SET ?';
  params = [this.table, properties];

  sql += ' ON DUPLICATE KEY UPDATE ' +
    _.without(Object.getOwnPropertyNames(properties), 'id')
    .map(function (k) {
      params.push(k, k);
      return '?? = VALUES(??)';
    })
    .join(', ');

  sql += ';';

  this.db.query(sql, params, callback);
};

/**
 * Deletes the designated record(s) from database.
 * @param {Boolean|Number|String|Date|Object|Array} selector a selector to match the record(s) in database.
 * @param {Function} callback a callback function i.e. function(error, data).
 */
Model.prototype.del = function (selector, callback) {
  var sql, params, result;

  sql = 'DELETE FROM ??';
  params = [this.table];

  result = this._parseSelector(selector);
  if (! _.isEmpty(result.sql)) {
    sql += ' WHERE ' + result.sql;
    params.push.apply(params, result.params);
  }

  sql += ';';

  this.db.query(sql, params, callback);
};

module.exports = Model;
<commit_msg>Renamed internal "Model" var to "Collection".<commit_after>var _ = require('lodash');

/**
 * Constructs a new MySQL collection, i.e. a class representing the data of a table.
 * @param {Database} db a mysql database instance.
 * @param {String} table the name of the table on database.
 * @constructor
 */
function Collection(db, table) {
  this.db = db;
  this.table = table;
}

/**
 * Parses the given selector and returns a parameterized where clause.
 * @param {Boolean|Number|String|Date|Object|Array} selector the selector.
 * @returns {Object} with two properties: "sql" and "params".
 * @private
 */
Collection.prototype._parseSelector = function (selector) {
  var self = this, sql, params;

  if (_.isArray(selector)) {
    sql = [];
    params = [];

    selector.forEach(function (e) {
      var result = self._parseSelector(e);

      sql.push(result.sql);
      params.push.apply(params, result.params);
    });

    return {sql: sql.join(' OR '), params: params};

  } else if (_.isPlainObject(selector)) {
    sql = [];
    params = [];

    _.forOwn(selector, function (v, k) {
      sql.push('`' + k + '` = ?');
      params.push(v);
    });

    return {sql: sql.join(' AND '), params: params};

  } else { // boolean, number, string, date
    sql = '`id` = ?';
    params = [selector];

    return {sql: sql, params: params};
  }
};

/**
 * Retrieves the designated record(s) from database.
 * @param {Boolean|Number|String|Date|Object|Array} selector a selector to match the record(s) in database.
 * @param {Function} callback a callback function i.e. function(error, data).
 */
Collection.prototype.get = function (selector, callback) {
  var sql, params, result;

  if (typeof selector === 'function') {
    callback = selector;
    selector = null;
  }

  sql = 'SELECT * FROM ??';
  params = [this.table];

  if (selector) {
    result = this._parseSelector(selector);

    if (! _.isEmpty(result.sql)) {
      sql += ' WHERE ' + result.sql;
      params.push.apply(params, result.params);
    }
  }

  sql += ';';

  this.db.query(sql, params, callback);
};

/**
 * Counts the designated record(s) in database.
 * @param {Boolean|Number|String|Date|Object|Array} [selector] a selector to match the record(s) in database.
 * @param {Function} callback a callback function i.e. function(error, data).
 */
Collection.prototype.count = function (selector, callback) {
  var sql, params, result;

  if (typeof selector === 'function') {
    callback = selector;
    selector = null;
  }

  sql = 'SELECT COUNT(*) AS `count` FROM ??';
  params = [this.table];

  if (selector) {
    result = this._parseSelector(selector);

    if (! _.isEmpty(result.sql)) {
      sql += ' WHERE ' + result.sql;
      params.push.apply(params, result.params);
    }
  }

  sql += ';';

  this.db.query(sql, params, function (error, records) {
    var count;

    if (error) return callback(error);
    count = records[0].count;

    callback(null, count);
  });
};

/**
 * Creates or updates the specified record in database.
 * @param {Object} properties the record's properties to be set in the database.
 * @param {Function} callback a callback function i.e. function(error, data).
 */
Collection.prototype.set = function (properties, callback) {
  var sql, params;

  sql = 'INSERT INTO ?? SET ?';
  params = [this.table, properties];

  sql += ' ON DUPLICATE KEY UPDATE ' +
    _.without(Object.getOwnPropertyNames(properties), 'id')
    .map(function (k) {
      return '`' + k + '` = VALUES(`' + k + '`)';
    })
    .join(', ');

  sql += ';';

  this.db.query(sql, params, callback);
};

/**
 * Deletes the designated record(s) from database.
 * @param {Boolean|Number|String|Date|Object|Array} selector a selector to match the record(s) in database.
 * @param {Function} callback a callback function i.e. function(error, data).
 */
Collection.prototype.del = function (selector, callback) {
  var sql, params, result;

  sql = 'DELETE FROM ??';
  params = [this.table];

  result = this._parseSelector(selector);
  if (! _.isEmpty(result.sql)) {
    sql += ' WHERE ' + result.sql;
    params.push.apply(params, result.params);
  }

  sql += ';';

  this.db.query(sql, params, callback);
};

module.exports = Collection;
<|endoftext|>


<commit_before>'use strict';

const Joi = require('joi');
const moment = require('moment');

const Message = require('./Message');

class CustomerIoIdentifyMessage extends Message {

  constructor(...args) {
    super(...args);
    // Data validation rules.
    // TODO: move to helpers.
    const whenNullOrEmpty = Joi.valid(['', null]);
    const optionalStringDefaultsToUndefined = Joi
      .string()
      .empty(whenNullOrEmpty)
      .default(undefined);

    const optionalTimestampDefaultsToUndefined = Joi
      .date()
      .timestamp('unix')
      .raw()
      .empty(whenNullOrEmpty)
      .default(undefined);

    this.schema = Joi.object().keys({
      id: Joi.string().required().regex(/^[0-9a-f]{24}$/, 'valid object id'),
      data: Joi.object().keys({
        // Remove field when provided as empty string or null.
        email: Joi.string().empty(whenNullOrEmpty).default(undefined),
        phone: Joi.string().empty(whenNullOrEmpty).default(undefined),

        // Required:
        updated_at: Joi.date().timestamp('unix').raw().required(),
        created_at: Joi.date().timestamp('unix').raw().required(),

        mobile_status: Joi.valid([
          'active',
          'undeliverable',
          'unknown',
          null,
        ]).default(undefined),

        // Optional, defaults to null when provided as empty string or null.
        last_authenticated_at: optionalTimestampDefaultsToUndefined,
        birthdate: optionalTimestampDefaultsToUndefined,
        first_name: optionalStringDefaultsToUndefined,
        last_name: optionalStringDefaultsToUndefined,
        addr_city: optionalStringDefaultsToUndefined,
        addr_state: optionalStringDefaultsToUndefined,
        addr_zip: optionalStringDefaultsToUndefined,
        source: optionalStringDefaultsToUndefined,
        source_detail: optionalStringDefaultsToUndefined,
        language: optionalStringDefaultsToUndefined,
        country: optionalStringDefaultsToUndefined,

              // Allow anything as a role, but default to user.
        role: Joi.string().empty(whenNullOrEmpty).default('user'),

        // When interests not present, make them an empty array.
        interests: Joi.array().items(Joi.string()).empty(null).default(undefined),

        // TODO: add cio specific fields, like unsubscribe
      })
      .or('email', 'phone'),
  })
  // Require presence at least one of: keyword, args, mms_image_url.
  }

  static fromUser(userMessage) {
    const user = userMessage.payload.data;
    // Copy user fields.
    const customerData = Object.assign({}, user);
    // Remove id
    delete customerData.id;

    // Rename mobilecommon_status to mobile_status
    if (customerData.mobilecommon_status) {
      const mobile_status = customerData.mobilecommon_status;
      delete customerData.mobilecommon_status;
      customerData.mobile_status = mobile_status;
    }

    // Rename mobile to phone
    // TODO: format phone
    if (customerData.mobile) {
      const mobile = customerData.mobile;
      delete customerData.mobile;
      customerData.phone = mobile;
    }

    if (customerData.created_at) {
      customerData.created_at = moment(customerData.created_at, moment.ISO_8601).unix();
    }

    if (customerData.updated_at) {
      customerData.updated_at = moment(customerData.updated_at, moment.ISO_8601).unix();
    }

    if (customerData.last_authenticated_at) {
      customerData.last_authenticated_at = moment(
        customerData.last_authenticated_at,
        moment.ISO_8601
      ).unix();
    }

    if (customerData.birthdate) {
      customerData.birthdate = moment(
        `${customerData.birthdate}T00:00:00Z`,
        moment.ISO_8601
      ).unix();
    }

    // TODO: Transform timestamps

    const customerIoIdentifyMessage = new CustomerIoIdentifyMessage({
      data: {
        id: user.id,
        data: customerData,
      },
      meta: {
        request_id: userMessage.payload.meta.request_id,
      },
    });
    return customerIoIdentifyMessage;
  }

}

module.exports = CustomerIoIdentifyMessage;
<commit_msg>Exclude phone number untill it's formatted<commit_after>'use strict';

const Joi = require('joi');
const moment = require('moment');

const Message = require('./Message');

class CustomerIoIdentifyMessage extends Message {

  constructor(...args) {
    super(...args);
    // Data validation rules.
    // TODO: move to helpers.
    const whenNullOrEmpty = Joi.valid(['', null]);
    const optionalStringDefaultsToUndefined = Joi
      .string()
      .empty(whenNullOrEmpty)
      .default(undefined);

    const optionalTimestampDefaultsToUndefined = Joi
      .date()
      .timestamp('unix')
      .raw()
      .empty(whenNullOrEmpty)
      .default(undefined);

    this.schema = Joi.object().keys({
      id: Joi.string().required().regex(/^[0-9a-f]{24}$/, 'valid object id'),
      data: Joi.object().keys({
        // Remove field when provided as empty string or null.
        email: Joi.string().empty(whenNullOrEmpty).default(undefined),

        // TODO: make sure has E.164 format
        // phone: Joi.string().empty(whenNullOrEmpty).default(undefined),

        // Required:
        updated_at: Joi.date().timestamp('unix').raw().required(),
        created_at: Joi.date().timestamp('unix').raw().required(),

        mobile_status: Joi.valid([
          'active',
          'undeliverable',
          'unknown',
          null,
        ]).default(undefined),

        // Optional, defaults to null when provided as empty string or null.
        last_authenticated_at: optionalTimestampDefaultsToUndefined,
        birthdate: optionalTimestampDefaultsToUndefined,
        first_name: optionalStringDefaultsToUndefined,
        last_name: optionalStringDefaultsToUndefined,
        addr_city: optionalStringDefaultsToUndefined,
        addr_state: optionalStringDefaultsToUndefined,
        addr_zip: optionalStringDefaultsToUndefined,
        source: optionalStringDefaultsToUndefined,
        source_detail: optionalStringDefaultsToUndefined,
        language: optionalStringDefaultsToUndefined,
        country: optionalStringDefaultsToUndefined,

              // Allow anything as a role, but default to user.
        role: Joi.string().empty(whenNullOrEmpty).default('user'),

        // When interests not present, make them an empty array.
        interests: Joi.array().items(Joi.string()).empty(null).default(undefined),

        // TODO: add cio specific fields, like unsubscribe
      }),
      // TODO: Bring back when phone is formatted in Northstar
      // .or('email', 'phone'),
  })
  // Require presence at least one of: keyword, args, mms_image_url.
  }

  static fromUser(userMessage) {
    const user = userMessage.payload.data;
    // Copy user fields.
    const customerData = Object.assign({}, user);
    // Remove id
    delete customerData.id;

    // Rename mobilecommon_status to mobile_status
    if (customerData.mobilecommon_status) {
      const mobile_status = customerData.mobilecommon_status;
      delete customerData.mobilecommon_status;
      customerData.mobile_status = mobile_status;
    }

    // Rename mobile to phone
    // TODO: format phone

    if (customerData.mobile) {
      const mobile = customerData.mobile;
      delete customerData.mobile;
      // TODO: Bring back when phone is formatted in Northstar
      // customerData.phone = mobile;
    }

    if (customerData.created_at) {
      customerData.created_at = moment(customerData.created_at, moment.ISO_8601).unix();
    }

    if (customerData.updated_at) {
      customerData.updated_at = moment(customerData.updated_at, moment.ISO_8601).unix();
    }

    if (customerData.last_authenticated_at) {
      customerData.last_authenticated_at = moment(
        customerData.last_authenticated_at,
        moment.ISO_8601
      ).unix();
    }

    if (customerData.birthdate) {
      customerData.birthdate = moment(
        `${customerData.birthdate}T00:00:00Z`,
        moment.ISO_8601
      ).unix();
    }

    // TODO: Transform timestamps

    const customerIoIdentifyMessage = new CustomerIoIdentifyMessage({
      data: {
        id: user.id,
        data: customerData,
      },
      meta: {
        request_id: userMessage.payload.meta.request_id,
      },
    });
    return customerIoIdentifyMessage;
  }

}

module.exports = CustomerIoIdentifyMessage;
<|endoftext|>


<commit_before>import createPotionFromTemplate from '../ajax/createPotionFromTemplate';
import {def_needToCompose} from '../support/constants';
import getRandomInt from '../system/getRandomInt';
import {imageServer} from '../system/system';
import partial from '../common/partial';
import {publish} from '../support/pubsub';
import setValue from '../system/setValue';

function randomBackgroundImage() {
  return 'url(' + imageServer + '/composing/potions/' +
    getRandomInt(1, 11) + '_' + getRandomInt(1, 51) + '.gif)';
}

function updateInfoDiv(infoDiv, potName) {
  infoDiv.children[0].innerHTML = '';
  infoDiv.children[0].classList.add('fshPot');
  infoDiv.children[0].style.backgroundImage = randomBackgroundImage();
  infoDiv.children[2].innerHTML = 'Creating \'' +
    potName + '\' Potion';
  infoDiv.children[3].innerHTML = '';
}

function amILast() {
  var openTemplates = document.querySelectorAll(
    '[id|="composing-template"]:not(#composing-template-multi)');
  if (openTemplates.length === 0) {
    setValue(def_needToCompose, false);
  }
}

function createSuccess(temp, textStatus) {
  var myParent = temp.parentNode;
  myParent.innerHTML = '
' + textStatus + '
';
  updateInfoDiv(myParent.previousElementSibling.previousElementSibling,
    temp[temp.selectedIndex].text);
  amILast();
}

function potionDone(temp, data, textStatus) {
  if (data.error) {
    temp.parentNode.innerHTML = '
' +
      data.error + '
';
  } else {
    createSuccess(temp, textStatus);
  }
}

function createPotion(temp) { // jQuery.min
  createPotionFromTemplate(temp.value).done(partial(potionDone, temp));
  // setTimeout(partial(potionDone, temp, {}, 'faked'), 200);
}

export default function backgroundCreate(self, temp) {
  if (!(temp instanceof Node)) {return;}
  self.innerHTML = '';
  self.classList.add('fshSpinner', 'fshSpinner12', 'fshComposingSpinner');
  createPotion(temp);
  publish('quickcreate');
}
<commit_msg>move guard<commit_after>import createPotionFromTemplate from '../ajax/createPotionFromTemplate';
import {def_needToCompose} from '../support/constants';
import getRandomInt from '../system/getRandomInt';
import {imageServer} from '../system/system';
import partial from '../common/partial';
import {publish} from '../support/pubsub';
import setValue from '../system/setValue';

function randomBackgroundImage() {
  return 'url(' + imageServer + '/composing/potions/' +
    getRandomInt(1, 11) + '_' + getRandomInt(1, 51) + '.gif)';
}

function updateInfoDiv(infoDiv, potName) {
  infoDiv.children[0].innerHTML = '';
  infoDiv.children[0].classList.add('fshPot');
  infoDiv.children[0].style.backgroundImage = randomBackgroundImage();
  infoDiv.children[2].innerHTML = 'Creating \'' +
    potName + '\' Potion';
  infoDiv.children[3].innerHTML = '';
}

function amILast() {
  var openTemplates = document.querySelectorAll(
    '[id|="composing-template"]:not(#composing-template-multi)');
  if (openTemplates.length === 0) {
    setValue(def_needToCompose, false);
  }
}

function createSuccess(temp, textStatus) {
  var myParent = temp.parentNode;
  myParent.innerHTML = '
' + textStatus + '
';
  updateInfoDiv(myParent.previousElementSibling.previousElementSibling,
    temp[temp.selectedIndex].text);
  amILast();
}

function potionDone(temp, data, textStatus) {
  if (!(temp instanceof Node)) {return;}
  if (data.error) {
    temp.parentNode.innerHTML = '
' +
      data.error + '
';
  } else {
    createSuccess(temp, textStatus);
  }
}

function createPotion(temp) { // jQuery.min
  createPotionFromTemplate(temp.value).done(partial(potionDone, temp));
  // setTimeout(partial(potionDone, temp, {}, 'faked'), 200);
}

export default function backgroundCreate(self, temp) {
  self.innerHTML = '';
  self.classList.add('fshSpinner', 'fshSpinner12', 'fshComposingSpinner');
  createPotion(temp);
  publish('quickcreate');
}
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import R from 'ramda';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { Field, formValueSelector, reduxForm } from 'redux-form';

import block from '../../../helpers/bem-cn';
import transformFormValues from '../../../helpers/transformFormValues';

import Section from '../../Layout/Section/Section';
import Title from '../../Layout/Title/Title';
import Row from '../../Layout/Row/Row';
import Input from '../../inputs/Input';
import Radio from '../../inputs/Radio/Radio';
import Label from '../../labels/Label';
import Hint from '../../labels/Hint/Hint';
import MultiSelect from '../../selects/MultiSelect/MultiSelect';
import Button from '../../buttons/Button';
import Icon from '../../Icon/Icon';

import RenderPlugins from '../../forms/plugins/RenderPlugins';

const b = block('j-api-form');

const propTypes = {
    api: PropTypes.object.isRequired,
    apiSchema: PropTypes.object.isRequired,
    excludePlugin: PropTypes.func.isRequired,
    handleDelete: PropTypes.func.isRequired,
    handleSubmit: PropTypes.func.isRequired,
    initialValues: PropTypes.object,
    location: PropTypes.object,
    selectPlugin: PropTypes.func.isRequired,
    selectedPlugins: PropTypes.arrayOf(PropTypes.string).isRequired,
};

const ApiForm = (props) => {
    const {
        api,
        apiSchema,
        excludePlugin,
        initialValues,
        handleSubmit,
        plugins,
        response,
        selectPlugin,
        selectedPlugins,
        location,
    } = props;
    const parse = value => (value === undefined ? undefined : parseInt(value));
    const includePlugin = value => {
        apiSchema.plugins.map((plugin, index) => {
            if (plugin.name === value.value && !selectedPlugins.includes(plugin.name)) {
                selectPlugin(plugin.name);
            }
        });
    };
    const removePlugin = value => {
        excludePlugin(value);
    };

    const getValues = key => {
        return initialValues.proxy[key];
    };

    const optionsTransformer = config => {
        const opts = config.map(item => ({
            label: item,
            value: item,
        }));

        return opts;
    };

    return (
        <form className={b} onSubmit={handleSubmit}>

                <Row>
                    <Title>Edit API</Title>

                        <Link
                            to={{
                                pathname: '/new',
                                state: {
                                    clone: api,
                                },
                            }}
                        >
                            <Button
                                type="button"
                                mod="primary"
                            >
                                <Icon type="copy-white" />
                                Copy
                            </Button>
                        </Link>
                        {
                            location &&
                                <Link
                                    to={'/'}
                                    onClick={() => {
                                        props.handleDelete(props.api.name);
                                    }}
                                >
                                    <Button
                                        type="button"
                                        mod="danger"
                                    >
                                        <Icon type="delete-white" />
                                        Delete
                                    </Button>
                                </Link>
                        }
                        <Button
                            type="submit"
                            mod="primary"
                        >
                            Save
                        </Button>

                </Row>

1. General

                    <Row className={b('row')()} fullwidth>
                        <Row col>
                            API Name
                            <Field
                                name="name"
                                type="text"
                                component={Input}
                                disabled={props.disabled}
                            />
                        </Row>
                        <Row col>
                            Is Active?
                            <Row className={b('radio-wrap')()}>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="active"
                                        component={Radio}
                                        value={'true'}
                                        type="radio"
                                        id="is-active"
                                    />
                                    Yes
                                </Row>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="active"
                                        component={Radio}
                                        value={'false'}
                                        type="radio"
                                        id="is-not-active"
                                    />
                                    No
                                </Row>
                            </Row>
                        </Row>
                    </Row>

2. Proxy

                    <Row className={b('row')()} fullwidth>
                        <Row col>
                            Listen Path
                            <Field
                                name="proxy.listen_path"
                                type="text"
                                placeholder="eg. http://gw.hellofresh.com/"
                                component={Input}
                            />
                            <Hint>The public url that is exposed by the Gateway</Hint>
                        </Row>
                        <Row col>
                            Upstream URL
                            <Field
                                name="proxy.upstream_url"
                                type="text"
                                component={Input}
                            />
                            <Hint>The url to which the Gateway forwards requests made to the public url.</Hint>
                        </Row>
                    </Row>
                    <Row className={b('row')()} fullwidth>
                        <Row col>
                            Methods
                            <Field
                                name="proxy.methods"
                                type="text"
                                placeholder="Choose one or more methods"
                                edit
                                value={() => getValues('methods')}
                                options={optionsTransformer(apiSchema.proxy.methods)}
                                component={MultiSelect}
                            />
                            <Hint>HTTP methods that are supported for the endpoint.</Hint>
                        </Row>
                        <Row col>
                            Preserve Host?
                            <Row className={b('radio-wrap')()}>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="proxy.preserve_host"
                                        component={Radio}
                                        value={'true'}
                                        type="radio"
                                        id="preserve-host-true"
                                    />
                                    Yes
                                </Row>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="proxy.preserve_host"
                                        component={Radio}
                                        value={'false'}
                                        type="radio"
                                        id="preserve-host-false"
                                    />
                                    No
                                </Row>
                            </Row>
                            <Hint>Preserve the host header the client used for the incoming request.</Hint>
                        </Row>
                    </Row>
                    <Row className={b('row')()} fullwidth>
                        <Row col>
                            Append Path?
                            <Row className={b('radio-wrap')()}>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="proxy.append_path"
                                        component={Radio}
                                        value={'true'}
                                        type="radio"
                                        id="append-path-true"
                                    />
                                    Yes
                                </Row>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="proxy.append_path"
                                        component={Radio}
                                        value={'false'}
                                        type="radio"
                                        id="append-path-false"
                                    />
                                    No
                                </Row>
                            </Row>
                            <Hint>Appends the path from the listen_path when forwarding the request to the upstream_url.</Hint>
                        </Row>
                        <Row col>
                            Strips Path?
                            <Row className={b('radio-wrap')()}>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="proxy.strip_path"
                                        component={Radio}
                                        value={'true'}
                                        type="radio"
                                        id="strip-path-true"
                                    />
                                    Yes
                                </Row>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="proxy.strip_path"
                                        component={Radio}
                                        value={'false'}
                                        type="radio"
                                        id="strip-path-false"
                                    />
                                    No
                                </Row>
                            </Row>
                            <Hint> Strip the path out of the listen_path when forwarding the request to the upstream_url.</Hint>
                        </Row>
                    </Row>

3. Health check

                    <Row className={b('row')()} fullwidth>
                        <Row col>
                            Health URL (optional)
                            <Field
                                name="health_check.url"
                                type="text"
                                placeholder="eg. http://gw.hellofresh.com/"
                                component={Input}
                            />
                            <Hint>The url that the Gateway will use to determine the health of the API. </Hint>
                        </Row>
                        <Row col>
                            Timeout (optional)
                            <Field
                                name="health_check.timeout"
                                type="number"
                                parse={parse}
                                component={Input}
                            />
                            <Hint>The length of time that the Gateway should wait before displaying an error.</Hint>
                        </Row>
                    </Row>

4. Plugins

                    {
                        !!plugins &&
                            <RenderPlugins
                                className={b()}
                                apiSchema={apiSchema}
                                plugins={plugins}
                                initialValues={initialValues}
                                selectedPlugins={selectedPlugins}
                                handlePluginInclude={includePlugin}
                                handlePluginExclude={removePlugin}
                                response={response}
                                edit
                            />
                    }

            <Row className={b('row',{ 'button-row': true })()}>
                <Button
                    type="submit"
                    mod="primary"
                >
                    Save
                </Button>
            </Row>
        </form>
    );
};

ApiForm.propTypes = propTypes;

const selector = formValueSelector('apiForm');

const form = reduxForm({
    form: 'apiForm',
    enableReinitialize: true, // this is needed!!
})(ApiForm);

export default connect(
    state => {
        const plugins = selector(state, 'plugins');

        const api = state.apiReducer.api;
        const apiPlugins = api.plugins;
        const defaultPlugins = state.apiReducer.apiSchema.plugins;

        const updatedPlugins = defaultPlugins.map(item => {
            const res = apiPlugins.filter(pl => pl.name === item.name);

            return res.length > 0 ? res[0] : item;
        });

        const lens = R.lensPath(['plugins']);
        // substitude the plugin.config.limit
        const updatedApi = R.set(lens, updatedPlugins, api);
        // const x = api.plugins.map((item, index) => item.name === )
        // console.warn('____', transformFormValues(api).plugins);
        // console.warn('____', state.apiReducer.api);
        // console.warn(updatedApi)

        // console.error(defaultPlugins);
        // console.log(apiPlugins);
        // console.warn(updatedPlugins);

        return {
            // initialValues: transformFormValues(state.apiReducer.api),
            initialValues: transformFormValues(updatedApi),
            // ***FOR SOME REASON NAME of the plugin DISCARDS while saving
            apiSchema: state.apiReducer.apiSchema,
            response: state.apiReducer.response,
            selectedPlugins: state.apiReducer.selectedPlugins,
            keepDirtyOnReinitialize: false,
            plugins,
        };
    },
    null,
)(form);
<commit_msg>remove redundant stuff<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import R from 'ramda';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { Field, formValueSelector, reduxForm } from 'redux-form';

import block from '../../../helpers/bem-cn';
import transformFormValues from '../../../helpers/transformFormValues';

import Section from '../../Layout/Section/Section';
import Title from '../../Layout/Title/Title';
import Row from '../../Layout/Row/Row';
import Input from '../../inputs/Input';
import Radio from '../../inputs/Radio/Radio';
import Label from '../../labels/Label';
import Hint from '../../labels/Hint/Hint';
import MultiSelect from '../../selects/MultiSelect/MultiSelect';
import Button from '../../buttons/Button';
import Icon from '../../Icon/Icon';

import RenderPlugins from '../../forms/plugins/RenderPlugins';

const b = block('j-api-form');

const propTypes = {
    api: PropTypes.object.isRequired,
    apiSchema: PropTypes.object.isRequired,
    excludePlugin: PropTypes.func.isRequired,
    handleDelete: PropTypes.func.isRequired,
    handleSubmit: PropTypes.func.isRequired,
    initialValues: PropTypes.object,
    location: PropTypes.object,
    selectPlugin: PropTypes.func.isRequired,
    selectedPlugins: PropTypes.arrayOf(PropTypes.string).isRequired,
};

const ApiForm = (props) => {
    const {
        api,
        apiSchema,
        excludePlugin,
        initialValues,
        handleSubmit,
        plugins,
        response,
        selectPlugin,
        selectedPlugins,
        location,
    } = props;
    const parse = value => value === undefined ? undefined : parseInt(value);
    const includePlugin = value => {
        apiSchema.plugins.map((plugin, index) => {
            if (plugin.name === value.value && !selectedPlugins.includes(plugin.name)) {
                selectPlugin(plugin.name);
            }
        });
    };
    const removePlugin = value => {
        excludePlugin(value);
    };
    const getValues = key => initialValues.proxy[key];
    const optionsTransformer = config => {
        const opts = config.map(item => ({
            label: item,
            value: item,
        }));

        return opts;
    };

    return (
        <form className={b} onSubmit={handleSubmit}>

                <Row>
                    <Title>Edit API</Title>

                        <Link
                            to={{
                                pathname: '/new',
                                state: {
                                    clone: api,
                                },
                            }}
                        >
                            <Button
                                type="button"
                                mod="primary"
                            >
                                <Icon type="copy-white" />
                                Copy
                            </Button>
                        </Link>
                        {
                            location &&
                                <Link
                                    to={'/'}
                                    onClick={() => {
                                        props.handleDelete(props.api.name);
                                    }}
                                >
                                    <Button
                                        type="button"
                                        mod="danger"
                                    >
                                        <Icon type="delete-white" />
                                        Delete
                                    </Button>
                                </Link>
                        }
                        <Button
                            type="submit"
                            mod="primary"
                        >
                            Save
                        </Button>

                </Row>

1. General

                    <Row className={b('row')()} fullwidth>
                        <Row col>
                            API Name
                            <Field
                                name="name"
                                type="text"
                                component={Input}
                                disabled={props.disabled}
                            />
                        </Row>
                        <Row col>
                            Is Active?
                            <Row className={b('radio-wrap')()}>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="active"
                                        component={Radio}
                                        value={'true'}
                                        type="radio"
                                        id="is-active"
                                    />
                                    Yes
                                </Row>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="active"
                                        component={Radio}
                                        value={'false'}
                                        type="radio"
                                        id="is-not-active"
                                    />
                                    No
                                </Row>
                            </Row>
                        </Row>
                    </Row>

2. Proxy

                    <Row className={b('row')()} fullwidth>
                        <Row col>
                            Listen Path
                            <Field
                                name="proxy.listen_path"
                                type="text"
                                placeholder="eg. http://gw.hellofresh.com/"
                                component={Input}
                            />
                            <Hint>The public url that is exposed by the Gateway</Hint>
                        </Row>
                        <Row col>
                            Upstream URL
                            <Field
                                name="proxy.upstream_url"
                                type="text"
                                component={Input}
                            />
                            <Hint>The url to which the Gateway forwards requests made to the public url.</Hint>
                        </Row>
                    </Row>
                    <Row className={b('row')()} fullwidth>
                        <Row col>
                            Methods
                            <Field
                                name="proxy.methods"
                                type="text"
                                placeholder="Choose one or more methods"
                                edit
                                value={() => getValues('methods')}
                                options={optionsTransformer(apiSchema.proxy.methods)}
                                component={MultiSelect}
                            />
                            <Hint>HTTP methods that are supported for the endpoint.</Hint>
                        </Row>
                        <Row col>
                            Preserve Host?
                            <Row className={b('radio-wrap')()}>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="proxy.preserve_host"
                                        component={Radio}
                                        value={'true'}
                                        type="radio"
                                        id="preserve-host-true"
                                    />
                                    Yes
                                </Row>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="proxy.preserve_host"
                                        component={Radio}
                                        value={'false'}
                                        type="radio"
                                        id="preserve-host-false"
                                    />
                                    No
                                </Row>
                            </Row>
                            <Hint>Preserve the host header the client used for the incoming request.</Hint>
                        </Row>
                    </Row>
                    <Row className={b('row')()} fullwidth>
                        <Row col>
                            Append Path?
                            <Row className={b('radio-wrap')()}>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="proxy.append_path"
                                        component={Radio}
                                        value={'true'}
                                        type="radio"
                                        id="append-path-true"
                                    />
                                    Yes
                                </Row>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="proxy.append_path"
                                        component={Radio}
                                        value={'false'}
                                        type="radio"
                                        id="append-path-false"
                                    />
                                    No
                                </Row>
                            </Row>
                            <Hint>Appends the path from the listen_path when forwarding the request to the upstream_url.</Hint>
                        </Row>
                        <Row col>
                            Strips Path?
                            <Row className={b('radio-wrap')()}>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="proxy.strip_path"
                                        component={Radio}
                                        value={'true'}
                                        type="radio"
                                        id="strip-path-true"
                                    />
                                    Yes
                                </Row>
                                <Row className={b('radio')()}>
                                    <Field
                                        name="proxy.strip_path"
                                        component={Radio}
                                        value={'false'}
                                        type="radio"
                                        id="strip-path-false"
                                    />
                                    No
                                </Row>
                            </Row>
                            <Hint> Strip the path out of the listen_path when forwarding the request to the upstream_url.</Hint>
                        </Row>
                    </Row>

3. Health check

                    <Row className={b('row')()} fullwidth>
                        <Row col>
                            Health URL (optional)
                            <Field
                                name="health_check.url"
                                type="text"
                                placeholder="eg. http://gw.hellofresh.com/"
                                component={Input}
                            />
                            <Hint>The url that the Gateway will use to determine the health of the API. </Hint>
                        </Row>
                        <Row col>
                            Timeout (optional)
                            <Field
                                name="health_check.timeout"
                                type="number"
                                parse={parse}
                                component={Input}
                            />
                            <Hint>The length of time that the Gateway should wait before displaying an error.</Hint>
                        </Row>
                    </Row>

4. Plugins

                    {
                        !!plugins &&
                            <RenderPlugins
                                className={b()}
                                apiSchema={apiSchema}
                                plugins={plugins}
                                initialValues={initialValues}
                                selectedPlugins={selectedPlugins}
                                handlePluginInclude={includePlugin}
                                handlePluginExclude={removePlugin}
                                response={response}
                                edit
                            />
                    }

            <Row className={b('row',{ 'button-row': true })()}>
                <Button
                    type="submit"
                    mod="primary"
                >
                    Save
                </Button>
            </Row>
        </form>
    );
};

ApiForm.propTypes = propTypes;

const selector = formValueSelector('apiForm');

const form = reduxForm({
    form: 'apiForm',
    enableReinitialize: true, // this is needed!!
})(ApiForm);

export default connect(
    state => {
        const plugins = selector(state, 'plugins');

        const api = state.apiReducer.api;
        const apiPlugins = api.plugins;
        const defaultPlugins = state.apiReducer.apiSchema.plugins;

        const updatedPlugins = defaultPlugins.map(item => {
            const res = apiPlugins.filter(pl => pl.name === item.name);

            return res.length > 0 ? res[0] : item;
        });

        const lens = R.lensPath(['plugins']);
        // substitude the plugin.config.limit
        const updatedApi = R.set(lens, updatedPlugins, api);
        // const x = api.plugins.map((item, index) => item.name === )
        // console.warn('____', transformFormValues(api).plugins);
        // console.warn('____', state.apiReducer.api);
        // console.warn(updatedApi)

        // console.error(defaultPlugins);
        // console.log(apiPlugins);
        // console.warn(updatedPlugins);

        return {
            // initialValues: transformFormValues(state.apiReducer.api),
            initialValues: transformFormValues(updatedApi),
            // ***FOR SOME REASON NAME of the plugin DISCARDS while saving
            apiSchema: state.apiReducer.apiSchema,
            response: state.apiReducer.response,
            selectedPlugins: state.apiReducer.selectedPlugins,
            keepDirtyOnReinitialize: false,
            plugins,
        };
    },
    null,
)(form);
<|endoftext|>