<commit_before>angular.module( 'App.Forms.Dashboard' ).directive( 'gjFormDashboardFinancialsManagedAccount', function(
	$q, $ocLazyLoad, $window, Form, Api, Growls, Environment, Geo, currencyFilter )
{
	var form = new Form( {
		template: '/app/components/forms/dashboard/financials/managed-account/managed-account.html',
		resetOnSubmit: true,
	} );

	var StripeFileUploadUrl = 'https://uploads.stripe.com/v1/files';
	var stripePublishableKey;

	form.onInit = function( scope )
	{
		scope.Geo = Geo;
		scope.stripeMeta = null;
		scope.additionalOwnerIndex = 0;

		scope.currencyFilter = currencyFilter;
		scope.formState.isLoaded = false;
		scope.formState.genericError = false;
		scope.formState.currencies = [];

		// if ( Environment.env == 'development' ) {
		// 	scope.formModel.bankAccount_country = 'GB';
		// 	scope.formModel.bankAccount_currency = 'GBP',
		// 	scope.formModel.bankAccount_accountNumber = '00012345';
		// 	scope.formModel.bankAccount_routingNumber = '108800';
		// 	scope.formModel.bankAccount_accountHolderName = 'MR I C ROFLCOPTER';
		// 	scope.formModel.bankAccount_accountHolderType = 'individual';
		// }

		// Gotta load in the Stripe JS API as well.
		$ocLazyLoad.load( [ '/app/modules/upload.js', { type: 'js', path: 'https://js.stripe.com/v2/' } ] )
			.then( function()
			{
				return Api.sendRequest( '/web/dash/financials/account' );
			} )
			.then( function( payload )
			{
				stripePublishableKey = payload.stripe.publishableKey;
				Stripe.setPublishableKey( payload.stripe.publishableKey );

				angular.extend( scope, payload );

				scope.stripeMeta = {};
				angular.extend( scope.stripeMeta, payload.stripe.required );

				// We currently don't allow them to edit, so we don't pull the current Stripe
				// fields in to the formModel.
				// var flatObj = {};
 				// dotflatten( flatObj, payload.stripe.current );
 				// angular.extend( scope.formModel, flatObj );

				scope.formModel.additional_owners_count = 0;
				if ( payload.stripe && payload.stripe.current && payload.stripe.current.legal_entity.additional_owners ) {
					scope.formModel.additional_owners_count = payload.stripe.current.legal_entity.additional_owners.length;
				}

				// Due by will be set if this account is required to fill in more by a specific date.
				// This is for additional collection of fields beyond what we want initially.
				scope.formState.isComplete = payload.account.is_verified && !payload.stripe.current.verification.due_by;

				scope.formState.isLoaded = true;
			} );

		function dotflatten( res, obj, current )
		{
			for ( var key in obj ) {
				var value = obj[ key ];
				var newKey = current ? current + '-' + key : key;  // joined key with hyphen

				if ( value && (typeof value == 'array' || typeof value == 'object') ) {
					// It's nested, so do it again.
					dotflatten( res, value, newKey );
				}
				else {
					// Values are always strings.
					if ( value ) {
						value = '' + value;
					}
					res[ newKey ] = value;
				}
			}
		}

		scope.helpers = {};

		scope.helpers.requiresField = function( field )
		{
			if ( !scope.stripeMeta ) {
				return undefined;
			}

			return scope.stripeMeta.minimum.indexOf( field ) != -1
				// We special case personal_id_number.
				// We need it for taxes, so we collect it if it's just in "additional".
				|| (
					field == 'legal_entity.personal_id_number'
					&& scope.stripeMeta.additional.indexOf( field ) != -1
				)
				|| (
					scope.stripe.current
					&& scope.stripe.current.verification
					&& scope.stripe.current.verification.fields_needed
					&& scope.stripe.current.verification.fields_needed.indexOf( field ) != -1
				);
		};

		scope.helpers.getStripeField = function( fieldPath )
		{
			if ( !scope.stripe.current ) {
				return undefined;
			}

			// Gotta traverse the object chain.
			// We should return false if any of the paths don't exist.
			var pieces = fieldPath.split( '.' );
			var field = pieces.pop();
			var obj = scope.stripe.current;

			for ( var i = 0; i < pieces.length; ++i ) {
				if ( !obj[ pieces[ i ] ] ) {
					return undefined;
				}
				obj = obj[ pieces[ i ] ];
			}

			if ( !obj[ field ] ) {
				return undefined;
			}

			return obj[ field ];
		};

		// This is only needed after the initial submission in some instances.
		scope.helpers.requiresVerificationDocument = function()
		{
			return scope.helpers.requiresField( 'legal_entity.verification.document' )
				|| scope.helpers.requiresField( 'legal_entity.additional_owners.0.verification.document' )
				|| scope.helpers.requiresField( 'legal_entity.additional_owners.1.verification.document' )
				|| scope.helpers.requiresField( 'legal_entity.additional_owners.2.verification.document' )
				|| scope.helpers.requiresField( 'legal_entity.additional_owners.3.verification.document' )
				;
		};

		scope.helpers.isVerificationPending = function()
		{
			// If they're in pending state and we don't require more info from them.
			if ( scope.account.status == 'pending' && !scope.helpers.requiresVerificationDocument() ) {
				return true;
			}

			return false;
		};

		scope.helpers.addAdditionalOwner = function()
		{
			++scope.formModel.additional_owners_count;
		}

		scope.helpers.removeAdditionalOwner = function( index )
		{
			// Helpers.
			function removeOwnerData( i )
			{
				var regex = new RegExp( 'legal_entity\-additional_owners\-' + i + '\-' );
				for ( var field in scope.formModel ) {
					if ( regex.test( field ) ) {
						delete scope.formModel[ field ];
					}
				}
			}

			function copyOwnerData( oldIndex, newIndex )
			{
				var regex = new RegExp( 'legal_entity\-additional_owners\-' + oldIndex + '\-' );
				for ( var field in scope.formModel ) {
					if ( regex.test( field ) ) {
						var newField = field.replace( '-' + oldIndex + '-', '-' + newIndex + '-' );
						scope.formModel[ newField ] = scope.formModel[ field ];
					}
				}
			}

			// Reindex all the owners after the one that was removed to be shifted over once.
			for ( var i = index + 1; i < scope.formModel.additional_owners_count; ++i ) {

				// We have to remove the owner data from the index before.
				// If the current owner doesn't have all fields filled, it won't overwrite completely.
				// It needs a "pristine" state to copy into.
				removeOwnerData( i - 1 );
				copyOwnerData( i, i - 1 );
			}

			// Clear out all the fields for the last one as well since it's now shifted.
			removeOwnerData( scope.formModel.additional_owners_count - 1 );
			--scope.formModel.additional_owners_count;
		}

		// scope.updateCurrencies = function( )
		// {
		// 	scope.formState.currencies = scope.stripe.currencies[ scope.formModel.bankAccount_country ];
		// }
	};

	function uploadIdDocument( inputId )
	{
		return $q( function( resolve, reject )
		{
			var formData = new FormData();
			formData.append( 'purpose', 'identity_document' );
			console.log( inputId );
			formData.append( 'file', document.getElementById( inputId ).querySelector( "input[type='file']" ).files[0] );

			var xhr = new XMLHttpRequest();
			xhr.open( 'POST', StripeFileUploadUrl );
			xhr.setRequestHeader( 'Authorization', 'Bearer ' + stripePublishableKey );
			xhr.setRequestHeader( 'Accept', 'application/json' );  // Makes sure it doesn't return as JSONP.
			xhr.send( formData );

			xhr.onreadystatechange = function()
			{
				if ( xhr.readyState == 4 ) {
					if ( xhr.status == 200 ) {
						resolve( JSON.parse( xhr.responseText ) );
					}
					else {
						reject( JSON.parse( xhr.responseText ).error );
					}
				}
			};
		} );
	}

	function createPiiToken( data )
	{
		return $q( function( resolve, reject )
		{
			if ( !data['legal_entity-personal_id_number'] ) {
				resolve( null );
				return;
			}

			Stripe.piiData.createToken( {
				personal_id_number: data['legal_entity-personal_id_number'],
			},
			function ( status, response )
			{
				if ( response.error ) {
					reject( response.error );
				}
				else {
					resolve( response.id );
				}
			} );
		} );
	}

	form.onSubmit = function( scope )
	{
		// We don't want to send the sensitive data to GJ.
		var data = angular.copy( scope.formModel );

		var requestPromise = $q.when( data );

		if ( scope.formModel['legal_entity-verification-document'] && scope.formModel['legal_entity-verification-status'] != 'verified' ) {
			requestPromise = requestPromise
				.then( function()
				{
					return uploadIdDocument( 'legal_entity-verification-document-input' );
				} )
				.then( function( response )
				{
					data['legal_entity-verification-document'] = response.id;
				} );
		}

		// Additional files
		for ( var i = 0; i < 4; i++ ) {
			if ( scope.formModel['legal_entity-additional_owners-' + i + '-verification-document'] ) {
				var curIndex = i;
				requestPromise = requestPromise
					.then( function()
					{
						return uploadIdDocument( 'legal_entity-additional_owners-' + curIndex + '-verification-document-input' );
					} )
					.then( function( response )
					{
						data['legal_entity-additional_owners-' + curIndex + '-verification-document'] = response.id;
					} );
			}
		}

		scope.formState.genericError = false;

		return requestPromise
			.then( function()
			{
				return createPiiToken( data );
			} )
			.catch( function( error )
			{
				// Error from Stripe.
				console.error( error );
				scope.formState.genericError = error.message;

				// Rethrow to make sure that no "then" blocks below go through.
				throw error;
			} )
			.then( function( id )
			{
				// Override the SSN with the token.
				// This way the raw SSN never hits our server. Only the token.
				if ( id ) {
					data['legal_entity-personal_id_number'] = id;
				}

				return Api.sendRequest( '/web/dash/financials/account', data );
			} )
			.then( function( response )
			{
				if ( response.success === false ) {
					scope.formState.genericError = true;
				}

				return response;
			} );
	};

	return form;
} );
<commit_msg>Remove log line<commit_after>angular.module( 'App.Forms.Dashboard' ).directive( 'gjFormDashboardFinancialsManagedAccount', function(
	$q, $ocLazyLoad, $window, Form, Api, Growls, Environment, Geo, currencyFilter )
{
	var form = new Form( {
		template: '/app/components/forms/dashboard/financials/managed-account/managed-account.html',
		resetOnSubmit: true,
	} );

	var StripeFileUploadUrl = 'https://uploads.stripe.com/v1/files';
	var stripePublishableKey;

	form.onInit = function( scope )
	{
		scope.Geo = Geo;
		scope.stripeMeta = null;
		scope.additionalOwnerIndex = 0;

		scope.currencyFilter = currencyFilter;
		scope.formState.isLoaded = false;
		scope.formState.genericError = false;
		scope.formState.currencies = [];

		// if ( Environment.env == 'development' ) {
		// 	scope.formModel.bankAccount_country = 'GB';
		// 	scope.formModel.bankAccount_currency = 'GBP',
		// 	scope.formModel.bankAccount_accountNumber = '00012345';
		// 	scope.formModel.bankAccount_routingNumber = '108800';
		// 	scope.formModel.bankAccount_accountHolderName = 'MR I C ROFLCOPTER';
		// 	scope.formModel.bankAccount_accountHolderType = 'individual';
		// }

		// Gotta load in the Stripe JS API as well.
		$ocLazyLoad.load( [ '/app/modules/upload.js', { type: 'js', path: 'https://js.stripe.com/v2/' } ] )
			.then( function()
			{
				return Api.sendRequest( '/web/dash/financials/account' );
			} )
			.then( function( payload )
			{
				stripePublishableKey = payload.stripe.publishableKey;
				Stripe.setPublishableKey( payload.stripe.publishableKey );

				angular.extend( scope, payload );

				scope.stripeMeta = {};
				angular.extend( scope.stripeMeta, payload.stripe.required );

				// We currently don't allow them to edit, so we don't pull the current Stripe
				// fields in to the formModel.
				// var flatObj = {};
 				// dotflatten( flatObj, payload.stripe.current );
 				// angular.extend( scope.formModel, flatObj );

				scope.formModel.additional_owners_count = 0;
				if ( payload.stripe && payload.stripe.current && payload.stripe.current.legal_entity.additional_owners ) {
					scope.formModel.additional_owners_count = payload.stripe.current.legal_entity.additional_owners.length;
				}

				// Due by will be set if this account is required to fill in more by a specific date.
				// This is for additional collection of fields beyond what we want initially.
				scope.formState.isComplete = payload.account.is_verified && !payload.stripe.current.verification.due_by;

				scope.formState.isLoaded = true;
			} );

		function dotflatten( res, obj, current )
		{
			for ( var key in obj ) {
				var value = obj[ key ];
				var newKey = current ? current + '-' + key : key;  // joined key with hyphen

				if ( value && (typeof value == 'array' || typeof value == 'object') ) {
					// It's nested, so do it again.
					dotflatten( res, value, newKey );
				}
				else {
					// Values are always strings.
					if ( value ) {
						value = '' + value;
					}
					res[ newKey ] = value;
				}
			}
		}

		scope.helpers = {};

		scope.helpers.requiresField = function( field )
		{
			if ( !scope.stripeMeta ) {
				return undefined;
			}

			return scope.stripeMeta.minimum.indexOf( field ) != -1
				// We special case personal_id_number.
				// We need it for taxes, so we collect it if it's just in "additional".
				|| (
					field == 'legal_entity.personal_id_number'
					&& scope.stripeMeta.additional.indexOf( field ) != -1
				)
				|| (
					scope.stripe.current
					&& scope.stripe.current.verification
					&& scope.stripe.current.verification.fields_needed
					&& scope.stripe.current.verification.fields_needed.indexOf( field ) != -1
				);
		};

		scope.helpers.getStripeField = function( fieldPath )
		{
			if ( !scope.stripe.current ) {
				return undefined;
			}

			// Gotta traverse the object chain.
			// We should return false if any of the paths don't exist.
			var pieces = fieldPath.split( '.' );
			var field = pieces.pop();
			var obj = scope.stripe.current;

			for ( var i = 0; i < pieces.length; ++i ) {
				if ( !obj[ pieces[ i ] ] ) {
					return undefined;
				}
				obj = obj[ pieces[ i ] ];
			}

			if ( !obj[ field ] ) {
				return undefined;
			}

			return obj[ field ];
		};

		// This is only needed after the initial submission in some instances.
		scope.helpers.requiresVerificationDocument = function()
		{
			return scope.helpers.requiresField( 'legal_entity.verification.document' )
				|| scope.helpers.requiresField( 'legal_entity.additional_owners.0.verification.document' )
				|| scope.helpers.requiresField( 'legal_entity.additional_owners.1.verification.document' )
				|| scope.helpers.requiresField( 'legal_entity.additional_owners.2.verification.document' )
				|| scope.helpers.requiresField( 'legal_entity.additional_owners.3.verification.document' )
				;
		};

		scope.helpers.isVerificationPending = function()
		{
			// If they're in pending state and we don't require more info from them.
			if ( scope.account.status == 'pending' && !scope.helpers.requiresVerificationDocument() ) {
				return true;
			}

			return false;
		};

		scope.helpers.addAdditionalOwner = function()
		{
			++scope.formModel.additional_owners_count;
		}

		scope.helpers.removeAdditionalOwner = function( index )
		{
			// Helpers.
			function removeOwnerData( i )
			{
				var regex = new RegExp( 'legal_entity\-additional_owners\-' + i + '\-' );
				for ( var field in scope.formModel ) {
					if ( regex.test( field ) ) {
						delete scope.formModel[ field ];
					}
				}
			}

			function copyOwnerData( oldIndex, newIndex )
			{
				var regex = new RegExp( 'legal_entity\-additional_owners\-' + oldIndex + '\-' );
				for ( var field in scope.formModel ) {
					if ( regex.test( field ) ) {
						var newField = field.replace( '-' + oldIndex + '-', '-' + newIndex + '-' );
						scope.formModel[ newField ] = scope.formModel[ field ];
					}
				}
			}

			// Reindex all the owners after the one that was removed to be shifted over once.
			for ( var i = index + 1; i < scope.formModel.additional_owners_count; ++i ) {

				// We have to remove the owner data from the index before.
				// If the current owner doesn't have all fields filled, it won't overwrite completely.
				// It needs a "pristine" state to copy into.
				removeOwnerData( i - 1 );
				copyOwnerData( i, i - 1 );
			}

			// Clear out all the fields for the last one as well since it's now shifted.
			removeOwnerData( scope.formModel.additional_owners_count - 1 );
			--scope.formModel.additional_owners_count;
		}

		// scope.updateCurrencies = function( )
		// {
		// 	scope.formState.currencies = scope.stripe.currencies[ scope.formModel.bankAccount_country ];
		// }
	};

	function uploadIdDocument( inputId )
	{
		return $q( function( resolve, reject )
		{
			var formData = new FormData();
			formData.append( 'purpose', 'identity_document' );
			formData.append( 'file', document.getElementById( inputId ).querySelector( "input[type='file']" ).files[0] );

			var xhr = new XMLHttpRequest();
			xhr.open( 'POST', StripeFileUploadUrl );
			xhr.setRequestHeader( 'Authorization', 'Bearer ' + stripePublishableKey );
			xhr.setRequestHeader( 'Accept', 'application/json' );  // Makes sure it doesn't return as JSONP.
			xhr.send( formData );

			xhr.onreadystatechange = function()
			{
				if ( xhr.readyState == 4 ) {
					if ( xhr.status == 200 ) {
						resolve( JSON.parse( xhr.responseText ) );
					}
					else {
						reject( JSON.parse( xhr.responseText ).error );
					}
				}
			};
		} );
	}

	function createPiiToken( data )
	{
		return $q( function( resolve, reject )
		{
			if ( !data['legal_entity-personal_id_number'] ) {
				resolve( null );
				return;
			}

			Stripe.piiData.createToken( {
				personal_id_number: data['legal_entity-personal_id_number'],
			},
			function ( status, response )
			{
				if ( response.error ) {
					reject( response.error );
				}
				else {
					resolve( response.id );
				}
			} );
		} );
	}

	form.onSubmit = function( scope )
	{
		// We don't want to send the sensitive data to GJ.
		var data = angular.copy( scope.formModel );

		var requestPromise = $q.when( data );

		if ( scope.formModel['legal_entity-verification-document'] && scope.formModel['legal_entity-verification-status'] != 'verified' ) {
			requestPromise = requestPromise
				.then( function()
				{
					return uploadIdDocument( 'legal_entity-verification-document-input' );
				} )
				.then( function( response )
				{
					data['legal_entity-verification-document'] = response.id;
				} );
		}

		// Additional files
		for ( var i = 0; i < 4; i++ ) {
			if ( scope.formModel['legal_entity-additional_owners-' + i + '-verification-document'] ) {
				var curIndex = i;
				requestPromise = requestPromise
					.then( function()
					{
						return uploadIdDocument( 'legal_entity-additional_owners-' + curIndex + '-verification-document-input' );
					} )
					.then( function( response )
					{
						data['legal_entity-additional_owners-' + curIndex + '-verification-document'] = response.id;
					} );
			}
		}

		scope.formState.genericError = false;

		return requestPromise
			.then( function()
			{
				return createPiiToken( data );
			} )
			.catch( function( error )
			{
				// Error from Stripe.
				console.error( error );
				scope.formState.genericError = error.message;

				// Rethrow to make sure that no "then" blocks below go through.
				throw error;
			} )
			.then( function( id )
			{
				// Override the SSN with the token.
				// This way the raw SSN never hits our server. Only the token.
				if ( id ) {
					data['legal_entity-personal_id_number'] = id;
				}

				return Api.sendRequest( '/web/dash/financials/account', data );
			} )
			.then( function( response )
			{
				if ( response.success === false ) {
					scope.formState.genericError = true;
				}

				return response;
			} );
	};

	return form;
} );
<|endoftext|>


