<commit_before>var fs = require('fs');
var http = require('http');
var request = require('request');
var apputil = require("./util.js");

var commandJsonDir = function() {
		return './public/commands.json';
};

var sortObject = function (o) {
    var sorted = {},
    key, a = [];
    for (key in o) {
        if (o.hasOwnProperty(key)) {
            a.push(key);
        }
    }
    a.sort();
    for (key = 0; key < a.length; key++) {
        sorted[a[key]] = o[a[key]];
    }
    return sorted;
};

var listCommands = function(callback) {
	apputil.readFile(commandJsonDir(), function (error, commandsFileContent){
		if (error) {
			callback(error);
		} else {
			var storedCommands = null;
			try {
				storedCommands = JSON.parse(commandsFileContent);
			} catch(e) {
				apputil.log("Error: Could not parse stored commands:\r\n" + e);
				callback(e);
			}
			try {
				var list = "<!doctype html><meta charset=\"utf-8\">" +
					"<title>Taco Bot Commands</title>
Available Commands
" +
					"
" +
					"
Command	Response
";
				storedCommands = sortObject(storedCommands);
				for (var storedCommand in storedCommands) {
					list += "
!" + storedCommand + "	";
					// If JSON object is an array list out the options
					if (Object.prototype.toString.call(storedCommand) == "[object Array]") {
						for (var item in storedCommand) {
							if (storedCommand[item].indexOf("http") > -1 ||
								storedCommand[item].indexOf("www") > -1) {
								list += " \"" +
								storedCommand[item] + "
";
							} else {
								list += "\" " + storedCommand[item] + "
";
							}
						}
					} else {
						// If not, just put the string content in the table slot
						if (storedCommands[storedCommand].indexOf("http") > -1) {
							list += "" +
							storedCommands[storedCommand] + "";
						} else {
							list += storedCommands[storedCommand];
						}
					}
					list += "
";
				}
				list += "
";
				callback(null, list);
			} catch(err) {
				apputil.log("Error generating command list html:\r\n" + err);
				callback(err);
			}
		}
	});
};

var updateCommands = function(postData, callback) {
	var newCommand = null;
	var invalidCommandReg = /\W|_/g;
	try {
		newCommand = JSON.parse(postData);
		if (!newCommand) {
			callback("Submitted command is null");
		} else if (!newCommand.name) {
			callback("Submitted command is missing command.name");
		} else if (!newCommand.value) {
			callback("Submitted command is missing command.value");
		} else if (invalidCommandReg.test(newCommand.name)) {
			callback("Command name must not have any non-alphanumeric characters");
		} else if (newCommand.name.indexOf(" ") > -1) {
			callback("Command name must not have any non-alphanumeric characters");
		} else {
			var currentCommands = null;
			try {
				currentCommands = JSON.parse(fs.readFileSync(commandJsonDir()));
			} catch(err) {
				var message = "Error parsing commands.json:\r\n" + err;
				apputil.log(message);
				callback(err);
				// Below: disallows adding invalid commands
				// This shouldn't be needed, but just to be sure (paranoia)
				currentCommands = null;
			}
			if (currentCommands) {
				try {
					currentCommands[newCommand.name.toLowerCase()] = newCommand.value;
					fs.writeFileSync(commandJsonDir(), JSON.stringify(currentCommands, null, 2));
					callback(null, "Command successfully added: !" +
						newCommand.name.toLowerCase() + " returns \"" +
						newCommand.value + "\"");
				} catch (error) {
					var message = "Error parsing commands.json while updating commands:\r\n" + error;
					apputil.log(message);
					callback(message);
				}
			} else {
				var message = "Error updating commands:\r\n\t Data read from commands.json was null?";
				apputil.log(message);
				callback(message);
			}
		}
	} catch(err) {
		var message = "Error: Submitted data was an invalid command or had invalid JSON:\r\n" + err;
		apputil.log(message);
		callback(message);
	}

};

var parseMessage = function(message) {
	var pattern = /\!([a-zA-Z0-9]+)/g;
	var matches = message.match(pattern);
	if (matches) {
		for (var i = 0; i < matches.length; i++) {
			matches[i] = matches[i].replace(/\!/g, '');
		}
	}
	return matches;
};

var jokePick = 0;
var huskerPick = 0;
var jokeStartup = true;
var huskerStartup = true;
var jokes = [];
var husker = [];
try {
	jokes = JSON.parse(fs.readFileSync(commandJsonDir())).joke;
	husker = JSON.parse(fs.readFileSync(commandJsonDir())).huskersermon;
}
catch (err) { apputil.log("Error: Failed to read command.json at startup\r\n" + err); }
var checkForCommandArray = function(command, commandObject, callback) {
	if (command == "joke" && Object.prototype.toString.call(commandObject) == "[object Array]") {
		console.log("jokes.length: " + jokes.length);
		// Initial joke shuffle
		console.log("Startup: " + jokeStartup);
		if (jokeStartup) {
			console.log("Hit code: jokePick = 0");
			jokes = apputil.shuffle(jokes);
			jokeStartup = false;
		}
		// Reset pool if jokePicks are exhausted
		if (jokePick >= jokes.length - 1) {
			console.log("Hit code: jokePick >= jokes.length - 1");
			jokes = apputil.shuffle(jokes);
			jokePick = 0;
		}
		// Reset pool if new jokes are added
		console.log("jokes.length: " + jokes.length + " commandObject.length: " + commandObject.length);
		if (jokes.length < commandObject.length) {
			console.log("Hit code: jokes.length < commandObject.length - 1");
			jokes = [];
			try { jokes = JSON.parse(fs.readFileSync(commandJsonDir())).joke; }
			catch (err) {
				var errmessage = "Error: Failed to reload command.json for new jokes\r\n" + err;
				apputil.log(errmessage);
				callback(errmessage);
			}
			jokes = apputil.shuffle(jokes);
			jokePick = 0;
		}
		var pickObject = jokes[jokePick];
		console.log("jokes.length: " + jokes.length +
			"\r\ncommandObject.length: " + commandObject.length + "\r\njokePick: " + jokePick);
		jokePick++;
		callback(null, pickObject);
	} else if(command == "huskersermon" && Object.prototype.toString.call(commandObject) == "[object Array]") {
		console.log("husker.length: " + husker.length);
		// Initial joke shuffle
		console.log("Startup: " + huskerStartup);
		if (huskerStartup) {
			console.log("Hit code: huskerPick = 0");
			husker = apputil.shuffle(husker);
			huskerStartup = false;
		}
		// Reset pool if huskerStartups are exhausted
		if (huskerPick >= husker.length - 1) {
			console.log("Hit code: huskerPick >= husker.length - 1");
			husker = apputil.shuffle(husker);
			huskerPick = 0;
		}
		// Reset pool if new husker are added
		console.log("husker.length: " + husker.length + " commandObject.length: " + commandObject.length);
		if (husker.length < commandObject.length) {
			console.log("Hit code: husker.length < commandObject.length - 1");
			husker = [];
			try { husker = JSON.parse(fs.readFileSync(commandJsonDir())).joke; }
			catch (err) {
				var errmessage = "Error: Failed to reload command.json for new husker\r\n" + err;
				apputil.log(errmessage);
				callback(errmessage);
			}
			husker = apputil.shuffle(husker);
			huskerPick = 0;
		}
		var pickObject = husker[huskerPick];
		console.log("husker.length: " + husker.length +
			"\r\ncommandObject.length: " + commandObject.length + "\r\nhuskerPick: " + huskerPick);
		huskerPick++;
		callback(null, pickObject);

	} else {
		callback(null, commandObject);
	}
};

var processCommand = function(command, post, config) {
	apputil.readFile(commandJsonDir(), function (error, commandsFileContent){
		if (error) {
			apputil.log(error);
		} else {
			var storedCommands = null;
			try {
				storedCommands = JSON.parse(commandsFileContent);
			} catch(e) {
				apputil.log("Error: Could not parse stored commands:\r\n" + e);
			}
			var commandFound = false;
			for (var storedCommand in storedCommands) {
				if (command.toLowerCase() == storedCommand) {
					commandFound = true;
					checkForCommandArray(storedCommand, storedCommands[storedCommand],
						function(err, reply) {
						if (!err) {
							apputil.groupme_text_post(reply, config, function(e, result){
								if (!e) {
									apputil.log(result);
								} else {
									apputil.log(e);
								}
							});
						} else {
							apputil.log(err);
						}
					});

				}
			}
			if (!commandFound) {
				apputil.log("Command not found: " + command.toLowerCase() + "\r\n", "commands_not_found.txt");
			}
		}
	});
};

module.exports = {

	commandJsonDir: commandJsonDir,

	list: listCommands,

	update : updateCommands,

	investigate: function(groupmePost, config) {
		try {
			var messageObject = JSON.parse(groupmePost);
		} catch (err) {
			apputil.log("Bad JSON in message from GroupMe:\r\nMessage:\r\n" + groupmePost
				+ "\r\nError:\r\n" + err);
		}
		if (messageObject) {
			var commands = parseMessage(messageObject.text);
			if (commands &&
				messageObject.sender_id != "329044" &&
				messageObject.sender_id != "329214" &&
				messageObject.sender_id != "356826") {
				for (var i = 0; i < commands.length; i++) {
					processCommand(commands[i], messageObject, config);
				}
			} // No else actions, since this will be done every GroupMe message
		}
	}
};
<commit_msg>refactoring the investigate function to handle pre-parsed objects. added comments. if there are no commands in a message parseMessage will return an empty array.<commit_after>var fs = require('fs');
var http = require('http');
var request = require('request');
var apputil = require("./util.js");

var commandJsonDir = function() {
		return './public/commands.json';
};

var sortObject = function (o) {
    var sorted = {},
    key, a = [];
    for (key in o) {
        if (o.hasOwnProperty(key)) {
            a.push(key);
        }
    }
    a.sort();
    for (key = 0; key < a.length; key++) {
        sorted[a[key]] = o[a[key]];
    }
    return sorted;
};

var listCommands = function(callback) {
	apputil.readFile(commandJsonDir(), function (error, commandsFileContent){
		if (error) {
			callback(error);
		} else {
			var storedCommands = null;
			try {
				storedCommands = JSON.parse(commandsFileContent);
			} catch(e) {
				apputil.log("Error: Could not parse stored commands:\r\n" + e);
				callback(e);
			}
			try {
				var list = "<!doctype html><meta charset=\"utf-8\">" +
					"<title>Taco Bot Commands</title>
Available Commands
" +
					"
" +
					"
Command	Response
";
				storedCommands = sortObject(storedCommands);
				for (var storedCommand in storedCommands) {
					list += "
!" + storedCommand + "	";
					// If JSON object is an array list out the options
					if (Object.prototype.toString.call(storedCommand) == "[object Array]") {
						for (var item in storedCommand) {
							if (storedCommand[item].indexOf("http") > -1 ||
								storedCommand[item].indexOf("www") > -1) {
								list += " \"" +
								storedCommand[item] + "
";
							} else {
								list += "\" " + storedCommand[item] + "
";
							}
						}
					} else {
						// If not, just put the string content in the table slot
						if (storedCommands[storedCommand].indexOf("http") > -1) {
							list += "" +
							storedCommands[storedCommand] + "";
						} else {
							list += storedCommands[storedCommand];
						}
					}
					list += "
";
				}
				list += "
";
				callback(null, list);
			} catch(err) {
				apputil.log("Error generating command list html:\r\n" + err);
				callback(err);
			}
		}
	});
};

