<commit_before>import { TRIPLE, INTERPOLATOR, COMMENT, SECTION, CLOSING, PARTIAL, REFERENCE } from 'config/types';
import mustacheType from './type';
import handlebarsBlockCodes from './handlebarsBlockCodes';
import refineExpression from 'parse/utils/refineExpression';
import readExpression from 'parse/converters/readExpression';
import 'legacy';

var indexRefPattern = /^\s*:\s*([a-zA-Z_$][a-zA-Z_$0-9]*)/,
	keyIndexRefPattern = /^\s*,\s*([a-zA-Z_$][a-zA-Z_$0-9]*)/,
	handlebarsBlockPattern = new RegExp( '^(' + Object.keys( handlebarsBlockCodes ).join( '|' ) + ')\\b' ),
	legalReference;

legalReference = /^[a-zA-Z$_0-9]+(?:(\.[a-zA-Z$_0-9]+)|(\[[a-zA-Z$_0-9]+\]))*$/;

export default function readDelimiterChange ( parser, delimiterType ) {
	var start, pos, mustache, type, block, expression, i, remaining, index, delimiters, relaxed;

	start = parser.pos;

	mustache = {};

	delimiters = parser[ delimiterType.delimiters ];

	if ( delimiterType.isStatic ) {
		mustache.s = true;
	}

	// Determine mustache type
	if ( delimiterType.isTriple ) {
		mustache.t = TRIPLE;
	} else {
		// We need to test for expressions before we test for mustache type, because
		// an expression that begins '!' looks a lot like a comment
		if ( parser.remaining()[0] === '!' ) {
			try {
				expression = readExpression( parser );

				// Was it actually an expression, or a comment block in disguise?
				parser.allowWhitespace();
				if ( parser.remaining().indexOf( delimiters[1] ) ) {
					expression = null;
				} else {
					mustache.t = INTERPOLATOR;
				}
			} catch ( err ) {}

			if ( !expression ) {
				index = parser.remaining().indexOf( delimiters[1] );

				if ( ~index ) {
					parser.pos += index;
				} else {
					parser.error( 'Expected closing delimiter (\'' + delimiters[1] + '\')' );
				}

				return {
					t: COMMENT
				};
			}
		}

		if ( !expression ) {
			type = mustacheType( parser );

			mustache.t = type || INTERPOLATOR; // default

			// See if there's an explicit section type e.g. {{#with}}...{{/with}}
			if ( type === SECTION ) {
				if ( block = parser.matchPattern( handlebarsBlockPattern ) ) {
					mustache.n = block;
				}

				parser.allowWhitespace();
			}

			// if it's a comment or a section closer, allow any contents except '}}'
			else if ( type === COMMENT || type === CLOSING ) {
				remaining = parser.remaining();
				index = remaining.indexOf( delimiters[1] );

				if ( index !== -1 ) {
					mustache.r = remaining.substr( 0, index ).split( ' ' )[0];
					parser.pos += index;
					return mustache;
				}
			}
		}
	}

	if ( !expression ) {
		// allow whitespace
		parser.allowWhitespace();

		// if this is a partial, we can relax the naming requirements for the expression
		if ( type === PARTIAL ) {
			relaxed = parser.relaxedNames;
			parser.relaxedNames = true;
			expression = readExpression( parser );
			parser.relaxedNames = relaxed;
		}

		// look for named yields
		else if ( mustache.t === INTERPOLATOR && parser.matchString( 'yield ' ) ) {
			parser.allowWhitespace();
			mustache.r = 'yield';
			relaxed = parser.relaxedNames;
			parser.relaxedNames = true;
			expression = readExpression( parser );
			parser.relaxedNames = false;

			if ( expression && expression.t === REFERENCE ) {
				mustache.yn = expression.n;
				expression = null;
			} else if ( expression ) {
				parser.error( 'Only names are supported with yield.' );
			}
		}

		// relax naming for inline partial section
		else if ( mustache.t === SECTION && mustache.n === 'partial' ) {
			relaxed = parser.relaxedNames;
			parser.relaxedNames = true;
			expression = readExpression( parser );
			parser.relaxedNames = false;
		}

		// otherwise, just get an expression
		else {
			// get expression
			expression = readExpression( parser );
		}

		// If this is a partial, it may have a context (e.g. `{{>item foo}}`). These
		// cases involve a bit of a hack - we want to turn it into the equivalent of
		// `{{#with foo}}{{>item}}{{/with}}`, but to get there we temporarily append
		// a 'contextPartialExpression' to the mustache, and process the context instead of
		// the reference
		let temp;
		if ( mustache.t === PARTIAL && expression && ( temp = readExpression( parser ) ) ) {
			mustache = {
				contextPartialExpression: expression
			};

			expression = temp;
		}

		// With certain valid references that aren't valid expressions,
		// e.g. {{1.foo}}, we have a problem: it looks like we've got an
		// expression, but the expression didn't consume the entire
		// reference. So we need to check that the mustache delimiters
		// appear next, unless there's an index reference (i.e. a colon)
		remaining = parser.remaining();

		if ( ( remaining.substr( 0, delimiters[1].length ) !== delimiters[1] ) && ( remaining.charAt( 0 ) !== ':' ) ) {
			pos = parser.pos;
			parser.pos = start;

			remaining = parser.remaining();
			index = remaining.indexOf( delimiters[1] );

			if ( index !== -1 ) {
				mustache.r = remaining.substr( 0, index ).trim();

				// Check it's a legal reference
				if ( !legalReference.test( mustache.r ) ) {
					parser.error( 'Expected a legal Mustache reference' );
				}

				parser.pos += index;
				return mustache;
			}

			parser.pos = pos; // reset, so we get more informative error messages
		}
	}

	refineExpression( expression, mustache );

	// if there was context, process the expression now and save it for later
	if ( mustache.contextPartialExpression ) {
		mustache.contextPartialExpression = [
			refineExpression( mustache.contextPartialExpression, { t: PARTIAL } )
		];
	}

	// optional index and key references
	if ( i = parser.matchPattern( indexRefPattern ) ) {
		let extra;

		if ( extra = parser.matchPattern( keyIndexRefPattern ) ) {
			mustache.i = i + ',' + extra;
		} else {
			mustache.i = i;
		}
	}

	return mustache;
}
<commit_msg>use parser.nextChar() method<commit_after>import { TRIPLE, INTERPOLATOR, COMMENT, SECTION, CLOSING, PARTIAL, REFERENCE } from 'config/types';
import mustacheType from './type';
import handlebarsBlockCodes from './handlebarsBlockCodes';
import refineExpression from 'parse/utils/refineExpression';
import readExpression from 'parse/converters/readExpression';
import 'legacy';

var indexRefPattern = /^\s*:\s*([a-zA-Z_$][a-zA-Z_$0-9]*)/,
	keyIndexRefPattern = /^\s*,\s*([a-zA-Z_$][a-zA-Z_$0-9]*)/,
	handlebarsBlockPattern = new RegExp( '^(' + Object.keys( handlebarsBlockCodes ).join( '|' ) + ')\\b' ),
	legalReference;

legalReference = /^[a-zA-Z$_0-9]+(?:(\.[a-zA-Z$_0-9]+)|(\[[a-zA-Z$_0-9]+\]))*$/;

export default function readDelimiterChange ( parser, delimiterType ) {
	var start, pos, mustache, type, block, expression, i, remaining, index, delimiters, relaxed;

	start = parser.pos;

	mustache = {};

	delimiters = parser[ delimiterType.delimiters ];

	if ( delimiterType.isStatic ) {
		mustache.s = true;
	}

	// Determine mustache type
	if ( delimiterType.isTriple ) {
		mustache.t = TRIPLE;
	} else {
		// We need to test for expressions before we test for mustache type, because
		// an expression that begins '!' looks a lot like a comment
		if ( parser.nextChar() === '!' ) {
			try {
				expression = readExpression( parser );

				// Was it actually an expression, or a comment block in disguise?
				parser.allowWhitespace();
				if ( parser.remaining().indexOf( delimiters[1] ) ) {
					expression = null;
				} else {
					mustache.t = INTERPOLATOR;
				}
			} catch ( err ) {}

			if ( !expression ) {
				index = parser.remaining().indexOf( delimiters[1] );

				if ( ~index ) {
					parser.pos += index;
				} else {
					parser.error( 'Expected closing delimiter (\'' + delimiters[1] + '\')' );
				}

				return {
					t: COMMENT
				};
			}
		}

		if ( !expression ) {
			type = mustacheType( parser );

			mustache.t = type || INTERPOLATOR; // default

			// See if there's an explicit section type e.g. {{#with}}...{{/with}}
			if ( type === SECTION ) {
				if ( block = parser.matchPattern( handlebarsBlockPattern ) ) {
					mustache.n = block;
				}

				parser.allowWhitespace();
			}

			// if it's a comment or a section closer, allow any contents except '}}'
			else if ( type === COMMENT || type === CLOSING ) {
				remaining = parser.remaining();
				index = remaining.indexOf( delimiters[1] );

				if ( index !== -1 ) {
					mustache.r = remaining.substr( 0, index ).split( ' ' )[0];
					parser.pos += index;
					return mustache;
				}
			}
		}
	}

	if ( !expression ) {
		// allow whitespace
		parser.allowWhitespace();

		// if this is a partial, we can relax the naming requirements for the expression
		if ( type === PARTIAL ) {
			relaxed = parser.relaxedNames;
			parser.relaxedNames = true;
			expression = readExpression( parser );
			parser.relaxedNames = relaxed;
		}

		// look for named yields
		else if ( mustache.t === INTERPOLATOR && parser.matchString( 'yield ' ) ) {
			parser.allowWhitespace();
			mustache.r = 'yield';
			relaxed = parser.relaxedNames;
			parser.relaxedNames = true;
			expression = readExpression( parser );
			parser.relaxedNames = false;

			if ( expression && expression.t === REFERENCE ) {
				mustache.yn = expression.n;
				expression = null;
			} else if ( expression ) {
				parser.error( 'Only names are supported with yield.' );
			}
		}

		// relax naming for inline partial section
		else if ( mustache.t === SECTION && mustache.n === 'partial' ) {
			relaxed = parser.relaxedNames;
			parser.relaxedNames = true;
			expression = readExpression( parser );
			parser.relaxedNames = false;
		}

		// otherwise, just get an expression
		else {
			// get expression
			expression = readExpression( parser );
		}

		// If this is a partial, it may have a context (e.g. `{{>item foo}}`). These
		// cases involve a bit of a hack - we want to turn it into the equivalent of
		// `{{#with foo}}{{>item}}{{/with}}`, but to get there we temporarily append
		// a 'contextPartialExpression' to the mustache, and process the context instead of
		// the reference
		let temp;
		if ( mustache.t === PARTIAL && expression && ( temp = readExpression( parser ) ) ) {
			mustache = {
				contextPartialExpression: expression
			};

			expression = temp;
		}

		// With certain valid references that aren't valid expressions,
		// e.g. {{1.foo}}, we have a problem: it looks like we've got an
		// expression, but the expression didn't consume the entire
		// reference. So we need to check that the mustache delimiters
		// appear next, unless there's an index reference (i.e. a colon)
		remaining = parser.remaining();

		if ( ( remaining.substr( 0, delimiters[1].length ) !== delimiters[1] ) && ( remaining.charAt( 0 ) !== ':' ) ) {
			pos = parser.pos;
			parser.pos = start;

			remaining = parser.remaining();
			index = remaining.indexOf( delimiters[1] );

			if ( index !== -1 ) {
				mustache.r = remaining.substr( 0, index ).trim();

				// Check it's a legal reference
				if ( !legalReference.test( mustache.r ) ) {
					parser.error( 'Expected a legal Mustache reference' );
				}

				parser.pos += index;
				return mustache;
			}

			parser.pos = pos; // reset, so we get more informative error messages
		}
	}

	refineExpression( expression, mustache );

	// if there was context, process the expression now and save it for later
	if ( mustache.contextPartialExpression ) {
		mustache.contextPartialExpression = [
			refineExpression( mustache.contextPartialExpression, { t: PARTIAL } )
		];
	}

	// optional index and key references
	if ( i = parser.matchPattern( indexRefPattern ) ) {
		let extra;

		if ( extra = parser.matchPattern( keyIndexRefPattern ) ) {
			mustache.i = i + ',' + extra;
		} else {
			mustache.i = i;
		}
	}

	return mustache;
}
<|endoftext|>