<commit_before>var redis = require('redis').createClient();
var uuid = require('node-uuid');

var streams = {}

module.exports = {
    addStream: function (req, res, next){
        var id = req.params.id;
        streams[id] = res;
    },
    getStream: function (id){
        return streams[id];
    },
    setup: function (req, res, next){

        redis.incr('client_counter', function (err, count){

            var id = uuid.v1();
            var major = parseInt(count / 65536, 10);
            var minor = parseInt(count % 65536);

            var stringId = 'id:'+major+'-'+minor;

            redis.set(stringId, id);
            redis.set('uuid:'+id, major+'-'+minor);

            res.send({
                minor: minor,
                major: major,
                client_id: id
            });

        })
    },
    shutup: function (req, res, next){
        var id = req.params.id;

        if(streams && streams[id]){
            streams[id].close();
            delete streams[id];
        }
    },
    erase: function (req, res, next){
        var id = req.params.id;
        redis.get('uuid:'+id, function (err, ids){
            if(err){
                res.status(500).end();
                next();
            }
            if(!ids){
                res.status(404).end(); next();
            }
            redis.del('uuid:'+id);
            redis.del('id:'+ids);
            res.status(200).end();
            next();
        });
    }
}<commit_msg>Split shutup and erase<commit_after>var redis = require('redis').createClient();
var uuid = require('node-uuid');