var updateCommands = function(postData, callback) {
	var newCommand = null;
	var invalidCommandReg = /\W|_/g;
	try {
		newCommand = JSON.parse(postData);
		if (!newCommand) {
			callback("Submitted command is null");
		} else if (!newCommand.name) {
			callback("Submitted command is missing command.name");
		} else if (!newCommand.value) {
			callback("Submitted command is missing command.value");
		} else if (invalidCommandReg.test(newCommand.name)) {
			callback("Command name must not have any non-alphanumeric characters");
		} else if (newCommand.name.indexOf(" ") > -1) {
			callback("Command name must not have any non-alphanumeric characters");
		} else {
			var currentCommands = null;
			try {
				currentCommands = JSON.parse(fs.readFileSync(commandJsonDir()));
			} catch(err) {
				var message = "Error parsing commands.json:\r\n" + err;
				apputil.log(message);
				callback(err);
				// Below: disallows adding invalid commands
				// This shouldn't be needed, but just to be sure (paranoia)
				currentCommands = null;
			}
			if (currentCommands) {
				try {
					currentCommands[newCommand.name.toLowerCase()] = newCommand.value;
					fs.writeFileSync(commandJsonDir(), JSON.stringify(currentCommands, null, 2));
					callback(null, "Command successfully added: !" +
						newCommand.name.toLowerCase() + " returns \"" +
						newCommand.value + "\"");
				} catch (error) {
					var message = "Error parsing commands.json while updating commands:\r\n" + error;
					apputil.log(message);
					callback(message);
				}
			} else {
				var message = "Error updating commands:\r\n\t Data read from commands.json was null?";
				apputil.log(message);
				callback(message);
			}
		}
	} catch(err) {
		var message = "Error: Submitted data was an invalid command or had invalid JSON:\r\n" + err;
		apputil.log(message);
		callback(message);
	}

};

// Look for segments of a message that have an exclamation followed by one or
// more alphaneumeric characters
var parseMessage = function(message) {
	var pattern = /\!([a-zA-Z0-9]+)/g;
	var matches = message.match(pattern);

	if (matches) {
		for (var i = 0; i < matches.length; i++) {
			matches[i] = matches[i].replace(/\!/g, '');
		}
	}
	else {
		// if no matches are found, return an empty array
		// this makes it easier for the function's clients to handle because they
		// do not have to worry about nulls.
		return [];
	}
	return matches;
};

var jokePick = 0;
var huskerPick = 0;
var jokeStartup = true;
var huskerStartup = true;
var jokes = [];
var husker = [];
try {
	jokes = JSON.parse(fs.readFileSync(commandJsonDir())).joke;
	husker = JSON.parse(fs.readFileSync(commandJsonDir())).huskersermon;
}
catch (err) { apputil.log("Error: Failed to read command.json at startup\r\n" + err); }
var checkForCommandArray = function(command, commandObject, callback) {
	if (command == "joke" && Object.prototype.toString.call(commandObject) == "[object Array]") {
		console.log("jokes.length: " + jokes.length);
		// Initial joke shuffle
		console.log("Startup: " + jokeStartup);
		if (jokeStartup) {
			console.log("Hit code: jokePick = 0");
			jokes = apputil.shuffle(jokes);
			jokeStartup = false;
		}
		// Reset pool if jokePicks are exhausted
		if (jokePick >= jokes.length - 1) {
			console.log("Hit code: jokePick >= jokes.length - 1");
			jokes = apputil.shuffle(jokes);
			jokePick = 0;
		}
		// Reset pool if new jokes are added
		console.log("jokes.length: " + jokes.length + " commandObject.length: " + commandObject.length);
		if (jokes.length < commandObject.length) {
			console.log("Hit code: jokes.length < commandObject.length - 1");
			jokes = [];
			try { jokes = JSON.parse(fs.readFileSync(commandJsonDir())).joke; }
			catch (err) {
				var errmessage = "Error: Failed to reload command.json for new jokes\r\n" + err;
				apputil.log(errmessage);
				callback(errmessage);
			}
			jokes = apputil.shuffle(jokes);
			jokePick = 0;
		}
		var pickObject = jokes[jokePick];
		console.log("jokes.length: " + jokes.length +
			"\r\ncommandObject.length: " + commandObject.length + "\r\njokePick: " + jokePick);
		jokePick++;
		callback(null, pickObject);
	} else if(command == "huskersermon" && Object.prototype.toString.call(commandObject) == "[object Array]") {
		console.log("husker.length: " + husker.length);
		// Initial joke shuffle
		console.log("Startup: " + huskerStartup);
		if (huskerStartup) {
			console.log("Hit code: huskerPick = 0");
			husker = apputil.shuffle(husker);
			huskerStartup = false;
		}
		// Reset pool if huskerStartups are exhausted
		if (huskerPick >= husker.length - 1) {
			console.log("Hit code: huskerPick >= husker.length - 1");
			husker = apputil.shuffle(husker);
			huskerPick = 0;
		}
		// Reset pool if new husker are added
		console.log("husker.length: " + husker.length + " commandObject.length: " + commandObject.length);
		if (husker.length < commandObject.length) {
			console.log("Hit code: husker.length < commandObject.length - 1");
			husker = [];
			try { husker = JSON.parse(fs.readFileSync(commandJsonDir())).joke; }
			catch (err) {
				var errmessage = "Error: Failed to reload command.json for new husker\r\n" + err;
				apputil.log(errmessage);
				callback(errmessage);
			}
			husker = apputil.shuffle(husker);
			huskerPick = 0;
		}
		var pickObject = husker[huskerPick];
		console.log("husker.length: " + husker.length +
			"\r\ncommandObject.length: " + commandObject.length + "\r\nhuskerPick: " + huskerPick);
		huskerPick++;
		callback(null, pickObject);

	} else {
		callback(null, commandObject);
	}
};

var processCommand = function(command, post, config) {
	apputil.readFile(commandJsonDir(), function (error, commandsFileContent){
		if (error) {
			apputil.log(error);
		} else {
			var storedCommands = null;
			try {
				storedCommands = JSON.parse(commandsFileContent);
			} catch(e) {
				apputil.log("Error: Could not parse stored commands:\r\n" + e);
			}
			var commandFound = false;
			for (var storedCommand in storedCommands) {
				if (command.toLowerCase() == storedCommand) {
					commandFound = true;
					checkForCommandArray(storedCommand, storedCommands[storedCommand],
						function(err, reply) {
						if (!err) {
							apputil.groupme_text_post(reply, config, function(e, result){
								if (!e) {
									apputil.log(result);
								} else {
									apputil.log(e);
								}
							});
						} else {
							apputil.log(err);
						}
					});

				}
			}
			if (!commandFound) {
				apputil.log("Command not found: " + command.toLowerCase() + "\r\n", "commands_not_found.txt");
			}
		}
	});
};

// Check for known ignored accounts (bots, kuranden, etc)
// TODO: Move some of this into configuration maybe?
var isIgnoredAccount = function(groupmePost) {
	var senderId = groupmePost.sender_id;
	var senderType = groupmePost.sender_type;

	return senderId === "329044"
		|| senderId === "329214"
		|| senderId === "356826"
		|| senderType === "bot" // ignore all bot posts, we may want to relax this restriction in the future
}

module.exports = {

	commandJsonDir: commandJsonDir,

	list: listCommands,

	update : updateCommands,

	investigate: function(groupmePost, config) {
		if (isIgnoredAccount(groupmePost))
		{
			// if the account is an ignored account don't do anything more with the
			// post
			return;
		}

		// find commands in the text of the groupme message and process them
		var commands = parseMessage(groupmePost.text);
		for (var i = 0; i < commands.length; i++) {
			processCommand(commands[i], groupmePost, config);
		}
	}
};
<|endoftext|>


<commit_before>/**
 * `modules/analytics-4` data store: properties.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import invariant from 'invariant';

/**
 * Internal dependencies
 */
import API from 'googlesitekit-api';
import Data from 'googlesitekit-data';
import { STORE_NAME, PROPERTY_CREATE, MAX_WEBDATASTREAMS_PER_BATCH } from './constants';
import { normalizeURL } from '../../../util';
import { createFetchStore } from '../../../googlesitekit/data/create-fetch-store';
import { isValidPropertySelection } from '../utils/validation';
import { actions as webDataStreamActions } from './webdatastreams';
import { isValidAccountID } from '../../analytics/util';
const { commonActions } = Data;

const fetchGetPropertyStore = createFetchStore( {
	baseName: 'getProperty',
	controlCallback( { propertyID } ) {
		return API.get( 'modules', 'analytics-4', 'property', { propertyID }, {
			useCache: true,
		} );
	},
	reducerCallback( state, property, { propertyID } ) {
		return {
			...state,
			propertiesByID: {
				...state.propertiesByID,
				[ propertyID ]: property,
			},
		};
	},
	argsToParams( propertyID ) {
		return { propertyID };
	},
	validateParams( { propertyID } = {} ) {
		invariant( propertyID, 'propertyID is required.' );
	},
} );

const fetchGetPropertiesStore = createFetchStore( {
	baseName: 'getProperties',
	controlCallback( { accountID } ) {
		return API.get( 'modules', 'analytics-4', 'properties', { accountID }, {
			useCache: true,
		} );
	},
	reducerCallback( state, properties, { accountID } ) {
		return {
			...state,
			properties: {
				...state.properties,
				[ accountID ]: properties,
			},
			propertiesByID: accountID && state.properties[ accountID ]?.reduce(
				( accum, property ) => ( { ...accum, [ property._id ]: property } ),
				state.propertiesByID || {},
			),
		};
	},
	argsToParams( accountID ) {
		return { accountID };
	},
	validateParams( { accountID } = {} ) {
		invariant( accountID, 'accountID is required.' );
	},
} );

const fetchCreatePropertyStore = createFetchStore( {
	baseName: 'createProperty',
	controlCallback( { accountID } ) {
		return API.set( 'modules', 'analytics-4', 'create-property', { accountID } );
	},
	reducerCallback( state, property, { accountID } ) {
		return {
			...state,
			properties: {
				...state.properties,
				[ accountID ]: [
					...( state.properties[ accountID ] || [] ),
					property,
				],
			},
		};
	},
	argsToParams( accountID ) {
		return { accountID };
	},
	validateParams( { accountID } = {} ) {
		invariant( accountID, 'accountID is required.' );
	},
} );

const baseInitialState = {
	properties: {},
	propertiesByID: {},
};