<commit_before>import log from 'utils/log';
import config from 'config/config';
import parser from 'config/options/template/parser';
import deIndent from 'virtualdom/items/Partial/deIndent';

export default function getPartialDescriptor ( ractive, name ) {
	var partial;

	// If the partial in instance or view heirarchy instances, great
	if ( partial = getPartialFromRegistry( ractive, name ) ) {
		return partial;
	}

	// Does it exist on the page as a script tag?
	partial = parser.fromId( name, { noThrow: true } );

	if ( partial ) {
		// is this necessary?
		partial = deIndent( partial );

		// parse and register to this ractive instance
		let parsed = parser.parse( partial, parser.getParseOptions( ractive ) );

		// register (and return main partial if there are others in the template)
		return ractive.partials[ name ] = parsed.t;
	}

	log.error({
		debug: ractive.debug,
		message: 'noTemplateForPartial',
		args: { name: name }
	});

	// No match? Return an empty array
	return [];

}

function getPartialFromRegistry ( ractive, name ) {

	var partials = config.registries.partials;

	// find first instance in the ractive or view hierarchy that has this partial
	// TODO is this necessary, with prototypal inheritance (and item-level rather
	// than registry-level option functions)?
	var instance = partials.findInstance( ractive, name );

	if ( !instance ) { return; }

	let partial = instance.partials[ name ], fn;

	// partial is a function?
	if ( typeof partial === 'function' ) {
		fn = partial.bind( instance );
		fn.isOwner = instance.partials.hasOwnProperty(name);
		partial = fn( instance.data );
	}

	if ( !partial ) {
		log.warn({
			debug: ractive.debug,
			message: 'noRegistryFunctionReturn',
			args: { registry: 'partial', name: name }
		});
		return;
	}

	// If this was added manually to the registry,
	// but hasn't been parsed, parse it now
	if ( !parser.isParsed( partial ) ) {

		// use the parseOptions of the ractive instance on which it was found
		let parsed = parser.parse( partial, parser.getParseOptions( instance ) );

		// Partials cannot contain nested partials!
		// TODO add a test for this
		if ( parsed.p ) {
			log.warn({
				debug: ractive.debug,
				message: 'noNestedPartials',
				args: { rname: name }
			});
		}

		// if fn, use instance to store result, otherwise needs to go
		// in the correct point in prototype chain on instance or constructor
		let target = fn ? instance : partials.findOwner( instance, name );

		// may be a template with partials, which need to be registered and main template extracted
		target.partials[ name ] = partial = parsed.t;
	}

	// store for reset
	if ( fn ) {
		partial._fn = fn;
	}

	return partial;

}
<commit_msg>remove TODO<commit_after>import log from 'utils/log';
import config from 'config/config';
import parser from 'config/options/template/parser';
import deIndent from 'virtualdom/items/Partial/deIndent';

export default function getPartialDescriptor ( ractive, name ) {
	var partial;

	// If the partial in instance or view heirarchy instances, great
	if ( partial = getPartialFromRegistry( ractive, name ) ) {
		return partial;
	}

	// Does it exist on the page as a script tag?
	partial = parser.fromId( name, { noThrow: true } );

	if ( partial ) {
		// is this necessary?
		partial = deIndent( partial );

		// parse and register to this ractive instance
		let parsed = parser.parse( partial, parser.getParseOptions( ractive ) );

		// register (and return main partial if there are others in the template)
		return ractive.partials[ name ] = parsed.t;
	}

	log.error({
		debug: ractive.debug,
		message: 'noTemplateForPartial',
		args: { name: name }
	});

	// No match? Return an empty array
	return [];

}

function getPartialFromRegistry ( ractive, name ) {

	var partials = config.registries.partials;

	// find first instance in the ractive or view hierarchy that has this partial
	var instance = partials.findInstance( ractive, name );

	if ( !instance ) { return; }

	let partial = instance.partials[ name ], fn;

	// partial is a function?
	if ( typeof partial === 'function' ) {
		fn = partial.bind( instance );
		fn.isOwner = instance.partials.hasOwnProperty(name);
		partial = fn( instance.data );
	}

	if ( !partial ) {
		log.warn({
			debug: ractive.debug,
			message: 'noRegistryFunctionReturn',
			args: { registry: 'partial', name: name }
		});
		return;
	}

	// If this was added manually to the registry,
	// but hasn't been parsed, parse it now
	if ( !parser.isParsed( partial ) ) {

		// use the parseOptions of the ractive instance on which it was found
		let parsed = parser.parse( partial, parser.getParseOptions( instance ) );

		// Partials cannot contain nested partials!
		// TODO add a test for this
		if ( parsed.p ) {
			log.warn({
				debug: ractive.debug,
				message: 'noNestedPartials',
				args: { rname: name }
			});
		}

		// if fn, use instance to store result, otherwise needs to go
		// in the correct point in prototype chain on instance or constructor
		let target = fn ? instance : partials.findOwner( instance, name );

		// may be a template with partials, which need to be registered and main template extracted
		target.partials[ name ] = partial = parsed.t;
	}

	// store for reset
	if ( fn ) {
		partial._fn = fn;
	}

	return partial;

}
<|endoftext|>


<commit_before>'use strict';

function globalModule_Try(moduleString) {
	try {
		return require(moduleString);
	} catch (exception) {
		console.log("FAILED TO LOAD: \"" + moduleString + "\"");
		console.log(exception);
		return null;
	}
}

function dump_debug_string(string) {
	var fileSystem_Module = globalModule_Try('fs');
	var inHouseFileHandle = fileSystem_Module.openSync("./local_debug_dump.txt", 'a');
	fileSystem_Module.writeSync(inHouseFileHandle, string);
	fileSystem_Module.closeSync(inHouseFileHandle);
}

function message_locator_service(mainMessage) {
	var path_Module = globalModule_Try('path');
	var stackTrace_Module = globalModule_Try('stack-trace');
	var currentFrame = stackTrace_Module.get()[1];
	console.log(mainMessage + " >>> \"" + path_Module.basename(currentFrame.getFileName()) + ":" +
	    currentFrame.getLineNumber() + "\"\n");
}

function spot_the_head(htmlLineArray) {
	var headAreaMark_Array = [ -1, -1 ];
	var headMark_RegExp = new RegExp("<\\s*\\/?\\s*head\\s*>", "i");
	for (var i = 0; i < htmlLineArray.length; i++) {
		if (headMark_RegExp.exec(htmlLineArray[i]) !== null) {
			if (headAreaMark_Array[0] === -1) {
				headAreaMark_Array[0] = i;
			} else {
				headAreaMark_Array[1] = i;
				break;
			}
		}
	}
	if (headAreaMark_Array[0] === -1 || headAreaMark_Array[1] === -1) {
		message_locator_service("HEAD AREA BOUNDRIES BUGGY OR NOT FOUND AT ALL...!");
		return false;
	} else {
		return headAreaMark_Array;
	}
}

function carriage_return_needed() {
	var os_Module = globalModule_Try('os');
	var windowsSpotter_RegExp = new RegExp("windows", "i");
	if (windowsSpotter_RegExp.exec(os_Module.type()) !== null) {
		return true;
	} else {
		return false;
	}
}

function end_of_line_clean_save(fileName, array, carriageReturn) {
	var carriageReturnString = "";
	if (carriageReturn) {
		carriageReturnString = "\r";
	}
	var fileSystem_Module = globalModule_Try('fs');
	var currentFileHandle = fileSystem_Module.openSync(fileName, 'w');

	var lineSpotter_RegExp = new RegExp("^([\\x20\\x09]*)(.*)\\x0d*$", "i");
	var initialLineResultArray = lineSpotter_RegExp.exec(array[0]);
	if (initialLineResultArray !== null) {
		if (initialLineResultArray[2]) {
			fileSystem_Module.writeSync(currentFileHandle, initialLineResultArray[1] + initialLineResultArray[2] +
			    carriageReturnString + "\n");
		}
	} else {
		message_locator_service("MISSED THE INITIAL LINE...!");
		return false;
	}
	for (var j = 1; j < (array.length - 1); j++) {
		var lineResultArray = lineSpotter_RegExp.exec(array[j]);
		if (lineResultArray !== null) {
			if (j === (array.length - 2)) {
				var nextToLast_ResultArray = lineSpotter_RegExp.exec(array[array.length - 1]);
				if (!nextToLast_ResultArray[2]) {
					fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2]);
				} else {
					fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2] + carriageReturnString +
					    "\n");
				}
			} else {
				fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2] + carriageReturnString +
				    "\n");
			}
		} else {
			message_locator_service("MISSED A LINE...!");
			return false;
		}
	}
	var finalLineResultArray = lineSpotter_RegExp.exec(array[array.length - 1]);
	if (finalLineResultArray !== null) {
		if (finalLineResultArray[2]) {
			fileSystem_Module.writeSync(currentFileHandle, finalLineResultArray[1] + finalLineResultArray[2]);
		}
	} else {
		message_locator_service("MISSED THE FINAL LINE...!");
		return false;
	}
	fileSystem_Module.closeSync(currentFileHandle);
	return true;
}

function array_from_file_delete(entire_fileName) {
	var fileSystem_Module = globalModule_Try('fs');
	if (fileSystem_Module.existsSync(entire_fileName)) {
		var targetFile_LineArray = fileSystem_Module.readFileSync(entire_fileName, 'utf8', 'r').toString().split('\n');
		fileSystem_Module.unlinkSync(entire_fileName);
		return targetFile_LineArray;
	} else {
		message_locator_service("TARGET FILE DOES NOT EXIST...!");
		return false;
	}
}

function array_from_file(entire_fileName) {
	var fileSystem_Module = globalModule_Try('fs');
	if (fileSystem_Module.existsSync(entire_fileName)) {
		var targetFile_LineArray = fileSystem_Module.readFileSync(entire_fileName, 'utf8', 'r').toString().split('\n');
		return targetFile_LineArray;
	} else {
		message_locator_service("TARGET FILE DOES NOT EXIST...!");
		return false;
	}
}

// Switching html head area to minified targets...
function toMin(headStart, headEnd, carriageReturn, contentArray) {
	var changed = false;
	var hasMin_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)(?:\\.min)+(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	var carelessAboutMin_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	for (var i = (headStart + 1); i < headEnd; i++) {
		if (hasMin_RegExp.exec(contentArray[i]) === null) {
			var regExp_ResultArray = carelessAboutMin_RegExp.exec(contentArray[i]);
			if (regExp_ResultArray !== null) {
				contentArray[i] = regExp_ResultArray[1] + ".min" + regExp_ResultArray[2] + carriageReturn;
				if (!changed) {
					changed = true;
				}
			}
		}
	}
	if (changed) {
		return contentArray;
	} else {
		return false;
	}
}

// Switching html head area to regular targets...
function toRegular(headStart, headEnd, carriageReturn, contentArray) {
	var changed = false;
	var minSuspect_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)\\.min(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	for (var i = (headStart + 1); i < headEnd; i++) {
		var regExp_ResultArray = minSuspect_RegExp.exec(contentArray[i]);
		if (regExp_ResultArray !== null) {
			contentArray[i] = regExp_ResultArray[1] + regExp_ResultArray[2] + carriageReturn;
			if (!changed) {
				changed = true;
			}
		}
	}
	if (changed) {
		return contentArray;
	} else {
		return false;
	}
}

