<commit_before>'use strict';

const path = require('path');
const fs = require('fs');

const findPackage = require('./src/find_package.js');

const webpack = require('webpack');
const resolve = require('resolve');
const mkdirp = require('mkdirp');

// We must place our files in a special folder for integration /w the android
// build system.
const destination = process.env.SILK_BUILDJS_DEST;
const modulePath = findPackage(process.env.SILK_BUILDJS_SOURCE);
const pkg = require(path.join(modulePath, 'package.json'));
const localWebpack = path.join(modulePath, 'webpack.config.js');

let babelCache;
if (!process.env.BABEL_CACHE || process.env.BABEL_CACHE === '1') {
  babelCache = path.join(destination, '../.babelcache');
  mkdirp.sync(babelCache);
} else {
  console.log('~ babel cache has been disabled ~');
  babelCache = false;
}

const name = pkg.name;
let main = pkg.main || './index.js';
if (!path.extname(main)) {
  main += '.js';
}

if (main.indexOf('./') !== 0) {
  main = `./${main}`;
}

const absMain = path.resolve(modulePath, main);
let mainDir;

try {
  mainDir = fs.realpathSync(path.dirname(absMain));
} catch (err) {
  mainDir = path.dirname(absMain);
}

// XXX: Would be nicer to abort this in the bash script rather than after we
// have booted up node here...
if (
  main.indexOf('build/Release') === 0 ||
  main.indexOf('./build/Release') === 0 ||
  /\.node$/.test(main)
) {
  console.log(`Module contains no JS main skipping webpack ...`);
  process.exit(0);
}

if (!main) {
  throw new Error(`package.json must have main in ${process.cwd()}`);
}

const externals = [
  // TODO: auto generate these ...
  'base_version',
  'bleno',
  'mic',
  'noble',
  'node-hid',
  'node-webrtc',
  'opencv',
  'segfault-handler',
  'silk-alog',
  'silk-battery',
  'silk-camera',
  'silk-core-version',
  'silk-cv',
  'silk-dialog-engine',
  'silk-dialog-storage',
  'silk-gc1',
  'silk-input',
  'silk-kws',
  'silk-lights',
  'silk-modwatcher',
  'silk-movie',
  'silk-netstatus',
  'silk-ntp',
  'silk-properties',
  'silk-say',
  'silk-sensors',
  'silk-sysutils',
  'silk-vad',
  'silk-vibrator',
  'silk-volume',
  'silk-wifi',
  'v8-profiler',
  'kissfft',
  'silk-caffe',
  (context, request, callback) => {
    if (resolve.isCore(request)) {
      callback(null, true);
      return;
    }

    // For extra fun node will allow resolving .main without a ./ this behavior
    // makes .main look nicer but is completely different than how requiring
    // without a specific path is handled elsewhere... To ensure we don't
    // accidentally resolve a node module to a local file we handle this case
    // very specifically.
    if (context === modulePath && pkg.main === request) {
      const resolvedPath = path.resolve(context, request);
      if (!fs.existsSync(resolvedPath)) {
        callback(new Error(`${modulePath} has a .main which is missing ...`));
        return;
      }
    }

    // Handle path rewriting for native modules
    if (
      /\.node$/.test(request) ||
      request.indexOf('build/Release') !== -1
    ) {
      if (path.isAbsolute(request)) {
        callback(null, true);
        return;
      }

      const absExternalPath = path.resolve(context, request);
      let relativeExternalPath = path.relative(mainDir, absExternalPath);
      if (relativeExternalPath.indexOf('.') !== 0) {
        relativeExternalPath = `./${relativeExternalPath}`;
      }
      callback(null, relativeExternalPath);
      return;
    }

    resolve(request,  {
      basedir: context,
      package: pkg,
      extensions: ['.js', '.json'],
    }, (err, resolvedPath) => {
      if (err) {
        console.log(`Missing module imported from ${context} (${request})`);
        callback(null, true);
        return;
      }
      callback(null, false);
    });
  }
];

const entry = {};
entry[main] = main;

const config = {
  context: modulePath,
  externals,
  target: 'node',
  node: {
    __dirname: false,
    __filename: false,
  },
  devtool: 'source-map',
  entry,
  output: {
    path: path.join(destination),
    libraryTarget: 'commonjs2',
    filename: `[name]`,
  },
  resolve: {
    extensions: ['', '.js', '.json'],
    // Common "gothcha" modules ...
    alias: {
      'any-promise': require.resolve('./shims/any-promise.js'),
      'json3': require.resolve('./shims/json3.js'),
    },
  },
  babel: {
    cacheDirectory: babelCache,
    presets: [
      require('babel-preset-silk-node4'),
    ],
  },
  module : {
    loaders: [
      { test: /\.json$/, loader: require.resolve('json-loader') },
      {
        test: /\.js$/,
        loader: require.resolve('babel-loader'),
        query: {
          babelrc: false,
        }
      }
    ]
  }
}

if (fs.existsSync(localWebpack)) {
  console.log(`${localWebpack} found agumenting buildjs ...`);
  const rules = Object.assign({}, require(localWebpack));
  if (rules.externals && Array.isArray(rules.externals)) {
    // Order is important here the rules should be ordered such that the
    // webpack.config comes from the module first and our global rules second.
    config.externals = rules.externals.concat(config.externals);
    delete rules.externals;
  }
  Object.assign(config, rules);
}

module.exports = config;
<commit_msg>Update node_module list in webpack<commit_after>'use strict';

const path = require('path');
const fs = require('fs');

const findPackage = require('./src/find_package.js');

const webpack = require('webpack');
const resolve = require('resolve');
const mkdirp = require('mkdirp');

// We must place our files in a special folder for integration /w the android
// build system.
const destination = process.env.SILK_BUILDJS_DEST;
const modulePath = findPackage(process.env.SILK_BUILDJS_SOURCE);
const pkg = require(path.join(modulePath, 'package.json'));
const localWebpack = path.join(modulePath, 'webpack.config.js');

let babelCache;
if (!process.env.BABEL_CACHE || process.env.BABEL_CACHE === '1') {
  babelCache = path.join(destination, '../.babelcache');
  mkdirp.sync(babelCache);
} else {
  console.log('~ babel cache has been disabled ~');
  babelCache = false;
}

const name = pkg.name;
let main = pkg.main || './index.js';
if (!path.extname(main)) {
  main += '.js';
}

if (main.indexOf('./') !== 0) {
  main = `./${main}`;
}

const absMain = path.resolve(modulePath, main);
let mainDir;

try {
  mainDir = fs.realpathSync(path.dirname(absMain));
} catch (err) {
  mainDir = path.dirname(absMain);
}

// XXX: Would be nicer to abort this in the bash script rather than after we
// have booted up node here...
if (
  main.indexOf('build/Release') === 0 ||
  main.indexOf('./build/Release') === 0 ||
  /\.node$/.test(main)
) {
  console.log(`Module contains no JS main skipping webpack ...`);
  process.exit(0);
}

if (!main) {
  throw new Error(`package.json must have main in ${process.cwd()}`);
}

const externals = [
  // TODO: auto generate these ...
  'base_version',
  'bleno',
  'mic',
  'noble',
  'node-hid',
  'node-webrtc',
  'opencv',
  'segfault-handler',
  'silk-alog',
  'silk-battery',
  'silk-camera',
  'silk-core-version',
  'silk-cv',
  'silk-dialog-engine',
  'silk-dialog-script',
  'silk-dialog-storage',
  'silk-gc1',
  'silk-input',
  'silk-kws',
  'silk-lights',
  'silk-modwatcher',
  'silk-movie',
  'silk-netstatus',
  'silk-ntp',
  'silk-properties',
  'silk-say',
  'silk-sensors',
  'silk-stt',
  'silk-tts',
  'silk-sysutils',
  'silk-vad',
  'silk-vibrator',
  'silk-volume',
  'silk-wifi',
  'v8-profiler',
  'kissfft',
  'silk-caffe',
  (context, request, callback) => {
    if (resolve.isCore(request)) {
      callback(null, true);
      return;
    }

    // For extra fun node will allow resolving .main without a ./ this behavior
    // makes .main look nicer but is completely different than how requiring
    // without a specific path is handled elsewhere... To ensure we don't
    // accidentally resolve a node module to a local file we handle this case
    // very specifically.
    if (context === modulePath && pkg.main === request) {
      const resolvedPath = path.resolve(context, request);
      if (!fs.existsSync(resolvedPath)) {
        callback(new Error(`${modulePath} has a .main which is missing ...`));
        return;
      }
    }

    // Handle path rewriting for native modules
    if (
      /\.node$/.test(request) ||
      request.indexOf('build/Release') !== -1
    ) {
      if (path.isAbsolute(request)) {
        callback(null, true);
        return;
      }

      const absExternalPath = path.resolve(context, request);
      let relativeExternalPath = path.relative(mainDir, absExternalPath);
      if (relativeExternalPath.indexOf('.') !== 0) {
        relativeExternalPath = `./${relativeExternalPath}`;
      }
      callback(null, relativeExternalPath);
      return;
    }

    resolve(request,  {
      basedir: context,
      package: pkg,
      extensions: ['.js', '.json'],
    }, (err, resolvedPath) => {
      if (err) {
        console.log(`Missing module imported from ${context} (${request})`);
        callback(null, true);
        return;
      }
      callback(null, false);
    });
  }
];

const entry = {};
entry[main] = main;

const config = {
  context: modulePath,
  externals,
  target: 'node',
  node: {
    __dirname: false,
    __filename: false,
  },
  devtool: 'source-map',
  entry,
  output: {
    path: path.join(destination),
    libraryTarget: 'commonjs2',
    filename: `[name]`,
  },
  resolve: {
    extensions: ['', '.js', '.json'],
    // Common "gothcha" modules ...
    alias: {
      'any-promise': require.resolve('./shims/any-promise.js'),
      'json3': require.resolve('./shims/json3.js'),
    },
  },
  babel: {
    cacheDirectory: babelCache,
    presets: [
      require('babel-preset-silk-node4'),
    ],
  },
  module : {
    loaders: [
      { test: /\.json$/, loader: require.resolve('json-loader') },
      {
        test: /\.js$/,
        loader: require.resolve('babel-loader'),
        query: {
          babelrc: false,
        }
      }
    ]
  }
}

if (fs.existsSync(localWebpack)) {
  console.log(`${localWebpack} found agumenting buildjs ...`);
  const rules = Object.assign({}, require(localWebpack));
  if (rules.externals && Array.isArray(rules.externals)) {
    // Order is important here the rules should be ordered such that the
    // webpack.config comes from the module first and our global rules second.
    config.externals = rules.externals.concat(config.externals);
    delete rules.externals;
  }
  Object.assign(config, rules);
}

module.exports = config;
<|endoftext|>


<commit_before>var config = {
    // db connection;
};

module.exports = config;
<commit_msg>add db connection<commit_after>var config = {
    // db connection;
    dbgeo: 'mongodb://localhost:27017/geo',
    dbimagestore: 'mongodb://localhost:27017/imagestore'
};

module.exports = config;
<|endoftext|>


<commit_before>var data = require('../data/sampleData');
var mongodb = require('../data/mongodb');
var indicator = require('../data/indicator');
var dataset = require('../data/dataset');
var async = require('../lib/async');
var IndicatorSchema = indicator.Indicator;
var datasetSchema = dataset.Dataset;

exports.cubeList = function(req, res) {
	res.send(data.cubeListJSON);
};

exports.cubeInfo = function(req, res) {
	res.send(data.cubeInfoJSON);
};