const baseActions = {
	/**
	 * Creates a new GA4 property.
	 *
	 * @since 1.31.0
	 *
	 * @param {string} accountID Analytics account ID.
	 * @return {Object} Object with `response` and `error`.
	 */
	createProperty( accountID ) {
		invariant( accountID, 'accountID is required.' );

		return ( function*() {
			const { response, error } = yield fetchCreatePropertyStore.actions.fetchCreateProperty( accountID );
			return { response, error };
		}() );
	},

	/**
	 * Sets the given property and related fields in the store.
	 *
	 * @since 1.31.0
	 *
	 * @param {string} propertyID GA4 property ID.
	 * @return {Object} A Generator function.
	 */
	selectProperty( propertyID ) {
		invariant( isValidPropertySelection( propertyID ), 'A valid propertyID selection is required.' );

		return ( function* () {
			const registry = yield Data.commonActions.getRegistry();

			registry.dispatch( STORE_NAME ).setPropertyID( propertyID );
			registry.dispatch( STORE_NAME ).setWebDataStreamID( '' );
			registry.dispatch( STORE_NAME ).setMeasurementID( '' );

			if ( PROPERTY_CREATE === propertyID ) {
				return;
			}

			yield webDataStreamActions.waitForWebDataStreams( propertyID );

			const webdatastream = registry.select( STORE_NAME ).getMatchingWebDataStream( propertyID );
			if ( webdatastream ) {
				registry.dispatch( STORE_NAME ).setWebDataStreamID( webdatastream._id );
				registry.dispatch( STORE_NAME ).setMeasurementID( webdatastream.measurementId ); // eslint-disable-line sitekit/acronym-case
			}
		}() );
	},

	/**
	 * Matches a property by URL.
	 *
	 * @since n.e.x.t
	 *
	 * @param {Array.<number>}        properties Array of property IDs.
	 * @param {Array.<string>|string} url        A list of URLs or a signle URL to match properties.
	 * @return {Object} A property object if found.
	 */
	*matchPropertyByURL( properties, url ) {
		const registry = yield commonActions.getRegistry();
		const urls = ( Array.isArray( url ) ? url : [ url ] ).map( normalizeURL );

		for ( let i = 0; i < properties.length; i += MAX_WEBDATASTREAMS_PER_BATCH ) {
			const chunk = properties.slice( i, i + MAX_WEBDATASTREAMS_PER_BATCH );
			const webdatastreams = yield commonActions.await(
				registry.__experimentalResolveSelect( STORE_NAME ).getWebDataStreamsBatch( chunk ),
			);

			for ( const propertyID in webdatastreams ) {
				for ( const webdatastream of webdatastreams[ propertyID ] ) {
					for ( const singleURL of urls ) {
						if ( singleURL === normalizeURL( webdatastream.defaultUri ) ) {
							return yield commonActions.await(
								registry.__experimentalResolveSelect( STORE_NAME ).getProperty( propertyID ),
							);
						}
					}
				}
			}
		}

		return null;
	},

	/**
	 * Matches a property by measurement ID.
	 *
	 * @since n.e.x.t
	 *
	 * @param {Array.<number>}        properties    Array of property IDs.
	 * @param {Array.<string>|string} measurementID A list of measurement IDs or a signle measurement ID to match properties.
	 * @return {Object} A property object if found.
	 */
	*matchPropertyByMeasurementID( properties, measurementID ) {
		const registry = yield commonActions.getRegistry();
		const measurementIDs = Array.isArray( measurementID ) ? measurementID : [ measurementID ];

		for ( let i = 0; i < properties.length; i += MAX_WEBDATASTREAMS_PER_BATCH ) {
			const chunk = properties.slice( i, i + MAX_WEBDATASTREAMS_PER_BATCH );
			const webdatastreams = yield commonActions.await(
				registry.__experimentalResolveSelect( STORE_NAME ).getWebDataStreamsBatch( chunk ),
			);

			for ( const propertyID in webdatastreams ) {
				for ( const webdatastream of webdatastreams[ propertyID ] ) {
					for ( const singleMeasurementID of measurementIDs ) {
						if ( singleMeasurementID === webdatastream.measurementId ) { // eslint-disable-line sitekit/acronym-case
							return yield commonActions.await(
								registry.__experimentalResolveSelect( STORE_NAME ).getProperty( propertyID ),
							);
						}
					}
				}
			}
		}

		return null;
	},
};

const baseControls = {
};

const baseReducer = ( state, { type } ) => {
	switch ( type ) {
		default: {
			return state;
		}
	}
};

const baseResolvers = {
	*getProperties( accountID ) {
		if ( ! isValidAccountID( accountID ) ) {
			return;
		}

		const registry = yield Data.commonActions.getRegistry();
		// Only fetch properties if there are none in the store for the given account.
		const properties = registry.select( STORE_NAME ).getProperties( accountID );
		if ( properties === undefined ) {
			yield fetchGetPropertiesStore.actions.fetchGetProperties( accountID );
		}
	},
	*getProperty( propertyID ) {
		const registry = yield Data.commonActions.getRegistry();
		const property = registry.select( STORE_NAME ).getProperty( propertyID );
		if ( property === undefined ) {
			yield fetchGetPropertyStore.actions.fetchGetProperty( propertyID );
		}
	},
};

const baseSelectors = {
	/**
	 * Gets all GA4 properties this account can access.
	 *
	 * @since 1.31.0
	 *
	 * @param {Object} state     Data store's state.
	 * @param {string} accountID The GA4 Account ID to fetch properties for.
	 * @return {(Array.<Object>|undefined)} An array of GA4 properties; `undefined` if not loaded.
	 */
	getProperties( state, accountID ) {
		return state.properties[ accountID ];
	},

	/**
	 * Gets a property with specific ID.
	 *
	 * @since 1.31.0
	 *
	 * @param {Object} state      Data store's state.
	 * @param {string} propertyID The GA4 property ID to fetch property object for.
	 * @return {(Object|undefined)} A property object; `undefined` if not loaded.
	 */
	getProperty( state, propertyID ) {
		return state.propertiesByID[ propertyID ];
	},
};

const store = Data.combineStores(
	fetchCreatePropertyStore,
	fetchGetPropertiesStore,
	fetchGetPropertyStore,
	{
		initialState: baseInitialState,
		actions: baseActions,
		controls: baseControls,
		reducer: baseReducer,
		resolvers: baseResolvers,
		selectors: baseSelectors,
	}
);

export const initialState = store.initialState;
export const actions = store.actions;
export const controls = store.controls;
export const reducer = store.reducer;
export const resolvers = store.resolvers;
export const selectors = store.selectors;

export default store;
<commit_msg>Revert fix as breaks other tests.<commit_after>/**
 * `modules/analytics-4` data store: properties.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import invariant from 'invariant';

/**
 * Internal dependencies
 */
import API from 'googlesitekit-api';
import Data from 'googlesitekit-data';
import { STORE_NAME, PROPERTY_CREATE, MAX_WEBDATASTREAMS_PER_BATCH } from './constants';
import { normalizeURL } from '../../../util';
import { createFetchStore } from '../../../googlesitekit/data/create-fetch-store';
import { isValidPropertySelection } from '../utils/validation';
import { actions as webDataStreamActions } from './webdatastreams';
import { isValidAccountID } from '../../analytics/util';
const { commonActions } = Data;

const fetchGetPropertyStore = createFetchStore( {
	baseName: 'getProperty',
	controlCallback( { propertyID } ) {
		return API.get( 'modules', 'analytics-4', 'property', { propertyID }, {
			useCache: true,
		} );
	},
	reducerCallback( state, property, { propertyID } ) {
		return {
			...state,
			propertiesByID: {
				...state.propertiesByID,
				[ propertyID ]: property,
			},
		};
	},
	argsToParams( propertyID ) {
		return { propertyID };
	},
	validateParams( { propertyID } = {} ) {
		invariant( propertyID, 'propertyID is required.' );
	},
} );

const fetchGetPropertiesStore = createFetchStore( {
	baseName: 'getProperties',
	controlCallback( { accountID } ) {
		return API.get( 'modules', 'analytics-4', 'properties', { accountID }, {
			useCache: true,
		} );
	},
	reducerCallback( state, properties, { accountID } ) {
		return {
			...state,
			properties: {
				...state.properties,
				[ accountID ]: properties,
			},
			propertiesByID: properties.reduce(
				( accum, property ) => ( { ...accum, [ property._id ]: property } ),
				state.propertiesByID || {},
			),
		};
	},
	argsToParams( accountID ) {
		return { accountID };
	},
	validateParams( { accountID } = {} ) {
		invariant( accountID, 'accountID is required.' );
	},
} );

const fetchCreatePropertyStore = createFetchStore( {
	baseName: 'createProperty',
	controlCallback( { accountID } ) {
		return API.set( 'modules', 'analytics-4', 'create-property', { accountID } );
	},
	reducerCallback( state, property, { accountID } ) {
		return {
			...state,
			properties: {
				...state.properties,
				[ accountID ]: [
					...( state.properties[ accountID ] || [] ),
					property,
				],
			},
		};
	},
	argsToParams( accountID ) {
		return { accountID };
	},
	validateParams( { accountID } = {} ) {
		invariant( accountID, 'accountID is required.' );
	},
} );

const baseInitialState = {
	properties: {},
	propertiesByID: {},
};

const baseActions = {
	/**
	 * Creates a new GA4 property.
	 *
	 * @since 1.31.0
	 *
	 * @param {string} accountID Analytics account ID.
	 * @return {Object} Object with `response` and `error`.
	 */
	createProperty( accountID ) {
		invariant( accountID, 'accountID is required.' );

		return ( function*() {
			const { response, error } = yield fetchCreatePropertyStore.actions.fetchCreateProperty( accountID );
			return { response, error };
		}() );
	},

	/**
	 * Sets the given property and related fields in the store.
	 *
	 * @since 1.31.0
	 *
	 * @param {string} propertyID GA4 property ID.
	 * @return {Object} A Generator function.
	 */
	selectProperty( propertyID ) {
		invariant( isValidPropertySelection( propertyID ), 'A valid propertyID selection is required.' );

		return ( function* () {
			const registry = yield Data.commonActions.getRegistry();

			registry.dispatch( STORE_NAME ).setPropertyID( propertyID );
			registry.dispatch( STORE_NAME ).setWebDataStreamID( '' );
			registry.dispatch( STORE_NAME ).setMeasurementID( '' );

			if ( PROPERTY_CREATE === propertyID ) {
				return;
			}

			yield webDataStreamActions.waitForWebDataStreams( propertyID );

			const webdatastream = registry.select( STORE_NAME ).getMatchingWebDataStream( propertyID );
			if ( webdatastream ) {
				registry.dispatch( STORE_NAME ).setWebDataStreamID( webdatastream._id );
				registry.dispatch( STORE_NAME ).setMeasurementID( webdatastream.measurementId ); // eslint-disable-line sitekit/acronym-case
			}
		}() );
	},

	/**
	 * Matches a property by URL.
	 *
	 * @since n.e.x.t
	 *
	 * @param {Array.<number>}        properties Array of property IDs.
	 * @param {Array.<string>|string} url        A list of URLs or a signle URL to match properties.
	 * @return {Object} A property object if found.
	 */
	*matchPropertyByURL( properties, url ) {
		const registry = yield commonActions.getRegistry();
		const urls = ( Array.isArray( url ) ? url : [ url ] ).map( normalizeURL );

		for ( let i = 0; i < properties.length; i += MAX_WEBDATASTREAMS_PER_BATCH ) {
			const chunk = properties.slice( i, i + MAX_WEBDATASTREAMS_PER_BATCH );
			const webdatastreams = yield commonActions.await(
				registry.__experimentalResolveSelect( STORE_NAME ).getWebDataStreamsBatch( chunk ),
			);

			for ( const propertyID in webdatastreams ) {
				for ( const webdatastream of webdatastreams[ propertyID ] ) {
					for ( const singleURL of urls ) {
						if ( singleURL === normalizeURL( webdatastream.defaultUri ) ) {
							return yield commonActions.await(
								registry.__experimentalResolveSelect( STORE_NAME ).getProperty( propertyID ),
							);
						}
					}
				}
			}
		}

		return null;
	},

	/**
	 * Matches a property by measurement ID.
	 *
	 * @since n.e.x.t
	 *
	 * @param {Array.<number>}        properties    Array of property IDs.
	 * @param {Array.<string>|string} measurementID A list of measurement IDs or a signle measurement ID to match properties.
	 * @return {Object} A property object if found.
	 */
	*matchPropertyByMeasurementID( properties, measurementID ) {
		const registry = yield commonActions.getRegistry();
		const measurementIDs = Array.isArray( measurementID ) ? measurementID : [ measurementID ];

		for ( let i = 0; i < properties.length; i += MAX_WEBDATASTREAMS_PER_BATCH ) {
			const chunk = properties.slice( i, i + MAX_WEBDATASTREAMS_PER_BATCH );
			const webdatastreams = yield commonActions.await(
				registry.__experimentalResolveSelect( STORE_NAME ).getWebDataStreamsBatch( chunk ),
			);

			for ( const propertyID in webdatastreams ) {
				for ( const webdatastream of webdatastreams[ propertyID ] ) {
					for ( const singleMeasurementID of measurementIDs ) {
						if ( singleMeasurementID === webdatastream.measurementId ) { // eslint-disable-line sitekit/acronym-case
							return yield commonActions.await(
								registry.__experimentalResolveSelect( STORE_NAME ).getProperty( propertyID ),
							);
						}
					}
				}
			}
		}

		return null;
	},
};