function delete_writingArray_ToFile(fileName, array) {
	var fileSystem_Module = globalModule_Try('fs');
	if (fileSystem_Module.existsSync(fileName)) {
		fileSystem_Module.unlinkSync(fileName);
	}
	var inHouseFileHandle = fileSystem_Module.openSync(fileName, 'w');
	for (var i = 0; i < (array.length - 1); i++) {
		fileSystem_Module.writeSync(inHouseFileHandle, array[i] + "\n");
	}
	if (array[array.length - 1]) {
		fileSystem_Module.writeSync(inHouseFileHandle, array[array.length - 1]);
	}
	fileSystem_Module.closeSync(inHouseFileHandle);
}

module.exports = {
  casual__options__servant : function(options_object, option_request) {
	  var top_level_options_reference_object = {
	    action : [ 'switch', 'clean' ],
	    chattiness : [ 'true', 'false' ],
	    direction : [ 'min', 'regular' ],
	    file_source : [ 'wildcard', 'list' ],
	  };
	  for ( var item in options_object) {
		  if (item === option_request) {

			  if (top_level_options_reference_object[item].includes(item)) {

			  } else {

			  }
		  } else {

		  }
	  }
  },

  add_on_options__servant : function(global_object) {
	  var noisy = true;
	  var global_options_object = global_object.data.options;
	  var global_add_on_options_object = {
		  chattiness : [ 'true', 'false' ]
	  };
	  if (global_options_object !== undefined) {
		  if (noisy) {
			  console.log(">>> Options section found... Doing further checking... <<<");
		  }
		  for ( var item in global_add_on_options_object) {
			  if (global_options_object.hasOwnProperty(item)) {
				  var contains_valid_value = false;
				  for (var i = 0; i < global_add_on_options_object[item].length; i++) {
					  if (global_add_on_options_object[item].includes(global_options_object[item])) {
						  contains_valid_value = true;
						  break;
					  }
				  }
				  if (!contains_valid_value) {
					  console.log("\"" + global_options_object[item] + "\" IS NOT A VALID OPTION WITH \"" + item + "\" ...!");
					  return false;
				  }
			  } else {
				  if (noisy) {
					  console.log("MISSING OBJECTS OPTIONS PROPERTY: \"" + item + "\" ...!");
				  }
				  return false;
			  }
		  }
		  return true;
	  } else {
		  console.log(">>> NO VALID OPTIONS SECTION FOUND...! <<<");
		  return false;
	  }
  },

  private_action_checker : function(global_object, reference_object, noisy) {
	  var global_options_object = global_object.data.options;
	  if (global_options_object !== undefined) {
		  if (noisy) {
			  console.log(">>> Options section found... Doing further checking... <<<");
		  }
		  for ( var item in reference_object) {
			  if (global_options_object.hasOwnProperty(item)) {
				  var contains_valid_value = false;
				  for (var i = 0; i < reference_object[item].length; i++) {
					  if (reference_object[item].includes(global_options_object[item])) {
						  contains_valid_value = true;
						  break;
					  }
				  }
				  if (!contains_valid_value) {
					  console.log("\"" + global_options_object[item] + "\" IS NOT A VALID OPTION WITH \"" + item + "\" ...!");
					  return false;
				  }
			  } else {
				  if (noisy) {
					  console.log("MISSING OBJECTS OPTIONS PROPERTY: \"" + item + "\" ...!");
				  }
				  return false;
			  }
		  }
		  return true;
	  } else {
		  console.log(">>> NO VALID OPTIONS SECTION FOUND...! <<<");
		  return false;
	  }
  },

  process_wildcard_input : function(source, directory) {
	  var wildcard_extractor_RegExp = new RegExp("^\\*(.+)$");
	  var result_array = wildcard_extractor_RegExp.exec(source);
	  var final_files_array = [];
	  if (result_array) {
		  var tail_string = result_array[1];
		  var prepared_tail = tail_string.replace(/\./ig, "\\.");
		  var wildcard_RegExp = new RegExp("^(.+" + prepared_tail + ")$", "i");
		  var fileSystem_Module = globalModule_Try('fs');
		  var raw_file_array = fileSystem_Module.readdirSync(directory);
		  var targets_file_array = [];
		  for (var i = 0; i < raw_file_array.length; i++) {
			  var single_file_result_array = wildcard_RegExp.exec(raw_file_array[i]);
			  if (single_file_result_array) {
				  final_files_array.push(directory + single_file_result_array[1]);
			  }
		  }
		  return final_files_array;
	  } else {
		  message_locator_service("NO VALID WILDCARD FOUND...!");
		  return false;
	  }
  },

  toggle_all_head_links : function(direction, file) {
	  var pointToMin = false;
	  if (direction === 'min') {
		  pointToMin = true;
	  }
	  var targetFile_LineArray = array_from_file(file);
	  if (targetFile_LineArray) {
		  var windowsNeeded_carriageReturn = "";
		  if (carriage_return_needed) {
			  windowsNeeded_carriageReturn = "\r";
		  }
		  var headStart = spot_the_head(targetFile_LineArray)[0];
		  var headEnd = spot_the_head(targetFile_LineArray)[1];

		  // Actual array manipulation...
		  if (pointToMin) {
			  targetFile_LineArray = toMin(headStart, headEnd, windowsNeeded_carriageReturn, targetFile_LineArray);
			  if (targetFile_LineArray) {
				  delete_writingArray_ToFile(file, targetFile_LineArray);
				  return true;
			  } else {
				  return true;
			  }
		  } else {
			  targetFile_LineArray = toRegular(headStart, headEnd, windowsNeeded_carriageReturn, targetFile_LineArray);
			  if (targetFile_LineArray) {
				  delete_writingArray_ToFile(file, targetFile_LineArray);
				  return true;
			  } else {
				  return true;
			  }
		  }
	  } else {
		  message_locator_service("FAILED TO GET VALID DATA ARRAY...!");
		  return false;
	  }
  },

  end_of_line_refresh : function(file) {
	  var targetFile_LineArray = array_from_file_delete(file);
	  if (targetFile_LineArray) {
		  return end_of_line_clean_save(file, targetFile_LineArray, carriage_return_needed());
	  } else {
		  message_locator_service("FAILED TO GET VALID DATA ARRAY...!");
		  return false;
	  }
  }
};
<commit_msg>Removed one line... - MH - PT<commit_after>'use strict';

function globalModule_Try(moduleString) {
	try {
		return require(moduleString);
	} catch (exception) {
		console.log("FAILED TO LOAD: \"" + moduleString + "\"");
		console.log(exception);
		return null;
	}
}

function dump_debug_string(string) {
	var fileSystem_Module = globalModule_Try('fs');
	var inHouseFileHandle = fileSystem_Module.openSync("./local_debug_dump.txt", 'a');
	fileSystem_Module.writeSync(inHouseFileHandle, string);
	fileSystem_Module.closeSync(inHouseFileHandle);
}

function message_locator_service(mainMessage) {
	var path_Module = globalModule_Try('path');
	var stackTrace_Module = globalModule_Try('stack-trace');
	var currentFrame = stackTrace_Module.get()[1];
	console.log(mainMessage + " >>> \"" + path_Module.basename(currentFrame.getFileName()) + ":" +
	    currentFrame.getLineNumber() + "\"\n");
}

function spot_the_head(htmlLineArray) {
	var headAreaMark_Array = [ -1, -1 ];
	var headMark_RegExp = new RegExp("<\\s*\\/?\\s*head\\s*>", "i");
	for (var i = 0; i < htmlLineArray.length; i++) {
		if (headMark_RegExp.exec(htmlLineArray[i]) !== null) {
			if (headAreaMark_Array[0] === -1) {
				headAreaMark_Array[0] = i;
			} else {
				headAreaMark_Array[1] = i;
				break;
			}
		}
	}
	if (headAreaMark_Array[0] === -1 || headAreaMark_Array[1] === -1) {
		message_locator_service("HEAD AREA BOUNDRIES BUGGY OR NOT FOUND AT ALL...!");
		return false;
	} else {
		return headAreaMark_Array;
	}
}

function carriage_return_needed() {
	var os_Module = globalModule_Try('os');
	var windowsSpotter_RegExp = new RegExp("windows", "i");
	if (windowsSpotter_RegExp.exec(os_Module.type()) !== null) {
		return true;
	} else {
		return false;
	}
}

function end_of_line_clean_save(fileName, array, carriageReturn) {
	var carriageReturnString = "";
	if (carriageReturn) {
		carriageReturnString = "\r";
	}
	var fileSystem_Module = globalModule_Try('fs');
	var currentFileHandle = fileSystem_Module.openSync(fileName, 'w');

	var lineSpotter_RegExp = new RegExp("^([\\x20\\x09]*)(.*)\\x0d*$", "i");
	var initialLineResultArray = lineSpotter_RegExp.exec(array[0]);
	if (initialLineResultArray !== null) {
		if (initialLineResultArray[2]) {
			fileSystem_Module.writeSync(currentFileHandle, initialLineResultArray[1] + initialLineResultArray[2] +
			    carriageReturnString + "\n");
		}
	} else {
		message_locator_service("MISSED THE INITIAL LINE...!");
		return false;
	}
	for (var j = 1; j < (array.length - 1); j++) {
		var lineResultArray = lineSpotter_RegExp.exec(array[j]);
		if (lineResultArray !== null) {
			if (j === (array.length - 2)) {
				var nextToLast_ResultArray = lineSpotter_RegExp.exec(array[array.length - 1]);
				if (!nextToLast_ResultArray[2]) {
					fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2]);
				} else {
					fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2] + carriageReturnString +
					    "\n");
				}
			} else {
				fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2] + carriageReturnString +
				    "\n");
			}
		} else {
			message_locator_service("MISSED A LINE...!");
			return false;
		}
	}
	var finalLineResultArray = lineSpotter_RegExp.exec(array[array.length - 1]);
	if (finalLineResultArray !== null) {
		if (finalLineResultArray[2]) {
			fileSystem_Module.writeSync(currentFileHandle, finalLineResultArray[1] + finalLineResultArray[2]);
		}
	} else {
		message_locator_service("MISSED THE FINAL LINE...!");
		return false;
	}
	fileSystem_Module.closeSync(currentFileHandle);
	return true;
}

function array_from_file_delete(entire_fileName) {
	var fileSystem_Module = globalModule_Try('fs');
	if (fileSystem_Module.existsSync(entire_fileName)) {
		var targetFile_LineArray = fileSystem_Module.readFileSync(entire_fileName, 'utf8', 'r').toString().split('\n');
		fileSystem_Module.unlinkSync(entire_fileName);
		return targetFile_LineArray;
	} else {
		message_locator_service("TARGET FILE DOES NOT EXIST...!");
		return false;
	}
}

function array_from_file(entire_fileName) {
	var fileSystem_Module = globalModule_Try('fs');
	if (fileSystem_Module.existsSync(entire_fileName)) {
		var targetFile_LineArray = fileSystem_Module.readFileSync(entire_fileName, 'utf8', 'r').toString().split('\n');
		return targetFile_LineArray;
	} else {
		message_locator_service("TARGET FILE DOES NOT EXIST...!");
		return false;
	}
}

// Switching html head area to minified targets...
function toMin(headStart, headEnd, carriageReturn, contentArray) {
	var changed = false;
	var hasMin_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)(?:\\.min)+(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	var carelessAboutMin_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	for (var i = (headStart + 1); i < headEnd; i++) {
		if (hasMin_RegExp.exec(contentArray[i]) === null) {
			var regExp_ResultArray = carelessAboutMin_RegExp.exec(contentArray[i]);
			if (regExp_ResultArray !== null) {
				contentArray[i] = regExp_ResultArray[1] + ".min" + regExp_ResultArray[2] + carriageReturn;
				if (!changed) {
					changed = true;
				}
			}
		}
	}
	if (changed) {
		return contentArray;
	} else {
		return false;
	}
}