exports.querySplit = function(req, res) {
	var resultJSON = {
		"grid" : {
			"total" : 0,
			"result" : []
		},
		"chart" : {
			"result" : []
		}
	};
	var queryParam = req.body;
	var matchObj = generateMatchObj(queryParam, false);
	// for grid
	var group = generateGroupObj(queryParam);
	var groupObj = group.returnObj;
	var groupObjProject = group.returnProject;
	var sortStr = group.returnSort;
	// for chart
	var groupSplitJSON4Chart = generateGroupSplitObj(queryParam);
	var groupObj4Chart = groupSplitJSON4Chart.returnObj;
	var groupObj4ChartProject = groupSplitJSON4Chart.returnProject;
	var sortStr4Chart = groupSplitJSON4Chart.returnSort;
	// to get all the query results and return
	async.parallel([
			function(callback) {
				// query for grid
				datasetSchema.aggregate().match(matchObj).group(groupObj).project(groupObjProject).sort(sortStr).limit(
						500).exec(function(err, doc) {
					if (err)
						throw err;
					resultJSON.grid.result = doc;
					resultJSON.grid.total = doc.length;
					callback();
				});
			},
			function(callback) {
				// query for chart
				datasetSchema.aggregate().match(matchObj).group(groupObj4Chart).project(groupObj4ChartProject).sort(
						sortStr4Chart).limit(500).exec(function(err, doc) {
					if (err)
						throw err;
					// console.log(doc);
					resultJSON.chart.result = doc;
					callback();
				});
			} ], function() {
		res.send(resultJSON);
	});
};

function generateGroupSplitObj(queryParam) {
	var returnJSON = {};
	var dimensions = queryParam.dimensions;
	var measures = queryParam.measures;
	var primaryDimension = queryParam.primaryDimension;
	var split = queryParam.split;
	var breakException = {};
	var idStr = "_id:{";
	var projectStr = "{";
	var sortStr = "field " + primaryDimension;
	try {
		dimensions.forEach(function(item, index) {
			if (item.uniqueName == queryParam.primaryDimension) {
				projectStr += item.uniqueName;
				projectStr += ":\"$_id." + item.uniqueName + "\",";
				idStr += item.uniqueName;
				idStr += ":\"$";
				idStr += item.uniqueName;
				idStr += "\"";
				throw breakException;
			}
		});
	} catch (e) {
		if (e !== breakException)
			console.log(e);
	}
	idStr += "},"
	var indicatorStr = "";
	var splitValue = split.splitValue;
	// var sortStr = "";
	measures.forEach(function(item) {
		splitValue.forEach(function(value) {
			var isString = (typeof value === 'string');
			// convert split value string
			var cvtVal = value;
			if (isString)
				cvtVal = convertSplitValue(value);
			if (indicatorStr != '') {
				indicatorStr += ","
			}
			var splitIndicator = "";
			splitIndicator += item.uniqueName;
			splitIndicator += "_";
			splitIndicator += cvtVal;
			// if (index == 0 && sortStr == '') {
			// sortStr = "{" + splitIndicator + ": 1}";
			// }
			projectStr += splitIndicator
			projectStr += ":1,";
			indicatorStr += splitIndicator;
			indicatorStr += ":{";
			if (item.data_type == 'number') {
				indicatorStr += "$sum:{$cond:[{$eq:[";
			} else if (item.data_type == 'percentage') {
				indicatorStr += "$avg:{$cond:[{$eq:[";
			} else {
				return "";
			}
			indicatorStr += "\"$";
			indicatorStr += split.dimensions;
			indicatorStr += "\",";
			if (isString) {
				indicatorStr += "\"";
				indicatorStr += value;
				indicatorStr += "\"]},";
			} else {
				indicatorStr += value;
				indicatorStr += "]},";
			}
			indicatorStr += "\"$";
			indicatorStr += item.uniqueName;
			indicatorStr += "\",0]}}";
		});
	});
	var res = "{" + idStr + indicatorStr + "}";
	console.log('result string:' + res);
	var returnObj = eval("(" + res + ")");
	projectStr += "_id:0}";
	var projectObj = eval("(" + projectStr + ")");
	returnJSON = {
		"returnObj" : returnObj,
		"returnProject" : projectObj,
		"returnSort" : sortStr
	}
	return returnJSON;
}

exports.queryResult = function(req, res) {
	var queryParam = req.body;
	var resultJSON = {
		"grid" : {
			"total" : 0,
			"result" : []
		},
		"chart" : {
			"result" : []
		}
	};
	var matchObj = generateMatchObj(queryParam);
	// for grid
	var group = generateGroupObj(queryParam, false);
	var groupObj = group.returnObj;
	var groupObjProject = group.returnProject;
	var sortStr = group.returnSort;
	// for chart
	var chartGroup = generateGroupObj(queryParam, true);
	var groupObj4Chart = chartGroup.returnObj;

	// to get all the query results and return
	async.parallel([
			function(callback) {
				// query for grid
				datasetSchema.aggregate().match(matchObj).group(groupObj).project(groupObjProject).sort(sortStr).limit(
						500).exec(function(err, doc) {
					if (err)
						console.log('Exception: ' + err);
					resultJSON.grid.result = convertResult(doc, false);
					resultJSON.grid.total = doc.length;
					callback();
				});
			},
			function(callback) {
				// query for chart
				datasetSchema.aggregate().match(matchObj).group(groupObj4Chart).project(groupObjProject).sort(sortStr)
						.limit(500).exec(function(err, doc) {
							if (err)
								console.log('Exception: ' + err);
							resultJSON.chart.result = convertResult(doc, true);
							callback();
						});
			} ], function() {
		res.send(resultJSON);
	});
};

function generateGroupObj(queryParam, isChart) {
	var dimensions = queryParam.dimensions;
	var measures = queryParam.measures;
	var breakException = {};
	var idStr = "_id:{";
	var projectStr = "{";
	try {
		dimensions.forEach(function(item, index) {
			if (isChart) {
				if (item.uniqueName == queryParam.primaryDimension) {
					idStr += item.uniqueName;
					idStr += ":\"$";
					idStr += item.uniqueName;
					idStr += "\"";
					projectStr += item.uniqueName;
					projectStr += ":\"$_id." + item.uniqueName + "\",";
					throw breakException;
				}
			} else {
				idStr += item.uniqueName;
				idStr += ":\"$";
				idStr += item.uniqueName;
				idStr += "\"";
				if (index < dimensions.length - 1) {
					idStr += ","
				}
				projectStr += item.uniqueName;
				projectStr += ":\"$_id." + item.uniqueName + "\",";
			}
		});
	} catch (e) {
		if (e !== breakException)
			throw e;
	}
	idStr += "},"
	var indicatorStr = "";
	measures.forEach(function(item, index) {
		indicatorStr += item.uniqueName;
		indicatorStr += ":{";
		projectStr += item.uniqueName
		projectStr += ":1,";
		if (item.data_type == 'number') {
			indicatorStr += "$sum:";
		} else if (item.data_type == 'percentage') {
			indicatorStr += "$avg:";
		} else {
			return "";
		}
		indicatorStr += "\"$";
		indicatorStr += item.uniqueName;
		indicatorStr += "\"";
		indicatorStr += "}"
		if (index < measures.length - 1) {
			indicatorStr += ","
		}
	});
	var res = "{" + idStr + indicatorStr + "}";
	var returnObj = eval("(" + res + ")");
	projectStr += "_id:0}";
	console.log(projectStr);
	var projectObj = eval("(" + projectStr + ")");
	returnJSON = {
		"returnObj" : returnObj,
		"returnProject" : projectObj,
		"returnSort" : generateSortStr(measures)
	}
	return returnJSON;
}

function generateMatchObj(queryParam) {
	var dimensions = queryParam.dimensions;
	var filters = queryParam.filters;
	var filterArray = [];
	dimensions.forEach(function(item, index) {
		if (item.uniqueName in filters) {
			var array = eval('filters.' + item.uniqueName);
			if (array != null && array.length > 0) {
				var str = '';
				if (item.uniqueName == 'year') {
					str = array.join(",");
				} else {
					str = "'" + array.join("','") + "'";
				}
				filterArray.push(item.uniqueName + ': {$in:[' + str + ']}');
			}
		}
	});
	var matchStr = '{ ' + filterArray.join(",") + ' }';
	console.log(matchStr);
	var returnObj = eval("(" + matchStr + ")");
	return returnObj;
}

function generateSortStr(measures) {
	var sortStr = 'field -';
	if (measures != null && measures.length > 0) {
		sortStr += measures[0].uniqueName;
		return sortStr;
	} else {
		return null;
	}
}

function convertResult(doc, isChart) {
	var results = doc;
	// doc.forEach(function(item) {
	// var gstr = JSON.stringify(item._id);
	// gstr = gstr.substring(1, gstr.length - 1);
	// delete item._id;
	// var mstr = JSON.stringify(item);
	// mstr = mstr.substring(1, mstr.length - 1);
	// var recordStr = '{' + gstr + ',' + mstr + '}';
	// var recordObj = eval("(" + recordStr + ")");
	// results.push(recordObj);
	// });
	// sort result by year for charts
	if (isChart) {
		if (results.length > 0 && 'year' in results[0])
			bubbleSort(results, 'year');
	}
	return results;
}

function bubbleSort(a, par) {
	var swapped;
	do {
		swapped = false;
		for ( var i = 0; i < a.length - 1; i++) {
			if (a[i][par] > a[i + 1][par]) {
				var temp = a[i];
				a[i] = a[i + 1];
				a[i + 1] = temp;
				swapped = true;
			}
		}
	} while (swapped);
}

function convertSplitValue(str) {
	var returnStr = str.trim().replace(/ |-|&|\(|\)/g, '');
	return returnStr;
}

exports.indicatorMapping = function(req, res) {
	var indicatorMappingJSON = {};
	var query = require('url').parse(req.url, true).query;
	var idc = query.idc;
	var dimensions = [];
	var measures = [];
	IndicatorSchema.find({
		indicator_key : idc
	}, function(err, doc) {
		if (err)
			console.log('Exception: ' + err);
		doc.forEach(function(item, index) {
			var tempDimensions = item.dimension;
			console.log(tempDimensions);
			tempDimensions.forEach(function(dimension, index) {
				var tempDimension = {
					"uniqueName" : dimension.dimension_key,
					"name" : dimension.dimension_key,
					"text" : dimension.dimension_text
				};
				dimensions.push(tempDimension);
			});
			var tempMesureJson = {
				"uniqueName" : item.indicator_key,
				"name" : item.indicator_key,
				"text" : item.indicator_text,
				"data_source" : item.data_source,
				"data_type" : item.data_type
			};
			measures.push(tempMesureJson);
		});
		indicatorMappingJSON = {
			"dimensions" : dimensions,
			"measures" : measures
		};
		res.send(indicatorMappingJSON);
	});
}

exports.indicatorSearch = function(req, res) {
	var query = require('url').parse(req.url, true).query;
	var indicatorResultJSON = {};
	if (query.query != null) {
		var key = query.query.toLowerCase();
		var results = [];
		IndicatorSchema.find({
			indicator_text : {
				$regex : key,
				$options : 'i'
			}
		}, function(err, doc) {
			if (err)
				console.log('Exception: ' + err);
			doc.forEach(function(item, index) {
				var tempJson = {
					"uniqueName" : item.indicator_key,
					"text" : item.indicator_text + ' - ' + item.data_source
				};
				results.push(tempJson);
			});
			indicatorResultJSON = {
				"indicators" : results
			};
			res.send(indicatorResultJSON);
		});
	} else {
		indicatorResultJSON = {
			"indicators" : []
		};
		res.send(indicatorResultJSON);
	}
};

exports.dimensionValueSearch = function(req, res) {
	var query = require('url').parse(req.url, true).query;
	var dimensionValueResultJSON = {};
	if (query.dim != null) {
		var key = query.dim.toLowerCase();
		var results = [];
		// exclude blank record
		var matchStr = '{ ' + key + ' : { $ne : \'\' } }';
		var matchObj = eval("(" + matchStr + ")");
		datasetSchema.distinct(key, matchObj, function(err, doc) {
			if (err)
				console.log('Exception: ' + err);
			doc.forEach(function(item, index) {
				var tempJson = {
					"name" : item
				};
				results.push(tempJson);
			});
			dimensionValueResultJSON = {
				"dimensionValues" : results
			};
			res.send(dimensionValueResultJSON);
		});
	} else {
		dimensionValueResultJSON = {
			"dimensionValues" : []
		};
		res.send(dimensionValueResultJSON);
	}
}<commit_msg>minor changes<commit_after>var data = require('../data/sampleData');
var mongodb = require('../data/mongodb');
var indicator = require('../data/indicator');
var dataset = require('../data/dataset');
var async = require('../lib/async');
var IndicatorSchema = indicator.Indicator;
var datasetSchema = dataset.Dataset;

exports.cubeList = function(req, res) {
	res.send(data.cubeListJSON);
};

exports.cubeInfo = function(req, res) {
	res.send(data.cubeInfoJSON);
};