const baseControls = {
};

const baseReducer = ( state, { type } ) => {
	switch ( type ) {
		default: {
			return state;
		}
	}
};

const baseResolvers = {
	*getProperties( accountID ) {
		if ( ! isValidAccountID( accountID ) ) {
			return;
		}

		const registry = yield Data.commonActions.getRegistry();
		// Only fetch properties if there are none in the store for the given account.
		const properties = registry.select( STORE_NAME ).getProperties( accountID );
		if ( properties === undefined ) {
			yield fetchGetPropertiesStore.actions.fetchGetProperties( accountID );
		}
	},
	*getProperty( propertyID ) {
		const registry = yield Data.commonActions.getRegistry();
		const property = registry.select( STORE_NAME ).getProperty( propertyID );
		if ( property === undefined ) {
			yield fetchGetPropertyStore.actions.fetchGetProperty( propertyID );
		}
	},
};

const baseSelectors = {
	/**
	 * Gets all GA4 properties this account can access.
	 *
	 * @since 1.31.0
	 *
	 * @param {Object} state     Data store's state.
	 * @param {string} accountID The GA4 Account ID to fetch properties for.
	 * @return {(Array.<Object>|undefined)} An array of GA4 properties; `undefined` if not loaded.
	 */
	getProperties( state, accountID ) {
		return state.properties[ accountID ];
	},

	/**
	 * Gets a property with specific ID.
	 *
	 * @since 1.31.0
	 *
	 * @param {Object} state      Data store's state.
	 * @param {string} propertyID The GA4 property ID to fetch property object for.
	 * @return {(Object|undefined)} A property object; `undefined` if not loaded.
	 */
	getProperty( state, propertyID ) {
		return state.propertiesByID[ propertyID ];
	},
};

const store = Data.combineStores(
	fetchCreatePropertyStore,
	fetchGetPropertiesStore,
	fetchGetPropertyStore,
	{
		initialState: baseInitialState,
		actions: baseActions,
		controls: baseControls,
		reducer: baseReducer,
		resolvers: baseResolvers,
		selectors: baseSelectors,
	}
);

export const initialState = store.initialState;
export const actions = store.actions;
export const controls = store.controls;
export const reducer = store.reducer;
export const resolvers = store.resolvers;
export const selectors = store.selectors;

export default store;
<|endoftext|>


<commit_before>'use strict'

var path = require('path')
var rootPath = path.normalize(__dirname + '/../..')
var _ = require('lodash')
var baseLine = {
  root: rootPath,
  hostname: process.env.HOST || process.env.HOSTNAME,
  templateEngine: 'swig',
  // The secret should be set to a non-guessable string that
  // is used to compute a session hash
  sessionSecret: 'MEANSTACKJS',
  // The name of the MongoDB collection to store sessions in
  sessionCollection: 'sessions',
  // The session cookie settings
  sessionCookie: {
    path: '/',
    httpOnly: true,
    // If secure is set to true then it will cause the cookie to be set
    // only when SSL-enabled (HTTPS) is used, and otherwise it won't
    // set a cookie. 'true' is recommended yet it requires the above
    // mentioned pre-requisite.
    secure: false,
    // Only set the maxAge to null if the cookie shouldn't be expired
    // at all. The cookie will expunge when the browser is closed.
    maxAge: null
  },
  html: {
    googleAnalytics: 'UA-71654331-1',
    keywords: 'MEAN, MEANSTACKJS, mongodb, expressjs, angularjs,nodejs, javascript',
    description: 'The Meanstack js is a opensource framework that is made for and by developers'
  },

  // The session cookie name
  sessionName: 'connect.meanstackjs',
  title: 'MEANSTACKJS',

  // AGGREGATION
  // bower_components -  Needs to be manually added below
  // modules - aggregated automatically
  // images - manually called in files
  // styles - manually called  & automatically compiles the global style scss in COMPILED Folder
  // uploads - Automatic uploads to be manually called in the files
  // USE EXTERNAL FILES - 'https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js',
  // OR USE INTERNAL FILES - '/bower_components/jquery/dist/jquery.js'
  assets: {
    js: [
      '/bower_components/socket.io-client/socket.io.js',
      '/bower_components/ng-file-upload/ng-file-upload-all.js',
      '/bower_components/angular-mocks/angular-mocks.js',
      '/bower_components/angular-cookies/angular-cookies.js',
      '/bower_components/angular-sanitize/angular-sanitize.js',
      '/bower_components/angular-animate/angular-animate.js',
      '/bower_components/angular-resource/angular-resource.js',
      '/bower_components/angular-ui-router/release/angular-ui-router.js',
      '/bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
      '/bower_components/angular-moment/angular-moment.js',
      '/bower_components/moment/moment.js',
      '/bower_components/lodash/lodash.js',
      '/bower_components/toastr/toastr.js',
      '/bower_components/bootstrap-sass/assets/javascripts/bootstrap.min.js',
      '/bower_components/angular/angular.js',
      '/bower_components/jquery/dist/jquery.js'
    ],
    css: [
      '/styles/compiled/global.style.css',
      '/bower_components/toastr/toastr.css'
    // '/bower_components/font-awesome/css/font-awesome.min.css'
    ]
  },
  buildreq: {
    console: true,
    response: {
      method: 'get',
      data: {},
      user: {},
      count: 0,
      hostname: '',
      type: '',
      actions: {
        prev: false,
        next: false,
        reload: false
      },
      delete: ['error']
    },
    query: {
      sort: '',
      limit: 20,
      select: '',
      filter: {},
      populateId: 'user',
      populateItems: '',
      lean: false,
      skip: 0,
      where: '',
      gt: 1,
      lt: 0,
      in: [],
      equal: '',
      errorMessage: 'Unknown Value'
    },
    routing: {
      schema: true,
      url: '/api/v1/',
      build: true
    }
  }
}
var settings
if (process.env.NODE_ENV === 'test') {
  settings = _.merge(baseLine, require('./environments/test.js'))
} else if (process.env.NODE_ENV === 'production') {
  settings = _.merge(baseLine, require('./environments/production.js'))
} else {
  settings = _.merge(baseLine, require('./environments/development.js'))
}

module.exports = settings
<commit_msg>#18 updated the settings for jwt<commit_after>'use strict'

var path = require('path')
var rootPath = path.normalize(__dirname + '/../..')
var _ = require('lodash')
var baseLine = {
  root: rootPath,
  hostname: process.env.HOST || process.env.HOSTNAME,
  templateEngine: 'swig',
  // JWT Object https://github.com/auth0/node-jsonwebtoken
  jwt: {
    // is used to compute a JWT SIGN
     secret: 'MEANSTACKJS',
     options:{
      expiresIn: 60 * 120 //60 seconds * 120  = 2 hours
     }
  },
  // is used to compute a session hash
  sessionSecret: 'MEANSTACKJS',
  // The name of the MongoDB collection to store sessions in
  sessionCollection: 'sessions',
  // The session cookie settings
  sessionCookie: {
    path: '/',
    httpOnly: true,
    // If secure is set to true then it will cause the cookie to be set
    // only when SSL-enabled (HTTPS) is used, and otherwise it won't
    // set a cookie. 'true' is recommended yet it requires the above
    // mentioned pre-requisite.
    secure: false,
    // Only set the maxAge to null if the cookie shouldn't be expired
    // at all. The cookie will expunge when the browser is closed.
    maxAge: null
  },
  html: {
    googleAnalytics: 'UA-71654331-1',
    keywords: 'MEAN, MEANSTACKJS, mongodb, expressjs, angularjs,nodejs, javascript',
    description: 'The Meanstack js is a opensource framework that is made for and by developers'
  },

  // The session cookie name
  sessionName: 'connect.meanstackjs',
  title: 'MEANSTACKJS',

  // AGGREGATION
  // bower_components -  Needs to be manually added below
  // modules - aggregated automatically
  // images - manually called in files
  // styles - manually called  & automatically compiles the global style scss in COMPILED Folder
  // uploads - Automatic uploads to be manually called in the files
  // USE EXTERNAL FILES - 'https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js',
  // OR USE INTERNAL FILES - '/bower_components/jquery/dist/jquery.js'
  assets: {
    js: [
      '/bower_components/angular-jwt/dist/angular-jwt.js',
      '/bower_components/socket.io-client/socket.io.js',
      '/bower_components/ng-file-upload/ng-file-upload-all.js',
      '/bower_components/angular-mocks/angular-mocks.js',
      '/bower_components/angular-cookies/angular-cookies.js',
      '/bower_components/angular-sanitize/angular-sanitize.js',
      '/bower_components/angular-animate/angular-animate.js',
      '/bower_components/angular-resource/angular-resource.js',
      '/bower_components/angular-ui-router/release/angular-ui-router.js',
      '/bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
      '/bower_components/angular-moment/angular-moment.js',
      '/bower_components/moment/moment.js',
      '/bower_components/lodash/lodash.js',
      '/bower_components/toastr/toastr.js',
      '/bower_components/bootstrap-sass/assets/javascripts/bootstrap.js',
      '/bower_components/angular/angular.js',
      '/bower_components/jquery/dist/jquery.js'
    ],
    css: [
      '/styles/compiled/global.style.css',
      '/bower_components/toastr/toastr.css'
    // '/bower_components/font-awesome/css/font-awesome.min.css'
    ]
  },
  buildreq: {
    console: true,
    response: {
      method: 'get',
      data: {},
      user: {},
      count: 0,
      hostname: '',
      type: '',
      actions: {
        prev: false,
        next: false,
        reload: false
      },
      delete: ['error']
    },
    query: {
      sort: '',
      limit: 20,
      select: '',
      filter: {},
      populateId: 'user',
      populateItems: '',
      lean: false,
      skip: 0,
      where: '',
      gt: 1,
      lt: 0,
      in: [],
      equal: '',
      errorMessage: 'Unknown Value'
    },
    routing: {
      schema: true,
      url: '/api/v1/',
      build: true
    }
  }
}
var settings
if (process.env.NODE_ENV === 'test') {
  settings = _.merge(baseLine, require('./environments/test.js'))
} else if (process.env.NODE_ENV === 'production') {
  settings = _.merge(baseLine, require('./environments/production.js'))
} else {
  settings = _.merge(baseLine, require('./environments/development.js'))
}

module.exports = settings
<|endoftext|>


<commit_before>var rotateThemes = function(){

	var THEMES = ['Blumenau', 'Floripa', 'Joinville', 'Lages'];
	var ugalContainer, themeTitleContainer, currTheme = 0;

	function init(){
		storeContainers();
		presentCurrentTheme();
	}

	function storeContainers(){
		themeTitleContainer = document.getElementById('themeTitle');
		ugalContainer = document.getElementById('ugalContainer');
	}

	function presentCurrentTheme(){
		renderTheme();
		printThemeTitle();
		centerThemeTitle();
		updateCurrentTheme();
	}

	function renderTheme(){
		ugal.init({
			container: ugalContainer.id,
			width: window.innerWidth,
			height: window.innerHeight,
			theme: THEMES[currTheme]
		});
	}

	function printThemeTitle(){
		themeTitleContainer.innerText = THEMES[currTheme];
	}

	function centerThemeTitle(){
		themeTitleContainer.style.marginLeft = getThemeTitleCenteredMargin('clientWidth');
		themeTitleContainer.style.marginTop = getThemeTitleCenteredMargin('clientHeight');
	}

	function getThemeTitleCenteredMargin(dimension){
		return parseInt((themeTitleContainer[dimension]/-2) + (ugalContainer[dimension]/2)) + 'px';
	}

	function updateCurrentTheme(){
		currTheme = currTheme < 3 ? ++currTheme : 0;
		setTimeout(presentCurrentTheme, 3000);
	}

	init();

};