// Switching html head area to regular targets...
function toRegular(headStart, headEnd, carriageReturn, contentArray) {
	var changed = false;
	var minSuspect_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)\\.min(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	for (var i = (headStart + 1); i < headEnd; i++) {
		var regExp_ResultArray = minSuspect_RegExp.exec(contentArray[i]);
		if (regExp_ResultArray !== null) {
			contentArray[i] = regExp_ResultArray[1] + regExp_ResultArray[2] + carriageReturn;
			if (!changed) {
				changed = true;
			}
		}
	}
	if (changed) {
		return contentArray;
	} else {
		return false;
	}
}

function delete_writingArray_ToFile(fileName, array) {
	var fileSystem_Module = globalModule_Try('fs');
	if (fileSystem_Module.existsSync(fileName)) {
		fileSystem_Module.unlinkSync(fileName);
	}
	var inHouseFileHandle = fileSystem_Module.openSync(fileName, 'w');
	for (var i = 0; i < (array.length - 1); i++) {
		fileSystem_Module.writeSync(inHouseFileHandle, array[i] + "\n");
	}
	if (array[array.length - 1]) {
		fileSystem_Module.writeSync(inHouseFileHandle, array[array.length - 1]);
	}
	fileSystem_Module.closeSync(inHouseFileHandle);
}

module.exports = {
  casual__options__servant : function(options_object, option_request) {
	  var top_level_options_reference_object = {
	    action : [ 'switch', 'clean' ],
	    chattiness : [ 'true', 'false' ],
	    direction : [ 'min', 'regular' ],
	    file_source : [ 'wildcard', 'list' ],
	  };
	  for ( var item in options_object) {
		  if (item === option_request) {
			  if (top_level_options_reference_object[item].includes(item)) {

			  } else {

			  }
		  } else {

		  }
	  }
  },

  add_on_options__servant : function(global_object) {
	  var noisy = true;
	  var global_options_object = global_object.data.options;
	  var global_add_on_options_object = {
		  chattiness : [ 'true', 'false' ]
	  };
	  if (global_options_object !== undefined) {
		  if (noisy) {
			  console.log(">>> Options section found... Doing further checking... <<<");
		  }
		  for ( var item in global_add_on_options_object) {
			  if (global_options_object.hasOwnProperty(item)) {
				  var contains_valid_value = false;
				  for (var i = 0; i < global_add_on_options_object[item].length; i++) {
					  if (global_add_on_options_object[item].includes(global_options_object[item])) {
						  contains_valid_value = true;
						  break;
					  }
				  }
				  if (!contains_valid_value) {
					  console.log("\"" + global_options_object[item] + "\" IS NOT A VALID OPTION WITH \"" + item + "\" ...!");
					  return false;
				  }
			  } else {
				  if (noisy) {
					  console.log("MISSING OBJECTS OPTIONS PROPERTY: \"" + item + "\" ...!");
				  }
				  return false;
			  }
		  }
		  return true;
	  } else {
		  console.log(">>> NO VALID OPTIONS SECTION FOUND...! <<<");
		  return false;
	  }
  },

  private_action_checker : function(global_object, reference_object, noisy) {
	  var global_options_object = global_object.data.options;
	  if (global_options_object !== undefined) {
		  if (noisy) {
			  console.log(">>> Options section found... Doing further checking... <<<");
		  }
		  for ( var item in reference_object) {
			  if (global_options_object.hasOwnProperty(item)) {
				  var contains_valid_value = false;
				  for (var i = 0; i < reference_object[item].length; i++) {
					  if (reference_object[item].includes(global_options_object[item])) {
						  contains_valid_value = true;
						  break;
					  }
				  }
				  if (!contains_valid_value) {
					  console.log("\"" + global_options_object[item] + "\" IS NOT A VALID OPTION WITH \"" + item + "\" ...!");
					  return false;
				  }
			  } else {
				  if (noisy) {
					  console.log("MISSING OBJECTS OPTIONS PROPERTY: \"" + item + "\" ...!");
				  }
				  return false;
			  }
		  }
		  return true;
	  } else {
		  console.log(">>> NO VALID OPTIONS SECTION FOUND...! <<<");
		  return false;
	  }
  },

  process_wildcard_input : function(source, directory) {
	  var wildcard_extractor_RegExp = new RegExp("^\\*(.+)$");
	  var result_array = wildcard_extractor_RegExp.exec(source);
	  var final_files_array = [];
	  if (result_array) {
		  var tail_string = result_array[1];
		  var prepared_tail = tail_string.replace(/\./ig, "\\.");
		  var wildcard_RegExp = new RegExp("^(.+" + prepared_tail + ")$", "i");
		  var fileSystem_Module = globalModule_Try('fs');
		  var raw_file_array = fileSystem_Module.readdirSync(directory);
		  var targets_file_array = [];
		  for (var i = 0; i < raw_file_array.length; i++) {
			  var single_file_result_array = wildcard_RegExp.exec(raw_file_array[i]);
			  if (single_file_result_array) {
				  final_files_array.push(directory + single_file_result_array[1]);
			  }
		  }
		  return final_files_array;
	  } else {
		  message_locator_service("NO VALID WILDCARD FOUND...!");
		  return false;
	  }
  },

  toggle_all_head_links : function(direction, file) {
	  var pointToMin = false;
	  if (direction === 'min') {
		  pointToMin = true;
	  }
	  var targetFile_LineArray = array_from_file(file);
	  if (targetFile_LineArray) {
		  var windowsNeeded_carriageReturn = "";
		  if (carriage_return_needed) {
			  windowsNeeded_carriageReturn = "\r";
		  }
		  var headStart = spot_the_head(targetFile_LineArray)[0];
		  var headEnd = spot_the_head(targetFile_LineArray)[1];

		  // Actual array manipulation...
		  if (pointToMin) {
			  targetFile_LineArray = toMin(headStart, headEnd, windowsNeeded_carriageReturn, targetFile_LineArray);
			  if (targetFile_LineArray) {
				  delete_writingArray_ToFile(file, targetFile_LineArray);
				  return true;
			  } else {
				  return true;
			  }
		  } else {
			  targetFile_LineArray = toRegular(headStart, headEnd, windowsNeeded_carriageReturn, targetFile_LineArray);
			  if (targetFile_LineArray) {
				  delete_writingArray_ToFile(file, targetFile_LineArray);
				  return true;
			  } else {
				  return true;
			  }
		  }
	  } else {
		  message_locator_service("FAILED TO GET VALID DATA ARRAY...!");
		  return false;
	  }
  },

  end_of_line_refresh : function(file) {
	  var targetFile_LineArray = array_from_file_delete(file);
	  if (targetFile_LineArray) {
		  return end_of_line_clean_save(file, targetFile_LineArray, carriage_return_needed());
	  } else {
		  message_locator_service("FAILED TO GET VALID DATA ARRAY...!");
		  return false;
	  }
  }
};
<|endoftext|>


<commit_before>import { expect } from 'chai';
import { Given, When, Then } from 'cucumber';

import * as libtransactions from '../../../../server/lib/transactions';
import * as store from '../stores';
import * as utils from '../../../utils';

Given('a User {string}', async function (name) {
  const { user, userCollective } = await store.newUser(name);
  this.addValue(name, userCollective);
  this.addValue(`${name}-user`, user);
});

Given('a User {string} as an {string} to {string}', async function (userName, role, collectiveName) {
  const { user, userCollective } = await store.newUser(userName);
  this.addValue(userName, userCollective);
  this.addValue(`${userName}-user`, user);
  const collective = this.getValue(collectiveName);
  collective.addUserWithRole(user, role);
});

Given('a Host {string} in {string} and charges {string} of fee', async function (name, currency, fee) {
  const { hostCollective, hostAdmin } = await store.newHost(name, currency, fee);
  this.addValue(name, hostCollective);
  this.addValue(`${name}-admin`, hostAdmin);
});

Given('an Organization {string} in {string} administered by {string}', async function (orgName, currency, userName) {
  const orgAdmin = this.getValue(`${userName}-user`);
  const organization = await store.newOrganization({ name: orgName, currency }, orgAdmin);
  this.addValue(orgName, organization);
});

Given('a Collective {string} in {string} hosted by {string}', async function (name, currency, hostName) {
  const hostCollective = this.getValue(hostName);
  const hostAdmin = this.getValue(`${hostName}-admin`);
  const { collective } = await store.newCollectiveInHost(name, currency, hostCollective);
  this.addValue(name, collective);
  this.addValue(`${name}-host-collective`, hostCollective);
  this.addValue(`${name}-host-admin`, hostAdmin);
});

Given('{string} is hosted by {string}', async function (collectiveName, hostName) {
  const hostCollective = this.getValue(hostName);
  const collective = this.getValue(collectiveName);
  collective.addHost(hostCollective);
});

Given('{string} connects a {string} account', async function (hostName, connectedAccountName) {
  const host = this.getValue(hostName);
  const hostAdmin = this.getValue(`${hostName}-admin`);
  const method = {
    stripe: store.stripeConnectedAccount,
  }[connectedAccountName.toLowerCase()];
  await method(host.id, hostAdmin.id);
});

Given('{string} payment processor fee is {string}', async function (ppName, feeStr) {
  this.addValue(`${ppName.toLowerCase()}-payment-provider-fee`, feeStr);
});

Given('platform fee is {string}', async function (feeStr) {
  this.addValue(`platform-fee`, feeStr);
});

async function handleDonation (fromName, value, toName, paymentMethod, userName) {
  const [ amountStr, currency ] = value.split(' ');
  const amount = parseInt(amountStr);
  const user = this.getValue(`${userName ? userName : fromName}-user`);
  const userCollective = this.getValue(fromName);
  const collective = this.getValue(toName);
  /* Retrieve fees that may or may not have been set */
  const paymentMethodName = paymentMethod.toLowerCase();
  const ppFee = utils.readFee(amount, this.getValue(`${paymentMethodName}-payment-provider-fee`));
  const appFee = utils.readFee(amount, this.getValue('platform-fee'));
  /* Use the appropriate stub to execute the order */
  const method = {
    stripe: store.stripeOneTimeDonation,
  }[paymentMethodName];
  if (!method) throw new Error(`Payment Method ${paymentMethod} doesn't exist`);
  return method({
    user,
    userCollective,
    collective,
    currency,
    amount,
    appFee,
    ppFee,
  });
}

When('{string} donates {string} to {string} via {string}', handleDonation);

When('{string} donates {string} to {string} via {string} as {string}', handleDonation);

Then('{string} should have contributed {string} to {string}', async function(userName, value, collectiveName) {
  const [ amount, currency ] = value.split(' ');
  const userCollective = this.getValue(userName);
  const collective = this.getValue(collectiveName);
  /* Doesn't ever sum up different currencies */
  const userToCollectiveAmount = await libtransactions.sum({
    FromCollectiveId: userCollective.id,
    CollectiveId: collective.id,
    currency,
    type: 'CREDIT',
  });
  expect(userToCollectiveAmount).to.equal(parseInt(amount));
});

Then('{string} should have {string} in their balance', async function(collectiveName, value) {
  const [ amount, currency ] = value.split(' ');
  const collective = this.getValue(collectiveName);
  /* Doesn't ever sum up different currencies */
  const userToCollectiveAmount = await libtransactions.sum({
    CollectiveId: collective.id,
    currency,
  });
  expect(userToCollectiveAmount).to.equal(parseInt(amount));
});
<commit_msg>chore(bdd): User is optional for handleDonation step handler<commit_after>import { expect } from 'chai';
import { Given, When, Then } from 'cucumber';

import * as libtransactions from '../../../../server/lib/transactions';
import * as store from '../stores';
import * as utils from '../../../utils';

Given('a User {string}', async function (name) {
  const { user, userCollective } = await store.newUser(name);
  this.addValue(name, userCollective);
  this.addValue(`${name}-user`, user);
});

Given('a User {string} as an {string} to {string}', async function (userName, role, collectiveName) {
  const { user, userCollective } = await store.newUser(userName);
  this.addValue(userName, userCollective);
  this.addValue(`${userName}-user`, user);
  const collective = this.getValue(collectiveName);
  collective.addUserWithRole(user, role);
});