exports.querySplit = function(req, res) {
	var resultJSON = {
		"grid" : {
			"total" : 0,
			"result" : []
		},
		"chart" : {
			"result" : []
		}
	};
	var queryParam = req.body;
	var matchObj = generateMatchObj(queryParam, false);
	// for grid
	var group = generateGroupObj(queryParam);
	var groupObj = group.returnObj;
	var groupObjProject = group.returnProject;
	var sortStr = group.returnSort;
	// for chart
	var groupSplitJSON4Chart = generateGroupSplitObj(queryParam);
	var groupObj4Chart = groupSplitJSON4Chart.returnObj;
	var groupObj4ChartProject = groupSplitJSON4Chart.returnProject;
	var sortStr4Chart = groupSplitJSON4Chart.returnSort;
	// to get all the query results and return
	async.parallel([
			function(callback) {
				// query for grid
				datasetSchema.aggregate().match(matchObj).group(groupObj).project(groupObjProject).sort(sortStr).limit(
						500).exec(function(err, doc) {
					if (err)
						throw err;
					resultJSON.grid.result = doc;
					resultJSON.grid.total = doc.length;
					callback();
				});
			},
			function(callback) {
				// query for chart
				datasetSchema.aggregate().match(matchObj).group(groupObj4Chart).project(groupObj4ChartProject).sort(
						sortStr4Chart).limit(500).exec(function(err, doc) {
					if (err)
						throw err;
					// console.log(doc);
					resultJSON.chart.result = doc;
					callback();
				});
			} ], function() {
		res.send(resultJSON);
	});
};

function generateGroupSplitObj(queryParam) {
	var returnJSON = {};
	var dimensions = queryParam.dimensions;
	var measures = queryParam.measures;
	var primaryDimension = queryParam.primaryDimension;
	var split = queryParam.split;
	var breakException = {};
	var idStr = "_id:{";
	var projectStr = "{";
	var sortStr = "field " + primaryDimension;
	try {
		dimensions.forEach(function(item, index) {
			if (item.uniqueName == queryParam.primaryDimension) {
				projectStr += item.uniqueName;
				projectStr += ":\"$_id." + item.uniqueName + "\",";
				idStr += item.uniqueName;
				idStr += ":\"$";
				idStr += item.uniqueName;
				idStr += "\"";
				throw breakException;
			}
		});
	} catch (e) {
		if (e !== breakException)
			console.log(e);
	}
	idStr += "},"
	var indicatorStr = "";
	var splitValue = split.splitValue;
	// var sortStr = "";
	measures.forEach(function(item) {
		splitValue.forEach(function(value) {
			var isString = (typeof value === 'string');
			// convert split value string
			var cvtVal = value;
			if (isString)
				cvtVal = convertSplitValue(value);
			if (indicatorStr != '') {
				indicatorStr += ","
			}
			var splitIndicator = "";
			splitIndicator += item.uniqueName;
			splitIndicator += "_";
			splitIndicator += cvtVal;
			// if (index == 0 && sortStr == '') {
			// sortStr = "{" + splitIndicator + ": 1}";
			// }
			projectStr += splitIndicator
			projectStr += ":1,";
			indicatorStr += splitIndicator;
			indicatorStr += ":{";
			if (item.data_type == 'number') {
				indicatorStr += "$sum:{$cond:[{$eq:[";
			} else if (item.data_type == 'percentage') {
				indicatorStr += "$avg:{$cond:[{$eq:[";
			} else {
				return "";
			}
			indicatorStr += "\"$";
			indicatorStr += split.dimensions;
			indicatorStr += "\",";
			if (isString) {
				indicatorStr += "\"";
				indicatorStr += value;
				indicatorStr += "\"]},";
			} else {
				indicatorStr += value;
				indicatorStr += "]},";
			}
			indicatorStr += "\"$";
			indicatorStr += item.uniqueName;
			indicatorStr += "\",0]}}";
		});
	});
	var res = "{" + idStr + indicatorStr + "}";
	console.log('result string:' + res);
	var returnObj = eval("(" + res + ")");
	projectStr += "_id:0}";
	var projectObj = eval("(" + projectStr + ")");
	returnJSON = {
		"returnObj" : returnObj,
		"returnProject" : projectObj,
		"returnSort" : sortStr
	}
	return returnJSON;
}

exports.queryResult = function(req, res) {
	var queryParam = req.body;
	var resultJSON = {
		"grid" : {
			"total" : 0,
			"result" : []
		},
		"chart" : {
			"result" : []
		}
	};
	var matchObj = generateMatchObj(queryParam);
	// for grid
	var group = generateGroupObj(queryParam, false);
	var groupObj = group.returnObj;
	var groupObjProject = group.returnProject;
	var sortStr = group.returnSort;
	// for chart
	var chartGroup = generateGroupObj(queryParam, true);
	var groupObj4Chart = chartGroup.returnObj;

	// to get all the query results and return
	async.parallel([
			function(callback) {
				// query for grid
				datasetSchema.aggregate().match(matchObj).group(groupObj).project(groupObjProject).sort(sortStr).limit(
						500).exec(function(err, doc) {
					if (err)
						console.log('Exception: ' + err);
					resultJSON.grid.result = convertResult(doc, false);
					resultJSON.grid.total = doc.length;
					callback();
				});
			},
			function(callback) {
				// query for chart
				datasetSchema.aggregate().match(matchObj).group(groupObj4Chart).project(groupObjProject).sort(sortStr)
						.limit(500).exec(function(err, doc) {
							if (err)
								console.log('Exception: ' + err);
							resultJSON.chart.result = convertResult(doc, true);
							callback();
						});
			} ], function() {
		res.send(resultJSON);
	});
};

function generateGroupObj(queryParam, isChart) {
	var dimensions = queryParam.dimensions;
	var measures = queryParam.measures;
	var breakException = {};
	var idStr = "_id:{";
	var projectStr = "{";
	try {
		dimensions.forEach(function(item, index) {
			if (isChart) {
				if (item.uniqueName == queryParam.primaryDimension) {
					idStr += item.uniqueName;
					idStr += ":\"$";
					idStr += item.uniqueName;
					idStr += "\"";
					projectStr += item.uniqueName;
					projectStr += ":\"$_id." + item.uniqueName + "\",";
					throw breakException;
				}
			} else {
				idStr += item.uniqueName;
				idStr += ":\"$";
				idStr += item.uniqueName;
				idStr += "\"";
				if (index < dimensions.length - 1) {
					idStr += ","
				}
				projectStr += item.uniqueName;
				projectStr += ":\"$_id." + item.uniqueName + "\",";
			}
		});
	} catch (e) {
		if (e !== breakException)
			throw e;
	}
	idStr += "},"
	var indicatorStr = "";
	measures.forEach(function(item, index) {
		indicatorStr += item.uniqueName;
		indicatorStr += ":{";
		projectStr += item.uniqueName
		projectStr += ":1,";
		if (item.data_type == 'number') {
			indicatorStr += "$sum:";
		} else if (item.data_type == 'percentage') {
			indicatorStr += "$avg:";
		} else {
			return "";
		}
		indicatorStr += "\"$";
		indicatorStr += item.uniqueName;
		indicatorStr += "\"";
		indicatorStr += "}"
		if (index < measures.length - 1) {
			indicatorStr += ","
		}
	});
	var res = "{" + idStr + indicatorStr + "}";
	var returnObj = eval("(" + res + ")");
	projectStr += "_id:0}";
	console.log(projectStr);
	var projectObj = eval("(" + projectStr + ")");
	returnJSON = {
		"returnObj" : returnObj,
		"returnProject" : projectObj,
		"returnSort" : generateSortStr(measures)
	}
	return returnJSON;
}

function generateMatchObj(queryParam) {
	var dimensions = queryParam.dimensions;
	var filters = queryParam.filters;
	var filterArray = [];
	dimensions.forEach(function(item, index) {
		if (item.uniqueName in filters) {
			var array = eval('filters.' + item.uniqueName);
			if (array != null && array.length > 0) {
				var str = '';
				if (item.uniqueName == 'year') {
					str = array.join(",");
				} else {
					str = "'" + array.join("','") + "'";
				}
				filterArray.push(item.uniqueName + ': {$in:[' + str + ']}');
			}
		}
	});
	var matchStr = '{ ' + filterArray.join(",") + ' }';
	console.log(matchStr);
	var returnObj = eval("(" + matchStr + ")");
	return returnObj;
}

function generateSortStr(measures) {
	var sortStr = 'field -';
	if (measures != null && measures.length > 0) {
		sortStr += measures[0].uniqueName;
		return sortStr;
	} else {
		return null;
	}
}

function convertResult(doc, isChart) {
	var results = doc;
	// doc.forEach(function(item) {
	// var gstr = JSON.stringify(item._id);
	// gstr = gstr.substring(1, gstr.length - 1);
	// delete item._id;
	// var mstr = JSON.stringify(item);
	// mstr = mstr.substring(1, mstr.length - 1);
	// var recordStr = '{' + gstr + ',' + mstr + '}';
	// var recordObj = eval("(" + recordStr + ")");
	// results.push(recordObj);
	// });
	// sort result by year for charts
	if (isChart) {
		if (results.length > 0 && 'year' in results[0])
			bubbleSort(results, 'year');
	}
	return results;
}

function bubbleSort(a, par) {
	var swapped;
	do {
		swapped = false;
		for ( var i = 0; i < a.length - 1; i++) {
			if (a[i][par] > a[i + 1][par]) {
				var temp = a[i];
				a[i] = a[i + 1];
				a[i + 1] = temp;
				swapped = true;
			}
		}
	} while (swapped);
}

function convertSplitValue(str) {
	var returnStr = str.trim().replace(/ |-|&|\(|\)/g, '');
	return returnStr;
}

exports.indicatorMapping = function(req, res) {
	var indicatorMappingJSON = {};
	var query = require('url').parse(req.url, true).query;
	var idc = query.idc;
	var dimensions = [];
	var measures = [];
	IndicatorSchema.find({
		indicator_key : idc
	}, function(err, doc) {
		if (err)
			console.log('Exception: ' + err);
		doc.forEach(function(item, index) {
			var tempDimensions = item.dimension;
			tempDimensions.forEach(function(dimension, index) {
				var tempDimension = {
					"uniqueName" : dimension.dimension_key,
					"name" : dimension.dimension_key,
					"text" : dimension.dimension_text
				};
				dimensions.push(tempDimension);
			});
			var tempMesureJson = {
				"uniqueName" : item.indicator_key,
				"name" : item.indicator_key,
				"text" : item.indicator_text,
				"data_source" : item.data_source,
				"data_type" : item.data_type
			};
			measures.push(tempMesureJson);
		});
		indicatorMappingJSON = {
			"dimensions" : dimensions,
			"measures" : measures
		};
		res.send(indicatorMappingJSON);
	});
}

exports.indicatorSearch = function(req, res) {
	var query = require('url').parse(req.url, true).query;
	var indicatorResultJSON = {};
	if (query.query != null) {
		var key = query.query.toLowerCase();
		var results = [];
		IndicatorSchema.find({
			indicator_text : {
				$regex : key,
				$options : 'i'
			}
		}, function(err, doc) {
			if (err)
				console.log('Exception: ' + err);
			doc.forEach(function(item, index) {
				var tempJson = {
					"uniqueName" : item.indicator_key,
					"text" : item.indicator_text + ' - ' + item.data_source
				};
				results.push(tempJson);
			});
			indicatorResultJSON = {
				"indicators" : results
			};
			res.send(indicatorResultJSON);
		});
	} else {
		indicatorResultJSON = {
			"indicators" : []
		};
		res.send(indicatorResultJSON);
	}
};

exports.dimensionValueSearch = function(req, res) {
	var query = require('url').parse(req.url, true).query;
	var dimensionValueResultJSON = {};
	if (query.dim != null) {
		var key = query.dim.toLowerCase();
		var results = [];
		// exclude blank record
		var matchStr = '{ ' + key + ' : { $ne : \'\' } }';
		var matchObj = eval("(" + matchStr + ")");
		datasetSchema.distinct(key, matchObj, function(err, doc) {
			if (err)
				console.log('Exception: ' + err);
			doc.forEach(function(item, index) {
				var tempJson = {
					"name" : item
				};
				results.push(tempJson);
			});
			dimensionValueResultJSON = {
				"dimensionValues" : results
			};
			res.send(dimensionValueResultJSON);
		});
	} else {
		dimensionValueResultJSON = {
			"dimensionValues" : []
		};
		res.send(dimensionValueResultJSON);
	}
}<|endoftext|>