window.onload = rotateThemes;<commit_msg>issue#19 Fixed Coloured-Only Gallery page title alignment<commit_after>var rotateThemes = function(){

	var THEMES = ['Blumenau', 'Floripa', 'Joinville', 'Lages'];
	var ugalContainer, themeTitleContainer, currTheme = 0;

	function init(){
		storeContainers();
		presentCurrentTheme();
	}

	function storeContainers(){
		themeTitleContainer = document.getElementById('themeTitle');
		ugalContainer = document.getElementById('ugalContainer');
	}

	function presentCurrentTheme(){
		renderTheme();
		printThemeTitle();
		setupThemeTitle();
		updateCurrentTheme();
	}

	function renderTheme(){
		ugal.init({
			container: ugalContainer.id,
			width: window.innerWidth,
			height: window.innerHeight,
			theme: THEMES[currTheme]
		});
	}

	function printThemeTitle(){
		themeTitleContainer.innerText = THEMES[currTheme];
	}

	function setupThemeTitle(){
		themeTitleContainer.style.color = '#FFF';
		themeTitleContainer.style.position = 'absolute';
		themeTitleContainer.style.zIndex = 10;
		themeTitleContainer.style.marginLeft = getThemeTitleCenteredMargin('clientWidth');
		themeTitleContainer.style.marginTop = getThemeTitleCenteredMargin('clientHeight');
	}

	function getThemeTitleCenteredMargin(dimension){
		return parseInt((themeTitleContainer[dimension]/-2) + (ugalContainer[dimension]/2)) + 'px';
	}

	function updateCurrentTheme(){
		currTheme = currTheme < 3 ? ++currTheme : 0;
		setTimeout(presentCurrentTheme, 3000);
	}

	init();

};

window.onload = rotateThemes;<|endoftext|>


<commit_before>'use strict';

var AbstractStore = require('stores/AbstractStore');
var assign = require('object-assign');
var GeoAppDispatcher = require('../dispatcher/GeoAppDispatcher');
var GeoAppActionsConstants = require('../constants/GeoAppActions');
var CHANGE_EVENT = 'change';
var LocalStoreDataProvider = require('stores/LocalStorageDataProvider');

var CategoriesStore = assign({}, AbstractStore, {

    getAllCategories: function () {
        return LocalStoreDataProvider.read(GeoAppActionsConstants.CATEGORIES_COLLECTION);
    }

});

GeoAppDispatcher.register(function (action) {
    switch (action.actionType) {
        case GeoAppActionsConstants.CATEGORY_CREATE:
            LocalStoreDataProvider.addCollectionItem(GeoAppActionsConstants.CATEGORIES_COLLECTION, action.rawData.name, action.rawData);
            CategoriesStore.emitChange();
            break;
        default:
    }

});

module.exports = CategoriesStore;
<commit_msg>remove unused var<commit_after>'use strict';

var AbstractStore = require('stores/AbstractStore');
var assign = require('object-assign');
var GeoAppDispatcher = require('../dispatcher/GeoAppDispatcher');
var GeoAppActionsConstants = require('../constants/GeoAppActions');
var LocalStoreDataProvider = require('stores/LocalStorageDataProvider');

var CategoriesStore = assign({}, AbstractStore, {

    getAllCategories: function () {
        return LocalStoreDataProvider.read(GeoAppActionsConstants.CATEGORIES_COLLECTION);
    }

});

GeoAppDispatcher.register(function (action) {
    switch (action.actionType) {
        case GeoAppActionsConstants.CATEGORY_CREATE:
            LocalStoreDataProvider.addCollectionItem(GeoAppActionsConstants.CATEGORIES_COLLECTION, action.rawData.name, action.rawData);
            CategoriesStore.emitChange();
            break;
        default:
    }

});

module.exports = CategoriesStore;
<|endoftext|>


<commit_before>// Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@vimperator.org>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the License.txt file included with this file.

const DEFAULT_FAVICON = "chrome://global/skin/icons/Portrait.png";

const Config = Module("config", ConfigBase, {
    init: function () {
        // don't wait too long when selecting new messages
        // GetThreadTree()._selectDelay = 300; // TODO: make configurable
    },

    /*** required options, no checks done if they really exist, so be careful ***/
    name: "Muttator",
    hostApplication: "Thunderbird",

    get mainWindowId() this.isComposeWindow ? "msgcomposeWindow" : "messengerWindow",

    /*** optional options, there are checked for existence and a fallback provided  ***/
    get features() this.isComposeWindow ? ["addressbook"] : ["hints", "mail", "marks", "addressbook", "tabs"],
    defaults: {
        titlestring: "Muttator"
    },

    toolbars: {
        composition: [["composeToolbar2"],                                   "Composition toolbar"],
        folderlist:  [["folderPaneBox", "folderpane_splitter"],              "Folder list"],
        mail:        [["mail-bar3"],                                         "Main toolbar for getting mail and composing new ones."],
        menu:        [["mail-toolbar-menubar2", "compose-toolbar-menubar2"], "Menu Bar"]/*,
        // TODO: stupid element doesn't have an id!
        tabs:       [[function(visible) document.getElementById("tabmail").tabStrip.collapsed = !visible],       "Tab bar"]*/
    },

    //get isComposeWindow() window.wintype == "msgcompose",
    get isComposeWindow() window.document.location == "chrome://messenger/content/messengercompose/messengercompose.xul",
    get browserModes() [modes.MESSAGE],
    get mailModes() [modes.NORMAL],
    // focusContent() focuses this widget
    get mainWidget() this.isComposeWindow ? document.getElementById("content-frame") : GetThreadTree(),
    get mainToolbar() document.getElementById(this.isComposeWindow ? "compose-toolbar-menubar2" : "mail-bar3"),
    get visualbellWindow() document.getElementById(this.mainWindowId),
    styleableChrome: ["chrome://messenger/content/messenger.xul",
                      "chrome://messenger/content/messengercompose/messengercompose.xul"],

    autocommands: [["DOMLoad",         "Triggered when a page's DOM content has fully loaded"],
                   ["FolderLoad",      "Triggered after switching folders in Thunderbird"],
                   ["PageLoadPre",     "Triggered after a page load is initiated"],
                   ["PageLoad",        "Triggered when a page gets (re)loaded/opened"],
                   ["MuttatorEnter",    "Triggered after Thunderbird starts"],
                   ["MuttatorLeave",    "Triggered before exiting Thunderbird"],
                   ["MuttatorLeavePre", "Triggered before exiting Thunderbird"]],

    dialogs: [
        ["about",            "About Thunderbird",
            function () { window.openAboutDialog(); }],
        ["addons",           "Manage Add-ons",
            function () { window.openAddonsMgr(); }],
        ["addressbook",      "Address book",
            function () { window.toAddressBook(); }],
        ["accounts",      "Account Manager",
            function () { MsgAccountManager(); }],
        ["checkupdates",     "Check for updates",
            function () { window.checkForUpdates(); }],
        /*["cleardata",        "Clear private data",
         function () { Cc[GLUE_CID].getService(Ci.nsIBrowserGlue).sanitize(window || null); }],*/
        ["console",          "JavaScript console",
            function () { window.toJavaScriptConsole(); }],
        /*["customizetoolbar", "Customize the Toolbar",
            function () { BrowserCustomizeToolbar(); }],*/
        ["dominspector",     "DOM Inspector",
            function () { window.inspectDOMDocument(content.document); }],
        ["downloads",        "Manage Downloads",
            function () { window.toOpenWindowByType('Download:Manager', 'chrome://mozapps/content/downloads/downloads.xul', 'chrome,dialog=no,resizable'); }],
        /*["import",           "Import Preferences, Bookmarks, History, etc. from other browsers",
            function () { BrowserImport(); }],
        ["openfile",         "Open the file selector dialog",
            function () { BrowserOpenFileWindow(); }],
        ["pageinfo",         "Show information about the current page",
            function () { BrowserPageInfo(); }],
        ["pagesource",       "View page source",
            function () { BrowserViewSourceOfDocument(content.document); }],*/
        ["preferences",      "Show Thunderbird preferences dialog",
            function () { openOptionsDialog(); }],
        /*["printpreview",     "Preview the page before printing",
            function () { PrintUtils.printPreview(onEnterPrintPreview, onExitPrintPreview); }],*/
        ["printsetup",       "Setup the page size and orientation before printing",
            function () { PrintUtils.showPageSetup(); }],
        ["print",            "Show print dialog",
            function () { PrintUtils.print(); }],
        ["saveframe",        "Save frame to disk",
            function () { window.saveFrameDocument(); }],
        ["savepage",         "Save page to disk",
            function () { window.saveDocument(window.content.document); }],
        /*["searchengines",    "Manage installed search engines",
            function () { openDialog("chrome://browser/content/search/engineManager.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
        ["selectionsource",  "View selection source",
            function () { buffer.viewSelectionSource(); }]*/
    ],

    get hasTabbrowser() !this.isComposeWindow,

    focusChange: function (win) {
        // we switch to -- MESSAGE -- mode for Muttator, when the main HTML widget gets focus
        if (win && (win.document instanceof HTMLDocument || win.document instanceof XMLDocument) ||
            liberator.focus instanceof HTMLAnchorElement) {
            if (config.isComposeWindow)
                modes.set(modes.INSERT, modes.TEXTAREA);
            else if (liberator.mode != modes.MESSAGE)
                liberator.mode = modes.MESSAGE;
        }
    },
    get browser() this.isComposeWindow ? null : window.getBrowser(), // XXX: Does the composer really don't have a browser object?
    tabbrowser: {
        __proto__: document.getElementById("tabmail"),
        get mTabContainer() this.tabContainer,
        get mTabs() this.tabContainer.childNodes,
        get visibleTabs() Array.slice(this.mTabs),
        get mCurrentTab() this.tabContainer.selectedItem,
        get mStrip() this.tabStrip,
        get browsers() {
            let browsers = [];
            for ([,tab] in Iterator(this.tabInfo)) {
                let func = tab.mode.getBrowser || tab.mode.tabType.getBrowser;
                if (func)
                    browsers.push(func.call(tab.mode.tabType, tab));
            }
            return browsers;
        }
    },

    modes: [
        ["MESSAGE", { char: "m" }],
        ["COMPOSE"]
    ],

    // NOTE: as I don't use TB I have no idea how robust this is. --djk
    get outputHeight() {
        if (!this.isComposeWindow) {
            let container = document.getElementById("tabpanelcontainer").boxObject;
            let deck      = document.getElementById("displayDeck");
            let box       = document.getElementById("messagepanebox");
            let splitter  = document.getElementById("threadpane-splitter").boxObject;

            if (splitter.width > splitter.height)
                return container.height - deck.minHeight - box.minHeight- splitter.height;
            else
                return container.height - Math.max(deck.minHeight, box.minHeight);
        }
        else
            return document.getElementById("appcontent").boxObject.height;
    },

    get scripts() this.isComposeWindow ? ["compose/compose.js"] : [
        "addressbook.js",
        "mail.js",
        "tabs.js",
    ],

    // to allow Vim to :set ft=mail automatically
    tempFile: "mutt-ator-mail",

}, {
}, {
    commands: function () {
        commands.add(["pref[erences]", "prefs"],
            "Show " + config.hostApplication + " preferences",
            function () { window.openOptionsDialog(); },
            { argCount: "0" });
    },
    modes: function () {
        this.ignoreKeys = {
            "<Return>": modes.NORMAL | modes.INSERT,
            "<Space>": modes.NORMAL | modes.INSERT,
            "<Up>": modes.INSERT,
            "<Down>": modes.INSERT,
            // FIXME: Ctrl-v/Ctrl-z binding will likely be removed
            //        in common code soon, temporary workaround for muttator
            "<C-v>": modes.MESSAGE | modes.INSERT,
            "<C-z>": modes.MESSAGE | modes.INSERT
        };
    },
    options: function () {
        // FIXME: comment obviously incorrect
        // 0: never automatically edit externally
        // 1: automatically edit externally when message window is shown the first time
        // 2: automatically edit externally, once the message text gets focus (not working currently)
        options.add(["autoexternal", "ae"],
            "Edit message with external editor by default",
            "boolean", false);

        if (!this.isComposeWindow) {
            options.add(["online"],
                "Set the 'work offline' option",
                "boolean", true,
                {
                    setter: function (value) {
                        if (MailOfflineMgr.isOnline() != value)
                            MailOfflineMgr.toggleOfflineStatus();
                        return value;
                    },
                    getter: function () MailOfflineMgr.isOnline()
                });
        }
    }
});