Given('a Host {string} in {string} and charges {string} of fee', async function (name, currency, fee) {
  const { hostCollective, hostAdmin } = await store.newHost(name, currency, fee);
  this.addValue(name, hostCollective);
  this.addValue(`${name}-admin`, hostAdmin);
});

Given('an Organization {string} in {string} administered by {string}', async function (orgName, currency, userName) {
  const orgAdmin = this.getValue(`${userName}-user`);
  const organization = await store.newOrganization({ name: orgName, currency }, orgAdmin);
  this.addValue(orgName, organization);
});

Given('a Collective {string} in {string} hosted by {string}', async function (name, currency, hostName) {
  const hostCollective = this.getValue(hostName);
  const hostAdmin = this.getValue(`${hostName}-admin`);
  const { collective } = await store.newCollectiveInHost(name, currency, hostCollective);
  this.addValue(name, collective);
  this.addValue(`${name}-host-collective`, hostCollective);
  this.addValue(`${name}-host-admin`, hostAdmin);
});

Given('{string} is hosted by {string}', async function (collectiveName, hostName) {
  const hostCollective = this.getValue(hostName);
  const collective = this.getValue(collectiveName);
  collective.addHost(hostCollective);
});

Given('{string} connects a {string} account', async function (hostName, connectedAccountName) {
  const host = this.getValue(hostName);
  const hostAdmin = this.getValue(`${hostName}-admin`);
  const method = {
    stripe: store.stripeConnectedAccount,
  }[connectedAccountName.toLowerCase()];
  await method(host.id, hostAdmin.id);
});

Given('{string} payment processor fee is {string}', async function (ppName, feeStr) {
  this.addValue(`${ppName.toLowerCase()}-payment-provider-fee`, feeStr);
});

Given('platform fee is {string}', async function (feeStr) {
  this.addValue(`platform-fee`, feeStr);
});

async function handleDonation (fromName, value, toName, paymentMethod, userName=null) {
  const [ amountStr, currency ] = value.split(' ');
  const amount = parseInt(amountStr);
  const user = !userName
    ? this.getValue(`${userName ? userName : fromName}-user`)
    : this.getValue(`${fromName}-user`);
  const userCollective = this.getValue(fromName);
  const collective = this.getValue(toName);
  /* Retrieve fees that may or may not have been set */
  const paymentMethodName = paymentMethod.toLowerCase();
  const ppFee = utils.readFee(amount, this.getValue(`${paymentMethodName}-payment-provider-fee`));
  const appFee = utils.readFee(amount, this.getValue('platform-fee'));
  /* Use the appropriate stub to execute the order */
  const method = {
    stripe: store.stripeOneTimeDonation,
  }[paymentMethodName];
  if (!method) throw new Error(`Payment Method ${paymentMethod} doesn't exist`);
  return method({
    user,
    userCollective,
    collective,
    currency,
    amount,
    appFee,
    ppFee,
  });
}

When('{string} donates {string} to {string} via {string}', handleDonation);

When('{string} donates {string} to {string} via {string} as {string}', handleDonation);

Then('{string} should have contributed {string} to {string}', async function(userName, value, collectiveName) {
  const [ amount, currency ] = value.split(' ');
  const userCollective = this.getValue(userName);
  const collective = this.getValue(collectiveName);
  /* Doesn't ever sum up different currencies */
  const userToCollectiveAmount = await libtransactions.sum({
    FromCollectiveId: userCollective.id,
    CollectiveId: collective.id,
    currency,
    type: 'CREDIT',
  });
  expect(userToCollectiveAmount).to.equal(parseInt(amount));
});

Then('{string} should have {string} in their balance', async function(collectiveName, value) {
  const [ amount, currency ] = value.split(' ');
  const collective = this.getValue(collectiveName);
  /* Doesn't ever sum up different currencies */
  const userToCollectiveAmount = await libtransactions.sum({
    CollectiveId: collective.id,
    currency,
  });
  expect(userToCollectiveAmount).to.equal(parseInt(amount));
});
<|endoftext|>


<commit_before>const buildMiddlewareParameters = require('~/test/unit/helpers/middleware-parameters-builder.js')

const { renderDetails } = require('~/src/apps/companies/controllers/details')

const companiesHouseCompany = require('~/test/unit/data/companies/companies-house-company.json')
const minimalCompany = require('~/test/unit/data/companies/minimal-company.json')
const config = require('~/config')

describe('Companies details controller', () => {
  describe('#renderDetails', () => {
    const commonTests = (template) => {
      it('should render the correct template', () => {
        const templateName = this.middlewareParameters.resMock.render.firstCall.args[0]
        expect(templateName).to.equal(template)
      })

      it('should include company details', () => {
        const options = this.middlewareParameters.resMock.render.firstCall.args[1]
        expect(options.companyDetails).to.not.be.null
      })

      it('should include account management details', () => {
        const options = this.middlewareParameters.resMock.render.firstCall.args[1]
        expect(options.accountManagementDetails).to.not.be.null
      })

      it('should include one list information', () => {
        const options = this.middlewareParameters.resMock.render.firstCall.args[1]
        expect(options.accountManagementDetails).to.not.be.null
      })

      it('should include a link to the One List support email', () => {
        const options = this.middlewareParameters.resMock.render.firstCall.args[1]
        expect(options.oneListEmail).to.equal(config.oneList.email)
      })
    }

    context('when the company contains Companies House data', () => {
      beforeEach(async () => {
        this.middlewareParameters = buildMiddlewareParameters({
          company: companiesHouseCompany,
        })

        await renderDetails(
          this.middlewareParameters.reqMock,
          this.middlewareParameters.resMock,
          this.middlewareParameters.nextSpy
        )
      })

      commonTests('companies/views/_deprecated/details')

      it('should include companies house details', () => {
        const options = this.middlewareParameters.resMock.render.firstCall.args[1]
        expect(options.chDetails).to.not.be.null
      })
    })

    context('when the company has no companies house data', () => {
      beforeEach(async () => {
        this.middlewareParameters = buildMiddlewareParameters({
          company: minimalCompany,
        })

        await renderDetails(
          this.middlewareParameters.reqMock,
          this.middlewareParameters.resMock,
          this.middlewareParameters.nextSpy
        )
      })

      commonTests('companies/views/_deprecated/details')

      it('should not include Companies House details', () => {
        const options = this.middlewareParameters.resMock.render.firstCall.args[1]
        expect(options.chDetails).to.be.null
      })
    })
  })
})
<commit_msg>Assert breadcrumb is added<commit_after>const buildMiddlewareParameters = require('~/test/unit/helpers/middleware-parameters-builder.js')

const { renderDetails } = require('~/src/apps/companies/controllers/details')

const companiesHouseCompany = require('~/test/unit/data/companies/companies-house-company.json')
const minimalCompany = require('~/test/unit/data/companies/minimal-company.json')
const dnbCompany = require('~/test/unit/data/companies/dnb-company.json')
const config = require('~/config')

describe('Companies details controller', () => {
  describe('#renderDetails', () => {
    const commonTests = (expectedBreadcrumb, expectedTemplate) => {
      it('should add a breadcrumb', () => {
        const breadcrumbSpy = this.middlewareParameters.resMock.breadcrumb

        expect(breadcrumbSpy).to.be.calledWith(expectedBreadcrumb.text)
        expect(breadcrumbSpy).to.have.been.calledOnce
      })

      it('should render the correct template', () => {
        const templateName = this.middlewareParameters.resMock.render.firstCall.args[0]
        expect(templateName).to.equal(expectedTemplate)
      })

      it('should include company details', () => {
        const options = this.middlewareParameters.resMock.render.firstCall.args[1]
        expect(options.companyDetails).to.not.be.null
      })

      it('should include account management details', () => {
        const options = this.middlewareParameters.resMock.render.firstCall.args[1]
        expect(options.accountManagementDetails).to.not.be.null
      })

      it('should include one list information', () => {
        const options = this.middlewareParameters.resMock.render.firstCall.args[1]
        expect(options.accountManagementDetails).to.not.be.null
      })

      it('should include a link to the One List support email', () => {
        const options = this.middlewareParameters.resMock.render.firstCall.args[1]
        expect(options.oneListEmail).to.equal(config.oneList.email)
      })
    }

    context('when the company contains Companies House data', () => {
      beforeEach(async () => {
        this.middlewareParameters = buildMiddlewareParameters({
          company: companiesHouseCompany,
        })

        await renderDetails(
          this.middlewareParameters.reqMock,
          this.middlewareParameters.resMock,
          this.middlewareParameters.nextSpy
        )
      })

      commonTests({ text: 'SAMSUNG BIOEPIS UK LIMITED' }, 'companies/views/_deprecated/details')

      it('should include companies house details', () => {
        const options = this.middlewareParameters.resMock.render.firstCall.args[1]
        expect(options.chDetails).to.not.be.null
      })
    })

    context('when the company has no companies house data', () => {
      beforeEach(async () => {
        this.middlewareParameters = buildMiddlewareParameters({
          company: minimalCompany,
        })

        await renderDetails(
          this.middlewareParameters.reqMock,
          this.middlewareParameters.resMock,
          this.middlewareParameters.nextSpy
        )
      })

      commonTests({ text: 'SAMSUNG BIOEPIS UK LIMITED' }, 'companies/views/_deprecated/details')

      it('should not include Companies House details', () => {
        const options = this.middlewareParameters.resMock.render.firstCall.args[1]
        expect(options.chDetails).to.be.null
      })
    })
  })
})
<|endoftext|>


<commit_before><commit_msg>Added some Jasmine tests to make sure everything is working<commit_after>// This is just some sample test code to get me started.
describe("A spec", function() {
  var foo;

  beforeEach(function() {
    foo = 0;
    foo += 1;
  });

  afterEach(function() {
    foo = 0;
  });

  it("is just a function, so it can contain any code", function() {
    expect(foo).toEqual(1);
  });

  it("can have more than one expectation", function() {
    expect(foo).toEqual(1);
    expect(true).toEqual(true);
  });

  describe("nested inside a second describe", function() {
    var bar;

    beforeEach(function() {
      bar = 1;
    });

    it("can reference both scopes as needed ", function() {
      expect(foo).toEqual(bar);
    });
  });
});<|endoftext|>


<commit_before>var isCommonJS = typeof window == "undefined" && typeof exports == "object";

jasmine.Env.prototype.parameterize = function(description, paramDefinitions, specDefinitions) {
  var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);

  var parentSuite = this.currentSuite;
  if (parentSuite) {
    parentSuite.add(suite);
  } else {
    this.currentRunner_.add(suite);
  }

  this.currentSuite = suite;

  var declarationError = null;
  try {
      var paramList = paramDefinitions.call(suite);
      for (var i = 0; i < paramList.length; ++i) {
          var params = paramList[i];
          var paramDescription = JSON.stringify(params);
          var paramSpecDefinitions = function() {
              specDefinitions.apply(this, params);
          };
          describe(paramDescription, paramSpecDefinitions);
      }
  } catch(e) {
      declarationError = e;
  }

  if (declarationError) {
    this.it("encountered a declaration exception", function() {
      throw declarationError;
    });
  }

  this.currentSuite = parentSuite;

  return suite;
};

jasmine.Env.prototype.xparameterize = function(desc, paramDefinitions, specDefinitions) {
  return {
    execute: function() {
    }
  };
};

/**
 * Defines a parameterized suite of specifications.
 *
 * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
 * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
 * of setup in some tests.
 *
 * @example
 * // TODO: a simple suite
 *
 * // TODO: a simple suite with a nested describe block
 *
 * @param {String} description A string, usually the class under test.
 * @param {Function} paramDefinitions function that returns an array of parameter arrays.
 * @param {Function} specDefinitions function that defines several specs, accepting the parameters.
 */