var streams = {}

module.exports = {
    addStream: function (req, res, next){
        var id = req.params.id;
        streams[id] = res;
    },
    getStream: function (id){
        return streams[id];
    },
    setup: function (req, res, next){

        redis.incr('client_counter', function (err, count){

            var id = uuid.v1();
            var major = parseInt(count / 65536, 10);
            var minor = parseInt(count % 65536);

            var stringId = 'id:'+major+'-'+minor;

            redis.set(stringId, id);
            redis.set('uuid:'+id, major+'-'+minor);

            res.send({
                minor: minor,
                major: major,
                client_id: id
            });

        })
    },
    shutup: function (req, res, next){
        var id = req.params.id;

        if(streams && streams[id]){
            streams[id].close();
            delete streams[id];
            res.status(200).end();
        } else {
            res.status(404).end();
        }

    },
    erase: function (req, res, next){
        var id = req.params.id;
        redis.get('uuid:'+id, function (err, ids){
            if(err){
                res.status(500).end();
                next();
            }
            if(!ids){
                res.status(404).end(); next();
            }
            redis.del('uuid:'+id);
            redis.del('id:'+ids);
            res.status(200).end();
            next();
        });
    }
}<|endoftext|>


<commit_before>"use strict";

function gsuiSpectrum( canvas ) {
	this.canvas = canvas;
	this.canvas.height = 1;
	this.ctx = canvas.getContext( "2d" );
	this.colors = [
		[   5,   2,  20 ], // 0
		[   8,   5,  30 ], // 1
		[  15,   7,  50 ], // 2
		[  75,   7,  35 ],   // 3
		[  80,   0,   0 ],   // 4
		[ 180,   0,   0 ],   // 5
		[ 200,  25,  10 ], // 6
		[ 200, 128,  10 ], // 7
		[ 200, 200,  20 ], // 8
	];
};

gsuiSpectrum.prototype = {
	setResolution: function( w ) {
		this.canvas.width = w;
	},
	clear: function() {
		this.ctx.clearRect( 0, 0, this.canvas.width, this.canvas.height );
	},
	draw: function( data ) {
		var datum, col, colId,
			r, g, b, ws,
			x = 0,
			i = 0,
			cnv = this.canvas,
			ctx = this.ctx,
			w = cnv.width,
			h = cnv.height,
			datalen = data.length;

		if ( datalen !== this.datalen ) {
			this._calcWidths( data, datalen, w );
			this.datalen = datalen;
		}
		ws = this._widths;
		for ( ; i < datalen; ++i ) {
			datum = 1 - Math.cos( data[ i ] / 255 * Math.PI / 2 );
			if ( datum < .05 ) {
				r = 4 + 10 * datum;
				g = 4 + 10 * datum;
				b = 5 + 20 * datum;
			} else {
				     if ( datum < .08 ) { colId = 0; datum /= .08; }
				else if ( datum < .15 ) { colId = 1; datum /= .15; }
				else if ( datum < .17 ) { colId = 2; datum /= .17; }
				else if ( datum < .25 ) { colId = 3; datum /= .25; }
				else if ( datum < .3  ) { colId = 4; datum /= .3; }
				else if ( datum < .4  ) { colId = 5; datum /= .4; }
				else if ( datum < .6  ) { colId = 6; datum /= .6; }
				else if ( datum < .8  ) { colId = 7; datum /= .8; }
				else                    { colId = 8; }
				col = this.colors[ colId ];
				r = col[ 0 ] * datum;
				g = col[ 1 ] * datum;
				b = col[ 2 ] * datum;
			}
			ctx.fillStyle = "rgb("
				+ ~~r + ","
				+ ~~g + ","
				+ ~~b + ")";

			ctx.fillRect( x, 0, ws[ i ], h );
			x += ws[ i ];
		}
	},

	// private:
	_calcWidths: function( data, len, w ) {
		var i, sum = 0, arr = new Array( len );

		for ( i = 0; i < len; ++i ) {
			sum += arr[ i ] = Math.log( len / ( i + 1 ) );
		}
		for ( i = 0; i < len; ++i ) {
			arr[ i ] = arr[ i ] / sum * w;
		}
		this._widths = arr;
	}
};
<commit_msg>gsuiSpectrum: .draw, recalcul the rectwidth after a different resolution<commit_after>"use strict";

function gsuiSpectrum( canvas ) {
	this.canvas = canvas;
	this.canvas.height = 1;
	this.ctx = canvas.getContext( "2d" );
	this.colors = [
		[   5,   2,  20 ], // 0
		[   8,   5,  30 ], // 1
		[  15,   7,  50 ], // 2
		[  75,   7,  35 ],   // 3
		[  80,   0,   0 ],   // 4
		[ 180,   0,   0 ],   // 5
		[ 200,  25,  10 ], // 6
		[ 200, 128,  10 ], // 7
		[ 200, 200,  20 ], // 8
	];
};

gsuiSpectrum.prototype = {
	setResolution: function( w ) {
		this.canvas.width = w;
	},
	clear: function() {
		this.ctx.clearRect( 0, 0, this.canvas.width, this.canvas.height );
	},
	draw: function( data ) {
		var datum, col, colId,
			r, g, b, ws,
			x = 0,
			i = 0,
			cnv = this.canvas,
			ctx = this.ctx,
			w = cnv.width,
			h = cnv.height,
			datalen = data.length;

		if ( this._datalen !== datalen || this._width !== w ) {
			this._calcWidths( data,
				this._datalen = datalen,
				this._width = w );
		}
		ws = this._widths;
		for ( ; i < datalen; ++i ) {
			datum = 1 - Math.cos( data[ i ] / 255 * Math.PI / 2 );
			if ( datum < .05 ) {
				r = 4 + 10 * datum;
				g = 4 + 10 * datum;
				b = 5 + 20 * datum;
			} else {
				     if ( datum < .08 ) { colId = 0; datum /= .08; }
				else if ( datum < .15 ) { colId = 1; datum /= .15; }
				else if ( datum < .17 ) { colId = 2; datum /= .17; }
				else if ( datum < .25 ) { colId = 3; datum /= .25; }
				else if ( datum < .3  ) { colId = 4; datum /= .3; }
				else if ( datum < .4  ) { colId = 5; datum /= .4; }
				else if ( datum < .6  ) { colId = 6; datum /= .6; }
				else if ( datum < .8  ) { colId = 7; datum /= .8; }
				else                    { colId = 8; }
				col = this.colors[ colId ];
				r = col[ 0 ] * datum;
				g = col[ 1 ] * datum;
				b = col[ 2 ] * datum;
			}
			ctx.fillStyle = "rgb("
				+ ~~r + ","
				+ ~~g + ","
				+ ~~b + ")";
			ctx.fillRect( x, 0, ws[ i ], h );
			x += ws[ i ];
		}
	},

	// private:
	_calcWidths: function( data, len, w ) {
		var i, sum = 0, arr = new Array( len );

		for ( i = 0; i < len; ++i ) {
			sum += arr[ i ] = Math.log( len / ( i + 1 ) );
		}
		for ( i = 0; i < len; ++i ) {
			arr[ i ] = arr[ i ] / sum * w;
		}
		this._widths = arr;
	}
};
<|endoftext|>