<commit_before>(function($){
	// This function adds noise to the background-color attribute of an element
	$.fn.noisy = function(options) {
		return this.each(function() {
	 		var canvas = document.createElement('canvas'),
	 		    ctx = canvas.getContext("2d");

	 		options = $.extend({}, $.fn.noisy.defaults, options);

	 		// Use fallback image if canvas isn't supported
	 		if ((options.fallbackImage !== undefined) && !ctx) {
	 			$(this).css('background-image', options.fallbackImage);
	 			return;
	 		}

	 		canvas.width = canvas.height = options.tileSize;
	 		var imgData = ctx.createImageData(canvas.width, canvas.height);

	 		var rand = function(min, max) {
	 			return Math.floor(Math.random()*(max-min)+min);
	 		};

	 		// Add black and white pixels at random positions to the canvas
	 		for (var i = 0; i < options.noise * Math.pow(options.tileSize, 2); i++) {
	 			var x = rand(0, canvas.width),
	 			    y = rand(0, canvas.height),
	 			    index = (x + y * imgData.width) * 4;

	 			if (options.monochromatic) var randColorChannel = rand(0, 255);

	 			imgData.data[index  ] = randColorChannel;                                           // red
	 			imgData.data[index+1] = options.monochromatic ? randColorChannel : rand(0, 255);    // green
	 			imgData.data[index+2] = options.monochromatic ? randColorChannel : rand(0, 255);    // blue
	 			imgData.data[index+3] = rand(0, 255*options.maxNoiseOpacity);                       // alpha
	 		}

	 		ctx.putImageData(imgData, 0, 0);
	 		$(this).css('background', 'url(' + canvas.toDataURL('image/png') + ')' + options.backgroundColor);
		});
	};

	$.fn.noisy.defaults = {
		// How many percent of the image that is filled with noise,
		//   represented by a number between 0 and 1 inclusive
		noise:              1,

		// The width and height of the background image in pixels
		tileSize:           200,

		// An empty string is transparent
		backgroundColor:    '',

		// The maximum noise particle opacity,
		//   represented by a number between 0 and 1 inclusive
		maxNoiseOpacity:    20/255,

		// A string linking to the image used if there's no canvas support
		fallbackImage:      undefined,

		// Specifies wheter the particles are grayscale or colorful
		monochromatic:      false
	};
})(jQuery);<commit_msg>Fixed an issue in the monochromatic issue which caused it to only generate blue and green colors. Thanks gustav arnesson for that fix<commit_after>(function($){
	// This function adds noise to the background-color attribute of an element
	$.fn.noisy = function(options) {
		return this.each(function() {
	 		var canvas = document.createElement('canvas'),
	 		    ctx = canvas.getContext("2d");

	 		options = $.extend({}, $.fn.noisy.defaults, options);

	 		// Use fallback image if canvas isn't supported
	 		if ((options.fallbackImage !== undefined) && !ctx) {
	 			$(this).css('background-image', options.fallbackImage);
	 			return;
	 		}

	 		canvas.width = canvas.height = options.tileSize;
	 		var imgData = ctx.createImageData(canvas.width, canvas.height);

	 		var rand = function(min, max) {
	 			return Math.floor(Math.random()*(max-min)+min);
	 		};

	 		// Add black and white pixels at random positions to the canvas
	 		for (var i = 0; i < options.noise * Math.pow(options.tileSize, 2); i++) {
	 			var x = rand(0, canvas.width),
	 			    y = rand(0, canvas.height),
	 			    index = (x + y * imgData.width) * 4;

	 			var randColorChannel = rand(0, 255);
	 			imgData.data[index  ] = randColorChannel;                                           // red
	 			imgData.data[index+1] = options.monochromatic ? randColorChannel : rand(0, 255);    // green
	 			imgData.data[index+2] = options.monochromatic ? randColorChannel : rand(0, 255);    // blue
	 			imgData.data[index+3] = rand(0, 255*options.maxNoiseOpacity);                       // alpha
	 		}

	 		ctx.putImageData(imgData, 0, 0);
	 		$(this).css('background', 'url(' + canvas.toDataURL('image/png') + ')' + options.backgroundColor);
		});
	};

	$.fn.noisy.defaults = {
		// How many percent of the image that is filled with noise,
		//   represented by a number between 0 and 1 inclusive
		noise:              1,

		// The width and height of the background image in pixels
		tileSize:           200,

		// An empty string is transparent
		backgroundColor:    '',

		// The maximum noise particle opacity,
		//   represented by a number between 0 and 1 inclusive
		maxNoiseOpacity:    20/255,

		// A string linking to the image used if there's no canvas support
		fallbackImage:      undefined,

		// Specifies wheter the particles are grayscale or colorful
		monochromatic:      false
	};
})(jQuery);<|endoftext|>


<commit_before>wesabe.provide('download.CompoundPlayer', function() {});

wesabe.lang.extend(wesabe.download.CompoundPlayer, {
  register: function(params) {
    var klass = this.create(params);

    // make sure we put it where wesabe.require expects it
    wesabe.provide('fi-scripts.'+klass.fid, klass);

    return klass;
  },

  create: function(params) {
    var klass = function() {
      // inherit from CompoundPlayer
      wesabe.lang.extend(this, wesabe.download.CompoundPlayer.prototype);
      // subclass it
      wesabe.lang.extend(this, params);
    };

    klass.fid = params.fid;
    klass.org = params.org;

    return klass;
  },
});

wesabe.lang.extend(wesabe.download.CompoundPlayer.prototype, {
  playerIndex: -1,
  currentJob: null,
  players: null,

  start: function(answers, browser) {
    var self = this;

    function startNextPlayer() {
      self.playerIndex++;
      self.currentPlayer = new self.players[self.playerIndex]();
      wesabe.info("Starting player ", self.currentPlayer);
      self.currentPlayer.job = jobProxy;
      self.currentPlayer.start(answers, browser);
    }

    var jobProxy = {
      update: function(status, result) {
        // proxy job updates through
        self.job.update(status, result);
      },

      fail: function(status, result) {
        wesabe.info("Could not complete job with ", self.currentJob, " (", status, " ", result, ")");

        if (self.playerIndex+1 < self.players.length) {
          startNextPlayer();
        } else {
          // no more players to try, report the last failure
          self.job.fail(status, result);
        }
      },

      succeed: function() {
        self.job.succeed();
      },

      timer: self.job.timer,

      get page() {
        return self.currentPlayer.page;
      },
    };

    startNextPlayer();
  },

  resume: function() {
    self.currentPlayer && self.currentPlayer.resume();
  },
});
<commit_msg>Add support for goals and options to compound players.<commit_after>wesabe.provide('download.CompoundPlayer', function() {});

wesabe.lang.extend(wesabe.download.CompoundPlayer, {
  register: function(params) {
    var klass = this.create(params);

    // make sure we put it where wesabe.require expects it
    wesabe.provide('fi-scripts.'+klass.fid, klass);

    return klass;
  },

  create: function(params) {
    var klass = function() {
      // inherit from CompoundPlayer
      wesabe.lang.extend(this, wesabe.download.CompoundPlayer.prototype);
      // subclass it
      wesabe.lang.extend(this, params);
    };

    klass.fid = params.fid;
    klass.org = params.org;

    return klass;
  },
});

wesabe.lang.extend(wesabe.download.CompoundPlayer.prototype, {
  playerIndex: -1,
  currentJob: null,
  players: null,

  start: function(answers, browser) {
    var self = this;

    function startNextPlayer() {
      self.playerIndex++;
      self.currentPlayer = new self.players[self.playerIndex]();
      wesabe.info("Starting player ", self.currentPlayer);
      self.currentPlayer.job = jobProxy;
      self.currentPlayer.start(answers, browser);
    }

    var jobProxy = {
      update: function(status, result) {
        // proxy job updates through
        self.job.update(status, result);
      },

      fail: function(status, result) {
        wesabe.info("Could not complete job with ", self.currentPlayer, " (", status, " ", result, ")");

        if (self.playerIndex+1 < self.players.length) {
          startNextPlayer();
        } else {
          // no more players to try, report the last failure
          self.job.fail(status, result);
        }
      },

      succeed: function() {
        self.job.succeed();
      },

      timer: self.job.timer,

      get page() {
        return self.currentPlayer.page;
      },

      goal: self.job.goal,

      options: self.job.options,
    };

    startNextPlayer();
  },

  resume: function() {
    self.currentPlayer && self.currentPlayer.resume();
  },
});
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var Promise = require('bluebird');
var findQuery = require('objection-find');
var expressAdapter = require('./adapters/expressAdapter');

/**
 * POST /persons
 *
 * GET /persons
 * GET /persons/:id
 * GET /persons/:id/parent
 * GET /persons/:id/children
 * GET /persons/:id/movies
 *
 * PUT /persons/:id
 * PUT /persons/:id/children
 * PUT /persons/:id/movies
 *
 * PATCH /persons/:id
 *
 * DELETE /persons/:id
 * DELETE /persons/:id/children
 * DELETE /persons/:id/movies
 *
 * restApiGenerator()
 *   .addModel(Person)
 *   .addModel(Movie)
 *   .exclude('PUT', '/api/v1/persons')
 */

function RestApiGenerator(objection) {
  this._objection = objection;
  this._logger = _.noop;
  this._models = Object.create(null);
  this._findQueries = Object.create(null);
  this._routePrefix = '/';
  this._exclude = [];
  this._databaseGetter = null;
  this._adapter = expressAdapter;
  this._pluralizer = function (word) {
    return word + 's';
  };
}

RestApiGenerator.prototype.logger = function (logger) {
  this._logger = logger;
  return this;
};

RestApiGenerator.prototype.addModel = function (modelClass, modifyCb) {
  var self = this;

  this._models[modelClass.tableName] = modelClass;
  this._findQueries[modelClass.tableName] = findQuery(modelClass);

  if (modifyCb) {
   modifyCb(this._findQueries[modelClass.tableName]);
  }

  _.each(modelClass.getRelations(), function (relation) {
    if (!self._findQueries[relation.relatedModelClass.tableName]) {
      self._findQueries[relation.relatedModelClass.tableName] = findQuery(relation.relatedModelClass);
    }
  });

  return this;
};

RestApiGenerator.prototype.routePrefix = function (routePrefix) {
  if (_.last(routePrefix) !== '/') {
    this._routePrefix = routePrefix + '/';
  } else {
    this._routePrefix = routePrefix;
  }
  return this;
};

RestApiGenerator.prototype.pluralizer = function (pluralizer) {
  this._pluralizer = pluralizer;
  return this;
};

RestApiGenerator.prototype.exclude = function (method, exclude) {
  this._exclude.push({
    method: method,
    exclude: exclude
  });
  return this;
};

RestApiGenerator.prototype.databaseGetter = function (databaseGetter) {
  this._databaseGetter = databaseGetter;
  return this;
};

RestApiGenerator.prototype.adapter = function (adapter) {
  this._adapter = adapter;
  return this;
};

RestApiGenerator.prototype.generate = function (app) {
  var self = this;

  _.each(this._models, function (modelClass) {
    var route = self._routeForModel(modelClass);

    if (!self._isExcluded('POST', route)) {
      self._generatePost(app, modelClass);
    }

    if (!self._isExcluded('GET', route)) {
      self._generateGetAll(app, modelClass);
    }

    if (!self._isExcluded('GET', route + '/:id')) {
      self._generateGet(app, modelClass);
    }

    if (!self._isExcluded('PUT', route + '/:id')) {
      self._generatePut(app, modelClass);
    }

    if (!self._isExcluded('PATCH', route + '/:id')) {
      self._generatePatch(app, modelClass);
    }

    if (!self._isExcluded('DELETE', route + '/:id')) {
      self._generateDelete(app, modelClass);
    }

    _.each(modelClass.getRelations(), function (relation) {
      var route = self._routeForRelation(relation);

      if (!self._isExcluded('POST', route)) {
        self._generateRelationPost(app, relation);
      }

      if (!self._isExcluded('GET', route)) {
        self._generateRelationGetAll(app, relation);
      }

      if (!self._isExcluded('DELETE', route)) {
        self._generateRelationDeleteAll(app, relation);
      }

      if (!(relation instanceof modelClass.OneToOneRelation)) {
        if (!self._isExcluded('PUT', route)) {
          self._generateRelationPutAll(app, relation);
        }
      }
    });
  });
};