var parameterize = function(description, paramDefinitions, specDefinitions) {
    return jasmine.getEnv().parameterize(description, paramDefinitions, specDefinitions);
};
if (isCommonJS) exports.parameterize = parameterize;

/**
 * Disables a parameterized suite of specifications.  Used to disable some suites in a file, or files, temporarily during development.
 *
 * @param {String} description A string, usually the class under test.
 * @param {Function} paramDefinitions function that returns an array of parameter arrays.
 * @param {Function} specDefinitions function that defines several specs, accepting the parameters.
 */
var xparameterize = function(description, paramDefinitions, specDefinitions) {
  return jasmine.getEnv().xparameterize(description, paramDefinitions, specDefinitions);
};
if (isCommonJS) exports.xparameterize = xparameterize;

/**
 * Matcher that checks that the expected exception was thrown by the actual.
 *
 * @param {Error} [expected]
 * @param {number} [messageId]
 */
jasmine.Matchers.prototype.toThrow = function(expected, messageId) {
  var result = false;
  var exception;
  if (typeof this.actual != 'function') {
    throw new Error('Actual is not a function');
  }
  try {
    this.actual();
  } catch (e) {
    exception = e;
  }
  if (exception) {
    result = (expected === jasmine.undefined ||
              (!(expected instanceof MslException) && this.env.equals_(exception.message || exception, expected.message || expected)) ||
               ((expected.name == 'MslException' || exception.name == expected.name) &&
                (expected.error == MslError.NONE || exception.error == expected.error) &&
                (messageId == undefined || messageId == null || exception.messageId == messageId)));
  }

  var not = this.isNot ? "not " : "";

  this.message = function() {
    if (exception && (expected === jasmine.undefined || !result)) {
      var expectedInfo;
      if (expected) {
          if (expected.name) {
              expectedInfo = expected.name;
              if (expected.error != MslError.NONE) expectedInfo += ' ' + expected.message;
              if (messageId != undefined && messageId != null) expectedInfo += ' [messageId:' + messageId + ']';
          } else {
              expectedInfo = expected;
          }
      }
      var exceptionInfo = exception;
      if (exception.name) {
          exceptionInfo = exception.name;
          if (exception.error != MslError.NONE) exceptionInfo += ' ' + exception.message;
          if (exception.messageId != undefined && exception.messageId != null) exceptionInfo += ' [messageId:' + exception.messageId + ']';
      }
      return ["Expected function " + not + "to throw ",
              (expectedInfo) ? expectedInfo : "an exception",
              ", but it threw ",
              exceptionInfo].join('');
    } else {
      return "Expected function to throw an exception.";
    }
  };

  return result;
};<commit_msg>Override Jasmine matcher function to include the full stack trace when displaying thrown Errors.<commit_after>var isCommonJS = typeof window == "undefined" && typeof exports == "object";

jasmine.Env.prototype.parameterize = function(description, paramDefinitions, specDefinitions) {
  var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);

  var parentSuite = this.currentSuite;
  if (parentSuite) {
    parentSuite.add(suite);
  } else {
    this.currentRunner_.add(suite);
  }

  this.currentSuite = suite;

  var declarationError = null;
  try {
      var paramList = paramDefinitions.call(suite);
      for (var i = 0; i < paramList.length; ++i) {
          var params = paramList[i];
          var paramDescription = JSON.stringify(params);
          var paramSpecDefinitions = function() {
              specDefinitions.apply(this, params);
          };
          describe(paramDescription, paramSpecDefinitions);
      }
  } catch(e) {
      declarationError = e;
  }

  if (declarationError) {
    this.it("encountered a declaration exception", function() {
      throw declarationError;
    });
  }

  this.currentSuite = parentSuite;

  return suite;
};

jasmine.Env.prototype.xparameterize = function(desc, paramDefinitions, specDefinitions) {
  return {
    execute: function() {
    }
  };
};

/**
 * Defines a parameterized suite of specifications.
 *
 * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
 * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
 * of setup in some tests.
 *
 * @example
 * // TODO: a simple suite
 *
 * // TODO: a simple suite with a nested describe block
 *
 * @param {String} description A string, usually the class under test.
 * @param {Function} paramDefinitions function that returns an array of parameter arrays.
 * @param {Function} specDefinitions function that defines several specs, accepting the parameters.
 */
var parameterize = function(description, paramDefinitions, specDefinitions) {
    return jasmine.getEnv().parameterize(description, paramDefinitions, specDefinitions);
};
if (isCommonJS) exports.parameterize = parameterize;

/**
 * Disables a parameterized suite of specifications.  Used to disable some suites in a file, or files, temporarily during development.
 *
 * @param {String} description A string, usually the class under test.
 * @param {Function} paramDefinitions function that returns an array of parameter arrays.
 * @param {Function} specDefinitions function that defines several specs, accepting the parameters.
 */
var xparameterize = function(description, paramDefinitions, specDefinitions) {
  return jasmine.getEnv().xparameterize(description, paramDefinitions, specDefinitions);
};
if (isCommonJS) exports.xparameterize = xparameterize;

/**
 * Matcher that checks that the expected exception was thrown by the actual.
 *
 * @param {Error} expected expected exception.
 * @param {number} messageId expected MSL message ID.
 */
jasmine.Matchers.prototype.toThrow = function(expected, messageId) {
  var result = false;
  var exception;
  if (typeof this.actual != 'function') {
    throw new Error('Actual is not a function');
  }
  try {
    this.actual();
  } catch (e) {
    exception = e;
  }
  if (exception) {
    result = (expected === jasmine.undefined ||
              (!(expected instanceof MslException) && this.env.equals_(exception.message || exception, expected.message || expected)) ||
               ((expected.name == 'MslException' || exception.name == expected.name) &&
                (expected.error == MslError.NONE || exception.error == expected.error) &&
                (messageId == undefined || messageId == null || exception.messageId == messageId)));
  }

  var not = this.isNot ? "not " : "";

  this.message = function() {
    if (exception && (expected === jasmine.undefined || !result)) {
      var expectedInfo;
      if (expected) {
          if (expected.name) {
              expectedInfo = expected.name;
              if (expected.error != MslError.NONE) expectedInfo += ' ' + expected.message;
              if (messageId != undefined && messageId != null) expectedInfo += ' [messageId:' + messageId + ']';
          } else {
              expectedInfo = expected;
          }
      }
      var exceptionInfo = exception;
      if (exception.name) {
          exceptionInfo = exception.name;
          if (exception.error != MslError.NONE) exceptionInfo += ' ' + exception.message;
          if (exception.messageId != undefined && exception.messageId != null) exceptionInfo += ' [messageId:' + exception.messageId + ']';
      }
      return ["Expected function " + not + "to throw ",
              (expectedInfo) ? expectedInfo : "an exception",
              ", but it threw ",
              exceptionInfo].join('');
    } else {
      return "Expected function to throw an exception.";
    }
  };
  this.stack = exception.stack;

  return result;
};
/**
 * Override matcher function to include stack trace.
 *
 * @param {string} matcher name.
 * @param {function} matcher function.
 */
jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
  return function() {
    var matcherArgs = jasmine.util.argsToArray(arguments);
    var result = matcherFunction.apply(this, arguments);

    if (this.isNot) {
      result = !result;
    }

    if (this.reportWasCalled_) return result;

    var message;
    if (!result) {
      if (this.message) {
        message = this.message.apply(this, arguments);
        if (jasmine.isArray_(message)) {
          message = message[this.isNot ? 1 : 0];
        }
      } else {
        var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
        message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
        if (matcherArgs.length > 0) {
          for (var i = 0; i < matcherArgs.length; i++) {
            if (i > 0) message += ",";
            message += " " + jasmine.pp(matcherArgs[i]);
          }
        }
        message += ".";
      }
    }
    var expectationResult = new jasmine.ExpectationResult({
      matcherName: matcherName,
      passed: result,
      expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
      actual: this.actual,
      message: message,
    });
    if (this.stack) {
      expectationResult.trace = { stack: this.stack };
    }
    this.spec.addMatcherResult(expectationResult);
    return jasmine.undefined;
  };
};<|endoftext|>


<commit_before>import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { dropTask, restartableTask } from 'ember-concurrency';
import { all } from 'rsvp';
import ObjectProxy from '@ember/object/proxy';
import sortableByPosition from 'ilios-common/utils/sortable-by-position';
import scrollIntoView from 'scroll-into-view';

export default class DetailCohortsComponent extends Component {
  @service currentUser;
  @service store;
  @service intl;
  @tracked isSorting = false;
  @tracked managingMaterial;
  @tracked totalMaterialsToSave;
  @tracked currentMaterialsSaved;
  @tracked displayAddNewForm = false;
  @tracked type;
  @tracked materialsRelationship;
  @tracked learningMaterialStatuses;
  @tracked learningMaterialUserRoles;
  @tracked title;

  constructor() {
    super(...arguments);
    this.learningMaterialStatuses = this.store.peekAll('learning-material-status');
    this.learningMaterialUserRoles = this.store.peekAll('learning-material-user-role');
  }

  @restartableTask
  *load() {
    this.materialsRelationship = yield this.args.subject.learningMaterials;
  }

  get materials() {
    if (!this.materialsRelationship) {
      return [];
    }

    return this.materialsRelationship.toArray();
  }

  get parentMaterialIds() {
    return this.materials.map((lm) => {
      return lm.belongsTo('learningMaterial').id();
    });
  }

  get proxyMaterials() {
    const materialProxy = ObjectProxy.extend({ confirmRemoval: false });
    return this.materials
      .sort(sortableByPosition)
      .map((material) => materialProxy.create({ content: material }));
  }

  get isManaging() {
    return !!this.managingMaterial;
  }

  get isSession() {
    return !this.args.isCourse;
  }
  get displaySearchBox() {
    return !this.isManaging && !this.displayAddNewForm && !this.isSorting && this.args.editable;
  }

  get hasMoreThanOneLearningMaterial() {
    return this.materials && this.materials.length > 1;
  }

  confirmRemoval(lmProxy) {
    lmProxy.set('showRemoveConfirmation', true);
  }
  cancelRemove(lmProxy) {
    lmProxy.set('showRemoveConfirmation', false);
  }

  @action
  addNewLearningMaterial(type) {
    this.type = type;
    this.displayAddNewForm = true;
  }

  @action
  closeLearningmaterialManager() {
    this.managingMaterial = null;
    scrollIntoView(this.title);
  }

  @action
  closeNewLearningmaterial() {
    this.displayAddNewForm = false;
    scrollIntoView(this.title);
  }

  @dropTask
  *saveNewLearningMaterial(lm) {
    const savedLm = yield lm.save();

    let lmSubject;
    let position = 0;
    if (this.materials && this.materials.length) {
      position = this.materials.sortBy('position').reverse()[0].get('position') + 1;
    }
    if (this.args.isCourse) {
      lmSubject = this.store.createRecord('course-learning-material', {
        course: this.args.subject,
        position,
      });
    } else {
      lmSubject = this.store.createRecord('session-learning-material', {
        session: this.args.subject,
        position,
      });
    }
    lmSubject.set('learningMaterial', savedLm);
    yield lmSubject.save();
    this.displayAddNewForm = false;
    this.type = null;
    scrollIntoView(this.title);
  }

  @dropTask
  *saveSortOrder(learningMaterials) {
    const materialsToSave = [];
    for (let i = 0, n = learningMaterials.length; i < n; i++) {
      const lm = learningMaterials[i];
      const position = i + 1;
      if (lm.position != position) {
        lm.set('position', position);
        materialsToSave.push(lm);
      }
    }

    yield this.saveSomeMaterials(materialsToSave);
    this.isSorting = false;
    scrollIntoView(this.title);
  }