// vim: set fdm=marker sw=4 ts=4 et:
<commit_msg>[Muttator] enable statusbar to be hidden<commit_after>// Copyright (c) 2006-2009 by Martin Stubenschrott <stubenschrott@vimperator.org>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the License.txt file included with this file.

const DEFAULT_FAVICON = "chrome://global/skin/icons/Portrait.png";

const Config = Module("config", ConfigBase, {
    init: function () {
        // don't wait too long when selecting new messages
        // GetThreadTree()._selectDelay = 300; // TODO: make configurable
    },

    /*** required options, no checks done if they really exist, so be careful ***/
    name: "Muttator",
    hostApplication: "Thunderbird",

    get mainWindowId() this.isComposeWindow ? "msgcomposeWindow" : "messengerWindow",

    /*** optional options, there are checked for existence and a fallback provided  ***/
    get features() this.isComposeWindow ? ["addressbook"] : ["hints", "mail", "marks", "addressbook", "tabs"],
    defaults: {
        titlestring: "Muttator"
    },

    toolbars: {
        composition: [["composeToolbar2"],                                   "Composition toolbar"],
        folderlist:  [["folderPaneBox", "folderpane_splitter"],              "Folder list"],
        mail:        [["mail-bar3"],                                         "Main toolbar for getting mail and composing new ones."],
        menu:        [["mail-toolbar-menubar2", "compose-toolbar-menubar2"], "Menu Bar"],/*,
        // TODO: stupid element doesn't have an id!
        tabs:       [[function(visible) document.getElementById("tabmail").tabStrip.collapsed = !visible],       "Tab bar"]*/
        status:      [["status-bar"],                                        "Status Bar"]
    },

    //get isComposeWindow() window.wintype == "msgcompose",
    get isComposeWindow() window.document.location == "chrome://messenger/content/messengercompose/messengercompose.xul",
    get browserModes() [modes.MESSAGE],
    get mailModes() [modes.NORMAL],
    // focusContent() focuses this widget
    get mainWidget() this.isComposeWindow ? document.getElementById("content-frame") : GetThreadTree(),
    get mainToolbar() document.getElementById(this.isComposeWindow ? "compose-toolbar-menubar2" : "mail-bar3"),
    get visualbellWindow() document.getElementById(this.mainWindowId),
    styleableChrome: ["chrome://messenger/content/messenger.xul",
                      "chrome://messenger/content/messengercompose/messengercompose.xul"],

    autocommands: [["DOMLoad",         "Triggered when a page's DOM content has fully loaded"],
                   ["FolderLoad",      "Triggered after switching folders in Thunderbird"],
                   ["PageLoadPre",     "Triggered after a page load is initiated"],
                   ["PageLoad",        "Triggered when a page gets (re)loaded/opened"],
                   ["MuttatorEnter",    "Triggered after Thunderbird starts"],
                   ["MuttatorLeave",    "Triggered before exiting Thunderbird"],
                   ["MuttatorLeavePre", "Triggered before exiting Thunderbird"]],

    dialogs: [
        ["about",            "About Thunderbird",
            function () { window.openAboutDialog(); }],
        ["addons",           "Manage Add-ons",
            function () { window.openAddonsMgr(); }],
        ["addressbook",      "Address book",
            function () { window.toAddressBook(); }],
        ["accounts",      "Account Manager",
            function () { MsgAccountManager(); }],
        ["checkupdates",     "Check for updates",
            function () { window.checkForUpdates(); }],
        /*["cleardata",        "Clear private data",
         function () { Cc[GLUE_CID].getService(Ci.nsIBrowserGlue).sanitize(window || null); }],*/
        ["console",          "JavaScript console",
            function () { window.toJavaScriptConsole(); }],
        /*["customizetoolbar", "Customize the Toolbar",
            function () { BrowserCustomizeToolbar(); }],*/
        ["dominspector",     "DOM Inspector",
            function () { window.inspectDOMDocument(content.document); }],
        ["downloads",        "Manage Downloads",
            function () { window.toOpenWindowByType('Download:Manager', 'chrome://mozapps/content/downloads/downloads.xul', 'chrome,dialog=no,resizable'); }],
        /*["import",           "Import Preferences, Bookmarks, History, etc. from other browsers",
            function () { BrowserImport(); }],
        ["openfile",         "Open the file selector dialog",
            function () { BrowserOpenFileWindow(); }],
        ["pageinfo",         "Show information about the current page",
            function () { BrowserPageInfo(); }],
        ["pagesource",       "View page source",
            function () { BrowserViewSourceOfDocument(content.document); }],*/
        ["preferences",      "Show Thunderbird preferences dialog",
            function () { openOptionsDialog(); }],
        /*["printpreview",     "Preview the page before printing",
            function () { PrintUtils.printPreview(onEnterPrintPreview, onExitPrintPreview); }],*/
        ["printsetup",       "Setup the page size and orientation before printing",
            function () { PrintUtils.showPageSetup(); }],
        ["print",            "Show print dialog",
            function () { PrintUtils.print(); }],
        ["saveframe",        "Save frame to disk",
            function () { window.saveFrameDocument(); }],
        ["savepage",         "Save page to disk",
            function () { window.saveDocument(window.content.document); }],
        /*["searchengines",    "Manage installed search engines",
            function () { openDialog("chrome://browser/content/search/engineManager.xul", "_blank", "chrome,dialog,modal,centerscreen"); }],
        ["selectionsource",  "View selection source",
            function () { buffer.viewSelectionSource(); }]*/
    ],

    get hasTabbrowser() !this.isComposeWindow,

    focusChange: function (win) {
        // we switch to -- MESSAGE -- mode for Muttator, when the main HTML widget gets focus
        if (win && (win.document instanceof HTMLDocument || win.document instanceof XMLDocument) ||
            liberator.focus instanceof HTMLAnchorElement) {
            if (config.isComposeWindow)
                modes.set(modes.INSERT, modes.TEXTAREA);
            else if (liberator.mode != modes.MESSAGE)
                liberator.mode = modes.MESSAGE;
        }
    },
    get browser() this.isComposeWindow ? null : window.getBrowser(), // XXX: Does the composer really don't have a browser object?
    tabbrowser: {
        __proto__: document.getElementById("tabmail"),
        get mTabContainer() this.tabContainer,
        get mTabs() this.tabContainer.childNodes,
        get visibleTabs() Array.slice(this.mTabs),
        get mCurrentTab() this.tabContainer.selectedItem,
        get mStrip() this.tabStrip,
        get browsers() {
            let browsers = [];
            for ([,tab] in Iterator(this.tabInfo)) {
                let func = tab.mode.getBrowser || tab.mode.tabType.getBrowser;
                if (func)
                    browsers.push(func.call(tab.mode.tabType, tab));
            }
            return browsers;
        }
    },

    modes: [
        ["MESSAGE", { char: "m" }],
        ["COMPOSE"]
    ],

    // NOTE: as I don't use TB I have no idea how robust this is. --djk
    get outputHeight() {
        if (!this.isComposeWindow) {
            let container = document.getElementById("tabpanelcontainer").boxObject;
            let deck      = document.getElementById("displayDeck");
            let box       = document.getElementById("messagepanebox");
            let splitter  = document.getElementById("threadpane-splitter").boxObject;

            if (splitter.width > splitter.height)
                return container.height - deck.minHeight - box.minHeight- splitter.height;
            else
                return container.height - Math.max(deck.minHeight, box.minHeight);
        }
        else
            return document.getElementById("appcontent").boxObject.height;
    },

    get scripts() this.isComposeWindow ? ["compose/compose.js"] : [
        "addressbook.js",
        "mail.js",
        "tabs.js",
    ],

    // to allow Vim to :set ft=mail automatically
    tempFile: "mutt-ator-mail",

}, {
}, {
    commands: function () {
        commands.add(["pref[erences]", "prefs"],
            "Show " + config.hostApplication + " preferences",
            function () { window.openOptionsDialog(); },
            { argCount: "0" });
    },
    modes: function () {
        this.ignoreKeys = {
            "<Return>": modes.NORMAL | modes.INSERT,
            "<Space>": modes.NORMAL | modes.INSERT,
            "<Up>": modes.INSERT,
            "<Down>": modes.INSERT,
            // FIXME: Ctrl-v/Ctrl-z binding will likely be removed
            //        in common code soon, temporary workaround for muttator
            "<C-v>": modes.MESSAGE | modes.INSERT,
            "<C-z>": modes.MESSAGE | modes.INSERT
        };
    },
    options: function () {
        // FIXME: comment obviously incorrect
        // 0: never automatically edit externally
        // 1: automatically edit externally when message window is shown the first time
        // 2: automatically edit externally, once the message text gets focus (not working currently)
        options.add(["autoexternal", "ae"],
            "Edit message with external editor by default",
            "boolean", false);

        if (!this.isComposeWindow) {
            options.add(["online"],
                "Set the 'work offline' option",
                "boolean", true,
                {
                    setter: function (value) {
                        if (MailOfflineMgr.isOnline() != value)
                            MailOfflineMgr.toggleOfflineStatus();
                        return value;
                    },
                    getter: function () MailOfflineMgr.isOnline()
                });
        }
    }
});

// vim: set fdm=marker sw=4 ts=4 et:
<|endoftext|>


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

Ext.define("viewer.DirectFeatureService", {
    config: {
        actionBeanUrl: null,
        appLayer: null,
        protocol: null,
        url: null
    },
    constructor: function(config) {
        this.initConfig(config);
        if(this.config.actionbeanUrl == null) {
            this.config.actionbeanUrl = actionBeans["feature"];
        }
        console.log("DirectFeatureService init", this.config);
    },
    loadAttributes: function(successFunction, failureFunction) {

        Ext.Ajax.request({
            url: this.config.actionbeanUrl,
            params: {getLayerFeatureType: true, protocol: this.protocol, layer: this.appLayer.layerName},
            success: function(result) {
                var response = Ext.JSON.decode(result.responseText);

                if(response.success) {

                    successFunction(response.attributes);
                } else {
                    if(failureFunction != undefined) {
                        failureFunction(response.error);
                    }
                }
            },
            failure: function(result) {
                if(failureFunction != undefined) {
                    failureFunction("Ajax request failed with status " + result.status + " " + result.statusText + ": " + result.responseText);
                }
            }
        });
    }
});