RestApiGenerator.prototype._routeForModel = function (modelClass) {
  return this._routePrefix + this._pluralizer(_.camelCase(modelClass.name));
};

RestApiGenerator.prototype._routeForRelation = function (relation) {
  return this._routeForModel(relation.ownerModelClass) + '/:id/' + relation.name;
};

RestApiGenerator.prototype._isExcluded = function (method, route) {
  return _.any(this._exclude, function (exc) {
    if (exc.method.toLowerCase() === method.toLowerCase()) {
      if (_.isString(exc.exclude)) {
        return exc.exclude === route;
      } else {
        return exc.exclude.test(route);
      }
    } else {
      return false;
    }
  });
};

RestApiGenerator.prototype._generatePost = function (app, $modelClass) {
  var self = this;
  var route = this._routeForModel($modelClass);

  this._logger('POST ' + route);
  this._adapter(app, 'POST', route, function (req) {
    var modelClass = self._bindModelClass($modelClass, req);

    return self._objection.transaction(modelClass, function (modelClass) {
      return modelClass
        .query()
        .allowEager(self._findQueries[modelClass.tableName].allowEager())
        .eager(req.query.eager)
        .insert(req.body)
        .then(function (model) {
          return model.$query().first();
        });
    });
  });
};

RestApiGenerator.prototype._generateGetAll = function (app, $modelClass) {
  var self = this;
  var route = this._routeForModel($modelClass);

  this._logger('GET ' + route);
  this._adapter(app, 'GET', route, function (req) {
    var boundModelClass = self._bindModelClass($modelClass, req);
    return self._findQueries[boundModelClass.tableName].build(req.query, boundModelClass.query());
  });
};

RestApiGenerator.prototype._generateGet = function (app, $modelClass) {
  var self = this;
  var route = this._routeForModel($modelClass) + '/:id';

  this._logger('GET ' + route);
  this._adapter(app, 'GET', route, function (req) {
    var modelClass = self._bindModelClass($modelClass, req);

    return modelClass
      .query()
      .eager(req.query.eager)
      .allowEager(self._findQueries[modelClass.tableName].allowEager())
      .where(modelClass.idColumn, req.params.id)
      .first()
      .then(function (model) {
        if (!model) { throw error(404); }
        return model;
      });
  });
};

RestApiGenerator.prototype._generatePut = function (app, $modelClass) {
  var self = this;
  var route = this._routeForModel($modelClass) + '/:id';

  this._logger('PUT ' + route);
  this._adapter(app, 'PUT', route, function (req) {
    var modelClass = self._bindModelClass($modelClass, req);

    return modelClass
      .query()
      .update(req.body)
      .where(modelClass.idColumn, req.params.id)
      .then(function (model) {
        return modelClass
          .query()
          .allowEager(self._findQueries[modelClass.tableName].allowEager())
          .eager(req.query.eager)
          .where(modelClass.idColumn, req.params.id)
          .first();
      })
      .then(function (model) {
        if (!model) { throw error(404); }
        return model;
      });
  });
};

RestApiGenerator.prototype._generatePatch = function (app, $modelClass) {
  var self = this;
  var route = this._routeForModel($modelClass) + '/:id';

  this._logger('PATCH ' + route);
  this._adapter(app, 'PATCH', route, function (req) {
    var modelClass = self._bindModelClass($modelClass, req);

    return modelClass
      .query()
      .patch(req.body)
      .where(modelClass.idColumn, req.params.id)
      .then(function () {
        return modelClass
          .query()
          .allowEager(self._findQueries[modelClass.tableName].allowEager())
          .eager(req.query.eager)
          .where(modelClass.idColumn, req.params.id)
          .first();
      })
      .then(function (model) {
        if (!model) { throw error(404); }
        return model;
      });
  });
};

RestApiGenerator.prototype._generateDelete = function (app, $modelClass) {
  var self = this;
  var route = this._routeForModel($modelClass) + '/:id';

  this._logger('DELETE ' + route);
  this._adapter(app, 'DELETE', route, function (req) {
    var modelClass = self._bindModelClass($modelClass, req);

    return self._objection.transaction(modelClass, function (modelClass) {
      return modelClass
        .query()
        .delete()
        .where(modelClass.idColumn, req.params.id);
    }).then(function () {
      return {};
    });
  });
};

RestApiGenerator.prototype._generateRelationPost = function (app, relation) {
  var self = this;
  var route = this._routeForRelation(relation);

  this._logger('POST ' + route);
  this._adapter(app, 'POST', route, function (req) {
    var modelClass = self._bindModelClass(relation.ownerModelClass, req);

    return self._objection.transaction(modelClass, function (modelClass) {
      return modelClass
        .query()
        .where(modelClass.idColumn, req.params.id)
        .first()
        .then(function (model) {
          if (!model) { throw error(404); }
          return model
            .$relatedQuery(relation.name)
            .insert(req.body);
        })
        .then(function (model) {
          return model
            .$query()
            .first()
            .allowEager(self._findQueries[relation.relatedModelClass.tableName].allowEager())
            .eager(req.query.eager);
        });
    });
  });
};

RestApiGenerator.prototype._generateRelationGetAll = function (app, relation) {
  var self = this;
  var route = this._routeForRelation(relation);

  this._logger('GET ' + route);
  this._adapter(app, 'GET', route, function (req) {
    var modelClass = self._bindModelClass(relation.ownerModelClass, req);

    return modelClass
      .query()
      .where(modelClass.idColumn, req.params.id)
      .first()
      .then(function (model) {
        if (!model) { throw error(404); }
        var query = model.$relatedQuery(relation.name);
        self._findQueries[relation.relatedModelClass.tableName].build(req.query, query);

        if (relation instanceof modelClass.OneToOneRelation) {
          return query.first();
        } else {
          return query;
        }
      });
  });
};

RestApiGenerator.prototype._generateRelationPutAll = function (app, relation) {
  var self = this;
  var route = this._routeForRelation(relation);

  this._logger('PUT ' + route);
  this._adapter(app, 'PUT', route, function (req) {
    var modelClass = self._bindModelClass(relation.ownerModelClass, req);
    var relatedModelClass = self._bindModelClass(relation.relatedModelClass, req);
    var model;

    return self._objection.transaction(modelClass, relatedModelClass, function (modelClass, relatedModelClass) {
      return modelClass
        .query()
        .where(modelClass.getFullIdColumn(), req.params.id)
        .first()
        .eager(relation.name)
        .then(function ($model) {
          model = $model;
          if (!model) { throw error(404); }

          var current = model[relation.name];
          var currentById = _.indexBy(current, relatedModelClass.getIdProperty());
          var inputModels = relatedModelClass.ensureModelArray(req.body);

          function isNew(model) {
            return !model.$id() || !currentById[model.$id()];
          }

          var insertModels = _.filter(inputModels, isNew);
          var updateModels = _.filter(inputModels, _.negate(isNew));
          var deleteModels = _.filter(current, function (model) {
            return !_.find(inputModels, function (inputModel) {
              // Non-strict equal on purpose.
              return inputModel.$id() == model.$id();
            });
          });

          var insertAndUpdateQueries = _.flatten([
            _.map(updateModels, function (update) {
              return update.$query().patch();
            }),
            _.map(insertModels, function (insert) {
              delete insert[relatedModelClass.getIdProperty()];
              return model.$relatedQuery(relation.name).insert(insert);
            })
          ]);

          return model
            .$relatedQuery(relation.name)
            .delete()
            .whereIn(relatedModelClass.getFullIdColumn(), _.invoke(deleteModels, '$id'))
            .then(function () {
              return Promise.all(insertAndUpdateQueries);
            });
        })
        .then(function () {
          return model.$relatedQuery(relation.name);
        });
    });
  });
};

RestApiGenerator.prototype._generateRelationDeleteAll = function (app, relation) {
  var self = this;
  var route = this._routeForRelation(relation);

  this._logger('DELETE ' + route);
  this._adapter(app, 'DELETE', route, function (req) {
    var modelClass = self._bindModelClass(relation.ownerModelClass, req);

    return modelClass
      .query()
      .where(modelClass.idColumn, req.params.id)
      .first()
      .then(function (model) {
        if (!model) { throw error(404); }
        return model.$relatedQuery(relation.name).delete();
      })
      .then(function () {
        return {};
      });
  });
};

RestApiGenerator.prototype._bindModelClass = function (modelClass, req) {
  if (this._databaseGetter) {
    return modelClass.bindKnex(this._databaseGetter(req));
  } else {
    return modelClass;
  }
};

function error(statusCode) {
  var err = new Error();
  err.statusCode = statusCode;
  return err;
}

module.exports = RestApiGenerator;
<commit_msg>Add a DELETE method for collections.<commit_after>'use strict';

var _ = require('lodash');
var Promise = require('bluebird');
var findQuery = require('objection-find');
var expressAdapter = require('./adapters/expressAdapter');

/**
 * POST /persons
 *
 * GET /persons
 * GET /persons/:id
 * GET /persons/:id/parent
 * GET /persons/:id/children
 * GET /persons/:id/movies
 *
 * PUT /persons/:id
 * PUT /persons/:id/children
 * PUT /persons/:id/movies
 *
 * PATCH /persons/:id
 *
 * DELETE /persons/:id
 * DELETE /persons/:id/children
 * DELETE /persons/:id/movies
 *
 * restApiGenerator()
 *   .addModel(Person)
 *   .addModel(Movie)
 *   .exclude('PUT', '/api/v1/persons')
 */

function RestApiGenerator(objection) {
  this._objection = objection;
  this._logger = _.noop;
  this._models = Object.create(null);
  this._findQueries = Object.create(null);
  this._routePrefix = '/';
  this._exclude = [];
  this._databaseGetter = null;
  this._adapter = expressAdapter;
  this._pluralizer = function (word) {
    return word + 's';
  };
}

RestApiGenerator.prototype.logger = function (logger) {
  this._logger = logger;
  return this;
};

RestApiGenerator.prototype.addModel = function (modelClass, modifyCb) {
  var self = this;

  this._models[modelClass.tableName] = modelClass;
  this._findQueries[modelClass.tableName] = findQuery(modelClass);

  if (modifyCb) {
   modifyCb(this._findQueries[modelClass.tableName]);
  }

  _.each(modelClass.getRelations(), function (relation) {
    if (!self._findQueries[relation.relatedModelClass.tableName]) {
      self._findQueries[relation.relatedModelClass.tableName] = findQuery(relation.relatedModelClass);
    }
  });

  return this;
};

RestApiGenerator.prototype.routePrefix = function (routePrefix) {
  if (_.last(routePrefix) !== '/') {
    this._routePrefix = routePrefix + '/';
  } else {
    this._routePrefix = routePrefix;
  }
  return this;
};

RestApiGenerator.prototype.pluralizer = function (pluralizer) {
  this._pluralizer = pluralizer;
  return this;
};

RestApiGenerator.prototype.exclude = function (method, exclude) {
  this._exclude.push({
    method: method,
    exclude: exclude
  });
  return this;
};

RestApiGenerator.prototype.databaseGetter = function (databaseGetter) {
  this._databaseGetter = databaseGetter;
  return this;
};

RestApiGenerator.prototype.adapter = function (adapter) {
  this._adapter = adapter;
  return this;
};