  @dropTask
  *addLearningMaterial(parentLearningMaterial) {
    let newLearningMaterial;

    if (this.args.isCourse) {
      newLearningMaterial = this.store.createRecord('course-learning-material', {
        course: this.args.subject,
        learningMaterial: parentLearningMaterial,
        position: 0,
      });
    } else {
      newLearningMaterial = this.store.createRecord('session-learning-material', {
        session: this.args.subject,
        learningMaterial: parentLearningMaterial,
        position: 0,
      });
    }
    let position = 0;
    if (this.materials && this.materials.length > 1) {
      position = this.materials.sortBy('position').reverse()[0].get('position') + 1;
    }
    newLearningMaterial.set('position', position);
    yield newLearningMaterial.save();
  }

  @dropTask
  *remove(lmProxy) {
    const subjectLearningMaterial = lmProxy.get('content');
    subjectLearningMaterial.deleteRecord();
    return yield subjectLearningMaterial.save();
  }

  async saveSomeMaterials(arr) {
    const chunk = arr.splice(0, 5);
    const savedMaterials = await all(chunk.invoke('save'));
    let moreMaterials = [];
    if (arr.length) {
      moreMaterials = await this.saveSomeMaterials(arr);
    }

    return [].concat(savedMaterials, moreMaterials);
  }
}
<commit_msg>when scrolling to component title, scroll at the way to the top.<commit_after>import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { dropTask, restartableTask } from 'ember-concurrency';
import { all } from 'rsvp';
import ObjectProxy from '@ember/object/proxy';
import sortableByPosition from 'ilios-common/utils/sortable-by-position';
import scrollIntoView from 'scroll-into-view';

export default class DetailCohortsComponent extends Component {
  @service currentUser;
  @service store;
  @service intl;
  @tracked isSorting = false;
  @tracked managingMaterial;
  @tracked totalMaterialsToSave;
  @tracked currentMaterialsSaved;
  @tracked displayAddNewForm = false;
  @tracked type;
  @tracked materialsRelationship;
  @tracked learningMaterialStatuses;
  @tracked learningMaterialUserRoles;
  @tracked title;

  constructor() {
    super(...arguments);
    this.learningMaterialStatuses = this.store.peekAll('learning-material-status');
    this.learningMaterialUserRoles = this.store.peekAll('learning-material-user-role');
  }

  @restartableTask
  *load() {
    this.materialsRelationship = yield this.args.subject.learningMaterials;
  }

  get materials() {
    if (!this.materialsRelationship) {
      return [];
    }

    return this.materialsRelationship.toArray();
  }

  get parentMaterialIds() {
    return this.materials.map((lm) => {
      return lm.belongsTo('learningMaterial').id();
    });
  }

  get proxyMaterials() {
    const materialProxy = ObjectProxy.extend({ confirmRemoval: false });
    return this.materials
      .sort(sortableByPosition)
      .map((material) => materialProxy.create({ content: material }));
  }

  get isManaging() {
    return !!this.managingMaterial;
  }

  get isSession() {
    return !this.args.isCourse;
  }
  get displaySearchBox() {
    return !this.isManaging && !this.displayAddNewForm && !this.isSorting && this.args.editable;
  }

  get hasMoreThanOneLearningMaterial() {
    return this.materials && this.materials.length > 1;
  }

  confirmRemoval(lmProxy) {
    lmProxy.set('showRemoveConfirmation', true);
  }
  cancelRemove(lmProxy) {
    lmProxy.set('showRemoveConfirmation', false);
  }

  @action
  addNewLearningMaterial(type) {
    this.type = type;
    this.displayAddNewForm = true;
  }

  @action
  closeLearningmaterialManager() {
    this.managingMaterial = null;
    scrollIntoView(this.title, {
      align: { top: 0 },
    });
  }

  @action
  closeNewLearningmaterial() {
    this.displayAddNewForm = false;
    scrollIntoView(this.title, {
      align: { top: 0 },
    });
  }

  @dropTask
  *saveNewLearningMaterial(lm) {
    const savedLm = yield lm.save();

    let lmSubject;
    let position = 0;
    if (this.materials && this.materials.length) {
      position = this.materials.sortBy('position').reverse()[0].get('position') + 1;
    }
    if (this.args.isCourse) {
      lmSubject = this.store.createRecord('course-learning-material', {
        course: this.args.subject,
        position,
      });
    } else {
      lmSubject = this.store.createRecord('session-learning-material', {
        session: this.args.subject,
        position,
      });
    }
    lmSubject.set('learningMaterial', savedLm);
    yield lmSubject.save();
    this.displayAddNewForm = false;
    this.type = null;
    scrollIntoView(this.title, {
      align: { top: 0 },
    });
  }

  @dropTask
  *saveSortOrder(learningMaterials) {
    const materialsToSave = [];
    for (let i = 0, n = learningMaterials.length; i < n; i++) {
      const lm = learningMaterials[i];
      const position = i + 1;
      if (lm.position != position) {
        lm.set('position', position);
        materialsToSave.push(lm);
      }
    }

    yield this.saveSomeMaterials(materialsToSave);
    this.isSorting = false;
    scrollIntoView(this.title, {
      align: { top: 0 },
    });
  }

  @dropTask
  *addLearningMaterial(parentLearningMaterial) {
    let newLearningMaterial;

    if (this.args.isCourse) {
      newLearningMaterial = this.store.createRecord('course-learning-material', {
        course: this.args.subject,
        learningMaterial: parentLearningMaterial,
        position: 0,
      });
    } else {
      newLearningMaterial = this.store.createRecord('session-learning-material', {
        session: this.args.subject,
        learningMaterial: parentLearningMaterial,
        position: 0,
      });
    }
    let position = 0;
    if (this.materials && this.materials.length > 1) {
      position = this.materials.sortBy('position').reverse()[0].get('position') + 1;
    }
    newLearningMaterial.set('position', position);
    yield newLearningMaterial.save();
  }

  @dropTask
  *remove(lmProxy) {
    const subjectLearningMaterial = lmProxy.get('content');
    subjectLearningMaterial.deleteRecord();
    return yield subjectLearningMaterial.save();
  }

  async saveSomeMaterials(arr) {
    const chunk = arr.splice(0, 5);
    const savedMaterials = await all(chunk.invoke('save'));
    let moreMaterials = [];
    if (arr.length) {
      moreMaterials = await this.saveSomeMaterials(arr);
    }

    return [].concat(savedMaterials, moreMaterials);
  }
}
<|endoftext|>


<commit_before><commit_msg>Remove empty file<commit_after><|endoftext|>


<commit_before>function RandomGreeting(){

}

function dateMessage(){
    var dayOfWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; // gets day of the week from here
    var n = new Date();
    var weekday = n.getDay();
    document.write("Today is ", dayOfWeek[weekday], ", "); //writes the Day of the week
    console.log(weekday);// 1
    var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
    var s = new Date();
    var month = s.getMonth();//gets the month function
    document.write(months[month], " "); //displays month
    var r = new Date();
    var dayNumber = r.getDate(); //gets day number
    document.write(dayNumber, "th"); //displays day
}

function BirthdayCountDown(){

}
<commit_msg>fixed small error<commit_after>function randomGreeting(){

}

function dateMessage(){
    var dayOfWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; // gets day of the week from here
    var n = new Date();
    var weekday = n.getDay();
    document.write("Today is ", dayOfWeek[weekday], ", "); //writes the Day of the week
    console.log(weekday);// 1
    var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
    var s = new Date();
    var month = s.getMonth();//gets the month function
    document.write(months[month], " "); //displays month
    var r = new Date();
    var dayNumber = r.getDate(); //gets day number
    document.write(dayNumber, "th"); //displays day
}

function BirthdayCountDown(){

}
<|endoftext|>


<commit_before>
module.exports = {
  FunctionName: "{FUNCTION-NAME}",
  Description: "TODO",
  Handler: "index.handler",
  Role: "{ROLE}",
  Region: "{REGION}",
  Runtime: "nodejs",
  MemorySize: {MEMORY-SIZE},
  Timeout: {TIMEOUT}
}
<commit_msg>「package.json」の情報を使うように変更<commit_after>
package = require("./package.json")

module.exports = {
  FunctionName: package.name,
  Description: "v" + package.version + ": " + package.description,
  Handler: "index.handler",
  Role: "{ROLE}",
  Region: "{REGION}",
  Runtime: "nodejs",
  MemorySize: {MEMORY-SIZE},
  Timeout: {TIMEOUT}
}
<|endoftext|>


<commit_before>'use strict';

//================================================================================================
// Voting system
//================================================================================================

// Event function for voting
function vote(value, voteCountElement)
{

  // Data that goes into the post request body
  let voteData = new FormData();
  voteData.append('vote', value);
  voteData.append('postID', voteCountElement.dataset.postid);

  fetch('/resources/lib/vote.php', {
    method: 'POST',
    header: {'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'},
    credentials: 'same-origin',
    body: voteData
  })
  .then(
    function(response){
      if (response.status != 200) {
        console.log('Something went wrong with the request. Status code: ' + response.status);
        return;
      }

      response.json().then(function(data){

        // Check for errors
        if (data.error) {

          const errorElement = document.createElement('p');
          errorElement.classList.add('error');
          errorElement.textContent = data.error;

          const voteBox = document.querySelector('.voteBox');
          voteBox.appendChild(errorElement);

        } else {

          // Update vote count if successful
          voteCountElement.innerHTML = data.newCount;

          // Change colors depending on value
          if (data.newCount <= -1) {
            voteCountElement.style.color = 'red';
          } else if (data.newCount == 0) {
            voteCountElement.style.color = 'black';
          } else if (data.newCount >= 1) {
            voteCountElement.style.color = 'green';
          }

        }

      });
    }
  )
  .catch(function(error){
    console.log('Fetch error: ' + error);
  });
}

// Get all voting elements
const voteBox = document.querySelectorAll('.voteBox');

// Loop through them and add event listeners
voteBox.forEach(function(singleBox){

  let voteCount = singleBox.querySelector('.voteCount');
  const voteUp = singleBox.querySelector('.voteUp');
  const voteDown = singleBox.querySelector('.voteDown');

  // Color the vote count based on value
  if (voteCount.innerHTML <= -1) {
    voteCount.style.color = 'red';
  } else if (voteCount.innerHTML == 0) {
    voteCount.style.color = 'black';
  } else if (voteCount.innerHTML >= 1) {
    voteCount.style.color = 'green';
  }

  // Seperate event listeners for up and down voting
  voteUp.addEventListener('click', function(){ vote(1, voteCount) });
  voteDown.addEventListener('click', function(){ vote(-1, voteCount) });

});

//================================================================================================
// Edit and update post
//================================================================================================

// Event function for generating new fields for updating posts
function postEdit(id)
{

  // Assign varibles to important elements and old content
  const contentElement = document.querySelector('#id-'+id);
  const elementParent = contentElement.parentElement;
  const sibling = contentElement.nextElementSibling;
  const oldContent = contentElement.innerHTML;

  // Create input element with old content
  const contentInput = document.createElement('textarea');
  contentInput.classList.add('newContentEdit');
  contentInput.value = oldContent;

  // Create save button
  const saveButton = document.createElement('button');
  saveButton.innerHTML = 'Save changes';
  saveButton.classList.add('button', 'editSaveButton', 'for-'+id);

  // Create cancel button
  const cancelButton = document.createElement('button');
  cancelButton.innerHTML = "Cancel changes";
  cancelButton.classList.add('button', 'editCancelButton');

  // Execute remove and create elements
  elementParent.removeChild(contentElement);
  elementParent.insertBefore(contentInput, sibling);
  elementParent.insertBefore(saveButton, sibling);
  elementParent.insertBefore(cancelButton, sibling);

  // Add event listener to new save button
  saveButton.addEventListener('click', function(){
    fetchEdit(id, contentInput, elementParent, sibling);
  });

  // Add event listener to cancel button
  cancelButton.addEventListener('click', function(){

    // Remove editing field and buttons
    elementParent.removeChild(contentInput);
    elementParent.removeChild(saveButton);
    elementParent.removeChild(cancelButton);

    // Add back the old element in unchanged state
    elementParent.insertBefore(contentElement, sibling);

  });

}