Ext.define("viewer.AppLayerService", {
    config: {
        actionbeanUrl: null,
        appLayer: null,
        debug: false
    },
    constructor: function(config) {
        if(config.actionbeanUrl == null) {
            config.actionbeanUrl = actionBeans["appLayer"];
        }
        this.initConfig(config);
    },
    loadAttributesAndDetails: function(theAppLayer, successFunction, failureFunction) {

        Ext.Ajax.request({
            url: this.config.actionbeanUrl,
            params: {attributes: true, appLayer: this.appLayer.id},
            success: function(result) {
                var response = Ext.JSON.decode(result.responseText);

                if(response.success) {
                    theAppLayer.attributes = response.attributes;
                    theAppLayer.geometryAttributeIndex = response.geometryAttributeIndex;
                    theAppLayer.geometryAttribute = response.geometryAttribute;
                    theAppLayer.details = response.details;
                    successFunction(response.attributes);
                } else {
                    if(failureFunction != undefined) {
                        failureFunction(response.error);
                    }
                }
            },
            failure: function(result) {
                if(failureFunction != undefined) {
                    failureFunction("Ajax request failed with status " + result.status + " " + result.statusText + ": " + result.responseText);
                }
            }
        });
    },
    getStoreUrl: function() {
        return this.getActionbeanUrl() + "?store=1&appLayer=" + this.appLayer.id + (this.debug ? "&debug=true" : "");
    }
});
<commit_msg>correct function name<commit_after>/*
 * Copyright (C) 2012 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

Ext.define("viewer.DirectFeatureService", {
    config: {
        actionBeanUrl: null,
        appLayer: null,
        protocol: null,
        url: null
    },
    constructor: function(config) {
        this.initConfig(config);
        if(this.config.actionbeanUrl == null) {
            this.config.actionbeanUrl = actionBeans["feature"];
        }
        console.log("DirectFeatureService init", this.config);
    },
    loadAttributes: function(successFunction, failureFunction) {

        Ext.Ajax.request({
            url: this.config.actionbeanUrl,
            params: {getLayerFeatureType: true, protocol: this.protocol, layer: this.appLayer.layerName},
            success: function(result) {
                var response = Ext.JSON.decode(result.responseText);

                if(response.success) {

                    successFunction(response.attributes);
                } else {
                    if(failureFunction != undefined) {
                        failureFunction(response.error);
                    }
                }
            },
            failure: function(result) {
                if(failureFunction != undefined) {
                    failureFunction("Ajax request failed with status " + result.status + " " + result.statusText + ": " + result.responseText);
                }
            }
        });
    }
});

Ext.define("viewer.AppLayerService", {
    config: {
        actionbeanUrl: null,
        appLayer: null,
        debug: false
    },
    constructor: function(config) {
        if(config.actionbeanUrl == null) {
            config.actionbeanUrl = actionBeans["appLayer"];
        }
        this.initConfig(config);
    },
    loadAttributes: function(theAppLayer, successFunction, failureFunction) {

        Ext.Ajax.request({
            url: this.config.actionbeanUrl,
            params: {attributes: true, appLayer: this.appLayer.id},
            success: function(result) {
                var response = Ext.JSON.decode(result.responseText);

                if(response.success) {
                    theAppLayer.attributes = response.attributes;
                    theAppLayer.geometryAttributeIndex = response.geometryAttributeIndex;
                    theAppLayer.geometryAttribute = response.geometryAttribute;
                    theAppLayer.details = response.details;
                    successFunction(response.attributes);
                } else {
                    if(failureFunction != undefined) {
                        failureFunction(response.error);
                    }
                }
            },
            failure: function(result) {
                if(failureFunction != undefined) {
                    failureFunction("Ajax request failed with status " + result.status + " " + result.statusText + ": " + result.responseText);
                }
            }
        });
    },
    getStoreUrl: function() {
        return this.getActionbeanUrl() + "?store=1&appLayer=" + this.appLayer.id + (this.debug ? "&debug=true" : "");
    }
});
<|endoftext|>


<commit_before>/**
 * Bootstrap
 * Client entry point
 * @flow
 */

// Polyfills
import 'babel/polyfill'

// Modules
import React from 'react'
import ReactDOM from 'react-dom'
import { Router } from 'react-router'
import { createHistory } from 'history'
import ReactRouterRelay from 'react-router-relay'

// Routes
import routes from './routes'

// Initialize dependencies
const history = createHistory()

// Mount the app
ReactDOM.render(
  <Router
    createElement={ReactRouterRelay.createElement}
    history={history}
    routes={routes}
  />,
  document.getElementById('app')
)
<commit_msg>Handle hot loading the instance<commit_after>/**
 * Bootstrap
 * Client entry point
 * @flow
 */

// Polyfills
import 'babel/polyfill'

// Modules
import React from 'react'
import ReactDOM from 'react-dom'
import { Router } from 'react-router'
import { createHistory } from 'history'
import ReactRouterRelay from 'react-router-relay'

// Routes
import routes from './routes'

// Initialize dependencies
const history = createHistory()

// Mount the app
const instance = ReactDOM.render(
  <Router
    createElement={ReactRouterRelay.createElement}
    history={history}
    routes={routes}
  />,
  document.getElementById('app')
)

// Fix hotloading for pure components
// @TODO: handle updating the routes
if (module.hot) {
  module.hot.accept('./routes', () => {
    instance.forceUpdate()
  })
}
<|endoftext|>


<commit_before>export default [
  {
    name: ‘Open New Branch’,
    description: ‘new branch company in Los Angeles. May or may not make profit’,
    shortDescription: ‘have a new office’,
    onBuyActionPoints: 2,
    onBuyCaptial: 3,
    onBuySatisfaction: 4,
    onQuarterActionPoints: 5,
    onQuarterCaptial: 4,
    onQuarterSatisfaction: 5,
    image: ‘/icons/catering-icon.png’,
    isPurchased: false
  },
  {
    name: ‘Sell a branch company’,
    description: ‘Sell a non-profit branch company, may make more profit in the future’,
    shortDescription: ’Sell a non-profit branch’,
    onBuyActionPoints: 2,
    onBuyCaptial: 3,
    onBuySatisfaction: 4,
    onQuarterActionPoints: 5,
    onQuarterCaptial: 5,
    onQuarterSatisfaction: 6,
    image: ‘/icons/catering-icon.png’,
    isPurchased: false
  },
  {
    name: ’Hire new employee’,
    description: ‘hire more people to work in company, develop new product’,
    shortDescription: ‘hire people’,
    onBuyActionPoints: 2,
    onBuyCaptial: 3,
    onBuySatisfaction: 4,
    onQuarterActionPoints: 2,
    onQuarterCaptial: 3,
    onQuarterSatisfaction: 5,
    image: ‘/icons/catering-icon.png’,
    isPurchased: false
  },
  {
    name: ‘fire employee’,
    description: ‘fire some employee to have maximum profit, Company is too bit to operate’,
    shortDescription: ‘fire employee’,
    onBuyActionPoints: 2,
    onBuyCaptial: 3,
    onBuySatisfaction: 3,
    onQuarterActionPoints: 4,
    onQuarterCaptial: 1,
    onQuarterSatisfaction: 5,
    image: ‘/icons/catering-icon.png’,
    isPurchased": false
  },
  {
    name: ‘New develop team’,
    description: ’open a new develop team to have better product, may make profit in the future because of new product’,
    shortDescription: ‘new develop team’,
    onBuyActionPoints: 2,
    onBuyCaptial: 2,
    onBuySatisfaction: 4,
    onQuarterActionPoints: 2,
    onQuarterCaptial: 4,
    onQuarterSatisfaction: 2,
    image: ‘/icons/catering-icon.png’,
    isPurchased": false
  },
  {
    name: ’rise salary’,
    description: ‘rise employee's salary, YAY! to have better more efficient team’,
    shortDescription: ‘rise salary’,
    onBuyActionPoints:2,
    onBuyCaptial:3,
    onBuySatisfaction:4,
    onQuarterActionPoints:2,
    onQuarterCaptial:3,
    onQuarterSatisfaction:3,
    image: ’/icons/catering-icon.png’,
    isPurchased": false
  },
  {
    name: ‘reduce wages’,
    description: ‘reduce wages to have more profit, may have much more profit, and may cause a less efficient team’,
    shortDescription: ‘reduce wages’,
    onBuyActionPoints: 2,
    onBuyCaptial: 2,
    onBuySatisfaction: 4,
    onQuarterActionPoints: 2,
    onQuarterCaptial: 3,
    onQuarterSatisfaction:2,
    image: ‘/icons/catering-icon.png,
    isPurchased: false
  }
];
<commit_msg>Fixed part of issue...<commit_after>export default [
  {
    name: 'open new branch',
    description: 'new branch company in Los Angeles. May or may not make profit. Risk Decision!',
    shortDescription: 'have a new office',
    onBuyActionPoints: 2,
    onBuyCaptial: 3,
    onBuySatisfaction: 4,
  },
  {
    name: 'Sell a branch company',
    description: 'Sell a non-profit branch company',
    description: 'Sell a non-profit branch company. may make profit in the future, 20 people could lose their job',
    shortDescription: 'sell a branch',
    shortDescription: 'Sell a non-profit branch company,'
    onBuyActionPoints:2,
    onBuyCaptial: 3,
    onBuySatisfaction: 4,
  },
  {
    name: 'Hire new employee',
    description: 'hire more people to work in company. need more people to build up new product. Might make less profit',
    shortDescription: 'hire people',
    onBuyActionPoints: 2,
    onBuyCaptial: 3,
    onBuySatisfaction: 4,
  },
  {
    name: 'fire employee',
    description: 'fire some employee to have maximum profit. Company is too big to operate. Profit is decreasing',
    shortDescription: 'fire some people who is not that important to the department',
    onBuyActionPoints: 2,
    onBuyCaptial: 3,
    onBuySatisfaction: 3,
  },
  {
    name: 'promote a CIO',
    description: 'Promote a new CIO. To make better decision, and let team work better',
    shortDescription: 'promote a CIO',
    onBuyActionPoints: 2,
    onBuyCaptial : 3,
    onBuySatisfaction: 1,
  },
  {
    name: 'New develop team',
    description: 'open a new develop team to have better product, might decrease the effiency by dividing teams',
    shortDescription: 'new develop team',
    onBuyActionPoints: 2,
    onBuyCaptial: 2,
    onBuySatisfaction: 4,
  },
  {
    name: 'rise salary',
    description: 'rise employee salary. Let team work better, and be more efficient',
    shortDescription: 'rise employee salary!Yay!',
    onBuyActionPoints: 2,
    onBuyCaptial: 3,
    onBuySatisfaction: 4,
  },
  {
    name: 'reduce wages',
    description: 'reduce wages to have more profit. may have better profit, but may have less efficient team',
    shortDescription: 'reduce wages',
    onBuyActionPoints: 2,
    onBuyCaptial : 2,
    onBuySatisfaction: 4,
  }
];
<|endoftext|>


<commit_before>/**
 * All utility functions for processing synced records after being synced. These should changes
 * should be detected by SyncQueue and sent back to the server on next sync.
 */

import { getNextNumber, NUMBER_SEQUENCE_KEYS } from '../database/utilities';

const { REQUISITION_SERIAL_NUMBER, SUPPLIER_INVOICE_NUMBER } = NUMBER_SEQUENCE_KEYS;

export class PostSyncProcessor {
  constructor(database) {
    this.database = database;
    this.queue = [];
    this.runPostSyncQueue = this.runPostSyncQueue.bind(this);
    this.onDatabaseEvent = this.onDatabaseEvent.bind(this);
    this.checkTables = this.checkTables.bind(this);

    this.database.addListener(this.onDatabaseEvent);
  }

  /**
   * Runs all the post sync functions triggered by sync events on database through
   * this.onDatabaseEvent
   */
  runPostSyncQueue() {
    console.log('Running post queue: ', this.queue.length);
    this.database.write(() => this.queue.forEach(func => func()));
  }

  /**
   * Runs post processes checks across tables, ensuring data is correct.
   * Useful to run after crashes.
   * Tables manually added as to not iterate over tables that don't have any post processing.
   */
  checkTables() {
    this.database
      .objects('Requisition')
      .forEach(record => this.delegateByRecordType('Requisition', record));

    this.database
      .objects('Transaction')
      .forEach(record => this.delegateByRecordType('Transaction', record));

    this.runPostSyncQueue();
  }