RestApiGenerator.prototype.generate = function (app) {
  var self = this;

  _.each(this._models, function (modelClass) {
    var route = self._routeForModel(modelClass);

    if (!self._isExcluded('POST', route)) {
      self._generatePost(app, modelClass);
    }

    if (!self._isExcluded('GET', route)) {
      self._generateGetAll(app, modelClass);
    }

    if (!self._isExcluded('DELETE', route)) {
      self._generateDeleteAll(app, modelClass);
    }

    if (!self._isExcluded('GET', route + '/:id')) {
      self._generateGet(app, modelClass);
    }

    if (!self._isExcluded('PUT', route + '/:id')) {
      self._generatePut(app, modelClass);
    }

    if (!self._isExcluded('PATCH', route + '/:id')) {
      self._generatePatch(app, modelClass);
    }

    if (!self._isExcluded('DELETE', route + '/:id')) {
      self._generateDelete(app, modelClass);
    }

    _.each(modelClass.getRelations(), function (relation) {
      var route = self._routeForRelation(relation);

      if (!self._isExcluded('POST', route)) {
        self._generateRelationPost(app, relation);
      }

      if (!self._isExcluded('GET', route)) {
        self._generateRelationGetAll(app, relation);
      }

      if (!self._isExcluded('DELETE', route)) {
        self._generateRelationDeleteAll(app, relation);
      }

      if (!(relation instanceof modelClass.OneToOneRelation)) {
        if (!self._isExcluded('PUT', route)) {
          self._generateRelationPutAll(app, relation);
        }
      }
    });
  });
};

RestApiGenerator.prototype._routeForModel = function (modelClass) {
  return this._routePrefix + this._pluralizer(_.camelCase(modelClass.name));
};

RestApiGenerator.prototype._routeForRelation = function (relation) {
  return this._routeForModel(relation.ownerModelClass) + '/:id/' + relation.name;
};

RestApiGenerator.prototype._isExcluded = function (method, route) {
  return _.any(this._exclude, function (exc) {
    if (exc.method.toLowerCase() === method.toLowerCase()) {
      if (_.isString(exc.exclude)) {
        return exc.exclude === route;
      } else {
        return exc.exclude.test(route);
      }
    } else {
      return false;
    }
  });
};

RestApiGenerator.prototype._generatePost = function (app, $modelClass) {
  var self = this;
  var route = this._routeForModel($modelClass);

  this._logger('POST ' + route);
  this._adapter(app, 'POST', route, function (req) {
    var modelClass = self._bindModelClass($modelClass, req);

    return self._objection.transaction(modelClass, function (modelClass) {
      return modelClass
        .query()
        .allowEager(self._findQueries[modelClass.tableName].allowEager())
        .eager(req.query.eager)
        .insert(req.body)
        .then(function (model) {
          return model.$query().first();
        });
    });
  });
};

RestApiGenerator.prototype._generateGetAll = function (app, $modelClass) {
  var self = this;
  var route = this._routeForModel($modelClass);

  this._logger('GET ' + route);
  this._adapter(app, 'GET', route, function (req) {
    var boundModelClass = self._bindModelClass($modelClass, req);
    return self._findQueries[boundModelClass.tableName].build(req.query, boundModelClass.query());
  });
};

RestApiGenerator.prototype._generateDeleteAll = function (app, $modelClass) {
  var self = this;
  var route = this._routeForModel($modelClass);

  this._logger('DELETE ' + route);
  this._adapter(app, 'DELETE', route, function (req) {
    var boundModelClass = self._bindModelClass($modelClass, req);
    return self._findQueries[boundModelClass.tableName].build(req.query, boundModelClass.query()).delete().then(function() {
        return {};
    });
  });
};

RestApiGenerator.prototype._generateGet = function (app, $modelClass) {
  var self = this;
  var route = this._routeForModel($modelClass) + '/:id';

  this._logger('GET ' + route);
  this._adapter(app, 'GET', route, function (req) {
    var modelClass = self._bindModelClass($modelClass, req);

    return modelClass
      .query()
      .eager(req.query.eager)
      .allowEager(self._findQueries[modelClass.tableName].allowEager())
      .where(modelClass.idColumn, req.params.id)
      .first()
      .then(function (model) {
        if (!model) { throw error(404); }
        return model;
      });
  });
};

RestApiGenerator.prototype._generatePut = function (app, $modelClass) {
  var self = this;
  var route = this._routeForModel($modelClass) + '/:id';

  this._logger('PUT ' + route);
  this._adapter(app, 'PUT', route, function (req) {
    var modelClass = self._bindModelClass($modelClass, req);

    return modelClass
      .query()
      .update(req.body)
      .where(modelClass.idColumn, req.params.id)
      .then(function (model) {
        return modelClass
          .query()
          .allowEager(self._findQueries[modelClass.tableName].allowEager())
          .eager(req.query.eager)
          .where(modelClass.idColumn, req.params.id)
          .first();
      })
      .then(function (model) {
        if (!model) { throw error(404); }
        return model;
      });
  });
};

RestApiGenerator.prototype._generatePatch = function (app, $modelClass) {
  var self = this;
  var route = this._routeForModel($modelClass) + '/:id';

  this._logger('PATCH ' + route);
  this._adapter(app, 'PATCH', route, function (req) {
    var modelClass = self._bindModelClass($modelClass, req);

    return modelClass
      .query()
      .patch(req.body)
      .where(modelClass.idColumn, req.params.id)
      .then(function () {
        return modelClass
          .query()
          .allowEager(self._findQueries[modelClass.tableName].allowEager())
          .eager(req.query.eager)
          .where(modelClass.idColumn, req.params.id)
          .first();
      })
      .then(function (model) {
        if (!model) { throw error(404); }
        return model;
      });
  });
};

RestApiGenerator.prototype._generateDelete = function (app, $modelClass) {
  var self = this;
  var route = this._routeForModel($modelClass) + '/:id';

  this._logger('DELETE ' + route);
  this._adapter(app, 'DELETE', route, function (req) {
    var modelClass = self._bindModelClass($modelClass, req);

    return self._objection.transaction(modelClass, function (modelClass) {
      return modelClass
        .query()
        .delete()
        .where(modelClass.idColumn, req.params.id);
    }).then(function () {
      return {};
    });
  });
};

RestApiGenerator.prototype._generateRelationPost = function (app, relation) {
  var self = this;
  var route = this._routeForRelation(relation);

  this._logger('POST ' + route);
  this._adapter(app, 'POST', route, function (req) {
    var modelClass = self._bindModelClass(relation.ownerModelClass, req);

    return self._objection.transaction(modelClass, function (modelClass) {
      return modelClass
        .query()
        .where(modelClass.idColumn, req.params.id)
        .first()
        .then(function (model) {
          if (!model) { throw error(404); }
          return model
            .$relatedQuery(relation.name)
            .insert(req.body);
        })
        .then(function (model) {
          return model
            .$query()
            .first()
            .allowEager(self._findQueries[relation.relatedModelClass.tableName].allowEager())
            .eager(req.query.eager);
        });
    });
  });
};

RestApiGenerator.prototype._generateRelationGetAll = function (app, relation) {
  var self = this;
  var route = this._routeForRelation(relation);

  this._logger('GET ' + route);
  this._adapter(app, 'GET', route, function (req) {
    var modelClass = self._bindModelClass(relation.ownerModelClass, req);

    return modelClass
      .query()
      .where(modelClass.idColumn, req.params.id)
      .first()
      .then(function (model) {
        if (!model) { throw error(404); }
        var query = model.$relatedQuery(relation.name);
        self._findQueries[relation.relatedModelClass.tableName].build(req.query, query);

        if (relation instanceof modelClass.OneToOneRelation) {
          return query.first();
        } else {
          return query;
        }
      });
  });
};

RestApiGenerator.prototype._generateRelationPutAll = function (app, relation) {
  var self = this;
  var route = this._routeForRelation(relation);

  this._logger('PUT ' + route);
  this._adapter(app, 'PUT', route, function (req) {
    var modelClass = self._bindModelClass(relation.ownerModelClass, req);
    var relatedModelClass = self._bindModelClass(relation.relatedModelClass, req);
    var model;

    return self._objection.transaction(modelClass, relatedModelClass, function (modelClass, relatedModelClass) {
      return modelClass
        .query()
        .where(modelClass.getFullIdColumn(), req.params.id)
        .first()
        .eager(relation.name)
        .then(function ($model) {
          model = $model;
          if (!model) { throw error(404); }

          var current = model[relation.name];
          var currentById = _.indexBy(current, relatedModelClass.getIdProperty());
          var inputModels = relatedModelClass.ensureModelArray(req.body);

          function isNew(model) {
            return !model.$id() || !currentById[model.$id()];
          }

          var insertModels = _.filter(inputModels, isNew);
          var updateModels = _.filter(inputModels, _.negate(isNew));
          var deleteModels = _.filter(current, function (model) {
            return !_.find(inputModels, function (inputModel) {
              // Non-strict equal on purpose.
              return inputModel.$id() == model.$id();
            });
          });

          var insertAndUpdateQueries = _.flatten([
            _.map(updateModels, function (update) {
              return update.$query().patch();
            }),
            _.map(insertModels, function (insert) {
              delete insert[relatedModelClass.getIdProperty()];
              return model.$relatedQuery(relation.name).insert(insert);
            })
          ]);

          return model
            .$relatedQuery(relation.name)
            .delete()
            .whereIn(relatedModelClass.getFullIdColumn(), _.invoke(deleteModels, '$id'))
            .then(function () {
              return Promise.all(insertAndUpdateQueries);
            });
        })
        .then(function () {
          return model.$relatedQuery(relation.name);
        });
    });
  });
};

RestApiGenerator.prototype._generateRelationDeleteAll = function (app, relation) {
  var self = this;
  var route = this._routeForRelation(relation);

  this._logger('DELETE ' + route);
  this._adapter(app, 'DELETE', route, function (req) {
    var modelClass = self._bindModelClass(relation.ownerModelClass, req);

    return modelClass
      .query()
      .where(modelClass.idColumn, req.params.id)
      .first()
      .then(function (model) {
        if (!model) { throw error(404); }
        return model.$relatedQuery(relation.name).delete();
      })
      .then(function () {
        return {};
      });
  });
};

RestApiGenerator.prototype._bindModelClass = function (modelClass, req) {
  if (this._databaseGetter) {
    return modelClass.bindKnex(this._databaseGetter(req));
  } else {
    return modelClass;
  }
};

function error(statusCode) {
  var err = new Error();
  err.statusCode = statusCode;
  return err;
}

module.exports = RestApiGenerator;
<|endoftext|>


<commit_before>/* eslint-disable camelcase */
// @flow

import * as React from 'react'
import {TabNavigator} from '../components/tabbed-view'
import {TabBarIcon} from '../components/tabbar-icon'

import {newsImages} from '../../../images/news-images'
import NewsContainer from './news-container'

export default TabNavigator(
	{
		StOlafNewsView: {
			screen: ({navigation}) => (
				<NewsContainer
					mode="wp-json"
					name="St. Olaf"
					navigation={navigation}
					query={{per_page: 10, _embed: true}}
					thumbnail={newsImages.stolaf}
					url="https://wp.stolaf.edu/wp-json/wp/v2/posts"
				/>
			),
			navigationOptions: {
				tabBarLabel: 'St. Olaf',
				tabBarIcon: TabBarIcon('school'),
			},
		},

		OlevilleNewsView: {
			screen: ({navigation}) => (
				<NewsContainer
					embedFeaturedImage={true}
					mode="wp-json"
					name="Oleville"
					navigation={navigation}
					query={{per_page: 10, _embed: true}}
					thumbnail={newsImages.oleville}
					url="http://oleville.com/wp-json/wp/v2/posts/"
				/>
			),
			navigationOptions: {
				tabBarLabel: 'Oleville',
				tabBarIcon: TabBarIcon('happy'),
			},
		},

		MessNewsView: {
			screen: ({navigation}) => (
				<NewsContainer
					mode="rss"
					name="The Mess"
					navigation={navigation}
					thumbnail={newsImages.mess}
					url="http://manitoumessenger.com/feed/"
				/>
			),
			navigationOptions: {
				tabBarLabel: 'The Mess',
				tabBarIcon: TabBarIcon('paper'),
			},
		},

		PoliticOleNewsView: {
			screen: ({navigation}) => (
				<NewsContainer
					mode="rss"
					name="PoliticOle"
					navigation={navigation}
					thumbnail={newsImages.politicole}
					url="http://oleville.com/politicole/feed/"
				/>
			),
			navigationOptions: {
				tabBarLabel: 'PoliticOle',
				tabBarIcon: TabBarIcon('megaphone'),
			},
		},

		KstoNewsView: {
			screen: ({navigation}) => (
				<NewsContainer
					mode="wp-json"
					name="KSTO"
					navigation={navigation}
					query={{per_page: 10, _embed: true}}
					thumbnail={newsImages.ksto}
					url="https://pages.stolaf.edu/ksto/wp-json/wp/v2/posts/"
				/>
			),
			navigationOptions: {
				tabBarLabel: 'KSTO',
				tabBarIcon: TabBarIcon('radio'),
			},
		},
	},
	{
		navigationOptions: {
			title: 'News',
		},
	},
)
<commit_msg>Change manitou mess to use Wordpress<commit_after>/* eslint-disable camelcase */
// @flow