function fetchEdit(id, input, parent, sibling)
{

  // Variables to prepare for fetch call
  const editData = new FormData();
  editData.append('postEdit', input.value);
  editData.append('postID', id);

  // Initiate fetch request
  fetch('resources/lib/postEdit.php', {
    method: 'POST',
    header: {'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'},
    body: editData
  })
  .then(
    function(response){
      if (response.status != 200) {
        console.log('Something went wrong with the request. Status code: ' + response.status);
        return;
      }

      response.json().then(function(data){

        // Create new element with updated content
        const newContentElement = document.createElement('p');
        newContentElement.setAttribute('class', 'postContent');
        newContentElement.setAttribute('id', 'id-'+id);
        newContentElement.innerHTML = data.newPost.post_content;

        // Create response element that confirms change
        const editConfirm = document.createElement('p');
        editConfirm.setAttribute('class', 'message');
        editConfirm.innerHTML = data.message;

        // TODO: Error message handling on post edit

        // Execute new elements create
        parent.removeChild(input);
        parent.insertBefore(newContentElement, sibling);
        parent.insertBefore(editConfirm, sibling);

      });
    }
  )
  .catch(function(error){
    console.log('Fetch error: ' + error);
  });

}

// Get all edit buttons
const editButtons = document.querySelectorAll('.postEdit');

editButtons.forEach(function(button){

  // Get the post id
  const postID = button.dataset.postid;

  // Add event listener and run function
  button.addEventListener('click', function(){
    postEdit(postID);
  })
});
<commit_msg>Error handling in voting system<commit_after>'use strict';

//================================================================================================
// Voting system
//================================================================================================

// Event function for voting
function vote(value, voteCountElement, parent)
{

  // Data that goes into the post request body
  let voteData = new FormData();
  voteData.append('vote', value);
  voteData.append('postID', voteCountElement.dataset.postid);

  fetch('/resources/lib/vote.php', {
    method: 'POST',
    header: {'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'},
    credentials: 'same-origin',
    body: voteData
  })
  .then(
    function(response){
      if (response.status != 200) {
        console.log('Something went wrong with the request. Status code: ' + response.status);
        return;
      }

      response.json().then(function(data){

        // Check for errors
        if (data.error) {

          const errorElement = document.createElement('p');
          errorElement.classList.add('error');
          errorElement.textContent = data.error;

          parent.appendChild(errorElement);

          setTimeout(function(){
            parent.removeChild(errorElement);
          }, 3000);

        } else {

          // Update vote count if successful
          voteCountElement.innerHTML = data.newCount;

          // Change colors depending on value
          if (data.newCount <= -1) {
            voteCountElement.style.color = 'red';
          } else if (data.newCount == 0) {
            voteCountElement.style.color = 'black';
          } else if (data.newCount >= 1) {
            voteCountElement.style.color = 'green';
          }

        }

      });
    }
  )
  .catch(function(error){
    console.log('Fetch error: ' + error);
  });
}

// Get all voting elements
const voteBox = document.querySelectorAll('.voteBox');

// Loop through them and add event listeners
voteBox.forEach(function(singleBox){

  let voteCount = singleBox.querySelector('.voteCount');
  const voteUp = singleBox.querySelector('.voteUp');
  const voteDown = singleBox.querySelector('.voteDown');

  // Color the vote count based on value
  if (voteCount.innerHTML <= -1) {
    voteCount.style.color = 'red';
  } else if (voteCount.innerHTML == 0) {
    voteCount.style.color = 'black';
  } else if (voteCount.innerHTML >= 1) {
    voteCount.style.color = 'green';
  }

  // Seperate event listeners for up and down voting
  voteUp.addEventListener('click', function(){ vote(1, voteCount, singleBox) });
  voteDown.addEventListener('click', function(){ vote(-1, voteCount, singleBox) });

});

//================================================================================================
// Edit and update post
//================================================================================================

// Event function for generating new fields for updating posts
function postEdit(id)
{

  // Assign varibles to important elements and old content
  const contentElement = document.querySelector('#id-'+id);
  const elementParent = contentElement.parentElement;
  const sibling = contentElement.nextElementSibling;
  const oldContent = contentElement.innerHTML;

  // Create input element with old content
  const contentInput = document.createElement('textarea');
  contentInput.classList.add('newContentEdit');
  contentInput.value = oldContent;

  // Create save button
  const saveButton = document.createElement('button');
  saveButton.innerHTML = 'Save changes';
  saveButton.classList.add('button', 'editSaveButton', 'for-'+id);

  // Create cancel button
  const cancelButton = document.createElement('button');
  cancelButton.innerHTML = "Cancel changes";
  cancelButton.classList.add('button', 'editCancelButton');

  // Execute remove and create elements
  elementParent.removeChild(contentElement);
  elementParent.insertBefore(contentInput, sibling);
  elementParent.insertBefore(saveButton, sibling);
  elementParent.insertBefore(cancelButton, sibling);

  // Add event listener to new save button
  saveButton.addEventListener('click', function(){
    fetchEdit(id, contentInput, elementParent, sibling);
  });

  // Add event listener to cancel button
  cancelButton.addEventListener('click', function(){

    // Remove editing field and buttons
    elementParent.removeChild(contentInput);
    elementParent.removeChild(saveButton);
    elementParent.removeChild(cancelButton);

    // Add back the old element in unchanged state
    elementParent.insertBefore(contentElement, sibling);

  });

}

function fetchEdit(id, input, parent, sibling)
{

  // Variables to prepare for fetch call
  const editData = new FormData();
  editData.append('postEdit', input.value);
  editData.append('postID', id);

  // Initiate fetch request
  fetch('resources/lib/postEdit.php', {
    method: 'POST',
    header: {'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'},
    body: editData
  })
  .then(
    function(response){
      if (response.status != 200) {
        console.log('Something went wrong with the request. Status code: ' + response.status);
        return;
      }

      response.json().then(function(data){

        // Create new element with updated content
        const newContentElement = document.createElement('p');
        newContentElement.setAttribute('class', 'postContent');
        newContentElement.setAttribute('id', 'id-'+id);
        newContentElement.innerHTML = data.newPost.post_content;

        // Create response element that confirms change
        const editConfirm = document.createElement('p');
        editConfirm.setAttribute('class', 'message');
        editConfirm.innerHTML = data.message;

        // TODO: Error message handling on post edit

        // Execute new elements create
        parent.removeChild(input);
        parent.insertBefore(newContentElement, sibling);
        parent.insertBefore(editConfirm, sibling);

      });
    }
  )
  .catch(function(error){
    console.log('Fetch error: ' + error);
  });

}

// Get all edit buttons
const editButtons = document.querySelectorAll('.postEdit');

editButtons.forEach(function(button){

  // Get the post id
  const postID = button.dataset.postid;

  // Add event listener and run function
  button.addEventListener('click', function(){
    postEdit(postID);
  })
});
<|endoftext|>


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

  var Monster = VAGABOND.ENTITIES.Monster;

  var milo = new Monster().init(2, 5, 30, 4, 6);

  console.log(milo.getCoor());
  console.log(milo.getHealth());
  console.log(milo.getDefense());
  milo.takeDamage(10);
  console.log(milo.getHealth());

  var otis = new Monster().init(0, 0, 50, 30, 10);
  console.log(otis.getCoor());
  console.log(milo.getCoor());
  console.log(milo.getHealth());
  console.log(otis);
})();
<commit_msg>Flesh out object composition model<commit_after>var hasID = function(initID) {
  var id = initID;

  return {
    getID: function() {
      return id;
    },

    setID: function(newID) {
      id = newID;
    }
  };
};

var hasName = function(initName) {
  var name = initName;

  return {
    getName: function() {
      return name;
    },

    setName: function(newName) {
      name = newName;
    }
  };
};

var hasCoor = function(initX, initY) {
  var x = initX;
  var y = initY;

  return {
    getX: function() {
      return x;
    },

    getY: function() {
      return y;
    },

    setX: function(newX) {
      x = newX;
    },

    setY: function(newY) {
      y = newY;
    }
  };
};

var hasMovableCoor = function(x, y) {
  var coor = hasCoor(x, y);

  return {
    getX: coor.getX,
    getY: coor.getY,
    setX: coor.setX,
    setY: coor.setY,
    move: function(dx, dy) {
      setX(getX + dx);
      setY(getY + dy);
    }
  };
};

var hasHealth = function(initialHealth) {
  var health = initialHealth;

  return {
    changeHealth: function(dHealth) {
      health += dHealth;
    },

    setHealth: function(newHealth) {
      health = newHealth;
    },

    getHealth: function() {
      return health;
    }
  };
};

var KillableEntity = function(x, y, hp) {
  var coorFuncs = hasCoor(x, y);
  var healthFuncs = hasHealth(hp);

  return {
    getX: coorFuncs.getX,
    getY: coorFuncs.getY,
    setX: coorFuncs.setX,
    setY: coorFuncs.setY,
    changeHealth: healthFuncs.changeHealth,
    setHealth: healthFuncs.setHealth,
    getHealth: healthFuncs.getHealth
  };
};

var MovableKillableEntity = function(x, y, hp) {
  var movableCoorFuncs = hasMovableCoor(x, y);
  var healthFuncs = hasHealth(hp);

  return {
    getX: movableCoorFuncs.getX,
    getY: movableCoorFuncs.getY,
    setX: movableCoorFuncs.setX,
    setY: movableCoorFuncs.setY,
    move: movableCoorFuncs.move,
    changeHealth: healthFuncs.changeHealth,
    setHealth: healthFuncs.setHealth,
    getHealth: healthFuncs.getHealth
  };
};

var Monster = function(id, name, x, y, hp) {
  var idFuncs = hasID(id);
  var nameFuncs = hasName(name);
  var mke = MovableKillableEntity(x, y, hp);

  return {
    getID: idFuncs.getID,
    setID: idFuncs.setID,
    getName: nameFuncs.getName,
    setName: nameFuncs.setName,
    getX: mke.getX,
    getY: mke.getY,
    setX: mke.setX,
    setY: mke.setY,
    move: mke.move,
    changeHealth: mke.changeHealth,
    setHealth: mke.setHealth,
    getHealth: mke.getHealth
  };
};

var Wall = KillableEntity;
var milo = new Monster(0, 'Milo', 2, 4, 30);
var otis = new Wall(5, 10, 50);

console.log(milo, milo.getHealth());
console.log(otis, otis.getHealth());

/*(function() {
  'use strict';

  var Monster = VAGABOND.ENTITIES.Monster;

  var milo = new Monster().init(2, 5, 30, 4, 6);

  console.log(milo.getCoor());
  console.log(milo.getHealth());
  console.log(milo.getDefense());
  milo.takeDamage(10);
  console.log(milo.getHealth());

  var otis = new Monster().init(0, 0, 50, 30, 10);
  console.log(otis.getCoor());
  console.log(milo.getCoor());
  console.log(milo.getHealth());
  console.log(otis);
})();
*/
<|endoftext|>


<commit_before>angular.module("OpenHq").controller("ArchivedProjectsController", function($scope, $routeParams, $location, Project, ProjectsRepository) {
  Project.query({archived: true}).then(function(projects) {
    $scope.archived_projects = projects;
  });

  $scope.restoreProject = function(project) {
    ProjectsRepository.restore(project.slug).then(function(project){
      // TODO: add a notification
      $location.url('/projects/'+project.slug);
    });
  };
});<commit_msg>didnt need the routeParams<commit_after>angular.module("OpenHq").controller("ArchivedProjectsController", function($scope, $location, Project, ProjectsRepository) {
  Project.query({archived: true}).then(function(projects) {
    $scope.archived_projects = projects;
  });

  $scope.restoreProject = function(project) {
    ProjectsRepository.restore(project.slug).then(function(project){
      // TODO: add a notification
      $location.url('/projects/'+project.slug);
    });
  };
});<|endoftext|>