<commit_before>/*!
 * bootprint <https://github.com/nknapp/bootprint>
 *
 * Copyright (c) 2015 Nils Knappmeier.
 * Released under the MIT license.
 */

var path = require('path')
var fs = require('fs')
var cp = require('child_process')
// require('trace')
// require('clarify')
process.on('exit', function () {
  var unhandledReasons = require('q').getUnhandledReasons()
  if (unhandledReasons.length > 0) {
    console.log(unhandledReasons)
  }
})

/* global describe */
/* global it */
/* global beforeEach */
var expect = require('chai').expect
var bootprint = require('../')
var tmpDir = path.join(__dirname, 'tmp')
var targetDir = path.join(tmpDir, 'target')
var swaggerJsonFile = path.join(tmpDir, 'changing.json')
var qfs = require('m-io/fs')

beforeEach(function () {
  return qfs.removeTree(tmpDir)
    .then(function () {
      return qfs.makeTree(tmpDir)
    })
})

function run () {
  return bootprint
    .merge({
      handlebars: {
        templates: path.join(__dirname, 'fixtures', 'handlebars')
      },
      less: {
        main: require.resolve('./fixtures/main.less')
      }
    })
    .build(swaggerJsonFile, targetDir)
    .generate()
}

describe('The programmatic interface', function () {
  it('should load the input json each time it runs', function () {
    fs.writeFileSync(swaggerJsonFile, JSON.stringify({
      eins: 'one', zwei: 'two', drei: 'three'
    }))

    return run()
      .then(function () {
        var content = fs.readFileSync(path.join(targetDir, 'index.html'), {encoding: 'utf-8'})
        expect(content.trim()).to.equal('eins=one zwei=two drei=three')
        fs.writeFileSync(swaggerJsonFile, JSON.stringify({
          eins: 'un', zwei: 'deux', drei: 'trois'
        }))
        return run()
      })
      .then(function () {
        var content = fs.readFileSync(path.join(targetDir, 'index.html'), {encoding: 'utf-8'})
        expect(content.trim()).to.equal('eins=un zwei=deux drei=trois')
      })
  })

  it('should accept yaml as input', function () {
    return bootprint
      .merge({
        handlebars: {
          templates: path.join(__dirname, 'fixtures', 'handlebars')
        },
        less: {
          main: require.resolve('./fixtures/main.less')
        }
      })
      .build(require.resolve('./fixtures/input.yaml'), targetDir)
      .generate()
      .then(function () {
        var content = fs.readFileSync(path.join(targetDir, 'index.html'), {encoding: 'utf-8'})
        return expect(content.trim()).to.equal('eins=ichi zwei=ni drei=san')
      })
  })
})

describe('The CLI interface', function () {
  var targetDir = path.join(tmpDir, 'cli-target')

  function outputFile (filename) {
    return fs.readFileSync(path.join(targetDir, filename), {encoding: 'utf-8'}).trim()
  }

  it('should run without errors if the correct number of parameters is provided', function () {
    cp.spawnSync('./bin/bootprint.js ./test/fixtures/test-module.js ./test/fixtures/input.yaml ' + targetDir, {
      shell: true,
      encoding: 'utf-8'
    })
    expect(outputFile('index.html'), 'Checking index.html').to.equal('eins=ichi zwei=ni drei=san')
    expect(outputFile('main.css'), 'Checking main.css').to.equal("body{background-color:'#abc'}")
  })

  it('should return with a non-zero exit-code and an error message if too few parameters are given', function () {
    var result = cp.spawnSync('./bin/bootprint.js ./test/fixtures/input.yaml ' + targetDir, {
      shell: true,
      encoding: 'utf-8'
    })
    expect(result.stderr, 'Checking stderr-output')
      .to.match(/\s*Invalid number of command-line arguments. 3 arguments expected.*/)
    expect(result.status === 1, 'Checking exit-code')
  })

  it('should return with a non-zero exit-code and an error without stack-trace if the source file could not be found', function () {
    var result = cp.spawnSync('./bin/bootprint.js ./test/fixtures/test-module.js  ./test/fixtures/non-existing-file.yaml ' + targetDir, {
      shell: true,
      encoding: 'utf-8'
    })
    expect(result.stderr, 'Checking stderr-output')
      .to.match(/.*no such file or directory.*/)
    expect(result.stderr, 'stderr should not contain a stack-trace').not.to.match(/throw e/)

    expect(result.status === 1, 'Checking exit-code')
  })

  it('should return with a non-zero exit-code and an error with stack-trace for unexpected errors', function () {
    var result = cp.spawnSync('./bin/bootprint.js ./test/fixtures/test-module-error.js  ./test/fixtures/non-existing-file.yaml ' + targetDir, {
      shell: true,
      encoding: 'utf-8'
    })
    expect(result.stderr, 'stderr should contain a stack-trace').to.match(/throw new Error/)
    expect(result.status === 1, 'Checking exit-code')
  })
})
<commit_msg>Fix testcases in TravisCI<commit_after>/*!
 * bootprint <https://github.com/nknapp/bootprint>
 *
 * Copyright (c) 2015 Nils Knappmeier.
 * Released under the MIT license.
 */

var path = require('path')
var fs = require('fs')
var cp = require('child_process')
// require('trace')
// require('clarify')
var Q = require('q')
process.on('exit', function () {
  var unhandledReasons = require('q').getUnhandledReasons()
  if (unhandledReasons.length > 0) {
    console.log(unhandledReasons)
  }
})

/* global describe */
/* global it */
/* global beforeEach */
var expect = require('chai').expect
var bootprint = require('../')
var tmpDir = path.join(__dirname, 'tmp')
var targetDir = path.join(tmpDir, 'target')
var swaggerJsonFile = path.join(tmpDir, 'changing.json')
var qfs = require('m-io/fs')

beforeEach(function () {
  return qfs.removeTree(tmpDir)
    .then(function () {
      return qfs.makeTree(tmpDir)
    })
})

function run () {
  return bootprint
    .merge({
      handlebars: {
        templates: path.join(__dirname, 'fixtures', 'handlebars')
      },
      less: {
        main: require.resolve('./fixtures/main.less')
      }
    })
    .build(swaggerJsonFile, targetDir)
    .generate()
}

describe('The programmatic interface', function () {
  it('should load the input json each time it runs', function () {
    fs.writeFileSync(swaggerJsonFile, JSON.stringify({
      eins: 'one', zwei: 'two', drei: 'three'
    }))

    return run()
      .then(function () {
        var content = fs.readFileSync(path.join(targetDir, 'index.html'), {encoding: 'utf-8'})
        expect(content.trim()).to.equal('eins=one zwei=two drei=three')
        fs.writeFileSync(swaggerJsonFile, JSON.stringify({
          eins: 'un', zwei: 'deux', drei: 'trois'
        }))
        return run()
      })
      .then(function () {
        var content = fs.readFileSync(path.join(targetDir, 'index.html'), {encoding: 'utf-8'})
        expect(content.trim()).to.equal('eins=un zwei=deux drei=trois')
      })
  })

  it('should accept yaml as input', function () {
    return bootprint
      .merge({
        handlebars: {
          templates: path.join(__dirname, 'fixtures', 'handlebars')
        },
        less: {
          main: require.resolve('./fixtures/main.less')
        }
      })
      .build(require.resolve('./fixtures/input.yaml'), targetDir)
      .generate()
      .then(function () {
        var content = fs.readFileSync(path.join(targetDir, 'index.html'), {encoding: 'utf-8'})
        return expect(content.trim()).to.equal('eins=ichi zwei=ni drei=san')
      })
  })
})

describe('The CLI interface', function () {
  var targetDir = path.join(tmpDir, 'cli-target')

  function exec (command) {
    var deferred = Q.defer()
    cp.exec(command, {encoding: 'utf-8'}, function (err, stdout, stderr) {
      return deferred.resolve({
        err: err,
        stdout: stdout,
        stderr: stderr
      })
    })
    return deferred.promise
  }

  function outputFile (filename) {
    return fs.readFileSync(path.join(targetDir, filename), {encoding: 'utf-8'}).trim()
  }

  it('should run without errors if the correct number of parameters is provided', function () {
    return exec('./bin/bootprint.js ./test/fixtures/test-module.js ./test/fixtures/input.yaml ' + targetDir)
      .then(function (result) {
        expect(result.err).to.be.null
        expect(outputFile('index.html'), 'Checking index.html').to.equal('eins=ichi zwei=ni drei=san')
        expect(outputFile('main.css'), 'Checking main.css').to.equal("body{background-color:'#abc'}")
      })
  })

  it('should return with a non-zero exit-code and an error message if too few parameters are given', function () {
    return exec('./bin/bootprint.js ./test/fixtures/input.yaml ' + targetDir)
      .then(function (result) {
        expect(result.err).not.to.be.null
        expect(result.stderr, 'Checking stderr-output')
          .to.match(/\s*Invalid number of command-line arguments. 3 arguments expected.*/)
        expect(result.status === 1, 'Checking exit-code')
      })
  })

  it('should return with a non-zero exit-code and an error without stack-trace if the source file could not be found', function () {
    exec('./bin/bootprint.js ./test/fixtures/test-module.js  ./test/fixtures/non-existing-file.yaml ' + targetDir)
      .then(function (result) {
        expect(result.stderr, 'Checking stderr-output').to.match(/.*no such file or directory.*/)
        expect(result.stderr, 'stderr should not contain a stack-trace').not.to.match(/throw/)
        expect(result.error).not.to.be.null
      })
  })

  it('should return with a non-zero exit-code and an error with stack-trace for unexpected errors', function () {
    exec('./bin/bootprint.js ./test/fixtures/test-module-error.js  ./test/fixtures/non-existing-file.yaml ' + targetDir)
      .then(function (result) {
        expect(result.stderr, 'stderr should contain a stack-trace').to.match(/throw new Error/)
        expect(result.error).not.to.be.null
      })
  })
})
<|endoftext|>