import * as React from 'react'
import {TabNavigator} from '../components/tabbed-view'
import {TabBarIcon} from '../components/tabbar-icon'

import {newsImages} from '../../../images/news-images'
import NewsContainer from './news-container'

export default TabNavigator(
	{
		StOlafNewsView: {
			screen: ({navigation}) => (
				<NewsContainer
					mode="wp-json"
					name="St. Olaf"
					navigation={navigation}
					query={{per_page: 10, _embed: true}}
					thumbnail={newsImages.stolaf}
					url="https://wp.stolaf.edu/wp-json/wp/v2/posts"
				/>
			),
			navigationOptions: {
				tabBarLabel: 'St. Olaf',
				tabBarIcon: TabBarIcon('school'),
			},
		},

		OlevilleNewsView: {
			screen: ({navigation}) => (
				<NewsContainer
					embedFeaturedImage={true}
					mode="wp-json"
					name="Oleville"
					navigation={navigation}
					query={{per_page: 10, _embed: true}}
					thumbnail={newsImages.oleville}
					url="http://oleville.com/wp-json/wp/v2/posts/"
				/>
			),
			navigationOptions: {
				tabBarLabel: 'Oleville',
				tabBarIcon: TabBarIcon('happy'),
			},
		},

		MessNewsView: {
			screen: ({navigation}) => (
				<NewsContainer
					mode="wp-json"
					name="The Mess"
					navigation={navigation}
					query={{per_page: 10, _embed: true}}
					thumbnail={newsImages.mess}
					url="https://manitoumessenger.com/wp-json/wp/v2/posts/"
				/>
			),
			navigationOptions: {
				tabBarLabel: 'The Mess',
				tabBarIcon: TabBarIcon('paper'),
			},
		},

		PoliticOleNewsView: {
			screen: ({navigation}) => (
				<NewsContainer
					mode="rss"
					name="PoliticOle"
					navigation={navigation}
					thumbnail={newsImages.politicole}
					url="http://oleville.com/politicole/feed/"
				/>
			),
			navigationOptions: {
				tabBarLabel: 'PoliticOle',
				tabBarIcon: TabBarIcon('megaphone'),
			},
		},

		KstoNewsView: {
			screen: ({navigation}) => (
				<NewsContainer
					mode="wp-json"
					name="KSTO"
					navigation={navigation}
					query={{per_page: 10, _embed: true}}
					thumbnail={newsImages.ksto}
					url="https://pages.stolaf.edu/ksto/wp-json/wp/v2/posts/"
				/>
			),
			navigationOptions: {
				tabBarLabel: 'KSTO',
				tabBarIcon: TabBarIcon('radio'),
			},
		},
	},
	{
		navigationOptions: {
			title: 'News',
		},
	},
)
<|endoftext|>


<commit_before>/*jshint node:true, indent:2, curly:true eqeqeq:true, immed:true, latedef:true, newcap:true, noarg:true,
regexp:true, undef:true, trailing:true, white:true */
/*global XT:true, XV:true, XM:true, Backbone:true, enyo:true, _:true */

(function () {

  enyo.kind({
    name: "XV.RelationWidget",
    kind: enyo.Control,
    classes: "xv-inputwidget xv-relationwidget",
    published: {
      attr: null,
      label: "",
      placeholder: "",
      value: null,
      list: "",
      collection: "",
      disabled: false,
      keyAttribute: "number",
      nameAttribute: "name",
      descripAttribute: ""
    },
    events: {
      onSearch: "",
      onValueChange: "",
      onWorkspace: ""
    },
    handlers: {
      onModelChange: "modelChanged",
      onSelect: "itemSelected"
    },
    components: [
      {kind: "FittableColumns", components: [
        {name: "label", content: "", classes: "xv-decorated-label"},
        {kind: "onyx.InputDecorator", name: "decorator",
          classes: "xv-input-decorator", components: [
          {name: 'input', kind: "onyx.Input", classes: "xv-subinput",
            onkeyup: "keyUp", onkeydown: "keyDown", onblur: "receiveBlur",
            onfocus: "receiveFocus"
          },
          {kind: "onyx.MenuDecorator", components: [
            {kind: "onyx.IconButton", src: "assets/triangle-down-large.png",
              classes: "xv-relationwidget-icon"},
            {name: 'popupMenu', floating: true, kind: "onyx.Menu",
              components: [
              {kind: "XV.MenuItem", name: 'searchItem', content: "_search".loc()},
              {kind: "XV.MenuItem", name: 'openItem', content: "_open".loc(),
                disabled: true},
              {kind: "XV.MenuItem", name: 'newItem', content: "_new".loc(),
                disabled: true}
            ]}
          ]},
          {name: "completer", kind: "XV.Completer"}
        ]}
      ]},
      {name: "name", classes: "xv-relationwidget-description"},
      {name: "description", classes: "xv-relationwidget-description"}
    ],
    autocomplete: function () {
      var key = this.getKeyAttribute(),
        attr = this.getValue() ? this.getValue().get(key) : "",
        value = this.$.input.getValue(),
        query;

      if (value && value !== attr) {
        query = {
          parameters: [{
            attribute: key,
            operator: "BEGINS_WITH",
            value: value
          }],
          rowLimit: 1,
          orderBy: [{
            attribute: key
          }]
        };
        this._collection.fetch({
          success: enyo.bind(this, "_fetchSuccess"),
          query: query
        });
      } else if (!value) {
        this.setValue(null);
      }
    },
    clear: function (options) {
      this.setValue(null, options);
    },
    create: function () {
      this.inherited(arguments);
      this.listChanged();
      this.labelChanged();
      this.disabledChanged();
    },
    disabledChanged: function () {
      var disabled = this.getDisabled();
      this.$.input.setDisabled(disabled);
      this.$.name.addRemoveClass("disabled", disabled);
      this.$.description.addRemoveClass("disabled", disabled);
    },
    focus: function () {
      this.$.input.focus();
    },
    getValueToString: function () {
      return this.value.get(this.getKeyAttribute());
    },
    keyDown: function (inSender, inEvent) {
      // If tabbed out...
      inEvent.activator = this.$.decorator;
      if (inEvent.keyCode === 9) {
        this.$.completer.waterfall("onRequestHideMenu", inEvent);
        this.autocomplete();
      }
    },
    keyUp: function (inSender, inEvent) {
      var query,
        key = this.getKeyAttribute(),
        attr = this.getValue() ? this.getValue().get(key) : "",
        value = this.$.input.getValue(),
        completer = this.$.completer;
      inEvent.activator = this.$.decorator;

      // Look up if value changed
      if (value && value !== attr &&
          inEvent.keyCode !== 9) {
        query = {
          parameters: [{
            attribute: key,
            operator: "BEGINS_WITH",
            value: value
          }],
          rowLimit: 10,
          orderBy: [{
            attribute: key
          }]
        };
        this._collection.fetch({
          success: enyo.bind(this, "_collectionFetchSuccess"),
          query: query
        });
      } else {
        completer.waterfall("onRequestHideMenu", inEvent);
      }
    },
    itemSelected: function (inSender, inEvent) {
      if (inEvent.originator.kind === 'onyx.MenuItem') {
        this.relationSelected(inSender, inEvent);
      } else {
        this.menuItemSelected(inSender, inEvent);
      }
      return true;
    },
    labelChanged: function () {
      var label = (this.getLabel() || ("_" + this.attr || "").loc());
      this.$.label.setContent(label + ":");
    },
    listChanged: function () {
      var list = this.getList(),
        Collection,
        workspace;
      delete this._List;
      delete this._Workspace;

      // Get List class
      if (!list) { return; }
      this._List = XT.getObjectByName(list);

      // Get Workspace class
      workspace = this._List.prototype.getWorkspace();
      this._Workspace = workspace ? XT.getObjectByName(workspace) : null;

      // Setup collection instance
      Collection = this.getCollection() ?
        XT.getObjectByName(this.getCollection()) : null;
      if (!Collection) { return; }
      this._collection = new Collection();
    },
    menuItemSelected: function (inSender, inEvent) {
      var that = this,
        menuItem = inEvent.originator,
        list = this.getList(),
        model = this.getValue(),
        id = model ? model.id : null,
        workspace = this._List ? this._List.prototype.getWorkspace() : null,
        callback;
      switch (menuItem.name)
      {
      case 'searchItem':
        callback = function (value) {
          that.setValue(value);
        };
        this.doSearch({
          list: list,
          searchText: this.$.input.getValue(),
          callback: callback
        });
        break;
      case 'openItem':
        this.doWorkspace({
          workspace: workspace,
          id: id,
          allowNew: false
        });
        break;
      case 'newItem':
        // Callback options on commit of the workspace
        // Find the model with matching id, fetch and set it.
        callback = function (model) {
          var Model = that._collection.model,
            value = new Model({id: model.id}),
            options = {};
          options.success = function () {
            that.setValue(value);
          };
          value.fetch(options);
        };
        this.doWorkspace({
          workspace: workspace,
          callback: callback,
          allowNew: false
        });
        break;
      }
    },
    modelChanged: function (inSender, inEvent) {
      var that = this,
        List = this._List,
        workspace = List.prototype.getWorkspace(),
        Workspace = workspace ? XT.getObjectByName(workspace) : null,
        options = {},
        model = this.getValue();
      // If the model that changed was related to and exists on this widget
      // refresh the local model.
      if (!List || !Workspace || !model) { return; }
      if (Workspace.prototype.model === inEvent.model &&
        model.id === inEvent.id) {
        options.success = function () {
          that.setValue(model);
        };
        model.fetch(options);
      }
    },
    placeholderChanged: function () {
      var placeholder = this.getPlaceholder();
      this.$.input.setPlaceholder(placeholder);
    },
    receiveBlur: function (inSender, inEvent) {
      this.autocomplete();
      this._hasFocus = false;
    },
    receiveFocus: function (inSender, inEvent) {
      this._hasFocus = true;
      this._relationSelected = false;
    },
    relationSelected: function (inSender, inEvent) {
      this._relationSelected = true;
      inEvent.activator = this.$.decorator;
      this.setValue(inEvent.originator.model);
      this.$.completer.waterfall("onRequestHideMenu", inEvent);
      return true;
    },
    /**
      Programatically sets the value of this widget.

      @param value Can be a model or the id of a model (String or Number).
        If it is an ID, then the correct model will be fetched and this
        function will be called again recursively with the model.
      @param options {Object}
     */
    setValue: function (value, options) {
      options = options || {};
      var that = this,
        newId = value ? value.id : null,
        oldId = this.value ? this.value.id : null,
        key = this.getKeyAttribute(),
        name = this.getNameAttribute(),
        descrip = this.getDescripAttribute(),
        inEvent = { value: value, originator: this },
        keyValue = "",
        nameValue = "",
        descripValue = "",
        Workspace = this._Workspace,
        Model = Workspace && Workspace.prototype.model ?
          XT.getObjectByName(Workspace.prototype.model)  : null,
        couldNotCreate = Model ? !Model.canCreate() : true,
        setPrivileges = function () {
          if (value && newId) {
            that.$.openItem.setDisabled(!value.couldRead());
          }
        };

      // Here is where we find the model and re-call this method if we're given
      // an id instead of a whole model.
      if (_.isNumber(value) || _.isString(value)) {
        if (this.value === value || oldId === value) { return; }
        Model = XT.getObjectByName(this._collection.model.prototype.recordType);
        value = new Model({id: value});
        options = {
          success: function () {
            that.setValue(value);
          }
        };
        this.value = value;
        // XXX shouldn't we pass the options in here?
        value.fetch(/*options*/);
        return;
      }

      this.value = value;
      if (value && value.get) {
        keyValue = value.get(key) || "";
        nameValue = value.get(name) || "";
        descripValue = value.get(descrip) || "";
      }
      this.$.input.setValue(keyValue);
      this.$.name.setShowing(nameValue);
      this.$.name.setContent(nameValue);
      this.$.description.setShowing(descripValue);
      this.$.description.setContent(descripValue);

      // Only notify if selection actually changed
      if (newId !== oldId && !options.silent) { this.doValueChange(inEvent); }

      // Handle menu actions
      that.$.openItem.setShowing(Workspace);
      that.$.newItem.setShowing(Workspace);
      that.$.openItem.setDisabled(true);
      that.$.newItem.setDisabled(couldNotCreate);
      if (Model && Workspace) {
        if (XT.session) {
          setPrivileges();
        } else {
          XT.getStartupManager().registerCallback(setPrivileges);
        }
      }
    },
    /** @private */
    _collectionFetchSuccess: function () {
      if (!this._hasFocus) { return; }
      var key = this.getKeyAttribute(),
        value = this.$.input.getValue(),
        models = this._collection.models,
        inEvent = { activator: this.$.decorator };
      if (models.length) {
        this.$.completer.buildList(key, value, models);
        if (!this.$.completer.showing) {
          this.$.completer.waterfall("onRequestShowMenu", inEvent);
        }
        this.$.completer.adjustPosition();
      } else {
        this.$.completer.waterfall("onRequestHideMenu", inEvent);
      }
    },
    /** @private */
    _fetchSuccess: function () {
      if (this._relationSelected) { return; }
      var value = this._collection.length ? this._collection.models[0] : null,
        target = enyo.dispatcher.captureTarget;
      this.setValue(value);
      enyo.dispatcher.captureTarget = target;
    }

  });
}());<commit_msg>issue #18579: fixed bug<commit_after>/*jshint node:true, indent:2, curly:true eqeqeq:true, immed:true, latedef:true, newcap:true, noarg:true,
regexp:true, undef:true, trailing:true, white:true */
/*global XT:true, XV:true, XM:true, Backbone:true, enyo:true, _:true */