  /**
   * Respond to a database change event. Must be called from within a database
   * write transaction.
   * @param  {string} changeType  The type of database change, e.g. CREATE, UPDATE, DELETE
   * @param  {string} recordType  The type of record changed (from database schema)
   * @param  {object} record      The record changed
   * @param  {string} causedBy    The cause of this database event, either 'sync' or undefined
   * @return {none}
   */
  onDatabaseEvent(changeType, recordType, record, causedBy) {
    console.log('event: ', causedBy);
    if (causedBy !== 'sync') return; // Exit if not a change caused by sync
    this.delegateByRecordType(recordType, record);
  }

  /**
   * Delegates records to the correct utility function
   * @param  {string} recordType  The type of record changed (from database schema)
   * @param  {object} record      The record changed
   * @return {none}
   */
  delegateByRecordType(recordType, record) {
    console.log('Delegate', recordType);
    switch (recordType) {
      case 'Requisition':
        this.queue = this.queue.concat(this.postProcessRequisition(record));
        break;
      case 'Transaction':
        this.queue = this.queue.concat(this.postProcessTransaction(record));
        break;
      default:
        break;
    }
  }

  /**
   * Builds an array of post process functions based on conditions, runs a database write call
   * to apply all the post process functions if there are any.
   * @param  {object} record     The record changed
   * @return {array}  An array of functions to be called for the given record
   */
  postProcessRequisition(record) {
    const processes = [];
    // Allocate serial number to requisitions with serial number of -1. This has been generated
    // by the server, coming from another store as supplier.
    console.log('in func, serial: ', record.serialNumber);
    if (record.serialNumber === '-1') {
      processes.push(() => {
        console.log('reqbefore', record.serialNumber);
        record.serialNumber = getNextNumber(this.database, REQUISITION_SERIAL_NUMBER);
        console.log('reqafter', record.serialNumber);
      });
    }

    if (processes.length > 0) {
      processes.push(() => this.database.update('Requisition', record));
    }
    console.log('processes: ', processes);
    return processes;
  }

  /**
   * Builds an array of post process functions based on conditions, runs a database write call
   * to apply all the post process functions if there are any.
   * @param  {object} record     The record changed
   * @return {array}  An array of functions to be called for the given record
   */
  postProcessTransaction(record) {
    const processes = [];
    // Allocate serial number to supplier invoices with serial number of -1. This has been generated
    // by the server, coming from another store as supplier.
    if (record.serialNumber === '-1' && record.type === 'supplier_invoice') {
      processes.push(() => {
        console.log('supbefore', record.serialNumber);
        record.serialNumber = getNextNumber(this.database, SUPPLIER_INVOICE_NUMBER);
        console.log('reqafter', record.serialNumber);
      });
    }

    // If any changes, add database update for record
    if (processes.length > 0) {
      processes.push(() => this.database.update('Transaction', record));
    }
    console.log('end');
    return processes;
  }
}
<commit_msg>comment tidy<commit_after>/**
 * All utility functions for processing synced records after being synced. These should changes
 * should be detected by SyncQueue and sent back to the server on next sync.
 */

import { getNextNumber, NUMBER_SEQUENCE_KEYS } from '../database/utilities';

const { REQUISITION_SERIAL_NUMBER, SUPPLIER_INVOICE_NUMBER } = NUMBER_SEQUENCE_KEYS;

export class PostSyncProcessor {
  constructor(database) {
    this.database = database;
    this.queue = [];
    this.runPostSyncQueue = this.runPostSyncQueue.bind(this);
    this.onDatabaseEvent = this.onDatabaseEvent.bind(this);
    this.checkTables = this.checkTables.bind(this);

    this.database.addListener(this.onDatabaseEvent);
  }

  /**
   * Runs all the post sync functions triggered by sync events on database through
   * this.onDatabaseEvent
   */
  runPostSyncQueue() {
    console.log('Running post queue: ', this.queue.length);
    this.database.write(() => this.queue.forEach(func => func()));
  }

  /**
   * Runs post checks across tables, ensuring data is correct.
   * Useful to run after crashes.
   * Tables manually added as to not iterate over tables that don't have any post processing.
   */
  checkTables() {
    this.database
      .objects('Requisition')
      .forEach(record => this.delegateByRecordType('Requisition', record));

    this.database
      .objects('Transaction')
      .forEach(record => this.delegateByRecordType('Transaction', record));

    this.runPostSyncQueue();
  }

  /**
   * Respond to a database change event. Must be called from within a database
   * write transaction.
   * @param  {string} changeType  The type of database change, e.g. CREATE, UPDATE, DELETE
   * @param  {string} recordType  The type of record changed (from database schema)
   * @param  {object} record      The record changed
   * @param  {string} causedBy    The cause of this database event, either 'sync' or undefined
   * @return {none}
   */
  onDatabaseEvent(changeType, recordType, record, causedBy) {
    console.log('event: ', causedBy);
    if (causedBy !== 'sync') return; // Exit if not a change caused by sync
    this.delegateByRecordType(recordType, record);
  }

  /**
   * Delegates records to the correct utility function
   * @param  {string} recordType  The type of record changed (from database schema)
   * @param  {object} record      The record changed
   * @return {none}
   */
  delegateByRecordType(recordType, record) {
    console.log('Delegate', recordType);
    switch (recordType) {
      case 'Requisition':
        this.queue = this.queue.concat(this.postProcessRequisition(record));
        break;
      case 'Transaction':
        this.queue = this.queue.concat(this.postProcessTransaction(record));
        break;
      default:
        break;
    }
  }

  /**
   * Builds an array of post process functions based on conditions, runs a database write call
   * to apply all the post process functions if there are any.
   * @param  {object} record     The record changed
   * @return {array}  An array of functions to be called for the given record
   */
  postProcessRequisition(record) {
    const processes = [];
    // Allocate serial number to requisitions with serial number of -1. This has been generated
    // by the server, coming from another store as supplier.
    console.log('in func, serial: ', record.serialNumber);
    if (record.serialNumber === '-1') {
      processes.push(() => {
        console.log('reqbefore', record.serialNumber);
        record.serialNumber = getNextNumber(this.database, REQUISITION_SERIAL_NUMBER);
        console.log('reqafter', record.serialNumber);
      });
    }

    if (processes.length > 0) {
      processes.push(() => this.database.update('Requisition', record));
    }
    console.log('processes: ', processes);
    return processes;
  }

  /**
   * Builds an array of post process functions based on conditions, runs a database write call
   * to apply all the post process functions if there are any.
   * @param  {object} record     The record changed
   * @return {array}  An array of functions to be called for the given record
   */
  postProcessTransaction(record) {
    const processes = [];
    // Allocate serial number to supplier invoices with serial number of -1. This has been generated
    // by the server, coming from another store as supplier.
    if (record.serialNumber === '-1' && record.type === 'supplier_invoice') {
      processes.push(() => {
        console.log('supbefore', record.serialNumber);
        record.serialNumber = getNextNumber(this.database, SUPPLIER_INVOICE_NUMBER);
        console.log('reqafter', record.serialNumber);
      });
    }

    // If any changes, add database update for record
    if (processes.length > 0) {
      processes.push(() => this.database.update('Transaction', record));
    }
    console.log('end');
    return processes;
  }
}
<|endoftext|>


<commit_before>examples.point_lighting = function (selector) {
  var data = d3.range(4e4).map(function() {
               return { xloc: 0, yloc: 0, xvel: 0, yvel: 0 }
             })

  var width = size.width
    , height = size.height

  var x = d3.scale.linear()
          .domain([-5, 5])
          .range([0, width])

  var y = d3.scale.linear()
          .domain([-5, 5])
          .range([0, height])

  var svg = d3.select(selector)
            .attr('height', height).attr('width', width)
            .call(pathgl)

  circle = svg.selectAll("circle")
               .data(data)
               .enter().append("circle")
           .attr('fill', function () { return "hsl(" + Math.random() * 360 + ",100%, 50%)" })
               .attr("cx", 10)
               .attr("cy", 10)
               .attr("r", 50)

  var xs  = function (x) {
    return 2 * (x / width) - 1
  }

  var ys = function (y) {
    return 1 - ((y / height) * 2)
  }
  d3.timer(function() {
    circle.each(function(d) {
      this.posBuffer[this.indices[0] + 0] = xs( x (d.xloc += d.xvel))
      this.posBuffer[this.indices[0] + 1] = ys( y ( d.yloc += d.yvel))
      this.posBuffer[this.indices[0] + 2] = 2 + 1000 * Math.abs(d.xvel * d.yvel)
      d.xvel += 0.04 * (Math.random() - .5) - 0.05 * d.xvel - 0.0005 * d.xloc
      d.yvel += 0.04 * (Math.random() - .5) - 0.05 * d.yvel - 0.0005 * d.yloc
    })
      console.timeEnd('a')
    //circle
    //.attr("cx", function(d) { return x(d.xloc) })
    //.attr("cy", function(d) { return y(d.yloc) })
    //.attr("r", function(d) { return Math.min(2 + 1000 * Math.abs(d.xvel * d.yvel), 10) })
    //.attr("fill", function (d) { return d.xvel > -0 ? 'red' : 'steelblue' })
  })

  d3.select('.blurb').text("Compare with http://bl.ocks.org/mbostock/raw/2647924/")
  c.selectAll('circle')
}<commit_msg>render less circles in svg so we dont crash phones. show simple manual updates<commit_after>examples.point_lighting = function (selector) {
  var data = d3.range(selector == 'canvas' ? 40000 : 1000).map(function() {
               return { xloc: 0, yloc: 0, xvel: 0, yvel: 0 }
             })

  var width = size.width
    , height = size.height

  var x = d3.scale.linear()
          .domain([-5, 5])
          .range([0, width])

  var y = d3.scale.linear()
          .domain([-5, 5])
          .range([0, height])

  var svg = d3.select(selector)
            .attr('height', height).attr('width', width)
            .call(pathgl)

  var circle = svg.selectAll("circle")
           .data(data)
           .enter().append("circle")
           .attr('fill', function () { return "hsl(" + Math.random() * 360 + ",100%, 50%)" })
           .attr("cx", 10)
           .attr("cy", 10)
           .attr("r", 50)

  var xs  = function (x) {
    return 2 * (x / width) - 1
  }

  var ys = function (y) {
    return 1 - ((y / height) * 2)
  }
  d3.timer(function() {
    circle.each(function(d) {
      d.xvel += 0.04 * (Math.random() - .5) - 0.05 * d.xvel - 0.0005 * d.xloc
      d.yvel += 0.04 * (Math.random() - .5) - 0.05 * d.yvel - 0.0005 * d.yloc

      if (selector == 'canvas') {
        this.posBuffer[this.indices[0] + 0] = xs(x(d.xloc += d.xvel))
        this.posBuffer[this.indices[0] + 1] = ys(y(d.yloc += d.yvel))
        this.posBuffer[this.indices[0] + 2] = 2 + 1000 * Math.abs(d.xvel * d.yvel)
      }
    })

      if (selector == 'svg')
        circle
        .attr("cx", function(d) { return x(d.xloc += d.xvel) })
        .attr("cy", function(d) { return y(d.yloc += d.yvel) })
        .attr("r", function(d) { return Math.min(2 + 1000 * Math.abs(d.xvel * d.yvel), 10) })
        .attr("fill", function (d) { return d.xvel > -0 ? 'red' : 'steelblue' })
  })

  d3.select('.blurb').text("Compare with http://bl.ocks.org/mbostock/raw/2647924/")
  c.selectAll('circle')
}<|endoftext|>