<commit_before>/**
 * Created by bo on 5/12/16.
 */

var to_register_at_site = true;
var template_str;
var loading_html;

$(document).ready(function () {
    loading_html = '

';
    $('#subject-registration-div').append(loading_html);
    next_btn();
    check_new_patients(true);
});

function check_new_patients(toRegisterSite) {

    $.ajax({
        url: baseApp + "/template/get-subject-template",
        type: "GET",
        data: {registerSite: toRegisterSite},
        success: function (template) {
            $('#loading_div').remove();
            template_str = template;
            if (template.length > 1) {
                provide_template_download();
                provide_filled_template_upload();
            }
            else {
                window.location.href = baseApp + "/views/feedback-subjects";
            }
        },
        error: function (jqXHR, textStatus, errorThrown) {
            console.log(jqXHR.status + " " + textStatus + " " + errorThrown);
            window.location.href = baseApp + "/views/feedback-subjects";
        }
    });
}

function provide_template_download() {
    var info = '
☛ Unregistered subjects are found in the dataset. These subjects should be registered with a "subject registration template", which can be downloaded<button id="download-subject-template-btn" class="btn btn-link btn-lg text-left" style="text-align: left">here</button>

';
    $(info).insertBefore('#subject-back-btn');

    $('#download-subject-template-btn').click(function () {
        var blob = new Blob(template_str, {type: "text/plain;charset=utf-8"});
        saveAs(blob, "subject-registration-template.txt");
    });
}

function provide_filled_template_upload() {
    var html = '
☛ Once you have filled out the template, select it using the file chooser below.
 <form id="upload-subject-template-form" class="form-horizontal"><input id="upload-subject-template-input" type="file" name="uploadPatientData" accept="*" /></form>
';
    $(html).insertBefore('#subject-back-btn');
}

function next_btn() {
    var html = '<button type="button" class="btn btn-primary" id="subject-back-btn">Back</button> ' +
        '<button type="button" class="btn btn-primary" id="subject-next-btn">Next</button>';
    $('#subject-registration-div').append(html);
    $('#subject-back-btn').click(function () {
        window.location.href = baseApp + "/views/feedback-data";
    });

    $('#subject-next-btn').click(function () {
        upload_subjects();
    });

}