(function () {

  enyo.kind({
    name: "XV.RelationWidget",
    kind: enyo.Control,
    classes: "xv-inputwidget xv-relationwidget",
    published: {
      attr: null,
      label: "",
      placeholder: "",
      value: null,
      list: "",
      collection: "",
      disabled: false,
      keyAttribute: "number",
      nameAttribute: "name",
      descripAttribute: ""
    },
    events: {
      onSearch: "",
      onValueChange: "",
      onWorkspace: ""
    },
    handlers: {
      onModelChange: "modelChanged",
      onSelect: "itemSelected"
    },
    components: [
      {kind: "FittableColumns", components: [
        {name: "label", content: "", classes: "xv-decorated-label"},
        {kind: "onyx.InputDecorator", name: "decorator",
          classes: "xv-input-decorator", components: [
          {name: 'input', kind: "onyx.Input", classes: "xv-subinput",
            onkeyup: "keyUp", onkeydown: "keyDown", onblur: "receiveBlur",
            onfocus: "receiveFocus"
          },
          {kind: "onyx.MenuDecorator", components: [
            {kind: "onyx.IconButton", src: "assets/triangle-down-large.png",
              classes: "xv-relationwidget-icon"},
            {name: 'popupMenu', floating: true, kind: "onyx.Menu",
              components: [
              {kind: "XV.MenuItem", name: 'searchItem', content: "_search".loc()},
              {kind: "XV.MenuItem", name: 'openItem', content: "_open".loc(),
                disabled: true},
              {kind: "XV.MenuItem", name: 'newItem', content: "_new".loc(),
                disabled: true}
            ]}
          ]},
          {name: "completer", kind: "XV.Completer"}
        ]}
      ]},
      {name: "name", classes: "xv-relationwidget-description"},
      {name: "description", classes: "xv-relationwidget-description"}
    ],
    autocomplete: function () {
      var key = this.getKeyAttribute(),
        attr = this.getValue() ? this.getValue().get(key) : "",
        value = this.$.input.getValue(),
        query;

      if (value && value !== attr) {
        query = {
          parameters: [{
            attribute: key,
            operator: "BEGINS_WITH",
            value: value
          }],
          rowLimit: 1,
          orderBy: [{
            attribute: key
          }]
        };
        this._collection.fetch({
          success: enyo.bind(this, "_fetchSuccess"),
          query: query
        });
      } else if (!value) {
        this.setValue(null);
      }
    },
    clear: function (options) {
      this.setValue(null, options);
    },
    create: function () {
      this.inherited(arguments);
      this.listChanged();
      this.labelChanged();
      this.disabledChanged();
    },
    disabledChanged: function () {
      var disabled = this.getDisabled();
      this.$.input.setDisabled(disabled);
      this.$.name.addRemoveClass("disabled", disabled);
      this.$.description.addRemoveClass("disabled", disabled);
    },
    focus: function () {
      this.$.input.focus();
    },
    getValueToString: function () {
      return this.value.get(this.getKeyAttribute());
    },
    keyDown: function (inSender, inEvent) {
      // If tabbed out...
      inEvent.activator = this.$.decorator;
      if (inEvent.keyCode === 9) {
        this.$.completer.waterfall("onRequestHideMenu", inEvent);
        this.autocomplete();
      }
    },
    keyUp: function (inSender, inEvent) {
      var query,
        key = this.getKeyAttribute(),
        attr = this.getValue() ? this.getValue().get(key) : "",
        value = this.$.input.getValue(),
        completer = this.$.completer;
      inEvent.activator = this.$.decorator;

      // Look up if value changed
      if (value && value !== attr &&
          inEvent.keyCode !== 9) {
        query = {
          parameters: [{
            attribute: key,
            operator: "BEGINS_WITH",
            value: value
          }],
          rowLimit: 10,
          orderBy: [{
            attribute: key
          }]
        };
        this._collection.fetch({
          success: enyo.bind(this, "_collectionFetchSuccess"),
          query: query
        });
      } else {
        completer.waterfall("onRequestHideMenu", inEvent);
      }
    },
    itemSelected: function (inSender, inEvent) {
      if (inEvent.originator.kind === 'onyx.MenuItem') {
        this.relationSelected(inSender, inEvent);
      } else {
        this.menuItemSelected(inSender, inEvent);
      }
      return true;
    },
    labelChanged: function () {
      var label = (this.getLabel() || ("_" + this.attr || "").loc());
      this.$.label.setContent(label + ":");
    },
    listChanged: function () {
      var list = this.getList(),
        Collection,
        workspace;
      delete this._List;
      delete this._Workspace;

      // Get List class
      if (!list) { return; }
      this._List = XT.getObjectByName(list);

      // Get Workspace class
      workspace = this._List.prototype.getWorkspace();
      this._Workspace = workspace ? XT.getObjectByName(workspace) : null;

      // Setup collection instance
      Collection = this.getCollection() ?
        XT.getObjectByName(this.getCollection()) : null;
      if (!Collection) { return; }
      this._collection = new Collection();
    },
    menuItemSelected: function (inSender, inEvent) {
      var that = this,
        menuItem = inEvent.originator,
        list = this.getList(),
        model = this.getValue(),
        id = model ? model.id : null,
        workspace = this._List ? this._List.prototype.getWorkspace() : null,
        callback;
      switch (menuItem.name)
      {
      case 'searchItem':
        callback = function (value) {
          that.setValue(value);
        };
        this.doSearch({
          list: list,
          searchText: this.$.input.getValue(),
          callback: callback
        });
        break;
      case 'openItem':
        this.doWorkspace({
          workspace: workspace,
          id: id,
          allowNew: false
        });
        break;
      case 'newItem':
        // Callback options on commit of the workspace
        // Find the model with matching id, fetch and set it.
        callback = function (model) {
          var Model = that._collection.model,
            value = new Model({id: model.id}),
            options = {};
          options.success = function () {
            that.setValue(value);
          };
          value.fetch(options);
        };
        this.doWorkspace({
          workspace: workspace,
          callback: callback,
          allowNew: false
        });
        break;
      }
    },
    modelChanged: function (inSender, inEvent) {
      var that = this,
        List = this._List,
        workspace = List.prototype.getWorkspace(),
        Workspace = workspace ? XT.getObjectByName(workspace) : null,
        options = {},
        model = this.getValue();
      // If the model that changed was related to and exists on this widget
      // refresh the local model.
      if (!List || !Workspace || !model) { return; }
      if (Workspace.prototype.model === inEvent.model &&
        model.id === inEvent.id) {
        options.success = function () {
          that.setValue(model);
        };
        model.fetch(options);
      }
    },
    placeholderChanged: function () {
      var placeholder = this.getPlaceholder();
      this.$.input.setPlaceholder(placeholder);
    },
    receiveBlur: function (inSender, inEvent) {
      this.autocomplete();
      this._hasFocus = false;
    },
    receiveFocus: function (inSender, inEvent) {
      this._hasFocus = true;
      this._relationSelected = false;
    },
    relationSelected: function (inSender, inEvent) {
      this._relationSelected = true;
      inEvent.activator = this.$.decorator;
      this.setValue(inEvent.originator.model);
      this.$.completer.waterfall("onRequestHideMenu", inEvent);
      return true;
    },
    /**
      Programatically sets the value of this widget.

      @param value Can be a model or the id of a model (String or Number).
        If it is an ID, then the correct model will be fetched and this
        function will be called again recursively with the model.
      @param options {Object}
     */
    setValue: function (value, options) {
      options = options || {};
      var that = this,
        newId = value ? value.id : null,
        oldId = this.value ? this.value.id : null,
        key = this.getKeyAttribute(),
        name = this.getNameAttribute(),
        descrip = this.getDescripAttribute(),
        inEvent = { value: value, originator: this },
        keyValue = "",
        nameValue = "",
        descripValue = "",
        Workspace = this._Workspace,
        Model = Workspace && Workspace.prototype.model ?
          XT.getObjectByName(Workspace.prototype.model)  : null,
        originalValue,
        couldNotCreate = Model ? !Model.canCreate() : true,
        setPrivileges = function () {
          if (value && newId) {
            that.$.openItem.setDisabled(!value.couldRead());
          }
        };

      // Here is where we find the model and re-call this method if we're given
      // an id instead of a whole model.
      if (_.isNumber(value) || _.isString(value)) {
        if (this.value === value || oldId === value) { return; }
        originalValue = value;
        Model = XT.getObjectByName(this._collection.model.prototype.recordType);
        value = new Model();
        options = {
          id: originalValue,
          success: function () {
            that.setValue(value);
          },
          error: function () {
            X.log("Error setting relational widget value");
          }
        };
        value.fetch(options);
        return;
      }

      this.value = value;
      if (value && value.get) {
        keyValue = value.get(key) || "";
        nameValue = value.get(name) || "";
        descripValue = value.get(descrip) || "";
      }
      this.$.input.setValue(keyValue);
      this.$.name.setShowing(nameValue);
      this.$.name.setContent(nameValue);
      this.$.description.setShowing(descripValue);
      this.$.description.setContent(descripValue);

      // Only notify if selection actually changed
      if (newId !== oldId && !options.silent) { this.doValueChange(inEvent); }

      // Handle menu actions
      that.$.openItem.setShowing(Workspace);
      that.$.newItem.setShowing(Workspace);
      that.$.openItem.setDisabled(true);
      that.$.newItem.setDisabled(couldNotCreate);
      if (Model && Workspace) {
        if (XT.session) {
          setPrivileges();
        } else {
          XT.getStartupManager().registerCallback(setPrivileges);
        }
      }
    },
    /** @private */
    _collectionFetchSuccess: function () {
      if (!this._hasFocus) { return; }
      var key = this.getKeyAttribute(),
        value = this.$.input.getValue(),
        models = this._collection.models,
        inEvent = { activator: this.$.decorator };
      if (models.length) {
        this.$.completer.buildList(key, value, models);
        if (!this.$.completer.showing) {
          this.$.completer.waterfall("onRequestShowMenu", inEvent);
        }
        this.$.completer.adjustPosition();
      } else {
        this.$.completer.waterfall("onRequestHideMenu", inEvent);
      }
    },
    /** @private */
    _fetchSuccess: function () {
      if (this._relationSelected) { return; }
      var value = this._collection.length ? this._collection.models[0] : null,
        target = enyo.dispatcher.captureTarget;
      this.setValue(value);
      enyo.dispatcher.captureTarget = target;
    }

  });
}());
<|endoftext|>