function upload_subjects() {
    $('#loading_div').remove();
    $(loading_html).insertAfter('#message-board');
    $('#message-board').empty();
    $.ajax({
        url: baseApp + "/upload/subjects",
        type: "POST",
        data: new FormData($("#upload-subject-template-form")[0]),
        enctype: 'multipart/form-data',
        processData: false,
        contentType: false,
        success: function (fileFormatErrors) {
            if(fileFormatErrors.length == 0) {
                update_submission();
            }
            else{
                log_errors(fileFormatErrors);
            }
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('#loading_div').remove();
            console.log(jqXHR.status + " " + textStatus + " " + errorThrown);
            $('#message-board').append('
Subject upload fails.
')
        }

    });
}

function update_submission() {
    $.ajax({
        url: baseApp + "/submission/update",
        type: "POST",
        data: {step: "feedback-subjects"},
        success: function () {
            $('#loading_div').remove();
            //handle subject file upload
            window.location.href = baseApp + "/views/feedback-subjects";
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('#loading_div').remove();
            console.log(jqXHR.status + " " + textStatus + " " + errorThrown);
            window.location.href = baseApp + "/views/subjects";
        }
    });
}

function log_errors(errors) {
    var info = '

';
    errors.forEach(function (error) {
        var errDiv = '
' + error.message + '
';
        info += errDiv;
    });
    info += '

';
    $("#message-board").append(info);
}
<commit_msg>add subject registration template retrieval warning message UI<commit_after>/**
 * Created by bo on 5/12/16.
 */

var template_str;
var loading_html;

$(document).ready(function () {
    loading_html = '

';
    $('#subject-registration-div').append(loading_html);
    next_btn();
    check_new_patients(true);
});

function check_new_patients(toRegisterSite) {
    $('#template_error').remove();

    $.ajax({
        url: baseApp + "/template/get-subject-template",
        type: "GET",
        data: {registerSite: toRegisterSite},
        success: function (template) {
            $('#loading_div').remove();
            template_str = template;
            if (template.length > 1) {
                provide_template_download();
                provide_filled_template_upload();
            }
            else {
                var html = "
Template is empty.
"
                $('#subject-registration-div').append(html);
            }
        },
        error: function (jqXHR, textStatus, errorThrown) {
            console.log(jqXHR.status + " " + textStatus + " " + errorThrown);
            var html = "
The retrieval of template has failed.
"
            $('#subject-registration-div').append(html);
        }
    });
}

function provide_template_download() {
    var info = '
☛ Unregistered subjects are found in the dataset. These subjects should be registered with a "subject registration template", which can be downloaded<button id="download-subject-template-btn" class="btn btn-link btn-lg text-left" style="text-align: left">here</button>

';
    $(info).insertBefore('#subject-back-btn');

    $('#download-subject-template-btn').click(function () {
        var blob = new Blob(template_str, {type: "text/plain;charset=utf-8"});
        saveAs(blob, "subject-registration-template.txt");
    });
}

function provide_filled_template_upload() {
    var html = '
☛ Once you have filled out the template, select it using the file chooser below.
 <form id="upload-subject-template-form" class="form-horizontal"><input id="upload-subject-template-input" type="file" name="uploadPatientData" accept="*" /></form>
';
    $(html).insertBefore('#subject-back-btn');
}

function next_btn() {
    var html = '<button type="button" class="btn btn-primary" id="subject-back-btn">Back</button> ' +
        '<button type="button" class="btn btn-primary" id="subject-next-btn">Next</button>';
    $('#subject-registration-div').append(html);
    $('#subject-back-btn').click(function () {
        window.location.href = baseApp + "/views/feedback-data";
    });

    $('#subject-next-btn').click(function () {
        upload_subjects();
    });

}

function upload_subjects() {
    $('#loading_div').remove();
    $(loading_html).insertAfter('#message-board');
    $('#message-board').empty();
    $.ajax({
        url: baseApp + "/upload/subjects",
        type: "POST",
        data: new FormData($("#upload-subject-template-form")[0]),
        enctype: 'multipart/form-data',
        processData: false,
        contentType: false,
        success: function (fileFormatErrors) {
            if(fileFormatErrors.length == 0) {
                update_submission();
            }
            else{
                log_errors(fileFormatErrors);
            }
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('#loading_div').remove();
            console.log(jqXHR.status + " " + textStatus + " " + errorThrown);
            $('#message-board').append('
Subject upload fails.
')
        }

    });
}

function update_submission() {
    $.ajax({
        url: baseApp + "/submission/update",
        type: "POST",
        data: {step: "feedback-subjects"},
        success: function () {
            $('#loading_div').remove();
            //handle subject file upload
            window.location.href = baseApp + "/views/feedback-subjects";
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('#loading_div').remove();
            console.log(jqXHR.status + " " + textStatus + " " + errorThrown);
            window.location.href = baseApp + "/views/subjects";
        }
    });
}

function log_errors(errors) {
    var info = '

';
    errors.forEach(function (error) {
        var errDiv = '
' + error.message + '
';
        info += errDiv;
    });
    info += '

';
    $("#message-board").append(info);
}
<|endoftext|>


<commit_before> var json = require('json-file'),
   Doc = require('../models/document'),
   User = require('../models/user'),
   Role = require('../models/roles');

 module.exports = {
   user: function() {
     var users;

     // Read users
     users = json.read('./data/users.json');

     // Insert users into the db
     User.collection.insert(users.data, function(err, users) {
       if (err) {
         console.log('======================================');
         console.log(err.message.substring(7, 26).toUpperCase() + ': Users Already created');
       } else {
         console.log('======================================');
         console.log('Users Have been inserted');
       }
     });
   },

   roles: function() {
     var roles;

     // Read roles
     roles = json.read('./data/roles.json');
     // Insert role into the db
     Role.collection.insert(roles.data, function(err, roles) {
       if (err) {
         console.log('======================================');
         console.log(err.message.substring(7, 26).toUpperCase() + ': Roles Already created');
       } else {
         console.log('======================================');
         console.log('Roles have been inserted');
       }
     });
   },

   documents: function() {
     var documents;

     // Read documents
     documents = json.read('./data/documents.json');
     // Insert documents into the db
     for(var key in documents.data) {
      var doc = documents.data[key];
      Doc.create({
        ownerId: doc.ownerId,
        title: doc.title,
        content: doc.content,
        access: doc.access,
        dateCreated: doc.dateCreated
      },
      function(err, documents) {
       if (err) {
         console.log('======================================');
         console.log(err.message.substring(7, 26).toUpperCase() + ': Users Already created');
       } else {
         console.log('======================================');
         console.log('Documents have been inserted');
       }
     });

     }

   }
 };

<commit_msg>seeding the database<commit_after> var json = require('json-file'),
   Doc = require('../models/document'),
   User = require('../models/user'),
   Role = require('../models/roles');

 module.exports = {
   user: function() {
     var users;

     // Read users
     users = json.read('./data/users.json');

     // Insert users into the db
     User.collection.insert(users.data, function(err, users) {
       if (err) {
         console.log('======================================');
         console.log(err.message.substring(7, 26).toUpperCase() + ': Users Already created');
       } else {
         console.log('======================================');
         console.log('Users Have been inserted');
       }
     });
   },

   roles: function() {
     var roles;

     // Read roles
     roles = json.read('./data/roles.json');
     // Insert role into the db
     Role.collection.insert(roles.data, function(err, roles) {
       if (err) {
         console.log('======================================');
         console.log(err.message.substring(7, 26).toUpperCase() + ': Roles Already created');
       } else {
         console.log('======================================');
         console.log('Roles have been inserted');
       }
     });
   },

   documents: function() {
     var documents;

     // Read documents
     documents = json.read('./data/documents.json');
     // Insert documents into the db
     documents.data.forEach(function(doc) {
       Doc.create({
        ownerId: doc.ownerId,
        title: doc.title,
        content: doc.content,
        access: doc.access,
        dateCreated: doc.dateCreated
      },
      function(err, documents) {
       if (err) {
         console.log('======================================');
         console.log(err.message.substring(7, 26).toUpperCase() + ': Users Already created');
       } else {
         console.log('======================================');
         console.log('Documents have been inserted');
       }
     });
     });
   }
 };
<|endoftext|>


<commit_before>/*jshint loopfunc: true */

import Ember from 'ember';
import InboundActions from 'ember-component-inbound-actions/inbound-actions';

/**
    ember-cli-jstree
**/
export default Ember.Component.extend(InboundActions, {
    // Properties for Ember communication
    actionReceiver: null,
    currentNode: null,
    selectedNodes: null,

    // Basic configuration objects
    data: null,
    plugins: null,
    themes: null,
    checkCallback: true,

    // Plugin option objects
    checkboxOptions: null,
    contextmenuOptions: null,
    typesOptions: null,

    selectionDidChange: null,
    treeObject: null,

    didInsertElement: function() {
        var configObject = {};
        var self = this;

        configObject["core"] = {
            "data": this.get('data'),
            "check_callback": this.get('checkCallback')
        };

        var themes = this.get('themes');
        if (themes && typeof themes === "object") {
            configObject["core"]["themes"] = themes;
        }

        var pluginsArray = this.get('plugins');
        if(pluginsArray) {
            pluginsArray = pluginsArray.replace(/ /g, '').split(',');
            configObject["plugins"] = pluginsArray;

            if (pluginsArray.indexOf("contextmenu") !== -1 ||
                pluginsArray.indexOf("dnd") !== -1 ||
                pluginsArray.indexOf("unique") !== -1) {
                // These plugins need core.check_callback
                configObject["core"]["check_callback"] = true;
            }
        }

        var checkboxOptions = this.get('checkboxOptions');
        if(checkboxOptions && pluginsArray.indexOf("checkbox") !== -1) {
            configObject["checkbox"] = checkboxOptions;
        }

        var stateOptions = this.get('stateOptions');
        if(stateOptions && pluginsArray.indexOf("state") !== -1) {
            configObject["checkbox"] = stateOptions;
        }

        var typesOptions = this.get('typesOptions');
        if(typesOptions && pluginsArray.indexOf("types") !== -1) {
            configObject["types"] = typesOptions;
        }

        var contextmenuOptions = this.get('contextmenuOptions');

        // This has eventually got to go. It's terrible.
        if (contextmenuOptions && pluginsArray.indexOf("contextmenu") !== -1) {
            // Remap action hash to functions and don't forget to pass node through
            if (typeof contextmenuOptions["items"] === "object") {
                var newMenuItems = {};
                for (var menuItem in contextmenuOptions["items"]) {
                    if (contextmenuOptions["items"].hasOwnProperty(menuItem)) {
                        // Copy over everything first
                        newMenuItems[menuItem] = contextmenuOptions["items"][menuItem];

                        // Only change it if it's a string. If a function, leave it
                        // This needs to be done so Ember can hijack the action and call it instead
                        if (typeof contextmenuOptions["items"][menuItem]["action"] === "string") {
                            var emberAction = contextmenuOptions["items"][menuItem]["action"];
                            newMenuItems[menuItem]["action"] = function() {
                                Ember.run(self, function() {
                                    var node = this.get('currentNode');
                                    this.send("contextmenuItemDidClick", emberAction, node);
                                });
                            };
                        }
                    }
                }

                // Wrap it up
                contextmenuOptions["items"] = function(node) {
                    Ember.run(self, function() {
                        this.set('currentNode', node);
                    });
                    return newMenuItems;
                };

            }

            // Pass options into the config object
            configObject["contextmenu"] = contextmenuOptions;
        }

        var treeObject = this.$().jstree(configObject);

        /**
            Register all sorts of events
            TODO: This should eventually encompass all of the jsTree events declared
              in their API.
        */

        /**
            Event: init.jstree
            Action: jstreeDidInit
            triggered after all events are bound
        **/
        treeObject.on('init.jstree', function() {
            this.sendAction('eventDidInit');
        }.bind(this));

        /**
            Event: ready.jstree
            Action: jstreeDidBecomeReady
            triggered after all nodes are finished loading
        **/
        treeObject.on('ready.jstree', function() {
            this.sendAction('eventDidBecomeReady');
        }.bind(this));

        /**
            Event: redraw.jstree
            Action: jstreeDidRedraw
            triggered after nodes are redrawn
        **/
        treeObject.on('redraw.jstree', function() {
            this.sendAction('eventDidRedraw');
        }.bind(this));

        /**
            Event: changed.jstree
            Action: jstreeDidChange
            triggered when selection changes
        **/
        treeObject.on('changed.jstree', function (e, data) {
            this.sendAction('eventDidChange', data);

            // Check if selection changed
            if(this.get('treeObject')) {
                var selectionChangedEventNames = ["model", "select_node", "deselect_node", "select_all", "deselect_all"];
                if (data.action && selectionChangedEventNames.indexOf(data.action) !== -1) {
                    var selNodes = Ember.A(this.get('treeObject').jstree(true).get_selected(true));
                    this.set('selectedNodes', selNodes);
                }
            }
        }.bind(this));

        this.set('treeObject', treeObject);
    },

    willDestroyElement: function() {

    },

    getTree: function() {
        var o = this.get('treeObject');
        return o.jstree(true);
    },

    actions: {

        redraw: function() {
            var o = this.get('treeObject');
            var t = o.jstree(true);
            if (null !== t) {
                t.settings.core['data'] = this.get('data');
                t.refresh();
            }
        },

        destroy: function() {
            var o = this.get('treeObject');
            if (null !== o) {
                o.jstree(true).destroy();
            }
        },

        getNode: function(nodeId) {
            if (typeof nodeId !== "string") {
                throw new Error('getNode() requires a node ID to be passed to it to return the node!');
            }

            var o = this.get('treeObject');
            if (null !== o) {
                this.sendAction('actionGetNode', o.jstree(true).get_node(nodeId));
            }
        },

        getContainer: function() {
            var o = this.get('treeObject');
            if (null !== o) {
                this.sendAction('actionGetContainer', o.jstree(true).get_container());
            }
        },

        getParent: function(obj) {
            obj = obj || "#";
            var o = this.get('treeObject');
            if (null !== o) {
                this.sendAction('actionGetParent', o.jstree(true).get_parent(obj));
            }
        },

        contextmenuItemDidClick: function(actionName, node) {
            var tree = this.get('getTree');
            if (undefined !== actionName) {
                this.sendAction(actionName, node, tree);
            }
        }
    }

});
<commit_msg>fixed issue with data binding<commit_after>/*jshint loopfunc: true */

import Ember from 'ember';
import InboundActions from 'ember-component-inbound-actions/inbound-actions';

export default Ember.Component.extend(InboundActions, {
    // Properties for Ember communication
    actionReceiver:       null,
    currentNode:          null,
    selectedNodes:        null,

    // Basic configuration objects
    data:                 null,
    plugins:              null,
    themes:               null,
    checkCallback:        true,

    // Plugin option objects
    checkboxOptions:      null,
    contextmenuOptions:   null,
    typesOptions:         null,

    selectionDidChange:   null,
    treeObject:           null,

    didInsertElement: function() {
        var treeObject = this._setupJsTree();

        this._setupEventHandlers(treeObject);

        this.set('treeObject', treeObject);
    },

    _setupJsTree: function() {
        var configObject = {};
        var self = this;

        configObject["core"] = {
            "data": this.get('data'),
            "check_callback": this.get('checkCallback')
        };

        var themes = this.get('themes');
        if (themes && typeof themes === "object") {
            configObject["core"]["themes"] = themes;
        }

        var pluginsArray = this.get('plugins');
        if(pluginsArray) {
            pluginsArray = pluginsArray.replace(/ /g, '').split(',');
            configObject["plugins"] = pluginsArray;

            if (pluginsArray.indexOf("contextmenu") !== -1 ||
                pluginsArray.indexOf("dnd") !== -1 ||
                pluginsArray.indexOf("unique") !== -1) {
                // These plugins need core.check_callback
                configObject["core"]["check_callback"] = true;
            }

            var checkboxOptions = this.get('checkboxOptions');
            if(checkboxOptions && pluginsArray.indexOf("checkbox") !== -1) {
                configObject["checkbox"] = checkboxOptions;
            }

            var stateOptions = this.get('stateOptions');
            if(stateOptions && pluginsArray.indexOf("state") !== -1) {
                configObject["checkbox"] = stateOptions;
            }

            var typesOptions = this.get('typesOptions');
            if(typesOptions && pluginsArray.indexOf("types") !== -1) {
                configObject["types"] = typesOptions;
            }

            this._setupContextMenus(pluginsArray);
        }

        return this.$().jstree(configObject);
    },

    _setupContextMenus: function() {
        var contextmenuOptions = this.get('contextmenuOptions');

        // This has eventually got to go. It's terrible.
        if (contextmenuOptions && pluginsArray.indexOf("contextmenu") !== -1) {
            // Remap action hash to functions and don't forget to pass node through
            if (typeof contextmenuOptions["items"] === "object") {
                var newMenuItems = {};
                for (var menuItem in contextmenuOptions["items"]) {
                    if (contextmenuOptions["items"].hasOwnProperty(menuItem)) {
                        // Copy over everything first
                        newMenuItems[menuItem] = contextmenuOptions["items"][menuItem];

                        // Only change it if it's a string. If a function, leave it
                        // This needs to be done so Ember can hijack the action and call it instead
                        if (typeof contextmenuOptions["items"][menuItem]["action"] === "string") {
                            var emberAction = contextmenuOptions["items"][menuItem]["action"];
                            newMenuItems[menuItem]["action"] = function() {
                                Ember.run(self, function() {
                                    var node = this.get('currentNode');
                                    this.send("contextmenuItemDidClick", emberAction, node);
                                });
                            };
                        }
                    }
                }

                // Wrap it up
                contextmenuOptions["items"] = function(node) {
                    Ember.run(self, function() {
                        this.set('currentNode', node);
                    });
                    return newMenuItems;
                };

            }

            // Pass options into the config object
            configObject["contextmenu"] = contextmenuOptions;
        }
    },

    /**
     * Register all sorts of events
     * TODO: This should eventually encompass all of the jsTree events declared in their API.
     *
     * @method _setupEventHandlers
     * @param  {Object}
     */
    _setupEventHandlers: function(treeObject) {
        /*
          Event: init.jstree
          Action: jstreeDidInit
          triggered after all events are bound
        */
        treeObject.on('init.jstree', function() {
            this.sendAction('eventDidInit');
        }.bind(this));

        /*
          Event: ready.jstree
          Action: jstreeDidBecomeReady
          triggered after all nodes are finished loading
        */
        treeObject.on('ready.jstree', function() {
            this.sendAction('eventDidBecomeReady');
        }.bind(this));

        /*
          Event: redraw.jstree
          Action: jstreeDidRedraw
          triggered after nodes are redrawn
        */
        treeObject.on('redraw.jstree', function() {
            this.sendAction('eventDidRedraw');
        }.bind(this));

        /*
          Event: changed.jstree
          Action: jstreeDidChange
          triggered when selection changes
        */
        treeObject.on('changed.jstree', function (e, data) {
            this.sendAction('eventDidChange', data);

            // Check if selection changed
            if(this.get('treeObject')) {
                var selectionChangedEventNames = ["model", "select_node", "deselect_node", "select_all", "deselect_all"];
                if (data.action && selectionChangedEventNames.indexOf(data.action) !== -1) {
                    var selNodes = Ember.A(this.get('treeObject').jstree(true).get_selected(true));
                    this.set('selectedNodes', selNodes);
                }
            }
        }.bind(this));
    },

    willDestroyElement: function() {

    },

    _redrawTree: function() {
        var o = this.get('treeObject');
        var t = o.jstree(true);
        if (null !== t) {
            t.settings.core['data'] = this.get('data');
            t.refresh();
        }
    }.observes('data'),

    getTree: function() {
        var o = this.get('treeObject');
        return o.jstree(true);
    },

    actions: {

        redraw: function() {
            this._redrawTree();
        },

        destroy: function() {
            var o = this.get('treeObject');
            if (null !== o) {
                o.jstree(true).destroy();
            }
        },

        getNode: function(nodeId) {
            if (typeof nodeId !== "string") {
                throw new Error('getNode() requires a node ID to be passed to it to return the node!');
            }

            var o = this.get('treeObject');
            if (null !== o) {
                this.sendAction('actionGetNode', o.jstree(true).get_node(nodeId));
            }
        },

        getContainer: function() {
            var o = this.get('treeObject');
            if (null !== o) {
                this.sendAction('actionGetContainer', o.jstree(true).get_container());
            }
        },

        getParent: function(obj) {
            obj = obj || "#";
            var o = this.get('treeObject');
            if (null !== o) {
                this.sendAction('actionGetParent', o.jstree(true).get_parent(obj));
            }
        },

        contextmenuItemDidClick: function(actionName, node) {
            var tree = this.get('getTree');
            if (undefined !== actionName) {
                this.sendAction(actionName, node, tree);
            }
        }
    }

});
<|endoftext|>


<commit_before>import './RedirectionModal.styl'
import React, { useState, useMemo, useEffect } from 'react'
import { FormattedMessage } from 'react-intl'

import Modal from 'react-modal'
import PrefixSetter from '../../components/PrefixSetter'
import cx from 'classnames'
import dropRightWhile from 'lodash/fp/dropRightWhile'
import initial from 'lodash/fp/initial'

import { urlToLru, lruVariations, longestMatching, lruToUrl, lruObjectToString } from '../../utils/lru'

Modal.setAppElement('#root')

const parsePrefixes = (lru, url, newEntity, tldTree) => {
  const urlLru = lruObjectToString(urlToLru(url, tldTree))
  const l = lru.split('|').length
  return dropRightWhile((stem) => stem === 'p:', initial(urlLru.split('|'))).map((stem, index) => {
    const editable = newEntity ? index >= l : index >= l - 1
    return {
      name: stem,
      editable,
      selected: index < l - 1 || newEntity,
    }
  })
}

const MergeReverse = ({
  webentity,
  url,
  tlds,
  originalWebentity,
  onSetPrefixes
}) => {

  const longestLru = useMemo(
    () => longestMatching(webentity.prefixes, url, tlds).lru,
    [webentity.prefixes, url, tlds]
  )
  const prefixes = useMemo(
    () => parsePrefixes(lruObjectToString(longestLru), url, true, tlds),
    [longestLru, url, tlds]
  )

  const initialPrefix = useMemo(
    () => prefixes
      .filter(({ selected }) => selected)
      .reduce((prev, part) => `${prev}${part.name}|`, '')
  )
  const handleSetPrefix = (prefix) => {
    setPrefixUrl(lruToUrl(prefix))
    onSetPrefixes(lruVariations(prefix))
  }

  const [prefixUrl, setPrefixUrl] = useState(lruToUrl(initialPrefix))

  useEffect(() => {
    onSetPrefixes(lruVariations(initialPrefix))
  },[])

  return (

        <FormattedMessage
          id="redirect-modal.step-2-merge-reverse-description"
          values={ {
            webentity: webentity.name,
            originalWebentity: originalWebentity.name,
            url: prefixUrl,
            code: (url) => {url},
            strong: (name) => {name}
          } }
        />

      <PrefixSetter
        parts={ prefixes }
        setPrefix={ handleSetPrefix }
      />

  )
}
const RedirectionModal = ({
  isOpen,
  // onClose,
  mergeRequired,
  tlds,
  onValidateDecision
}) => {
  const { redirectUrl, originalWebentity, redirectWebentity } = mergeRequired

  const [redirectionDecision, onSetRedirectionDecision] = useState(null)
  const [mergeDecision, onSetMergeDecision] = useState(null)
  const [lruPrefixes, setLruPrefixes] = useState(null)

  const handleDeny = () => {
    onSetRedirectionDecision(false)
    onSetMergeDecision(null)
  }

  const handleDecision = () => {
    onValidateDecision({
      redirectionDecision,
      mergeDecision,
      prefixes: lruPrefixes
    })
  }

  return (
    <Modal
      isOpen={ isOpen }
      // onRequestClose={ onClose }
      contentLabel="Redirection modal"
      style={ {
        content: {
          width: 700,
          maxWidth: '90vw',
          position: 'relative',
          top: 0,
          left: 0,
          overflow: 'hidden',
          padding: 0
        }
      } }
    >

<FormattedMessage id="redirect-modal.title" />
            {/*  */}

            <FormattedMessage
              id="redirect-modal.description"
              values={ {
                originalUrl: originalWebentity.tabUrl || originalWebentity.homepage,
                originalWebentity: originalWebentity.name,
                redirectUrl,
                redirectWebentity: redirectWebentity.name,
                code: (url) => {url},
                strong: (name) => {name}
              } }
            />

<FormattedMessage id="redirect-modal.step-1-title" />

<button onClick={ handleDeny } className={ cx('btn', { 'btn-success': redirectionDecision === false }) }><FormattedMessage id="redirect-modal.step-1-refuse" /></button>

<button onClick={ () => onSetRedirectionDecision(true) }  className={ cx('btn', { 'btn-success': redirectionDecision === true }) }><FormattedMessage id="redirect-modal.step-1-accept" /></button>

          {
            redirectionDecision === true &&

<FormattedMessage id="redirect-modal.step-2-title" />

                  <button onClick={ () => onSetMergeDecision('OUT') } className={ cx('btn', { 'btn-success': mergeDecision === 'OUT' }) }>
                    <FormattedMessage
                      id="redirect-modal.step-2-out"
                      values={ {
                        originalWebentity: originalWebentity.name,
                        strong: (name) => {name}
                      } }
                    />
                  </button>

                  <button onClick={ () => onSetMergeDecision('MERGE') } className={ cx('btn', { 'btn-success': mergeDecision === 'MERGE' }) }>
                    <FormattedMessage
                      id="redirect-modal.step-2-merge"
                      values={ {
                        originalWebentity: originalWebentity.name,
                        redirectWebentity: redirectWebentity.name,
                        strong: (name) => {name}
                      } }
                    />
                  </button>

                {longestMatching(redirectWebentity.prefixes, redirectUrl, tlds) &&

                    <button onClick={ () => onSetMergeDecision('MERGE-REVERSE') } className={ cx('btn', { 'btn-success': mergeDecision === 'MERGE-REVERSE' }) }>
                      <FormattedMessage
                        id="redirect-modal.step-2-merge-reverse"
                        values={ {
                          originalWebentity: originalWebentity.name,
                          redirectWebentity: redirectWebentity.name,
                          strong: (name) => {name}
                        } }
                      />
                    </button>

                }

                  <button onClick={ () => onSetMergeDecision('NONE') } className={ cx('btn', { 'btn-success': mergeDecision === 'NONE' }) }>
                    <FormattedMessage
                      id="redirect-modal.step-2-no-action"
                      values={ {
                        strong: (name) => {name}
                      } }
                    />
                  </button>

              {mergeDecision === 'MERGE-REVERSE' &&
                <MergeReverse
                  webentity={ redirectWebentity }
                  originalWebentity={ originalWebentity }
                  url={ redirectUrl }
                  tlds={ tlds }
                  onSetPrefixes={ setLruPrefixes }
                />
              }

          }

            {/*
<button className="btn btn-danger">cancel</button>
 */}

              <button
                onClick={ handleDecision }
                disabled={ redirectionDecision === null || redirectionDecision && !mergeDecision }
                className="btn btn-success">
                <FormattedMessage id="redirect-modal.confirm" />
              </button>

    </Modal>
  )
}

export default RedirectionModal
<commit_msg>reorder merge actions #173<commit_after>import './RedirectionModal.styl'
import React, { useState, useMemo, useEffect } from 'react'
import { FormattedMessage } from 'react-intl'

import Modal from 'react-modal'
import PrefixSetter from '../../components/PrefixSetter'
import cx from 'classnames'
import dropRightWhile from 'lodash/fp/dropRightWhile'
import initial from 'lodash/fp/initial'

import { urlToLru, lruVariations, longestMatching, lruToUrl, lruObjectToString } from '../../utils/lru'

Modal.setAppElement('#root')

const parsePrefixes = (lru, url, newEntity, tldTree) => {
  const urlLru = lruObjectToString(urlToLru(url, tldTree))
  const l = lru.split('|').length
  return dropRightWhile((stem) => stem === 'p:', initial(urlLru.split('|'))).map((stem, index) => {
    const editable = newEntity ? index >= l : index >= l - 1
    return {
      name: stem,
      editable,
      selected: index < l - 1 || newEntity,
    }
  })
}

const MergeReverse = ({
  webentity,
  url,
  tlds,
  originalWebentity,
  onSetPrefixes
}) => {

  const longestLru = useMemo(
    () => longestMatching(webentity.prefixes, url, tlds).lru,
    [webentity.prefixes, url, tlds]
  )
  const prefixes = useMemo(
    () => parsePrefixes(lruObjectToString(longestLru), url, true, tlds),
    [longestLru, url, tlds]
  )

  const initialPrefix = useMemo(
    () => prefixes
      .filter(({ selected }) => selected)
      .reduce((prev, part) => `${prev}${part.name}|`, '')
  )
  const handleSetPrefix = (prefix) => {
    setPrefixUrl(lruToUrl(prefix))
    onSetPrefixes(lruVariations(prefix))
  }

  const [prefixUrl, setPrefixUrl] = useState(lruToUrl(initialPrefix))

  useEffect(() => {
    onSetPrefixes(lruVariations(initialPrefix))
  },[])

  return (

        <FormattedMessage
          id="redirect-modal.step-2-merge-reverse-description"
          values={ {
            webentity: webentity.name,
            originalWebentity: originalWebentity.name,
            url: prefixUrl,
            code: (url) => {url},
            strong: (name) => {name}
          } }
        />

      <PrefixSetter
        parts={ prefixes }
        setPrefix={ handleSetPrefix }
      />

  )
}
const RedirectionModal = ({
  isOpen,
  // onClose,
  mergeRequired,
  tlds,
  onValidateDecision
}) => {
  const { redirectUrl, originalWebentity, redirectWebentity } = mergeRequired

  const [redirectionDecision, onSetRedirectionDecision] = useState(null)
  const [mergeDecision, onSetMergeDecision] = useState(null)
  const [lruPrefixes, setLruPrefixes] = useState(null)

  const handleDeny = () => {
    onSetRedirectionDecision(false)
    onSetMergeDecision(null)
  }

  const handleDecision = () => {
    onValidateDecision({
      redirectionDecision,
      mergeDecision,
      prefixes: lruPrefixes
    })
  }

  return (
    <Modal
      isOpen={ isOpen }
      // onRequestClose={ onClose }
      contentLabel="Redirection modal"
      style={ {
        content: {
          width: 700,
          maxWidth: '90vw',
          position: 'relative',
          top: 0,
          left: 0,
          overflow: 'hidden',
          padding: 0
        }
      } }
    >

<FormattedMessage id="redirect-modal.title" />
            {/*  */}

            <FormattedMessage
              id="redirect-modal.description"
              values={ {
                originalUrl: originalWebentity.tabUrl || originalWebentity.homepage,
                originalWebentity: originalWebentity.name,
                redirectUrl,
                redirectWebentity: redirectWebentity.name,
                code: (url) => {url},
                strong: (name) => {name}
              } }
            />

<FormattedMessage id="redirect-modal.step-1-title" />

<button onClick={ handleDeny } className={ cx('btn', { 'btn-success': redirectionDecision === false }) }><FormattedMessage id="redirect-modal.step-1-refuse" /></button>

<button onClick={ () => onSetRedirectionDecision(true) }  className={ cx('btn', { 'btn-success': redirectionDecision === true }) }><FormattedMessage id="redirect-modal.step-1-accept" /></button>

          {
            redirectionDecision === true &&

<FormattedMessage id="redirect-modal.step-2-title" />

                  <button onClick={ () => onSetMergeDecision('MERGE') } className={ cx('btn', { 'btn-success': mergeDecision === 'MERGE' }) }>
                    <FormattedMessage
                      id="redirect-modal.step-2-merge"
                      values={ {
                        originalWebentity: originalWebentity.name,
                        redirectWebentity: redirectWebentity.name,
                        strong: (name) => {name}
                      } }
                    />
                  </button>

                {longestMatching(redirectWebentity.prefixes, redirectUrl, tlds) &&

                    <button onClick={ () => onSetMergeDecision('MERGE-REVERSE') } className={ cx('btn', { 'btn-success': mergeDecision === 'MERGE-REVERSE' }) }>
                      <FormattedMessage
                        id="redirect-modal.step-2-merge-reverse"
                        values={ {
                          originalWebentity: originalWebentity.name,
                          redirectWebentity: redirectWebentity.name,
                          strong: (name) => {name}
                        } }
                      />
                    </button>

                }

                  <button onClick={ () => onSetMergeDecision('OUT') } className={ cx('btn', { 'btn-success': mergeDecision === 'OUT' }) }>
                    <FormattedMessage
                      id="redirect-modal.step-2-out"
                      values={ {
                        originalWebentity: originalWebentity.name,
                        strong: (name) => {name}
                      } }
                    />
                  </button>

                  <button onClick={ () => onSetMergeDecision('NONE') } className={ cx('btn', { 'btn-success': mergeDecision === 'NONE' }) }>
                    <FormattedMessage
                      id="redirect-modal.step-2-no-action"
                      values={ {
                        strong: (name) => {name}
                      } }
                    />
                  </button>

              {mergeDecision === 'MERGE-REVERSE' &&
                <MergeReverse
                  webentity={ redirectWebentity }
                  originalWebentity={ originalWebentity }
                  url={ redirectUrl }
                  tlds={ tlds }
                  onSetPrefixes={ setLruPrefixes }
                />
              }

          }

            {/*
<button className="btn btn-danger">cancel</button>
 */}

              <button
                onClick={ handleDecision }
                disabled={ redirectionDecision === null || redirectionDecision && !mergeDecision }
                className="btn btn-success">
                <FormattedMessage id="redirect-modal.confirm" />
              </button>

    </Modal>
  )
}

export default RedirectionModal
<|endoftext|>